diff options
Diffstat (limited to 'fs/cifs/cifsacl.c')
-rw-r--r-- | fs/cifs/cifsacl.c | 483 |
1 files changed, 418 insertions, 65 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index beeebf194234..f3c6fb9942ac 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -23,24 +23,16 @@ | |||
23 | 23 | ||
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/string.h> | ||
27 | #include <linux/keyctl.h> | ||
28 | #include <linux/key-type.h> | ||
29 | #include <keys/user-type.h> | ||
26 | #include "cifspdu.h" | 30 | #include "cifspdu.h" |
27 | #include "cifsglob.h" | 31 | #include "cifsglob.h" |
28 | #include "cifsacl.h" | 32 | #include "cifsacl.h" |
29 | #include "cifsproto.h" | 33 | #include "cifsproto.h" |
30 | #include "cifs_debug.h" | 34 | #include "cifs_debug.h" |
31 | 35 | ||
32 | |||
33 | static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { | ||
34 | {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"}, | ||
35 | {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"}, | ||
36 | {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"}, | ||
37 | {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"}, | ||
38 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"}, | ||
39 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"}, | ||
40 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} } | ||
41 | ; | ||
42 | |||
43 | |||
44 | /* security id for everyone/world system group */ | 36 | /* security id for everyone/world system group */ |
45 | static const struct cifs_sid sid_everyone = { | 37 | static const struct cifs_sid sid_everyone = { |
46 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; | 38 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; |
@@ -50,50 +42,385 @@ static const struct cifs_sid sid_authusers = { | |||
50 | /* group users */ | 42 | /* group users */ |
51 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | 43 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; |
52 | 44 | ||
45 | const struct cred *root_cred; | ||
53 | 46 | ||
54 | int match_sid(struct cifs_sid *ctsid) | 47 | static void |
48 | shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem, | ||
49 | int *nr_del) | ||
55 | { | 50 | { |
56 | int i, j; | 51 | struct rb_node *node; |
57 | int num_subauth, num_sat, num_saw; | 52 | struct rb_node *tmp; |
58 | struct cifs_sid *cwsid; | 53 | struct cifs_sid_id *psidid; |
54 | |||
55 | node = rb_first(root); | ||
56 | while (node) { | ||
57 | tmp = node; | ||
58 | node = rb_next(tmp); | ||
59 | psidid = rb_entry(tmp, struct cifs_sid_id, rbnode); | ||
60 | if (nr_to_scan == 0 || *nr_del == nr_to_scan) | ||
61 | ++(*nr_rem); | ||
62 | else { | ||
63 | if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE) | ||
64 | && psidid->refcount == 0) { | ||
65 | rb_erase(tmp, root); | ||
66 | ++(*nr_del); | ||
67 | } else | ||
68 | ++(*nr_rem); | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Run idmap cache shrinker. | ||
75 | */ | ||
76 | static int | ||
77 | cifs_idmap_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) | ||
78 | { | ||
79 | int nr_del = 0; | ||
80 | int nr_rem = 0; | ||
81 | struct rb_root *root; | ||
82 | |||
83 | root = &uidtree; | ||
84 | spin_lock(&siduidlock); | ||
85 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
86 | spin_unlock(&siduidlock); | ||
87 | |||
88 | root = &gidtree; | ||
89 | spin_lock(&sidgidlock); | ||
90 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
91 | spin_unlock(&sidgidlock); | ||
92 | |||
93 | return nr_rem; | ||
94 | } | ||
95 | |||
96 | static struct shrinker cifs_shrinker = { | ||
97 | .shrink = cifs_idmap_shrinker, | ||
98 | .seeks = DEFAULT_SEEKS, | ||
99 | }; | ||
100 | |||
101 | static int | ||
102 | cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) | ||
103 | { | ||
104 | char *payload; | ||
105 | |||
106 | payload = kmalloc(datalen, GFP_KERNEL); | ||
107 | if (!payload) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | memcpy(payload, data, datalen); | ||
111 | key->payload.data = payload; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static inline void | ||
116 | cifs_idmap_key_destroy(struct key *key) | ||
117 | { | ||
118 | kfree(key->payload.data); | ||
119 | } | ||
59 | 120 | ||
60 | if (!ctsid) | 121 | struct key_type cifs_idmap_key_type = { |
61 | return -1; | 122 | .name = "cifs.idmap", |
123 | .instantiate = cifs_idmap_key_instantiate, | ||
124 | .destroy = cifs_idmap_key_destroy, | ||
125 | .describe = user_describe, | ||
126 | .match = user_match, | ||
127 | }; | ||
128 | |||
129 | static void | ||
130 | sid_to_str(struct cifs_sid *sidptr, char *sidstr) | ||
131 | { | ||
132 | int i; | ||
133 | unsigned long saval; | ||
134 | char *strptr; | ||
62 | 135 | ||
63 | for (i = 0; i < NUM_WK_SIDS; ++i) { | 136 | strptr = sidstr; |
64 | cwsid = &(wksidarr[i].cifssid); | ||
65 | 137 | ||
66 | /* compare the revision */ | 138 | sprintf(strptr, "%s", "S"); |
67 | if (ctsid->revision != cwsid->revision) | 139 | strptr = sidstr + strlen(sidstr); |
68 | continue; | ||
69 | 140 | ||
70 | /* compare all of the six auth values */ | 141 | sprintf(strptr, "-%d", sidptr->revision); |
71 | for (j = 0; j < 6; ++j) { | 142 | strptr = sidstr + strlen(sidstr); |
72 | if (ctsid->authority[j] != cwsid->authority[j]) | 143 | |
73 | break; | 144 | for (i = 0; i < 6; ++i) { |
145 | if (sidptr->authority[i]) { | ||
146 | sprintf(strptr, "-%d", sidptr->authority[i]); | ||
147 | strptr = sidstr + strlen(sidstr); | ||
74 | } | 148 | } |
75 | if (j < 6) | 149 | } |
76 | continue; /* all of the auth values did not match */ | 150 | |
77 | 151 | for (i = 0; i < sidptr->num_subauth; ++i) { | |
78 | /* compare all of the subauth values if any */ | 152 | saval = le32_to_cpu(sidptr->sub_auth[i]); |
79 | num_sat = ctsid->num_subauth; | 153 | sprintf(strptr, "-%ld", saval); |
80 | num_saw = cwsid->num_subauth; | 154 | strptr = sidstr + strlen(sidstr); |
81 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | 155 | } |
82 | if (num_subauth) { | 156 | } |
83 | for (j = 0; j < num_subauth; ++j) { | 157 | |
84 | if (ctsid->sub_auth[j] != cwsid->sub_auth[j]) | 158 | static void |
85 | break; | 159 | id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, |
86 | } | 160 | struct cifs_sid_id **psidid, char *typestr) |
87 | if (j < num_subauth) | 161 | { |
88 | continue; /* all sub_auth values do not match */ | 162 | int rc; |
163 | char *strptr; | ||
164 | struct rb_node *node = root->rb_node; | ||
165 | struct rb_node *parent = NULL; | ||
166 | struct rb_node **linkto = &(root->rb_node); | ||
167 | struct cifs_sid_id *lsidid; | ||
168 | |||
169 | while (node) { | ||
170 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
171 | parent = node; | ||
172 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
173 | if (rc > 0) { | ||
174 | linkto = &(node->rb_left); | ||
175 | node = node->rb_left; | ||
176 | } else if (rc < 0) { | ||
177 | linkto = &(node->rb_right); | ||
178 | node = node->rb_right; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); | ||
183 | (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); | ||
184 | (*psidid)->refcount = 0; | ||
185 | |||
186 | sprintf((*psidid)->sidstr, "%s", typestr); | ||
187 | strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); | ||
188 | sid_to_str(&(*psidid)->sid, strptr); | ||
189 | |||
190 | clear_bit(SID_ID_PENDING, &(*psidid)->state); | ||
191 | clear_bit(SID_ID_MAPPED, &(*psidid)->state); | ||
192 | |||
193 | rb_link_node(&(*psidid)->rbnode, parent, linkto); | ||
194 | rb_insert_color(&(*psidid)->rbnode, root); | ||
195 | } | ||
196 | |||
197 | static struct cifs_sid_id * | ||
198 | id_rb_search(struct rb_root *root, struct cifs_sid *sidptr) | ||
199 | { | ||
200 | int rc; | ||
201 | struct rb_node *node = root->rb_node; | ||
202 | struct cifs_sid_id *lsidid; | ||
203 | |||
204 | while (node) { | ||
205 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
206 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
207 | if (rc > 0) { | ||
208 | node = node->rb_left; | ||
209 | } else if (rc < 0) { | ||
210 | node = node->rb_right; | ||
211 | } else /* node found */ | ||
212 | return lsidid; | ||
213 | } | ||
214 | |||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | static int | ||
219 | sidid_pending_wait(void *unused) | ||
220 | { | ||
221 | schedule(); | ||
222 | return signal_pending(current) ? -ERESTARTSYS : 0; | ||
223 | } | ||
224 | |||
225 | static int | ||
226 | sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, | ||
227 | struct cifs_fattr *fattr, uint sidtype) | ||
228 | { | ||
229 | int rc; | ||
230 | unsigned long cid; | ||
231 | struct key *idkey; | ||
232 | const struct cred *saved_cred; | ||
233 | struct cifs_sid_id *psidid, *npsidid; | ||
234 | struct rb_root *cidtree; | ||
235 | spinlock_t *cidlock; | ||
236 | |||
237 | if (sidtype == SIDOWNER) { | ||
238 | cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */ | ||
239 | cidlock = &siduidlock; | ||
240 | cidtree = &uidtree; | ||
241 | } else if (sidtype == SIDGROUP) { | ||
242 | cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */ | ||
243 | cidlock = &sidgidlock; | ||
244 | cidtree = &gidtree; | ||
245 | } else | ||
246 | return -ENOENT; | ||
247 | |||
248 | spin_lock(cidlock); | ||
249 | psidid = id_rb_search(cidtree, psid); | ||
250 | |||
251 | if (!psidid) { /* node does not exist, allocate one & attempt adding */ | ||
252 | spin_unlock(cidlock); | ||
253 | npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); | ||
254 | if (!npsidid) | ||
255 | return -ENOMEM; | ||
256 | |||
257 | npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL); | ||
258 | if (!npsidid->sidstr) { | ||
259 | kfree(npsidid); | ||
260 | return -ENOMEM; | ||
261 | } | ||
262 | |||
263 | spin_lock(cidlock); | ||
264 | psidid = id_rb_search(cidtree, psid); | ||
265 | if (psidid) { /* node happened to get inserted meanwhile */ | ||
266 | ++psidid->refcount; | ||
267 | spin_unlock(cidlock); | ||
268 | kfree(npsidid->sidstr); | ||
269 | kfree(npsidid); | ||
270 | } else { | ||
271 | psidid = npsidid; | ||
272 | id_rb_insert(cidtree, psid, &psidid, | ||
273 | sidtype == SIDOWNER ? "os:" : "gs:"); | ||
274 | ++psidid->refcount; | ||
275 | spin_unlock(cidlock); | ||
89 | } | 276 | } |
277 | } else { | ||
278 | ++psidid->refcount; | ||
279 | spin_unlock(cidlock); | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * If we are here, it is safe to access psidid and its fields | ||
284 | * since a reference was taken earlier while holding the spinlock. | ||
285 | * A reference on the node is put without holding the spinlock | ||
286 | * and it is OK to do so in this case, shrinker will not erase | ||
287 | * this node until all references are put and we do not access | ||
288 | * any fields of the node after a reference is put . | ||
289 | */ | ||
290 | if (test_bit(SID_ID_MAPPED, &psidid->state)) { | ||
291 | cid = psidid->id; | ||
292 | psidid->time = jiffies; /* update ts for accessing */ | ||
293 | goto sid_to_id_out; | ||
294 | } | ||
90 | 295 | ||
91 | cFYI(1, "matching sid: %s\n", wksidarr[i].sidname); | 296 | if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) |
92 | return 0; /* sids compare/match */ | 297 | goto sid_to_id_out; |
298 | |||
299 | if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { | ||
300 | saved_cred = override_creds(root_cred); | ||
301 | idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); | ||
302 | if (IS_ERR(idkey)) | ||
303 | cFYI(1, "%s: Can't map SID to an id", __func__); | ||
304 | else { | ||
305 | cid = *(unsigned long *)idkey->payload.value; | ||
306 | psidid->id = cid; | ||
307 | set_bit(SID_ID_MAPPED, &psidid->state); | ||
308 | key_put(idkey); | ||
309 | kfree(psidid->sidstr); | ||
310 | } | ||
311 | revert_creds(saved_cred); | ||
312 | psidid->time = jiffies; /* update ts for accessing */ | ||
313 | clear_bit(SID_ID_PENDING, &psidid->state); | ||
314 | wake_up_bit(&psidid->state, SID_ID_PENDING); | ||
315 | } else { | ||
316 | rc = wait_on_bit(&psidid->state, SID_ID_PENDING, | ||
317 | sidid_pending_wait, TASK_INTERRUPTIBLE); | ||
318 | if (rc) { | ||
319 | cFYI(1, "%s: sidid_pending_wait interrupted %d", | ||
320 | __func__, rc); | ||
321 | --psidid->refcount; /* decremented without spinlock */ | ||
322 | return rc; | ||
323 | } | ||
324 | if (test_bit(SID_ID_MAPPED, &psidid->state)) | ||
325 | cid = psidid->id; | ||
93 | } | 326 | } |
94 | 327 | ||
95 | cFYI(1, "No matching sid"); | 328 | sid_to_id_out: |
96 | return -1; | 329 | --psidid->refcount; /* decremented without spinlock */ |
330 | if (sidtype == SIDOWNER) | ||
331 | fattr->cf_uid = cid; | ||
332 | else | ||
333 | fattr->cf_gid = cid; | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | int | ||
339 | init_cifs_idmap(void) | ||
340 | { | ||
341 | struct cred *cred; | ||
342 | struct key *keyring; | ||
343 | int ret; | ||
344 | |||
345 | cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name); | ||
346 | |||
347 | /* create an override credential set with a special thread keyring in | ||
348 | * which requests are cached | ||
349 | * | ||
350 | * this is used to prevent malicious redirections from being installed | ||
351 | * with add_key(). | ||
352 | */ | ||
353 | cred = prepare_kernel_cred(NULL); | ||
354 | if (!cred) | ||
355 | return -ENOMEM; | ||
356 | |||
357 | keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred, | ||
358 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
359 | KEY_USR_VIEW | KEY_USR_READ, | ||
360 | KEY_ALLOC_NOT_IN_QUOTA); | ||
361 | if (IS_ERR(keyring)) { | ||
362 | ret = PTR_ERR(keyring); | ||
363 | goto failed_put_cred; | ||
364 | } | ||
365 | |||
366 | ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); | ||
367 | if (ret < 0) | ||
368 | goto failed_put_key; | ||
369 | |||
370 | ret = register_key_type(&cifs_idmap_key_type); | ||
371 | if (ret < 0) | ||
372 | goto failed_put_key; | ||
373 | |||
374 | /* instruct request_key() to use this special keyring as a cache for | ||
375 | * the results it looks up */ | ||
376 | cred->thread_keyring = keyring; | ||
377 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | ||
378 | root_cred = cred; | ||
379 | |||
380 | spin_lock_init(&siduidlock); | ||
381 | uidtree = RB_ROOT; | ||
382 | spin_lock_init(&sidgidlock); | ||
383 | gidtree = RB_ROOT; | ||
384 | |||
385 | register_shrinker(&cifs_shrinker); | ||
386 | |||
387 | cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring)); | ||
388 | return 0; | ||
389 | |||
390 | failed_put_key: | ||
391 | key_put(keyring); | ||
392 | failed_put_cred: | ||
393 | put_cred(cred); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | void | ||
398 | exit_cifs_idmap(void) | ||
399 | { | ||
400 | key_revoke(root_cred->thread_keyring); | ||
401 | unregister_key_type(&cifs_idmap_key_type); | ||
402 | put_cred(root_cred); | ||
403 | unregister_shrinker(&cifs_shrinker); | ||
404 | cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name); | ||
405 | } | ||
406 | |||
407 | void | ||
408 | cifs_destroy_idmaptrees(void) | ||
409 | { | ||
410 | struct rb_root *root; | ||
411 | struct rb_node *node; | ||
412 | |||
413 | root = &uidtree; | ||
414 | spin_lock(&siduidlock); | ||
415 | while ((node = rb_first(root))) | ||
416 | rb_erase(node, root); | ||
417 | spin_unlock(&siduidlock); | ||
418 | |||
419 | root = &gidtree; | ||
420 | spin_lock(&sidgidlock); | ||
421 | while ((node = rb_first(root))) | ||
422 | rb_erase(node, root); | ||
423 | spin_unlock(&sidgidlock); | ||
97 | } | 424 | } |
98 | 425 | ||
99 | /* if the two SIDs (roughly equivalent to a UUID for a user or group) are | 426 | /* if the two SIDs (roughly equivalent to a UUID for a user or group) are |
@@ -104,16 +431,24 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
104 | int num_subauth, num_sat, num_saw; | 431 | int num_subauth, num_sat, num_saw; |
105 | 432 | ||
106 | if ((!ctsid) || (!cwsid)) | 433 | if ((!ctsid) || (!cwsid)) |
107 | return 0; | 434 | return 1; |
108 | 435 | ||
109 | /* compare the revision */ | 436 | /* compare the revision */ |
110 | if (ctsid->revision != cwsid->revision) | 437 | if (ctsid->revision != cwsid->revision) { |
111 | return 0; | 438 | if (ctsid->revision > cwsid->revision) |
439 | return 1; | ||
440 | else | ||
441 | return -1; | ||
442 | } | ||
112 | 443 | ||
113 | /* compare all of the six auth values */ | 444 | /* compare all of the six auth values */ |
114 | for (i = 0; i < 6; ++i) { | 445 | for (i = 0; i < 6; ++i) { |
115 | if (ctsid->authority[i] != cwsid->authority[i]) | 446 | if (ctsid->authority[i] != cwsid->authority[i]) { |
116 | return 0; | 447 | if (ctsid->authority[i] > cwsid->authority[i]) |
448 | return 1; | ||
449 | else | ||
450 | return -1; | ||
451 | } | ||
117 | } | 452 | } |
118 | 453 | ||
119 | /* compare all of the subauth values if any */ | 454 | /* compare all of the subauth values if any */ |
@@ -122,12 +457,16 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
122 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | 457 | num_subauth = num_sat < num_saw ? num_sat : num_saw; |
123 | if (num_subauth) { | 458 | if (num_subauth) { |
124 | for (i = 0; i < num_subauth; ++i) { | 459 | for (i = 0; i < num_subauth; ++i) { |
125 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) | 460 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) { |
126 | return 0; | 461 | if (ctsid->sub_auth[i] > cwsid->sub_auth[i]) |
462 | return 1; | ||
463 | else | ||
464 | return -1; | ||
465 | } | ||
127 | } | 466 | } |
128 | } | 467 | } |
129 | 468 | ||
130 | return 1; /* sids compare/match */ | 469 | return 0; /* sids compare/match */ |
131 | } | 470 | } |
132 | 471 | ||
133 | 472 | ||
@@ -382,22 +721,22 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
382 | #ifdef CONFIG_CIFS_DEBUG2 | 721 | #ifdef CONFIG_CIFS_DEBUG2 |
383 | dump_ace(ppace[i], end_of_acl); | 722 | dump_ace(ppace[i], end_of_acl); |
384 | #endif | 723 | #endif |
385 | if (compare_sids(&(ppace[i]->sid), pownersid)) | 724 | if (compare_sids(&(ppace[i]->sid), pownersid) == 0) |
386 | access_flags_to_mode(ppace[i]->access_req, | 725 | access_flags_to_mode(ppace[i]->access_req, |
387 | ppace[i]->type, | 726 | ppace[i]->type, |
388 | &fattr->cf_mode, | 727 | &fattr->cf_mode, |
389 | &user_mask); | 728 | &user_mask); |
390 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) | 729 | if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) |
391 | access_flags_to_mode(ppace[i]->access_req, | 730 | access_flags_to_mode(ppace[i]->access_req, |
392 | ppace[i]->type, | 731 | ppace[i]->type, |
393 | &fattr->cf_mode, | 732 | &fattr->cf_mode, |
394 | &group_mask); | 733 | &group_mask); |
395 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) | 734 | if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) |
396 | access_flags_to_mode(ppace[i]->access_req, | 735 | access_flags_to_mode(ppace[i]->access_req, |
397 | ppace[i]->type, | 736 | ppace[i]->type, |
398 | &fattr->cf_mode, | 737 | &fattr->cf_mode, |
399 | &other_mask); | 738 | &other_mask); |
400 | if (compare_sids(&(ppace[i]->sid), &sid_authusers)) | 739 | if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) |
401 | access_flags_to_mode(ppace[i]->access_req, | 740 | access_flags_to_mode(ppace[i]->access_req, |
402 | ppace[i]->type, | 741 | ppace[i]->type, |
403 | &fattr->cf_mode, | 742 | &fattr->cf_mode, |
@@ -475,10 +814,10 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
475 | 814 | ||
476 | 815 | ||
477 | /* Convert CIFS ACL to POSIX form */ | 816 | /* Convert CIFS ACL to POSIX form */ |
478 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | 817 | static int parse_sec_desc(struct cifs_sb_info *cifs_sb, |
479 | struct cifs_fattr *fattr) | 818 | struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) |
480 | { | 819 | { |
481 | int rc; | 820 | int rc = 0; |
482 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 821 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
483 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | 822 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ |
484 | char *end_of_acl = ((char *)pntsd) + acl_len; | 823 | char *end_of_acl = ((char *)pntsd) + acl_len; |
@@ -500,12 +839,26 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
500 | le32_to_cpu(pntsd->sacloffset), dacloffset); | 839 | le32_to_cpu(pntsd->sacloffset), dacloffset); |
501 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ | 840 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ |
502 | rc = parse_sid(owner_sid_ptr, end_of_acl); | 841 | rc = parse_sid(owner_sid_ptr, end_of_acl); |
503 | if (rc) | 842 | if (rc) { |
843 | cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc); | ||
844 | return rc; | ||
845 | } | ||
846 | rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER); | ||
847 | if (rc) { | ||
848 | cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc); | ||
504 | return rc; | 849 | return rc; |
850 | } | ||
505 | 851 | ||
506 | rc = parse_sid(group_sid_ptr, end_of_acl); | 852 | rc = parse_sid(group_sid_ptr, end_of_acl); |
507 | if (rc) | 853 | if (rc) { |
854 | cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc); | ||
508 | return rc; | 855 | return rc; |
856 | } | ||
857 | rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP); | ||
858 | if (rc) { | ||
859 | cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc); | ||
860 | return rc; | ||
861 | } | ||
509 | 862 | ||
510 | if (dacloffset) | 863 | if (dacloffset) |
511 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | 864 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, |
@@ -520,7 +873,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
520 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 873 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
521 | sizeof(struct cifs_sid)); */ | 874 | sizeof(struct cifs_sid)); */ |
522 | 875 | ||
523 | return 0; | 876 | return rc; |
524 | } | 877 | } |
525 | 878 | ||
526 | 879 | ||
@@ -688,7 +1041,7 @@ out: | |||
688 | } | 1041 | } |
689 | 1042 | ||
690 | /* Set an ACL on the server */ | 1043 | /* Set an ACL on the server */ |
691 | static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | 1044 | int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, |
692 | struct inode *inode, const char *path) | 1045 | struct inode *inode, const char *path) |
693 | { | 1046 | { |
694 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1047 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
@@ -727,7 +1080,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
727 | rc = PTR_ERR(pntsd); | 1080 | rc = PTR_ERR(pntsd); |
728 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | 1081 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); |
729 | } else { | 1082 | } else { |
730 | rc = parse_sec_desc(pntsd, acllen, fattr); | 1083 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); |
731 | kfree(pntsd); | 1084 | kfree(pntsd); |
732 | if (rc) | 1085 | if (rc) |
733 | cERROR(1, "parse sec desc failed rc = %d", rc); | 1086 | cERROR(1, "parse sec desc failed rc = %d", rc); |