Commit 2843483d authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (51 commits)
  [CIFS] log better errors on failed mounts
  [CIFS] Return better error when server requires signing but client forbids
  [CIFS] fix typo
  [CIFS] acl support part 4
  [CIFS] Fix minor problems noticed by scan
  [CIFS] fix bad handling of EAGAIN error on kernel_recvmsg in cifs_demultiplex_thread
  [CIFS] build break
  [CIFS] endian fixes
  [CIFS] endian fixes in new acl code
  [CIFS] Fix some endianness problems in new acl code
  [CIFS] missing #endif from a previous patch
  [CIFS] formatting fixes
  [CIFS] Break up unicode_sessetup string functions
  [CIFS] parse server_GUID in SPNEGO negProt response
  [CIFS]
  [CIFS] Fix endian conversion problem in posix mkdir
  [CIFS] fix build break when lanman not enabled
  [CIFS] remove two sparse warnings
  [CIFS] remove compile warnings when debug disabled
  [CIFS] CIFS ACL support part 3
  ...
parents 26790656 a761ac57
Version 1.51
------------
Fix memory leak in statfs when mounted to very old servers (e.g.
Windows 9x). Add new feature "POSIX open" which allows servers
which support the current POSIX Extensions to provide better semantics
(e.g. delete for open files opened with posix open). Take into
account umask on posix mkdir not just older style mkdir. Add
ability to mount to IPC$ share (which allows CIFS named pipes to be
opened, read and written as if they were files). When 1st tree
connect fails (e.g. due to signing negotiation failure) fix
leak that causes cifsd not to stop and rmmod to fail to cleanup
cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
bigendian architectures. Fix possible memory corruption when
EAGAIN returned on kern_recvmsg. Return better error if server
requires packet signing but client has disabled it.
Version 1.50 Version 1.50
------------ ------------
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
...@@ -6,7 +22,10 @@ done with "serverino" mount option). Add support for POSIX Unlink ...@@ -6,7 +22,10 @@ done with "serverino" mount option). Add support for POSIX Unlink
Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix"
mount option to allow disabling the CIFS Unix Extensions for just mount option to allow disabling the CIFS Unix Extensions for just
that mount. Fix hang on spinlock in find_writable_file (race when that mount. Fix hang on spinlock in find_writable_file (race when
reopening file after session crash). reopening file after session crash). Byte range unlock request to
windows server could unlock more bytes (on server copy of file)
than intended if start of unlock request is well before start of
a previous byte range lock that we issued.
Version 1.49 Version 1.49
------------ ------------
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
# #
obj-$(CONFIG_CIFS) += cifs.o obj-$(CONFIG_CIFS) += cifs.o
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifsacl.o
...@@ -385,10 +385,9 @@ asn1_oid_decode(struct asn1_ctx *ctx, ...@@ -385,10 +385,9 @@ asn1_oid_decode(struct asn1_ctx *ctx,
unsigned long *optr; unsigned long *optr;
size = eoc - ctx->pointer + 1; size = eoc - ctx->pointer + 1;
*oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC); *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
if (*oid == NULL) { if (*oid == NULL)
return 0; return 0;
}
optr = *oid; optr = *oid;
...@@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON) } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) { || (tag != ASN1_SEQ)) {
cFYI(1, cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
("Exit 6 cls = %d con = %d tag = %d end = %p (%d)", cls, con, tag, end, *end));
cls, con, tag, end, *end));
} }
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
......
...@@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
i++; i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
length = length = sprintf(buf, "\n%d) %s Uses: %d ", i,
sprintf(buf, tcon->treeName, atomic_read(&tcon->useCount));
"\n%d) %s Uses: %d Type: %s DevInfo: 0x%x " buf += length;
"Attributes: 0x%x\nPathComponentMax: %d Status: %d", if (tcon->nativeFileSystem) {
i, tcon->treeName, length = sprintf(buf, "Type: %s ",
atomic_read(&tcon->useCount), tcon->nativeFileSystem);
tcon->nativeFileSystem, buf += length;
}
length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x"
"\nPathComponentMax: %d Status: %d",
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
le32_to_cpu(tcon->fsAttrInfo.Attributes), le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
...@@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer, ...@@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer,
if (count < 3) { if (count < 3) {
/* single char or single char followed by null */ /* single char or single char followed by null */
c = flags_string[0]; c = flags_string[0];
if (c == '0' || c == 'n' || c == 'N') if (c == '0' || c == 'n' || c == 'N') {
extended_security = CIFSSEC_DEF; /* default */ extended_security = CIFSSEC_DEF; /* default */
else if (c == '1' || c == 'y' || c == 'Y') return count;
} else if (c == '1' || c == 'y' || c == 'Y') {
extended_security = CIFSSEC_MAX; extended_security = CIFSSEC_MAX;
return count; return count;
} else if (!isdigit(c)) {
cERROR(1, ("invalid flag %c", c));
return -EINVAL;
}
} }
/* else we have a number */ /* else we have a number */
......
/*
* fs/cifs/cifsacl.c
*
* Copyright (C) International Business Machines Corp., 2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for mapping CIFS/NTFS ACLs
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsacl.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL
static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
{{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
{{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
{{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
{{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"}
};
/* security id for everyone */
static const struct cifs_sid sid_everyone =
{1, 1, {0, 0, 0, 0, 0, 0}, {} };
/* group users */
static const struct cifs_sid sid_user =
{1, 2 , {0, 0, 0, 0, 0, 5}, {} };
int match_sid(struct cifs_sid *ctsid)
{
int i, j;
int num_subauth, num_sat, num_saw;
struct cifs_sid *cwsid;
if (!ctsid)
return (-1);
for (i = 0; i < NUM_WK_SIDS; ++i) {
cwsid = &(wksidarr[i].cifssid);
/* compare the revision */
if (ctsid->revision != cwsid->revision)
continue;
/* compare all of the six auth values */
for (j = 0; j < 6; ++j) {
if (ctsid->authority[j] != cwsid->authority[j])
break;
}
if (j < 6)
continue; /* all of the auth values did not match */
/* compare all of the subauth values if any */
num_sat = ctsid->num_subauth;
num_saw = cwsid->num_subauth;
num_subauth = num_sat < num_saw ? num_sat : num_saw;
if (num_subauth) {
for (j = 0; j < num_subauth; ++j) {
if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
break;
}
if (j < num_subauth)
continue; /* all sub_auth values do not match */
}
cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
return (0); /* sids compare/match */
}
cFYI(1, ("No matching sid"));
return (-1);
}
/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
the same returns 1, if they do not match returns 0 */
int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
{
int i;
int num_subauth, num_sat, num_saw;
if ((!ctsid) || (!cwsid))
return (0);
/* compare the revision */
if (ctsid->revision != cwsid->revision)
return (0);
/* compare all of the six auth values */
for (i = 0; i < 6; ++i) {
if (ctsid->authority[i] != cwsid->authority[i])
return (0);
}
/* compare all of the subauth values if any */
num_sat = ctsid->num_subauth;
num_saw = cwsid->num_subauth;
num_subauth = num_sat < num_saw ? num_sat : num_saw;
if (num_subauth) {
for (i = 0; i < num_subauth; ++i) {
if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
return (0);
}
}
return (1); /* sids compare/match */
}
static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
{
int num_subauth;
/* validate that we do not go past end of acl */
/* XXX this if statement can be removed
if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
cERROR(1, ("ACL too small to parse ACE"));
return;
} */
num_subauth = pace->num_subauth;
if (num_subauth) {
#ifdef CONFIG_CIFS_DEBUG2
int i;
cFYI(1, ("ACE revision %d num_subauth %d",
pace->revision, pace->num_subauth));
for (i = 0; i < num_subauth; ++i) {
cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
le32_to_cpu(pace->sub_auth[i])));
}
/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */
cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1])));
#endif
}
return;
}
static void parse_ntace(struct cifs_ntace *pntace, char *end_of_acl)
{
/* validate that we do not go past end of acl */
if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) {
cERROR(1, ("ACL too small to parse NT ACE"));
return;
}
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x",
pntace->type, pntace->flags, pntace->size,
pntace->access_req));
#endif
return;
}
static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid)
{
int i;
int num_aces = 0;
int acl_size;
char *acl_base;
struct cifs_ntace **ppntace;
struct cifs_ace **ppace;
/* BB need to add parm so we can store the SID BB */
/* validate that we do not go past end of acl */
if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
cERROR(1, ("ACL too small to parse DACL"));
return;
}
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("DACL revision %d size %d num aces %d",
le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
le32_to_cpu(pdacl->num_aces)));
#endif
acl_base = (char *)pdacl;
acl_size = sizeof(struct cifs_acl);
num_aces = le32_to_cpu(pdacl->num_aces);
if (num_aces > 0) {
ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *),
GFP_KERNEL);
ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
GFP_KERNEL);
/* cifscred->cecount = pdacl->num_aces;
cifscred->ntaces = kmalloc(num_aces *
sizeof(struct cifs_ntace *), GFP_KERNEL);
cifscred->aces = kmalloc(num_aces *
sizeof(struct cifs_ace *), GFP_KERNEL);*/
for (i = 0; i < num_aces; ++i) {
ppntace[i] = (struct cifs_ntace *)
(acl_base + acl_size);
ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] +
sizeof(struct cifs_ntace));
parse_ntace(ppntace[i], end_of_acl);
if (end_of_acl < ((char *)ppace[i] +
(le16_to_cpu(ppntace[i]->size) -
sizeof(struct cifs_ntace)))) {
cERROR(1, ("ACL too small to parse ACE"));
break;
} else
parse_ace(ppace[i], end_of_acl);
/* memcpy((void *)(&(cifscred->ntaces[i])),
(void *)ppntace[i],
sizeof(struct cifs_ntace));
memcpy((void *)(&(cifscred->aces[i])),
(void *)ppace[i],
sizeof(struct cifs_ace)); */
acl_base = (char *)ppntace[i];
acl_size = le16_to_cpu(ppntace[i]->size);
}
kfree(ppace);
kfree(ppntace);
}
return;
}
static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
{
/* BB need to add parm so we can store the SID BB */
/* validate that we do not go past end of acl */
if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) {
cERROR(1, ("ACL too small to parse SID"));
return -EINVAL;
}
if (psid->num_subauth) {
#ifdef CONFIG_CIFS_DEBUG2
int i;
cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
psid->revision, psid->num_subauth, psid->sub_auth[0]));
for (i = 0; i < psid->num_subauth; i++) {
cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
le32_to_cpu(psid->sub_auth[i])));
}
/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */
cFYI(1, ("RID 0x%x",
le32_to_cpu(psid->sub_auth[psid->num_subauth-1])));
#endif
}
return 0;
}
/* Convert CIFS ACL to POSIX form */
int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
{
int rc;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
char *end_of_acl = ((char *)pntsd) + acl_len;
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
dacl_ptr = (struct cifs_acl *)((char *)pntsd +
le32_to_cpu(pntsd->dacloffset));
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
"sacloffset 0x%x dacloffset 0x%x",
pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
le32_to_cpu(pntsd->gsidoffset),
le32_to_cpu(pntsd->sacloffset),
le32_to_cpu(pntsd->dacloffset)));
#endif
rc = parse_sid(owner_sid_ptr, end_of_acl);
if (rc)
return rc;
rc = parse_sid(group_sid_ptr, end_of_acl);
if (rc)
return rc;
parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr);
/* cifscred->uid = owner_sid_ptr->rid;
cifscred->gid = group_sid_ptr->rid;
memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
sizeof (struct cifs_sid));
memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
sizeof (struct cifs_sid)); */
return (0);
}
#endif /* CONFIG_CIFS_EXPERIMENTAL */
/* /*
* fs/cifs/cifsacl.h * fs/cifs/cifsacl.h
* *
* Copyright (c) International Business Machines Corp., 2005 * Copyright (c) International Business Machines Corp., 2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -22,17 +22,65 @@ ...@@ -22,17 +22,65 @@
#ifndef _CIFSACL_H #ifndef _CIFSACL_H
#define _CIFSACL_H #define _CIFSACL_H
#define NUM_AUTHS 6 /* number of authority fields */
#define NUM_SUBAUTHS 5 /* number of sub authority fields */
#define NUM_WK_SIDS 7 /* number of well known sids */
#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
#define READ_BIT 0x4
#define WRITE_BIT 0x2
#define EXEC_BIT 0x1
#define UBITSHIFT 6
#define GBITSHIFT 3
struct cifs_ntsd {
__le16 revision; /* revision level */
__le16 type;
__le32 osidoffset;
__le32 gsidoffset;
__le32 sacloffset;
__le32 dacloffset;
} __attribute__((packed));
struct cifs_sid { struct cifs_sid {
__u8 revision; /* revision level */ __u8 revision; /* revision level */
__u8 num_subauths; __u8 num_subauth;
__u8 authority[6];
__le32 sub_auth[5]; /* sub_auth[num_subauth] */ /* BB FIXME endianness BB */
} __attribute__((packed));
struct cifs_acl {
__le16 revision; /* revision level */
__le16 size;
__le32 num_aces;
} __attribute__((packed));
struct cifs_ntace { /* first part of ACE which contains perms */
__u8 type;
__u8 flags;
__le16 size;
__le32 access_req;
} __attribute__((packed));
struct cifs_ace { /* last part of ACE which includes user info */
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[6]; __u8 authority[6];
__u32 sub_auth[4]; __le32 sub_auth[5];
/* next sub_auth if any ... */
} __attribute__((packed)); } __attribute__((packed));
/* everyone */ struct cifs_wksid {
/* extern const struct cifs_sid sid_everyone;*/ struct cifs_sid cifssid;
/* group users */ char sidname[SIDNAMELENGTH];
/* extern const struct cifs_sid sid_user;*/ } __attribute__((packed));
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern int match_sid(struct cifs_sid *);
extern int compare_sids(struct cifs_sid *, struct cifs_sid *);
#endif /* CONFIG_CIFS_EXPERIMENTAL */
#endif /* _CIFSACL_H */ #endif /* _CIFSACL_H */
...@@ -345,7 +345,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, ...@@ -345,7 +345,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
user = kmalloc(2 + (len * 2), GFP_KERNEL); user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL) if (user == NULL)
goto calc_exit_2; goto calc_exit_2;
len = cifs_strtoUCS(user, ses->userName, len, nls_cp); len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
UniStrupr(user); UniStrupr(user);
hmac_md5_update((char *)user, 2*len, pctxt); hmac_md5_update((char *)user, 2*len, pctxt);
...@@ -356,7 +356,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, ...@@ -356,7 +356,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
domain = kmalloc(2 + (len * 2), GFP_KERNEL); domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if (domain == NULL) if (domain == NULL)
goto calc_exit_1; goto calc_exit_1;
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp); len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
nls_cp);
/* the following line was removed since it didn't work well /* the following line was removed since it didn't work well
with lower cased domain name that passed as an option. with lower cased domain name that passed as an option.
Maybe converting the domain name earlier makes sense */ Maybe converting the domain name earlier makes sense */
......
...@@ -49,10 +49,6 @@ ...@@ -49,10 +49,6 @@
static struct quotactl_ops cifs_quotactl_ops; static struct quotactl_ops cifs_quotactl_ops;
#endif /* QUOTA */ #endif /* QUOTA */
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
int cifsFYI = 0; int cifsFYI = 0;
int cifsERROR = 1; int cifsERROR = 1;
int traceSMB = 0; int traceSMB = 0;
...@@ -240,9 +236,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd) ...@@ -240,9 +236,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
return 0; return 0;
} else /* file mode might have been restricted at mount time else /* file mode might have been restricted at mount time
on the client (above and beyond ACL on servers) for on the client (above and beyond ACL on servers) for
servers which do not support setting and viewing mode bits, servers which do not support setting and viewing mode bits,
so allowing client to check permissions is useful */ so allowing client to check permissions is useful */
...@@ -312,15 +308,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) ...@@ -312,15 +308,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
seq_printf(s, ",domain=%s", seq_printf(s, ",domain=%s",
cifs_sb->tcon->ses->domainName); cifs_sb->tcon->ses->domainName);
} }
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
} }
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_printf(s, ",posixpaths"); seq_printf(s, ",posixpaths");
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
seq_printf(s, ",rsize=%d", cifs_sb->rsize); seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize); seq_printf(s, ",wsize=%d", cifs_sb->wsize);
} }
...@@ -346,7 +342,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid, ...@@ -346,7 +342,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
if (pTcon) { if (pTcon) {
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
} else { } else {
return -EIO; rc = -EIO;
} }
FreeXid(xid); FreeXid(xid);
...@@ -716,7 +712,7 @@ static int ...@@ -716,7 +712,7 @@ static int
cifs_init_inodecache(void) cifs_init_inodecache(void)
{ {
cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
sizeof (struct cifsInodeInfo), sizeof(struct cifsInodeInfo),
0, (SLAB_RECLAIM_ACCOUNT| 0, (SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD), SLAB_MEM_SPREAD),
cifs_init_once); cifs_init_once);
...@@ -816,8 +812,8 @@ static int ...@@ -816,8 +812,8 @@ static int
cifs_init_mids(void) cifs_init_mids(void)
{ {
cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
sizeof (struct mid_q_entry), 0, sizeof(struct mid_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL); SLAB_HWCACHE_ALIGN, NULL);
if (cifs_mid_cachep == NULL) if (cifs_mid_cachep == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -829,8 +825,8 @@ cifs_init_mids(void) ...@@ -829,8 +825,8 @@ cifs_init_mids(void)
} }
cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
sizeof (struct oplock_q_entry), 0, sizeof(struct oplock_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL); SLAB_HWCACHE_ALIGN, NULL);
if (cifs_oplock_cachep == NULL) { if (cifs_oplock_cachep == NULL) {
mempool_destroy(cifs_mid_poolp); mempool_destroy(cifs_mid_poolp);
kmem_cache_destroy(cifs_mid_cachep); kmem_cache_destroy(cifs_mid_cachep);
...@@ -882,7 +878,8 @@ static int cifs_oplock_thread(void *dummyarg) ...@@ -882,7 +878,8 @@ static int cifs_oplock_thread(void *dummyarg)
the call */ the call */
/* mutex_lock(&inode->i_mutex);*/ /* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping); rc =
filemap_fdatawrite(inode->i_mapping);
if (CIFS_I(inode)->clientCanCacheRead if (CIFS_I(inode)->clientCanCacheRead
== 0) { == 0) {
filemap_fdatawait(inode->i_mapping); filemap_fdatawait(inode->i_mapping);
...@@ -907,8 +904,7 @@ static int cifs_oplock_thread(void *dummyarg) ...@@ -907,8 +904,7 @@ static int cifs_oplock_thread(void *dummyarg)
0 /* len */ , 0 /* offset */, 0, 0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE, 0, LOCKING_ANDX_OPLOCK_RELEASE,
0 /* wait flag */); 0 /* wait flag */);
cFYI(1, cFYI(1, ("Oplock release rc = %d", rc));
("Oplock release rc = %d ", rc));
} }
} else } else
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
......
/* /*
* fs/cifs/cifsfs.h * fs/cifs/cifsfs.h
* *
* Copyright (c) International Business Machines Corp., 2002, 2005 * Copyright (c) International Business Machines Corp., 2002, 2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -99,7 +99,12 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, ...@@ -99,7 +99,12 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int); size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode *inode, struct file *filep, extern int cifs_ioctl(struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg); unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.50"
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
#define CIFS_VERSION "1.51"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/in6.h> #include <linux/in6.h>
#include "cifs_fs_sb.h" #include "cifs_fs_sb.h"
#include "cifsacl.h"
/* /*
* The sizes of various internal tables and strings * The sizes of various internal tables and strings
*/ */
...@@ -89,7 +90,8 @@ enum statusEnum { ...@@ -89,7 +90,8 @@ enum statusEnum {
}; };
enum securityEnum { enum securityEnum {
LANMAN = 0, /* Legacy LANMAN auth */ PLAINTXT = 0, /* Legacy with Plaintext passwords */
LANMAN, /* Legacy LANMAN auth */
NTLM, /* Legacy NTLM012 auth with NTLM hash */ NTLM, /* Legacy NTLM012 auth with NTLM hash */
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO */ RawNTLMSSP, /* NTLMSSP without SPNEGO */
...@@ -115,6 +117,17 @@ struct mac_key { ...@@ -115,6 +117,17 @@ struct mac_key {
} data; } data;
}; };
struct cifs_cred {
int uid;
int gid;
int mode;
int cecount;
struct cifs_sid osid;
struct cifs_sid gsid;
struct cifs_ntace *ntaces;
struct cifs_ace *aces;
};
/* /*
***************************************************************** *****************************************************************
* Except the CIFS PDUs themselves all the * Except the CIFS PDUs themselves all the
...@@ -279,6 +292,7 @@ struct cifsTconInfo { ...@@ -279,6 +292,7 @@ struct cifsTconInfo {
FILE_SYSTEM_DEVICE_INFO fsDevInfo; FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
FILE_SYSTEM_UNIX_INFO fsUnixInfo; FILE_SYSTEM_UNIX_INFO fsUnixInfo;
unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */
unsigned retry:1; unsigned retry:1;
unsigned nocase:1; unsigned nocase:1;
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
...@@ -329,6 +343,7 @@ struct cifsFileInfo { ...@@ -329,6 +343,7 @@ struct cifsFileInfo {
struct list_head llist; /* list of byte range locks we have. */ struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */ unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */ unsigned invalidHandle:1; /* file closed via session abend */
unsigned messageMode:1; /* for pipes: message vs byte mode */
atomic_t wrtPending; /* handle in use - defer close */ atomic_t wrtPending; /* handle in use - defer close */
struct semaphore fh_sem; /* prevents reopen race after dead ses*/ struct semaphore fh_sem; /* prevents reopen race after dead ses*/
char *search_resume_name; /* BB removeme BB */ char *search_resume_name; /* BB removeme BB */
...@@ -464,6 +479,9 @@ struct dir_notify_req { ...@@ -464,6 +479,9 @@ struct dir_notify_req {
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MAY_LANMAN 0x00010 #define CIFSSEC_MAY_LANMAN 0x00010
#define CIFSSEC_MAY_PLNTXT 0x00020 #define CIFSSEC_MAY_PLNTXT 0x00020
#else
#define CIFSSEC_MAY_LANMAN 0
#define CIFSSEC_MAY_PLNTXT 0
#endif /* weak passwords */ #endif /* weak passwords */
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ #define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
...@@ -477,14 +495,23 @@ require use of the stronger protocol */ ...@@ -477,14 +495,23 @@ require use of the stronger protocol */
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MUST_LANMAN 0x10010 #define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020 #define CIFSSEC_MUST_PLNTXT 0x20020
#ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
#else
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ #define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
#endif /* UPCALL */
#else /* do not allow weak pw hash */
#ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */
#else #else
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */ #define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */
#endif /* UPCALL */
#endif /* WEAK_PW_HASH */ #endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 #define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2 #define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
/* /*
***************************************************************** *****************************************************************
* All constants go here * All constants go here
......
...@@ -215,6 +215,12 @@ ...@@ -215,6 +215,12 @@
/* file_execute, file_read_attributes*/ /* file_execute, file_read_attributes*/
/* write_dac, and delete. */ /* write_dac, and delete. */
#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
| FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
/* /*
* Invalid readdir handle * Invalid readdir handle
*/ */
...@@ -360,10 +366,10 @@ struct smb_hdr { ...@@ -360,10 +366,10 @@ struct smb_hdr {
__u8 WordCount; __u8 WordCount;
} __attribute__((packed)); } __attribute__((packed));
/* given a pointer to an smb_hdr retrieve the value of byte count */ /* given a pointer to an smb_hdr retrieve the value of byte count */
#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) #define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ /* given a pointer to an smb_hdr retrieve the pointer to the byte area */
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
/* /*
* Computer Name Length (since Netbios name was length 16 with last byte 0x20) * Computer Name Length (since Netbios name was length 16 with last byte 0x20)
...@@ -716,6 +722,14 @@ typedef struct smb_com_findclose_req { ...@@ -716,6 +722,14 @@ typedef struct smb_com_findclose_req {
#define REQ_OPENDIRONLY 0x00000008 #define REQ_OPENDIRONLY 0x00000008
#define REQ_EXTENDED_INFO 0x00000010 #define REQ_EXTENDED_INFO 0x00000010
/* File type */
#define DISK_TYPE 0x0000
#define BYTE_PIPE_TYPE 0x0001
#define MESSAGE_PIPE_TYPE 0x0002
#define PRINTER_TYPE 0x0003
#define COMM_DEV_TYPE 0x0004
#define UNKNOWN_TYPE 0xFFFF
typedef struct smb_com_open_req { /* also handles create */ typedef struct smb_com_open_req { /* also handles create */
struct smb_hdr hdr; /* wct = 24 */ struct smb_hdr hdr; /* wct = 24 */
__u8 AndXCommand; __u8 AndXCommand;
......
...@@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, ...@@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
int * /* bytes returned */ , const int long_op); int * /* bytes returned */ , const int long_op);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */, struct kvec *, int /* nvec to send */,
int * /* type of buf returned */ , const int long_op); int * /* type of buf returned */ , const int long_op,
const int logError /* whether to log status code*/ );
extern int SendReceiveBlockingLock(const unsigned int /* xid */ , extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
struct cifsTconInfo *, struct cifsTconInfo *,
struct smb_hdr * /* input */ , struct smb_hdr * /* input */ ,
...@@ -65,7 +66,7 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); ...@@ -65,7 +66,7 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType); enum securityEnum *secType);
extern int cifs_inet_pton(int, char *source, void *dst); extern int cifs_inet_pton(int, char *source, void *dst);
extern int map_smb_to_linux_error(struct smb_hdr *smb); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ , extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of const struct cifsTconInfo *, int /* length of
fixed section (word count) in two byte units */); fixed section (word count) in two byte units */);
...@@ -304,12 +305,13 @@ extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, ...@@ -304,12 +305,13 @@ extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
const char *pass); const char *pass);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
const struct nls_table *); const struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * ); extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *); const struct nls_table *);
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */ #endif /* CIFS_WEAK_PW_HASH */
extern int parse_sec_desc(struct cifs_ntsd *, int);
extern int CIFSSMBCopy(int xid, extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon, struct cifsTconInfo *source_tcon,
const char *fromName, const char *fromName,
......
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
#include "cifsacl.h"
#include "cifsproto.h" #include "cifsproto.h"
#include "cifs_unicode.h" #include "cifs_unicode.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#include "cifsacl.h"
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
static struct { static struct {
...@@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon) ...@@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
open_file = list_entry(tmp, struct cifsFileInfo, tlist); open_file = list_entry(tmp, struct cifsFileInfo, tlist);
if (open_file) { if (open_file)
open_file->invalidHandle = TRUE; open_file->invalidHandle = TRUE;
}
} }
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
...@@ -439,8 +438,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -439,8 +438,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMB->hdr.Mid = GetNextMid(server); pSMB->hdr.Mid = GetNextMid(server);
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
cFYI(1, ("Kerberos only mechanism, enable extended security"));
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
}
count = 0; count = 0;
for (i = 0; i < CIFS_NUM_PROT; i++) { for (i = 0; i < CIFS_NUM_PROT; i++) {
...@@ -513,7 +517,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -513,7 +517,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
(int)ts.tv_sec, (int)utc.tv_sec, (int)ts.tv_sec, (int)utc.tv_sec,
(int)(utc.tv_sec - ts.tv_sec))); (int)(utc.tv_sec - ts.tv_sec)));
val = (int)(utc.tv_sec - ts.tv_sec); val = (int)(utc.tv_sec - ts.tv_sec);
seconds = val < 0 ? -val : val; seconds = abs(val);
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
remain = seconds % MIN_TZ_ADJ; remain = seconds % MIN_TZ_ADJ;
if (remain >= (MIN_TZ_ADJ / 2)) if (remain >= (MIN_TZ_ADJ / 2))
...@@ -574,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -574,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
server->secType = NTLM; server->secType = NTLM;
else if (secFlags & CIFSSEC_MAY_NTLMV2) else if (secFlags & CIFSSEC_MAY_NTLMV2)
server->secType = NTLMv2; server->secType = NTLMv2;
/* else krb5 ... any others ... */ else if (secFlags & CIFSSEC_MAY_KRB5)
server->secType = Kerberos;
else if (secFlags & CIFSSEC_MAY_LANMAN)
server->secType = LANMAN;
/* #ifdef CONFIG_CIFS_EXPERIMENTAL
else if (secFlags & CIFSSEC_MAY_PLNTXT)
server->secType = ??
#endif */
else {
rc = -EOPNOTSUPP;
cERROR(1, ("Invalid security type"));
goto neg_err_exit;
}
/* else ... any others ...? */
/* one byte, so no need to convert this or EncryptionKeyLen from /* one byte, so no need to convert this or EncryptionKeyLen from
little endian */ little endian */
...@@ -604,22 +621,26 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -604,22 +621,26 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
(server->capabilities & CAP_EXTENDED_SECURITY)) { (server->capabilities & CAP_EXTENDED_SECURITY)) {
count = pSMBr->ByteCount; count = pSMBr->ByteCount;
if (count < 16) if (count < 16) {
rc = -EIO; rc = -EIO;
else if (count == 16) { goto neg_err_exit;
server->secType = RawNTLMSSP; }
if (server->socketUseCount.counter > 1) {
if (memcmp(server->server_GUID, if (server->socketUseCount.counter > 1) {
pSMBr->u.extended_response. if (memcmp(server->server_GUID,
GUID, 16) != 0) { pSMBr->u.extended_response.
cFYI(1, ("server UID changed")); GUID, 16) != 0) {
memcpy(server->server_GUID, cFYI(1, ("server UID changed"));
pSMBr->u.extended_response.GUID,
16);
}
} else
memcpy(server->server_GUID, memcpy(server->server_GUID,
pSMBr->u.extended_response.GUID, 16); pSMBr->u.extended_response.GUID,
16);
}
} else
memcpy(server->server_GUID,
pSMBr->u.extended_response.GUID, 16);
if (count == 16) {
server->secType = RawNTLMSSP;
} else { } else {
rc = decode_negTokenInit(pSMBr->u.extended_response. rc = decode_negTokenInit(pSMBr->u.extended_response.
SecurityBlob, SecurityBlob,
...@@ -642,10 +663,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -642,10 +663,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
/* MUST_SIGN already includes the MAY_SIGN FLAG /* MUST_SIGN already includes the MAY_SIGN FLAG
so if this is zero it means that signing is disabled */ so if this is zero it means that signing is disabled */
cFYI(1, ("Signing disabled")); cFYI(1, ("Signing disabled"));
if (server->secMode & SECMODE_SIGN_REQUIRED) if (server->secMode & SECMODE_SIGN_REQUIRED) {
cERROR(1, ("Server requires " cERROR(1, ("Server requires "
"/proc/fs/cifs/PacketSigningEnabled " "packet signing to be enabled in "
"to be on")); "/proc/fs/cifs/SecurityFlags."));
rc = -EOPNOTSUPP;
}
server->secMode &= server->secMode &=
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
...@@ -1052,7 +1075,7 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags, ...@@ -1052,7 +1075,7 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
InformationLevel) - 4; InformationLevel) - 4;
offset = param_offset + params; offset = param_offset + params;
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
pdata->Level = SMB_QUERY_FILE_UNIX_BASIC; pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
pdata->Permissions = cpu_to_le64(mode); pdata->Permissions = cpu_to_le64(mode);
pdata->PosixOpenFlags = cpu_to_le32(posix_flags); pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
pdata->OpenFlags = cpu_to_le32(*pOplock); pdata->OpenFlags = cpu_to_le32(*pOplock);
...@@ -1098,8 +1121,8 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags, ...@@ -1098,8 +1121,8 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction) if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
*pOplock |= CIFS_CREATE_ACTION; *pOplock |= CIFS_CREATE_ACTION;
/* check to make sure response data is there */ /* check to make sure response data is there */
if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) { if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
pRetData->Type = -1; /* unknown */ pRetData->Type = cpu_to_le32(-1); /* unknown */
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("unknown type")); cFYI(1, ("unknown type"));
#endif #endif
...@@ -1107,12 +1130,12 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags, ...@@ -1107,12 +1130,12 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
+ sizeof(FILE_UNIX_BASIC_INFO)) { + sizeof(FILE_UNIX_BASIC_INFO)) {
cERROR(1, ("Open response data too small")); cERROR(1, ("Open response data too small"));
pRetData->Type = -1; pRetData->Type = cpu_to_le32(-1);
goto psx_create_err; goto psx_create_err;
} }
memcpy((char *) pRetData, memcpy((char *) pRetData,
(char *)psx_rsp + sizeof(OPEN_PSX_RSP), (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
sizeof (FILE_UNIX_BASIC_INFO)); sizeof(FILE_UNIX_BASIC_INFO));
} }
psx_create_err: psx_create_err:
...@@ -1193,9 +1216,9 @@ SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -1193,9 +1216,9 @@ SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
} }
if (*pOplock & REQ_OPLOCK) if (*pOplock & REQ_OPLOCK)
pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
else if (*pOplock & REQ_BATCHOPLOCK) { else if (*pOplock & REQ_BATCHOPLOCK)
pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
}
pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
/* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
/* 0 = read /* 0 = read
...@@ -1310,9 +1333,8 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -1310,9 +1333,8 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
} }
if (*pOplock & REQ_OPLOCK) if (*pOplock & REQ_OPLOCK)
pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
else if (*pOplock & REQ_BATCHOPLOCK) { else if (*pOplock & REQ_BATCHOPLOCK)
pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
}
pSMB->DesiredAccess = cpu_to_le32(access_flags); pSMB->DesiredAccess = cpu_to_le32(access_flags);
pSMB->AllocationSize = 0; pSMB->AllocationSize = 0;
/* set file as system file if special file such /* set file as system file if special file such
...@@ -1424,9 +1446,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, ...@@ -1424,9 +1446,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
iov[0].iov_base = (char *)pSMB; iov[0].iov_base = (char *)pSMB;
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
rc = SendReceive2(xid, tcon->ses, iov, rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1 /* num iovecs */, &resp_buf_type, 0 /* not long op */, 1 /* log err */ );
&resp_buf_type, 0);
cifs_stats_inc(&tcon->num_reads); cifs_stats_inc(&tcon->num_reads);
pSMBr = (READ_RSP *)iov[0].iov_base; pSMBr = (READ_RSP *)iov[0].iov_base;
if (rc) { if (rc) {
...@@ -1446,11 +1467,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, ...@@ -1446,11 +1467,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
*nbytes = 0; *nbytes = 0;
} else { } else {
pReadData = (char *) (&pSMBr->hdr.Protocol) + pReadData = (char *) (&pSMBr->hdr.Protocol) +
le16_to_cpu(pSMBr->DataOffset); le16_to_cpu(pSMBr->DataOffset);
/* if (rc = copy_to_user(buf, pReadData, data_length)) { /* if (rc = copy_to_user(buf, pReadData, data_length)) {
cERROR(1,("Faulting on read rc = %d",rc)); cERROR(1,("Faulting on read rc = %d",rc));
rc = -EFAULT; rc = -EFAULT;
}*/ /* can not use copy_to_user when using page cache*/ }*/ /* can not use copy_to_user when using page cache*/
if (*buf) if (*buf)
memcpy(*buf, pReadData, data_length); memcpy(*buf, pReadData, data_length);
} }
...@@ -1645,7 +1666,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, ...@@ -1645,7 +1666,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
long_op); long_op, 0 /* do not log STATUS code */ );
cifs_stats_inc(&tcon->num_writes); cifs_stats_inc(&tcon->num_writes);
if (rc) { if (rc) {
cFYI(1, ("Send error Write2 = %d", rc)); cFYI(1, ("Send error Write2 = %d", rc));
...@@ -2538,7 +2559,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, ...@@ -2538,7 +2559,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
cFYI(1, ("data starts after end of smb")); cFYI(1, ("data starts after end of smb"));
return -EINVAL; return -EINVAL;
} else if (data_count + *ppdata > end_of_smb) { } else if (data_count + *ppdata > end_of_smb) {
cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p", cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
*ppdata, data_count, (data_count + *ppdata), *ppdata, data_count, (data_count + *ppdata),
end_of_smb, pSMBr)); end_of_smb, pSMBr));
return -EINVAL; return -EINVAL;
...@@ -2615,7 +2636,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -2615,7 +2636,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
reparse_buf->TargetNameOffset + reparse_buf->TargetNameOffset +
reparse_buf->TargetNameLen) > reparse_buf->TargetNameLen) >
end_of_smb) { end_of_smb) {
cFYI(1,("reparse buf goes beyond SMB")); cFYI(1, ("reparse buf beyond SMB"));
rc = -EIO; rc = -EIO;
goto qreparse_out; goto qreparse_out;
} }
...@@ -3042,25 +3063,12 @@ CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, ...@@ -3042,25 +3063,12 @@ CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
#endif /* CONFIG_POSIX */ #endif /* CONFIG_POSIX */
#ifdef CONFIG_CIFS_EXPERIMENTAL
/* security id for everyone */
static const struct cifs_sid sid_everyone =
{1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
/* group users */
static const struct cifs_sid sid_user =
{1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
/* Convert CIFS ACL to POSIX form */
static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
{
return 0;
}
/* Get Security Descriptor (by handle) from remote server for a file or dir */ /* Get Security Descriptor (by handle) from remote server for a file or dir */
int int
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
/* BB fix up return info */ char *acl_inf, const int buflen, /* BB fix up return info */ char *acl_inf, const int buflen,
const int acl_type /* ACCESS/DEFAULT not sure implication */) const int acl_type)
{ {
int rc = 0; int rc = 0;
int buf_type = 0; int buf_type = 0;
...@@ -3085,12 +3093,13 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, ...@@ -3085,12 +3093,13 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
iov[0].iov_base = (char *)pSMB; iov[0].iov_base = (char *)pSMB;
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0); rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
0 /* not long op */, 0 /* do not log STATUS codes */ );
cifs_stats_inc(&tcon->num_acl_get); cifs_stats_inc(&tcon->num_acl_get);
if (rc) { if (rc) {
cFYI(1, ("Send error in QuerySecDesc = %d", rc)); cFYI(1, ("Send error in QuerySecDesc = %d", rc));
} else { /* decode response */ } else { /* decode response */
struct cifs_sid *psec_desc; struct cifs_ntsd *psec_desc;
__le32 * parm; __le32 * parm;
int parm_len; int parm_len;
int data_len; int data_len;
...@@ -3105,8 +3114,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, ...@@ -3105,8 +3114,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
goto qsec_out; goto qsec_out;
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
cERROR(1, ("smb %p parm %p data %p", cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
pSMBr, parm, psec_desc)); /* BB removeme BB */
if (le32_to_cpu(pSMBr->ParameterCount) != 4) { if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
rc = -EIO; /* bad smb */ rc = -EIO; /* bad smb */
...@@ -3115,7 +3123,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, ...@@ -3115,7 +3123,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
/* BB check that data area is minimum length and as big as acl_len */ /* BB check that data area is minimum length and as big as acl_len */
acl_len = le32_to_cpu(*(__le32 *)parm); acl_len = le32_to_cpu(*parm);
/* BB check if (acl_len > bufsize) */ /* BB check if (acl_len > bufsize) */
parse_sec_desc(psec_desc, acl_len); parse_sec_desc(psec_desc, acl_len);
...@@ -3128,6 +3136,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, ...@@ -3128,6 +3136,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
return rc; return rc;
} }
#endif /* CONFIG_CIFS_EXPERIMENTAL */
/* Legacy Query Path Information call for lookup to old servers such /* Legacy Query Path Information call for lookup to old servers such
as Win9x/WinME */ as Win9x/WinME */
...@@ -3363,6 +3372,9 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -3363,6 +3372,9 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
rc = validate_t2((struct smb_t2_rsp *)pSMBr); rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
"Unix Extensions can be disabled on mount "
"by specifying the nosfu mount option."));
rc = -EIO; /* bad smb */ rc = -EIO; /* bad smb */
} else { } else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
...@@ -3883,12 +3895,10 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, ...@@ -3883,12 +3895,10 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
pSMB->hdr.Mid = GetNextMid(ses->server); pSMB->hdr.Mid = GetNextMid(ses->server);
pSMB->hdr.Tid = ses->ipc_tid; pSMB->hdr.Tid = ses->ipc_tid;
pSMB->hdr.Uid = ses->Suid; pSMB->hdr.Uid = ses->Suid;
if (ses->capabilities & CAP_STATUS32) { if (ses->capabilities & CAP_STATUS32)
pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
} if (ses->capabilities & CAP_DFS)
if (ses->capabilities & CAP_DFS) {
pSMB->hdr.Flags2 |= SMBFLG2_DFS; pSMB->hdr.Flags2 |= SMBFLG2_DFS;
}
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
...@@ -4060,10 +4070,6 @@ SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) ...@@ -4060,10 +4070,6 @@ SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
(void **) &pSMBr); (void **) &pSMBr);
if (rc) if (rc)
return rc; return rc;
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
params = 2; /* level */ params = 2; /* level */
pSMB->TotalDataCount = 0; pSMB->TotalDataCount = 0;
...@@ -4265,7 +4271,7 @@ CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon) ...@@ -4265,7 +4271,7 @@ CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
*) (((char *) &pSMBr->hdr.Protocol) + *) (((char *) &pSMBr->hdr.Protocol) +
data_offset); data_offset);
memcpy(&tcon->fsAttrInfo, response_data, memcpy(&tcon->fsAttrInfo, response_data,
sizeof (FILE_SYSTEM_ATTRIBUTE_INFO)); sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
} }
} }
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
...@@ -4334,7 +4340,7 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon) ...@@ -4334,7 +4340,7 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
(((char *) &pSMBr->hdr.Protocol) + (((char *) &pSMBr->hdr.Protocol) +
data_offset); data_offset);
memcpy(&tcon->fsDevInfo, response_data, memcpy(&tcon->fsDevInfo, response_data,
sizeof (FILE_SYSTEM_DEVICE_INFO)); sizeof(FILE_SYSTEM_DEVICE_INFO));
} }
} }
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
...@@ -4402,7 +4408,7 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon) ...@@ -4402,7 +4408,7 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
*) (((char *) &pSMBr->hdr.Protocol) + *) (((char *) &pSMBr->hdr.Protocol) +
data_offset); data_offset);
memcpy(&tcon->fsUnixInfo, response_data, memcpy(&tcon->fsUnixInfo, response_data,
sizeof (FILE_SYSTEM_UNIX_INFO)); sizeof(FILE_SYSTEM_UNIX_INFO));
} }
} }
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
...@@ -4612,7 +4618,7 @@ CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, ...@@ -4612,7 +4618,7 @@ CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
strncpy(pSMB->FileName, fileName, name_len); strncpy(pSMB->FileName, fileName, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
data_count = sizeof (struct file_end_of_file_info); data_count = sizeof(struct file_end_of_file_info);
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4100); pSMB->MaxDataCount = cpu_to_le16(4100);
pSMB->MaxSetupCount = 0; pSMB->MaxSetupCount = 0;
...@@ -4800,7 +4806,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, ...@@ -4800,7 +4806,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
data_offset = (char *) (&pSMB->hdr.Protocol) + offset; data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
count = sizeof (FILE_BASIC_INFO); count = sizeof(FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1; pSMB->SetupCount = 1;
...@@ -4871,7 +4877,7 @@ CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, ...@@ -4871,7 +4877,7 @@ CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
} }
params = 6 + name_len; params = 6 + name_len;
count = sizeof (FILE_BASIC_INFO); count = sizeof(FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0; pSMB->MaxSetupCount = 0;
...@@ -4900,7 +4906,7 @@ CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, ...@@ -4900,7 +4906,7 @@ CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
pSMB->Reserved4 = 0; pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count; pSMB->hdr.smb_buf_length += byte_count;
memcpy(data_offset, data, sizeof (FILE_BASIC_INFO)); memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
pSMB->ByteCount = cpu_to_le16(byte_count); pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
...@@ -5003,7 +5009,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, ...@@ -5003,7 +5009,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
} }
params = 6 + name_len; params = 6 + name_len;
count = sizeof (FILE_UNIX_BASIC_INFO); count = sizeof(FILE_UNIX_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0; pSMB->MaxSetupCount = 0;
......
...@@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
struct mid_q_entry *mid_entry; struct mid_q_entry *mid_entry;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
if ( kthread_should_stop() ) { if (kthread_should_stop()) {
/* the demux thread will exit normally /* the demux thread will exit normally
next time through the loop */ next time through the loop */
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
} }
list_for_each(tmp, &GlobalTreeConnectionList) { list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) { if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
tcon->tidStatus = CifsNeedReconnect; tcon->tidStatus = CifsNeedReconnect;
}
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
/* do not want to be sending data on a socket we are freeing */ /* do not want to be sending data on a socket we are freeing */
...@@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
up(&server->tcpSem); up(&server->tcpSem);
while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
try_to_freeze(); try_to_freeze();
if (server->protocolType == IPV6) { if (server->protocolType == IPV6) {
rc = ipv6_connect(&server->addr.sockAddr6, rc = ipv6_connect(&server->addr.sockAddr6,
...@@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
} else { } else {
atomic_inc(&tcpSesReconnectCount); atomic_inc(&tcpSesReconnectCount);
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
if ( !kthread_should_stop() ) if (!kthread_should_stop())
server->tcpStatus = CifsGood; server->tcpStatus = CifsGood;
server->sequence_number = 0; server->sequence_number = 0;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
length = tcpSesAllocCount.counter; length = tcpSesAllocCount.counter;
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
complete(&cifsd_complete); complete(&cifsd_complete);
if (length > 1) { if (length > 1)
mempool_resize(cifs_req_poolp, mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
length + cifs_min_rcv, GFP_KERNEL);
GFP_KERNEL);
}
set_freezable(); set_freezable();
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
...@@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
} }
} else if (isLargeBuf) { } else if (isLargeBuf) {
/* we are reusing a dirty large buf, clear its start */ /* we are reusing a dirty large buf, clear its start */
memset(bigbuf, 0, sizeof (struct smb_hdr)); memset(bigbuf, 0, sizeof(struct smb_hdr));
} }
if (smallbuf == NULL) { if (smallbuf == NULL) {
...@@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
} }
/* beginning of smb buffer is cleared in our buf_get */ /* beginning of smb buffer is cleared in our buf_get */
} else /* if existing small buf clear beginning */ } else /* if existing small buf clear beginning */
memset(smallbuf, 0, sizeof (struct smb_hdr)); memset(smallbuf, 0, sizeof(struct smb_hdr));
isLargeBuf = FALSE; isLargeBuf = FALSE;
isMultiRsp = FALSE; isMultiRsp = FALSE;
...@@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
iov.iov_len = 4; iov.iov_len = 4;
smb_msg.msg_control = NULL; smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0; smb_msg.msg_controllen = 0;
pdu_length = 4; /* enough to get RFC1001 header */
incomplete_rcv:
length = length =
kernel_recvmsg(csocket, &smb_msg, kernel_recvmsg(csocket, &smb_msg,
&iov, 1, 4, 0 /* BB see socket.h flags */); &iov, 1, pdu_length, 0 /* BB other flags? */);
if ( kthread_should_stop() ) { if (kthread_should_stop()) {
break; break;
} else if (server->tcpStatus == CifsNeedReconnect) { } else if (server->tcpStatus == CifsNeedReconnect) {
cFYI(1, ("Reconnect after server stopped responding")); cFYI(1, ("Reconnect after server stopped responding"));
...@@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
msleep(1); /* minimum sleep to prevent looping msleep(1); /* minimum sleep to prevent looping
allowing socket to clear and app threads to set allowing socket to clear and app threads to set
tcpStatus CifsNeedReconnect if server hung */ tcpStatus CifsNeedReconnect if server hung */
continue; if (pdu_length < 4)
goto incomplete_rcv;
else
continue;
} else if (length <= 0) { } else if (length <= 0) {
if (server->tcpStatus == CifsNew) { if (server->tcpStatus == CifsNew) {
cFYI(1, ("tcp session abend after SMBnegprot")); cFYI(1, ("tcp session abend after SMBnegprot"));
...@@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
wake_up(&server->response_q); wake_up(&server->response_q);
continue; continue;
} else if (length < 4) { } else if (length < 4) {
cFYI(1, cFYI(1, ("less than four bytes received (%d bytes)",
("Frame under four bytes received (%d bytes long)",
length)); length));
cifs_reconnect(server); pdu_length -= length;
csocket = server->ssocket; msleep(1);
wake_up(&server->response_q); goto incomplete_rcv;
continue;
} }
/* The right amount was read from socket - 4 bytes */ /* The right amount was read from socket - 4 bytes */
...@@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* else we have an SMB response */ /* else we have an SMB response */
if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
(pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
cERROR(1, ("Invalid size SMB length %d pdu_length %d", cERROR(1, ("Invalid size SMB length %d pdu_length %d",
length, pdu_length+4)); length, pdu_length+4));
cifs_reconnect(server); cifs_reconnect(server);
...@@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
total_read += length) { total_read += length) {
length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
pdu_length - total_read, 0); pdu_length - total_read, 0);
if ( kthread_should_stop() || if (kthread_should_stop() ||
(length == -EINTR)) { (length == -EINTR)) {
/* then will exit */ /* then will exit */
reconnect = 2; reconnect = 2;
...@@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
allowing socket to clear and app allowing socket to clear and app
threads to set tcpStatus threads to set tcpStatus
CifsNeedReconnect if server hung*/ CifsNeedReconnect if server hung*/
length = 0;
continue; continue;
} else if (length <= 0) { } else if (length <= 0) {
cERROR(1, ("Received no data, expecting %d", cERROR(1, ("Received no data, expecting %d",
...@@ -631,9 +632,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -631,9 +632,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* Was previous buf put in mpx struct for multi-rsp? */ /* Was previous buf put in mpx struct for multi-rsp? */
if (!isMultiRsp) { if (!isMultiRsp) {
/* smb buffer will be freed by user thread */ /* smb buffer will be freed by user thread */
if (isLargeBuf) { if (isLargeBuf)
bigbuf = NULL; bigbuf = NULL;
} else else
smallbuf = NULL; smallbuf = NULL;
} }
wake_up_process(task_to_wake); wake_up_process(task_to_wake);
...@@ -676,9 +677,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -676,9 +677,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
server->ssocket = NULL; server->ssocket = NULL;
} }
/* buffer usuallly freed in free_mid - need to free it here on exit */ /* buffer usuallly freed in free_mid - need to free it here on exit */
if (bigbuf != NULL) cifs_buf_release(bigbuf);
cifs_buf_release(bigbuf); if (smallbuf) /* no sense logging a debug message if NULL */
if (smallbuf != NULL)
cifs_small_buf_release(smallbuf); cifs_small_buf_release(smallbuf);
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
...@@ -702,9 +702,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -702,9 +702,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo, ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList); cifsSessionList);
if (ses->server == server) { if (ses->server == server)
ses->status = CifsExiting; ses->status = CifsExiting;
}
} }
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
...@@ -714,9 +713,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -714,9 +713,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
cFYI(1, ("Clearing Mid 0x%x - waking up ", cFYI(1, ("Clearing Mid 0x%x - waking up ",
mid_entry->mid)); mid_entry->mid));
task_to_wake = mid_entry->tsk; task_to_wake = mid_entry->tsk;
if (task_to_wake) { if (task_to_wake)
wake_up_process(task_to_wake); wake_up_process(task_to_wake);
}
} }
} }
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -749,18 +747,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -749,18 +747,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo, ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList); cifsSessionList);
if (ses->server == server) { if (ses->server == server)
ses->server = NULL; ses->server = NULL;
}
} }
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
kfree(server); kfree(server);
if (length > 0) { if (length > 0)
mempool_resize(cifs_req_poolp, mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
length + cifs_min_rcv, GFP_KERNEL);
GFP_KERNEL);
}
return 0; return 0;
} }
...@@ -1477,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ...@@ -1477,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
if (psin_server->sin_port) { /* user overrode default port */ if (psin_server->sin_port) { /* user overrode default port */
rc = (*csocket)->ops->connect(*csocket, rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server, (struct sockaddr *) psin_server,
sizeof (struct sockaddr_in), 0); sizeof(struct sockaddr_in), 0);
if (rc >= 0) if (rc >= 0)
connected = 1; connected = 1;
} }
...@@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ...@@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
rc = (*csocket)->ops->connect(*csocket, rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server, (struct sockaddr *) psin_server,
sizeof (struct sockaddr_in), 0); sizeof(struct sockaddr_in), 0);
if (rc >= 0) if (rc >= 0)
connected = 1; connected = 1;
} }
...@@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ...@@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
psin_server->sin_port = htons(RFC1001_PORT); psin_server->sin_port = htons(RFC1001_PORT);
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
psin_server, psin_server,
sizeof (struct sockaddr_in), 0); sizeof(struct sockaddr_in), 0);
if (rc >= 0) if (rc >= 0)
connected = 1; connected = 1;
} }
...@@ -1610,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -1610,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
if (psin_server->sin6_port) { /* user overrode default port */ if (psin_server->sin6_port) { /* user overrode default port */
rc = (*csocket)->ops->connect(*csocket, rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server, (struct sockaddr *) psin_server,
sizeof (struct sockaddr_in6), 0); sizeof(struct sockaddr_in6), 0);
if (rc >= 0) if (rc >= 0)
connected = 1; connected = 1;
} }
...@@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
rc = (*csocket)->ops->connect(*csocket, rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server, (struct sockaddr *) psin_server,
sizeof (struct sockaddr_in6), 0); sizeof(struct sockaddr_in6), 0);
if (rc >= 0) if (rc >= 0)
connected = 1; connected = 1;
} }
...@@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
if (!connected) { if (!connected) {
psin_server->sin6_port = htons(RFC1001_PORT); psin_server->sin6_port = htons(RFC1001_PORT);
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
psin_server, sizeof (struct sockaddr_in6), 0); psin_server, sizeof(struct sockaddr_in6), 0);
if (rc >= 0) if (rc >= 0)
connected = 1; connected = 1;
} }
...@@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, ...@@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
cFYI(1, ("very large write cap")); cFYI(1, ("very large write cap"));
#endif /* CIFS_DEBUG2 */ #endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
cFYI(1, ("setting capabilities failed")); if (vol_info == NULL) {
cFYI(1, ("resetting capabilities failed"));
} else
cERROR(1, ("Negotiating Unix capabilities "
"with the server failed. Consider "
"mounting with the Unix Extensions\n"
"disabled, if problems are found, "
"by specifying the nounix mount "
"option."));
} }
} }
} }
...@@ -1909,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1909,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
return rc; return rc;
} }
srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL); srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
if (srvTcp == NULL) { if (!srvTcp) {
rc = -ENOMEM; rc = -ENOMEM;
sock_release(csocket); sock_release(csocket);
kfree(volume_info.UNC); kfree(volume_info.UNC);
...@@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} else { } else {
memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
memcpy(&srvTcp->addr.sockAddr, &sin_server, memcpy(&srvTcp->addr.sockAddr, &sin_server,
sizeof (struct sockaddr_in)); sizeof(struct sockaddr_in));
atomic_set(&srvTcp->inFlight, 0); atomic_set(&srvTcp->inFlight, 0);
/* BB Add code for ipv6 case too */ /* BB Add code for ipv6 case too */
srvTcp->ssocket = csocket; srvTcp->ssocket = csocket;
...@@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (tsk) if (tsk)
kthread_stop(tsk); kthread_stop(tsk);
} }
} else } else {
cFYI(1, ("No session or bad tcon")); cFYI(1, ("No session or bad tcon"));
if ((pSesInfo->server) &&
(pSesInfo->server->tsk)) {
struct task_struct *tsk;
force_sig(SIGKILL,
pSesInfo->server->tsk);
tsk = pSesInfo->server->tsk;
if (tsk)
kthread_stop(tsk);
}
}
sesInfoFree(pSesInfo); sesInfoFree(pSesInfo);
/* pSesInfo = NULL; */ /* pSesInfo = NULL; */
} }
...@@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
tcon->ses = pSesInfo; tcon->ses = pSesInfo;
/* do not care if following two calls succeed - informational */ /* do not care if following two calls succeed - informational */
CIFSSMBQFSDeviceInfo(xid, tcon); if (!tcon->ipc) {
CIFSSMBQFSAttributeInfo(xid, tcon); CIFSSMBQFSDeviceInfo(xid, tcon);
CIFSSMBQFSAttributeInfo(xid, tcon);
}
/* tell server which Unix caps we support */ /* tell server which Unix caps we support */
if (tcon->ses->capabilities & CAP_UNIX) if (tcon->ses->capabilities & CAP_UNIX)
...@@ -2526,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -2526,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
sesssetup_nomem: /* do not return an error on nomem for the info strings, sesssetup_nomem: /* do not return an error on nomem for the info strings,
since that could make reconnection harder, and since that could make reconnection harder, and
reconnection might be needed to free memory */ reconnection might be needed to free memory */
if (smb_buffer) cifs_buf_release(smb_buffer);
cifs_buf_release(smb_buffer);
return rc; return rc;
} }
...@@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
int remaining_words = 0; int remaining_words = 0;
int bytes_returned = 0; int bytes_returned = 0;
int len; int len;
int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE); int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
PNEGOTIATE_MESSAGE SecurityBlob; PNEGOTIATE_MESSAGE SecurityBlob;
PCHALLENGE_MESSAGE SecurityBlob2; PCHALLENGE_MESSAGE SecurityBlob2;
__u32 negotiate_flags, capabilities; __u32 negotiate_flags, capabilities;
...@@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
rc = -EIO; rc = -EIO;
} }
if (smb_buffer) cifs_buf_release(smb_buffer);
cifs_buf_release(smb_buffer);
return rc; return rc;
} }
static int static int
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *ntlm_session_key, int ntlmv2_flag, char *ntlm_session_key, int ntlmv2_flag,
const struct nls_table *nls_codepage) const struct nls_table *nls_codepage)
{ {
struct smb_hdr *smb_buffer; struct smb_hdr *smb_buffer;
struct smb_hdr *smb_buffer_response; struct smb_hdr *smb_buffer_response;
...@@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
int remaining_words = 0; int remaining_words = 0;
int bytes_returned = 0; int bytes_returned = 0;
int len; int len;
int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
PAUTHENTICATE_MESSAGE SecurityBlob; PAUTHENTICATE_MESSAGE SecurityBlob;
__u32 negotiate_flags, capabilities; __u32 negotiate_flags, capabilities;
__u16 count; __u16 count;
...@@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
return -ENOMEM; return -ENOMEM;
} }
smb_buffer_response = smb_buffer; smb_buffer_response = smb_buffer;
pSMB = (SESSION_SETUP_ANDX *) smb_buffer; pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
/* send SMBsessionSetup here */ /* send SMBsessionSetup here */
header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
...@@ -2921,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -2921,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
CAP_EXTENDED_SECURITY; CAP_EXTENDED_SECURITY;
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE; smb_buffer->Flags2 |= SMBFLG2_UNICODE;
capabilities |= CAP_UNICODE; capabilities |= CAP_UNICODE;
...@@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
} }
pSMB->req.Capabilities = cpu_to_le32(capabilities); pSMB->req.Capabilities = cpu_to_le32(capabilities);
bcc_ptr = (char *) &pSMB->req.SecurityBlob; bcc_ptr = (char *)&pSMB->req.SecurityBlob;
SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr; SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
SecurityBlob->MessageType = NtLmAuthenticate; SecurityBlob->MessageType = NtLmAuthenticate;
bcc_ptr += SecurityBlobLength; bcc_ptr += SecurityBlobLength;
negotiate_flags = negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | 0x80000000 | NTLMSSP_NEGOTIATE_128;
0x80000000 | NTLMSSP_NEGOTIATE_128;
if (sign_CIFS_PDUs) if (sign_CIFS_PDUs)
negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
if (ntlmv2_flag) if (ntlmv2_flag)
...@@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0; SecurityBlob->DomainName.MaximumLength = 0;
} else { } else {
__u16 len = __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
nls_codepage); nls_codepage);
len *= 2; ln *= 2;
SecurityBlob->DomainName.MaximumLength = SecurityBlob->DomainName.MaximumLength =
cpu_to_le16(len); cpu_to_le16(ln);
SecurityBlob->DomainName.Buffer = SecurityBlob->DomainName.Buffer =
cpu_to_le32(SecurityBlobLength); cpu_to_le32(SecurityBlobLength);
bcc_ptr += len; bcc_ptr += ln;
SecurityBlobLength += len; SecurityBlobLength += ln;
SecurityBlob->DomainName.Length = SecurityBlob->DomainName.Length = cpu_to_le16(ln);
cpu_to_le16(len);
} }
if (user == NULL) { if (user == NULL) {
SecurityBlob->UserName.Buffer = 0; SecurityBlob->UserName.Buffer = 0;
SecurityBlob->UserName.Length = 0; SecurityBlob->UserName.Length = 0;
SecurityBlob->UserName.MaximumLength = 0; SecurityBlob->UserName.MaximumLength = 0;
} else { } else {
__u16 len = __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
nls_codepage); nls_codepage);
len *= 2; ln *= 2;
SecurityBlob->UserName.MaximumLength = SecurityBlob->UserName.MaximumLength =
cpu_to_le16(len); cpu_to_le16(ln);
SecurityBlob->UserName.Buffer = SecurityBlob->UserName.Buffer =
cpu_to_le32(SecurityBlobLength); cpu_to_le32(SecurityBlobLength);
bcc_ptr += len; bcc_ptr += ln;
SecurityBlobLength += len; SecurityBlobLength += ln;
SecurityBlob->UserName.Length = SecurityBlob->UserName.Length = cpu_to_le16(ln);
cpu_to_le16(len);
} }
/* SecurityBlob->WorkstationName.Length = /* SecurityBlob->WorkstationName.Length =
...@@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0; SecurityBlob->DomainName.MaximumLength = 0;
} else { } else {
__u16 len; __u16 ln;
negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
strncpy(bcc_ptr, domain, 63); strncpy(bcc_ptr, domain, 63);
len = strnlen(domain, 64); ln = strnlen(domain, 64);
SecurityBlob->DomainName.MaximumLength = SecurityBlob->DomainName.MaximumLength =
cpu_to_le16(len); cpu_to_le16(ln);
SecurityBlob->DomainName.Buffer = SecurityBlob->DomainName.Buffer =
cpu_to_le32(SecurityBlobLength); cpu_to_le32(SecurityBlobLength);
bcc_ptr += len; bcc_ptr += ln;
SecurityBlobLength += len; SecurityBlobLength += ln;
SecurityBlob->DomainName.Length = cpu_to_le16(len); SecurityBlob->DomainName.Length = cpu_to_le16(ln);
} }
if (user == NULL) { if (user == NULL) {
SecurityBlob->UserName.Buffer = 0; SecurityBlob->UserName.Buffer = 0;
SecurityBlob->UserName.Length = 0; SecurityBlob->UserName.Length = 0;
SecurityBlob->UserName.MaximumLength = 0; SecurityBlob->UserName.MaximumLength = 0;
} else { } else {
__u16 len; __u16 ln;
strncpy(bcc_ptr, user, 63); strncpy(bcc_ptr, user, 63);
len = strnlen(user, 64); ln = strnlen(user, 64);
SecurityBlob->UserName.MaximumLength = SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
cpu_to_le16(len);
SecurityBlob->UserName.Buffer = SecurityBlob->UserName.Buffer =
cpu_to_le32(SecurityBlobLength); cpu_to_le32(SecurityBlobLength);
bcc_ptr += len; bcc_ptr += ln;
SecurityBlobLength += len; SecurityBlobLength += ln;
SecurityBlob->UserName.Length = cpu_to_le16(len); SecurityBlob->UserName.Length = cpu_to_le16(ln);
} }
/* BB fill in our workstation name if known BB */ /* BB fill in our workstation name if known BB */
...@@ -3100,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3100,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
&bytes_returned, 1); &bytes_returned, 1);
if (rc) { if (rc) {
/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
} else if ((smb_buffer_response->WordCount == 3) } else if ((smb_buffer_response->WordCount == 3) ||
|| (smb_buffer_response->WordCount == 4)) { (smb_buffer_response->WordCount == 4)) {
__u16 action = le16_to_cpu(pSMBr->resp.Action); __u16 action = le16_to_cpu(pSMBr->resp.Action);
__u16 blob_len = __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
le16_to_cpu(pSMBr->resp.SecurityBlobLength);
if (action & GUEST_LOGIN) if (action & GUEST_LOGIN)
cFYI(1, (" Guest login")); /* BB Should we set anything cFYI(1, (" Guest login")); /* BB Should we set anything
in SesInfo struct ? */ in SesInfo struct ? */
...@@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
} else { } else {
remaining_words = BCC(smb_buffer_response) / 2; remaining_words = BCC(smb_buffer_response) / 2;
} }
len = len = UniStrnlen((wchar_t *) bcc_ptr,
UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1); remaining_words - 1);
/* We look for obvious messed up bcc or strings in response so we do not go off /* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */ terminating last Unicode string in response */
...@@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
<= BCC(smb_buffer_response)) { <= BCC(smb_buffer_response)) {
if (ses->serverOS) if (ses->serverOS)
kfree(ses->serverOS); kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1,GFP_KERNEL); ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverOS,bcc_ptr, len); strncpy(ses->serverOS,bcc_ptr, len);
bcc_ptr += len; bcc_ptr += len;
...@@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr[0] = 0; bcc_ptr[0] = 0;
bcc_ptr++; bcc_ptr++;
} else } else
cFYI(1, cFYI(1, ("field of length %d "
("field of length %d "
"extends beyond end of smb ", "extends beyond end of smb ",
len)); len));
} }
} else { } else {
cERROR(1, cERROR(1, ("Security Blob extends beyond end "
(" Security Blob extends beyond end "
"of SMB")); "of SMB"));
} }
} else { } else {
cERROR(1, ("No session structure passed in.")); cERROR(1, ("No session structure passed in."));
} }
} else { } else {
cERROR(1, cERROR(1, ("Invalid Word count %d: ",
(" Invalid Word count %d: ",
smb_buffer_response->WordCount)); smb_buffer_response->WordCount));
rc = -EIO; rc = -EIO;
} }
if (smb_buffer) cifs_buf_release(smb_buffer);
cifs_buf_release(smb_buffer);
return rc; return rc;
} }
...@@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr = pByteArea(smb_buffer_response); bcc_ptr = pByteArea(smb_buffer_response);
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
/* skip service field (NB: this field is always ASCII) */ /* skip service field (NB: this field is always ASCII) */
if (length == 3) {
if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
(bcc_ptr[2] == 'C')) {
cFYI(1, ("IPC connection"));
tcon->ipc = 1;
}
} else if (length == 2) {
if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
/* the most common case */
cFYI(1, ("disk share connection"));
}
}
bcc_ptr += length + 1; bcc_ptr += length + 1;
strncpy(tcon->treeName, tree, MAX_TREE_SIZE); strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
...@@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
kfree(tcon->nativeFileSystem); kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem = tcon->nativeFileSystem =
kzalloc(length + 2, GFP_KERNEL); kzalloc(length + 2, GFP_KERNEL);
cifs_strfromUCS_le(tcon->nativeFileSystem, if (tcon->nativeFileSystem)
(__le16 *) bcc_ptr, cifs_strfromUCS_le(
length, nls_codepage); tcon->nativeFileSystem,
(__le16 *) bcc_ptr,
length, nls_codepage);
bcc_ptr += 2 * length; bcc_ptr += 2 * length;
bcc_ptr[0] = 0; /* null terminate the string */ bcc_ptr[0] = 0; /* null terminate the string */
bcc_ptr[1] = 0; bcc_ptr[1] = 0;
...@@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
kfree(tcon->nativeFileSystem); kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem = tcon->nativeFileSystem =
kzalloc(length + 1, GFP_KERNEL); kzalloc(length + 1, GFP_KERNEL);
strncpy(tcon->nativeFileSystem, bcc_ptr, if (tcon->nativeFileSystem)
length); strncpy(tcon->nativeFileSystem, bcc_ptr,
length);
} }
/* else do not bother copying these information fields*/ /* else do not bother copying these information fields*/
} }
...@@ -3433,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, ...@@ -3433,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
ses->ipc_tid = smb_buffer_response->Tid; ses->ipc_tid = smb_buffer_response->Tid;
} }
if (smb_buffer) cifs_buf_release(smb_buffer);
cifs_buf_release(smb_buffer);
return rc; return rc;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* vfs operations that deal with dentries * vfs operations that deal with dentries
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -269,7 +269,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -269,7 +269,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
CIFSSMBClose(xid, pTcon, fileHandle); CIFSSMBClose(xid, pTcon, fileHandle);
} else if (newinode) { } else if (newinode) {
pCifsFile = pCifsFile =
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile == NULL) if (pCifsFile == NULL)
goto cifs_create_out; goto cifs_create_out;
...@@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
/* BB Do not bother to decode buf since no /* BB Do not bother to decode buf since no
local inode yet to put timestamps in, local inode yet to put timestamps in,
but we can reuse it safely */ but we can reuse it safely */
int bytes_written; unsigned int bytes_written;
struct win_dev *pdev; struct win_dev *pdev;
pdev = (struct win_dev *)buf; pdev = (struct win_dev *)buf;
if (S_ISCHR(mode)) { if (S_ISCHR(mode)) {
...@@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
xid = GetXid(); xid = GetXid();
cFYI(1, cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p",
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
parent_dir_inode, direntry->d_name.name, direntry)); parent_dir_inode, direntry->d_name.name, direntry));
/* check whether path exists */ /* check whether path exists */
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include "cifsglob.h" #include "cifsglob.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#include "cifsfs.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL #ifdef CONFIG_CIFS_EXPERIMENTAL
static struct dentry *cifs_get_parent(struct dentry *dentry) static struct dentry *cifs_get_parent(struct dentry *dentry)
......
...@@ -467,7 +467,7 @@ static int cifs_reopen_file(struct file *file, int can_flush) ...@@ -467,7 +467,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
int cifs_close(struct inode *inode, struct file *file) int cifs_close(struct inode *inode, struct file *file)
{ {
int rc = 0; int rc = 0;
int xid; int xid, timeout;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsFileInfo *pSMBFile = struct cifsFileInfo *pSMBFile =
...@@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file)
/* no sense reconnecting to close a file that is /* no sense reconnecting to close a file that is
already closed */ already closed */
if (pTcon->tidStatus != CifsNeedReconnect) { if (pTcon->tidStatus != CifsNeedReconnect) {
int timeout = 2; timeout = 2;
while ((atomic_read(&pSMBFile->wrtPending) != 0) while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout < 1000) ) { && (timeout <= 2048)) {
/* Give write a better chance to get to /* Give write a better chance to get to
server ahead of the close. We do not server ahead of the close. We do not
want to add a wait_q here as it would want to add a wait_q here as it would
...@@ -522,12 +522,30 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -522,12 +522,30 @@ int cifs_close(struct inode *inode, struct file *file)
list_del(&pSMBFile->flist); list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist); list_del(&pSMBFile->tlist);
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
timeout = 10;
/* We waited above to give the SMBWrite a chance to issue
on the wire (so we do not get SMBWrite returning EBADF
if writepages is racing with close. Note that writepages
does not specify a file handle, so it is possible for a file
to be opened twice, and the application close the "wrong"
file handle - in these cases we delay long enough to allow
the SMBWrite to get on the wire before the SMB Close.
We allow total wait here over 45 seconds, more than
oplock break time, and more than enough to allow any write
to complete on the server, or to time out on the client */
while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout <= 50000)) {
cERROR(1, ("writes pending, delay free of handle"));
msleep(timeout);
timeout *= 8;
}
kfree(pSMBFile->search_resume_name); kfree(pSMBFile->search_resume_name);
kfree(file->private_data); kfree(file->private_data);
file->private_data = NULL; file->private_data = NULL;
} else } else
rc = -EBADF; rc = -EBADF;
read_lock(&GlobalSMBSeslock);
if (list_empty(&(CIFS_I(inode)->openFileList))) { if (list_empty(&(CIFS_I(inode)->openFileList))) {
cFYI(1, ("closing last open instance for inode %p", inode)); cFYI(1, ("closing last open instance for inode %p", inode));
/* if the file is not open we do not know if we can cache info /* if the file is not open we do not know if we can cache info
...@@ -535,6 +553,7 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -535,6 +553,7 @@ int cifs_close(struct inode *inode, struct file *file)
CIFS_I(inode)->clientCanCacheRead = FALSE; CIFS_I(inode)->clientCanCacheRead = FALSE;
CIFS_I(inode)->clientCanCacheAll = FALSE; CIFS_I(inode)->clientCanCacheAll = FALSE;
} }
read_unlock(&GlobalSMBSeslock);
if ((rc == 0) && CIFS_I(inode)->write_behind_rc) if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
rc = CIFS_I(inode)->write_behind_rc; rc = CIFS_I(inode)->write_behind_rc;
FreeXid(xid); FreeXid(xid);
...@@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
mutex_lock(&fid->lock_mutex); mutex_lock(&fid->lock_mutex);
list_for_each_entry_safe(li, tmp, &fid->llist, llist) { list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
if (pfLock->fl_start <= li->offset && if (pfLock->fl_start <= li->offset &&
length >= li->length) { (pfLock->fl_start + length) >=
(li->offset + li->length)) {
stored_rc = CIFSSMBLock(xid, pTcon, stored_rc = CIFSSMBLock(xid, pTcon,
netfid, netfid,
li->length, li->offset, li->length, li->offset,
...@@ -1022,6 +1042,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) ...@@ -1022,6 +1042,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
} }
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
refind_writable:
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend) if (open_file->closePend)
continue; continue;
...@@ -1029,24 +1050,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) ...@@ -1029,24 +1050,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
((open_file->pfile->f_flags & O_RDWR) || ((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) { (open_file->pfile->f_flags & O_WRONLY))) {
atomic_inc(&open_file->wrtPending); atomic_inc(&open_file->wrtPending);
if (!open_file->invalidHandle) {
/* found a good writable file */
read_unlock(&GlobalSMBSeslock);
return open_file;
}
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
if ((open_file->invalidHandle) && /* Had to unlock since following call can block */
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) { rc = cifs_reopen_file(open_file->pfile, FALSE);
rc = cifs_reopen_file(open_file->pfile, FALSE); if (!rc) {
/* if it fails, try another handle - might be */ if (!open_file->closePend)
/* dangerous to hold up writepages with retry */ return open_file;
if (rc) { else { /* start over in case this was deleted */
cFYI(1, /* since the list could be modified */
("failed on reopen file in wp"));
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
/* can not use this handle, no write atomic_dec(&open_file->wrtPending);
pending on this one after all */ goto refind_writable;
atomic_dec
(&open_file->wrtPending);
continue;
} }
} }
return open_file;
/* if it fails, try another handle if possible -
(we can not do this if closePending since
loop could be modified - in which case we
have to start at the beginning of the list
again. Note that it would be bad
to hold up writepages here (rather than
in caller) with continuous retries */
cFYI(1, ("wp failed on reopen file"));
read_lock(&GlobalSMBSeslock);
/* can not use this handle, no write
pending on this one after all */
atomic_dec(&open_file->wrtPending);
if (open_file->closePend) /* list could have changed */
goto refind_writable;
/* else we simply continue to the next entry. Thus
we do not loop on reopen errors. If we
can not reopen the file, for example if we
reconnected to a server with another client
racing to delete or lock the file we would not
make progress if we restarted before the beginning
of the loop here. */
} }
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
...@@ -1709,7 +1755,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1709,7 +1755,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
struct page *page; struct page *page;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
int bytes_read = 0; unsigned int bytes_read = 0;
unsigned int read_size, i; unsigned int read_size, i;
char *smb_read_data = NULL; char *smb_read_data = NULL;
struct smb_com_read_rsp *pSMBr; struct smb_com_read_rsp *pSMBr;
...@@ -1803,7 +1849,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1803,7 +1849,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
i += bytes_read >> PAGE_CACHE_SHIFT; i += bytes_read >> PAGE_CACHE_SHIFT;
cifs_stats_bytes_read(pTcon, bytes_read); cifs_stats_bytes_read(pTcon, bytes_read);
if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
i++; /* account for partial page */ i++; /* account for partial page */
/* server copy of file can have smaller size /* server copy of file can have smaller size
......
...@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_mode = le64_to_cpu(findData.Permissions); inode->i_mode = le64_to_cpu(findData.Permissions);
/* since we set the inode type below we need to mask off /* since we set the inode type below we need to mask off
to avoid strange results if bits set above */ to avoid strange results if bits set above */
inode->i_mode &= ~S_IFMT; inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) { if (type == UNIX_FILE) {
inode->i_mode |= S_IFREG; inode->i_mode |= S_IFREG;
} else if (type == UNIX_SYMLINK) { } else if (type == UNIX_SYMLINK) {
...@@ -575,19 +575,33 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -575,19 +575,33 @@ int cifs_get_inode_info(struct inode **pinode,
return rc; return rc;
} }
static const struct inode_operations cifs_ipc_inode_ops = {
.lookup = cifs_lookup,
};
/* gets root inode */ /* gets root inode */
void cifs_read_inode(struct inode *inode) void cifs_read_inode(struct inode *inode)
{ {
int xid; int xid, rc;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
xid = GetXid(); xid = GetXid();
if (cifs_sb->tcon->unix_ext) if (cifs_sb->tcon->unix_ext)
cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
else else
cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
if (rc && cifs_sb->tcon->ipc) {
cFYI(1, ("ipc connection - fake read inode"));
inode->i_mode |= S_IFDIR;
inode->i_nlink = 2;
inode->i_op = &cifs_ipc_inode_ops;
inode->i_fop = &simple_dir_operations;
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
}
/* can not call macro FreeXid here since in a void func */ /* can not call macro FreeXid here since in a void func */
_FreeXid(xid); _FreeXid(xid);
} }
...@@ -919,18 +933,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -919,18 +933,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
goto mkdir_out; goto mkdir_out;
} }
mode &= ~current->fs->umask;
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
mode, NULL /* netfid */, pInfo, &oplock, mode, NULL /* netfid */, pInfo, &oplock,
full_path, cifs_sb->local_nls, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) { if (rc == -EOPNOTSUPP) {
kfree(pInfo);
goto mkdir_retry_old;
} else if (rc) {
cFYI(1, ("posix mkdir returned 0x%x", rc)); cFYI(1, ("posix mkdir returned 0x%x", rc));
d_drop(direntry); d_drop(direntry);
} else { } else {
int obj_type; int obj_type;
if (pInfo->Type == -1) /* no return info - go query */ if (pInfo->Type == cpu_to_le32(-1)) {
/* no return info, go query for it */
kfree(pInfo);
goto mkdir_get_info; goto mkdir_get_info;
}
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
to set uid/gid */ to set uid/gid */
inc_nlink(inode); inc_nlink(inode);
...@@ -940,8 +961,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -940,8 +961,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
newinode = new_inode(inode->i_sb); newinode = new_inode(inode->i_sb);
if (newinode == NULL) if (newinode == NULL) {
kfree(pInfo);
goto mkdir_get_info; goto mkdir_get_info;
}
/* Is an i_ino of zero legal? */ /* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that /* Are there sanity checks we can use to ensure that
the server is really filling in that field? */ the server is really filling in that field? */
...@@ -972,7 +995,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -972,7 +995,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
kfree(pInfo); kfree(pInfo);
goto mkdir_out; goto mkdir_out;
} }
mkdir_retry_old:
/* BB add setting the equivalent of mode via CreateX w/ACLs */ /* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
...@@ -1377,8 +1400,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset) ...@@ -1377,8 +1400,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset)
} }
i_size_write(inode, offset); i_size_write(inode, offset);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
/*
* unmap_mapping_range is called twice, first simply for efficiency
* so that truncate_inode_pages does fewer single-page unmaps. However
* after this first call, and before truncate_inode_pages finishes,
* it is possible for private pages to be COWed, which remain after
* truncate_inode_pages finishes, hence the second unmap_mapping_range
* call must be made for correctness.
*/
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset); truncate_inode_pages(mapping, offset);
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
goto out_truncate; goto out_truncate;
do_expand: do_expand:
...@@ -1469,7 +1501,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1469,7 +1501,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
atomic_dec(&open_file->wrtPending); atomic_dec(&open_file->wrtPending);
cFYI(1, ("SetFSize for attrs rc = %d", rc)); cFYI(1, ("SetFSize for attrs rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
int bytes_written; unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size, nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL, &bytes_written, NULL, NULL,
...@@ -1502,7 +1534,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1502,7 +1534,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == 0) { if (rc == 0) {
int bytes_written; unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, rc = CIFSSMBWrite(xid, pTcon,
netfid, 0, netfid, 0,
attrs->ia_size, attrs->ia_size,
......
...@@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) ...@@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
char *tmp_path = NULL; char *tmp_path = NULL;
char *tmpbuffer; char *tmpbuffer;
unsigned char *referrals = NULL; unsigned char *referrals = NULL;
int num_referrals = 0; unsigned int num_referrals = 0;
int len; int len;
__u16 fid; __u16 fid;
......
...@@ -169,7 +169,6 @@ cifs_buf_get(void) ...@@ -169,7 +169,6 @@ cifs_buf_get(void)
void void
cifs_buf_release(void *buf_to_free) cifs_buf_release(void *buf_to_free)
{ {
if (buf_to_free == NULL) { if (buf_to_free == NULL) {
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
return; return;
......
...@@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = { ...@@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
{ERRusempx, -EIO}, {ERRusempx, -EIO},
{ERRusestd, -EIO}, {ERRusestd, -EIO},
{ERR_NOTIFY_ENUM_DIR, -ENOBUFS}, {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
{ERRaccountexpired, -EACCES}, {ERRnoSuchUser, -EACCES},
/* {ERRaccountexpired, -EACCES},
{ERRbadclient, -EACCES}, {ERRbadclient, -EACCES},
{ERRbadLogonTime, -EACCES}, {ERRbadLogonTime, -EACCES},
{ERRpasswordExpired, -EACCES}, {ERRpasswordExpired, -EACCES},*/
{ERRaccountexpired, -EKEYEXPIRED},
{ERRbadclient, -EACCES},
{ERRbadLogonTime, -EACCES},
{ERRpasswordExpired, -EKEYEXPIRED},
{ERRnosupport, -EINVAL}, {ERRnosupport, -EINVAL},
{0, 0} {0, 0}
}; };
...@@ -270,7 +276,7 @@ static const struct { ...@@ -270,7 +276,7 @@ static const struct {
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
during the session setup } */ during the session setup } */
{ {
ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, { ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, { ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, { ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
...@@ -285,10 +291,10 @@ static const struct { ...@@ -285,10 +291,10 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, { ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, { ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, { ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
...@@ -585,7 +591,7 @@ static const struct { ...@@ -585,7 +591,7 @@ static const struct {
ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, { ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, { ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
...@@ -754,7 +760,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode) ...@@ -754,7 +760,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
} }
int int
map_smb_to_linux_error(struct smb_hdr *smb) map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
{ {
unsigned int i; unsigned int i;
int rc = -EIO; /* if transport error smb error may not be set */ int rc = -EIO; /* if transport error smb error may not be set */
...@@ -771,7 +777,9 @@ map_smb_to_linux_error(struct smb_hdr *smb) ...@@ -771,7 +777,9 @@ map_smb_to_linux_error(struct smb_hdr *smb)
/* translate the newer STATUS codes to old style SMB errors /* translate the newer STATUS codes to old style SMB errors
* and then to POSIX errors */ * and then to POSIX errors */
__u32 err = le32_to_cpu(smb->Status.CifsError); __u32 err = le32_to_cpu(smb->Status.CifsError);
if (cifsFYI & CIFS_RC) if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
cifs_print_status(err);
else if (cifsFYI & CIFS_RC)
cifs_print_status(err); cifs_print_status(err);
ntstatus_to_dos(err, &smberrclass, &smberrcode); ntstatus_to_dos(err, &smberrclass, &smberrcode);
} else { } else {
...@@ -813,7 +821,7 @@ map_smb_to_linux_error(struct smb_hdr *smb) ...@@ -813,7 +821,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
} }
/* else ERRHRD class errors or junk - return EIO */ /* else ERRHRD class errors or junk - return EIO */
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", cFYI(1, ("Mapping smb error code %d to POSIX err %d",
smberrcode, rc)); smberrcode, rc));
/* generic corrective action e.g. reconnect SMB session on /* generic corrective action e.g. reconnect SMB session on
...@@ -899,8 +907,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) ...@@ -899,8 +907,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
cERROR(1, ("illegal hours %d", st->Hours)); cERROR(1, ("illegal hours %d", st->Hours));
days = sd->Day; days = sd->Day;
month = sd->Month; month = sd->Month;
if ((days > 31) || (month > 12)) if ((days > 31) || (month > 12)) {
cERROR(1, ("illegal date, month %d day: %d", month, days)); cERROR(1, ("illegal date, month %d day: %d", month, days));
if (month > 12)
month = 12;
}
month -= 1; month -= 1;
days += total_days_of_prev_months[month]; days += total_days_of_prev_months[month];
days += 3652; /* account for difference in days between 1980 and 1970 */ days += 3652; /* account for difference in days between 1980 and 1970 */
......
...@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode) ...@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
char *buf, int *pobject_type, int isNewInode) char *buf, unsigned int *pobject_type, int isNewInode)
{ {
loff_t local_size; loff_t local_size;
struct timespec local_mtime; struct timespec local_mtime;
...@@ -294,7 +294,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -294,7 +294,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
} }
static void unix_fill_in_inode(struct inode *tmp_inode, static void unix_fill_in_inode(struct inode *tmp_inode,
FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode) FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode)
{ {
loff_t local_size; loff_t local_size;
struct timespec local_mtime; struct timespec local_mtime;
...@@ -826,7 +826,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, ...@@ -826,7 +826,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
int rc = 0; int rc = 0;
struct qstr qstring; struct qstr qstring;
struct cifsFileInfo *pCifsF; struct cifsFileInfo *pCifsF;
unsigned obj_type; unsigned int obj_type;
ino_t inum; ino_t inum;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct inode *tmp_inode; struct inode *tmp_inode;
...@@ -1067,7 +1067,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1067,7 +1067,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
for (i = 0; (i < num_to_fill) && (rc == 0); i++) { for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if (current_entry == NULL) { if (current_entry == NULL) {
/* evaluate whether this case is an error */ /* evaluate whether this case is an error */
cERROR(1,("past end of SMB num to fill %d i %d", cERROR(1, ("past SMB end, num to fill %d i %d",
num_to_fill, i)); num_to_fill, i));
break; break;
} }
......
...@@ -67,14 +67,59 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) ...@@ -67,14 +67,59 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
capabilities |= CAP_DFS; capabilities |= CAP_DFS;
} }
if (ses->capabilities & CAP_UNIX) { if (ses->capabilities & CAP_UNIX)
capabilities |= CAP_UNIX; capabilities |= CAP_UNIX;
}
/* BB check whether to init vcnum BB */ /* BB check whether to init vcnum BB */
return capabilities; return capabilities;
} }
static void
unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
{
char *bcc_ptr = *pbcc_area;
int bytes_ret = 0;
/* Copy OS version */
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
nls_cp);
bcc_ptr += 2 * bytes_ret;
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
*pbcc_area = bcc_ptr;
}
static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses,
const struct nls_table *nls_cp)
{
char *bcc_ptr = *pbcc_area;
int bytes_ret = 0;
/* copy domain */
if (ses->domainName == NULL) {
/* Sending null domain better than using a bogus domain name (as
we did briefly in 2.6.18) since server will use its default */
*bcc_ptr = 0;
*(bcc_ptr+1) = 0;
bytes_ret = 0;
} else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */
*pbcc_area = bcc_ptr;
}
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
const struct nls_table *nls_cp) const struct nls_table *nls_cp)
{ {
...@@ -100,32 +145,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, ...@@ -100,32 +145,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
} }
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */ bcc_ptr += 2; /* account for null termination */
/* copy domain */
if (ses->domainName == NULL) {
/* Sending null domain better than using a bogus domain name (as
we did briefly in 2.6.18) since server will use its default */
*bcc_ptr = 0;
*(bcc_ptr+1) = 0;
bytes_ret = 0;
} else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */
/* Copy OS version */
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
nls_cp);
bcc_ptr += 2 * bytes_ret;
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, unicode_domain_string(&bcc_ptr, ses, nls_cp);
32, nls_cp); unicode_oslm_strings(&bcc_ptr, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
*pbcc_area = bcc_ptr; *pbcc_area = bcc_ptr;
} }
...@@ -203,14 +225,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, ...@@ -203,14 +225,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len >= words_left) if (len >= words_left)
return rc; return rc;
if (ses->serverOS) kfree(ses->serverOS);
kfree(ses->serverOS);
/* UTF-8 string will not grow more than four times as big as UCS-16 */ /* UTF-8 string will not grow more than four times as big as UCS-16 */
ses->serverOS = kzalloc(4 * len, GFP_KERNEL); ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
if (ses->serverOS != NULL) { if (ses->serverOS != NULL)
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
nls_cp);
}
data += 2 * (len + 1); data += 2 * (len + 1);
words_left -= len + 1; words_left -= len + 1;
...@@ -220,8 +239,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, ...@@ -220,8 +239,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len >= words_left) if (len >= words_left)
return rc; return rc;
if (ses->serverNOS) kfree(ses->serverNOS);
kfree(ses->serverNOS);
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
if (ses->serverNOS != NULL) { if (ses->serverNOS != NULL) {
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
...@@ -240,8 +258,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, ...@@ -240,8 +258,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len > words_left) if (len > words_left)
return rc; return rc;
if (ses->serverDomain) kfree(ses->serverDomain);
kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
if (ses->serverDomain != NULL) { if (ses->serverDomain != NULL) {
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
...@@ -271,8 +288,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, ...@@ -271,8 +288,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
if (len >= bleft) if (len >= bleft)
return rc; return rc;
if (ses->serverOS) kfree(ses->serverOS);
kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1, GFP_KERNEL); ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
if (ses->serverOS) if (ses->serverOS)
...@@ -289,8 +305,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, ...@@ -289,8 +305,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
if (len >= bleft) if (len >= bleft)
return rc; return rc;
if (ses->serverNOS) kfree(ses->serverNOS);
kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
if (ses->serverNOS) if (ses->serverNOS)
...@@ -479,7 +494,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -479,7 +494,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
if (iov[0].iov_len % 2) { if (iov[0].iov_len % 2) {
*bcc_ptr = 0; *bcc_ptr = 0;
} bcc_ptr++; bcc_ptr++;
}
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else } else
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
...@@ -497,7 +513,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -497,7 +513,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
iov[1].iov_base = str_area; iov[1].iov_base = str_area;
iov[1].iov_len = count; iov[1].iov_len = count;
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0); rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type,
0 /* not long op */, 1 /* log NT STATUS if any */ );
/* SMB request buf freed in SendReceive2 */ /* SMB request buf freed in SendReceive2 */
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
......
...@@ -173,9 +173,10 @@ ...@@ -173,9 +173,10 @@
#define ERRusestd 251 /* temporarily unable to use either raw #define ERRusestd 251 /* temporarily unable to use either raw
or mpx */ or mpx */
#define ERR_NOTIFY_ENUM_DIR 1024 #define ERR_NOTIFY_ENUM_DIR 1024
#define ERRnoSuchUser 2238 /* user account does not exist */
#define ERRaccountexpired 2239 #define ERRaccountexpired 2239
#define ERRbadclient 2240 #define ERRbadclient 2240 /* can not logon from this client */
#define ERRbadLogonTime 2241 #define ERRbadLogonTime 2241 /* logon hours do not allow this */
#define ERRpasswordExpired 2242 #define ERRpasswordExpired 2242
#define ERRnetlogonNotStarted 2455 #define ERRnetlogonNotStarted 2455
#define ERRnosupport 0xFFFF #define ERRnosupport 0xFFFF
...@@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) ...@@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
if (temp == NULL) if (temp == NULL)
return temp; return temp;
else { else {
memset(temp, 0, sizeof (struct mid_q_entry)); memset(temp, 0, sizeof(struct mid_q_entry));
temp->mid = smb_buffer->Mid; /* always LE */ temp->mid = smb_buffer->Mid; /* always LE */
temp->pid = current->pid; temp->pid = current->pid;
temp->command = smb_buffer->Command; temp->command = smb_buffer->Command;
...@@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
iov.iov_len = len; iov.iov_len = len;
smb_msg.msg_name = sin; smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof (struct sockaddr); smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL; smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0; smb_msg.msg_controllen = 0;
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
...@@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, ...@@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
return -ENOTSOCK; /* BB eventually add reconnect code here */ return -ENOTSOCK; /* BB eventually add reconnect code here */
smb_msg.msg_name = sin; smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof (struct sockaddr); smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL; smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0; smb_msg.msg_controllen = 0;
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
...@@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, ...@@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
} /* else ok - we are setting up session */ } /* else ok - we are setting up session */
} }
*ppmidQ = AllocMidQEntry(in_buf, ses); *ppmidQ = AllocMidQEntry(in_buf, ses);
if (*ppmidQ == NULL) { if (*ppmidQ == NULL)
return -ENOMEM; return -ENOMEM;
}
return 0; return 0;
} }
...@@ -419,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses, ...@@ -419,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
int int
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
struct kvec *iov, int n_vec, int *pRespBufType /* ret */, struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
const int long_op) const int long_op, const int logError)
{ {
int rc = 0; int rc = 0;
unsigned int receive_len; unsigned int receive_len;
...@@ -465,7 +464,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -465,7 +464,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return rc; return rc;
} }
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED; midQ->midState = MID_REQUEST_SUBMITTED;
...@@ -568,13 +566,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -568,13 +566,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
} }
/* BB special case reconnect tid and uid here? */ /* BB special case reconnect tid and uid here? */
/* BB special case Errbadpassword and pwdexpired here */ rc = map_smb_to_linux_error(midQ->resp_buf, logError);
rc = map_smb_to_linux_error(midQ->resp_buf);
/* convert ByteCount if necessary */ /* convert ByteCount if necessary */
if (receive_len >= if (receive_len >= sizeof(struct smb_hdr) - 4
sizeof (struct smb_hdr) - /* do not count RFC1001 header */ +
4 /* do not count RFC1001 header */ +
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
BCC(midQ->resp_buf) = BCC(midQ->resp_buf) =
le16_to_cpu(BCC_LE(midQ->resp_buf)); le16_to_cpu(BCC_LE(midQ->resp_buf));
...@@ -749,12 +745,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -749,12 +745,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
*pbytes_returned = out_buf->smb_buf_length; *pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and uid here? */ /* BB special case reconnect tid and uid here? */
rc = map_smb_to_linux_error(out_buf); rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
/* convert ByteCount if necessary */ /* convert ByteCount if necessary */
if (receive_len >= if (receive_len >= sizeof(struct smb_hdr) - 4
sizeof (struct smb_hdr) - /* do not count RFC1001 header */ +
4 /* do not count RFC1001 header */ +
(2 * out_buf->WordCount) + 2 /* bcc */ ) (2 * out_buf->WordCount) + 2 /* bcc */ )
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else { } else {
...@@ -993,12 +988,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -993,12 +988,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
*pbytes_returned = out_buf->smb_buf_length; *pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and uid here? */ /* BB special case reconnect tid and uid here? */
rc = map_smb_to_linux_error(out_buf); rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
/* convert ByteCount if necessary */ /* convert ByteCount if necessary */
if (receive_len >= if (receive_len >= sizeof(struct smb_hdr) - 4
sizeof (struct smb_hdr) - /* do not count RFC1001 header */ +
4 /* do not count RFC1001 header */ +
(2 * out_buf->WordCount) + 2 /* bcc */ ) (2 * out_buf->WordCount) + 2 /* bcc */ )
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else { } else {
......
...@@ -261,21 +261,26 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, ...@@ -261,21 +261,26 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { #ifdef CONFIG_CIFS_EXPERIMENTAL
else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
__u16 fid; __u16 fid;
int oplock = FALSE; int oplock = FALSE;
rc = CIFSSMBOpen(xid, pTcon, full_path, if (experimEnabled)
FILE_OPEN, GENERIC_READ, 0, &fid, rc = CIFSSMBOpen(xid, pTcon, full_path,
&oplock, NULL, cifs_sb->local_nls, FILE_OPEN, GENERIC_READ, 0, &fid,
cifs_sb->mnt_cifs_flags & &oplock, NULL, cifs_sb->local_nls,
CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
/* else rc is EOPNOTSUPP from above */
if(rc == 0) { if(rc == 0) {
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
ea_value, buf_size, ea_value, buf_size,
ACL_TYPE_ACCESS); ACL_TYPE_ACCESS);
CIFSSMBClose(xid, pTcon, fid); CIFSSMBClose(xid, pTcon, fid);
} }
} */ /* BB enable after fixing up return data */ }
#endif /* EXPERIMENTAL */
#else #else
cFYI(1, ("query POSIX ACL not supported yet")); cFYI(1, ("query POSIX ACL not supported yet"));
#endif /* CONFIG_CIFS_POSIX */ #endif /* CONFIG_CIFS_POSIX */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment