diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/CHANGES | 5 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 120 | ||||
-rw-r--r-- | fs/cifs/cifsacl.h | 24 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 4 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 2 | ||||
-rw-r--r-- | fs/cifs/export.c | 1 |
7 files changed, 141 insertions, 22 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index c8ad87de4a78..13071faf8af7 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -6,7 +6,10 @@ which support the current POSIX Extensions to provide better semantics | |||
6 | (e.g. delete for open files opened with posix open). Take into | 6 | (e.g. delete for open files opened with posix open). Take into |
7 | account umask on posix mkdir not just older style mkdir. Add | 7 | account umask on posix mkdir not just older style mkdir. Add |
8 | ability to mount to IPC$ share (which allows CIFS named pipes to be | 8 | ability to mount to IPC$ share (which allows CIFS named pipes to be |
9 | opened, read and written as if they were files). | 9 | opened, read and written as if they were files). When 1st tree |
10 | connect fails (e.g. due to signing negotiation failure) fix | ||
11 | leak that causes cifsd not to stop and rmmod to fail to cleanup | ||
12 | cifs_request_buffers pool. | ||
10 | 13 | ||
11 | Version 1.50 | 14 | Version 1.50 |
12 | ------------ | 15 | ------------ |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 52f9cb808fd0..43ab26fff398 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -28,6 +28,20 @@ | |||
28 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
29 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
30 | 30 | ||
31 | |||
32 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
33 | |||
34 | struct cifs_wksid wksidarr[NUM_WK_SIDS] = { | ||
35 | {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"}, | ||
36 | {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"}, | ||
37 | {{1, 1, {0, 0, 0, 0, 0, 5}, {11, 0, 0, 0, 0} }, "net-users"}, | ||
38 | {{1, 1, {0, 0, 0, 0, 0, 5}, {18, 0, 0, 0, 0} }, "sys"}, | ||
39 | {{1, 2, {0, 0, 0, 0, 0, 5}, {32, 544, 0, 0, 0} }, "root"}, | ||
40 | {{1, 2, {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0, 0} }, "users"}, | ||
41 | {{1, 2, {0, 0, 0, 0, 0, 5}, {32, 546, 0, 0, 0} }, "guest"} | ||
42 | }; | ||
43 | |||
44 | |||
31 | /* security id for everyone */ | 45 | /* security id for everyone */ |
32 | static const struct cifs_sid sid_everyone = | 46 | static const struct cifs_sid sid_everyone = |
33 | {1, 1, {0, 0, 0, 0, 0, 0}, {} }; | 47 | {1, 1, {0, 0, 0, 0, 0, 0}, {} }; |
@@ -35,33 +49,113 @@ static const struct cifs_sid sid_everyone = | |||
35 | static const struct cifs_sid sid_user = | 49 | static const struct cifs_sid sid_user = |
36 | {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | 50 | {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; |
37 | 51 | ||
52 | |||
53 | int match_sid(struct cifs_sid *ctsid) | ||
54 | { | ||
55 | int i, j; | ||
56 | int num_subauth, num_sat, num_saw; | ||
57 | struct cifs_sid *cwsid; | ||
58 | |||
59 | if (!ctsid) | ||
60 | return (-1); | ||
61 | |||
62 | for (i = 0; i < NUM_WK_SIDS; ++i) { | ||
63 | cwsid = &(wksidarr[i].cifssid); | ||
64 | |||
65 | /* compare the revision */ | ||
66 | if (ctsid->revision != cwsid->revision) | ||
67 | continue; | ||
68 | |||
69 | /* compare all of the six auth values */ | ||
70 | for (j = 0; j < 6; ++j) { | ||
71 | if (ctsid->authority[j] != cwsid->authority[j]) | ||
72 | break; | ||
73 | } | ||
74 | if (j < 6) | ||
75 | continue; /* all of the auth values did not match */ | ||
76 | |||
77 | /* compare all of the subauth values if any */ | ||
78 | num_sat = cpu_to_le32(ctsid->num_subauth); | ||
79 | num_saw = cpu_to_le32(cwsid->num_subauth); | ||
80 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | ||
81 | if (num_subauth) { | ||
82 | for (j = 0; j < num_subauth; ++j) { | ||
83 | if (ctsid->sub_auth[j] != cwsid->sub_auth[j]) | ||
84 | break; | ||
85 | } | ||
86 | if (j < num_subauth) | ||
87 | continue; /* all sub_auth values do not match */ | ||
88 | } | ||
89 | |||
90 | cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname)); | ||
91 | return (0); /* sids compare/match */ | ||
92 | } | ||
93 | |||
94 | cFYI(1, ("No matching sid")); | ||
95 | return (-1); | ||
96 | } | ||
97 | |||
98 | |||
99 | int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid) | ||
100 | { | ||
101 | int i; | ||
102 | int num_subauth, num_sat, num_saw; | ||
103 | |||
104 | if ((!ctsid) || (!cwsid)) | ||
105 | return (-1); | ||
106 | |||
107 | /* compare the revision */ | ||
108 | if (ctsid->revision != cwsid->revision) | ||
109 | return (-1); | ||
110 | |||
111 | /* compare all of the six auth values */ | ||
112 | for (i = 0; i < 6; ++i) { | ||
113 | if (ctsid->authority[i] != cwsid->authority[i]) | ||
114 | return (-1); | ||
115 | } | ||
116 | |||
117 | /* compare all of the subauth values if any */ | ||
118 | num_sat = cpu_to_le32(ctsid->num_subauth); | ||
119 | num_saw = cpu_to_le32(cwsid->num_subauth); | ||
120 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | ||
121 | if (num_subauth) { | ||
122 | for (i = 0; i < num_subauth; ++i) { | ||
123 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) | ||
124 | return (-1); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | return (0); /* sids compare/match */ | ||
129 | } | ||
130 | |||
131 | |||
38 | static void parse_ace(struct cifs_ace *pace, char *end_of_acl) | 132 | static void parse_ace(struct cifs_ace *pace, char *end_of_acl) |
39 | { | 133 | { |
40 | int i; | 134 | int i; |
41 | int num_subauth; | 135 | int num_subauth; |
42 | __u32 *psub_auth; | ||
43 | 136 | ||
44 | /* validate that we do not go past end of acl */ | 137 | /* validate that we do not go past end of acl */ |
138 | |||
139 | /* XXX this if statement can be removed | ||
45 | if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) { | 140 | if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) { |
46 | cERROR(1, ("ACL too small to parse ACE")); | 141 | cERROR(1, ("ACL too small to parse ACE")); |
47 | return; | 142 | return; |
48 | } | 143 | } */ |
49 | 144 | ||
50 | num_subauth = cpu_to_le32(pace->num_subauth); | 145 | num_subauth = cpu_to_le32(pace->num_subauth); |
51 | if (num_subauth) { | 146 | if (num_subauth) { |
52 | psub_auth = (__u32 *)((char *)pace + sizeof(struct cifs_ace)); | ||
53 | #ifdef CONFIG_CIFS_DEBUG2 | 147 | #ifdef CONFIG_CIFS_DEBUG2 |
54 | cFYI(1, ("ACE revision %d num_subauth %d", | 148 | cFYI(1, ("ACE revision %d num_subauth %d", |
55 | pace->revision, pace->num_subauth)); | 149 | pace->revision, pace->num_subauth)); |
56 | for (i = 0; i < num_subauth; ++i) { | 150 | for (i = 0; i < num_subauth; ++i) { |
57 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, | 151 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, |
58 | le32_to_cpu(psub_auth[i]))); | 152 | le32_to_cpu(pace->sub_auth[i]))); |
59 | } | 153 | } |
60 | 154 | ||
61 | /* BB add length check to make sure that we do not have huge | 155 | /* BB add length check to make sure that we do not have huge |
62 | num auths and therefore go off the end */ | 156 | num auths and therefore go off the end */ |
63 | 157 | ||
64 | cFYI(1, ("RID %d", le32_to_cpu(psub_auth[num_subauth-1]))); | 158 | cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1]))); |
65 | #endif | 159 | #endif |
66 | } | 160 | } |
67 | 161 | ||
@@ -132,7 +226,13 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl) | |||
132 | sizeof(struct cifs_ntace)); | 226 | sizeof(struct cifs_ntace)); |
133 | 227 | ||
134 | parse_ntace(ppntace[i], end_of_acl); | 228 | parse_ntace(ppntace[i], end_of_acl); |
135 | parse_ace(ppace[i], end_of_acl); | 229 | if (end_of_acl < ((char *)ppace[i] + |
230 | (ppntace[i]->size - | ||
231 | sizeof(struct cifs_ntace)))) { | ||
232 | cERROR(1, ("ACL too small to parse ACE")); | ||
233 | break; | ||
234 | } else | ||
235 | parse_ace(ppace[i], end_of_acl); | ||
136 | 236 | ||
137 | /* memcpy((void *)(&(cifscred->ntaces[i])), | 237 | /* memcpy((void *)(&(cifscred->ntaces[i])), |
138 | (void *)ppntace[i], | 238 | (void *)ppntace[i], |
@@ -157,7 +257,6 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
157 | { | 257 | { |
158 | int i; | 258 | int i; |
159 | int num_subauth; | 259 | int num_subauth; |
160 | __u32 *psub_auth; | ||
161 | 260 | ||
162 | /* BB need to add parm so we can store the SID BB */ | 261 | /* BB need to add parm so we can store the SID BB */ |
163 | 262 | ||
@@ -169,20 +268,19 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
169 | 268 | ||
170 | num_subauth = cpu_to_le32(psid->num_subauth); | 269 | num_subauth = cpu_to_le32(psid->num_subauth); |
171 | if (num_subauth) { | 270 | if (num_subauth) { |
172 | psub_auth = (__u32 *)((char *)psid + sizeof(struct cifs_sid)); | ||
173 | #ifdef CONFIG_CIFS_DEBUG2 | 271 | #ifdef CONFIG_CIFS_DEBUG2 |
174 | cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x", | 272 | cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x", |
175 | psid->revision, psid->num_subauth, psid->sub_auth[0])); | 273 | psid->revision, psid->num_subauth, psid->sub_auth[0])); |
176 | 274 | ||
177 | for (i = 0; i < num_subauth; ++i) { | 275 | for (i = 0; i < num_subauth; ++i) { |
178 | cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, | 276 | cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, |
179 | le32_to_cpu(psub_auth[i]))); | 277 | le32_to_cpu(psid->sub_auth[i]))); |
180 | } | 278 | } |
181 | 279 | ||
182 | /* BB add length check to make sure that we do not have huge | 280 | /* BB add length check to make sure that we do not have huge |
183 | num auths and therefore go off the end */ | 281 | num auths and therefore go off the end */ |
184 | cFYI(1, ("RID 0x%x", | 282 | cFYI(1, ("RID 0x%x", |
185 | le32_to_cpu(psid->sub_auth[psid->num_subauth]))); | 283 | le32_to_cpu(psid->sub_auth[num_subauth-1]))); |
186 | #endif | 284 | #endif |
187 | } | 285 | } |
188 | 286 | ||
@@ -228,5 +326,7 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | |||
228 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 326 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
229 | sizeof (struct cifs_sid)); */ | 327 | sizeof (struct cifs_sid)); */ |
230 | 328 | ||
329 | |||
231 | return (0); | 330 | return (0); |
232 | } | 331 | } |
332 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index bf297ea1905a..1b115641b722 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -22,6 +22,10 @@ | |||
22 | #ifndef _CIFSACL_H | 22 | #ifndef _CIFSACL_H |
23 | #define _CIFSACL_H | 23 | #define _CIFSACL_H |
24 | 24 | ||
25 | |||
26 | #define NUM_WK_SIDS 7 /* number of well known sids */ | ||
27 | #define SIDNAMELENGTH 20 /* long enough for the ones we care about */ | ||
28 | |||
25 | struct cifs_ntsd { | 29 | struct cifs_ntsd { |
26 | __u16 revision; /* revision level */ | 30 | __u16 revision; /* revision level */ |
27 | __u16 type; | 31 | __u16 type; |
@@ -35,7 +39,7 @@ struct cifs_sid { | |||
35 | __u8 revision; /* revision level */ | 39 | __u8 revision; /* revision level */ |
36 | __u8 num_subauth; | 40 | __u8 num_subauth; |
37 | __u8 authority[6]; | 41 | __u8 authority[6]; |
38 | __u32 sub_auth[0]; /* sub_auth[num_subauth] */ | 42 | __u32 sub_auth[5]; /* sub_auth[num_subauth] */ |
39 | } __attribute__((packed)); | 43 | } __attribute__((packed)); |
40 | 44 | ||
41 | struct cifs_acl { | 45 | struct cifs_acl { |
@@ -55,12 +59,20 @@ struct cifs_ace { /* last part of ACE which includes user info */ | |||
55 | __u8 revision; /* revision level */ | 59 | __u8 revision; /* revision level */ |
56 | __u8 num_subauth; | 60 | __u8 num_subauth; |
57 | __u8 authority[6]; | 61 | __u8 authority[6]; |
58 | __u32 sub_auth[0]; | 62 | __u32 sub_auth[5]; |
63 | } __attribute__((packed)); | ||
64 | |||
65 | struct cifs_wksid { | ||
66 | struct cifs_sid cifssid; | ||
67 | char sidname[SIDNAMELENGTH]; | ||
59 | } __attribute__((packed)); | 68 | } __attribute__((packed)); |
60 | 69 | ||
61 | /* everyone */ | 70 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
62 | /* extern const struct cifs_sid sid_everyone;*/ | 71 | |
63 | /* group users */ | 72 | extern struct cifs_wksid wksidarr[NUM_WK_SIDS]; |
64 | /* extern const struct cifs_sid sid_user;*/ | 73 | extern int match_sid(struct cifs_sid *); |
74 | extern int compare_sids(struct cifs_sid *, struct cifs_sid *); | ||
75 | |||
76 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
65 | 77 | ||
66 | #endif /* _CIFSACL_H */ | 78 | #endif /* _CIFSACL_H */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c7c3521aa7cd..abca6b084ed1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -49,10 +49,6 @@ | |||
49 | static struct quotactl_ops cifs_quotactl_ops; | 49 | static struct quotactl_ops cifs_quotactl_ops; |
50 | #endif /* QUOTA */ | 50 | #endif /* QUOTA */ |
51 | 51 | ||
52 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
53 | extern struct export_operations cifs_export_ops; | ||
54 | #endif /* EXPERIMENTAL */ | ||
55 | |||
56 | int cifsFYI = 0; | 52 | int cifsFYI = 0; |
57 | int cifsERROR = 1; | 53 | int cifsERROR = 1; |
58 | int traceSMB = 0; | 54 | int traceSMB = 0; |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 13c53a4ee0f7..0a3ee5a322b0 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/cifsfs.h | 2 | * fs/cifs/cifsfs.h |
3 | * | 3 | * |
4 | * Copyright (c) International Business Machines Corp., 2002, 2005 | 4 | * Copyright (c) International Business Machines Corp., 2002, 2007 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * 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); | |||
101 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 101 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
102 | extern int cifs_ioctl(struct inode *inode, struct file *filep, | 102 | extern int cifs_ioctl(struct inode *inode, struct file *filep, |
103 | unsigned int command, unsigned long arg); | 103 | unsigned int command, unsigned long arg); |
104 | |||
105 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
106 | extern struct export_operations cifs_export_ops; | ||
107 | #endif /* EXPERIMENTAL */ | ||
108 | |||
104 | #define CIFS_VERSION "1.51" | 109 | #define CIFS_VERSION "1.51" |
105 | #endif /* _CIFSFS_H */ | 110 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index fda8b2490263..eff3226b2104 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -3058,6 +3058,7 @@ GetExtAttrOut: | |||
3058 | 3058 | ||
3059 | #endif /* CONFIG_POSIX */ | 3059 | #endif /* CONFIG_POSIX */ |
3060 | 3060 | ||
3061 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
3061 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ | 3062 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ |
3062 | int | 3063 | int |
3063 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3064 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, |
@@ -3129,6 +3130,7 @@ qsec_out: | |||
3129 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ | 3130 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ |
3130 | return rc; | 3131 | return rc; |
3131 | } | 3132 | } |
3133 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
3132 | 3134 | ||
3133 | /* Legacy Query Path Information call for lookup to old servers such | 3135 | /* Legacy Query Path Information call for lookup to old servers such |
3134 | as Win9x/WinME */ | 3136 | as Win9x/WinME */ |
diff --git a/fs/cifs/export.c b/fs/cifs/export.c index 893fd0aebff8..d614b91caeca 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/exportfs.h> | 43 | #include <linux/exportfs.h> |
44 | #include "cifsglob.h" | 44 | #include "cifsglob.h" |
45 | #include "cifs_debug.h" | 45 | #include "cifs_debug.h" |
46 | #include "cifsfs.h" | ||
46 | 47 | ||
47 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 48 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
48 | static struct dentry *cifs_get_parent(struct dentry *dentry) | 49 | static struct dentry *cifs_get_parent(struct dentry *dentry) |