diff options
Diffstat (limited to 'fs/cifs/cifsacl.c')
-rw-r--r-- | fs/cifs/cifsacl.c | 535 |
1 files changed, 94 insertions, 441 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 42b3fe981a0..f4508ee4e80 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -44,128 +44,6 @@ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | |||
44 | 44 | ||
45 | static const struct cred *root_cred; | 45 | static const struct cred *root_cred; |
46 | 46 | ||
47 | static void | ||
48 | shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem, | ||
49 | int *nr_del) | ||
50 | { | ||
51 | struct rb_node *node; | ||
52 | struct rb_node *tmp; | ||
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, struct shrink_control *sc) | ||
78 | { | ||
79 | int nr_to_scan = sc->nr_to_scan; | ||
80 | int nr_del = 0; | ||
81 | int nr_rem = 0; | ||
82 | struct rb_root *root; | ||
83 | |||
84 | root = &uidtree; | ||
85 | spin_lock(&siduidlock); | ||
86 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
87 | spin_unlock(&siduidlock); | ||
88 | |||
89 | root = &gidtree; | ||
90 | spin_lock(&sidgidlock); | ||
91 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
92 | spin_unlock(&sidgidlock); | ||
93 | |||
94 | root = &siduidtree; | ||
95 | spin_lock(&uidsidlock); | ||
96 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
97 | spin_unlock(&uidsidlock); | ||
98 | |||
99 | root = &sidgidtree; | ||
100 | spin_lock(&gidsidlock); | ||
101 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
102 | spin_unlock(&gidsidlock); | ||
103 | |||
104 | return nr_rem; | ||
105 | } | ||
106 | |||
107 | static void | ||
108 | sid_rb_insert(struct rb_root *root, unsigned long cid, | ||
109 | struct cifs_sid_id **psidid, char *typestr) | ||
110 | { | ||
111 | char *strptr; | ||
112 | struct rb_node *node = root->rb_node; | ||
113 | struct rb_node *parent = NULL; | ||
114 | struct rb_node **linkto = &(root->rb_node); | ||
115 | struct cifs_sid_id *lsidid; | ||
116 | |||
117 | while (node) { | ||
118 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
119 | parent = node; | ||
120 | if (cid > lsidid->id) { | ||
121 | linkto = &(node->rb_left); | ||
122 | node = node->rb_left; | ||
123 | } | ||
124 | if (cid < lsidid->id) { | ||
125 | linkto = &(node->rb_right); | ||
126 | node = node->rb_right; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | (*psidid)->id = cid; | ||
131 | (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); | ||
132 | (*psidid)->refcount = 0; | ||
133 | |||
134 | sprintf((*psidid)->sidstr, "%s", typestr); | ||
135 | strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); | ||
136 | sprintf(strptr, "%ld", cid); | ||
137 | |||
138 | clear_bit(SID_ID_PENDING, &(*psidid)->state); | ||
139 | clear_bit(SID_ID_MAPPED, &(*psidid)->state); | ||
140 | |||
141 | rb_link_node(&(*psidid)->rbnode, parent, linkto); | ||
142 | rb_insert_color(&(*psidid)->rbnode, root); | ||
143 | } | ||
144 | |||
145 | static struct cifs_sid_id * | ||
146 | sid_rb_search(struct rb_root *root, unsigned long cid) | ||
147 | { | ||
148 | struct rb_node *node = root->rb_node; | ||
149 | struct cifs_sid_id *lsidid; | ||
150 | |||
151 | while (node) { | ||
152 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
153 | if (cid > lsidid->id) | ||
154 | node = node->rb_left; | ||
155 | else if (cid < lsidid->id) | ||
156 | node = node->rb_right; | ||
157 | else /* node found */ | ||
158 | return lsidid; | ||
159 | } | ||
160 | |||
161 | return NULL; | ||
162 | } | ||
163 | |||
164 | static struct shrinker cifs_shrinker = { | ||
165 | .shrink = cifs_idmap_shrinker, | ||
166 | .seeks = DEFAULT_SEEKS, | ||
167 | }; | ||
168 | |||
169 | static int | 47 | static int |
170 | cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | 48 | cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
171 | { | 49 | { |
@@ -195,30 +73,39 @@ static struct key_type cifs_idmap_key_type = { | |||
195 | .match = user_match, | 73 | .match = user_match, |
196 | }; | 74 | }; |
197 | 75 | ||
198 | static void | 76 | static char * |
199 | sid_to_str(struct cifs_sid *sidptr, char *sidstr) | 77 | sid_to_key_str(struct cifs_sid *sidptr, unsigned int type) |
200 | { | 78 | { |
201 | int i; | 79 | int i, len; |
202 | unsigned int saval; | 80 | unsigned int saval; |
203 | char *strptr; | 81 | char *sidstr, *strptr; |
204 | 82 | ||
205 | strptr = sidstr; | 83 | /* 3 bytes for prefix */ |
84 | sidstr = kmalloc(3 + SID_STRING_BASE_SIZE + | ||
85 | (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth), | ||
86 | GFP_KERNEL); | ||
87 | if (!sidstr) | ||
88 | return sidstr; | ||
206 | 89 | ||
207 | sprintf(strptr, "S-%hhu", sidptr->revision); | 90 | strptr = sidstr; |
208 | strptr = sidstr + strlen(sidstr); | 91 | len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g', |
92 | sidptr->revision); | ||
93 | strptr += len; | ||
209 | 94 | ||
210 | for (i = 0; i < NUM_AUTHS; ++i) { | 95 | for (i = 0; i < NUM_AUTHS; ++i) { |
211 | if (sidptr->authority[i]) { | 96 | if (sidptr->authority[i]) { |
212 | sprintf(strptr, "-%hhu", sidptr->authority[i]); | 97 | len = sprintf(strptr, "-%hhu", sidptr->authority[i]); |
213 | strptr = sidstr + strlen(sidstr); | 98 | strptr += len; |
214 | } | 99 | } |
215 | } | 100 | } |
216 | 101 | ||
217 | for (i = 0; i < sidptr->num_subauth; ++i) { | 102 | for (i = 0; i < sidptr->num_subauth; ++i) { |
218 | saval = le32_to_cpu(sidptr->sub_auth[i]); | 103 | saval = le32_to_cpu(sidptr->sub_auth[i]); |
219 | sprintf(strptr, "-%u", saval); | 104 | len = sprintf(strptr, "-%u", saval); |
220 | strptr = sidstr + strlen(sidstr); | 105 | strptr += len; |
221 | } | 106 | } |
107 | |||
108 | return sidstr; | ||
222 | } | 109 | } |
223 | 110 | ||
224 | /* | 111 | /* |
@@ -284,184 +171,38 @@ cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) | |||
284 | dst->sub_auth[i] = src->sub_auth[i]; | 171 | dst->sub_auth[i] = src->sub_auth[i]; |
285 | } | 172 | } |
286 | 173 | ||
287 | static void | ||
288 | id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, | ||
289 | struct cifs_sid_id **psidid, char *typestr) | ||
290 | { | ||
291 | int rc; | ||
292 | char *strptr; | ||
293 | struct rb_node *node = root->rb_node; | ||
294 | struct rb_node *parent = NULL; | ||
295 | struct rb_node **linkto = &(root->rb_node); | ||
296 | struct cifs_sid_id *lsidid; | ||
297 | |||
298 | while (node) { | ||
299 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
300 | parent = node; | ||
301 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
302 | if (rc > 0) { | ||
303 | linkto = &(node->rb_left); | ||
304 | node = node->rb_left; | ||
305 | } else if (rc < 0) { | ||
306 | linkto = &(node->rb_right); | ||
307 | node = node->rb_right; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | cifs_copy_sid(&(*psidid)->sid, sidptr); | ||
312 | (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); | ||
313 | (*psidid)->refcount = 0; | ||
314 | |||
315 | sprintf((*psidid)->sidstr, "%s", typestr); | ||
316 | strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); | ||
317 | sid_to_str(&(*psidid)->sid, strptr); | ||
318 | |||
319 | clear_bit(SID_ID_PENDING, &(*psidid)->state); | ||
320 | clear_bit(SID_ID_MAPPED, &(*psidid)->state); | ||
321 | |||
322 | rb_link_node(&(*psidid)->rbnode, parent, linkto); | ||
323 | rb_insert_color(&(*psidid)->rbnode, root); | ||
324 | } | ||
325 | |||
326 | static struct cifs_sid_id * | ||
327 | id_rb_search(struct rb_root *root, struct cifs_sid *sidptr) | ||
328 | { | ||
329 | int rc; | ||
330 | struct rb_node *node = root->rb_node; | ||
331 | struct cifs_sid_id *lsidid; | ||
332 | |||
333 | while (node) { | ||
334 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
335 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
336 | if (rc > 0) { | ||
337 | node = node->rb_left; | ||
338 | } else if (rc < 0) { | ||
339 | node = node->rb_right; | ||
340 | } else /* node found */ | ||
341 | return lsidid; | ||
342 | } | ||
343 | |||
344 | return NULL; | ||
345 | } | ||
346 | |||
347 | static int | ||
348 | sidid_pending_wait(void *unused) | ||
349 | { | ||
350 | schedule(); | ||
351 | return signal_pending(current) ? -ERESTARTSYS : 0; | ||
352 | } | ||
353 | |||
354 | static int | 174 | static int |
355 | id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) | 175 | id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) |
356 | { | 176 | { |
357 | int rc = 0; | 177 | int rc; |
358 | struct key *sidkey; | 178 | struct key *sidkey; |
179 | char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */ | ||
359 | const struct cred *saved_cred; | 180 | const struct cred *saved_cred; |
360 | struct cifs_sid *lsid; | ||
361 | struct cifs_sid_id *psidid, *npsidid; | ||
362 | struct rb_root *cidtree; | ||
363 | spinlock_t *cidlock; | ||
364 | |||
365 | if (sidtype == SIDOWNER) { | ||
366 | cidlock = &siduidlock; | ||
367 | cidtree = &uidtree; | ||
368 | } else if (sidtype == SIDGROUP) { | ||
369 | cidlock = &sidgidlock; | ||
370 | cidtree = &gidtree; | ||
371 | } else | ||
372 | return -EINVAL; | ||
373 | |||
374 | spin_lock(cidlock); | ||
375 | psidid = sid_rb_search(cidtree, cid); | ||
376 | |||
377 | if (!psidid) { /* node does not exist, allocate one & attempt adding */ | ||
378 | spin_unlock(cidlock); | ||
379 | npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); | ||
380 | if (!npsidid) | ||
381 | return -ENOMEM; | ||
382 | |||
383 | npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL); | ||
384 | if (!npsidid->sidstr) { | ||
385 | kfree(npsidid); | ||
386 | return -ENOMEM; | ||
387 | } | ||
388 | |||
389 | spin_lock(cidlock); | ||
390 | psidid = sid_rb_search(cidtree, cid); | ||
391 | if (psidid) { /* node happened to get inserted meanwhile */ | ||
392 | ++psidid->refcount; | ||
393 | spin_unlock(cidlock); | ||
394 | kfree(npsidid->sidstr); | ||
395 | kfree(npsidid); | ||
396 | } else { | ||
397 | psidid = npsidid; | ||
398 | sid_rb_insert(cidtree, cid, &psidid, | ||
399 | sidtype == SIDOWNER ? "oi:" : "gi:"); | ||
400 | ++psidid->refcount; | ||
401 | spin_unlock(cidlock); | ||
402 | } | ||
403 | } else { | ||
404 | ++psidid->refcount; | ||
405 | spin_unlock(cidlock); | ||
406 | } | ||
407 | 181 | ||
408 | /* | 182 | rc = snprintf(desc, sizeof(desc), "%ci:%u", |
409 | * If we are here, it is safe to access psidid and its fields | 183 | sidtype == SIDOWNER ? 'o' : 'g', cid); |
410 | * since a reference was taken earlier while holding the spinlock. | 184 | if (rc >= sizeof(desc)) |
411 | * A reference on the node is put without holding the spinlock | 185 | return -EINVAL; |
412 | * and it is OK to do so in this case, shrinker will not erase | ||
413 | * this node until all references are put and we do not access | ||
414 | * any fields of the node after a reference is put . | ||
415 | */ | ||
416 | if (test_bit(SID_ID_MAPPED, &psidid->state)) { | ||
417 | cifs_copy_sid(ssid, &psidid->sid); | ||
418 | psidid->time = jiffies; /* update ts for accessing */ | ||
419 | goto id_sid_out; | ||
420 | } | ||
421 | 186 | ||
422 | if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) { | 187 | rc = 0; |
188 | saved_cred = override_creds(root_cred); | ||
189 | sidkey = request_key(&cifs_idmap_key_type, desc, ""); | ||
190 | if (IS_ERR(sidkey)) { | ||
423 | rc = -EINVAL; | 191 | rc = -EINVAL; |
424 | goto id_sid_out; | 192 | cFYI(1, "%s: Can't map %cid %u to a SID", __func__, |
425 | } | 193 | sidtype == SIDOWNER ? 'u' : 'g', cid); |
426 | 194 | goto out_revert_creds; | |
427 | if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { | 195 | } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) { |
428 | saved_cred = override_creds(root_cred); | 196 | rc = -EIO; |
429 | sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); | 197 | cFYI(1, "%s: Downcall contained malformed key " |
430 | if (IS_ERR(sidkey)) { | 198 | "(datalen=%hu)", __func__, sidkey->datalen); |
431 | rc = -EINVAL; | 199 | goto out_key_put; |
432 | cFYI(1, "%s: Can't map and id to a SID", __func__); | 200 | } |
433 | } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) { | 201 | cifs_copy_sid(ssid, (struct cifs_sid *)sidkey->payload.data); |
434 | rc = -EIO; | 202 | out_key_put: |
435 | cFYI(1, "%s: Downcall contained malformed key " | 203 | key_put(sidkey); |
436 | "(datalen=%hu)", __func__, sidkey->datalen); | 204 | out_revert_creds: |
437 | } else { | 205 | revert_creds(saved_cred); |
438 | lsid = (struct cifs_sid *)sidkey->payload.data; | ||
439 | cifs_copy_sid(&psidid->sid, lsid); | ||
440 | cifs_copy_sid(ssid, &psidid->sid); | ||
441 | set_bit(SID_ID_MAPPED, &psidid->state); | ||
442 | key_put(sidkey); | ||
443 | kfree(psidid->sidstr); | ||
444 | } | ||
445 | psidid->time = jiffies; /* update ts for accessing */ | ||
446 | revert_creds(saved_cred); | ||
447 | clear_bit(SID_ID_PENDING, &psidid->state); | ||
448 | wake_up_bit(&psidid->state, SID_ID_PENDING); | ||
449 | } else { | ||
450 | rc = wait_on_bit(&psidid->state, SID_ID_PENDING, | ||
451 | sidid_pending_wait, TASK_INTERRUPTIBLE); | ||
452 | if (rc) { | ||
453 | cFYI(1, "%s: sidid_pending_wait interrupted %d", | ||
454 | __func__, rc); | ||
455 | --psidid->refcount; | ||
456 | return rc; | ||
457 | } | ||
458 | if (test_bit(SID_ID_MAPPED, &psidid->state)) | ||
459 | cifs_copy_sid(ssid, &psidid->sid); | ||
460 | else | ||
461 | rc = -EINVAL; | ||
462 | } | ||
463 | id_sid_out: | ||
464 | --psidid->refcount; | ||
465 | return rc; | 206 | return rc; |
466 | } | 207 | } |
467 | 208 | ||
@@ -470,111 +211,66 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, | |||
470 | struct cifs_fattr *fattr, uint sidtype) | 211 | struct cifs_fattr *fattr, uint sidtype) |
471 | { | 212 | { |
472 | int rc; | 213 | int rc; |
473 | unsigned long cid; | 214 | struct key *sidkey; |
474 | struct key *idkey; | 215 | char *sidstr; |
475 | const struct cred *saved_cred; | 216 | const struct cred *saved_cred; |
476 | struct cifs_sid_id *psidid, *npsidid; | 217 | uid_t fuid = cifs_sb->mnt_uid; |
477 | struct rb_root *cidtree; | 218 | gid_t fgid = cifs_sb->mnt_gid; |
478 | spinlock_t *cidlock; | ||
479 | |||
480 | if (sidtype == SIDOWNER) { | ||
481 | cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */ | ||
482 | cidlock = &siduidlock; | ||
483 | cidtree = &uidtree; | ||
484 | } else if (sidtype == SIDGROUP) { | ||
485 | cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */ | ||
486 | cidlock = &sidgidlock; | ||
487 | cidtree = &gidtree; | ||
488 | } else | ||
489 | return -ENOENT; | ||
490 | |||
491 | spin_lock(cidlock); | ||
492 | psidid = id_rb_search(cidtree, psid); | ||
493 | |||
494 | if (!psidid) { /* node does not exist, allocate one & attempt adding */ | ||
495 | spin_unlock(cidlock); | ||
496 | npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); | ||
497 | if (!npsidid) | ||
498 | return -ENOMEM; | ||
499 | |||
500 | npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL); | ||
501 | if (!npsidid->sidstr) { | ||
502 | kfree(npsidid); | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | |||
506 | spin_lock(cidlock); | ||
507 | psidid = id_rb_search(cidtree, psid); | ||
508 | if (psidid) { /* node happened to get inserted meanwhile */ | ||
509 | ++psidid->refcount; | ||
510 | spin_unlock(cidlock); | ||
511 | kfree(npsidid->sidstr); | ||
512 | kfree(npsidid); | ||
513 | } else { | ||
514 | psidid = npsidid; | ||
515 | id_rb_insert(cidtree, psid, &psidid, | ||
516 | sidtype == SIDOWNER ? "os:" : "gs:"); | ||
517 | ++psidid->refcount; | ||
518 | spin_unlock(cidlock); | ||
519 | } | ||
520 | } else { | ||
521 | ++psidid->refcount; | ||
522 | spin_unlock(cidlock); | ||
523 | } | ||
524 | 219 | ||
525 | /* | 220 | /* |
526 | * If we are here, it is safe to access psidid and its fields | 221 | * If we have too many subauthorities, then something is really wrong. |
527 | * since a reference was taken earlier while holding the spinlock. | 222 | * Just return an error. |
528 | * A reference on the node is put without holding the spinlock | ||
529 | * and it is OK to do so in this case, shrinker will not erase | ||
530 | * this node until all references are put and we do not access | ||
531 | * any fields of the node after a reference is put . | ||
532 | */ | 223 | */ |
533 | if (test_bit(SID_ID_MAPPED, &psidid->state)) { | 224 | if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) { |
534 | cid = psidid->id; | 225 | cFYI(1, "%s: %u subauthorities is too many!", __func__, |
535 | psidid->time = jiffies; /* update ts for accessing */ | 226 | psid->num_subauth); |
536 | goto sid_to_id_out; | 227 | return -EIO; |
537 | } | 228 | } |
538 | 229 | ||
539 | if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) | 230 | sidstr = sid_to_key_str(psid, sidtype); |
540 | goto sid_to_id_out; | 231 | if (!sidstr) |
541 | 232 | return -ENOMEM; | |
542 | if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { | 233 | |
543 | saved_cred = override_creds(root_cred); | 234 | saved_cred = override_creds(root_cred); |
544 | idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); | 235 | sidkey = request_key(&cifs_idmap_key_type, sidstr, ""); |
545 | if (IS_ERR(idkey)) | 236 | if (IS_ERR(sidkey)) { |
546 | cFYI(1, "%s: Can't map SID to an id", __func__); | 237 | rc = -EINVAL; |
547 | else { | 238 | cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr, |
548 | cid = *(unsigned long *)idkey->payload.value; | 239 | sidtype == SIDOWNER ? 'u' : 'g'); |
549 | psidid->id = cid; | 240 | goto out_revert_creds; |
550 | set_bit(SID_ID_MAPPED, &psidid->state); | 241 | } |
551 | key_put(idkey); | 242 | |
552 | kfree(psidid->sidstr); | 243 | /* |
553 | } | 244 | * FIXME: Here we assume that uid_t and gid_t are same size. It's |
554 | revert_creds(saved_cred); | 245 | * probably a safe assumption but might be better to check based on |
555 | psidid->time = jiffies; /* update ts for accessing */ | 246 | * sidtype. |
556 | clear_bit(SID_ID_PENDING, &psidid->state); | 247 | */ |
557 | wake_up_bit(&psidid->state, SID_ID_PENDING); | 248 | if (sidkey->datalen < sizeof(uid_t)) { |
558 | } else { | 249 | rc = -EIO; |
559 | rc = wait_on_bit(&psidid->state, SID_ID_PENDING, | 250 | cFYI(1, "%s: Downcall contained malformed key " |
560 | sidid_pending_wait, TASK_INTERRUPTIBLE); | 251 | "(datalen=%hu)", __func__, sidkey->datalen); |
561 | if (rc) { | 252 | goto out_key_put; |
562 | cFYI(1, "%s: sidid_pending_wait interrupted %d", | ||
563 | __func__, rc); | ||
564 | --psidid->refcount; /* decremented without spinlock */ | ||
565 | return rc; | ||
566 | } | ||
567 | if (test_bit(SID_ID_MAPPED, &psidid->state)) | ||
568 | cid = psidid->id; | ||
569 | } | 253 | } |
570 | 254 | ||
571 | sid_to_id_out: | ||
572 | --psidid->refcount; /* decremented without spinlock */ | ||
573 | if (sidtype == SIDOWNER) | 255 | if (sidtype == SIDOWNER) |
574 | fattr->cf_uid = cid; | 256 | fuid = *(uid_t *)sidkey->payload.value; |
575 | else | 257 | else |
576 | fattr->cf_gid = cid; | 258 | fgid = *(gid_t *)sidkey->payload.value; |
577 | 259 | ||
260 | out_key_put: | ||
261 | key_put(sidkey); | ||
262 | out_revert_creds: | ||
263 | revert_creds(saved_cred); | ||
264 | kfree(sidstr); | ||
265 | |||
266 | /* | ||
267 | * Note that we return 0 here unconditionally. If the mapping | ||
268 | * fails then we just fall back to using the mnt_uid/mnt_gid. | ||
269 | */ | ||
270 | if (sidtype == SIDOWNER) | ||
271 | fattr->cf_uid = fuid; | ||
272 | else | ||
273 | fattr->cf_gid = fgid; | ||
578 | return 0; | 274 | return 0; |
579 | } | 275 | } |
580 | 276 | ||
@@ -621,17 +317,6 @@ init_cifs_idmap(void) | |||
621 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | 317 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |
622 | root_cred = cred; | 318 | root_cred = cred; |
623 | 319 | ||
624 | spin_lock_init(&siduidlock); | ||
625 | uidtree = RB_ROOT; | ||
626 | spin_lock_init(&sidgidlock); | ||
627 | gidtree = RB_ROOT; | ||
628 | |||
629 | spin_lock_init(&uidsidlock); | ||
630 | siduidtree = RB_ROOT; | ||
631 | spin_lock_init(&gidsidlock); | ||
632 | sidgidtree = RB_ROOT; | ||
633 | register_shrinker(&cifs_shrinker); | ||
634 | |||
635 | cFYI(1, "cifs idmap keyring: %d", key_serial(keyring)); | 320 | cFYI(1, "cifs idmap keyring: %d", key_serial(keyring)); |
636 | return 0; | 321 | return 0; |
637 | 322 | ||
@@ -648,41 +333,9 @@ exit_cifs_idmap(void) | |||
648 | key_revoke(root_cred->thread_keyring); | 333 | key_revoke(root_cred->thread_keyring); |
649 | unregister_key_type(&cifs_idmap_key_type); | 334 | unregister_key_type(&cifs_idmap_key_type); |
650 | put_cred(root_cred); | 335 | put_cred(root_cred); |
651 | unregister_shrinker(&cifs_shrinker); | ||
652 | cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name); | 336 | cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name); |
653 | } | 337 | } |
654 | 338 | ||
655 | void | ||
656 | cifs_destroy_idmaptrees(void) | ||
657 | { | ||
658 | struct rb_root *root; | ||
659 | struct rb_node *node; | ||
660 | |||
661 | root = &uidtree; | ||
662 | spin_lock(&siduidlock); | ||
663 | while ((node = rb_first(root))) | ||
664 | rb_erase(node, root); | ||
665 | spin_unlock(&siduidlock); | ||
666 | |||
667 | root = &gidtree; | ||
668 | spin_lock(&sidgidlock); | ||
669 | while ((node = rb_first(root))) | ||
670 | rb_erase(node, root); | ||
671 | spin_unlock(&sidgidlock); | ||
672 | |||
673 | root = &siduidtree; | ||
674 | spin_lock(&uidsidlock); | ||
675 | while ((node = rb_first(root))) | ||
676 | rb_erase(node, root); | ||
677 | spin_unlock(&uidsidlock); | ||
678 | |||
679 | root = &sidgidtree; | ||
680 | spin_lock(&gidsidlock); | ||
681 | while ((node = rb_first(root))) | ||
682 | rb_erase(node, root); | ||
683 | spin_unlock(&gidsidlock); | ||
684 | } | ||
685 | |||
686 | /* copy ntsd, owner sid, and group sid from a security descriptor to another */ | 339 | /* copy ntsd, owner sid, and group sid from a security descriptor to another */ |
687 | static void copy_sec_desc(const struct cifs_ntsd *pntsd, | 340 | static void copy_sec_desc(const struct cifs_ntsd *pntsd, |
688 | struct cifs_ntsd *pnntsd, __u32 sidsoffset) | 341 | struct cifs_ntsd *pnntsd, __u32 sidsoffset) |