Merge branch 'tip/perf/urgent-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.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
b1a6dc21 45static const struct cred *root_cred;
9409ae58 46
4d79dba0 47static int
cf7f601c 48cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
4d79dba0
SP
49{
50 char *payload;
51
41a9f1f6
JL
52 /*
53 * If the payload is less than or equal to the size of a pointer, then
54 * an allocation here is wasteful. Just copy the data directly to the
55 * payload.value union member instead.
56 *
57 * With this however, you must check the datalen before trying to
58 * dereference payload.data!
59 */
1f630680 60 if (prep->datalen <= sizeof(key->payload)) {
41a9f1f6
JL
61 key->payload.value = 0;
62 memcpy(&key->payload.value, prep->data, prep->datalen);
63 key->datalen = prep->datalen;
64 return 0;
65 }
cf7f601c 66 payload = kmalloc(prep->datalen, GFP_KERNEL);
4d79dba0
SP
67 if (!payload)
68 return -ENOMEM;
69
cf7f601c 70 memcpy(payload, prep->data, prep->datalen);
4d79dba0 71 key->payload.data = payload;
cf7f601c 72 key->datalen = prep->datalen;
4d79dba0
SP
73 return 0;
74}
75
76static inline void
77cifs_idmap_key_destroy(struct key *key)
78{
1f630680 79 if (key->datalen > sizeof(key->payload))
41a9f1f6 80 kfree(key->payload.data);
4d79dba0
SP
81}
82
b1a6dc21 83static struct key_type cifs_idmap_key_type = {
c4aca0c0 84 .name = "cifs.idmap",
4d79dba0
SP
85 .instantiate = cifs_idmap_key_instantiate,
86 .destroy = cifs_idmap_key_destroy,
87 .describe = user_describe,
88 .match = user_match,
89};
90
faa65f07
JL
91static char *
92sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
9409ae58 93{
faa65f07 94 int i, len;
ee13b2ba 95 unsigned int saval;
faa65f07 96 char *sidstr, *strptr;
193cdd8a 97 unsigned long long id_auth_val;
9409ae58 98
faa65f07
JL
99 /* 3 bytes for prefix */
100 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
101 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
102 GFP_KERNEL);
103 if (!sidstr)
104 return sidstr;
9409ae58 105
faa65f07
JL
106 strptr = sidstr;
107 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
108 sidptr->revision);
109 strptr += len;
9409ae58 110
193cdd8a
JL
111 /* The authority field is a single 48-bit number */
112 id_auth_val = (unsigned long long)sidptr->authority[5];
113 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
114 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
115 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
116 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
117 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
118
119 /*
120 * MS-DTYP states that if the authority is >= 2^32, then it should be
121 * expressed as a hex value.
122 */
123 if (id_auth_val <= UINT_MAX)
124 len = sprintf(strptr, "-%llu", id_auth_val);
125 else
126 len = sprintf(strptr, "-0x%llx", id_auth_val);
127
128 strptr += len;
9409ae58
SP
129
130 for (i = 0; i < sidptr->num_subauth; ++i) {
131 saval = le32_to_cpu(sidptr->sub_auth[i]);
faa65f07
JL
132 len = sprintf(strptr, "-%u", saval);
133 strptr += len;
9409ae58 134 }
faa65f07
JL
135
136 return sidstr;
9409ae58
SP
137}
138
436bb435
JL
139/*
140 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
141 * the same returns zero, if they do not match returns non-zero.
142 */
143static int
144compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
145{
146 int i;
147 int num_subauth, num_sat, num_saw;
148
149 if ((!ctsid) || (!cwsid))
150 return 1;
151
152 /* compare the revision */
153 if (ctsid->revision != cwsid->revision) {
154 if (ctsid->revision > cwsid->revision)
155 return 1;
156 else
157 return -1;
158 }
159
160 /* compare all of the six auth values */
161 for (i = 0; i < NUM_AUTHS; ++i) {
162 if (ctsid->authority[i] != cwsid->authority[i]) {
163 if (ctsid->authority[i] > cwsid->authority[i])
164 return 1;
165 else
166 return -1;
167 }
168 }
169
170 /* compare all of the subauth values if any */
171 num_sat = ctsid->num_subauth;
172 num_saw = cwsid->num_subauth;
173 num_subauth = num_sat < num_saw ? num_sat : num_saw;
174 if (num_subauth) {
175 for (i = 0; i < num_subauth; ++i) {
176 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
177 if (le32_to_cpu(ctsid->sub_auth[i]) >
178 le32_to_cpu(cwsid->sub_auth[i]))
179 return 1;
180 else
181 return -1;
182 }
183 }
184 }
185
186 return 0; /* sids compare/match */
187}
188
36960e44
JL
189static void
190cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
191{
36f87ee7
JL
192 int i;
193
194 dst->revision = src->revision;
30c9d6cc 195 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
36f87ee7
JL
196 for (i = 0; i < NUM_AUTHS; ++i)
197 dst->authority[i] = src->authority[i];
198 for (i = 0; i < dst->num_subauth; ++i)
199 dst->sub_auth[i] = src->sub_auth[i];
36960e44
JL
200}
201
9409ae58 202static int
faa65f07 203id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
9409ae58 204{
faa65f07 205 int rc;
21fed0d5 206 struct key *sidkey;
2ae03025
JL
207 struct cifs_sid *ksid;
208 unsigned int ksid_size;
faa65f07 209 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
21fed0d5 210 const struct cred *saved_cred;
21fed0d5 211
faa65f07
JL
212 rc = snprintf(desc, sizeof(desc), "%ci:%u",
213 sidtype == SIDOWNER ? 'o' : 'g', cid);
214 if (rc >= sizeof(desc))
215 return -EINVAL;
21fed0d5 216
faa65f07
JL
217 rc = 0;
218 saved_cred = override_creds(root_cred);
219 sidkey = request_key(&cifs_idmap_key_type, desc, "");
220 if (IS_ERR(sidkey)) {
21fed0d5 221 rc = -EINVAL;
faa65f07
JL
222 cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
223 sidtype == SIDOWNER ? 'u' : 'g', cid);
224 goto out_revert_creds;
225 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
226 rc = -EIO;
227 cFYI(1, "%s: Downcall contained malformed key "
228 "(datalen=%hu)", __func__, sidkey->datalen);
2ae03025 229 goto invalidate_key;
21fed0d5 230 }
2ae03025 231
1f630680
JL
232 /*
233 * A sid is usually too large to be embedded in payload.value, but if
234 * there are no subauthorities and the host has 8-byte pointers, then
235 * it could be.
236 */
237 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
238 (struct cifs_sid *)&sidkey->payload.value :
239 (struct cifs_sid *)sidkey->payload.data;
240
2ae03025
JL
241 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
242 if (ksid_size > sidkey->datalen) {
243 rc = -EIO;
244 cFYI(1, "%s: Downcall contained malformed key (datalen=%hu, "
245 "ksid_size=%u)", __func__, sidkey->datalen, ksid_size);
246 goto invalidate_key;
247 }
1f630680 248
2ae03025 249 cifs_copy_sid(ssid, ksid);
faa65f07
JL
250out_key_put:
251 key_put(sidkey);
252out_revert_creds:
253 revert_creds(saved_cred);
21fed0d5 254 return rc;
2ae03025
JL
255
256invalidate_key:
257 key_invalidate(sidkey);
258 goto out_key_put;
21fed0d5
SP
259}
260
9409ae58
SP
261static int
262sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
263 struct cifs_fattr *fattr, uint sidtype)
264{
265 int rc;
faa65f07
JL
266 struct key *sidkey;
267 char *sidstr;
9409ae58 268 const struct cred *saved_cred;
8abf2775
EB
269 kuid_t fuid = cifs_sb->mnt_uid;
270 kgid_t fgid = cifs_sb->mnt_gid;
9409ae58
SP
271
272 /*
faa65f07
JL
273 * If we have too many subauthorities, then something is really wrong.
274 * Just return an error.
9409ae58 275 */
faa65f07
JL
276 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
277 cFYI(1, "%s: %u subauthorities is too many!", __func__,
278 psid->num_subauth);
279 return -EIO;
9409ae58
SP
280 }
281
faa65f07
JL
282 sidstr = sid_to_key_str(psid, sidtype);
283 if (!sidstr)
284 return -ENOMEM;
285
286 saved_cred = override_creds(root_cred);
287 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
288 if (IS_ERR(sidkey)) {
289 rc = -EINVAL;
290 cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
291 sidtype == SIDOWNER ? 'u' : 'g');
292 goto out_revert_creds;
293 }
294
295 /*
296 * FIXME: Here we assume that uid_t and gid_t are same size. It's
297 * probably a safe assumption but might be better to check based on
298 * sidtype.
299 */
355958f2 300 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
41a9f1f6 301 if (sidkey->datalen != sizeof(uid_t)) {
faa65f07
JL
302 rc = -EIO;
303 cFYI(1, "%s: Downcall contained malformed key "
304 "(datalen=%hu)", __func__, sidkey->datalen);
2ae03025 305 key_invalidate(sidkey);
faa65f07 306 goto out_key_put;
9409ae58
SP
307 }
308
8abf2775
EB
309 if (sidtype == SIDOWNER) {
310 kuid_t uid;
311 uid_t id;
312 memcpy(&id, &sidkey->payload.value, sizeof(uid_t));
313 uid = make_kuid(&init_user_ns, id);
314 if (uid_valid(uid))
315 fuid = uid;
316 } else {
317 kgid_t gid;
318 gid_t id;
319 memcpy(&id, &sidkey->payload.value, sizeof(gid_t));
320 gid = make_kgid(&init_user_ns, id);
321 if (gid_valid(gid))
322 fgid = gid;
323 }
faa65f07
JL
324
325out_key_put:
326 key_put(sidkey);
327out_revert_creds:
328 revert_creds(saved_cred);
329 kfree(sidstr);
9409ae58 330
faa65f07
JL
331 /*
332 * Note that we return 0 here unconditionally. If the mapping
333 * fails then we just fall back to using the mnt_uid/mnt_gid.
334 */
335 if (sidtype == SIDOWNER)
336 fattr->cf_uid = fuid;
337 else
338 fattr->cf_gid = fgid;
9409ae58
SP
339 return 0;
340}
341
4d79dba0
SP
342int
343init_cifs_idmap(void)
344{
345 struct cred *cred;
346 struct key *keyring;
347 int ret;
348
ac3aa2f8 349 cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
4d79dba0
SP
350
351 /* create an override credential set with a special thread keyring in
352 * which requests are cached
353 *
354 * this is used to prevent malicious redirections from being installed
355 * with add_key().
356 */
357 cred = prepare_kernel_cred(NULL);
358 if (!cred)
359 return -ENOMEM;
360
8e3028b9
EB
361 keyring = keyring_alloc(".cifs_idmap",
362 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
f8aa23a5
DH
363 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
364 KEY_USR_VIEW | KEY_USR_READ,
365 KEY_ALLOC_NOT_IN_QUOTA, NULL);
4d79dba0
SP
366 if (IS_ERR(keyring)) {
367 ret = PTR_ERR(keyring);
368 goto failed_put_cred;
369 }
370
4d79dba0
SP
371 ret = register_key_type(&cifs_idmap_key_type);
372 if (ret < 0)
373 goto failed_put_key;
374
375 /* instruct request_key() to use this special keyring as a cache for
376 * the results it looks up */
700920eb 377 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
4d79dba0
SP
378 cred->thread_keyring = keyring;
379 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
380 root_cred = cred;
381
ac3aa2f8 382 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
4d79dba0
SP
383 return 0;
384
385failed_put_key:
386 key_put(keyring);
387failed_put_cred:
388 put_cred(cred);
389 return ret;
390}
391
392void
393exit_cifs_idmap(void)
394{
395 key_revoke(root_cred->thread_keyring);
396 unregister_key_type(&cifs_idmap_key_type);
397 put_cred(root_cred);
ac3aa2f8 398 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
4d79dba0
SP
399}
400
97837582
SF
401/* copy ntsd, owner sid, and group sid from a security descriptor to another */
402static void copy_sec_desc(const struct cifs_ntsd *pntsd,
403 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
404{
97837582
SF
405 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
406 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
407
408 /* copy security descriptor control portion */
409 pnntsd->revision = pntsd->revision;
410 pnntsd->type = pntsd->type;
411 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
412 pnntsd->sacloffset = 0;
413 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
414 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
415
416 /* copy owner sid */
417 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
418 le32_to_cpu(pntsd->osidoffset));
419 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
36960e44 420 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
97837582
SF
421
422 /* copy group sid */
423 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
424 le32_to_cpu(pntsd->gsidoffset));
425 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
426 sizeof(struct cifs_sid));
36960e44 427 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
97837582
SF
428
429 return;
430}
431
432
630f3f0c
SF
433/*
434 change posix mode to reflect permissions
435 pmode is the existing mode (we only want to overwrite part of this
436 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
437*/
9b5e6857 438static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
15b03959 439 umode_t *pbits_to_set)
630f3f0c 440{
9b5e6857 441 __u32 flags = le32_to_cpu(ace_flags);
15b03959 442 /* the order of ACEs is important. The canonical order is to begin with
ce06c9f0 443 DENY entries followed by ALLOW, otherwise an allow entry could be
15b03959 444 encountered first, making the subsequent deny entry like "dead code"
ce06c9f0 445 which would be superflous since Windows stops when a match is made
15b03959
SF
446 for the operation you are trying to perform for your user */
447
448 /* For deny ACEs we change the mask so that subsequent allow access
449 control entries do not turn on the bits we are denying */
450 if (type == ACCESS_DENIED) {
ad7a2926 451 if (flags & GENERIC_ALL)
15b03959 452 *pbits_to_set &= ~S_IRWXUGO;
ad7a2926 453
9b5e6857
AV
454 if ((flags & GENERIC_WRITE) ||
455 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 456 *pbits_to_set &= ~S_IWUGO;
9b5e6857
AV
457 if ((flags & GENERIC_READ) ||
458 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 459 *pbits_to_set &= ~S_IRUGO;
9b5e6857
AV
460 if ((flags & GENERIC_EXECUTE) ||
461 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959
SF
462 *pbits_to_set &= ~S_IXUGO;
463 return;
464 } else if (type != ACCESS_ALLOWED) {
b6b38f70 465 cERROR(1, "unknown access control type %d", type);
15b03959
SF
466 return;
467 }
468 /* else ACCESS_ALLOWED type */
630f3f0c 469
9b5e6857 470 if (flags & GENERIC_ALL) {
15b03959 471 *pmode |= (S_IRWXUGO & (*pbits_to_set));
b6b38f70 472 cFYI(DBG2, "all perms");
d61e5808
SF
473 return;
474 }
9b5e6857
AV
475 if ((flags & GENERIC_WRITE) ||
476 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 477 *pmode |= (S_IWUGO & (*pbits_to_set));
9b5e6857
AV
478 if ((flags & GENERIC_READ) ||
479 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 480 *pmode |= (S_IRUGO & (*pbits_to_set));
9b5e6857
AV
481 if ((flags & GENERIC_EXECUTE) ||
482 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959 483 *pmode |= (S_IXUGO & (*pbits_to_set));
630f3f0c 484
b6b38f70 485 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
630f3f0c
SF
486 return;
487}
488
ce06c9f0
SF
489/*
490 Generate access flags to reflect permissions mode is the existing mode.
491 This function is called for every ACE in the DACL whose SID matches
492 with either owner or group or everyone.
493*/
494
495static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
496 __u32 *pace_flags)
497{
498 /* reset access mask */
499 *pace_flags = 0x0;
500
501 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
502 mode &= bits_to_use;
503
504 /* check for R/W/X UGO since we do not know whose flags
505 is this but we have cleared all the bits sans RWX for
506 either user or group or other as per bits_to_use */
507 if (mode & S_IRUGO)
508 *pace_flags |= SET_FILE_READ_RIGHTS;
509 if (mode & S_IWUGO)
510 *pace_flags |= SET_FILE_WRITE_RIGHTS;
511 if (mode & S_IXUGO)
512 *pace_flags |= SET_FILE_EXEC_RIGHTS;
513
b6b38f70 514 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
ce06c9f0
SF
515 return;
516}
517
2b210adc 518static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
97837582
SF
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;
852e2295 534 for (i = 0; i < NUM_AUTHS; i++)
97837582
SF
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
ef571cad 542 return size;
97837582
SF
543}
544
297647c2 545
953f8681
SF
546#ifdef CONFIG_CIFS_DEBUG2
547static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
d0d66c44 548{
d0d66c44 549 int num_subauth;
d0d66c44
SP
550
551 /* validate that we do not go past end of acl */
297647c2 552
44093ca2 553 if (le16_to_cpu(pace->size) < 16) {
b6b38f70 554 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
44093ca2
SF
555 return;
556 }
557
558 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
b6b38f70 559 cERROR(1, "ACL too small to parse ACE");
d0d66c44 560 return;
44093ca2 561 }
d0d66c44 562
44093ca2 563 num_subauth = pace->sid.num_subauth;
d0d66c44 564 if (num_subauth) {
8f18c131 565 int i;
b6b38f70 566 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
44093ca2 567 pace->sid.revision, pace->sid.num_subauth, pace->type,
b6b38f70 568 pace->flags, le16_to_cpu(pace->size));
d12fd121 569 for (i = 0; i < num_subauth; ++i) {
b6b38f70
JP
570 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
571 le32_to_cpu(pace->sid.sub_auth[i]));
d12fd121
SF
572 }
573
574 /* BB add length check to make sure that we do not have huge
575 num auths and therefore go off the end */
d12fd121
SF
576 }
577
578 return;
579}
953f8681 580#endif
d12fd121 581
d0d66c44 582
a750e77c 583static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
d61e5808 584 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
0b8f18e3 585 struct cifs_fattr *fattr)
d0d66c44
SP
586{
587 int i;
588 int num_aces = 0;
589 int acl_size;
590 char *acl_base;
d0d66c44
SP
591 struct cifs_ace **ppace;
592
593 /* BB need to add parm so we can store the SID BB */
594
2b83457b
SF
595 if (!pdacl) {
596 /* no DACL in the security descriptor, set
597 all the permissions for user/group/other */
0b8f18e3 598 fattr->cf_mode |= S_IRWXUGO;
2b83457b
SF
599 return;
600 }
601
d0d66c44 602 /* validate that we do not go past end of acl */
af6f4612 603 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
b6b38f70 604 cERROR(1, "ACL too small to parse DACL");
d0d66c44
SP
605 return;
606 }
607
b6b38f70 608 cFYI(DBG2, "DACL revision %d size %d num aces %d",
af6f4612 609 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
b6b38f70 610 le32_to_cpu(pdacl->num_aces));
d0d66c44 611
7505e052
SF
612 /* reset rwx permissions for user/group/other.
613 Also, if num_aces is 0 i.e. DACL has no ACEs,
614 user/group/other have no permissions */
0b8f18e3 615 fattr->cf_mode &= ~(S_IRWXUGO);
7505e052 616
d0d66c44
SP
617 acl_base = (char *)pdacl;
618 acl_size = sizeof(struct cifs_acl);
619
adbc0358 620 num_aces = le32_to_cpu(pdacl->num_aces);
a5ff3769 621 if (num_aces > 0) {
15b03959
SF
622 umode_t user_mask = S_IRWXU;
623 umode_t group_mask = S_IRWXG;
2fbc2f17 624 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
15b03959 625
7250170c
DC
626 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
627 return;
d0d66c44
SP
628 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
629 GFP_KERNEL);
8132b65b
SF
630 if (!ppace) {
631 cERROR(1, "DACL memory allocation error");
632 return;
633 }
d0d66c44 634
d0d66c44 635 for (i = 0; i < num_aces; ++i) {
44093ca2 636 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
953f8681
SF
637#ifdef CONFIG_CIFS_DEBUG2
638 dump_ace(ppace[i], end_of_acl);
639#endif
9409ae58 640 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
e01b6400 641 access_flags_to_mode(ppace[i]->access_req,
15b03959 642 ppace[i]->type,
0b8f18e3 643 &fattr->cf_mode,
15b03959 644 &user_mask);
9409ae58 645 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
e01b6400 646 access_flags_to_mode(ppace[i]->access_req,
15b03959 647 ppace[i]->type,
0b8f18e3 648 &fattr->cf_mode,
15b03959 649 &group_mask);
9409ae58 650 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
e01b6400 651 access_flags_to_mode(ppace[i]->access_req,
15b03959 652 ppace[i]->type,
0b8f18e3 653 &fattr->cf_mode,
15b03959 654 &other_mask);
9409ae58 655 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
2fbc2f17
SP
656 access_flags_to_mode(ppace[i]->access_req,
657 ppace[i]->type,
658 &fattr->cf_mode,
659 &other_mask);
660
e01b6400 661
44093ca2 662/* memcpy((void *)(&(cifscred->aces[i])),
d12fd121
SF
663 (void *)ppace[i],
664 sizeof(struct cifs_ace)); */
d0d66c44 665
44093ca2
SF
666 acl_base = (char *)ppace[i];
667 acl_size = le16_to_cpu(ppace[i]->size);
d0d66c44
SP
668 }
669
670 kfree(ppace);
d0d66c44
SP
671 }
672
673 return;
674}
675
bcb02034 676
97837582
SF
677static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
678 struct cifs_sid *pgrpsid, __u64 nmode)
679{
2b210adc 680 u16 size = 0;
97837582
SF
681 struct cifs_acl *pnndacl;
682
683 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
684
685 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
686 pownersid, nmode, S_IRWXU);
687 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
688 pgrpsid, nmode, S_IRWXG);
689 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
690 &sid_everyone, nmode, S_IRWXO);
691
692 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
d9f382ef 693 pndacl->num_aces = cpu_to_le32(3);
97837582 694
ef571cad 695 return 0;
97837582
SF
696}
697
698
bcb02034
SF
699static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
700{
701 /* BB need to add parm so we can store the SID BB */
702
b9c7a2bb
SF
703 /* validate that we do not go past end of ACL - sid must be at least 8
704 bytes long (assuming no sub-auths - e.g. the null SID */
705 if (end_of_acl < (char *)psid + 8) {
b6b38f70 706 cERROR(1, "ACL too small to parse SID %p", psid);
bcb02034
SF
707 return -EINVAL;
708 }
d0d66c44 709
bcb02034 710#ifdef CONFIG_CIFS_DEBUG2
fc03d8a5 711 if (psid->num_subauth) {
8f18c131 712 int i;
b6b38f70
JP
713 cFYI(1, "SID revision %d num_auth %d",
714 psid->revision, psid->num_subauth);
bcb02034 715
af6f4612 716 for (i = 0; i < psid->num_subauth; i++) {
b6b38f70
JP
717 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
718 le32_to_cpu(psid->sub_auth[i]));
d0d66c44
SP
719 }
720
d12fd121 721 /* BB add length check to make sure that we do not have huge
d0d66c44 722 num auths and therefore go off the end */
b6b38f70
JP
723 cFYI(1, "RID 0x%x",
724 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
d0d66c44 725 }
fc03d8a5 726#endif
d0d66c44 727
bcb02034
SF
728 return 0;
729}
730
d0d66c44 731
bcb02034 732/* Convert CIFS ACL to POSIX form */
9409ae58
SP
733static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
734 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
bcb02034 735{
9409ae58 736 int rc = 0;
bcb02034
SF
737 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
738 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
bcb02034 739 char *end_of_acl = ((char *)pntsd) + acl_len;
7505e052 740 __u32 dacloffset;
bcb02034 741
0b8f18e3 742 if (pntsd == NULL)
b9c7a2bb
SF
743 return -EIO;
744
bcb02034 745 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 746 le32_to_cpu(pntsd->osidoffset));
bcb02034 747 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 748 le32_to_cpu(pntsd->gsidoffset));
7505e052 749 dacloffset = le32_to_cpu(pntsd->dacloffset);
63d2583f 750 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
b6b38f70 751 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
bcb02034 752 "sacloffset 0x%x dacloffset 0x%x",
af6f4612
SF
753 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
754 le32_to_cpu(pntsd->gsidoffset),
b6b38f70 755 le32_to_cpu(pntsd->sacloffset), dacloffset);
b9c7a2bb 756/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
bcb02034 757 rc = parse_sid(owner_sid_ptr, end_of_acl);
9409ae58
SP
758 if (rc) {
759 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
760 return rc;
761 }
762 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
763 if (rc) {
764 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
bcb02034 765 return rc;
9409ae58 766 }
bcb02034
SF
767
768 rc = parse_sid(group_sid_ptr, end_of_acl);
9409ae58
SP
769 if (rc) {
770 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
bcb02034 771 return rc;
9409ae58
SP
772 }
773 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
774 if (rc) {
775 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
776 return rc;
777 }
bcb02034 778
7505e052
SF
779 if (dacloffset)
780 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
0b8f18e3 781 group_sid_ptr, fattr);
7505e052 782 else
b6b38f70 783 cFYI(1, "no ACL"); /* BB grant all or default perms? */
d0d66c44 784
9409ae58 785 return rc;
bcb02034 786}
b9c7a2bb 787
97837582
SF
788/* Convert permission bits from mode to equivalent CIFS ACL */
789static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
8abf2775 790 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
97837582
SF
791{
792 int rc = 0;
793 __u32 dacloffset;
794 __u32 ndacloffset;
795 __u32 sidsoffset;
796 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
a5ff3769 797 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
97837582
SF
798 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
799 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
800
a5ff3769
SP
801 if (nmode != NO_CHANGE_64) { /* chmod */
802 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 803 le32_to_cpu(pntsd->osidoffset));
a5ff3769 804 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 805 le32_to_cpu(pntsd->gsidoffset));
a5ff3769
SP
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 /* copy sec desc control portion & owner and group sids */
818 copy_sec_desc(pntsd, pnntsd, sidsoffset);
819 *aclflag = CIFS_ACL_DACL;
820 } else {
821 memcpy(pnntsd, pntsd, secdesclen);
8abf2775
EB
822 if (uid_valid(uid)) { /* chown */
823 uid_t id;
a5ff3769
SP
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;
8abf2775
EB
830 id = from_kuid(&init_user_ns, uid);
831 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
a5ff3769
SP
832 if (rc) {
833 cFYI(1, "%s: Mapping error %d for owner id %d",
8abf2775 834 __func__, rc, id);
a5ff3769
SP
835 kfree(nowner_sid_ptr);
836 return rc;
837 }
36960e44 838 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
a5ff3769
SP
839 kfree(nowner_sid_ptr);
840 *aclflag = CIFS_ACL_OWNER;
841 }
8abf2775
EB
842 if (gid_valid(gid)) { /* chgrp */
843 gid_t id;
a5ff3769
SP
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;
8abf2775
EB
850 id = from_kgid(&init_user_ns, gid);
851 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
a5ff3769
SP
852 if (rc) {
853 cFYI(1, "%s: Mapping error %d for group id %d",
8abf2775 854 __func__, rc, id);
a5ff3769
SP
855 kfree(ngroup_sid_ptr);
856 return rc;
857 }
36960e44 858 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
a5ff3769
SP
859 kfree(ngroup_sid_ptr);
860 *aclflag = CIFS_ACL_GROUP;
861 }
862 }
97837582 863
ef571cad 864 return rc;
97837582
SF
865}
866
1bf4072d
CH
867static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
868 __u16 fid, u32 *pacllen)
b9c7a2bb 869{
b9c7a2bb 870 struct cifs_ntsd *pntsd = NULL;
6d5786a3
PS
871 unsigned int xid;
872 int rc;
7ffec372
JL
873 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
874
875 if (IS_ERR(tlink))
987b21d7 876 return ERR_CAST(tlink);
b9c7a2bb 877
6d5786a3 878 xid = get_xid();
7ffec372 879 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
6d5786a3 880 free_xid(xid);
b9c7a2bb 881
7ffec372 882 cifs_put_tlink(tlink);
b9c7a2bb 883
987b21d7
SP
884 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
885 if (rc)
886 return ERR_PTR(rc);
1bf4072d
CH
887 return pntsd;
888}
8b1327f6 889
1bf4072d
CH
890static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
891 const char *path, u32 *pacllen)
892{
893 struct cifs_ntsd *pntsd = NULL;
894 int oplock = 0;
6d5786a3
PS
895 unsigned int xid;
896 int rc, create_options = 0;
1bf4072d 897 __u16 fid;
96daf2b0 898 struct cifs_tcon *tcon;
7ffec372
JL
899 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
900
901 if (IS_ERR(tlink))
987b21d7 902 return ERR_CAST(tlink);
b9c7a2bb 903
7ffec372 904 tcon = tlink_tcon(tlink);
6d5786a3 905 xid = get_xid();
1bf4072d 906
3d3ea8e6
SP
907 if (backup_cred(cifs_sb))
908 create_options |= CREATE_OPEN_BACKUP_INTENT;
909
910 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
911 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
912 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
987b21d7
SP
913 if (!rc) {
914 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
915 CIFSSMBClose(xid, tcon, fid);
b9c7a2bb
SF
916 }
917
7ffec372 918 cifs_put_tlink(tlink);
6d5786a3 919 free_xid(xid);
987b21d7
SP
920
921 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
922 if (rc)
923 return ERR_PTR(rc);
7505e052
SF
924 return pntsd;
925}
926
1bf4072d 927/* Retrieve an ACL from the server */
fbeba8bb 928struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1bf4072d
CH
929 struct inode *inode, const char *path,
930 u32 *pacllen)
931{
932 struct cifs_ntsd *pntsd = NULL;
933 struct cifsFileInfo *open_file = NULL;
934
935 if (inode)
6508d904 936 open_file = find_readable_file(CIFS_I(inode), true);
1bf4072d
CH
937 if (!open_file)
938 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
939
4b4de76e 940 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
6ab409b5 941 cifsFileInfo_put(open_file);
1bf4072d
CH
942 return pntsd;
943}
944
a5ff3769
SP
945 /* Set an ACL on the server */
946int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
947 struct inode *inode, const char *path, int aclflag)
b96d31a6
CH
948{
949 int oplock = 0;
6d5786a3
PS
950 unsigned int xid;
951 int rc, access_flags, create_options = 0;
b96d31a6 952 __u16 fid;
96daf2b0 953 struct cifs_tcon *tcon;
a5ff3769 954 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec372 955 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
97837582 956
7ffec372
JL
957 if (IS_ERR(tlink))
958 return PTR_ERR(tlink);
959
960 tcon = tlink_tcon(tlink);
6d5786a3 961 xid = get_xid();
97837582 962
3d3ea8e6
SP
963 if (backup_cred(cifs_sb))
964 create_options |= CREATE_OPEN_BACKUP_INTENT;
965
a5ff3769
SP
966 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
967 access_flags = WRITE_OWNER;
968 else
969 access_flags = WRITE_DAC;
970
971 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
972 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
973 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
b96d31a6 974 if (rc) {
b6b38f70 975 cERROR(1, "Unable to open file to set ACL");
b96d31a6 976 goto out;
97837582
SF
977 }
978
a5ff3769 979 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
b6b38f70 980 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
97837582 981
7ffec372
JL
982 CIFSSMBClose(xid, tcon, fid);
983out:
6d5786a3 984 free_xid(xid);
7ffec372 985 cifs_put_tlink(tlink);
b96d31a6
CH
986 return rc;
987}
97837582 988
7505e052 989/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
987b21d7 990int
0b8f18e3
JL
991cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
992 struct inode *inode, const char *path, const __u16 *pfid)
7505e052
SF
993{
994 struct cifs_ntsd *pntsd = NULL;
995 u32 acllen = 0;
996 int rc = 0;
997
b6b38f70 998 cFYI(DBG2, "converting ACL to mode for %s", path);
1bf4072d
CH
999
1000 if (pfid)
1001 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
1002 else
1003 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
7505e052
SF
1004
1005 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
987b21d7
SP
1006 if (IS_ERR(pntsd)) {
1007 rc = PTR_ERR(pntsd);
1008 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1009 } else {
9409ae58 1010 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
987b21d7
SP
1011 kfree(pntsd);
1012 if (rc)
1013 cERROR(1, "parse sec desc failed rc = %d", rc);
1014 }
7505e052 1015
987b21d7 1016 return rc;
b9c7a2bb 1017}
953f8681 1018
7505e052 1019/* Convert mode bits to an ACL so we can update the ACL on the server */
a5ff3769
SP
1020int
1021id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
8abf2775 1022 kuid_t uid, kgid_t gid)
953f8681
SF
1023{
1024 int rc = 0;
a5ff3769 1025 int aclflag = CIFS_ACL_DACL; /* default flag to set */
cce246ee 1026 __u32 secdesclen = 0;
97837582
SF
1027 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1028 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
953f8681 1029
b6b38f70 1030 cFYI(DBG2, "set ACL from mode for %s", path);
953f8681
SF
1031
1032 /* Get the security descriptor */
1bf4072d 1033 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
987b21d7
SP
1034 if (IS_ERR(pntsd)) {
1035 rc = PTR_ERR(pntsd);
1036 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
c78cd838
JL
1037 goto out;
1038 }
7505e052 1039
c78cd838
JL
1040 /*
1041 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1042 * as chmod disables ACEs and set the security descriptor. Allocate
1043 * memory for the smb header, set security descriptor request security
1044 * descriptor parameters, and secuirty descriptor itself
1045 */
7ee0b4c6 1046 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
c78cd838
JL
1047 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1048 if (!pnntsd) {
1049 cERROR(1, "Unable to allocate security descriptor");
1050 kfree(pntsd);
1051 return -ENOMEM;
1052 }
97837582 1053
c78cd838
JL
1054 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1055 &aclflag);
97837582 1056
c78cd838 1057 cFYI(DBG2, "build_sec_desc rc: %d", rc);
97837582 1058
c78cd838
JL
1059 if (!rc) {
1060 /* Set the security descriptor */
1061 rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
1062 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
97837582
SF
1063 }
1064
c78cd838
JL
1065 kfree(pnntsd);
1066 kfree(pntsd);
1067out:
ef571cad 1068 return rc;
953f8681 1069}
This page took 0.377038 seconds and 5 git commands to generate.