]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/cifs/cifsacl.c
Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[mirror_ubuntu-bionic-kernel.git] / fs / cifs / cifsacl.c
1 /*
2 * fs/cifs/cifsacl.c
3 *
4 * Copyright (C) International Business Machines Corp., 2007,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for mapping CIFS/NTFS ACLs
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include <linux/fs.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>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsacl.h"
33 #include "cifsproto.h"
34 #include "cifs_debug.h"
35
36 /* security id for everyone/world system group */
37 static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
39 /* security id for Authenticated Users system group */
40 static const struct cifs_sid sid_authusers = {
41 1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
42 /* group users */
43 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
44
45 const struct cred *root_cred;
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
170 cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen)
171 {
172 char *payload;
173
174 payload = kmalloc(datalen, GFP_KERNEL);
175 if (!payload)
176 return -ENOMEM;
177
178 memcpy(payload, data, datalen);
179 key->payload.data = payload;
180 key->datalen = datalen;
181 return 0;
182 }
183
184 static inline void
185 cifs_idmap_key_destroy(struct key *key)
186 {
187 kfree(key->payload.data);
188 }
189
190 struct key_type cifs_idmap_key_type = {
191 .name = "cifs.idmap",
192 .instantiate = cifs_idmap_key_instantiate,
193 .destroy = cifs_idmap_key_destroy,
194 .describe = user_describe,
195 .match = user_match,
196 };
197
198 static void
199 sid_to_str(struct cifs_sid *sidptr, char *sidstr)
200 {
201 int i;
202 unsigned long saval;
203 char *strptr;
204
205 strptr = sidstr;
206
207 sprintf(strptr, "%s", "S");
208 strptr = sidstr + strlen(sidstr);
209
210 sprintf(strptr, "-%d", sidptr->revision);
211 strptr = sidstr + strlen(sidstr);
212
213 for (i = 0; i < 6; ++i) {
214 if (sidptr->authority[i]) {
215 sprintf(strptr, "-%d", sidptr->authority[i]);
216 strptr = sidstr + strlen(sidstr);
217 }
218 }
219
220 for (i = 0; i < sidptr->num_subauth; ++i) {
221 saval = le32_to_cpu(sidptr->sub_auth[i]);
222 sprintf(strptr, "-%ld", saval);
223 strptr = sidstr + strlen(sidstr);
224 }
225 }
226
227 static void
228 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
229 struct cifs_sid_id **psidid, char *typestr)
230 {
231 int rc;
232 char *strptr;
233 struct rb_node *node = root->rb_node;
234 struct rb_node *parent = NULL;
235 struct rb_node **linkto = &(root->rb_node);
236 struct cifs_sid_id *lsidid;
237
238 while (node) {
239 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
240 parent = node;
241 rc = compare_sids(sidptr, &((lsidid)->sid));
242 if (rc > 0) {
243 linkto = &(node->rb_left);
244 node = node->rb_left;
245 } else if (rc < 0) {
246 linkto = &(node->rb_right);
247 node = node->rb_right;
248 }
249 }
250
251 memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
252 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
253 (*psidid)->refcount = 0;
254
255 sprintf((*psidid)->sidstr, "%s", typestr);
256 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
257 sid_to_str(&(*psidid)->sid, strptr);
258
259 clear_bit(SID_ID_PENDING, &(*psidid)->state);
260 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
261
262 rb_link_node(&(*psidid)->rbnode, parent, linkto);
263 rb_insert_color(&(*psidid)->rbnode, root);
264 }
265
266 static struct cifs_sid_id *
267 id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
268 {
269 int rc;
270 struct rb_node *node = root->rb_node;
271 struct cifs_sid_id *lsidid;
272
273 while (node) {
274 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
275 rc = compare_sids(sidptr, &((lsidid)->sid));
276 if (rc > 0) {
277 node = node->rb_left;
278 } else if (rc < 0) {
279 node = node->rb_right;
280 } else /* node found */
281 return lsidid;
282 }
283
284 return NULL;
285 }
286
287 static int
288 sidid_pending_wait(void *unused)
289 {
290 schedule();
291 return signal_pending(current) ? -ERESTARTSYS : 0;
292 }
293
294 static int
295 id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
296 {
297 int rc = 0;
298 struct key *sidkey;
299 const struct cred *saved_cred;
300 struct cifs_sid *lsid;
301 struct cifs_sid_id *psidid, *npsidid;
302 struct rb_root *cidtree;
303 spinlock_t *cidlock;
304
305 if (sidtype == SIDOWNER) {
306 cidlock = &siduidlock;
307 cidtree = &uidtree;
308 } else if (sidtype == SIDGROUP) {
309 cidlock = &sidgidlock;
310 cidtree = &gidtree;
311 } else
312 return -EINVAL;
313
314 spin_lock(cidlock);
315 psidid = sid_rb_search(cidtree, cid);
316
317 if (!psidid) { /* node does not exist, allocate one & attempt adding */
318 spin_unlock(cidlock);
319 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
320 if (!npsidid)
321 return -ENOMEM;
322
323 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
324 if (!npsidid->sidstr) {
325 kfree(npsidid);
326 return -ENOMEM;
327 }
328
329 spin_lock(cidlock);
330 psidid = sid_rb_search(cidtree, cid);
331 if (psidid) { /* node happened to get inserted meanwhile */
332 ++psidid->refcount;
333 spin_unlock(cidlock);
334 kfree(npsidid->sidstr);
335 kfree(npsidid);
336 } else {
337 psidid = npsidid;
338 sid_rb_insert(cidtree, cid, &psidid,
339 sidtype == SIDOWNER ? "oi:" : "gi:");
340 ++psidid->refcount;
341 spin_unlock(cidlock);
342 }
343 } else {
344 ++psidid->refcount;
345 spin_unlock(cidlock);
346 }
347
348 /*
349 * If we are here, it is safe to access psidid and its fields
350 * since a reference was taken earlier while holding the spinlock.
351 * A reference on the node is put without holding the spinlock
352 * and it is OK to do so in this case, shrinker will not erase
353 * this node until all references are put and we do not access
354 * any fields of the node after a reference is put .
355 */
356 if (test_bit(SID_ID_MAPPED, &psidid->state)) {
357 memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
358 psidid->time = jiffies; /* update ts for accessing */
359 goto id_sid_out;
360 }
361
362 if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) {
363 rc = -EINVAL;
364 goto id_sid_out;
365 }
366
367 if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
368 saved_cred = override_creds(root_cred);
369 sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
370 if (IS_ERR(sidkey)) {
371 rc = -EINVAL;
372 cFYI(1, "%s: Can't map and id to a SID", __func__);
373 } else {
374 lsid = (struct cifs_sid *)sidkey->payload.data;
375 memcpy(&psidid->sid, lsid,
376 sidkey->datalen < sizeof(struct cifs_sid) ?
377 sidkey->datalen : sizeof(struct cifs_sid));
378 memcpy(ssid, &psidid->sid,
379 sidkey->datalen < sizeof(struct cifs_sid) ?
380 sidkey->datalen : sizeof(struct cifs_sid));
381 set_bit(SID_ID_MAPPED, &psidid->state);
382 key_put(sidkey);
383 kfree(psidid->sidstr);
384 }
385 psidid->time = jiffies; /* update ts for accessing */
386 revert_creds(saved_cred);
387 clear_bit(SID_ID_PENDING, &psidid->state);
388 wake_up_bit(&psidid->state, SID_ID_PENDING);
389 } else {
390 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
391 sidid_pending_wait, TASK_INTERRUPTIBLE);
392 if (rc) {
393 cFYI(1, "%s: sidid_pending_wait interrupted %d",
394 __func__, rc);
395 --psidid->refcount;
396 return rc;
397 }
398 if (test_bit(SID_ID_MAPPED, &psidid->state))
399 memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
400 else
401 rc = -EINVAL;
402 }
403 id_sid_out:
404 --psidid->refcount;
405 return rc;
406 }
407
408 static int
409 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
410 struct cifs_fattr *fattr, uint sidtype)
411 {
412 int rc;
413 unsigned long cid;
414 struct key *idkey;
415 const struct cred *saved_cred;
416 struct cifs_sid_id *psidid, *npsidid;
417 struct rb_root *cidtree;
418 spinlock_t *cidlock;
419
420 if (sidtype == SIDOWNER) {
421 cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
422 cidlock = &siduidlock;
423 cidtree = &uidtree;
424 } else if (sidtype == SIDGROUP) {
425 cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
426 cidlock = &sidgidlock;
427 cidtree = &gidtree;
428 } else
429 return -ENOENT;
430
431 spin_lock(cidlock);
432 psidid = id_rb_search(cidtree, psid);
433
434 if (!psidid) { /* node does not exist, allocate one & attempt adding */
435 spin_unlock(cidlock);
436 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
437 if (!npsidid)
438 return -ENOMEM;
439
440 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
441 if (!npsidid->sidstr) {
442 kfree(npsidid);
443 return -ENOMEM;
444 }
445
446 spin_lock(cidlock);
447 psidid = id_rb_search(cidtree, psid);
448 if (psidid) { /* node happened to get inserted meanwhile */
449 ++psidid->refcount;
450 spin_unlock(cidlock);
451 kfree(npsidid->sidstr);
452 kfree(npsidid);
453 } else {
454 psidid = npsidid;
455 id_rb_insert(cidtree, psid, &psidid,
456 sidtype == SIDOWNER ? "os:" : "gs:");
457 ++psidid->refcount;
458 spin_unlock(cidlock);
459 }
460 } else {
461 ++psidid->refcount;
462 spin_unlock(cidlock);
463 }
464
465 /*
466 * If we are here, it is safe to access psidid and its fields
467 * since a reference was taken earlier while holding the spinlock.
468 * A reference on the node is put without holding the spinlock
469 * and it is OK to do so in this case, shrinker will not erase
470 * this node until all references are put and we do not access
471 * any fields of the node after a reference is put .
472 */
473 if (test_bit(SID_ID_MAPPED, &psidid->state)) {
474 cid = psidid->id;
475 psidid->time = jiffies; /* update ts for accessing */
476 goto sid_to_id_out;
477 }
478
479 if (time_after(psidid->time + SID_MAP_RETRY, jiffies))
480 goto sid_to_id_out;
481
482 if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
483 saved_cred = override_creds(root_cred);
484 idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
485 if (IS_ERR(idkey))
486 cFYI(1, "%s: Can't map SID to an id", __func__);
487 else {
488 cid = *(unsigned long *)idkey->payload.value;
489 psidid->id = cid;
490 set_bit(SID_ID_MAPPED, &psidid->state);
491 key_put(idkey);
492 kfree(psidid->sidstr);
493 }
494 revert_creds(saved_cred);
495 psidid->time = jiffies; /* update ts for accessing */
496 clear_bit(SID_ID_PENDING, &psidid->state);
497 wake_up_bit(&psidid->state, SID_ID_PENDING);
498 } else {
499 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
500 sidid_pending_wait, TASK_INTERRUPTIBLE);
501 if (rc) {
502 cFYI(1, "%s: sidid_pending_wait interrupted %d",
503 __func__, rc);
504 --psidid->refcount; /* decremented without spinlock */
505 return rc;
506 }
507 if (test_bit(SID_ID_MAPPED, &psidid->state))
508 cid = psidid->id;
509 }
510
511 sid_to_id_out:
512 --psidid->refcount; /* decremented without spinlock */
513 if (sidtype == SIDOWNER)
514 fattr->cf_uid = cid;
515 else
516 fattr->cf_gid = cid;
517
518 return 0;
519 }
520
521 int
522 init_cifs_idmap(void)
523 {
524 struct cred *cred;
525 struct key *keyring;
526 int ret;
527
528 cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name);
529
530 /* create an override credential set with a special thread keyring in
531 * which requests are cached
532 *
533 * this is used to prevent malicious redirections from being installed
534 * with add_key().
535 */
536 cred = prepare_kernel_cred(NULL);
537 if (!cred)
538 return -ENOMEM;
539
540 keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
541 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
542 KEY_USR_VIEW | KEY_USR_READ,
543 KEY_ALLOC_NOT_IN_QUOTA);
544 if (IS_ERR(keyring)) {
545 ret = PTR_ERR(keyring);
546 goto failed_put_cred;
547 }
548
549 ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
550 if (ret < 0)
551 goto failed_put_key;
552
553 ret = register_key_type(&cifs_idmap_key_type);
554 if (ret < 0)
555 goto failed_put_key;
556
557 /* instruct request_key() to use this special keyring as a cache for
558 * the results it looks up */
559 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
560 cred->thread_keyring = keyring;
561 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
562 root_cred = cred;
563
564 spin_lock_init(&siduidlock);
565 uidtree = RB_ROOT;
566 spin_lock_init(&sidgidlock);
567 gidtree = RB_ROOT;
568
569 spin_lock_init(&uidsidlock);
570 siduidtree = RB_ROOT;
571 spin_lock_init(&gidsidlock);
572 sidgidtree = RB_ROOT;
573 register_shrinker(&cifs_shrinker);
574
575 cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring));
576 return 0;
577
578 failed_put_key:
579 key_put(keyring);
580 failed_put_cred:
581 put_cred(cred);
582 return ret;
583 }
584
585 void
586 exit_cifs_idmap(void)
587 {
588 key_revoke(root_cred->thread_keyring);
589 unregister_key_type(&cifs_idmap_key_type);
590 put_cred(root_cred);
591 unregister_shrinker(&cifs_shrinker);
592 cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name);
593 }
594
595 void
596 cifs_destroy_idmaptrees(void)
597 {
598 struct rb_root *root;
599 struct rb_node *node;
600
601 root = &uidtree;
602 spin_lock(&siduidlock);
603 while ((node = rb_first(root)))
604 rb_erase(node, root);
605 spin_unlock(&siduidlock);
606
607 root = &gidtree;
608 spin_lock(&sidgidlock);
609 while ((node = rb_first(root)))
610 rb_erase(node, root);
611 spin_unlock(&sidgidlock);
612
613 root = &siduidtree;
614 spin_lock(&uidsidlock);
615 while ((node = rb_first(root)))
616 rb_erase(node, root);
617 spin_unlock(&uidsidlock);
618
619 root = &sidgidtree;
620 spin_lock(&gidsidlock);
621 while ((node = rb_first(root)))
622 rb_erase(node, root);
623 spin_unlock(&gidsidlock);
624 }
625
626 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
627 the same returns 1, if they do not match returns 0 */
628 int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
629 {
630 int i;
631 int num_subauth, num_sat, num_saw;
632
633 if ((!ctsid) || (!cwsid))
634 return 1;
635
636 /* compare the revision */
637 if (ctsid->revision != cwsid->revision) {
638 if (ctsid->revision > cwsid->revision)
639 return 1;
640 else
641 return -1;
642 }
643
644 /* compare all of the six auth values */
645 for (i = 0; i < 6; ++i) {
646 if (ctsid->authority[i] != cwsid->authority[i]) {
647 if (ctsid->authority[i] > cwsid->authority[i])
648 return 1;
649 else
650 return -1;
651 }
652 }
653
654 /* compare all of the subauth values if any */
655 num_sat = ctsid->num_subauth;
656 num_saw = cwsid->num_subauth;
657 num_subauth = num_sat < num_saw ? num_sat : num_saw;
658 if (num_subauth) {
659 for (i = 0; i < num_subauth; ++i) {
660 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
661 if (le32_to_cpu(ctsid->sub_auth[i]) >
662 le32_to_cpu(cwsid->sub_auth[i]))
663 return 1;
664 else
665 return -1;
666 }
667 }
668 }
669
670 return 0; /* sids compare/match */
671 }
672
673
674 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
675 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
676 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
677 {
678 int i;
679
680 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
681 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
682
683 /* copy security descriptor control portion */
684 pnntsd->revision = pntsd->revision;
685 pnntsd->type = pntsd->type;
686 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
687 pnntsd->sacloffset = 0;
688 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
689 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
690
691 /* copy owner sid */
692 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
693 le32_to_cpu(pntsd->osidoffset));
694 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
695
696 nowner_sid_ptr->revision = owner_sid_ptr->revision;
697 nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
698 for (i = 0; i < 6; i++)
699 nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
700 for (i = 0; i < 5; i++)
701 nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
702
703 /* copy group sid */
704 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
705 le32_to_cpu(pntsd->gsidoffset));
706 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
707 sizeof(struct cifs_sid));
708
709 ngroup_sid_ptr->revision = group_sid_ptr->revision;
710 ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
711 for (i = 0; i < 6; i++)
712 ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
713 for (i = 0; i < 5; i++)
714 ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
715
716 return;
717 }
718
719
720 /*
721 change posix mode to reflect permissions
722 pmode is the existing mode (we only want to overwrite part of this
723 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
724 */
725 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
726 umode_t *pbits_to_set)
727 {
728 __u32 flags = le32_to_cpu(ace_flags);
729 /* the order of ACEs is important. The canonical order is to begin with
730 DENY entries followed by ALLOW, otherwise an allow entry could be
731 encountered first, making the subsequent deny entry like "dead code"
732 which would be superflous since Windows stops when a match is made
733 for the operation you are trying to perform for your user */
734
735 /* For deny ACEs we change the mask so that subsequent allow access
736 control entries do not turn on the bits we are denying */
737 if (type == ACCESS_DENIED) {
738 if (flags & GENERIC_ALL)
739 *pbits_to_set &= ~S_IRWXUGO;
740
741 if ((flags & GENERIC_WRITE) ||
742 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
743 *pbits_to_set &= ~S_IWUGO;
744 if ((flags & GENERIC_READ) ||
745 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
746 *pbits_to_set &= ~S_IRUGO;
747 if ((flags & GENERIC_EXECUTE) ||
748 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
749 *pbits_to_set &= ~S_IXUGO;
750 return;
751 } else if (type != ACCESS_ALLOWED) {
752 cERROR(1, "unknown access control type %d", type);
753 return;
754 }
755 /* else ACCESS_ALLOWED type */
756
757 if (flags & GENERIC_ALL) {
758 *pmode |= (S_IRWXUGO & (*pbits_to_set));
759 cFYI(DBG2, "all perms");
760 return;
761 }
762 if ((flags & GENERIC_WRITE) ||
763 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
764 *pmode |= (S_IWUGO & (*pbits_to_set));
765 if ((flags & GENERIC_READ) ||
766 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
767 *pmode |= (S_IRUGO & (*pbits_to_set));
768 if ((flags & GENERIC_EXECUTE) ||
769 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
770 *pmode |= (S_IXUGO & (*pbits_to_set));
771
772 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
773 return;
774 }
775
776 /*
777 Generate access flags to reflect permissions mode is the existing mode.
778 This function is called for every ACE in the DACL whose SID matches
779 with either owner or group or everyone.
780 */
781
782 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
783 __u32 *pace_flags)
784 {
785 /* reset access mask */
786 *pace_flags = 0x0;
787
788 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
789 mode &= bits_to_use;
790
791 /* check for R/W/X UGO since we do not know whose flags
792 is this but we have cleared all the bits sans RWX for
793 either user or group or other as per bits_to_use */
794 if (mode & S_IRUGO)
795 *pace_flags |= SET_FILE_READ_RIGHTS;
796 if (mode & S_IWUGO)
797 *pace_flags |= SET_FILE_WRITE_RIGHTS;
798 if (mode & S_IXUGO)
799 *pace_flags |= SET_FILE_EXEC_RIGHTS;
800
801 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
802 return;
803 }
804
805 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
806 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
807 {
808 int i;
809 __u16 size = 0;
810 __u32 access_req = 0;
811
812 pntace->type = ACCESS_ALLOWED;
813 pntace->flags = 0x0;
814 mode_to_access_flags(nmode, bits, &access_req);
815 if (!access_req)
816 access_req = SET_MINIMUM_RIGHTS;
817 pntace->access_req = cpu_to_le32(access_req);
818
819 pntace->sid.revision = psid->revision;
820 pntace->sid.num_subauth = psid->num_subauth;
821 for (i = 0; i < 6; i++)
822 pntace->sid.authority[i] = psid->authority[i];
823 for (i = 0; i < psid->num_subauth; i++)
824 pntace->sid.sub_auth[i] = psid->sub_auth[i];
825
826 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
827 pntace->size = cpu_to_le16(size);
828
829 return size;
830 }
831
832
833 #ifdef CONFIG_CIFS_DEBUG2
834 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
835 {
836 int num_subauth;
837
838 /* validate that we do not go past end of acl */
839
840 if (le16_to_cpu(pace->size) < 16) {
841 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
842 return;
843 }
844
845 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
846 cERROR(1, "ACL too small to parse ACE");
847 return;
848 }
849
850 num_subauth = pace->sid.num_subauth;
851 if (num_subauth) {
852 int i;
853 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
854 pace->sid.revision, pace->sid.num_subauth, pace->type,
855 pace->flags, le16_to_cpu(pace->size));
856 for (i = 0; i < num_subauth; ++i) {
857 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
858 le32_to_cpu(pace->sid.sub_auth[i]));
859 }
860
861 /* BB add length check to make sure that we do not have huge
862 num auths and therefore go off the end */
863 }
864
865 return;
866 }
867 #endif
868
869
870 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
871 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
872 struct cifs_fattr *fattr)
873 {
874 int i;
875 int num_aces = 0;
876 int acl_size;
877 char *acl_base;
878 struct cifs_ace **ppace;
879
880 /* BB need to add parm so we can store the SID BB */
881
882 if (!pdacl) {
883 /* no DACL in the security descriptor, set
884 all the permissions for user/group/other */
885 fattr->cf_mode |= S_IRWXUGO;
886 return;
887 }
888
889 /* validate that we do not go past end of acl */
890 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
891 cERROR(1, "ACL too small to parse DACL");
892 return;
893 }
894
895 cFYI(DBG2, "DACL revision %d size %d num aces %d",
896 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
897 le32_to_cpu(pdacl->num_aces));
898
899 /* reset rwx permissions for user/group/other.
900 Also, if num_aces is 0 i.e. DACL has no ACEs,
901 user/group/other have no permissions */
902 fattr->cf_mode &= ~(S_IRWXUGO);
903
904 acl_base = (char *)pdacl;
905 acl_size = sizeof(struct cifs_acl);
906
907 num_aces = le32_to_cpu(pdacl->num_aces);
908 if (num_aces > 0) {
909 umode_t user_mask = S_IRWXU;
910 umode_t group_mask = S_IRWXG;
911 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
912
913 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
914 return;
915 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
916 GFP_KERNEL);
917 if (!ppace) {
918 cERROR(1, "DACL memory allocation error");
919 return;
920 }
921
922 for (i = 0; i < num_aces; ++i) {
923 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
924 #ifdef CONFIG_CIFS_DEBUG2
925 dump_ace(ppace[i], end_of_acl);
926 #endif
927 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
928 access_flags_to_mode(ppace[i]->access_req,
929 ppace[i]->type,
930 &fattr->cf_mode,
931 &user_mask);
932 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
933 access_flags_to_mode(ppace[i]->access_req,
934 ppace[i]->type,
935 &fattr->cf_mode,
936 &group_mask);
937 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
938 access_flags_to_mode(ppace[i]->access_req,
939 ppace[i]->type,
940 &fattr->cf_mode,
941 &other_mask);
942 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
943 access_flags_to_mode(ppace[i]->access_req,
944 ppace[i]->type,
945 &fattr->cf_mode,
946 &other_mask);
947
948
949 /* memcpy((void *)(&(cifscred->aces[i])),
950 (void *)ppace[i],
951 sizeof(struct cifs_ace)); */
952
953 acl_base = (char *)ppace[i];
954 acl_size = le16_to_cpu(ppace[i]->size);
955 }
956
957 kfree(ppace);
958 }
959
960 return;
961 }
962
963
964 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
965 struct cifs_sid *pgrpsid, __u64 nmode)
966 {
967 u16 size = 0;
968 struct cifs_acl *pnndacl;
969
970 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
971
972 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
973 pownersid, nmode, S_IRWXU);
974 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
975 pgrpsid, nmode, S_IRWXG);
976 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
977 &sid_everyone, nmode, S_IRWXO);
978
979 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
980 pndacl->num_aces = cpu_to_le32(3);
981
982 return 0;
983 }
984
985
986 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
987 {
988 /* BB need to add parm so we can store the SID BB */
989
990 /* validate that we do not go past end of ACL - sid must be at least 8
991 bytes long (assuming no sub-auths - e.g. the null SID */
992 if (end_of_acl < (char *)psid + 8) {
993 cERROR(1, "ACL too small to parse SID %p", psid);
994 return -EINVAL;
995 }
996
997 if (psid->num_subauth) {
998 #ifdef CONFIG_CIFS_DEBUG2
999 int i;
1000 cFYI(1, "SID revision %d num_auth %d",
1001 psid->revision, psid->num_subauth);
1002
1003 for (i = 0; i < psid->num_subauth; i++) {
1004 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
1005 le32_to_cpu(psid->sub_auth[i]));
1006 }
1007
1008 /* BB add length check to make sure that we do not have huge
1009 num auths and therefore go off the end */
1010 cFYI(1, "RID 0x%x",
1011 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
1012 #endif
1013 }
1014
1015 return 0;
1016 }
1017
1018
1019 /* Convert CIFS ACL to POSIX form */
1020 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
1021 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
1022 {
1023 int rc = 0;
1024 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1025 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
1026 char *end_of_acl = ((char *)pntsd) + acl_len;
1027 __u32 dacloffset;
1028
1029 if (pntsd == NULL)
1030 return -EIO;
1031
1032 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1033 le32_to_cpu(pntsd->osidoffset));
1034 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1035 le32_to_cpu(pntsd->gsidoffset));
1036 dacloffset = le32_to_cpu(pntsd->dacloffset);
1037 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1038 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
1039 "sacloffset 0x%x dacloffset 0x%x",
1040 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
1041 le32_to_cpu(pntsd->gsidoffset),
1042 le32_to_cpu(pntsd->sacloffset), dacloffset);
1043 /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
1044 rc = parse_sid(owner_sid_ptr, end_of_acl);
1045 if (rc) {
1046 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
1047 return rc;
1048 }
1049 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
1050 if (rc) {
1051 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
1052 return rc;
1053 }
1054
1055 rc = parse_sid(group_sid_ptr, end_of_acl);
1056 if (rc) {
1057 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
1058 return rc;
1059 }
1060 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
1061 if (rc) {
1062 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
1063 return rc;
1064 }
1065
1066 if (dacloffset)
1067 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
1068 group_sid_ptr, fattr);
1069 else
1070 cFYI(1, "no ACL"); /* BB grant all or default perms? */
1071
1072 return rc;
1073 }
1074
1075 /* Convert permission bits from mode to equivalent CIFS ACL */
1076 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
1077 __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
1078 {
1079 int rc = 0;
1080 __u32 dacloffset;
1081 __u32 ndacloffset;
1082 __u32 sidsoffset;
1083 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1084 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
1085 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
1086 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
1087
1088 if (nmode != NO_CHANGE_64) { /* chmod */
1089 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1090 le32_to_cpu(pntsd->osidoffset));
1091 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1092 le32_to_cpu(pntsd->gsidoffset));
1093 dacloffset = le32_to_cpu(pntsd->dacloffset);
1094 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1095 ndacloffset = sizeof(struct cifs_ntsd);
1096 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1097 ndacl_ptr->revision = dacl_ptr->revision;
1098 ndacl_ptr->size = 0;
1099 ndacl_ptr->num_aces = 0;
1100
1101 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
1102 nmode);
1103 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1104 /* copy sec desc control portion & owner and group sids */
1105 copy_sec_desc(pntsd, pnntsd, sidsoffset);
1106 *aclflag = CIFS_ACL_DACL;
1107 } else {
1108 memcpy(pnntsd, pntsd, secdesclen);
1109 if (uid != NO_CHANGE_32) { /* chown */
1110 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1111 le32_to_cpu(pnntsd->osidoffset));
1112 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1113 GFP_KERNEL);
1114 if (!nowner_sid_ptr)
1115 return -ENOMEM;
1116 rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
1117 if (rc) {
1118 cFYI(1, "%s: Mapping error %d for owner id %d",
1119 __func__, rc, uid);
1120 kfree(nowner_sid_ptr);
1121 return rc;
1122 }
1123 memcpy(owner_sid_ptr, nowner_sid_ptr,
1124 sizeof(struct cifs_sid));
1125 kfree(nowner_sid_ptr);
1126 *aclflag = CIFS_ACL_OWNER;
1127 }
1128 if (gid != NO_CHANGE_32) { /* chgrp */
1129 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1130 le32_to_cpu(pnntsd->gsidoffset));
1131 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1132 GFP_KERNEL);
1133 if (!ngroup_sid_ptr)
1134 return -ENOMEM;
1135 rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
1136 if (rc) {
1137 cFYI(1, "%s: Mapping error %d for group id %d",
1138 __func__, rc, gid);
1139 kfree(ngroup_sid_ptr);
1140 return rc;
1141 }
1142 memcpy(group_sid_ptr, ngroup_sid_ptr,
1143 sizeof(struct cifs_sid));
1144 kfree(ngroup_sid_ptr);
1145 *aclflag = CIFS_ACL_GROUP;
1146 }
1147 }
1148
1149 return rc;
1150 }
1151
1152 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1153 __u16 fid, u32 *pacllen)
1154 {
1155 struct cifs_ntsd *pntsd = NULL;
1156 int xid, rc;
1157 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1158
1159 if (IS_ERR(tlink))
1160 return ERR_CAST(tlink);
1161
1162 xid = GetXid();
1163 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
1164 FreeXid(xid);
1165
1166 cifs_put_tlink(tlink);
1167
1168 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1169 if (rc)
1170 return ERR_PTR(rc);
1171 return pntsd;
1172 }
1173
1174 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1175 const char *path, u32 *pacllen)
1176 {
1177 struct cifs_ntsd *pntsd = NULL;
1178 int oplock = 0;
1179 int xid, rc, create_options = 0;
1180 __u16 fid;
1181 struct cifs_tcon *tcon;
1182 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1183
1184 if (IS_ERR(tlink))
1185 return ERR_CAST(tlink);
1186
1187 tcon = tlink_tcon(tlink);
1188 xid = GetXid();
1189
1190 if (backup_cred(cifs_sb))
1191 create_options |= CREATE_OPEN_BACKUP_INTENT;
1192
1193 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
1194 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1195 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1196 if (!rc) {
1197 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
1198 CIFSSMBClose(xid, tcon, fid);
1199 }
1200
1201 cifs_put_tlink(tlink);
1202 FreeXid(xid);
1203
1204 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1205 if (rc)
1206 return ERR_PTR(rc);
1207 return pntsd;
1208 }
1209
1210 /* Retrieve an ACL from the server */
1211 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1212 struct inode *inode, const char *path,
1213 u32 *pacllen)
1214 {
1215 struct cifs_ntsd *pntsd = NULL;
1216 struct cifsFileInfo *open_file = NULL;
1217
1218 if (inode)
1219 open_file = find_readable_file(CIFS_I(inode), true);
1220 if (!open_file)
1221 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1222
1223 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
1224 cifsFileInfo_put(open_file);
1225 return pntsd;
1226 }
1227
1228 /* Set an ACL on the server */
1229 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1230 struct inode *inode, const char *path, int aclflag)
1231 {
1232 int oplock = 0;
1233 int xid, rc, access_flags, create_options = 0;
1234 __u16 fid;
1235 struct cifs_tcon *tcon;
1236 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1237 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1238
1239 if (IS_ERR(tlink))
1240 return PTR_ERR(tlink);
1241
1242 tcon = tlink_tcon(tlink);
1243 xid = GetXid();
1244
1245 if (backup_cred(cifs_sb))
1246 create_options |= CREATE_OPEN_BACKUP_INTENT;
1247
1248 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1249 access_flags = WRITE_OWNER;
1250 else
1251 access_flags = WRITE_DAC;
1252
1253 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
1254 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1255 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1256 if (rc) {
1257 cERROR(1, "Unable to open file to set ACL");
1258 goto out;
1259 }
1260
1261 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
1262 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
1263
1264 CIFSSMBClose(xid, tcon, fid);
1265 out:
1266 FreeXid(xid);
1267 cifs_put_tlink(tlink);
1268 return rc;
1269 }
1270
1271 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1272 int
1273 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1274 struct inode *inode, const char *path, const __u16 *pfid)
1275 {
1276 struct cifs_ntsd *pntsd = NULL;
1277 u32 acllen = 0;
1278 int rc = 0;
1279
1280 cFYI(DBG2, "converting ACL to mode for %s", path);
1281
1282 if (pfid)
1283 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
1284 else
1285 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
1286
1287 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1288 if (IS_ERR(pntsd)) {
1289 rc = PTR_ERR(pntsd);
1290 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1291 } else {
1292 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1293 kfree(pntsd);
1294 if (rc)
1295 cERROR(1, "parse sec desc failed rc = %d", rc);
1296 }
1297
1298 return rc;
1299 }
1300
1301 /* Convert mode bits to an ACL so we can update the ACL on the server */
1302 int
1303 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1304 uid_t uid, gid_t gid)
1305 {
1306 int rc = 0;
1307 int aclflag = CIFS_ACL_DACL; /* default flag to set */
1308 __u32 secdesclen = 0;
1309 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1310 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1311
1312 cFYI(DBG2, "set ACL from mode for %s", path);
1313
1314 /* Get the security descriptor */
1315 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1316
1317 /* Add three ACEs for owner, group, everyone getting rid of
1318 other ACEs as chmod disables ACEs and set the security descriptor */
1319
1320 if (IS_ERR(pntsd)) {
1321 rc = PTR_ERR(pntsd);
1322 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1323 } else {
1324 /* allocate memory for the smb header,
1325 set security descriptor request security descriptor
1326 parameters, and secuirty descriptor itself */
1327
1328 secdesclen = secdesclen < DEFSECDESCLEN ?
1329 DEFSECDESCLEN : secdesclen;
1330 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1331 if (!pnntsd) {
1332 cERROR(1, "Unable to allocate security descriptor");
1333 kfree(pntsd);
1334 return -ENOMEM;
1335 }
1336
1337 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1338 &aclflag);
1339
1340 cFYI(DBG2, "build_sec_desc rc: %d", rc);
1341
1342 if (!rc) {
1343 /* Set the security descriptor */
1344 rc = set_cifs_acl(pnntsd, secdesclen, inode,
1345 path, aclflag);
1346 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1347 }
1348
1349 kfree(pnntsd);
1350 kfree(pntsd);
1351 }
1352
1353 return rc;
1354 }