io_uring: don't use 'fd' for openat/openat2/statx
[linux/fpc-iii.git] / fs / cifs / cifsacl.c
blob716574aab3b6a88c823a1511569511bb6491a94a
1 /*
2 * fs/cifs/cifsacl.c
4 * Copyright (C) International Business Machines Corp., 2007,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for mapping CIFS/NTFS ACLs
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <linux/fs.h>
25 #include <linux/slab.h>
26 #include <linux/string.h>
27 #include <linux/keyctl.h>
28 #include <linux/key-type.h>
29 #include <keys/user-type.h>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsacl.h"
33 #include "cifsproto.h"
34 #include "cifs_debug.h"
36 /* security id for everyone/world system group */
37 static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
39 /* security id for Authenticated Users system group */
40 static const struct cifs_sid sid_authusers = {
41 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
43 /* S-1-22-1 Unmapped Unix users */
44 static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
45 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
47 /* S-1-22-2 Unmapped Unix groups */
48 static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
49 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
52 * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
55 /* S-1-5-88 MS NFS and Apple style UID/GID/mode */
57 /* S-1-5-88-1 Unix uid */
58 static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
59 {cpu_to_le32(88),
60 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
62 /* S-1-5-88-2 Unix gid */
63 static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
64 {cpu_to_le32(88),
65 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
67 /* S-1-5-88-3 Unix mode */
68 static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
69 {cpu_to_le32(88),
70 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
72 static const struct cred *root_cred;
74 static int
75 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
77 char *payload;
80 * If the payload is less than or equal to the size of a pointer, then
81 * an allocation here is wasteful. Just copy the data directly to the
82 * payload.value union member instead.
84 * With this however, you must check the datalen before trying to
85 * dereference payload.data!
87 if (prep->datalen <= sizeof(key->payload)) {
88 key->payload.data[0] = NULL;
89 memcpy(&key->payload, prep->data, prep->datalen);
90 } else {
91 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
92 if (!payload)
93 return -ENOMEM;
94 key->payload.data[0] = payload;
97 key->datalen = prep->datalen;
98 return 0;
101 static inline void
102 cifs_idmap_key_destroy(struct key *key)
104 if (key->datalen > sizeof(key->payload))
105 kfree(key->payload.data[0]);
108 static struct key_type cifs_idmap_key_type = {
109 .name = "cifs.idmap",
110 .instantiate = cifs_idmap_key_instantiate,
111 .destroy = cifs_idmap_key_destroy,
112 .describe = user_describe,
115 static char *
116 sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
118 int i, len;
119 unsigned int saval;
120 char *sidstr, *strptr;
121 unsigned long long id_auth_val;
123 /* 3 bytes for prefix */
124 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
125 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
126 GFP_KERNEL);
127 if (!sidstr)
128 return sidstr;
130 strptr = sidstr;
131 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
132 sidptr->revision);
133 strptr += len;
135 /* The authority field is a single 48-bit number */
136 id_auth_val = (unsigned long long)sidptr->authority[5];
137 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
138 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
139 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
140 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
141 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
144 * MS-DTYP states that if the authority is >= 2^32, then it should be
145 * expressed as a hex value.
147 if (id_auth_val <= UINT_MAX)
148 len = sprintf(strptr, "-%llu", id_auth_val);
149 else
150 len = sprintf(strptr, "-0x%llx", id_auth_val);
152 strptr += len;
154 for (i = 0; i < sidptr->num_subauth; ++i) {
155 saval = le32_to_cpu(sidptr->sub_auth[i]);
156 len = sprintf(strptr, "-%u", saval);
157 strptr += len;
160 return sidstr;
164 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
165 * the same returns zero, if they do not match returns non-zero.
167 static int
168 compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
170 int i;
171 int num_subauth, num_sat, num_saw;
173 if ((!ctsid) || (!cwsid))
174 return 1;
176 /* compare the revision */
177 if (ctsid->revision != cwsid->revision) {
178 if (ctsid->revision > cwsid->revision)
179 return 1;
180 else
181 return -1;
184 /* compare all of the six auth values */
185 for (i = 0; i < NUM_AUTHS; ++i) {
186 if (ctsid->authority[i] != cwsid->authority[i]) {
187 if (ctsid->authority[i] > cwsid->authority[i])
188 return 1;
189 else
190 return -1;
194 /* compare all of the subauth values if any */
195 num_sat = ctsid->num_subauth;
196 num_saw = cwsid->num_subauth;
197 num_subauth = num_sat < num_saw ? num_sat : num_saw;
198 if (num_subauth) {
199 for (i = 0; i < num_subauth; ++i) {
200 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
201 if (le32_to_cpu(ctsid->sub_auth[i]) >
202 le32_to_cpu(cwsid->sub_auth[i]))
203 return 1;
204 else
205 return -1;
210 return 0; /* sids compare/match */
213 static bool
214 is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
216 int i;
217 int num_subauth;
218 const struct cifs_sid *pwell_known_sid;
220 if (!psid || (puid == NULL))
221 return false;
223 num_subauth = psid->num_subauth;
225 /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
226 if (num_subauth == 2) {
227 if (is_group)
228 pwell_known_sid = &sid_unix_groups;
229 else
230 pwell_known_sid = &sid_unix_users;
231 } else if (num_subauth == 3) {
232 if (is_group)
233 pwell_known_sid = &sid_unix_NFS_groups;
234 else
235 pwell_known_sid = &sid_unix_NFS_users;
236 } else
237 return false;
239 /* compare the revision */
240 if (psid->revision != pwell_known_sid->revision)
241 return false;
243 /* compare all of the six auth values */
244 for (i = 0; i < NUM_AUTHS; ++i) {
245 if (psid->authority[i] != pwell_known_sid->authority[i]) {
246 cifs_dbg(FYI, "auth %d did not match\n", i);
247 return false;
251 if (num_subauth == 2) {
252 if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
253 return false;
255 *puid = le32_to_cpu(psid->sub_auth[1]);
256 } else /* 3 subauths, ie Windows/Mac style */ {
257 *puid = le32_to_cpu(psid->sub_auth[0]);
258 if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
259 (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
260 return false;
262 *puid = le32_to_cpu(psid->sub_auth[2]);
265 cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
266 return true; /* well known sid found, uid returned */
269 static void
270 cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
272 int i;
274 dst->revision = src->revision;
275 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
276 for (i = 0; i < NUM_AUTHS; ++i)
277 dst->authority[i] = src->authority[i];
278 for (i = 0; i < dst->num_subauth; ++i)
279 dst->sub_auth[i] = src->sub_auth[i];
282 static int
283 id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
285 int rc;
286 struct key *sidkey;
287 struct cifs_sid *ksid;
288 unsigned int ksid_size;
289 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
290 const struct cred *saved_cred;
292 rc = snprintf(desc, sizeof(desc), "%ci:%u",
293 sidtype == SIDOWNER ? 'o' : 'g', cid);
294 if (rc >= sizeof(desc))
295 return -EINVAL;
297 rc = 0;
298 saved_cred = override_creds(root_cred);
299 sidkey = request_key(&cifs_idmap_key_type, desc, "");
300 if (IS_ERR(sidkey)) {
301 rc = -EINVAL;
302 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
303 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
304 goto out_revert_creds;
305 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
306 rc = -EIO;
307 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
308 __func__, sidkey->datalen);
309 goto invalidate_key;
313 * A sid is usually too large to be embedded in payload.value, but if
314 * there are no subauthorities and the host has 8-byte pointers, then
315 * it could be.
317 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
318 (struct cifs_sid *)&sidkey->payload :
319 (struct cifs_sid *)sidkey->payload.data[0];
321 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
322 if (ksid_size > sidkey->datalen) {
323 rc = -EIO;
324 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
325 __func__, sidkey->datalen, ksid_size);
326 goto invalidate_key;
329 cifs_copy_sid(ssid, ksid);
330 out_key_put:
331 key_put(sidkey);
332 out_revert_creds:
333 revert_creds(saved_cred);
334 return rc;
336 invalidate_key:
337 key_invalidate(sidkey);
338 goto out_key_put;
341 static int
342 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
343 struct cifs_fattr *fattr, uint sidtype)
345 int rc;
346 struct key *sidkey;
347 char *sidstr;
348 const struct cred *saved_cred;
349 kuid_t fuid = cifs_sb->mnt_uid;
350 kgid_t fgid = cifs_sb->mnt_gid;
353 * If we have too many subauthorities, then something is really wrong.
354 * Just return an error.
356 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
357 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
358 __func__, psid->num_subauth);
359 return -EIO;
362 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
363 uint32_t unix_id;
364 bool is_group;
366 if (sidtype != SIDOWNER)
367 is_group = true;
368 else
369 is_group = false;
371 if (is_well_known_sid(psid, &unix_id, is_group) == false)
372 goto try_upcall_to_get_id;
374 if (is_group) {
375 kgid_t gid;
376 gid_t id;
378 id = (gid_t)unix_id;
379 gid = make_kgid(&init_user_ns, id);
380 if (gid_valid(gid)) {
381 fgid = gid;
382 goto got_valid_id;
384 } else {
385 kuid_t uid;
386 uid_t id;
388 id = (uid_t)unix_id;
389 uid = make_kuid(&init_user_ns, id);
390 if (uid_valid(uid)) {
391 fuid = uid;
392 goto got_valid_id;
395 /* If unable to find uid/gid easily from SID try via upcall */
398 try_upcall_to_get_id:
399 sidstr = sid_to_key_str(psid, sidtype);
400 if (!sidstr)
401 return -ENOMEM;
403 saved_cred = override_creds(root_cred);
404 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
405 if (IS_ERR(sidkey)) {
406 rc = -EINVAL;
407 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
408 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
409 goto out_revert_creds;
413 * FIXME: Here we assume that uid_t and gid_t are same size. It's
414 * probably a safe assumption but might be better to check based on
415 * sidtype.
417 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
418 if (sidkey->datalen != sizeof(uid_t)) {
419 rc = -EIO;
420 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
421 __func__, sidkey->datalen);
422 key_invalidate(sidkey);
423 goto out_key_put;
426 if (sidtype == SIDOWNER) {
427 kuid_t uid;
428 uid_t id;
429 memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
430 uid = make_kuid(&init_user_ns, id);
431 if (uid_valid(uid))
432 fuid = uid;
433 } else {
434 kgid_t gid;
435 gid_t id;
436 memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
437 gid = make_kgid(&init_user_ns, id);
438 if (gid_valid(gid))
439 fgid = gid;
442 out_key_put:
443 key_put(sidkey);
444 out_revert_creds:
445 revert_creds(saved_cred);
446 kfree(sidstr);
449 * Note that we return 0 here unconditionally. If the mapping
450 * fails then we just fall back to using the mnt_uid/mnt_gid.
452 got_valid_id:
453 if (sidtype == SIDOWNER)
454 fattr->cf_uid = fuid;
455 else
456 fattr->cf_gid = fgid;
457 return 0;
461 init_cifs_idmap(void)
463 struct cred *cred;
464 struct key *keyring;
465 int ret;
467 cifs_dbg(FYI, "Registering the %s key type\n",
468 cifs_idmap_key_type.name);
470 /* create an override credential set with a special thread keyring in
471 * which requests are cached
473 * this is used to prevent malicious redirections from being installed
474 * with add_key().
476 cred = prepare_kernel_cred(NULL);
477 if (!cred)
478 return -ENOMEM;
480 keyring = keyring_alloc(".cifs_idmap",
481 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
482 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
483 KEY_USR_VIEW | KEY_USR_READ,
484 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
485 if (IS_ERR(keyring)) {
486 ret = PTR_ERR(keyring);
487 goto failed_put_cred;
490 ret = register_key_type(&cifs_idmap_key_type);
491 if (ret < 0)
492 goto failed_put_key;
494 /* instruct request_key() to use this special keyring as a cache for
495 * the results it looks up */
496 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
497 cred->thread_keyring = keyring;
498 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
499 root_cred = cred;
501 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
502 return 0;
504 failed_put_key:
505 key_put(keyring);
506 failed_put_cred:
507 put_cred(cred);
508 return ret;
511 void
512 exit_cifs_idmap(void)
514 key_revoke(root_cred->thread_keyring);
515 unregister_key_type(&cifs_idmap_key_type);
516 put_cred(root_cred);
517 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
520 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
521 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
522 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
524 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
525 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
527 /* copy security descriptor control portion */
528 pnntsd->revision = pntsd->revision;
529 pnntsd->type = pntsd->type;
530 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
531 pnntsd->sacloffset = 0;
532 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
533 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
535 /* copy owner sid */
536 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
537 le32_to_cpu(pntsd->osidoffset));
538 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
539 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
541 /* copy group sid */
542 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
543 le32_to_cpu(pntsd->gsidoffset));
544 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
545 sizeof(struct cifs_sid));
546 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
548 return;
553 change posix mode to reflect permissions
554 pmode is the existing mode (we only want to overwrite part of this
555 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
557 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
558 umode_t *pbits_to_set)
560 __u32 flags = le32_to_cpu(ace_flags);
561 /* the order of ACEs is important. The canonical order is to begin with
562 DENY entries followed by ALLOW, otherwise an allow entry could be
563 encountered first, making the subsequent deny entry like "dead code"
564 which would be superflous since Windows stops when a match is made
565 for the operation you are trying to perform for your user */
567 /* For deny ACEs we change the mask so that subsequent allow access
568 control entries do not turn on the bits we are denying */
569 if (type == ACCESS_DENIED) {
570 if (flags & GENERIC_ALL)
571 *pbits_to_set &= ~S_IRWXUGO;
573 if ((flags & GENERIC_WRITE) ||
574 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
575 *pbits_to_set &= ~S_IWUGO;
576 if ((flags & GENERIC_READ) ||
577 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
578 *pbits_to_set &= ~S_IRUGO;
579 if ((flags & GENERIC_EXECUTE) ||
580 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
581 *pbits_to_set &= ~S_IXUGO;
582 return;
583 } else if (type != ACCESS_ALLOWED) {
584 cifs_dbg(VFS, "unknown access control type %d\n", type);
585 return;
587 /* else ACCESS_ALLOWED type */
589 if (flags & GENERIC_ALL) {
590 *pmode |= (S_IRWXUGO & (*pbits_to_set));
591 cifs_dbg(NOISY, "all perms\n");
592 return;
594 if ((flags & GENERIC_WRITE) ||
595 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
596 *pmode |= (S_IWUGO & (*pbits_to_set));
597 if ((flags & GENERIC_READ) ||
598 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
599 *pmode |= (S_IRUGO & (*pbits_to_set));
600 if ((flags & GENERIC_EXECUTE) ||
601 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
602 *pmode |= (S_IXUGO & (*pbits_to_set));
604 cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode);
605 return;
609 Generate access flags to reflect permissions mode is the existing mode.
610 This function is called for every ACE in the DACL whose SID matches
611 with either owner or group or everyone.
614 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
615 __u32 *pace_flags)
617 /* reset access mask */
618 *pace_flags = 0x0;
620 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
621 mode &= bits_to_use;
623 /* check for R/W/X UGO since we do not know whose flags
624 is this but we have cleared all the bits sans RWX for
625 either user or group or other as per bits_to_use */
626 if (mode & S_IRUGO)
627 *pace_flags |= SET_FILE_READ_RIGHTS;
628 if (mode & S_IWUGO)
629 *pace_flags |= SET_FILE_WRITE_RIGHTS;
630 if (mode & S_IXUGO)
631 *pace_flags |= SET_FILE_EXEC_RIGHTS;
633 cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n",
634 mode, *pace_flags);
635 return;
638 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
639 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
641 int i;
642 __u16 size = 0;
643 __u32 access_req = 0;
645 pntace->type = ACCESS_ALLOWED;
646 pntace->flags = 0x0;
647 mode_to_access_flags(nmode, bits, &access_req);
648 if (!access_req)
649 access_req = SET_MINIMUM_RIGHTS;
650 pntace->access_req = cpu_to_le32(access_req);
652 pntace->sid.revision = psid->revision;
653 pntace->sid.num_subauth = psid->num_subauth;
654 for (i = 0; i < NUM_AUTHS; i++)
655 pntace->sid.authority[i] = psid->authority[i];
656 for (i = 0; i < psid->num_subauth; i++)
657 pntace->sid.sub_auth[i] = psid->sub_auth[i];
659 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
660 pntace->size = cpu_to_le16(size);
662 return size;
666 #ifdef CONFIG_CIFS_DEBUG2
667 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
669 int num_subauth;
671 /* validate that we do not go past end of acl */
673 if (le16_to_cpu(pace->size) < 16) {
674 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
675 return;
678 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
679 cifs_dbg(VFS, "ACL too small to parse ACE\n");
680 return;
683 num_subauth = pace->sid.num_subauth;
684 if (num_subauth) {
685 int i;
686 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
687 pace->sid.revision, pace->sid.num_subauth, pace->type,
688 pace->flags, le16_to_cpu(pace->size));
689 for (i = 0; i < num_subauth; ++i) {
690 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
691 i, le32_to_cpu(pace->sid.sub_auth[i]));
694 /* BB add length check to make sure that we do not have huge
695 num auths and therefore go off the end */
698 return;
700 #endif
702 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
703 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
704 struct cifs_fattr *fattr, bool mode_from_special_sid)
706 int i;
707 int num_aces = 0;
708 int acl_size;
709 char *acl_base;
710 struct cifs_ace **ppace;
712 /* BB need to add parm so we can store the SID BB */
714 if (!pdacl) {
715 /* no DACL in the security descriptor, set
716 all the permissions for user/group/other */
717 fattr->cf_mode |= S_IRWXUGO;
718 return;
721 /* validate that we do not go past end of acl */
722 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
723 cifs_dbg(VFS, "ACL too small to parse DACL\n");
724 return;
727 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
728 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
729 le32_to_cpu(pdacl->num_aces));
731 /* reset rwx permissions for user/group/other.
732 Also, if num_aces is 0 i.e. DACL has no ACEs,
733 user/group/other have no permissions */
734 fattr->cf_mode &= ~(S_IRWXUGO);
736 acl_base = (char *)pdacl;
737 acl_size = sizeof(struct cifs_acl);
739 num_aces = le32_to_cpu(pdacl->num_aces);
740 if (num_aces > 0) {
741 umode_t user_mask = S_IRWXU;
742 umode_t group_mask = S_IRWXG;
743 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
745 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
746 return;
747 ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
748 GFP_KERNEL);
749 if (!ppace)
750 return;
752 for (i = 0; i < num_aces; ++i) {
753 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
754 #ifdef CONFIG_CIFS_DEBUG2
755 dump_ace(ppace[i], end_of_acl);
756 #endif
757 if (mode_from_special_sid &&
758 (compare_sids(&(ppace[i]->sid),
759 &sid_unix_NFS_mode) == 0)) {
761 * Full permissions are:
762 * 07777 = S_ISUID | S_ISGID | S_ISVTX |
763 * S_IRWXU | S_IRWXG | S_IRWXO
765 fattr->cf_mode &= ~07777;
766 fattr->cf_mode |=
767 le32_to_cpu(ppace[i]->sid.sub_auth[2]);
768 break;
769 } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
770 access_flags_to_mode(ppace[i]->access_req,
771 ppace[i]->type,
772 &fattr->cf_mode,
773 &user_mask);
774 else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
775 access_flags_to_mode(ppace[i]->access_req,
776 ppace[i]->type,
777 &fattr->cf_mode,
778 &group_mask);
779 else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
780 access_flags_to_mode(ppace[i]->access_req,
781 ppace[i]->type,
782 &fattr->cf_mode,
783 &other_mask);
784 else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
785 access_flags_to_mode(ppace[i]->access_req,
786 ppace[i]->type,
787 &fattr->cf_mode,
788 &other_mask);
791 /* memcpy((void *)(&(cifscred->aces[i])),
792 (void *)ppace[i],
793 sizeof(struct cifs_ace)); */
795 acl_base = (char *)ppace[i];
796 acl_size = le16_to_cpu(ppace[i]->size);
799 kfree(ppace);
802 return;
805 unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
807 int i;
808 unsigned int ace_size = 20;
810 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
811 pntace->flags = 0x0;
812 pntace->access_req = cpu_to_le32(GENERIC_ALL);
813 pntace->sid.num_subauth = 1;
814 pntace->sid.revision = 1;
815 for (i = 0; i < NUM_AUTHS; i++)
816 pntace->sid.authority[i] = sid_authusers.authority[i];
818 pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
820 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
821 pntace->size = cpu_to_le16(ace_size);
822 return ace_size;
826 * Fill in the special SID based on the mode. See
827 * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
829 unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
831 int i;
832 unsigned int ace_size = 28;
834 pntace->type = ACCESS_DENIED_ACE_TYPE;
835 pntace->flags = 0x0;
836 pntace->access_req = 0;
837 pntace->sid.num_subauth = 3;
838 pntace->sid.revision = 1;
839 for (i = 0; i < NUM_AUTHS; i++)
840 pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
842 pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
843 pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
844 pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
846 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
847 pntace->size = cpu_to_le16(ace_size);
848 return ace_size;
851 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
852 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
854 u16 size = 0;
855 u32 num_aces = 0;
856 struct cifs_acl *pnndacl;
858 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
860 if (modefromsid) {
861 struct cifs_ace *pntace =
862 (struct cifs_ace *)((char *)pnndacl + size);
864 size += setup_special_mode_ACE(pntace, nmode);
865 num_aces++;
868 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
869 pownersid, nmode, S_IRWXU);
870 num_aces++;
871 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
872 pgrpsid, nmode, S_IRWXG);
873 num_aces++;
874 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
875 &sid_everyone, nmode, S_IRWXO);
876 num_aces++;
878 pndacl->num_aces = cpu_to_le32(num_aces);
879 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
881 return 0;
885 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
887 /* BB need to add parm so we can store the SID BB */
889 /* validate that we do not go past end of ACL - sid must be at least 8
890 bytes long (assuming no sub-auths - e.g. the null SID */
891 if (end_of_acl < (char *)psid + 8) {
892 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
893 return -EINVAL;
896 #ifdef CONFIG_CIFS_DEBUG2
897 if (psid->num_subauth) {
898 int i;
899 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
900 psid->revision, psid->num_subauth);
902 for (i = 0; i < psid->num_subauth; i++) {
903 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
904 i, le32_to_cpu(psid->sub_auth[i]));
907 /* BB add length check to make sure that we do not have huge
908 num auths and therefore go off the end */
909 cifs_dbg(FYI, "RID 0x%x\n",
910 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
912 #endif
914 return 0;
918 /* Convert CIFS ACL to POSIX form */
919 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
920 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
921 bool get_mode_from_special_sid)
923 int rc = 0;
924 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
925 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
926 char *end_of_acl = ((char *)pntsd) + acl_len;
927 __u32 dacloffset;
929 if (pntsd == NULL)
930 return -EIO;
932 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
933 le32_to_cpu(pntsd->osidoffset));
934 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
935 le32_to_cpu(pntsd->gsidoffset));
936 dacloffset = le32_to_cpu(pntsd->dacloffset);
937 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
938 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
939 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
940 le32_to_cpu(pntsd->gsidoffset),
941 le32_to_cpu(pntsd->sacloffset), dacloffset);
942 /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
943 rc = parse_sid(owner_sid_ptr, end_of_acl);
944 if (rc) {
945 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
946 return rc;
948 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
949 if (rc) {
950 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
951 __func__, rc);
952 return rc;
955 rc = parse_sid(group_sid_ptr, end_of_acl);
956 if (rc) {
957 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
958 __func__, rc);
959 return rc;
961 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
962 if (rc) {
963 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
964 __func__, rc);
965 return rc;
968 if (dacloffset)
969 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
970 group_sid_ptr, fattr, get_mode_from_special_sid);
971 else
972 cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
974 return rc;
977 /* Convert permission bits from mode to equivalent CIFS ACL */
978 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
979 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
980 bool mode_from_sid, int *aclflag)
982 int rc = 0;
983 __u32 dacloffset;
984 __u32 ndacloffset;
985 __u32 sidsoffset;
986 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
987 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
988 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
989 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
991 if (nmode != NO_CHANGE_64) { /* chmod */
992 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
993 le32_to_cpu(pntsd->osidoffset));
994 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
995 le32_to_cpu(pntsd->gsidoffset));
996 dacloffset = le32_to_cpu(pntsd->dacloffset);
997 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
998 ndacloffset = sizeof(struct cifs_ntsd);
999 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1000 ndacl_ptr->revision = dacl_ptr->revision;
1001 ndacl_ptr->size = 0;
1002 ndacl_ptr->num_aces = 0;
1004 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
1005 nmode, mode_from_sid);
1006 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1007 /* copy sec desc control portion & owner and group sids */
1008 copy_sec_desc(pntsd, pnntsd, sidsoffset);
1009 *aclflag = CIFS_ACL_DACL;
1010 } else {
1011 memcpy(pnntsd, pntsd, secdesclen);
1012 if (uid_valid(uid)) { /* chown */
1013 uid_t id;
1014 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1015 le32_to_cpu(pnntsd->osidoffset));
1016 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1017 GFP_KERNEL);
1018 if (!nowner_sid_ptr)
1019 return -ENOMEM;
1020 id = from_kuid(&init_user_ns, uid);
1021 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
1022 if (rc) {
1023 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
1024 __func__, rc, id);
1025 kfree(nowner_sid_ptr);
1026 return rc;
1028 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
1029 kfree(nowner_sid_ptr);
1030 *aclflag = CIFS_ACL_OWNER;
1032 if (gid_valid(gid)) { /* chgrp */
1033 gid_t id;
1034 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1035 le32_to_cpu(pnntsd->gsidoffset));
1036 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1037 GFP_KERNEL);
1038 if (!ngroup_sid_ptr)
1039 return -ENOMEM;
1040 id = from_kgid(&init_user_ns, gid);
1041 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
1042 if (rc) {
1043 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
1044 __func__, rc, id);
1045 kfree(ngroup_sid_ptr);
1046 return rc;
1048 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
1049 kfree(ngroup_sid_ptr);
1050 *aclflag = CIFS_ACL_GROUP;
1054 return rc;
1057 struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1058 const struct cifs_fid *cifsfid, u32 *pacllen)
1060 struct cifs_ntsd *pntsd = NULL;
1061 unsigned int xid;
1062 int rc;
1063 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1065 if (IS_ERR(tlink))
1066 return ERR_CAST(tlink);
1068 xid = get_xid();
1069 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1070 pacllen);
1071 free_xid(xid);
1073 cifs_put_tlink(tlink);
1075 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1076 if (rc)
1077 return ERR_PTR(rc);
1078 return pntsd;
1081 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1082 const char *path, u32 *pacllen)
1084 struct cifs_ntsd *pntsd = NULL;
1085 int oplock = 0;
1086 unsigned int xid;
1087 int rc;
1088 struct cifs_tcon *tcon;
1089 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1090 struct cifs_fid fid;
1091 struct cifs_open_parms oparms;
1093 if (IS_ERR(tlink))
1094 return ERR_CAST(tlink);
1096 tcon = tlink_tcon(tlink);
1097 xid = get_xid();
1099 oparms.tcon = tcon;
1100 oparms.cifs_sb = cifs_sb;
1101 oparms.desired_access = READ_CONTROL;
1102 oparms.create_options = cifs_create_options(cifs_sb, 0);
1103 oparms.disposition = FILE_OPEN;
1104 oparms.path = path;
1105 oparms.fid = &fid;
1106 oparms.reconnect = false;
1108 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1109 if (!rc) {
1110 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1111 CIFSSMBClose(xid, tcon, fid.netfid);
1114 cifs_put_tlink(tlink);
1115 free_xid(xid);
1117 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1118 if (rc)
1119 return ERR_PTR(rc);
1120 return pntsd;
1123 /* Retrieve an ACL from the server */
1124 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1125 struct inode *inode, const char *path,
1126 u32 *pacllen)
1128 struct cifs_ntsd *pntsd = NULL;
1129 struct cifsFileInfo *open_file = NULL;
1131 if (inode)
1132 open_file = find_readable_file(CIFS_I(inode), true);
1133 if (!open_file)
1134 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1136 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
1137 cifsFileInfo_put(open_file);
1138 return pntsd;
1141 /* Set an ACL on the server */
1142 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1143 struct inode *inode, const char *path, int aclflag)
1145 int oplock = 0;
1146 unsigned int xid;
1147 int rc, access_flags;
1148 struct cifs_tcon *tcon;
1149 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1150 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1151 struct cifs_fid fid;
1152 struct cifs_open_parms oparms;
1154 if (IS_ERR(tlink))
1155 return PTR_ERR(tlink);
1157 tcon = tlink_tcon(tlink);
1158 xid = get_xid();
1160 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1161 access_flags = WRITE_OWNER;
1162 else
1163 access_flags = WRITE_DAC;
1165 oparms.tcon = tcon;
1166 oparms.cifs_sb = cifs_sb;
1167 oparms.desired_access = access_flags;
1168 oparms.create_options = cifs_create_options(cifs_sb, 0);
1169 oparms.disposition = FILE_OPEN;
1170 oparms.path = path;
1171 oparms.fid = &fid;
1172 oparms.reconnect = false;
1174 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1175 if (rc) {
1176 cifs_dbg(VFS, "Unable to open file to set ACL\n");
1177 goto out;
1180 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
1181 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
1183 CIFSSMBClose(xid, tcon, fid.netfid);
1184 out:
1185 free_xid(xid);
1186 cifs_put_tlink(tlink);
1187 return rc;
1190 /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
1192 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1193 struct inode *inode, bool mode_from_special_sid,
1194 const char *path, const struct cifs_fid *pfid)
1196 struct cifs_ntsd *pntsd = NULL;
1197 u32 acllen = 0;
1198 int rc = 0;
1199 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1200 struct smb_version_operations *ops;
1202 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1204 if (IS_ERR(tlink))
1205 return PTR_ERR(tlink);
1207 ops = tlink_tcon(tlink)->ses->server->ops;
1209 if (pfid && (ops->get_acl_by_fid))
1210 pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
1211 else if (ops->get_acl)
1212 pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
1213 else {
1214 cifs_put_tlink(tlink);
1215 return -EOPNOTSUPP;
1217 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1218 if (IS_ERR(pntsd)) {
1219 rc = PTR_ERR(pntsd);
1220 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1221 } else if (mode_from_special_sid) {
1222 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
1223 } else {
1224 /* get approximated mode from ACL */
1225 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
1226 kfree(pntsd);
1227 if (rc)
1228 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
1231 cifs_put_tlink(tlink);
1233 return rc;
1236 /* Convert mode bits to an ACL so we can update the ACL on the server */
1238 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1239 kuid_t uid, kgid_t gid)
1241 int rc = 0;
1242 int aclflag = CIFS_ACL_DACL; /* default flag to set */
1243 __u32 secdesclen = 0;
1244 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1245 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1246 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1247 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1248 struct smb_version_operations *ops;
1249 bool mode_from_sid;
1251 if (IS_ERR(tlink))
1252 return PTR_ERR(tlink);
1254 ops = tlink_tcon(tlink)->ses->server->ops;
1256 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1258 /* Get the security descriptor */
1260 if (ops->get_acl == NULL) {
1261 cifs_put_tlink(tlink);
1262 return -EOPNOTSUPP;
1265 pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
1266 if (IS_ERR(pntsd)) {
1267 rc = PTR_ERR(pntsd);
1268 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1269 cifs_put_tlink(tlink);
1270 return rc;
1274 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1275 * as chmod disables ACEs and set the security descriptor. Allocate
1276 * memory for the smb header, set security descriptor request security
1277 * descriptor parameters, and secuirty descriptor itself
1279 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1280 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1281 if (!pnntsd) {
1282 kfree(pntsd);
1283 cifs_put_tlink(tlink);
1284 return -ENOMEM;
1287 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
1288 mode_from_sid = true;
1289 else
1290 mode_from_sid = false;
1292 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1293 mode_from_sid, &aclflag);
1295 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1297 if (ops->set_acl == NULL)
1298 rc = -EOPNOTSUPP;
1300 if (!rc) {
1301 /* Set the security descriptor */
1302 rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
1303 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1305 cifs_put_tlink(tlink);
1307 kfree(pnntsd);
1308 kfree(pntsd);
1309 return rc;