]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/cifs/cifsacl.c
Merge tag 'for-v4.3-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux...
[mirror_ubuntu-bionic-kernel.git] / fs / cifs / cifsacl.c
CommitLineData
bcb02034
SF
1/*
2 * fs/cifs/cifsacl.c
3 *
8b1327f6 4 * Copyright (C) International Business Machines Corp., 2007,2008
bcb02034
SF
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for mapping CIFS/NTFS ACLs
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
65874007 24#include <linux/fs.h>
5a0e3ad6 25#include <linux/slab.h>
4d79dba0
SP
26#include <linux/string.h>
27#include <linux/keyctl.h>
28#include <linux/key-type.h>
29#include <keys/user-type.h>
65874007
SF
30#include "cifspdu.h"
31#include "cifsglob.h"
d0d66c44 32#include "cifsacl.h"
65874007
SF
33#include "cifsproto.h"
34#include "cifs_debug.h"
65874007 35
2fbc2f17 36/* security id for everyone/world system group */
e01b6400
SP
37static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
2fbc2f17
SP
39/* security id for Authenticated Users system group */
40static const struct cifs_sid sid_authusers = {
bc09d141 41 1, 1, {0, 0, 0, 0, 0, 5}, {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 }
f7f7c185 66 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
4d79dba0
SP
67 if (!payload)
68 return -ENOMEM;
69
4d79dba0 70 key->payload.data = payload;
cf7f601c 71 key->datalen = prep->datalen;
4d79dba0
SP
72 return 0;
73}
74
75static inline void
76cifs_idmap_key_destroy(struct key *key)
77{
1f630680 78 if (key->datalen > sizeof(key->payload))
41a9f1f6 79 kfree(key->payload.data);
4d79dba0
SP
80}
81
b1a6dc21 82static struct key_type cifs_idmap_key_type = {
c4aca0c0 83 .name = "cifs.idmap",
4d79dba0
SP
84 .instantiate = cifs_idmap_key_instantiate,
85 .destroy = cifs_idmap_key_destroy,
86 .describe = user_describe,
4d79dba0
SP
87};
88
faa65f07
JL
89static char *
90sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
9409ae58 91{
faa65f07 92 int i, len;
ee13b2ba 93 unsigned int saval;
faa65f07 94 char *sidstr, *strptr;
193cdd8a 95 unsigned long long id_auth_val;
9409ae58 96
faa65f07
JL
97 /* 3 bytes for prefix */
98 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
99 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
100 GFP_KERNEL);
101 if (!sidstr)
102 return sidstr;
9409ae58 103
faa65f07
JL
104 strptr = sidstr;
105 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
106 sidptr->revision);
107 strptr += len;
9409ae58 108
193cdd8a
JL
109 /* The authority field is a single 48-bit number */
110 id_auth_val = (unsigned long long)sidptr->authority[5];
111 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
112 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
113 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
114 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
115 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
116
117 /*
118 * MS-DTYP states that if the authority is >= 2^32, then it should be
119 * expressed as a hex value.
120 */
121 if (id_auth_val <= UINT_MAX)
122 len = sprintf(strptr, "-%llu", id_auth_val);
123 else
124 len = sprintf(strptr, "-0x%llx", id_auth_val);
125
126 strptr += len;
9409ae58
SP
127
128 for (i = 0; i < sidptr->num_subauth; ++i) {
129 saval = le32_to_cpu(sidptr->sub_auth[i]);
faa65f07
JL
130 len = sprintf(strptr, "-%u", saval);
131 strptr += len;
9409ae58 132 }
faa65f07
JL
133
134 return sidstr;
9409ae58
SP
135}
136
436bb435
JL
137/*
138 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
139 * the same returns zero, if they do not match returns non-zero.
140 */
141static int
142compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
143{
144 int i;
145 int num_subauth, num_sat, num_saw;
146
147 if ((!ctsid) || (!cwsid))
148 return 1;
149
150 /* compare the revision */
151 if (ctsid->revision != cwsid->revision) {
152 if (ctsid->revision > cwsid->revision)
153 return 1;
154 else
155 return -1;
156 }
157
158 /* compare all of the six auth values */
159 for (i = 0; i < NUM_AUTHS; ++i) {
160 if (ctsid->authority[i] != cwsid->authority[i]) {
161 if (ctsid->authority[i] > cwsid->authority[i])
162 return 1;
163 else
164 return -1;
165 }
166 }
167
168 /* compare all of the subauth values if any */
169 num_sat = ctsid->num_subauth;
170 num_saw = cwsid->num_subauth;
171 num_subauth = num_sat < num_saw ? num_sat : num_saw;
172 if (num_subauth) {
173 for (i = 0; i < num_subauth; ++i) {
174 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
175 if (le32_to_cpu(ctsid->sub_auth[i]) >
176 le32_to_cpu(cwsid->sub_auth[i]))
177 return 1;
178 else
179 return -1;
180 }
181 }
182 }
183
184 return 0; /* sids compare/match */
185}
186
36960e44
JL
187static void
188cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
189{
36f87ee7
JL
190 int i;
191
192 dst->revision = src->revision;
30c9d6cc 193 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
36f87ee7
JL
194 for (i = 0; i < NUM_AUTHS; ++i)
195 dst->authority[i] = src->authority[i];
196 for (i = 0; i < dst->num_subauth; ++i)
197 dst->sub_auth[i] = src->sub_auth[i];
36960e44
JL
198}
199
9409ae58 200static int
faa65f07 201id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
9409ae58 202{
faa65f07 203 int rc;
21fed0d5 204 struct key *sidkey;
2ae03025
JL
205 struct cifs_sid *ksid;
206 unsigned int ksid_size;
faa65f07 207 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
21fed0d5 208 const struct cred *saved_cred;
21fed0d5 209
faa65f07
JL
210 rc = snprintf(desc, sizeof(desc), "%ci:%u",
211 sidtype == SIDOWNER ? 'o' : 'g', cid);
212 if (rc >= sizeof(desc))
213 return -EINVAL;
21fed0d5 214
faa65f07
JL
215 rc = 0;
216 saved_cred = override_creds(root_cred);
217 sidkey = request_key(&cifs_idmap_key_type, desc, "");
218 if (IS_ERR(sidkey)) {
21fed0d5 219 rc = -EINVAL;
f96637be
JP
220 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
221 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
faa65f07
JL
222 goto out_revert_creds;
223 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
224 rc = -EIO;
f96637be
JP
225 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
226 __func__, sidkey->datalen);
2ae03025 227 goto invalidate_key;
21fed0d5 228 }
2ae03025 229
1f630680
JL
230 /*
231 * A sid is usually too large to be embedded in payload.value, but if
232 * there are no subauthorities and the host has 8-byte pointers, then
233 * it could be.
234 */
235 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
236 (struct cifs_sid *)&sidkey->payload.value :
237 (struct cifs_sid *)sidkey->payload.data;
238
2ae03025
JL
239 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
240 if (ksid_size > sidkey->datalen) {
241 rc = -EIO;
f96637be
JP
242 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
243 __func__, sidkey->datalen, ksid_size);
2ae03025
JL
244 goto invalidate_key;
245 }
1f630680 246
2ae03025 247 cifs_copy_sid(ssid, ksid);
faa65f07
JL
248out_key_put:
249 key_put(sidkey);
250out_revert_creds:
251 revert_creds(saved_cred);
21fed0d5 252 return rc;
2ae03025
JL
253
254invalidate_key:
255 key_invalidate(sidkey);
256 goto out_key_put;
21fed0d5
SP
257}
258
9409ae58
SP
259static int
260sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
261 struct cifs_fattr *fattr, uint sidtype)
262{
263 int rc;
faa65f07
JL
264 struct key *sidkey;
265 char *sidstr;
9409ae58 266 const struct cred *saved_cred;
8abf2775
EB
267 kuid_t fuid = cifs_sb->mnt_uid;
268 kgid_t fgid = cifs_sb->mnt_gid;
9409ae58
SP
269
270 /*
faa65f07
JL
271 * If we have too many subauthorities, then something is really wrong.
272 * Just return an error.
9409ae58 273 */
faa65f07 274 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
f96637be
JP
275 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
276 __func__, psid->num_subauth);
faa65f07 277 return -EIO;
9409ae58
SP
278 }
279
faa65f07
JL
280 sidstr = sid_to_key_str(psid, sidtype);
281 if (!sidstr)
282 return -ENOMEM;
283
284 saved_cred = override_creds(root_cred);
285 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
286 if (IS_ERR(sidkey)) {
287 rc = -EINVAL;
f96637be
JP
288 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
289 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
faa65f07
JL
290 goto out_revert_creds;
291 }
292
293 /*
294 * FIXME: Here we assume that uid_t and gid_t are same size. It's
295 * probably a safe assumption but might be better to check based on
296 * sidtype.
297 */
355958f2 298 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
41a9f1f6 299 if (sidkey->datalen != sizeof(uid_t)) {
faa65f07 300 rc = -EIO;
f96637be
JP
301 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
302 __func__, sidkey->datalen);
2ae03025 303 key_invalidate(sidkey);
faa65f07 304 goto out_key_put;
9409ae58
SP
305 }
306
8abf2775
EB
307 if (sidtype == SIDOWNER) {
308 kuid_t uid;
309 uid_t id;
310 memcpy(&id, &sidkey->payload.value, sizeof(uid_t));
311 uid = make_kuid(&init_user_ns, id);
312 if (uid_valid(uid))
313 fuid = uid;
314 } else {
315 kgid_t gid;
316 gid_t id;
317 memcpy(&id, &sidkey->payload.value, sizeof(gid_t));
318 gid = make_kgid(&init_user_ns, id);
319 if (gid_valid(gid))
320 fgid = gid;
321 }
faa65f07
JL
322
323out_key_put:
324 key_put(sidkey);
325out_revert_creds:
326 revert_creds(saved_cred);
327 kfree(sidstr);
9409ae58 328
faa65f07
JL
329 /*
330 * Note that we return 0 here unconditionally. If the mapping
331 * fails then we just fall back to using the mnt_uid/mnt_gid.
332 */
333 if (sidtype == SIDOWNER)
334 fattr->cf_uid = fuid;
335 else
336 fattr->cf_gid = fgid;
9409ae58
SP
337 return 0;
338}
339
4d79dba0
SP
340int
341init_cifs_idmap(void)
342{
343 struct cred *cred;
344 struct key *keyring;
345 int ret;
346
f96637be
JP
347 cifs_dbg(FYI, "Registering the %s key type\n",
348 cifs_idmap_key_type.name);
4d79dba0
SP
349
350 /* create an override credential set with a special thread keyring in
351 * which requests are cached
352 *
353 * this is used to prevent malicious redirections from being installed
354 * with add_key().
355 */
356 cred = prepare_kernel_cred(NULL);
357 if (!cred)
358 return -ENOMEM;
359
8e3028b9
EB
360 keyring = keyring_alloc(".cifs_idmap",
361 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
f8aa23a5
DH
362 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
363 KEY_USR_VIEW | KEY_USR_READ,
364 KEY_ALLOC_NOT_IN_QUOTA, NULL);
4d79dba0
SP
365 if (IS_ERR(keyring)) {
366 ret = PTR_ERR(keyring);
367 goto failed_put_cred;
368 }
369
4d79dba0
SP
370 ret = register_key_type(&cifs_idmap_key_type);
371 if (ret < 0)
372 goto failed_put_key;
373
374 /* instruct request_key() to use this special keyring as a cache for
375 * the results it looks up */
700920eb 376 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
4d79dba0
SP
377 cred->thread_keyring = keyring;
378 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
379 root_cred = cred;
380
f96637be 381 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
4d79dba0
SP
382 return 0;
383
384failed_put_key:
385 key_put(keyring);
386failed_put_cred:
387 put_cred(cred);
388 return ret;
389}
390
391void
392exit_cifs_idmap(void)
393{
394 key_revoke(root_cred->thread_keyring);
395 unregister_key_type(&cifs_idmap_key_type);
396 put_cred(root_cred);
f96637be 397 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
4d79dba0
SP
398}
399
97837582
SF
400/* copy ntsd, owner sid, and group sid from a security descriptor to another */
401static void copy_sec_desc(const struct cifs_ntsd *pntsd,
402 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
403{
97837582
SF
404 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
405 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
406
407 /* copy security descriptor control portion */
408 pnntsd->revision = pntsd->revision;
409 pnntsd->type = pntsd->type;
410 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
411 pnntsd->sacloffset = 0;
412 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
413 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
414
415 /* copy owner sid */
416 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
417 le32_to_cpu(pntsd->osidoffset));
418 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
36960e44 419 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
97837582
SF
420
421 /* copy group sid */
422 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
423 le32_to_cpu(pntsd->gsidoffset));
424 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
425 sizeof(struct cifs_sid));
36960e44 426 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
97837582
SF
427
428 return;
429}
430
431
630f3f0c
SF
432/*
433 change posix mode to reflect permissions
434 pmode is the existing mode (we only want to overwrite part of this
435 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
436*/
9b5e6857 437static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
15b03959 438 umode_t *pbits_to_set)
630f3f0c 439{
9b5e6857 440 __u32 flags = le32_to_cpu(ace_flags);
15b03959 441 /* the order of ACEs is important. The canonical order is to begin with
ce06c9f0 442 DENY entries followed by ALLOW, otherwise an allow entry could be
15b03959 443 encountered first, making the subsequent deny entry like "dead code"
ce06c9f0 444 which would be superflous since Windows stops when a match is made
15b03959
SF
445 for the operation you are trying to perform for your user */
446
447 /* For deny ACEs we change the mask so that subsequent allow access
448 control entries do not turn on the bits we are denying */
449 if (type == ACCESS_DENIED) {
ad7a2926 450 if (flags & GENERIC_ALL)
15b03959 451 *pbits_to_set &= ~S_IRWXUGO;
ad7a2926 452
9b5e6857
AV
453 if ((flags & GENERIC_WRITE) ||
454 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 455 *pbits_to_set &= ~S_IWUGO;
9b5e6857
AV
456 if ((flags & GENERIC_READ) ||
457 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 458 *pbits_to_set &= ~S_IRUGO;
9b5e6857
AV
459 if ((flags & GENERIC_EXECUTE) ||
460 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959
SF
461 *pbits_to_set &= ~S_IXUGO;
462 return;
463 } else if (type != ACCESS_ALLOWED) {
f96637be 464 cifs_dbg(VFS, "unknown access control type %d\n", type);
15b03959
SF
465 return;
466 }
467 /* else ACCESS_ALLOWED type */
630f3f0c 468
9b5e6857 469 if (flags & GENERIC_ALL) {
15b03959 470 *pmode |= (S_IRWXUGO & (*pbits_to_set));
f96637be 471 cifs_dbg(NOISY, "all perms\n");
d61e5808
SF
472 return;
473 }
9b5e6857
AV
474 if ((flags & GENERIC_WRITE) ||
475 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 476 *pmode |= (S_IWUGO & (*pbits_to_set));
9b5e6857
AV
477 if ((flags & GENERIC_READ) ||
478 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 479 *pmode |= (S_IRUGO & (*pbits_to_set));
9b5e6857
AV
480 if ((flags & GENERIC_EXECUTE) ||
481 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959 482 *pmode |= (S_IXUGO & (*pbits_to_set));
630f3f0c 483
f96637be 484 cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode);
630f3f0c
SF
485 return;
486}
487
ce06c9f0
SF
488/*
489 Generate access flags to reflect permissions mode is the existing mode.
490 This function is called for every ACE in the DACL whose SID matches
491 with either owner or group or everyone.
492*/
493
494static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
495 __u32 *pace_flags)
496{
497 /* reset access mask */
498 *pace_flags = 0x0;
499
500 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
501 mode &= bits_to_use;
502
503 /* check for R/W/X UGO since we do not know whose flags
504 is this but we have cleared all the bits sans RWX for
505 either user or group or other as per bits_to_use */
506 if (mode & S_IRUGO)
507 *pace_flags |= SET_FILE_READ_RIGHTS;
508 if (mode & S_IWUGO)
509 *pace_flags |= SET_FILE_WRITE_RIGHTS;
510 if (mode & S_IXUGO)
511 *pace_flags |= SET_FILE_EXEC_RIGHTS;
512
f96637be
JP
513 cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n",
514 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) {
f96637be 554 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
44093ca2
SF
555 return;
556 }
557
558 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
f96637be 559 cifs_dbg(VFS, "ACL too small to parse ACE\n");
d0d66c44 560 return;
44093ca2 561 }
d0d66c44 562
44093ca2 563 num_subauth = pace->sid.num_subauth;
d0d66c44 564 if (num_subauth) {
8f18c131 565 int i;
f96637be
JP
566 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
567 pace->sid.revision, pace->sid.num_subauth, pace->type,
568 pace->flags, le16_to_cpu(pace->size));
d12fd121 569 for (i = 0; i < num_subauth; ++i) {
f96637be
JP
570 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
571 i, 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)) {
f96637be 604 cifs_dbg(VFS, "ACL too small to parse DACL\n");
d0d66c44
SP
605 return;
606 }
607
f96637be
JP
608 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
609 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
610 le32_to_cpu(pdacl->num_aces));
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);
f96637be 630 if (!ppace)
8132b65b 631 return;
d0d66c44 632
d0d66c44 633 for (i = 0; i < num_aces; ++i) {
44093ca2 634 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
953f8681
SF
635#ifdef CONFIG_CIFS_DEBUG2
636 dump_ace(ppace[i], end_of_acl);
637#endif
9409ae58 638 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
e01b6400 639 access_flags_to_mode(ppace[i]->access_req,
15b03959 640 ppace[i]->type,
0b8f18e3 641 &fattr->cf_mode,
15b03959 642 &user_mask);
9409ae58 643 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
e01b6400 644 access_flags_to_mode(ppace[i]->access_req,
15b03959 645 ppace[i]->type,
0b8f18e3 646 &fattr->cf_mode,
15b03959 647 &group_mask);
9409ae58 648 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
e01b6400 649 access_flags_to_mode(ppace[i]->access_req,
15b03959 650 ppace[i]->type,
0b8f18e3 651 &fattr->cf_mode,
15b03959 652 &other_mask);
9409ae58 653 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
2fbc2f17
SP
654 access_flags_to_mode(ppace[i]->access_req,
655 ppace[i]->type,
656 &fattr->cf_mode,
657 &other_mask);
658
e01b6400 659
44093ca2 660/* memcpy((void *)(&(cifscred->aces[i])),
d12fd121
SF
661 (void *)ppace[i],
662 sizeof(struct cifs_ace)); */
d0d66c44 663
44093ca2
SF
664 acl_base = (char *)ppace[i];
665 acl_size = le16_to_cpu(ppace[i]->size);
d0d66c44
SP
666 }
667
668 kfree(ppace);
d0d66c44
SP
669 }
670
671 return;
672}
673
bcb02034 674
97837582
SF
675static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
676 struct cifs_sid *pgrpsid, __u64 nmode)
677{
2b210adc 678 u16 size = 0;
97837582
SF
679 struct cifs_acl *pnndacl;
680
681 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
682
683 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
684 pownersid, nmode, S_IRWXU);
685 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
686 pgrpsid, nmode, S_IRWXG);
687 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
688 &sid_everyone, nmode, S_IRWXO);
689
690 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
d9f382ef 691 pndacl->num_aces = cpu_to_le32(3);
97837582 692
ef571cad 693 return 0;
97837582
SF
694}
695
696
bcb02034
SF
697static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
698{
699 /* BB need to add parm so we can store the SID BB */
700
b9c7a2bb
SF
701 /* validate that we do not go past end of ACL - sid must be at least 8
702 bytes long (assuming no sub-auths - e.g. the null SID */
703 if (end_of_acl < (char *)psid + 8) {
f96637be 704 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
bcb02034
SF
705 return -EINVAL;
706 }
d0d66c44 707
bcb02034 708#ifdef CONFIG_CIFS_DEBUG2
fc03d8a5 709 if (psid->num_subauth) {
8f18c131 710 int i;
f96637be
JP
711 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
712 psid->revision, psid->num_subauth);
bcb02034 713
af6f4612 714 for (i = 0; i < psid->num_subauth; i++) {
f96637be
JP
715 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
716 i, le32_to_cpu(psid->sub_auth[i]));
d0d66c44
SP
717 }
718
d12fd121 719 /* BB add length check to make sure that we do not have huge
d0d66c44 720 num auths and therefore go off the end */
f96637be
JP
721 cifs_dbg(FYI, "RID 0x%x\n",
722 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
d0d66c44 723 }
fc03d8a5 724#endif
d0d66c44 725
bcb02034
SF
726 return 0;
727}
728
d0d66c44 729
bcb02034 730/* Convert CIFS ACL to POSIX form */
9409ae58
SP
731static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
732 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
bcb02034 733{
9409ae58 734 int rc = 0;
bcb02034
SF
735 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
736 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
bcb02034 737 char *end_of_acl = ((char *)pntsd) + acl_len;
7505e052 738 __u32 dacloffset;
bcb02034 739
0b8f18e3 740 if (pntsd == NULL)
b9c7a2bb
SF
741 return -EIO;
742
bcb02034 743 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 744 le32_to_cpu(pntsd->osidoffset));
bcb02034 745 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 746 le32_to_cpu(pntsd->gsidoffset));
7505e052 747 dacloffset = le32_to_cpu(pntsd->dacloffset);
63d2583f 748 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
f96637be 749 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
af6f4612
SF
750 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
751 le32_to_cpu(pntsd->gsidoffset),
b6b38f70 752 le32_to_cpu(pntsd->sacloffset), dacloffset);
b9c7a2bb 753/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
bcb02034 754 rc = parse_sid(owner_sid_ptr, end_of_acl);
9409ae58 755 if (rc) {
f96637be 756 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
9409ae58
SP
757 return rc;
758 }
759 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
760 if (rc) {
f96637be
JP
761 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
762 __func__, rc);
bcb02034 763 return rc;
9409ae58 764 }
bcb02034
SF
765
766 rc = parse_sid(group_sid_ptr, end_of_acl);
9409ae58 767 if (rc) {
f96637be
JP
768 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
769 __func__, rc);
bcb02034 770 return rc;
9409ae58
SP
771 }
772 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
773 if (rc) {
f96637be
JP
774 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
775 __func__, rc);
9409ae58
SP
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
f96637be 783 cifs_dbg(FYI, "no ACL\n"); /* 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 832 if (rc) {
f96637be
JP
833 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
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 852 if (rc) {
f96637be
JP
853 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
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
42eacf9e
SF
867struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
868 const struct cifs_fid *cifsfid, 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();
42eacf9e
SF
879 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
880 pacllen);
6d5786a3 881 free_xid(xid);
b9c7a2bb 882
7ffec372 883 cifs_put_tlink(tlink);
b9c7a2bb 884
f96637be 885 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
987b21d7
SP
886 if (rc)
887 return ERR_PTR(rc);
1bf4072d
CH
888 return pntsd;
889}
8b1327f6 890
1bf4072d
CH
891static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
892 const char *path, u32 *pacllen)
893{
894 struct cifs_ntsd *pntsd = NULL;
895 int oplock = 0;
6d5786a3
PS
896 unsigned int xid;
897 int rc, create_options = 0;
96daf2b0 898 struct cifs_tcon *tcon;
7ffec372 899 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40
PS
900 struct cifs_fid fid;
901 struct cifs_open_parms oparms;
7ffec372
JL
902
903 if (IS_ERR(tlink))
987b21d7 904 return ERR_CAST(tlink);
b9c7a2bb 905
7ffec372 906 tcon = tlink_tcon(tlink);
6d5786a3 907 xid = get_xid();
1bf4072d 908
3d3ea8e6
SP
909 if (backup_cred(cifs_sb))
910 create_options |= CREATE_OPEN_BACKUP_INTENT;
911
d81b8a40
PS
912 oparms.tcon = tcon;
913 oparms.cifs_sb = cifs_sb;
914 oparms.desired_access = READ_CONTROL;
915 oparms.create_options = create_options;
916 oparms.disposition = FILE_OPEN;
917 oparms.path = path;
918 oparms.fid = &fid;
919 oparms.reconnect = false;
920
921 rc = CIFS_open(xid, &oparms, &oplock, NULL);
987b21d7 922 if (!rc) {
d81b8a40
PS
923 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
924 CIFSSMBClose(xid, tcon, fid.netfid);
b9c7a2bb
SF
925 }
926
7ffec372 927 cifs_put_tlink(tlink);
6d5786a3 928 free_xid(xid);
987b21d7 929
f96637be 930 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
987b21d7
SP
931 if (rc)
932 return ERR_PTR(rc);
7505e052
SF
933 return pntsd;
934}
935
1bf4072d 936/* Retrieve an ACL from the server */
fbeba8bb 937struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1bf4072d
CH
938 struct inode *inode, const char *path,
939 u32 *pacllen)
940{
941 struct cifs_ntsd *pntsd = NULL;
942 struct cifsFileInfo *open_file = NULL;
943
944 if (inode)
6508d904 945 open_file = find_readable_file(CIFS_I(inode), true);
1bf4072d
CH
946 if (!open_file)
947 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
948
42eacf9e 949 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
6ab409b5 950 cifsFileInfo_put(open_file);
1bf4072d
CH
951 return pntsd;
952}
953
a5ff3769
SP
954 /* Set an ACL on the server */
955int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
956 struct inode *inode, const char *path, int aclflag)
b96d31a6
CH
957{
958 int oplock = 0;
6d5786a3
PS
959 unsigned int xid;
960 int rc, access_flags, create_options = 0;
96daf2b0 961 struct cifs_tcon *tcon;
a5ff3769 962 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec372 963 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40
PS
964 struct cifs_fid fid;
965 struct cifs_open_parms oparms;
97837582 966
7ffec372
JL
967 if (IS_ERR(tlink))
968 return PTR_ERR(tlink);
969
970 tcon = tlink_tcon(tlink);
6d5786a3 971 xid = get_xid();
97837582 972
3d3ea8e6
SP
973 if (backup_cred(cifs_sb))
974 create_options |= CREATE_OPEN_BACKUP_INTENT;
975
a5ff3769
SP
976 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
977 access_flags = WRITE_OWNER;
978 else
979 access_flags = WRITE_DAC;
980
d81b8a40
PS
981 oparms.tcon = tcon;
982 oparms.cifs_sb = cifs_sb;
983 oparms.desired_access = access_flags;
984 oparms.create_options = create_options;
985 oparms.disposition = FILE_OPEN;
986 oparms.path = path;
987 oparms.fid = &fid;
988 oparms.reconnect = false;
989
990 rc = CIFS_open(xid, &oparms, &oplock, NULL);
b96d31a6 991 if (rc) {
f96637be 992 cifs_dbg(VFS, "Unable to open file to set ACL\n");
b96d31a6 993 goto out;
97837582
SF
994 }
995
d81b8a40 996 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
f96637be 997 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
97837582 998
d81b8a40 999 CIFSSMBClose(xid, tcon, fid.netfid);
7ffec372 1000out:
6d5786a3 1001 free_xid(xid);
7ffec372 1002 cifs_put_tlink(tlink);
b96d31a6
CH
1003 return rc;
1004}
97837582 1005
7505e052 1006/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
987b21d7 1007int
0b8f18e3 1008cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
42eacf9e
SF
1009 struct inode *inode, const char *path,
1010 const struct cifs_fid *pfid)
7505e052
SF
1011{
1012 struct cifs_ntsd *pntsd = NULL;
1013 u32 acllen = 0;
1014 int rc = 0;
42eacf9e
SF
1015 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1016 struct cifs_tcon *tcon;
7505e052 1017
f96637be 1018 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1bf4072d 1019
42eacf9e
SF
1020 if (IS_ERR(tlink))
1021 return PTR_ERR(tlink);
1022 tcon = tlink_tcon(tlink);
7505e052 1023
42eacf9e
SF
1024 if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
1025 pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
1026 &acllen);
1027 else if (tcon->ses->server->ops->get_acl)
1028 pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1029 &acllen);
1030 else {
1031 cifs_put_tlink(tlink);
1032 return -EOPNOTSUPP;
1033 }
7505e052 1034 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
987b21d7
SP
1035 if (IS_ERR(pntsd)) {
1036 rc = PTR_ERR(pntsd);
f96637be 1037 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
987b21d7 1038 } else {
9409ae58 1039 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
987b21d7
SP
1040 kfree(pntsd);
1041 if (rc)
f96637be 1042 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
987b21d7 1043 }
7505e052 1044
42eacf9e
SF
1045 cifs_put_tlink(tlink);
1046
987b21d7 1047 return rc;
b9c7a2bb 1048}
953f8681 1049
7505e052 1050/* Convert mode bits to an ACL so we can update the ACL on the server */
a5ff3769
SP
1051int
1052id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
8abf2775 1053 kuid_t uid, kgid_t gid)
953f8681
SF
1054{
1055 int rc = 0;
a5ff3769 1056 int aclflag = CIFS_ACL_DACL; /* default flag to set */
cce246ee 1057 __u32 secdesclen = 0;
97837582
SF
1058 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1059 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
83e3bc23
SF
1060 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1061 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1062 struct cifs_tcon *tcon;
1063
1064 if (IS_ERR(tlink))
1065 return PTR_ERR(tlink);
1066 tcon = tlink_tcon(tlink);
953f8681 1067
f96637be 1068 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
953f8681
SF
1069
1070 /* Get the security descriptor */
83e3bc23
SF
1071
1072 if (tcon->ses->server->ops->get_acl == NULL) {
1073 cifs_put_tlink(tlink);
1074 return -EOPNOTSUPP;
1075 }
1076
1077 pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1078 &secdesclen);
987b21d7
SP
1079 if (IS_ERR(pntsd)) {
1080 rc = PTR_ERR(pntsd);
f96637be 1081 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
83e3bc23
SF
1082 cifs_put_tlink(tlink);
1083 return rc;
c78cd838 1084 }
7505e052 1085
c78cd838
JL
1086 /*
1087 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1088 * as chmod disables ACEs and set the security descriptor. Allocate
1089 * memory for the smb header, set security descriptor request security
1090 * descriptor parameters, and secuirty descriptor itself
1091 */
7ee0b4c6 1092 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
c78cd838
JL
1093 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1094 if (!pnntsd) {
c78cd838 1095 kfree(pntsd);
83e3bc23 1096 cifs_put_tlink(tlink);
c78cd838
JL
1097 return -ENOMEM;
1098 }
97837582 1099
c78cd838
JL
1100 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1101 &aclflag);
97837582 1102
f96637be 1103 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
97837582 1104
83e3bc23
SF
1105 if (tcon->ses->server->ops->set_acl == NULL)
1106 rc = -EOPNOTSUPP;
1107
c78cd838
JL
1108 if (!rc) {
1109 /* Set the security descriptor */
83e3bc23
SF
1110 rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
1111 path, aclflag);
f96637be 1112 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
97837582 1113 }
83e3bc23 1114 cifs_put_tlink(tlink);
97837582 1115
c78cd838
JL
1116 kfree(pnntsd);
1117 kfree(pntsd);
ef571cad 1118 return rc;
953f8681 1119}