diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/CHANGES | 21 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/asn1.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 28 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 333 | ||||
-rw-r--r-- | fs/cifs/cifsacl.h | 64 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 5 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 38 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 11 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 31 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 20 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 8 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 158 | ||||
-rw-r--r-- | fs/cifs/connect.c | 262 | ||||
-rw-r--r-- | fs/cifs/dir.c | 9 | ||||
-rw-r--r-- | fs/cifs/export.c | 1 | ||||
-rw-r--r-- | fs/cifs/file.c | 86 | ||||
-rw-r--r-- | fs/cifs/inode.c | 52 | ||||
-rw-r--r-- | fs/cifs/link.c | 2 | ||||
-rw-r--r-- | fs/cifs/misc.c | 1 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 33 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 8 | ||||
-rw-r--r-- | fs/cifs/sess.c | 103 | ||||
-rw-r--r-- | fs/cifs/smberr.h | 5 | ||||
-rw-r--r-- | fs/cifs/transport.c | 34 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 19 |
26 files changed, 961 insertions, 383 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index bed6215c079..3d419163c3d 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,19 @@ +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 ------------ 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 Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" mount option to allow disabling the CIFS Unix Extensions for just 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 ------------ diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 6ecd9d6ba3f..ff6ba8d823f 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -3,4 +3,4 @@ # 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 diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index f50a88d58f7..2a01f3ef96a 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -385,10 +385,9 @@ asn1_oid_decode(struct asn1_ctx *ctx, unsigned long *optr; size = eoc - ctx->pointer + 1; - *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC); - if (*oid == NULL) { + *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); + if (*oid == NULL) return 0; - } optr = *oid; @@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { - cFYI(1, - ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end)); + cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end)); } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 1bf8cf522ad..73c4c419663 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, i++; tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); - length = - sprintf(buf, - "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x " - "Attributes: 0x%x\nPathComponentMax: %d Status: %d", - i, tcon->treeName, - atomic_read(&tcon->useCount), - tcon->nativeFileSystem, + length = sprintf(buf, "\n%d) %s Uses: %d ", i, + tcon->treeName, atomic_read(&tcon->useCount)); + buf += length; + if (tcon->nativeFileSystem) { + length = sprintf(buf, "Type: %s ", + 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->fsAttrInfo.Attributes), le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), @@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer, if (count < 3) { /* single char or single char followed by null */ c = flags_string[0]; - if (c == '0' || c == 'n' || c == 'N') + if (c == '0' || c == 'n' || c == 'N') { 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; - return count; + return count; + } else if (!isdigit(c)) { + cERROR(1, ("invalid flag %c", c)); + return -EINVAL; + } } /* else we have a number */ diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c new file mode 100644 index 00000000000..e8e56353f5a --- /dev/null +++ b/fs/cifs/cifsacl.c @@ -0,0 +1,333 @@ +/* + * 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 */ diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 5eff35d6e56..420f8781364 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -1,7 +1,7 @@ /* * 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) * * This library is free software; you can redistribute it and/or modify @@ -22,17 +22,65 @@ #ifndef _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 { __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]; - __u32 sub_auth[4]; - /* next sub_auth if any ... */ + __le32 sub_auth[5]; } __attribute__((packed)); -/* everyone */ -/* extern const struct cifs_sid sid_everyone;*/ -/* group users */ -/* extern const struct cifs_sid sid_user;*/ +struct cifs_wksid { + struct cifs_sid cifssid; + char sidname[SIDNAMELENGTH]; +} __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 */ diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 36272293027..632070b4275 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -345,7 +345,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, user = kmalloc(2 + (len * 2), GFP_KERNEL); if (user == NULL) 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); hmac_md5_update((char *)user, 2*len, pctxt); @@ -356,7 +356,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, domain = kmalloc(2 + (len * 2), GFP_KERNEL); if (domain == NULL) 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 with lower cased domain name that passed as an option. Maybe converting the domain name earlier makes sense */ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ba8f7868cb2..a6fbea57c4b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -49,10 +49,6 @@ static struct quotactl_ops cifs_quotactl_ops; #endif /* QUOTA */ -#ifdef CONFIG_CIFS_EXPERIMENTAL -extern struct export_operations cifs_export_ops; -#endif /* EXPERIMENTAL */ - int cifsFYI = 0; int cifsERROR = 1; int traceSMB = 0; @@ -240,9 +236,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd) 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; - } 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 servers which do not support setting and viewing mode bits, so allowing client to check permissions is useful */ @@ -312,15 +308,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) seq_printf(s, ",domain=%s", 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) 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, ",wsize=%d", cifs_sb->wsize); } @@ -346,7 +342,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid, if (pTcon) { cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); } else { - return -EIO; + rc = -EIO; } FreeXid(xid); @@ -716,7 +712,7 @@ static int cifs_init_inodecache(void) { cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", - sizeof (struct cifsInodeInfo), + sizeof(struct cifsInodeInfo), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD), cifs_init_once); @@ -816,8 +812,8 @@ static int cifs_init_mids(void) { cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", - sizeof (struct mid_q_entry), 0, - SLAB_HWCACHE_ALIGN, NULL); + sizeof(struct mid_q_entry), 0, + SLAB_HWCACHE_ALIGN, NULL); if (cifs_mid_cachep == NULL) return -ENOMEM; @@ -829,8 +825,8 @@ cifs_init_mids(void) } cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", - sizeof (struct oplock_q_entry), 0, - SLAB_HWCACHE_ALIGN, NULL); + sizeof(struct oplock_q_entry), 0, + SLAB_HWCACHE_ALIGN, NULL); if (cifs_oplock_cachep == NULL) { mempool_destroy(cifs_mid_poolp); kmem_cache_destroy(cifs_mid_cachep); @@ -882,7 +878,8 @@ static int cifs_oplock_thread(void *dummyarg) the call */ /* mutex_lock(&inode->i_mutex);*/ if (S_ISREG(inode->i_mode)) { - rc = filemap_fdatawrite(inode->i_mapping); + rc = + filemap_fdatawrite(inode->i_mapping); if (CIFS_I(inode)->clientCanCacheRead == 0) { filemap_fdatawait(inode->i_mapping); @@ -907,8 +904,7 @@ static int cifs_oplock_thread(void *dummyarg) 0 /* len */ , 0 /* offset */, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, 0 /* wait flag */); - cFYI(1, - ("Oplock release rc = %d ", rc)); + cFYI(1, ("Oplock release rc = %d", rc)); } } else spin_unlock(&GlobalMid_Lock); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index a20de77a385..0a3ee5a322b 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -1,7 +1,7 @@ /* * 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) * * 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 *, size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, 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); -#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 */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b98742fc3b5..87f51f23276 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -19,6 +19,7 @@ #include <linux/in.h> #include <linux/in6.h> #include "cifs_fs_sb.h" +#include "cifsacl.h" /* * The sizes of various internal tables and strings */ @@ -89,7 +90,8 @@ enum statusEnum { }; enum securityEnum { - LANMAN = 0, /* Legacy LANMAN auth */ + PLAINTXT = 0, /* Legacy with Plaintext passwords */ + LANMAN, /* Legacy LANMAN auth */ NTLM, /* Legacy NTLM012 auth with NTLM hash */ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ RawNTLMSSP, /* NTLMSSP without SPNEGO */ @@ -115,6 +117,17 @@ struct mac_key { } 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 @@ -279,6 +292,7 @@ struct cifsTconInfo { FILE_SYSTEM_DEVICE_INFO fsDevInfo; FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ FILE_SYSTEM_UNIX_INFO fsUnixInfo; + unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ unsigned retry:1; unsigned nocase:1; unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol @@ -329,6 +343,7 @@ struct cifsFileInfo { struct list_head llist; /* list of byte range locks we have. */ unsigned closePend:1; /* file is marked to close */ 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 */ struct semaphore fh_sem; /* prevents reopen race after dead ses*/ char *search_resume_name; /* BB removeme BB */ @@ -464,6 +479,9 @@ struct dir_notify_req { #ifdef CONFIG_CIFS_WEAK_PW_HASH #define CIFSSEC_MAY_LANMAN 0x00010 #define CIFSSEC_MAY_PLNTXT 0x00020 +#else +#define CIFSSEC_MAY_LANMAN 0 +#define CIFSSEC_MAY_PLNTXT 0 #endif /* weak passwords */ #define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ @@ -477,14 +495,23 @@ require use of the stronger protocol */ #ifdef CONFIG_CIFS_WEAK_PW_HASH #define CIFSSEC_MUST_LANMAN 0x10010 #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 */ +#endif /* UPCALL */ +#else /* do not allow weak pw hash */ +#ifdef CONFIG_CIFS_UPCALL +#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */ #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 */ #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ #define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_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 diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 6a2056e58ce..c41ff74e912 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -215,6 +215,12 @@ /* file_execute, file_read_attributes*/ /* 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 */ @@ -360,10 +366,10 @@ struct smb_hdr { __u8 WordCount; } __attribute__((packed)); /* 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_LE(smb_var) ( *(__le16 *)((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))) /* 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) @@ -716,6 +722,14 @@ typedef struct smb_com_findclose_req { #define REQ_OPENDIRONLY 0x00000008 #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 */ struct smb_hdr hdr; /* wct = 24 */ __u8 AndXCommand; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 04a69dafedb..1a883663b22 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, int * /* bytes returned */ , const int long_op); extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 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 */ , struct cifsTconInfo *, struct smb_hdr * /* input */ , @@ -65,7 +66,7 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern int decode_negTokenInit(unsigned char *security_blob, int length, enum securityEnum *secType); 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 */ , const struct cifsTconInfo *, int /* length |