blob: 992f1fb299d14beb701e257440e8f56f390c9db0 [file] [log] [blame]
Steve Frenchbcb02032007-09-25 16:17:24 +00001/*
2 * fs/cifs/cifsacl.c
3 *
Steve French8b1327f2008-03-14 22:37:16 +00004 * Copyright (C) International Business Machines Corp., 2007,2008
Steve Frenchbcb02032007-09-25 16:17:24 +00005 * 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
Steve French65874002007-09-25 19:53:44 +000024#include <linux/fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050026#include <linux/string.h>
27#include <linux/keyctl.h>
28#include <linux/key-type.h>
29#include <keys/user-type.h>
Steve French65874002007-09-25 19:53:44 +000030#include "cifspdu.h"
31#include "cifsglob.h"
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +000032#include "cifsacl.h"
Steve French65874002007-09-25 19:53:44 +000033#include "cifsproto.h"
34#include "cifs_debug.h"
Steve French65874002007-09-25 19:53:44 +000035
Shirish Pargaonkar2fbc2f12010-12-06 14:56:46 -060036/* security id for everyone/world system group */
Shirish Pargaonkare01b6402007-10-30 04:45:14 +000037static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
Shirish Pargaonkar2fbc2f12010-12-06 14:56:46 -060039/* security id for Authenticated Users system group */
40static const struct cifs_sid sid_authusers = {
Steve French4f612582011-05-27 20:40:18 +000041 1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
Steve Frenchbcb02032007-09-25 16:17:24 +000042/* group users */
Steve Frenchad7a2922008-02-07 23:25:02 +000043static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +000044
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -050045const struct cred *root_cred;
46
47static void
48shrink_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}
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050072
73/*
74 * Run idmap cache shrinker.
75 */
76static int
Al Viroef1d5752011-05-29 13:46:08 +010077cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050078{
Al Viroef1d5752011-05-29 13:46:08 +010079 int nr_to_scan = sc->nr_to_scan;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -050080 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
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -050094 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
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500104 return nr_rem;
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500105}
106
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500107static void
108sid_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
145static struct cifs_sid_id *
146sid_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
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500164static struct shrinker cifs_shrinker = {
165 .shrink = cifs_idmap_shrinker,
166 .seeks = DEFAULT_SEEKS,
167};
168
169static int
170cifs_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;
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500180 key->datalen = datalen;
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500181 return 0;
182}
183
184static inline void
185cifs_idmap_key_destroy(struct key *key)
186{
187 kfree(key->payload.data);
188}
189
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500190struct key_type cifs_idmap_key_type = {
Shirish Pargaonkarc4aca0c2011-05-06 02:35:00 -0500191 .name = "cifs.idmap",
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500192 .instantiate = cifs_idmap_key_instantiate,
193 .destroy = cifs_idmap_key_destroy,
194 .describe = user_describe,
195 .match = user_match,
196};
197
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500198static void
199sid_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
227static void
228id_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
266static struct cifs_sid_id *
267id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
268{
269 int rc;
270 struct rb_node *node = root->rb_node;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500271 struct cifs_sid_id *lsidid;
272
273 while (node) {
274 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500275 rc = compare_sids(sidptr, &((lsidid)->sid));
276 if (rc > 0) {
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500277 node = node->rb_left;
278 } else if (rc < 0) {
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500279 node = node->rb_right;
280 } else /* node found */
281 return lsidid;
282 }
283
284 return NULL;
285}
286
287static int
288sidid_pending_wait(void *unused)
289{
290 schedule();
291 return signal_pending(current) ? -ERESTARTSYS : 0;
292}
293
294static int
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500295id_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 }
403id_sid_out:
404 --psidid->refcount;
405 return rc;
406}
407
408static int
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500409sid_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
511sid_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
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500521int
522init_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 cred->thread_keyring = keyring;
560 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
561 root_cred = cred;
562
563 spin_lock_init(&siduidlock);
564 uidtree = RB_ROOT;
565 spin_lock_init(&sidgidlock);
566 gidtree = RB_ROOT;
567
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500568 spin_lock_init(&uidsidlock);
569 siduidtree = RB_ROOT;
570 spin_lock_init(&gidsidlock);
571 sidgidtree = RB_ROOT;
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500572 register_shrinker(&cifs_shrinker);
573
574 cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring));
575 return 0;
576
577failed_put_key:
578 key_put(keyring);
579failed_put_cred:
580 put_cred(cred);
581 return ret;
582}
583
584void
585exit_cifs_idmap(void)
586{
587 key_revoke(root_cred->thread_keyring);
588 unregister_key_type(&cifs_idmap_key_type);
589 put_cred(root_cred);
590 unregister_shrinker(&cifs_shrinker);
591 cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name);
592}
593
594void
595cifs_destroy_idmaptrees(void)
596{
597 struct rb_root *root;
598 struct rb_node *node;
599
600 root = &uidtree;
601 spin_lock(&siduidlock);
602 while ((node = rb_first(root)))
603 rb_erase(node, root);
604 spin_unlock(&siduidlock);
605
606 root = &gidtree;
607 spin_lock(&sidgidlock);
608 while ((node = rb_first(root)))
609 rb_erase(node, root);
610 spin_unlock(&sidgidlock);
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500611
612 root = &siduidtree;
613 spin_lock(&uidsidlock);
614 while ((node = rb_first(root)))
615 rb_erase(node, root);
616 spin_unlock(&uidsidlock);
617
618 root = &sidgidtree;
619 spin_lock(&gidsidlock);
620 while ((node = rb_first(root)))
621 rb_erase(node, root);
622 spin_unlock(&gidsidlock);
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500623}
Steve French297647c2007-10-12 04:11:59 +0000624
Steve Frencha750e772007-10-17 22:50:39 +0000625/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
626 the same returns 1, if they do not match returns 0 */
Steve French630f3f0c2007-10-25 21:17:17 +0000627int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
Steve French297647c2007-10-12 04:11:59 +0000628{
629 int i;
630 int num_subauth, num_sat, num_saw;
631
632 if ((!ctsid) || (!cwsid))
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500633 return 1;
Steve French297647c2007-10-12 04:11:59 +0000634
635 /* compare the revision */
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500636 if (ctsid->revision != cwsid->revision) {
637 if (ctsid->revision > cwsid->revision)
638 return 1;
639 else
640 return -1;
641 }
Steve French297647c2007-10-12 04:11:59 +0000642
643 /* compare all of the six auth values */
644 for (i = 0; i < 6; ++i) {
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500645 if (ctsid->authority[i] != cwsid->authority[i]) {
646 if (ctsid->authority[i] > cwsid->authority[i])
647 return 1;
648 else
649 return -1;
650 }
Steve French297647c2007-10-12 04:11:59 +0000651 }
652
653 /* compare all of the subauth values if any */
Steve Frenchadbc0352007-10-17 02:12:46 +0000654 num_sat = ctsid->num_subauth;
Steve Frenchadddd492007-10-17 02:48:17 +0000655 num_saw = cwsid->num_subauth;
Steve French297647c2007-10-12 04:11:59 +0000656 num_subauth = num_sat < num_saw ? num_sat : num_saw;
657 if (num_subauth) {
658 for (i = 0; i < num_subauth; ++i) {
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500659 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
Steve French383c5532011-05-27 15:19:12 +0000660 if (le32_to_cpu(ctsid->sub_auth[i]) >
661 le32_to_cpu(cwsid->sub_auth[i]))
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500662 return 1;
663 else
664 return -1;
665 }
Steve French297647c2007-10-12 04:11:59 +0000666 }
667 }
668
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500669 return 0; /* sids compare/match */
Steve French297647c2007-10-12 04:11:59 +0000670}
671
Steve French97837582007-12-31 07:47:21 +0000672
673/* copy ntsd, owner sid, and group sid from a security descriptor to another */
674static void copy_sec_desc(const struct cifs_ntsd *pntsd,
675 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
676{
677 int i;
678
679 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
680 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
681
682 /* copy security descriptor control portion */
683 pnntsd->revision = pntsd->revision;
684 pnntsd->type = pntsd->type;
685 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
686 pnntsd->sacloffset = 0;
687 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
688 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
689
690 /* copy owner sid */
691 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
692 le32_to_cpu(pntsd->osidoffset));
693 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
694
695 nowner_sid_ptr->revision = owner_sid_ptr->revision;
696 nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
697 for (i = 0; i < 6; i++)
698 nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
699 for (i = 0; i < 5; i++)
700 nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
701
702 /* copy group sid */
703 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
704 le32_to_cpu(pntsd->gsidoffset));
705 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
706 sizeof(struct cifs_sid));
707
708 ngroup_sid_ptr->revision = group_sid_ptr->revision;
709 ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
710 for (i = 0; i < 6; i++)
711 ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
712 for (i = 0; i < 5; i++)
Shirish Pargaonkarb1910ad2008-07-24 14:53:20 +0000713 ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
Steve French97837582007-12-31 07:47:21 +0000714
715 return;
716}
717
718
Steve French630f3f0c2007-10-25 21:17:17 +0000719/*
720 change posix mode to reflect permissions
721 pmode is the existing mode (we only want to overwrite part of this
722 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
723*/
Al Viro9b5e6852007-12-05 08:24:38 +0000724static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
Steve French15b03952007-11-08 17:57:40 +0000725 umode_t *pbits_to_set)
Steve French4879b442007-10-19 21:57:39 +0000726{
Al Viro9b5e6852007-12-05 08:24:38 +0000727 __u32 flags = le32_to_cpu(ace_flags);
Steve French15b03952007-11-08 17:57:40 +0000728 /* the order of ACEs is important. The canonical order is to begin with
Steve Frenchce06c9f2007-11-08 21:12:01 +0000729 DENY entries followed by ALLOW, otherwise an allow entry could be
Steve French15b03952007-11-08 17:57:40 +0000730 encountered first, making the subsequent deny entry like "dead code"
Steve Frenchce06c9f2007-11-08 21:12:01 +0000731 which would be superflous since Windows stops when a match is made
Steve French15b03952007-11-08 17:57:40 +0000732 for the operation you are trying to perform for your user */
733
734 /* For deny ACEs we change the mask so that subsequent allow access
735 control entries do not turn on the bits we are denying */
736 if (type == ACCESS_DENIED) {
Steve Frenchad7a2922008-02-07 23:25:02 +0000737 if (flags & GENERIC_ALL)
Steve French15b03952007-11-08 17:57:40 +0000738 *pbits_to_set &= ~S_IRWXUGO;
Steve Frenchad7a2922008-02-07 23:25:02 +0000739
Al Viro9b5e6852007-12-05 08:24:38 +0000740 if ((flags & GENERIC_WRITE) ||
741 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000742 *pbits_to_set &= ~S_IWUGO;
Al Viro9b5e6852007-12-05 08:24:38 +0000743 if ((flags & GENERIC_READ) ||
744 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000745 *pbits_to_set &= ~S_IRUGO;
Al Viro9b5e6852007-12-05 08:24:38 +0000746 if ((flags & GENERIC_EXECUTE) ||
747 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000748 *pbits_to_set &= ~S_IXUGO;
749 return;
750 } else if (type != ACCESS_ALLOWED) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000751 cERROR(1, "unknown access control type %d", type);
Steve French15b03952007-11-08 17:57:40 +0000752 return;
753 }
754 /* else ACCESS_ALLOWED type */
Steve French44093ca2007-10-23 21:22:55 +0000755
Al Viro9b5e6852007-12-05 08:24:38 +0000756 if (flags & GENERIC_ALL) {
Steve French15b03952007-11-08 17:57:40 +0000757 *pmode |= (S_IRWXUGO & (*pbits_to_set));
Joe Perchesb6b38f72010-04-21 03:50:45 +0000758 cFYI(DBG2, "all perms");
Steve Frenchd61e5802007-10-26 04:32:43 +0000759 return;
760 }
Al Viro9b5e6852007-12-05 08:24:38 +0000761 if ((flags & GENERIC_WRITE) ||
762 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000763 *pmode |= (S_IWUGO & (*pbits_to_set));
Al Viro9b5e6852007-12-05 08:24:38 +0000764 if ((flags & GENERIC_READ) ||
765 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000766 *pmode |= (S_IRUGO & (*pbits_to_set));
Al Viro9b5e6852007-12-05 08:24:38 +0000767 if ((flags & GENERIC_EXECUTE) ||
768 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000769 *pmode |= (S_IXUGO & (*pbits_to_set));
Steve Frenchd61e5802007-10-26 04:32:43 +0000770
Joe Perchesb6b38f72010-04-21 03:50:45 +0000771 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
Steve French630f3f0c2007-10-25 21:17:17 +0000772 return;
773}
774
Steve Frenchce06c9f2007-11-08 21:12:01 +0000775/*
776 Generate access flags to reflect permissions mode is the existing mode.
777 This function is called for every ACE in the DACL whose SID matches
778 with either owner or group or everyone.
779*/
780
781static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
782 __u32 *pace_flags)
783{
784 /* reset access mask */
785 *pace_flags = 0x0;
786
787 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
788 mode &= bits_to_use;
789
790 /* check for R/W/X UGO since we do not know whose flags
791 is this but we have cleared all the bits sans RWX for
792 either user or group or other as per bits_to_use */
793 if (mode & S_IRUGO)
794 *pace_flags |= SET_FILE_READ_RIGHTS;
795 if (mode & S_IWUGO)
796 *pace_flags |= SET_FILE_WRITE_RIGHTS;
797 if (mode & S_IXUGO)
798 *pace_flags |= SET_FILE_EXEC_RIGHTS;
799
Joe Perchesb6b38f72010-04-21 03:50:45 +0000800 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
Steve Frenchce06c9f2007-11-08 21:12:01 +0000801 return;
802}
803
Al Viro2b210ad2008-03-29 03:09:18 +0000804static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
Steve French97837582007-12-31 07:47:21 +0000805 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
806{
807 int i;
808 __u16 size = 0;
809 __u32 access_req = 0;
810
811 pntace->type = ACCESS_ALLOWED;
812 pntace->flags = 0x0;
813 mode_to_access_flags(nmode, bits, &access_req);
814 if (!access_req)
815 access_req = SET_MINIMUM_RIGHTS;
816 pntace->access_req = cpu_to_le32(access_req);
817
818 pntace->sid.revision = psid->revision;
819 pntace->sid.num_subauth = psid->num_subauth;
820 for (i = 0; i < 6; i++)
821 pntace->sid.authority[i] = psid->authority[i];
822 for (i = 0; i < psid->num_subauth; i++)
823 pntace->sid.sub_auth[i] = psid->sub_auth[i];
824
825 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
826 pntace->size = cpu_to_le16(size);
827
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000828 return size;
Steve French97837582007-12-31 07:47:21 +0000829}
830
Steve French297647c2007-10-12 04:11:59 +0000831
Steve French953f8682007-10-31 04:54:42 +0000832#ifdef CONFIG_CIFS_DEBUG2
833static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000834{
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000835 int num_subauth;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000836
837 /* validate that we do not go past end of acl */
Steve French297647c2007-10-12 04:11:59 +0000838
Steve French44093ca2007-10-23 21:22:55 +0000839 if (le16_to_cpu(pace->size) < 16) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000840 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
Steve French44093ca2007-10-23 21:22:55 +0000841 return;
842 }
843
844 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000845 cERROR(1, "ACL too small to parse ACE");
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000846 return;
Steve French44093ca2007-10-23 21:22:55 +0000847 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000848
Steve French44093ca2007-10-23 21:22:55 +0000849 num_subauth = pace->sid.num_subauth;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000850 if (num_subauth) {
Steve French8f18c132007-10-12 18:54:12 +0000851 int i;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000852 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
Steve French44093ca2007-10-23 21:22:55 +0000853 pace->sid.revision, pace->sid.num_subauth, pace->type,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000854 pace->flags, le16_to_cpu(pace->size));
Steve Frenchd12fd122007-10-03 19:43:19 +0000855 for (i = 0; i < num_subauth; ++i) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000856 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
857 le32_to_cpu(pace->sid.sub_auth[i]));
Steve Frenchd12fd122007-10-03 19:43:19 +0000858 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000859
Steve Frenchd12fd122007-10-03 19:43:19 +0000860 /* BB add length check to make sure that we do not have huge
861 num auths and therefore go off the end */
Steve Frenchd12fd122007-10-03 19:43:19 +0000862 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000863
Steve Frenchd12fd122007-10-03 19:43:19 +0000864 return;
865}
Steve French953f8682007-10-31 04:54:42 +0000866#endif
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000867
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000868
Steve Frencha750e772007-10-17 22:50:39 +0000869static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
Steve Frenchd61e5802007-10-26 04:32:43 +0000870 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400871 struct cifs_fattr *fattr)
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000872{
873 int i;
874 int num_aces = 0;
875 int acl_size;
876 char *acl_base;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000877 struct cifs_ace **ppace;
878
879 /* BB need to add parm so we can store the SID BB */
880
Steve French2b834572007-11-25 10:01:00 +0000881 if (!pdacl) {
882 /* no DACL in the security descriptor, set
883 all the permissions for user/group/other */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400884 fattr->cf_mode |= S_IRWXUGO;
Steve French2b834572007-11-25 10:01:00 +0000885 return;
886 }
887
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000888 /* validate that we do not go past end of acl */
Steve Frenchaf6f4612007-10-16 18:40:37 +0000889 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000890 cERROR(1, "ACL too small to parse DACL");
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000891 return;
892 }
893
Joe Perchesb6b38f72010-04-21 03:50:45 +0000894 cFYI(DBG2, "DACL revision %d size %d num aces %d",
Steve Frenchaf6f4612007-10-16 18:40:37 +0000895 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
Joe Perchesb6b38f72010-04-21 03:50:45 +0000896 le32_to_cpu(pdacl->num_aces));
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000897
Steve French7505e052007-11-01 18:03:01 +0000898 /* reset rwx permissions for user/group/other.
899 Also, if num_aces is 0 i.e. DACL has no ACEs,
900 user/group/other have no permissions */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400901 fattr->cf_mode &= ~(S_IRWXUGO);
Steve French7505e052007-11-01 18:03:01 +0000902
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000903 acl_base = (char *)pdacl;
904 acl_size = sizeof(struct cifs_acl);
905
Steve Frenchadbc0352007-10-17 02:12:46 +0000906 num_aces = le32_to_cpu(pdacl->num_aces);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000907 if (num_aces > 0) {
Steve French15b03952007-11-08 17:57:40 +0000908 umode_t user_mask = S_IRWXU;
909 umode_t group_mask = S_IRWXG;
Shirish Pargaonkar2fbc2f12010-12-06 14:56:46 -0600910 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
Steve French15b03952007-11-08 17:57:40 +0000911
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000912 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
913 GFP_KERNEL);
Stanislav Fomichev8132b652011-02-06 02:05:28 +0300914 if (!ppace) {
915 cERROR(1, "DACL memory allocation error");
916 return;
917 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000918
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000919 for (i = 0; i < num_aces; ++i) {
Steve French44093ca2007-10-23 21:22:55 +0000920 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
Steve French953f8682007-10-31 04:54:42 +0000921#ifdef CONFIG_CIFS_DEBUG2
922 dump_ace(ppace[i], end_of_acl);
923#endif
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500924 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000925 access_flags_to_mode(ppace[i]->access_req,
Steve French15b03952007-11-08 17:57:40 +0000926 ppace[i]->type,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400927 &fattr->cf_mode,
Steve French15b03952007-11-08 17:57:40 +0000928 &user_mask);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500929 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000930 access_flags_to_mode(ppace[i]->access_req,
Steve French15b03952007-11-08 17:57:40 +0000931 ppace[i]->type,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400932 &fattr->cf_mode,
Steve French15b03952007-11-08 17:57:40 +0000933 &group_mask);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500934 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000935 access_flags_to_mode(ppace[i]->access_req,
Steve French15b03952007-11-08 17:57:40 +0000936 ppace[i]->type,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400937 &fattr->cf_mode,
Steve French15b03952007-11-08 17:57:40 +0000938 &other_mask);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500939 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
Shirish Pargaonkar2fbc2f12010-12-06 14:56:46 -0600940 access_flags_to_mode(ppace[i]->access_req,
941 ppace[i]->type,
942 &fattr->cf_mode,
943 &other_mask);
944
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000945
Steve French44093ca2007-10-23 21:22:55 +0000946/* memcpy((void *)(&(cifscred->aces[i])),
Steve Frenchd12fd122007-10-03 19:43:19 +0000947 (void *)ppace[i],
948 sizeof(struct cifs_ace)); */
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000949
Steve French44093ca2007-10-23 21:22:55 +0000950 acl_base = (char *)ppace[i];
951 acl_size = le16_to_cpu(ppace[i]->size);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000952 }
953
954 kfree(ppace);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000955 }
956
957 return;
958}
959
Steve Frenchbcb02032007-09-25 16:17:24 +0000960
Steve French97837582007-12-31 07:47:21 +0000961static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
962 struct cifs_sid *pgrpsid, __u64 nmode)
963{
Al Viro2b210ad2008-03-29 03:09:18 +0000964 u16 size = 0;
Steve French97837582007-12-31 07:47:21 +0000965 struct cifs_acl *pnndacl;
966
967 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
968
969 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
970 pownersid, nmode, S_IRWXU);
971 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
972 pgrpsid, nmode, S_IRWXG);
973 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
974 &sid_everyone, nmode, S_IRWXO);
975
976 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
Shirish Pargaonkard9f382e2008-02-12 20:46:26 +0000977 pndacl->num_aces = cpu_to_le32(3);
Steve French97837582007-12-31 07:47:21 +0000978
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000979 return 0;
Steve French97837582007-12-31 07:47:21 +0000980}
981
982
Steve Frenchbcb02032007-09-25 16:17:24 +0000983static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
984{
985 /* BB need to add parm so we can store the SID BB */
986
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000987 /* validate that we do not go past end of ACL - sid must be at least 8
988 bytes long (assuming no sub-auths - e.g. the null SID */
989 if (end_of_acl < (char *)psid + 8) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000990 cERROR(1, "ACL too small to parse SID %p", psid);
Steve Frenchbcb02032007-09-25 16:17:24 +0000991 return -EINVAL;
992 }
Steve Frenchbcb02032007-09-25 16:17:24 +0000993
Steve Frenchaf6f4612007-10-16 18:40:37 +0000994 if (psid->num_subauth) {
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000995#ifdef CONFIG_CIFS_DEBUG2
Steve French8f18c132007-10-12 18:54:12 +0000996 int i;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000997 cFYI(1, "SID revision %d num_auth %d",
998 psid->revision, psid->num_subauth);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000999
Steve Frenchaf6f4612007-10-16 18:40:37 +00001000 for (i = 0; i < psid->num_subauth; i++) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001001 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
1002 le32_to_cpu(psid->sub_auth[i]));
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001003 }
1004
Steve Frenchd12fd122007-10-03 19:43:19 +00001005 /* BB add length check to make sure that we do not have huge
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001006 num auths and therefore go off the end */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001007 cFYI(1, "RID 0x%x",
1008 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
Steve Frenchbcb02032007-09-25 16:17:24 +00001009#endif
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001010 }
1011
Steve Frenchbcb02032007-09-25 16:17:24 +00001012 return 0;
1013}
1014
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001015
Steve Frenchbcb02032007-09-25 16:17:24 +00001016/* Convert CIFS ACL to POSIX form */
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001017static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
1018 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
Steve Frenchbcb02032007-09-25 16:17:24 +00001019{
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001020 int rc = 0;
Steve Frenchbcb02032007-09-25 16:17:24 +00001021 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1022 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
Steve Frenchbcb02032007-09-25 16:17:24 +00001023 char *end_of_acl = ((char *)pntsd) + acl_len;
Steve French7505e052007-11-01 18:03:01 +00001024 __u32 dacloffset;
Steve Frenchbcb02032007-09-25 16:17:24 +00001025
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001026 if (pntsd == NULL)
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001027 return -EIO;
1028
Steve Frenchbcb02032007-09-25 16:17:24 +00001029 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve Frenchaf6f4612007-10-16 18:40:37 +00001030 le32_to_cpu(pntsd->osidoffset));
Steve Frenchbcb02032007-09-25 16:17:24 +00001031 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve Frenchaf6f4612007-10-16 18:40:37 +00001032 le32_to_cpu(pntsd->gsidoffset));
Steve French7505e052007-11-01 18:03:01 +00001033 dacloffset = le32_to_cpu(pntsd->dacloffset);
Steve French63d25832007-11-05 21:46:10 +00001034 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001035 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
Steve Frenchbcb02032007-09-25 16:17:24 +00001036 "sacloffset 0x%x dacloffset 0x%x",
Steve Frenchaf6f4612007-10-16 18:40:37 +00001037 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
1038 le32_to_cpu(pntsd->gsidoffset),
Joe Perchesb6b38f72010-04-21 03:50:45 +00001039 le32_to_cpu(pntsd->sacloffset), dacloffset);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001040/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
Steve Frenchbcb02032007-09-25 16:17:24 +00001041 rc = parse_sid(owner_sid_ptr, end_of_acl);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001042 if (rc) {
1043 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
Steve Frenchbcb02032007-09-25 16:17:24 +00001044 return rc;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001045 }
1046 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
1047 if (rc) {
1048 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
1049 return rc;
1050 }
Steve Frenchbcb02032007-09-25 16:17:24 +00001051
1052 rc = parse_sid(group_sid_ptr, end_of_acl);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001053 if (rc) {
1054 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
Steve Frenchbcb02032007-09-25 16:17:24 +00001055 return rc;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001056 }
1057 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
1058 if (rc) {
1059 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
1060 return rc;
1061 }
Steve Frenchbcb02032007-09-25 16:17:24 +00001062
Steve French7505e052007-11-01 18:03:01 +00001063 if (dacloffset)
1064 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001065 group_sid_ptr, fattr);
Steve French7505e052007-11-01 18:03:01 +00001066 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00001067 cFYI(1, "no ACL"); /* BB grant all or default perms? */
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001068
Steve Frenchbcb02032007-09-25 16:17:24 +00001069/* cifscred->uid = owner_sid_ptr->rid;
1070 cifscred->gid = group_sid_ptr->rid;
1071 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
Steve French630f3f0c2007-10-25 21:17:17 +00001072 sizeof(struct cifs_sid));
Steve Frenchbcb02032007-09-25 16:17:24 +00001073 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
Steve French630f3f0c2007-10-25 21:17:17 +00001074 sizeof(struct cifs_sid)); */
Steve Frenchbcb02032007-09-25 16:17:24 +00001075
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001076 return rc;
Steve Frenchbcb02032007-09-25 16:17:24 +00001077}
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001078
1079
Steve French97837582007-12-31 07:47:21 +00001080/* Convert permission bits from mode to equivalent CIFS ACL */
1081static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
Steve Frenchcce246e2008-04-09 20:55:31 +00001082 struct inode *inode, __u64 nmode)
Steve French97837582007-12-31 07:47:21 +00001083{
1084 int rc = 0;
1085 __u32 dacloffset;
1086 __u32 ndacloffset;
1087 __u32 sidsoffset;
1088 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1089 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
1090 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
1091
1092 if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +00001093 return -EIO;
Steve French97837582007-12-31 07:47:21 +00001094
1095 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1096 le32_to_cpu(pntsd->osidoffset));
1097 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1098 le32_to_cpu(pntsd->gsidoffset));
1099
1100 dacloffset = le32_to_cpu(pntsd->dacloffset);
1101 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1102
1103 ndacloffset = sizeof(struct cifs_ntsd);
1104 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1105 ndacl_ptr->revision = dacl_ptr->revision;
1106 ndacl_ptr->size = 0;
1107 ndacl_ptr->num_aces = 0;
1108
1109 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode);
1110
1111 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1112
1113 /* copy security descriptor control portion and owner and group sid */
1114 copy_sec_desc(pntsd, pnntsd, sidsoffset);
1115
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +00001116 return rc;
Steve French97837582007-12-31 07:47:21 +00001117}
1118
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001119static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1120 __u16 fid, u32 *pacllen)
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001121{
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001122 struct cifs_ntsd *pntsd = NULL;
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001123 int xid, rc;
Jeff Layton7ffec372010-09-29 19:51:11 -04001124 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1125
1126 if (IS_ERR(tlink))
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001127 return ERR_CAST(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001128
1129 xid = GetXid();
Jeff Layton7ffec372010-09-29 19:51:11 -04001130 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001131 FreeXid(xid);
Steve French8b1327f2008-03-14 22:37:16 +00001132
Jeff Layton7ffec372010-09-29 19:51:11 -04001133 cifs_put_tlink(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001134
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001135 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1136 if (rc)
1137 return ERR_PTR(rc);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001138 return pntsd;
1139}
1140
1141static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1142 const char *path, u32 *pacllen)
1143{
1144 struct cifs_ntsd *pntsd = NULL;
1145 int oplock = 0;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001146 int xid, rc, create_options = 0;
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001147 __u16 fid;
Steve French96daf2b2011-05-27 04:34:02 +00001148 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -04001149 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001150
Jeff Layton7ffec372010-09-29 19:51:11 -04001151 if (IS_ERR(tlink))
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001152 return ERR_CAST(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001153
1154 tcon = tlink_tcon(tlink);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001155 xid = GetXid();
1156
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001157 if (backup_cred(cifs_sb))
1158 create_options |= CREATE_OPEN_BACKUP_INTENT;
1159
1160 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
1161 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1162 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001163 if (!rc) {
1164 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
1165 CIFSSMBClose(xid, tcon, fid);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001166 }
1167
Jeff Layton7ffec372010-09-29 19:51:11 -04001168 cifs_put_tlink(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001169 FreeXid(xid);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001170
1171 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1172 if (rc)
1173 return ERR_PTR(rc);
Steve French7505e052007-11-01 18:03:01 +00001174 return pntsd;
1175}
1176
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001177/* Retrieve an ACL from the server */
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -06001178struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001179 struct inode *inode, const char *path,
1180 u32 *pacllen)
1181{
1182 struct cifs_ntsd *pntsd = NULL;
1183 struct cifsFileInfo *open_file = NULL;
1184
1185 if (inode)
Jeff Layton6508d902010-09-29 19:51:11 -04001186 open_file = find_readable_file(CIFS_I(inode), true);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001187 if (!open_file)
1188 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1189
1190 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001191 cifsFileInfo_put(open_file);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001192 return pntsd;
1193}
1194
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001195static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
1196 struct cifs_ntsd *pnntsd, u32 acllen)
1197{
1198 int oplock = 0;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001199 int xid, rc, create_options = 0;
Steve French97837582007-12-31 07:47:21 +00001200 __u16 fid;
Steve French96daf2b2011-05-27 04:34:02 +00001201 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -04001202 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Steve French97837582007-12-31 07:47:21 +00001203
Jeff Layton7ffec372010-09-29 19:51:11 -04001204 if (IS_ERR(tlink))
1205 return PTR_ERR(tlink);
1206
1207 tcon = tlink_tcon(tlink);
Steve French97837582007-12-31 07:47:21 +00001208 xid = GetXid();
1209
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001210 if (backup_cred(cifs_sb))
1211 create_options |= CREATE_OPEN_BACKUP_INTENT;
1212
1213 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, create_options,
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001214 &fid, &oplock, NULL, cifs_sb->local_nls,
1215 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1216 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001217 cERROR(1, "Unable to open file to set ACL");
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001218 goto out;
Steve French97837582007-12-31 07:47:21 +00001219 }
1220
Jeff Layton7ffec372010-09-29 19:51:11 -04001221 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001222 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
Steve French97837582007-12-31 07:47:21 +00001223
Jeff Layton7ffec372010-09-29 19:51:11 -04001224 CIFSSMBClose(xid, tcon, fid);
1225out:
Steve French97837582007-12-31 07:47:21 +00001226 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001227 cifs_put_tlink(tlink);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001228 return rc;
1229}
Steve French97837582007-12-31 07:47:21 +00001230
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001231/* Set an ACL on the server */
Steve Frenchb73b9a42011-04-19 18:27:10 +00001232int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001233 struct inode *inode, const char *path)
1234{
1235 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001236
Joe Perchesb6b38f72010-04-21 03:50:45 +00001237 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001238
Shirish Pargaonkare22906c2011-08-09 14:30:39 -05001239 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
Steve French97837582007-12-31 07:47:21 +00001240}
1241
Steve French7505e052007-11-01 18:03:01 +00001242/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001243int
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001244cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1245 struct inode *inode, const char *path, const __u16 *pfid)
Steve French7505e052007-11-01 18:03:01 +00001246{
1247 struct cifs_ntsd *pntsd = NULL;
1248 u32 acllen = 0;
1249 int rc = 0;
1250
Joe Perchesb6b38f72010-04-21 03:50:45 +00001251 cFYI(DBG2, "converting ACL to mode for %s", path);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001252
1253 if (pfid)
1254 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
1255 else
1256 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
Steve French7505e052007-11-01 18:03:01 +00001257
1258 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001259 if (IS_ERR(pntsd)) {
1260 rc = PTR_ERR(pntsd);
1261 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1262 } else {
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001263 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001264 kfree(pntsd);
1265 if (rc)
1266 cERROR(1, "parse sec desc failed rc = %d", rc);
1267 }
Steve French7505e052007-11-01 18:03:01 +00001268
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001269 return rc;
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001270}
Steve French953f8682007-10-31 04:54:42 +00001271
Steve French7505e052007-11-01 18:03:01 +00001272/* Convert mode bits to an ACL so we can update the ACL on the server */
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06001273int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
Steve French953f8682007-10-31 04:54:42 +00001274{
1275 int rc = 0;
Steve Frenchcce246e2008-04-09 20:55:31 +00001276 __u32 secdesclen = 0;
Steve French97837582007-12-31 07:47:21 +00001277 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1278 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
Steve French953f8682007-10-31 04:54:42 +00001279
Joe Perchesb6b38f72010-04-21 03:50:45 +00001280 cFYI(DBG2, "set ACL from mode for %s", path);
Steve French953f8682007-10-31 04:54:42 +00001281
1282 /* Get the security descriptor */
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001283 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
Steve French953f8682007-10-31 04:54:42 +00001284
Steve French97837582007-12-31 07:47:21 +00001285 /* Add three ACEs for owner, group, everyone getting rid of
1286 other ACEs as chmod disables ACEs and set the security descriptor */
Steve French953f8682007-10-31 04:54:42 +00001287
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001288 if (IS_ERR(pntsd)) {
1289 rc = PTR_ERR(pntsd);
1290 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1291 } else {
Steve French97837582007-12-31 07:47:21 +00001292 /* allocate memory for the smb header,
1293 set security descriptor request security descriptor
1294 parameters, and secuirty descriptor itself */
Steve French953f8682007-10-31 04:54:42 +00001295
Steve Frenchcce246e2008-04-09 20:55:31 +00001296 secdesclen = secdesclen < DEFSECDESCLEN ?
1297 DEFSECDESCLEN : secdesclen;
1298 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
Steve French97837582007-12-31 07:47:21 +00001299 if (!pnntsd) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001300 cERROR(1, "Unable to allocate security descriptor");
Steve French97837582007-12-31 07:47:21 +00001301 kfree(pntsd);
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +00001302 return -ENOMEM;
Steve French97837582007-12-31 07:47:21 +00001303 }
Steve French7505e052007-11-01 18:03:01 +00001304
Steve Frenchcce246e2008-04-09 20:55:31 +00001305 rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
Steve French97837582007-12-31 07:47:21 +00001306
Joe Perchesb6b38f72010-04-21 03:50:45 +00001307 cFYI(DBG2, "build_sec_desc rc: %d", rc);
Steve French97837582007-12-31 07:47:21 +00001308
1309 if (!rc) {
1310 /* Set the security descriptor */
Steve Frenchcce246e2008-04-09 20:55:31 +00001311 rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001312 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
Steve French97837582007-12-31 07:47:21 +00001313 }
1314
1315 kfree(pnntsd);
1316 kfree(pntsd);
1317 }
1318
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +00001319 return rc;
Steve French953f8682007-10-31 04:54:42 +00001320}