]> Git Repo - linux.git/blame - fs/cifs/cifsacl.c
cifs: Pass GLOBAL_ROOT_UID and GLOBAL_ROOT_GID to keyring_alloc
[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 ([email protected])
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;
faa65f07
JL
269 uid_t fuid = cifs_sb->mnt_uid;
270 gid_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
9409ae58 309 if (sidtype == SIDOWNER)
41a9f1f6 310 memcpy(&fuid, &sidkey->payload.value, sizeof(uid_t));
9409ae58 311 else
41a9f1f6 312 memcpy(&fgid, &sidkey->payload.value, sizeof(gid_t));
faa65f07
JL
313
314out_key_put:
315 key_put(sidkey);
316out_revert_creds:
317 revert_creds(saved_cred);
318 kfree(sidstr);
9409ae58 319
faa65f07
JL
320 /*
321 * Note that we return 0 here unconditionally. If the mapping
322 * fails then we just fall back to using the mnt_uid/mnt_gid.
323 */
324 if (sidtype == SIDOWNER)
325 fattr->cf_uid = fuid;
326 else
327 fattr->cf_gid = fgid;
9409ae58
SP
328 return 0;
329}
330
4d79dba0
SP
331int
332init_cifs_idmap(void)
333{
334 struct cred *cred;
335 struct key *keyring;
336 int ret;
337
ac3aa2f8 338 cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
4d79dba0
SP
339
340 /* create an override credential set with a special thread keyring in
341 * which requests are cached
342 *
343 * this is used to prevent malicious redirections from being installed
344 * with add_key().
345 */
346 cred = prepare_kernel_cred(NULL);
347 if (!cred)
348 return -ENOMEM;
349
8e3028b9
EB
350 keyring = keyring_alloc(".cifs_idmap",
351 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
f8aa23a5
DH
352 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
353 KEY_USR_VIEW | KEY_USR_READ,
354 KEY_ALLOC_NOT_IN_QUOTA, NULL);
4d79dba0
SP
355 if (IS_ERR(keyring)) {
356 ret = PTR_ERR(keyring);
357 goto failed_put_cred;
358 }
359
4d79dba0
SP
360 ret = register_key_type(&cifs_idmap_key_type);
361 if (ret < 0)
362 goto failed_put_key;
363
364 /* instruct request_key() to use this special keyring as a cache for
365 * the results it looks up */
700920eb 366 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
4d79dba0
SP
367 cred->thread_keyring = keyring;
368 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
369 root_cred = cred;
370
ac3aa2f8 371 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
4d79dba0
SP
372 return 0;
373
374failed_put_key:
375 key_put(keyring);
376failed_put_cred:
377 put_cred(cred);
378 return ret;
379}
380
381void
382exit_cifs_idmap(void)
383{
384 key_revoke(root_cred->thread_keyring);
385 unregister_key_type(&cifs_idmap_key_type);
386 put_cred(root_cred);
ac3aa2f8 387 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
4d79dba0
SP
388}
389
97837582
SF
390/* copy ntsd, owner sid, and group sid from a security descriptor to another */
391static void copy_sec_desc(const struct cifs_ntsd *pntsd,
392 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
393{
97837582
SF
394 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
395 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
396
397 /* copy security descriptor control portion */
398 pnntsd->revision = pntsd->revision;
399 pnntsd->type = pntsd->type;
400 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
401 pnntsd->sacloffset = 0;
402 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
403 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
404
405 /* copy owner sid */
406 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
407 le32_to_cpu(pntsd->osidoffset));
408 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
36960e44 409 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
97837582
SF
410
411 /* copy group sid */
412 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
413 le32_to_cpu(pntsd->gsidoffset));
414 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
415 sizeof(struct cifs_sid));
36960e44 416 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
97837582
SF
417
418 return;
419}
420
421
630f3f0c
SF
422/*
423 change posix mode to reflect permissions
424 pmode is the existing mode (we only want to overwrite part of this
425 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
426*/
9b5e6857 427static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
15b03959 428 umode_t *pbits_to_set)
630f3f0c 429{
9b5e6857 430 __u32 flags = le32_to_cpu(ace_flags);
15b03959 431 /* the order of ACEs is important. The canonical order is to begin with
ce06c9f0 432 DENY entries followed by ALLOW, otherwise an allow entry could be
15b03959 433 encountered first, making the subsequent deny entry like "dead code"
ce06c9f0 434 which would be superflous since Windows stops when a match is made
15b03959
SF
435 for the operation you are trying to perform for your user */
436
437 /* For deny ACEs we change the mask so that subsequent allow access
438 control entries do not turn on the bits we are denying */
439 if (type == ACCESS_DENIED) {
ad7a2926 440 if (flags & GENERIC_ALL)
15b03959 441 *pbits_to_set &= ~S_IRWXUGO;
ad7a2926 442
9b5e6857
AV
443 if ((flags & GENERIC_WRITE) ||
444 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 445 *pbits_to_set &= ~S_IWUGO;
9b5e6857
AV
446 if ((flags & GENERIC_READ) ||
447 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 448 *pbits_to_set &= ~S_IRUGO;
9b5e6857
AV
449 if ((flags & GENERIC_EXECUTE) ||
450 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959
SF
451 *pbits_to_set &= ~S_IXUGO;
452 return;
453 } else if (type != ACCESS_ALLOWED) {
b6b38f70 454 cERROR(1, "unknown access control type %d", type);
15b03959
SF
455 return;
456 }
457 /* else ACCESS_ALLOWED type */
630f3f0c 458
9b5e6857 459 if (flags & GENERIC_ALL) {
15b03959 460 *pmode |= (S_IRWXUGO & (*pbits_to_set));
b6b38f70 461 cFYI(DBG2, "all perms");
d61e5808
SF
462 return;
463 }
9b5e6857
AV
464 if ((flags & GENERIC_WRITE) ||
465 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 466 *pmode |= (S_IWUGO & (*pbits_to_set));
9b5e6857
AV
467 if ((flags & GENERIC_READ) ||
468 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 469 *pmode |= (S_IRUGO & (*pbits_to_set));
9b5e6857
AV
470 if ((flags & GENERIC_EXECUTE) ||
471 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959 472 *pmode |= (S_IXUGO & (*pbits_to_set));
630f3f0c 473
b6b38f70 474 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
630f3f0c
SF
475 return;
476}
477
ce06c9f0
SF
478/*
479 Generate access flags to reflect permissions mode is the existing mode.
480 This function is called for every ACE in the DACL whose SID matches
481 with either owner or group or everyone.
482*/
483
484static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
485 __u32 *pace_flags)
486{
487 /* reset access mask */
488 *pace_flags = 0x0;
489
490 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
491 mode &= bits_to_use;
492
493 /* check for R/W/X UGO since we do not know whose flags
494 is this but we have cleared all the bits sans RWX for
495 either user or group or other as per bits_to_use */
496 if (mode & S_IRUGO)
497 *pace_flags |= SET_FILE_READ_RIGHTS;
498 if (mode & S_IWUGO)
499 *pace_flags |= SET_FILE_WRITE_RIGHTS;
500 if (mode & S_IXUGO)
501 *pace_flags |= SET_FILE_EXEC_RIGHTS;
502
b6b38f70 503 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
ce06c9f0
SF
504 return;
505}
506
2b210adc 507static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
97837582
SF
508 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
509{
510 int i;
511 __u16 size = 0;
512 __u32 access_req = 0;
513
514 pntace->type = ACCESS_ALLOWED;
515 pntace->flags = 0x0;
516 mode_to_access_flags(nmode, bits, &access_req);
517 if (!access_req)
518 access_req = SET_MINIMUM_RIGHTS;
519 pntace->access_req = cpu_to_le32(access_req);
520
521 pntace->sid.revision = psid->revision;
522 pntace->sid.num_subauth = psid->num_subauth;
852e2295 523 for (i = 0; i < NUM_AUTHS; i++)
97837582
SF
524 pntace->sid.authority[i] = psid->authority[i];
525 for (i = 0; i < psid->num_subauth; i++)
526 pntace->sid.sub_auth[i] = psid->sub_auth[i];
527
528 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
529 pntace->size = cpu_to_le16(size);
530
ef571cad 531 return size;
97837582
SF
532}
533
297647c2 534
953f8681
SF
535#ifdef CONFIG_CIFS_DEBUG2
536static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
d0d66c44 537{
d0d66c44 538 int num_subauth;
d0d66c44
SP
539
540 /* validate that we do not go past end of acl */
297647c2 541
44093ca2 542 if (le16_to_cpu(pace->size) < 16) {
b6b38f70 543 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
44093ca2
SF
544 return;
545 }
546
547 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
b6b38f70 548 cERROR(1, "ACL too small to parse ACE");
d0d66c44 549 return;
44093ca2 550 }
d0d66c44 551
44093ca2 552 num_subauth = pace->sid.num_subauth;
d0d66c44 553 if (num_subauth) {
8f18c131 554 int i;
b6b38f70 555 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
44093ca2 556 pace->sid.revision, pace->sid.num_subauth, pace->type,
b6b38f70 557 pace->flags, le16_to_cpu(pace->size));
d12fd121 558 for (i = 0; i < num_subauth; ++i) {
b6b38f70
JP
559 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
560 le32_to_cpu(pace->sid.sub_auth[i]));
d12fd121
SF
561 }
562
563 /* BB add length check to make sure that we do not have huge
564 num auths and therefore go off the end */
d12fd121
SF
565 }
566
567 return;
568}
953f8681 569#endif
d12fd121 570
d0d66c44 571
a750e77c 572static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
d61e5808 573 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
0b8f18e3 574 struct cifs_fattr *fattr)
d0d66c44
SP
575{
576 int i;
577 int num_aces = 0;
578 int acl_size;
579 char *acl_base;
d0d66c44
SP
580 struct cifs_ace **ppace;
581
582 /* BB need to add parm so we can store the SID BB */
583
2b83457b
SF
584 if (!pdacl) {
585 /* no DACL in the security descriptor, set
586 all the permissions for user/group/other */
0b8f18e3 587 fattr->cf_mode |= S_IRWXUGO;
2b83457b
SF
588 return;
589 }
590
d0d66c44 591 /* validate that we do not go past end of acl */
af6f4612 592 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
b6b38f70 593 cERROR(1, "ACL too small to parse DACL");
d0d66c44
SP
594 return;
595 }
596
b6b38f70 597 cFYI(DBG2, "DACL revision %d size %d num aces %d",
af6f4612 598 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
b6b38f70 599 le32_to_cpu(pdacl->num_aces));
d0d66c44 600
7505e052
SF
601 /* reset rwx permissions for user/group/other.
602 Also, if num_aces is 0 i.e. DACL has no ACEs,
603 user/group/other have no permissions */
0b8f18e3 604 fattr->cf_mode &= ~(S_IRWXUGO);
7505e052 605
d0d66c44
SP
606 acl_base = (char *)pdacl;
607 acl_size = sizeof(struct cifs_acl);
608
adbc0358 609 num_aces = le32_to_cpu(pdacl->num_aces);
a5ff3769 610 if (num_aces > 0) {
15b03959
SF
611 umode_t user_mask = S_IRWXU;
612 umode_t group_mask = S_IRWXG;
2fbc2f17 613 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
15b03959 614
7250170c
DC
615 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
616 return;
d0d66c44
SP
617 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
618 GFP_KERNEL);
8132b65b
SF
619 if (!ppace) {
620 cERROR(1, "DACL memory allocation error");
621 return;
622 }
d0d66c44 623
d0d66c44 624 for (i = 0; i < num_aces; ++i) {
44093ca2 625 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
953f8681
SF
626#ifdef CONFIG_CIFS_DEBUG2
627 dump_ace(ppace[i], end_of_acl);
628#endif
9409ae58 629 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
e01b6400 630 access_flags_to_mode(ppace[i]->access_req,
15b03959 631 ppace[i]->type,
0b8f18e3 632 &fattr->cf_mode,
15b03959 633 &user_mask);
9409ae58 634 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
e01b6400 635 access_flags_to_mode(ppace[i]->access_req,
15b03959 636 ppace[i]->type,
0b8f18e3 637 &fattr->cf_mode,
15b03959 638 &group_mask);
9409ae58 639 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
e01b6400 640 access_flags_to_mode(ppace[i]->access_req,
15b03959 641 ppace[i]->type,
0b8f18e3 642 &fattr->cf_mode,
15b03959 643 &other_mask);
9409ae58 644 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
2fbc2f17
SP
645 access_flags_to_mode(ppace[i]->access_req,
646 ppace[i]->type,
647 &fattr->cf_mode,
648 &other_mask);
649
e01b6400 650
44093ca2 651/* memcpy((void *)(&(cifscred->aces[i])),
d12fd121
SF
652 (void *)ppace[i],
653 sizeof(struct cifs_ace)); */
d0d66c44 654
44093ca2
SF
655 acl_base = (char *)ppace[i];
656 acl_size = le16_to_cpu(ppace[i]->size);
d0d66c44
SP
657 }
658
659 kfree(ppace);
d0d66c44
SP
660 }
661
662 return;
663}
664
bcb02034 665
97837582
SF
666static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
667 struct cifs_sid *pgrpsid, __u64 nmode)
668{
2b210adc 669 u16 size = 0;
97837582
SF
670 struct cifs_acl *pnndacl;
671
672 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
673
674 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
675 pownersid, nmode, S_IRWXU);
676 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
677 pgrpsid, nmode, S_IRWXG);
678 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
679 &sid_everyone, nmode, S_IRWXO);
680
681 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
d9f382ef 682 pndacl->num_aces = cpu_to_le32(3);
97837582 683
ef571cad 684 return 0;
97837582
SF
685}
686
687
bcb02034
SF
688static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
689{
690 /* BB need to add parm so we can store the SID BB */
691
b9c7a2bb
SF
692 /* validate that we do not go past end of ACL - sid must be at least 8
693 bytes long (assuming no sub-auths - e.g. the null SID */
694 if (end_of_acl < (char *)psid + 8) {
b6b38f70 695 cERROR(1, "ACL too small to parse SID %p", psid);
bcb02034
SF
696 return -EINVAL;
697 }
d0d66c44 698
bcb02034 699#ifdef CONFIG_CIFS_DEBUG2
fc03d8a5 700 if (psid->num_subauth) {
8f18c131 701 int i;
b6b38f70
JP
702 cFYI(1, "SID revision %d num_auth %d",
703 psid->revision, psid->num_subauth);
bcb02034 704
af6f4612 705 for (i = 0; i < psid->num_subauth; i++) {
b6b38f70
JP
706 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
707 le32_to_cpu(psid->sub_auth[i]));
d0d66c44
SP
708 }
709
d12fd121 710 /* BB add length check to make sure that we do not have huge
d0d66c44 711 num auths and therefore go off the end */
b6b38f70
JP
712 cFYI(1, "RID 0x%x",
713 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
d0d66c44 714 }
fc03d8a5 715#endif
d0d66c44 716
bcb02034
SF
717 return 0;
718}
719
d0d66c44 720
bcb02034 721/* Convert CIFS ACL to POSIX form */
9409ae58
SP
722static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
723 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
bcb02034 724{
9409ae58 725 int rc = 0;
bcb02034
SF
726 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
727 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
bcb02034 728 char *end_of_acl = ((char *)pntsd) + acl_len;
7505e052 729 __u32 dacloffset;
bcb02034 730
0b8f18e3 731 if (pntsd == NULL)
b9c7a2bb
SF
732 return -EIO;
733
bcb02034 734 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 735 le32_to_cpu(pntsd->osidoffset));
bcb02034 736 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 737 le32_to_cpu(pntsd->gsidoffset));
7505e052 738 dacloffset = le32_to_cpu(pntsd->dacloffset);
63d2583f 739 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
b6b38f70 740 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
bcb02034 741 "sacloffset 0x%x dacloffset 0x%x",
af6f4612
SF
742 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
743 le32_to_cpu(pntsd->gsidoffset),
b6b38f70 744 le32_to_cpu(pntsd->sacloffset), dacloffset);
b9c7a2bb 745/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
bcb02034 746 rc = parse_sid(owner_sid_ptr, end_of_acl);
9409ae58
SP
747 if (rc) {
748 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
749 return rc;
750 }
751 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
752 if (rc) {
753 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
bcb02034 754 return rc;
9409ae58 755 }
bcb02034
SF
756
757 rc = parse_sid(group_sid_ptr, end_of_acl);
9409ae58
SP
758 if (rc) {
759 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
bcb02034 760 return rc;
9409ae58
SP
761 }
762 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
763 if (rc) {
764 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
765 return rc;
766 }
bcb02034 767
7505e052
SF
768 if (dacloffset)
769 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
0b8f18e3 770 group_sid_ptr, fattr);
7505e052 771 else
b6b38f70 772 cFYI(1, "no ACL"); /* BB grant all or default perms? */
d0d66c44 773
9409ae58 774 return rc;
bcb02034 775}
b9c7a2bb 776
97837582
SF
777/* Convert permission bits from mode to equivalent CIFS ACL */
778static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
a5ff3769 779 __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
97837582
SF
780{
781 int rc = 0;
782 __u32 dacloffset;
783 __u32 ndacloffset;
784 __u32 sidsoffset;
785 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
a5ff3769 786 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
97837582
SF
787 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
788 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
789
a5ff3769
SP
790 if (nmode != NO_CHANGE_64) { /* chmod */
791 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 792 le32_to_cpu(pntsd->osidoffset));
a5ff3769 793 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 794 le32_to_cpu(pntsd->gsidoffset));
a5ff3769
SP
795 dacloffset = le32_to_cpu(pntsd->dacloffset);
796 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
797 ndacloffset = sizeof(struct cifs_ntsd);
798 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
799 ndacl_ptr->revision = dacl_ptr->revision;
800 ndacl_ptr->size = 0;
801 ndacl_ptr->num_aces = 0;
802
803 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
804 nmode);
805 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
806 /* copy sec desc control portion & owner and group sids */
807 copy_sec_desc(pntsd, pnntsd, sidsoffset);
808 *aclflag = CIFS_ACL_DACL;
809 } else {
810 memcpy(pnntsd, pntsd, secdesclen);
811 if (uid != NO_CHANGE_32) { /* chown */
812 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
813 le32_to_cpu(pnntsd->osidoffset));
814 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
815 GFP_KERNEL);
816 if (!nowner_sid_ptr)
817 return -ENOMEM;
818 rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
819 if (rc) {
820 cFYI(1, "%s: Mapping error %d for owner id %d",
821 __func__, rc, uid);
822 kfree(nowner_sid_ptr);
823 return rc;
824 }
36960e44 825 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
a5ff3769
SP
826 kfree(nowner_sid_ptr);
827 *aclflag = CIFS_ACL_OWNER;
828 }
829 if (gid != NO_CHANGE_32) { /* chgrp */
830 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
831 le32_to_cpu(pnntsd->gsidoffset));
832 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
833 GFP_KERNEL);
834 if (!ngroup_sid_ptr)
835 return -ENOMEM;
836 rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
837 if (rc) {
838 cFYI(1, "%s: Mapping error %d for group id %d",
839 __func__, rc, gid);
840 kfree(ngroup_sid_ptr);
841 return rc;
842 }
36960e44 843 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
a5ff3769
SP
844 kfree(ngroup_sid_ptr);
845 *aclflag = CIFS_ACL_GROUP;
846 }
847 }
97837582 848
ef571cad 849 return rc;
97837582
SF
850}
851
1bf4072d
CH
852static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
853 __u16 fid, u32 *pacllen)
b9c7a2bb 854{
b9c7a2bb 855 struct cifs_ntsd *pntsd = NULL;
6d5786a3
PS
856 unsigned int xid;
857 int rc;
7ffec372
JL
858 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
859
860 if (IS_ERR(tlink))
987b21d7 861 return ERR_CAST(tlink);
b9c7a2bb 862
6d5786a3 863 xid = get_xid();
7ffec372 864 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
6d5786a3 865 free_xid(xid);
b9c7a2bb 866
7ffec372 867 cifs_put_tlink(tlink);
b9c7a2bb 868
987b21d7
SP
869 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
870 if (rc)
871 return ERR_PTR(rc);
1bf4072d
CH
872 return pntsd;
873}
8b1327f6 874
1bf4072d
CH
875static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
876 const char *path, u32 *pacllen)
877{
878 struct cifs_ntsd *pntsd = NULL;
879 int oplock = 0;
6d5786a3
PS
880 unsigned int xid;
881 int rc, create_options = 0;
1bf4072d 882 __u16 fid;
96daf2b0 883 struct cifs_tcon *tcon;
7ffec372
JL
884 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
885
886 if (IS_ERR(tlink))
987b21d7 887 return ERR_CAST(tlink);
b9c7a2bb 888
7ffec372 889 tcon = tlink_tcon(tlink);
6d5786a3 890 xid = get_xid();
1bf4072d 891
3d3ea8e6
SP
892 if (backup_cred(cifs_sb))
893 create_options |= CREATE_OPEN_BACKUP_INTENT;
894
895 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
896 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
897 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
987b21d7
SP
898 if (!rc) {
899 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
900 CIFSSMBClose(xid, tcon, fid);
b9c7a2bb
SF
901 }
902
7ffec372 903 cifs_put_tlink(tlink);
6d5786a3 904 free_xid(xid);
987b21d7
SP
905
906 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
907 if (rc)
908 return ERR_PTR(rc);
7505e052
SF
909 return pntsd;
910}
911
1bf4072d 912/* Retrieve an ACL from the server */
fbeba8bb 913struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1bf4072d
CH
914 struct inode *inode, const char *path,
915 u32 *pacllen)
916{
917 struct cifs_ntsd *pntsd = NULL;
918 struct cifsFileInfo *open_file = NULL;
919
920 if (inode)
6508d904 921 open_file = find_readable_file(CIFS_I(inode), true);
1bf4072d
CH
922 if (!open_file)
923 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
924
4b4de76e 925 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
6ab409b5 926 cifsFileInfo_put(open_file);
1bf4072d
CH
927 return pntsd;
928}
929
a5ff3769
SP
930 /* Set an ACL on the server */
931int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
932 struct inode *inode, const char *path, int aclflag)
b96d31a6
CH
933{
934 int oplock = 0;
6d5786a3
PS
935 unsigned int xid;
936 int rc, access_flags, create_options = 0;
b96d31a6 937 __u16 fid;
96daf2b0 938 struct cifs_tcon *tcon;
a5ff3769 939 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec372 940 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
97837582 941
7ffec372
JL
942 if (IS_ERR(tlink))
943 return PTR_ERR(tlink);
944
945 tcon = tlink_tcon(tlink);
6d5786a3 946 xid = get_xid();
97837582 947
3d3ea8e6
SP
948 if (backup_cred(cifs_sb))
949 create_options |= CREATE_OPEN_BACKUP_INTENT;
950
a5ff3769
SP
951 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
952 access_flags = WRITE_OWNER;
953 else
954 access_flags = WRITE_DAC;
955
956 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
957 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
958 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
b96d31a6 959 if (rc) {
b6b38f70 960 cERROR(1, "Unable to open file to set ACL");
b96d31a6 961 goto out;
97837582
SF
962 }
963
a5ff3769 964 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
b6b38f70 965 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
97837582 966
7ffec372
JL
967 CIFSSMBClose(xid, tcon, fid);
968out:
6d5786a3 969 free_xid(xid);
7ffec372 970 cifs_put_tlink(tlink);
b96d31a6
CH
971 return rc;
972}
97837582 973
7505e052 974/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
987b21d7 975int
0b8f18e3
JL
976cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
977 struct inode *inode, const char *path, const __u16 *pfid)
7505e052
SF
978{
979 struct cifs_ntsd *pntsd = NULL;
980 u32 acllen = 0;
981 int rc = 0;
982
b6b38f70 983 cFYI(DBG2, "converting ACL to mode for %s", path);
1bf4072d
CH
984
985 if (pfid)
986 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
987 else
988 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
7505e052
SF
989
990 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
987b21d7
SP
991 if (IS_ERR(pntsd)) {
992 rc = PTR_ERR(pntsd);
993 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
994 } else {
9409ae58 995 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
987b21d7
SP
996 kfree(pntsd);
997 if (rc)
998 cERROR(1, "parse sec desc failed rc = %d", rc);
999 }
7505e052 1000
987b21d7 1001 return rc;
b9c7a2bb 1002}
953f8681 1003
7505e052 1004/* Convert mode bits to an ACL so we can update the ACL on the server */
a5ff3769
SP
1005int
1006id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1007 uid_t uid, gid_t gid)
953f8681
SF
1008{
1009 int rc = 0;
a5ff3769 1010 int aclflag = CIFS_ACL_DACL; /* default flag to set */
cce246ee 1011 __u32 secdesclen = 0;
97837582
SF
1012 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1013 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
953f8681 1014
b6b38f70 1015 cFYI(DBG2, "set ACL from mode for %s", path);
953f8681
SF
1016
1017 /* Get the security descriptor */
1bf4072d 1018 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
987b21d7
SP
1019 if (IS_ERR(pntsd)) {
1020 rc = PTR_ERR(pntsd);
1021 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
c78cd838
JL
1022 goto out;
1023 }
7505e052 1024
c78cd838
JL
1025 /*
1026 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1027 * as chmod disables ACEs and set the security descriptor. Allocate
1028 * memory for the smb header, set security descriptor request security
1029 * descriptor parameters, and secuirty descriptor itself
1030 */
7ee0b4c6 1031 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
c78cd838
JL
1032 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1033 if (!pnntsd) {
1034 cERROR(1, "Unable to allocate security descriptor");
1035 kfree(pntsd);
1036 return -ENOMEM;
1037 }
97837582 1038
c78cd838
JL
1039 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1040 &aclflag);
97837582 1041
c78cd838 1042 cFYI(DBG2, "build_sec_desc rc: %d", rc);
97837582 1043
c78cd838
JL
1044 if (!rc) {
1045 /* Set the security descriptor */
1046 rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
1047 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
97837582
SF
1048 }
1049
c78cd838
JL
1050 kfree(pnntsd);
1051 kfree(pntsd);
1052out:
ef571cad 1053 return rc;
953f8681 1054}
This page took 0.570932 seconds and 4 git commands to generate.