]> err.no Git - linux-2.6/commitdiff
[CIFS] CIFS ACL support part 3
authorSteve French <sfrench@us.ibm.com>
Fri, 12 Oct 2007 04:11:59 +0000 (04:11 +0000)
committerSteve French <sfrench@us.ibm.com>
Fri, 12 Oct 2007 04:11:59 +0000 (04:11 +0000)
Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/CHANGES
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifssmb.c
fs/cifs/export.c

index c8ad87de4a784b6a3a9fd58b9a3752db0285ed73..13071faf8af72ed300091cbb921f45f16ff5595c 100644 (file)
@@ -6,7 +6,10 @@ 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).
+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.
 
 Version 1.50
 ------------
index 52f9cb808fd033d93ee88a466983bea88f26a594..43ab26fff398eb2537962feaa77d01a0387b8a58 100644 (file)
 #include "cifsproto.h"
 #include "cifs_debug.h"
 
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+
+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}, {11, 0, 0, 0, 0} }, "net-users"},
+       {{1, 1, {0, 0, 0, 0, 0, 5}, {18, 0, 0, 0, 0} }, "sys"},
+       {{1, 2, {0, 0, 0, 0, 0, 5}, {32, 544, 0, 0, 0} }, "root"},
+       {{1, 2, {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0, 0} }, "users"},
+       {{1, 2, {0, 0, 0, 0, 0, 5}, {32, 546, 0, 0, 0} }, "guest"}
+};
+
+
 /* security id for everyone */
 static const struct cifs_sid sid_everyone =
                {1, 1, {0, 0, 0, 0, 0, 0}, {} };
@@ -35,33 +49,113 @@ static const struct cifs_sid sid_everyone =
 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 = cpu_to_le32(ctsid->num_subauth);
+               num_saw = cpu_to_le32(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);
+}
+
+
+int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
+{
+       int i;
+       int num_subauth, num_sat, num_saw;
+
+       if ((!ctsid) || (!cwsid))
+               return (-1);
+
+       /* compare the revision */
+       if (ctsid->revision != cwsid->revision)
+               return (-1);
+
+       /* compare all of the six auth values */
+       for (i = 0; i < 6; ++i) {
+               if (ctsid->authority[i] != cwsid->authority[i])
+                       return (-1);
+       }
+
+       /* compare all of the subauth values if any */
+       num_sat = cpu_to_le32(ctsid->num_subauth);
+       num_saw = cpu_to_le32(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 (-1);
+               }
+       }
+
+       return (0); /* sids compare/match */
+}
+
+
 static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
 {
        int i;
        int num_subauth;
-        __u32 *psub_auth;
 
        /* 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 = cpu_to_le32(pace->num_subauth);
        if (num_subauth) {
-               psub_auth = (__u32 *)((char *)pace + sizeof(struct cifs_ace));
 #ifdef CONFIG_CIFS_DEBUG2
                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(psub_auth[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(psub_auth[num_subauth-1])));
+               cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1])));
 #endif
        }
 
@@ -132,7 +226,13 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl)
                                        sizeof(struct cifs_ntace));
 
                        parse_ntace(ppntace[i], end_of_acl);
-                       parse_ace(ppace[i], end_of_acl);
+                       if (end_of_acl < ((char *)ppace[i] +
+                                       (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],
@@ -157,7 +257,6 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 {
        int i;
        int num_subauth;
-       __u32 *psub_auth;
 
        /* BB need to add parm so we can store the SID BB */
 
@@ -169,20 +268,19 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 
        num_subauth = cpu_to_le32(psid->num_subauth);
        if (num_subauth) {
-               psub_auth = (__u32 *)((char *)psid + sizeof(struct cifs_sid));
 #ifdef CONFIG_CIFS_DEBUG2
                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 < num_subauth; ++i) {
                        cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
-                               le32_to_cpu(psub_auth[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])));
+                       le32_to_cpu(psid->sub_auth[num_subauth-1])));
 #endif
        }
 
@@ -228,5 +326,7 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
        memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
                        sizeof (struct cifs_sid)); */
 
+
        return (0);
 }
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
index bf297ea1905a349653923ab944e1ba68496c2ccd..1b115641b7222c3d2d0f363eea5e2eaff492c150 100644 (file)
 #ifndef _CIFSACL_H
 #define _CIFSACL_H
 
+
+#define NUM_WK_SIDS 7 /* number of well known sids */
+#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
+
 struct cifs_ntsd {
        __u16 revision; /* revision level */
        __u16 type;
@@ -35,7 +39,7 @@ struct cifs_sid {
        __u8 revision; /* revision level */
        __u8 num_subauth;
        __u8 authority[6];
-       __u32 sub_auth[0]; /* sub_auth[num_subauth] */
+       __u32 sub_auth[5]; /* sub_auth[num_subauth] */
 } __attribute__((packed));
 
 struct cifs_acl {
@@ -55,12 +59,20 @@ struct cifs_ace { /* last part of ACE which includes user info */
        __u8 revision; /* revision level */
        __u8 num_subauth;
        __u8 authority[6];
-       __u32 sub_auth[0];
+       __u32 sub_auth[5];
+} __attribute__((packed));
+
+struct cifs_wksid {
+       struct cifs_sid cifssid;
+       char sidname[SIDNAMELENGTH];
 } __attribute__((packed));
 
-/* everyone */
-/* extern const struct cifs_sid sid_everyone;*/
-/* group users */
-/* extern const struct cifs_sid sid_user;*/
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+
+extern struct cifs_wksid wksidarr[NUM_WK_SIDS];
+extern int match_sid(struct cifs_sid *);
+extern int compare_sids(struct cifs_sid *, struct cifs_sid *);
+
+#endif /*  CONFIG_CIFS_EXPERIMENTAL */
 
 #endif /* _CIFSACL_H */
index c7c3521aa7cddc601170b4f6e716e996f98d62c7..abca6b084ed1468f48507a04db168fe89851ac25 100644 (file)
 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;
index 13c53a4ee0f7ad2c23573db24b69cc6190d5c75e..0a3ee5a322b02a4329c1448dea61713a1c422f24 100644 (file)
@@ -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
@@ -101,5 +101,10 @@ 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,
                       unsigned int command, unsigned long arg);
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern struct export_operations cifs_export_ops;
+#endif /* EXPERIMENTAL */
+
 #define CIFS_VERSION   "1.51"
 #endif                         /* _CIFSFS_H */
index fda8b2490263a8fd437974385fea980bf4dcddcd..eff3226b210498965432b149da88c40d7447bb63 100644 (file)
@@ -3058,6 +3058,7 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
@@ -3129,6 +3130,7 @@ qsec_out:
 /*     cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
        return rc;
 }
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
index 893fd0aebff82160ec04ecd6b4de5825c7bfa956..d614b91caeca5f53ad188dd5f20735f1a88d9501 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/exportfs.h>
 #include "cifsglob.h"
 #include "cifs_debug.h"
+#include "cifsfs.h"
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 static struct dentry *cifs_get_parent(struct dentry *dentry)