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