PCI: SRIOV control and status via sysfs (documentation)
[linux-2.6/cjktty.git] / fs / cifs / cifsacl.c
blobfc783e264420a890751aa81e819fc8b53aaa1a81
1 /*
2 * fs/cifs/cifsacl.c
4 * Copyright (C) International Business Machines Corp., 2007,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for mapping CIFS/NTFS ACLs
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.
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.
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
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"
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}, {} };
45 const struct cred *root_cred;
47 static void
48 shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
49 int *nr_del)
51 struct rb_node *node;
52 struct rb_node *tmp;
53 struct cifs_sid_id *psidid;
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);
74 * Run idmap cache shrinker.
76 static int
77 cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
79 int nr_to_scan = sc->nr_to_scan;
80 int nr_del = 0;
81 int nr_rem = 0;
82 struct rb_root *root;
84 root = &uidtree;
85 spin_lock(&siduidlock);
86 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
87 spin_unlock(&siduidlock);
89 root = &gidtree;
90 spin_lock(&sidgidlock);
91 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
92 spin_unlock(&sidgidlock);
94 root = &siduidtree;
95 spin_lock(&uidsidlock);
96 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
97 spin_unlock(&uidsidlock);
99 root = &sidgidtree;
100 spin_lock(&gidsidlock);
101 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
102 spin_unlock(&gidsidlock);
104 return nr_rem;
107 static void
108 sid_rb_insert(struct rb_root *root, unsigned long cid,
109 struct cifs_sid_id **psidid, char *typestr)
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;
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;
124 if (cid < lsidid->id) {
125 linkto = &(node->rb_right);
126 node = node->rb_right;
130 (*psidid)->id = cid;
131 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
132 (*psidid)->refcount = 0;
134 sprintf((*psidid)->sidstr, "%s", typestr);
135 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
136 sprintf(strptr, "%ld", cid);
138 clear_bit(SID_ID_PENDING, &(*psidid)->state);
139 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
141 rb_link_node(&(*psidid)->rbnode, parent, linkto);
142 rb_insert_color(&(*psidid)->rbnode, root);
145 static struct cifs_sid_id *
146 sid_rb_search(struct rb_root *root, unsigned long cid)
148 struct rb_node *node = root->rb_node;
149 struct cifs_sid_id *lsidid;
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;
161 return NULL;
164 static struct shrinker cifs_shrinker = {
165 .shrink = cifs_idmap_shrinker,
166 .seeks = DEFAULT_SEEKS,
169 static int
170 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
172 char *payload;
174 payload = kmalloc(prep->datalen, GFP_KERNEL);
175 if (!payload)
176 return -ENOMEM;
178 memcpy(payload, prep->data, prep->datalen);
179 key->payload.data = payload;
180 key->datalen = prep->datalen;
181 return 0;
184 static inline void
185 cifs_idmap_key_destroy(struct key *key)
187 kfree(key->payload.data);
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,
198 static void
199 sid_to_str(struct cifs_sid *sidptr, char *sidstr)
201 int i;
202 unsigned long saval;
203 char *strptr;
205 strptr = sidstr;
207 sprintf(strptr, "%s", "S");
208 strptr = sidstr + strlen(sidstr);
210 sprintf(strptr, "-%d", sidptr->revision);
211 strptr = sidstr + strlen(sidstr);
213 for (i = 0; i < 6; ++i) {
214 if (sidptr->authority[i]) {
215 sprintf(strptr, "-%d", sidptr->authority[i]);
216 strptr = sidstr + strlen(sidstr);
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);
227 static void
228 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
229 struct cifs_sid_id **psidid, char *typestr)
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;
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;
251 memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
252 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
253 (*psidid)->refcount = 0;
255 sprintf((*psidid)->sidstr, "%s", typestr);
256 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
257 sid_to_str(&(*psidid)->sid, strptr);
259 clear_bit(SID_ID_PENDING, &(*psidid)->state);
260 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
262 rb_link_node(&(*psidid)->rbnode, parent, linkto);
263 rb_insert_color(&(*psidid)->rbnode, root);
266 static struct cifs_sid_id *
267 id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
269 int rc;
270 struct rb_node *node = root->rb_node;
271 struct cifs_sid_id *lsidid;
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;
284 return NULL;
287 static int
288 sidid_pending_wait(void *unused)
290 schedule();
291 return signal_pending(current) ? -ERESTARTSYS : 0;
294 static int
295 id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
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;
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;
314 spin_lock(cidlock);
315 psidid = sid_rb_search(cidtree, cid);
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;
323 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
324 if (!npsidid->sidstr) {
325 kfree(npsidid);
326 return -ENOMEM;
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);
343 } else {
344 ++psidid->refcount;
345 spin_unlock(cidlock);
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 .
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;
362 if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) {
363 rc = -EINVAL;
364 goto id_sid_out;
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);
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;
398 if (test_bit(SID_ID_MAPPED, &psidid->state))
399 memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
400 else
401 rc = -EINVAL;
403 id_sid_out:
404 --psidid->refcount;
405 return rc;
408 static int
409 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
410 struct cifs_fattr *fattr, uint sidtype)
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;
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;
431 spin_lock(cidlock);
432 psidid = id_rb_search(cidtree, psid);
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;
440 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
441 if (!npsidid->sidstr) {
442 kfree(npsidid);
443 return -ENOMEM;
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);
460 } else {
461 ++psidid->refcount;
462 spin_unlock(cidlock);
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 .
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;
479 if (time_after(psidid->time + SID_MAP_RETRY, jiffies))
480 goto sid_to_id_out;
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);
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;
507 if (test_bit(SID_ID_MAPPED, &psidid->state))
508 cid = psidid->id;
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;
518 return 0;
522 init_cifs_idmap(void)
524 struct cred *cred;
525 struct key *keyring;
526 int ret;
528 cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
530 /* create an override credential set with a special thread keyring in
531 * which requests are cached
533 * this is used to prevent malicious redirections from being installed
534 * with add_key().
536 cred = prepare_kernel_cred(NULL);
537 if (!cred)
538 return -ENOMEM;
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;
549 ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
550 if (ret < 0)
551 goto failed_put_key;
553 ret = register_key_type(&cifs_idmap_key_type);
554 if (ret < 0)
555 goto failed_put_key;
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;
564 spin_lock_init(&siduidlock);
565 uidtree = RB_ROOT;
566 spin_lock_init(&sidgidlock);
567 gidtree = RB_ROOT;
569 spin_lock_init(&uidsidlock);
570 siduidtree = RB_ROOT;
571 spin_lock_init(&gidsidlock);
572 sidgidtree = RB_ROOT;
573 register_shrinker(&cifs_shrinker);
575 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
576 return 0;
578 failed_put_key:
579 key_put(keyring);
580 failed_put_cred:
581 put_cred(cred);
582 return ret;
585 void
586 exit_cifs_idmap(void)
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", cifs_idmap_key_type.name);
595 void
596 cifs_destroy_idmaptrees(void)
598 struct rb_root *root;
599 struct rb_node *node;
601 root = &uidtree;
602 spin_lock(&siduidlock);
603 while ((node = rb_first(root)))
604 rb_erase(node, root);
605 spin_unlock(&siduidlock);
607 root = &gidtree;
608 spin_lock(&sidgidlock);
609 while ((node = rb_first(root)))
610 rb_erase(node, root);
611 spin_unlock(&sidgidlock);
613 root = &siduidtree;
614 spin_lock(&uidsidlock);
615 while ((node = rb_first(root)))
616 rb_erase(node, root);
617 spin_unlock(&uidsidlock);
619 root = &sidgidtree;
620 spin_lock(&gidsidlock);
621 while ((node = rb_first(root)))
622 rb_erase(node, root);
623 spin_unlock(&gidsidlock);
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)
630 int i;
631 int num_subauth, num_sat, num_saw;
633 if ((!ctsid) || (!cwsid))
634 return 1;
636 /* compare the revision */
637 if (ctsid->revision != cwsid->revision) {
638 if (ctsid->revision > cwsid->revision)
639 return 1;
640 else
641 return -1;
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;
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;
670 return 0; /* sids compare/match */
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)
678 int i;
680 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
681 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
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));
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);
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];
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));
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];
716 return;
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
725 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
726 umode_t *pbits_to_set)
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 */
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;
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;
755 /* else ACCESS_ALLOWED type */
757 if (flags & GENERIC_ALL) {
758 *pmode |= (S_IRWXUGO & (*pbits_to_set));
759 cFYI(DBG2, "all perms");
760 return;
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));
772 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
773 return;
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.
782 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
783 __u32 *pace_flags)
785 /* reset access mask */
786 *pace_flags = 0x0;
788 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
789 mode &= bits_to_use;
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;
801 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
802 return;
805 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
806 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
808 int i;
809 __u16 size = 0;
810 __u32 access_req = 0;
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);
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];
826 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
827 pntace->size = cpu_to_le16(size);
829 return size;
833 #ifdef CONFIG_CIFS_DEBUG2
834 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
836 int num_subauth;
838 /* validate that we do not go past end of acl */
840 if (le16_to_cpu(pace->size) < 16) {
841 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
842 return;
845 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
846 cERROR(1, "ACL too small to parse ACE");
847 return;
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]));
861 /* BB add length check to make sure that we do not have huge
862 num auths and therefore go off the end */
865 return;
867 #endif
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)
874 int i;
875 int num_aces = 0;
876 int acl_size;
877 char *acl_base;
878 struct cifs_ace **ppace;
880 /* BB need to add parm so we can store the SID BB */
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;
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;
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));
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);
904 acl_base = (char *)pdacl;
905 acl_size = sizeof(struct cifs_acl);
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;
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;
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);
949 /* memcpy((void *)(&(cifscred->aces[i])),
950 (void *)ppace[i],
951 sizeof(struct cifs_ace)); */
953 acl_base = (char *)ppace[i];
954 acl_size = le16_to_cpu(ppace[i]->size);
957 kfree(ppace);
960 return;
964 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
965 struct cifs_sid *pgrpsid, __u64 nmode)
967 u16 size = 0;
968 struct cifs_acl *pnndacl;
970 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
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);
979 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
980 pndacl->num_aces = cpu_to_le32(3);
982 return 0;
986 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
988 /* BB need to add parm so we can store the SID BB */
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;
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);
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]));
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
1015 return 0;
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)
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;
1029 if (pntsd == NULL)
1030 return -EIO;
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;
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;
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;
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;
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? */
1072 return rc;
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)
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 */
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;
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;
1123 memcpy(owner_sid_ptr, nowner_sid_ptr,
1124 sizeof(struct cifs_sid));
1125 kfree(nowner_sid_ptr);
1126 *aclflag = CIFS_ACL_OWNER;
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;
1142 memcpy(group_sid_ptr, ngroup_sid_ptr,
1143 sizeof(struct cifs_sid));
1144 kfree(ngroup_sid_ptr);
1145 *aclflag = CIFS_ACL_GROUP;
1149 return rc;
1152 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1153 __u16 fid, u32 *pacllen)
1155 struct cifs_ntsd *pntsd = NULL;
1156 unsigned int xid;
1157 int rc;
1158 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1160 if (IS_ERR(tlink))
1161 return ERR_CAST(tlink);
1163 xid = get_xid();
1164 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
1165 free_xid(xid);
1167 cifs_put_tlink(tlink);
1169 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1170 if (rc)
1171 return ERR_PTR(rc);
1172 return pntsd;
1175 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1176 const char *path, u32 *pacllen)
1178 struct cifs_ntsd *pntsd = NULL;
1179 int oplock = 0;
1180 unsigned int xid;
1181 int rc, create_options = 0;
1182 __u16 fid;
1183 struct cifs_tcon *tcon;
1184 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1186 if (IS_ERR(tlink))
1187 return ERR_CAST(tlink);
1189 tcon = tlink_tcon(tlink);
1190 xid = get_xid();
1192 if (backup_cred(cifs_sb))
1193 create_options |= CREATE_OPEN_BACKUP_INTENT;
1195 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
1196 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1197 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1198 if (!rc) {
1199 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
1200 CIFSSMBClose(xid, tcon, fid);
1203 cifs_put_tlink(tlink);
1204 free_xid(xid);
1206 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1207 if (rc)
1208 return ERR_PTR(rc);
1209 return pntsd;
1212 /* Retrieve an ACL from the server */
1213 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1214 struct inode *inode, const char *path,
1215 u32 *pacllen)
1217 struct cifs_ntsd *pntsd = NULL;
1218 struct cifsFileInfo *open_file = NULL;
1220 if (inode)
1221 open_file = find_readable_file(CIFS_I(inode), true);
1222 if (!open_file)
1223 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1225 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
1226 cifsFileInfo_put(open_file);
1227 return pntsd;
1230 /* Set an ACL on the server */
1231 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1232 struct inode *inode, const char *path, int aclflag)
1234 int oplock = 0;
1235 unsigned int xid;
1236 int rc, access_flags, create_options = 0;
1237 __u16 fid;
1238 struct cifs_tcon *tcon;
1239 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1240 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1242 if (IS_ERR(tlink))
1243 return PTR_ERR(tlink);
1245 tcon = tlink_tcon(tlink);
1246 xid = get_xid();
1248 if (backup_cred(cifs_sb))
1249 create_options |= CREATE_OPEN_BACKUP_INTENT;
1251 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1252 access_flags = WRITE_OWNER;
1253 else
1254 access_flags = WRITE_DAC;
1256 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
1257 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1258 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1259 if (rc) {
1260 cERROR(1, "Unable to open file to set ACL");
1261 goto out;
1264 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
1265 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
1267 CIFSSMBClose(xid, tcon, fid);
1268 out:
1269 free_xid(xid);
1270 cifs_put_tlink(tlink);
1271 return rc;
1274 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1276 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1277 struct inode *inode, const char *path, const __u16 *pfid)
1279 struct cifs_ntsd *pntsd = NULL;
1280 u32 acllen = 0;
1281 int rc = 0;
1283 cFYI(DBG2, "converting ACL to mode for %s", path);
1285 if (pfid)
1286 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
1287 else
1288 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
1290 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1291 if (IS_ERR(pntsd)) {
1292 rc = PTR_ERR(pntsd);
1293 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1294 } else {
1295 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1296 kfree(pntsd);
1297 if (rc)
1298 cERROR(1, "parse sec desc failed rc = %d", rc);
1301 return rc;
1304 /* Convert mode bits to an ACL so we can update the ACL on the server */
1306 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1307 uid_t uid, gid_t gid)
1309 int rc = 0;
1310 int aclflag = CIFS_ACL_DACL; /* default flag to set */
1311 __u32 secdesclen = 0;
1312 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1313 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1315 cFYI(DBG2, "set ACL from mode for %s", path);
1317 /* Get the security descriptor */
1318 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1320 /* Add three ACEs for owner, group, everyone getting rid of
1321 other ACEs as chmod disables ACEs and set the security descriptor */
1323 if (IS_ERR(pntsd)) {
1324 rc = PTR_ERR(pntsd);
1325 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1326 } else {
1327 /* allocate memory for the smb header,
1328 set security descriptor request security descriptor
1329 parameters, and secuirty descriptor itself */
1331 secdesclen = secdesclen < DEFSECDESCLEN ?
1332 DEFSECDESCLEN : secdesclen;
1333 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1334 if (!pnntsd) {
1335 cERROR(1, "Unable to allocate security descriptor");
1336 kfree(pntsd);
1337 return -ENOMEM;
1340 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1341 &aclflag);
1343 cFYI(DBG2, "build_sec_desc rc: %d", rc);
1345 if (!rc) {
1346 /* Set the security descriptor */
1347 rc = set_cifs_acl(pnntsd, secdesclen, inode,
1348 path, aclflag);
1349 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1352 kfree(pnntsd);
1353 kfree(pntsd);
1356 return rc;