1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/fs.h>
25#include <linux/slab.h>
26#include <linux/string.h>
27#include <linux/keyctl.h>
28#include <linux/key-type.h>
29#include <keys/user-type.h>
30#include "cifspdu.h"
31#include "cifsglob.h"
32#include "cifsacl.h"
33#include "cifsproto.h"
34#include "cifs_debug.h"
35
36
37static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
39
40static const struct cifs_sid sid_authusers = {
41 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
42
43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
44
45static const struct cred *root_cred;
46
47static int
48cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
49{
50 char *payload;
51
52
53
54
55
56
57
58
59
60 if (prep->datalen <= sizeof(key->payload)) {
61 key->payload.value = 0;
62 memcpy(&key->payload.value, prep->data, prep->datalen);
63 key->datalen = prep->datalen;
64 return 0;
65 }
66 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
67 if (!payload)
68 return -ENOMEM;
69
70 key->payload.data = payload;
71 key->datalen = prep->datalen;
72 return 0;
73}
74
75static inline void
76cifs_idmap_key_destroy(struct key *key)
77{
78 if (key->datalen > sizeof(key->payload))
79 kfree(key->payload.data);
80}
81
82static struct key_type cifs_idmap_key_type = {
83 .name = "cifs.idmap",
84 .instantiate = cifs_idmap_key_instantiate,
85 .destroy = cifs_idmap_key_destroy,
86 .describe = user_describe,
87};
88
89static char *
90sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
91{
92 int i, len;
93 unsigned int saval;
94 char *sidstr, *strptr;
95 unsigned long long id_auth_val;
96
97
98 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
99 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
100 GFP_KERNEL);
101 if (!sidstr)
102 return sidstr;
103
104 strptr = sidstr;
105 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
106 sidptr->revision);
107 strptr += len;
108
109
110 id_auth_val = (unsigned long long)sidptr->authority[5];
111 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
112 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
113 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
114 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
115 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
116
117
118
119
120
121 if (id_auth_val <= UINT_MAX)
122 len = sprintf(strptr, "-%llu", id_auth_val);
123 else
124 len = sprintf(strptr, "-0x%llx", id_auth_val);
125
126 strptr += len;
127
128 for (i = 0; i < sidptr->num_subauth; ++i) {
129 saval = le32_to_cpu(sidptr->sub_auth[i]);
130 len = sprintf(strptr, "-%u", saval);
131 strptr += len;
132 }
133
134 return sidstr;
135}
136
137
138
139
140
141static int
142compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
143{
144 int i;
145 int num_subauth, num_sat, num_saw;
146
147 if ((!ctsid) || (!cwsid))
148 return 1;
149
150
151 if (ctsid->revision != cwsid->revision) {
152 if (ctsid->revision > cwsid->revision)
153 return 1;
154 else
155 return -1;
156 }
157
158
159 for (i = 0; i < NUM_AUTHS; ++i) {
160 if (ctsid->authority[i] != cwsid->authority[i]) {
161 if (ctsid->authority[i] > cwsid->authority[i])
162 return 1;
163 else
164 return -1;
165 }
166 }
167
168
169 num_sat = ctsid->num_subauth;
170 num_saw = cwsid->num_subauth;
171 num_subauth = num_sat < num_saw ? num_sat : num_saw;
172 if (num_subauth) {
173 for (i = 0; i < num_subauth; ++i) {
174 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
175 if (le32_to_cpu(ctsid->sub_auth[i]) >
176 le32_to_cpu(cwsid->sub_auth[i]))
177 return 1;
178 else
179 return -1;
180 }
181 }
182 }
183
184 return 0;
185}
186
187static void
188cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
189{
190 int i;
191
192 dst->revision = src->revision;
193 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
194 for (i = 0; i < NUM_AUTHS; ++i)
195 dst->authority[i] = src->authority[i];
196 for (i = 0; i < dst->num_subauth; ++i)
197 dst->sub_auth[i] = src->sub_auth[i];
198}
199
200static int
201id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
202{
203 int rc;
204 struct key *sidkey;
205 struct cifs_sid *ksid;
206 unsigned int ksid_size;
207 char desc[3 + 10 + 1];
208 const struct cred *saved_cred;
209
210 rc = snprintf(desc, sizeof(desc), "%ci:%u",
211 sidtype == SIDOWNER ? 'o' : 'g', cid);
212 if (rc >= sizeof(desc))
213 return -EINVAL;
214
215 rc = 0;
216 saved_cred = override_creds(root_cred);
217 sidkey = request_key(&cifs_idmap_key_type, desc, "");
218 if (IS_ERR(sidkey)) {
219 rc = -EINVAL;
220 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
221 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
222 goto out_revert_creds;
223 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
224 rc = -EIO;
225 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
226 __func__, sidkey->datalen);
227 goto invalidate_key;
228 }
229
230
231
232
233
234
235 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
236 (struct cifs_sid *)&sidkey->payload.value :
237 (struct cifs_sid *)sidkey->payload.data;
238
239 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
240 if (ksid_size > sidkey->datalen) {
241 rc = -EIO;
242 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
243 __func__, sidkey->datalen, ksid_size);
244 goto invalidate_key;
245 }
246
247 cifs_copy_sid(ssid, ksid);
248out_key_put:
249 key_put(sidkey);
250out_revert_creds:
251 revert_creds(saved_cred);
252 return rc;
253
254invalidate_key:
255 key_invalidate(sidkey);
256 goto out_key_put;
257}
258
259static int
260sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
261 struct cifs_fattr *fattr, uint sidtype)
262{
263 int rc;
264 struct key *sidkey;
265 char *sidstr;
266 const struct cred *saved_cred;
267 kuid_t fuid = cifs_sb->mnt_uid;
268 kgid_t fgid = cifs_sb->mnt_gid;
269
270
271
272
273
274 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
275 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
276 __func__, psid->num_subauth);
277 return -EIO;
278 }
279
280 sidstr = sid_to_key_str(psid, sidtype);
281 if (!sidstr)
282 return -ENOMEM;
283
284 saved_cred = override_creds(root_cred);
285 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
286 if (IS_ERR(sidkey)) {
287 rc = -EINVAL;
288 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
289 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
290 goto out_revert_creds;
291 }
292
293
294
295
296
297
298 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
299 if (sidkey->datalen != sizeof(uid_t)) {
300 rc = -EIO;
301 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
302 __func__, sidkey->datalen);
303 key_invalidate(sidkey);
304 goto out_key_put;
305 }
306
307 if (sidtype == SIDOWNER) {
308 kuid_t uid;
309 uid_t id;
310 memcpy(&id, &sidkey->payload.value, sizeof(uid_t));
311 uid = make_kuid(&init_user_ns, id);
312 if (uid_valid(uid))
313 fuid = uid;
314 } else {
315 kgid_t gid;
316 gid_t id;
317 memcpy(&id, &sidkey->payload.value, sizeof(gid_t));
318 gid = make_kgid(&init_user_ns, id);
319 if (gid_valid(gid))
320 fgid = gid;
321 }
322
323out_key_put:
324 key_put(sidkey);
325out_revert_creds:
326 revert_creds(saved_cred);
327 kfree(sidstr);
328
329
330
331
332
333 if (sidtype == SIDOWNER)
334 fattr->cf_uid = fuid;
335 else
336 fattr->cf_gid = fgid;
337 return 0;
338}
339
340int
341init_cifs_idmap(void)
342{
343 struct cred *cred;
344 struct key *keyring;
345 int ret;
346
347 cifs_dbg(FYI, "Registering the %s key type\n",
348 cifs_idmap_key_type.name);
349
350
351
352
353
354
355
356 cred = prepare_kernel_cred(NULL);
357 if (!cred)
358 return -ENOMEM;
359
360 keyring = keyring_alloc(".cifs_idmap",
361 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
362 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
363 KEY_USR_VIEW | KEY_USR_READ,
364 KEY_ALLOC_NOT_IN_QUOTA, NULL);
365 if (IS_ERR(keyring)) {
366 ret = PTR_ERR(keyring);
367 goto failed_put_cred;
368 }
369
370 ret = register_key_type(&cifs_idmap_key_type);
371 if (ret < 0)
372 goto failed_put_key;
373
374
375
376 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
377 cred->thread_keyring = keyring;
378 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
379 root_cred = cred;
380
381 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
382 return 0;
383
384failed_put_key:
385 key_put(keyring);
386failed_put_cred:
387 put_cred(cred);
388 return ret;
389}
390
391void
392exit_cifs_idmap(void)
393{
394 key_revoke(root_cred->thread_keyring);
395 unregister_key_type(&cifs_idmap_key_type);
396 put_cred(root_cred);
397 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
398}
399
400
401static void copy_sec_desc(const struct cifs_ntsd *pntsd,
402 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
403{
404 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
405 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
406
407
408 pnntsd->revision = pntsd->revision;
409 pnntsd->type = pntsd->type;
410 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
411 pnntsd->sacloffset = 0;
412 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
413 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
414
415
416 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
417 le32_to_cpu(pntsd->osidoffset));
418 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
419 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
420
421
422 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
423 le32_to_cpu(pntsd->gsidoffset));
424 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
425 sizeof(struct cifs_sid));
426 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
427
428 return;
429}
430
431
432
433
434
435
436
437static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
438 umode_t *pbits_to_set)
439{
440 __u32 flags = le32_to_cpu(ace_flags);
441
442
443
444
445
446
447
448
449 if (type == ACCESS_DENIED) {
450 if (flags & GENERIC_ALL)
451 *pbits_to_set &= ~S_IRWXUGO;
452
453 if ((flags & GENERIC_WRITE) ||
454 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
455 *pbits_to_set &= ~S_IWUGO;
456 if ((flags & GENERIC_READ) ||
457 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
458 *pbits_to_set &= ~S_IRUGO;
459 if ((flags & GENERIC_EXECUTE) ||
460 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
461 *pbits_to_set &= ~S_IXUGO;
462 return;
463 } else if (type != ACCESS_ALLOWED) {
464 cifs_dbg(VFS, "unknown access control type %d\n", type);
465 return;
466 }
467
468
469 if (flags & GENERIC_ALL) {
470 *pmode |= (S_IRWXUGO & (*pbits_to_set));
471 cifs_dbg(NOISY, "all perms\n");
472 return;
473 }
474 if ((flags & GENERIC_WRITE) ||
475 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
476 *pmode |= (S_IWUGO & (*pbits_to_set));
477 if ((flags & GENERIC_READ) ||
478 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
479 *pmode |= (S_IRUGO & (*pbits_to_set));
480 if ((flags & GENERIC_EXECUTE) ||
481 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
482 *pmode |= (S_IXUGO & (*pbits_to_set));
483
484 cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode);
485 return;
486}
487
488
489
490
491
492
493
494static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
495 __u32 *pace_flags)
496{
497
498 *pace_flags = 0x0;
499
500
501 mode &= bits_to_use;
502
503
504
505
506 if (mode & S_IRUGO)
507 *pace_flags |= SET_FILE_READ_RIGHTS;
508 if (mode & S_IWUGO)
509 *pace_flags |= SET_FILE_WRITE_RIGHTS;
510 if (mode & S_IXUGO)
511 *pace_flags |= SET_FILE_EXEC_RIGHTS;
512
513 cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n",
514 mode, *pace_flags);
515 return;
516}
517
518static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
519 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
520{
521 int i;
522 __u16 size = 0;
523 __u32 access_req = 0;
524
525 pntace->type = ACCESS_ALLOWED;
526 pntace->flags = 0x0;
527 mode_to_access_flags(nmode, bits, &access_req);
528 if (!access_req)
529 access_req = SET_MINIMUM_RIGHTS;
530 pntace->access_req = cpu_to_le32(access_req);
531
532 pntace->sid.revision = psid->revision;
533 pntace->sid.num_subauth = psid->num_subauth;
534 for (i = 0; i < NUM_AUTHS; i++)
535 pntace->sid.authority[i] = psid->authority[i];
536 for (i = 0; i < psid->num_subauth; i++)
537 pntace->sid.sub_auth[i] = psid->sub_auth[i];
538
539 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
540 pntace->size = cpu_to_le16(size);
541
542 return size;
543}
544
545
546#ifdef CONFIG_CIFS_DEBUG2
547static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
548{
549 int num_subauth;
550
551
552
553 if (le16_to_cpu(pace->size) < 16) {
554 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
555 return;
556 }
557
558 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
559 cifs_dbg(VFS, "ACL too small to parse ACE\n");
560 return;
561 }
562
563 num_subauth = pace->sid.num_subauth;
564 if (num_subauth) {
565 int i;
566 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
567 pace->sid.revision, pace->sid.num_subauth, pace->type,
568 pace->flags, le16_to_cpu(pace->size));
569 for (i = 0; i < num_subauth; ++i) {
570 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
571 i, le32_to_cpu(pace->sid.sub_auth[i]));
572 }
573
574
575
576 }
577
578 return;
579}
580#endif
581
582
583static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
584 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
585 struct cifs_fattr *fattr)
586{
587 int i;
588 int num_aces = 0;
589 int acl_size;
590 char *acl_base;
591 struct cifs_ace **ppace;
592
593
594
595 if (!pdacl) {
596
597
598 fattr->cf_mode |= S_IRWXUGO;
599 return;
600 }
601
602
603 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
604 cifs_dbg(VFS, "ACL too small to parse DACL\n");
605 return;
606 }
607
608 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
609 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
610 le32_to_cpu(pdacl->num_aces));
611
612
613
614
615 fattr->cf_mode &= ~(S_IRWXUGO);
616
617 acl_base = (char *)pdacl;
618 acl_size = sizeof(struct cifs_acl);
619
620 num_aces = le32_to_cpu(pdacl->num_aces);
621 if (num_aces > 0) {
622 umode_t user_mask = S_IRWXU;
623 umode_t group_mask = S_IRWXG;
624 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
625
626 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
627 return;
628 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
629 GFP_KERNEL);
630 if (!ppace)
631 return;
632
633 for (i = 0; i < num_aces; ++i) {
634 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
635#ifdef CONFIG_CIFS_DEBUG2
636 dump_ace(ppace[i], end_of_acl);
637#endif
638 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
639 access_flags_to_mode(ppace[i]->access_req,
640 ppace[i]->type,
641 &fattr->cf_mode,
642 &user_mask);
643 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
644 access_flags_to_mode(ppace[i]->access_req,
645 ppace[i]->type,
646 &fattr->cf_mode,
647 &group_mask);
648 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
649 access_flags_to_mode(ppace[i]->access_req,
650 ppace[i]->type,
651 &fattr->cf_mode,
652 &other_mask);
653 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
654 access_flags_to_mode(ppace[i]->access_req,
655 ppace[i]->type,
656 &fattr->cf_mode,
657 &other_mask);
658
659
660
661
662
663
664 acl_base = (char *)ppace[i];
665 acl_size = le16_to_cpu(ppace[i]->size);
666 }
667
668 kfree(ppace);
669 }
670
671 return;
672}
673
674
675static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
676 struct cifs_sid *pgrpsid, __u64 nmode)
677{
678 u16 size = 0;
679 struct cifs_acl *pnndacl;
680
681 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
682
683 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
684 pownersid, nmode, S_IRWXU);
685 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
686 pgrpsid, nmode, S_IRWXG);
687 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
688 &sid_everyone, nmode, S_IRWXO);
689
690 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
691 pndacl->num_aces = cpu_to_le32(3);
692
693 return 0;
694}
695
696
697static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
698{
699
700
701
702
703 if (end_of_acl < (char *)psid + 8) {
704 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
705 return -EINVAL;
706 }
707
708#ifdef CONFIG_CIFS_DEBUG2
709 if (psid->num_subauth) {
710 int i;
711 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
712 psid->revision, psid->num_subauth);
713
714 for (i = 0; i < psid->num_subauth; i++) {
715 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
716 i, le32_to_cpu(psid->sub_auth[i]));
717 }
718
719
720
721 cifs_dbg(FYI, "RID 0x%x\n",
722 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
723 }
724#endif
725
726 return 0;
727}
728
729
730
731static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
732 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
733{
734 int rc = 0;
735 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
736 struct cifs_acl *dacl_ptr;
737 char *end_of_acl = ((char *)pntsd) + acl_len;
738 __u32 dacloffset;
739
740 if (pntsd == NULL)
741 return -EIO;
742
743 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
744 le32_to_cpu(pntsd->osidoffset));
745 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
746 le32_to_cpu(pntsd->gsidoffset));
747 dacloffset = le32_to_cpu(pntsd->dacloffset);
748 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
749 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
750 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
751 le32_to_cpu(pntsd->gsidoffset),
752 le32_to_cpu(pntsd->sacloffset), dacloffset);
753
754 rc = parse_sid(owner_sid_ptr, end_of_acl);
755 if (rc) {
756 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
757 return rc;
758 }
759 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
760 if (rc) {
761 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
762 __func__, rc);
763 return rc;
764 }
765
766 rc = parse_sid(group_sid_ptr, end_of_acl);
767 if (rc) {
768 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
769 __func__, rc);
770 return rc;
771 }
772 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
773 if (rc) {
774 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
775 __func__, rc);
776 return rc;
777 }
778
779 if (dacloffset)
780 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
781 group_sid_ptr, fattr);
782 else
783 cifs_dbg(FYI, "no ACL\n");
784
785 return rc;
786}
787
788
789static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
790 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
791{
792 int rc = 0;
793 __u32 dacloffset;
794 __u32 ndacloffset;
795 __u32 sidsoffset;
796 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
797 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
798 struct cifs_acl *dacl_ptr = NULL;
799 struct cifs_acl *ndacl_ptr = NULL;
800
801 if (nmode != NO_CHANGE_64) {
802 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
803 le32_to_cpu(pntsd->osidoffset));
804 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
805 le32_to_cpu(pntsd->gsidoffset));
806 dacloffset = le32_to_cpu(pntsd->dacloffset);
807 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
808 ndacloffset = sizeof(struct cifs_ntsd);
809 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
810 ndacl_ptr->revision = dacl_ptr->revision;
811 ndacl_ptr->size = 0;
812 ndacl_ptr->num_aces = 0;
813
814 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
815 nmode);
816 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
817
818 copy_sec_desc(pntsd, pnntsd, sidsoffset);
819 *aclflag = CIFS_ACL_DACL;
820 } else {
821 memcpy(pnntsd, pntsd, secdesclen);
822 if (uid_valid(uid)) {
823 uid_t id;
824 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
825 le32_to_cpu(pnntsd->osidoffset));
826 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
827 GFP_KERNEL);
828 if (!nowner_sid_ptr)
829 return -ENOMEM;
830 id = from_kuid(&init_user_ns, uid);
831 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
832 if (rc) {
833 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
834 __func__, rc, id);
835 kfree(nowner_sid_ptr);
836 return rc;
837 }
838 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
839 kfree(nowner_sid_ptr);
840 *aclflag = CIFS_ACL_OWNER;
841 }
842 if (gid_valid(gid)) {
843 gid_t id;
844 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
845 le32_to_cpu(pnntsd->gsidoffset));
846 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
847 GFP_KERNEL);
848 if (!ngroup_sid_ptr)
849 return -ENOMEM;
850 id = from_kgid(&init_user_ns, gid);
851 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
852 if (rc) {
853 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
854 __func__, rc, id);
855 kfree(ngroup_sid_ptr);
856 return rc;
857 }
858 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
859 kfree(ngroup_sid_ptr);
860 *aclflag = CIFS_ACL_GROUP;
861 }
862 }
863
864 return rc;
865}
866
867struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
868 const struct cifs_fid *cifsfid, u32 *pacllen)
869{
870 struct cifs_ntsd *pntsd = NULL;
871 unsigned int xid;
872 int rc;
873 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
874
875 if (IS_ERR(tlink))
876 return ERR_CAST(tlink);
877
878 xid = get_xid();
879 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
880 pacllen);
881 free_xid(xid);
882
883 cifs_put_tlink(tlink);
884
885 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
886 if (rc)
887 return ERR_PTR(rc);
888 return pntsd;
889}
890
891static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
892 const char *path, u32 *pacllen)
893{
894 struct cifs_ntsd *pntsd = NULL;
895 int oplock = 0;
896 unsigned int xid;
897 int rc, create_options = 0;
898 struct cifs_tcon *tcon;
899 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
900 struct cifs_fid fid;
901 struct cifs_open_parms oparms;
902
903 if (IS_ERR(tlink))
904 return ERR_CAST(tlink);
905
906 tcon = tlink_tcon(tlink);
907 xid = get_xid();
908
909 if (backup_cred(cifs_sb))
910 create_options |= CREATE_OPEN_BACKUP_INTENT;
911
912 oparms.tcon = tcon;
913 oparms.cifs_sb = cifs_sb;
914 oparms.desired_access = READ_CONTROL;
915 oparms.create_options = create_options;
916 oparms.disposition = FILE_OPEN;
917 oparms.path = path;
918 oparms.fid = &fid;
919 oparms.reconnect = false;
920
921 rc = CIFS_open(xid, &oparms, &oplock, NULL);
922 if (!rc) {
923 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
924 CIFSSMBClose(xid, tcon, fid.netfid);
925 }
926
927 cifs_put_tlink(tlink);
928 free_xid(xid);
929
930 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
931 if (rc)
932 return ERR_PTR(rc);
933 return pntsd;
934}
935
936
937struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
938 struct inode *inode, const char *path,
939 u32 *pacllen)
940{
941 struct cifs_ntsd *pntsd = NULL;
942 struct cifsFileInfo *open_file = NULL;
943
944 if (inode)
945 open_file = find_readable_file(CIFS_I(inode), true);
946 if (!open_file)
947 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
948
949 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
950 cifsFileInfo_put(open_file);
951 return pntsd;
952}
953
954
955int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
956 struct inode *inode, const char *path, int aclflag)
957{
958 int oplock = 0;
959 unsigned int xid;
960 int rc, access_flags, create_options = 0;
961 struct cifs_tcon *tcon;
962 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
963 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
964 struct cifs_fid fid;
965 struct cifs_open_parms oparms;
966
967 if (IS_ERR(tlink))
968 return PTR_ERR(tlink);
969
970 tcon = tlink_tcon(tlink);
971 xid = get_xid();
972
973 if (backup_cred(cifs_sb))
974 create_options |= CREATE_OPEN_BACKUP_INTENT;
975
976 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
977 access_flags = WRITE_OWNER;
978 else
979 access_flags = WRITE_DAC;
980
981 oparms.tcon = tcon;
982 oparms.cifs_sb = cifs_sb;
983 oparms.desired_access = access_flags;
984 oparms.create_options = create_options;
985 oparms.disposition = FILE_OPEN;
986 oparms.path = path;
987 oparms.fid = &fid;
988 oparms.reconnect = false;
989
990 rc = CIFS_open(xid, &oparms, &oplock, NULL);
991 if (rc) {
992 cifs_dbg(VFS, "Unable to open file to set ACL\n");
993 goto out;
994 }
995
996 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
997 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
998
999 CIFSSMBClose(xid, tcon, fid.netfid);
1000out:
1001 free_xid(xid);
1002 cifs_put_tlink(tlink);
1003 return rc;
1004}
1005
1006
1007int
1008cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1009 struct inode *inode, const char *path,
1010 const struct cifs_fid *pfid)
1011{
1012 struct cifs_ntsd *pntsd = NULL;
1013 u32 acllen = 0;
1014 int rc = 0;
1015 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1016 struct cifs_tcon *tcon;
1017
1018 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1019
1020 if (IS_ERR(tlink))
1021 return PTR_ERR(tlink);
1022 tcon = tlink_tcon(tlink);
1023
1024 if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
1025 pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
1026 &acllen);
1027 else if (tcon->ses->server->ops->get_acl)
1028 pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1029 &acllen);
1030 else {
1031 cifs_put_tlink(tlink);
1032 return -EOPNOTSUPP;
1033 }
1034
1035 if (IS_ERR(pntsd)) {
1036 rc = PTR_ERR(pntsd);
1037 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1038 } else {
1039 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1040 kfree(pntsd);
1041 if (rc)
1042 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
1043 }
1044
1045 cifs_put_tlink(tlink);
1046
1047 return rc;
1048}
1049
1050
1051int
1052id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1053 kuid_t uid, kgid_t gid)
1054{
1055 int rc = 0;
1056 int aclflag = CIFS_ACL_DACL;
1057 __u32 secdesclen = 0;
1058 struct cifs_ntsd *pntsd = NULL;
1059 struct cifs_ntsd *pnntsd = NULL;
1060 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1061 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1062 struct cifs_tcon *tcon;
1063
1064 if (IS_ERR(tlink))
1065 return PTR_ERR(tlink);
1066 tcon = tlink_tcon(tlink);
1067
1068 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1069
1070
1071
1072 if (tcon->ses->server->ops->get_acl == NULL) {
1073 cifs_put_tlink(tlink);
1074 return -EOPNOTSUPP;
1075 }
1076
1077 pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1078 &secdesclen);
1079 if (IS_ERR(pntsd)) {
1080 rc = PTR_ERR(pntsd);
1081 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1082 cifs_put_tlink(tlink);
1083 return rc;
1084 }
1085
1086
1087
1088
1089
1090
1091
1092 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1093 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1094 if (!pnntsd) {
1095 kfree(pntsd);
1096 cifs_put_tlink(tlink);
1097 return -ENOMEM;
1098 }
1099
1100 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1101 &aclflag);
1102
1103 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1104
1105 if (tcon->ses->server->ops->set_acl == NULL)
1106 rc = -EOPNOTSUPP;
1107
1108 if (!rc) {
1109
1110 rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
1111 path, aclflag);
1112 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1113 }
1114 cifs_put_tlink(tlink);
1115
1116 kfree(pnntsd);
1117 kfree(pntsd);
1118 return rc;
1119}
1120