overlayfs: Implement splice-read
[linux-block.git] / fs / cifs / cifsacl.c
CommitLineData
929be906 1// SPDX-License-Identifier: LGPL-2.1
bcb02034 2/*
bcb02034 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 *
bcb02034
SF
9 */
10
65874007 11#include <linux/fs.h>
5a0e3ad6 12#include <linux/slab.h>
4d79dba0
SP
13#include <linux/string.h>
14#include <linux/keyctl.h>
15#include <linux/key-type.h>
bd9684b0 16#include <uapi/linux/posix_acl.h>
dc1af4c4
CB
17#include <linux/posix_acl.h>
18#include <linux/posix_acl_xattr.h>
4d79dba0 19#include <keys/user-type.h>
65874007
SF
20#include "cifspdu.h"
21#include "cifsglob.h"
d0d66c44 22#include "cifsacl.h"
65874007
SF
23#include "cifsproto.h"
24#include "cifs_debug.h"
8401e936 25#include "fs_context.h"
bd9684b0
CB
26#include "cifs_fs_sb.h"
27#include "cifs_unicode.h"
65874007 28
2fbc2f17 29/* security id for everyone/world system group */
e01b6400
SP
30static const struct cifs_sid sid_everyone = {
31 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
2fbc2f17
SP
32/* security id for Authenticated Users system group */
33static const struct cifs_sid sid_authusers = {
bc09d141 34 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
d0d66c44 35
3514de3f
SF
36/* S-1-22-1 Unmapped Unix users */
37static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
38 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
39
40/* S-1-22-2 Unmapped Unix groups */
41static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
42 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
43
44/*
cba22b1c 45 * See https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
3514de3f
SF
46 */
47
48/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
49
50/* S-1-5-88-1 Unix uid */
51static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
52 {cpu_to_le32(88),
53 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
54
55/* S-1-5-88-2 Unix gid */
56static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
57 {cpu_to_le32(88),
58 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
59
60/* S-1-5-88-3 Unix mode */
61static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
62 {cpu_to_le32(88),
63 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
64
b1a6dc21 65static const struct cred *root_cred;
9409ae58 66
4d79dba0 67static int
cf7f601c 68cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
4d79dba0
SP
69{
70 char *payload;
71
41a9f1f6
JL
72 /*
73 * If the payload is less than or equal to the size of a pointer, then
74 * an allocation here is wasteful. Just copy the data directly to the
75 * payload.value union member instead.
76 *
77 * With this however, you must check the datalen before trying to
78 * dereference payload.data!
79 */
1f630680 80 if (prep->datalen <= sizeof(key->payload)) {
146aa8b1
DH
81 key->payload.data[0] = NULL;
82 memcpy(&key->payload, prep->data, prep->datalen);
83 } else {
84 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
85 if (!payload)
86 return -ENOMEM;
87 key->payload.data[0] = payload;
41a9f1f6 88 }
4d79dba0 89
cf7f601c 90 key->datalen = prep->datalen;
4d79dba0
SP
91 return 0;
92}
93
94static inline void
95cifs_idmap_key_destroy(struct key *key)
96{
1f630680 97 if (key->datalen > sizeof(key->payload))
146aa8b1 98 kfree(key->payload.data[0]);
4d79dba0
SP
99}
100
b1a6dc21 101static struct key_type cifs_idmap_key_type = {
c4aca0c0 102 .name = "cifs.idmap",
4d79dba0
SP
103 .instantiate = cifs_idmap_key_instantiate,
104 .destroy = cifs_idmap_key_destroy,
105 .describe = user_describe,
4d79dba0
SP
106};
107
faa65f07
JL
108static char *
109sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
9409ae58 110{
faa65f07 111 int i, len;
ee13b2ba 112 unsigned int saval;
faa65f07 113 char *sidstr, *strptr;
193cdd8a 114 unsigned long long id_auth_val;
9409ae58 115
faa65f07
JL
116 /* 3 bytes for prefix */
117 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
118 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
119 GFP_KERNEL);
120 if (!sidstr)
121 return sidstr;
9409ae58 122
faa65f07
JL
123 strptr = sidstr;
124 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
125 sidptr->revision);
126 strptr += len;
9409ae58 127
193cdd8a
JL
128 /* The authority field is a single 48-bit number */
129 id_auth_val = (unsigned long long)sidptr->authority[5];
130 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
131 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
132 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
133 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
134 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
135
136 /*
137 * MS-DTYP states that if the authority is >= 2^32, then it should be
138 * expressed as a hex value.
139 */
140 if (id_auth_val <= UINT_MAX)
141 len = sprintf(strptr, "-%llu", id_auth_val);
142 else
143 len = sprintf(strptr, "-0x%llx", id_auth_val);
144
145 strptr += len;
9409ae58
SP
146
147 for (i = 0; i < sidptr->num_subauth; ++i) {
148 saval = le32_to_cpu(sidptr->sub_auth[i]);
faa65f07
JL
149 len = sprintf(strptr, "-%u", saval);
150 strptr += len;
9409ae58 151 }
faa65f07
JL
152
153 return sidstr;
9409ae58
SP
154}
155
436bb435
JL
156/*
157 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
158 * the same returns zero, if they do not match returns non-zero.
159 */
160static int
161compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
162{
163 int i;
164 int num_subauth, num_sat, num_saw;
165
166 if ((!ctsid) || (!cwsid))
167 return 1;
168
169 /* compare the revision */
170 if (ctsid->revision != cwsid->revision) {
171 if (ctsid->revision > cwsid->revision)
172 return 1;
173 else
174 return -1;
175 }
176
177 /* compare all of the six auth values */
178 for (i = 0; i < NUM_AUTHS; ++i) {
179 if (ctsid->authority[i] != cwsid->authority[i]) {
180 if (ctsid->authority[i] > cwsid->authority[i])
181 return 1;
182 else
183 return -1;
184 }
185 }
186
187 /* compare all of the subauth values if any */
188 num_sat = ctsid->num_subauth;
189 num_saw = cwsid->num_subauth;
190 num_subauth = num_sat < num_saw ? num_sat : num_saw;
191 if (num_subauth) {
192 for (i = 0; i < num_subauth; ++i) {
193 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
194 if (le32_to_cpu(ctsid->sub_auth[i]) >
195 le32_to_cpu(cwsid->sub_auth[i]))
196 return 1;
197 else
198 return -1;
199 }
200 }
201 }
202
203 return 0; /* sids compare/match */
204}
205
3514de3f
SF
206static bool
207is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
208{
209 int i;
210 int num_subauth;
211 const struct cifs_sid *pwell_known_sid;
212
213 if (!psid || (puid == NULL))
214 return false;
215
216 num_subauth = psid->num_subauth;
217
218 /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
219 if (num_subauth == 2) {
220 if (is_group)
221 pwell_known_sid = &sid_unix_groups;
222 else
223 pwell_known_sid = &sid_unix_users;
224 } else if (num_subauth == 3) {
225 if (is_group)
226 pwell_known_sid = &sid_unix_NFS_groups;
227 else
228 pwell_known_sid = &sid_unix_NFS_users;
229 } else
230 return false;
231
232 /* compare the revision */
233 if (psid->revision != pwell_known_sid->revision)
234 return false;
235
236 /* compare all of the six auth values */
237 for (i = 0; i < NUM_AUTHS; ++i) {
238 if (psid->authority[i] != pwell_known_sid->authority[i]) {
239 cifs_dbg(FYI, "auth %d did not match\n", i);
240 return false;
241 }
242 }
243
244 if (num_subauth == 2) {
245 if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
246 return false;
247
248 *puid = le32_to_cpu(psid->sub_auth[1]);
249 } else /* 3 subauths, ie Windows/Mac style */ {
250 *puid = le32_to_cpu(psid->sub_auth[0]);
251 if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
252 (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
253 return false;
254
255 *puid = le32_to_cpu(psid->sub_auth[2]);
256 }
257
258 cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
259 return true; /* well known sid found, uid returned */
260}
261
f5065508 262static __u16
36960e44
JL
263cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
264{
36f87ee7 265 int i;
f5065508 266 __u16 size = 1 + 1 + 6;
36f87ee7
JL
267
268 dst->revision = src->revision;
30c9d6cc 269 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
36f87ee7
JL
270 for (i = 0; i < NUM_AUTHS; ++i)
271 dst->authority[i] = src->authority[i];
272 for (i = 0; i < dst->num_subauth; ++i)
273 dst->sub_auth[i] = src->sub_auth[i];
f5065508
SP
274 size += (dst->num_subauth * 4);
275
276 return size;
36960e44
JL
277}
278
9409ae58 279static int
faa65f07 280id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
9409ae58 281{
faa65f07 282 int rc;
21fed0d5 283 struct key *sidkey;
2ae03025
JL
284 struct cifs_sid *ksid;
285 unsigned int ksid_size;
faa65f07 286 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
21fed0d5 287 const struct cred *saved_cred;
21fed0d5 288
faa65f07
JL
289 rc = snprintf(desc, sizeof(desc), "%ci:%u",
290 sidtype == SIDOWNER ? 'o' : 'g', cid);
291 if (rc >= sizeof(desc))
292 return -EINVAL;
21fed0d5 293
faa65f07
JL
294 rc = 0;
295 saved_cred = override_creds(root_cred);
028db3e2 296 sidkey = request_key(&cifs_idmap_key_type, desc, "");
faa65f07 297 if (IS_ERR(sidkey)) {
21fed0d5 298 rc = -EINVAL;
f96637be
JP
299 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
300 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
faa65f07
JL
301 goto out_revert_creds;
302 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
303 rc = -EIO;
f96637be
JP
304 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
305 __func__, sidkey->datalen);
2ae03025 306 goto invalidate_key;
21fed0d5 307 }
2ae03025 308
1f630680
JL
309 /*
310 * A sid is usually too large to be embedded in payload.value, but if
311 * there are no subauthorities and the host has 8-byte pointers, then
312 * it could be.
313 */
314 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
146aa8b1
DH
315 (struct cifs_sid *)&sidkey->payload :
316 (struct cifs_sid *)sidkey->payload.data[0];
1f630680 317
2ae03025
JL
318 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
319 if (ksid_size > sidkey->datalen) {
320 rc = -EIO;
f96637be
JP
321 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
322 __func__, sidkey->datalen, ksid_size);
2ae03025
JL
323 goto invalidate_key;
324 }
1f630680 325
2ae03025 326 cifs_copy_sid(ssid, ksid);
faa65f07
JL
327out_key_put:
328 key_put(sidkey);
329out_revert_creds:
330 revert_creds(saved_cred);
21fed0d5 331 return rc;
2ae03025
JL
332
333invalidate_key:
334 key_invalidate(sidkey);
335 goto out_key_put;
21fed0d5
SP
336}
337
9934430e 338int
9409ae58
SP
339sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
340 struct cifs_fattr *fattr, uint sidtype)
341{
f2d67931 342 int rc = 0;
faa65f07
JL
343 struct key *sidkey;
344 char *sidstr;
9409ae58 345 const struct cred *saved_cred;
8401e936
RS
346 kuid_t fuid = cifs_sb->ctx->linux_uid;
347 kgid_t fgid = cifs_sb->ctx->linux_gid;
9409ae58
SP
348
349 /*
faa65f07
JL
350 * If we have too many subauthorities, then something is really wrong.
351 * Just return an error.
9409ae58 352 */
faa65f07 353 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
f96637be
JP
354 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
355 __func__, psid->num_subauth);
faa65f07 356 return -EIO;
9409ae58
SP
357 }
358
9934430e
SF
359 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
360 (cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
3514de3f
SF
361 uint32_t unix_id;
362 bool is_group;
363
364 if (sidtype != SIDOWNER)
365 is_group = true;
366 else
367 is_group = false;
368
369 if (is_well_known_sid(psid, &unix_id, is_group) == false)
370 goto try_upcall_to_get_id;
371
372 if (is_group) {
373 kgid_t gid;
374 gid_t id;
375
376 id = (gid_t)unix_id;
377 gid = make_kgid(&init_user_ns, id);
378 if (gid_valid(gid)) {
379 fgid = gid;
380 goto got_valid_id;
381 }
382 } else {
383 kuid_t uid;
384 uid_t id;
385
386 id = (uid_t)unix_id;
387 uid = make_kuid(&init_user_ns, id);
388 if (uid_valid(uid)) {
389 fuid = uid;
390 goto got_valid_id;
391 }
392 }
393 /* If unable to find uid/gid easily from SID try via upcall */
394 }
395
396try_upcall_to_get_id:
faa65f07
JL
397 sidstr = sid_to_key_str(psid, sidtype);
398 if (!sidstr)
399 return -ENOMEM;
400
401 saved_cred = override_creds(root_cred);
028db3e2 402 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
faa65f07 403 if (IS_ERR(sidkey)) {
f96637be
JP
404 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
405 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
faa65f07
JL
406 goto out_revert_creds;
407 }
408
409 /*
410 * FIXME: Here we assume that uid_t and gid_t are same size. It's
411 * probably a safe assumption but might be better to check based on
412 * sidtype.
413 */
355958f2 414 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
41a9f1f6 415 if (sidkey->datalen != sizeof(uid_t)) {
f96637be
JP
416 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
417 __func__, sidkey->datalen);
2ae03025 418 key_invalidate(sidkey);
faa65f07 419 goto out_key_put;
9409ae58
SP
420 }
421
8abf2775
EB
422 if (sidtype == SIDOWNER) {
423 kuid_t uid;
424 uid_t id;
146aa8b1 425 memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
8abf2775
EB
426 uid = make_kuid(&init_user_ns, id);
427 if (uid_valid(uid))
428 fuid = uid;
429 } else {
430 kgid_t gid;
431 gid_t id;
146aa8b1 432 memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
8abf2775
EB
433 gid = make_kgid(&init_user_ns, id);
434 if (gid_valid(gid))
435 fgid = gid;
436 }
faa65f07
JL
437
438out_key_put:
439 key_put(sidkey);
440out_revert_creds:
441 revert_creds(saved_cred);
442 kfree(sidstr);
9409ae58 443
faa65f07
JL
444 /*
445 * Note that we return 0 here unconditionally. If the mapping
8401e936 446 * fails then we just fall back to using the ctx->linux_uid/linux_gid.
faa65f07 447 */
3514de3f 448got_valid_id:
f2d67931 449 rc = 0;
faa65f07
JL
450 if (sidtype == SIDOWNER)
451 fattr->cf_uid = fuid;
452 else
453 fattr->cf_gid = fgid;
f2d67931 454 return rc;
9409ae58
SP
455}
456
4d79dba0
SP
457int
458init_cifs_idmap(void)
459{
460 struct cred *cred;
461 struct key *keyring;
462 int ret;
463
f96637be
JP
464 cifs_dbg(FYI, "Registering the %s key type\n",
465 cifs_idmap_key_type.name);
4d79dba0
SP
466
467 /* create an override credential set with a special thread keyring in
468 * which requests are cached
469 *
470 * this is used to prevent malicious redirections from being installed
471 * with add_key().
472 */
5a17f040 473 cred = prepare_kernel_cred(&init_task);
4d79dba0
SP
474 if (!cred)
475 return -ENOMEM;
476
8e3028b9
EB
477 keyring = keyring_alloc(".cifs_idmap",
478 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
028db3e2
LT
479 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
480 KEY_USR_VIEW | KEY_USR_READ,
5ac7eace 481 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
4d79dba0
SP
482 if (IS_ERR(keyring)) {
483 ret = PTR_ERR(keyring);
484 goto failed_put_cred;
485 }
486
4d79dba0
SP
487 ret = register_key_type(&cifs_idmap_key_type);
488 if (ret < 0)
489 goto failed_put_key;
490
491 /* instruct request_key() to use this special keyring as a cache for
492 * the results it looks up */
700920eb 493 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
4d79dba0
SP
494 cred->thread_keyring = keyring;
495 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
496 root_cred = cred;
497
f96637be 498 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
4d79dba0
SP
499 return 0;
500
501failed_put_key:
502 key_put(keyring);
503failed_put_cred:
504 put_cred(cred);
505 return ret;
506}
507
508void
509exit_cifs_idmap(void)
510{
511 key_revoke(root_cred->thread_keyring);
512 unregister_key_type(&cifs_idmap_key_type);
513 put_cred(root_cred);
f96637be 514 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
4d79dba0
SP
515}
516
97837582 517/* copy ntsd, owner sid, and group sid from a security descriptor to another */
bc3e9dd9
SP
518static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd,
519 struct cifs_ntsd *pnntsd,
520 __u32 sidsoffset,
521 struct cifs_sid *pownersid,
522 struct cifs_sid *pgrpsid)
97837582 523{
97837582
SF
524 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
525 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
526
527 /* copy security descriptor control portion */
528 pnntsd->revision = pntsd->revision;
529 pnntsd->type = pntsd->type;
530 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
531 pnntsd->sacloffset = 0;
532 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
533 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
534
535 /* copy owner sid */
bc3e9dd9
SP
536 if (pownersid)
537 owner_sid_ptr = pownersid;
538 else
539 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582
SF
540 le32_to_cpu(pntsd->osidoffset));
541 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
36960e44 542 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
97837582
SF
543
544 /* copy group sid */
bc3e9dd9
SP
545 if (pgrpsid)
546 group_sid_ptr = pgrpsid;
547 else
548 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582
SF
549 le32_to_cpu(pntsd->gsidoffset));
550 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
551 sizeof(struct cifs_sid));
36960e44 552 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
97837582 553
bc3e9dd9 554 return sidsoffset + (2 * sizeof(struct cifs_sid));
97837582
SF
555}
556
557
630f3f0c
SF
558/*
559 change posix mode to reflect permissions
560 pmode is the existing mode (we only want to overwrite part of this
561 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
562*/
9b5e6857 563static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
0f22053e 564 umode_t *pdenied, umode_t mask)
630f3f0c 565{
9b5e6857 566 __u32 flags = le32_to_cpu(ace_flags);
0f22053e
SP
567 /*
568 * Do not assume "preferred" or "canonical" order.
569 * The first DENY or ALLOW ACE which matches perfectly is
570 * the permission to be used. Once allowed or denied, same
571 * permission in later ACEs do not matter.
572 */
573
574 /* If not already allowed, deny these bits */
15b03959 575 if (type == ACCESS_DENIED) {
0f22053e
SP
576 if (flags & GENERIC_ALL &&
577 !(*pmode & mask & 0777))
578 *pdenied |= mask & 0777;
579
580 if (((flags & GENERIC_WRITE) ||
581 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
582 !(*pmode & mask & 0222))
583 *pdenied |= mask & 0222;
584
585 if (((flags & GENERIC_READ) ||
586 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
587 !(*pmode & mask & 0444))
588 *pdenied |= mask & 0444;
589
590 if (((flags & GENERIC_EXECUTE) ||
591 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
592 !(*pmode & mask & 0111))
593 *pdenied |= mask & 0111;
594
15b03959
SF
595 return;
596 } else if (type != ACCESS_ALLOWED) {
f96637be 597 cifs_dbg(VFS, "unknown access control type %d\n", type);
15b03959
SF
598 return;
599 }
600 /* else ACCESS_ALLOWED type */
630f3f0c 601
0f22053e
SP
602 if ((flags & GENERIC_ALL) &&
603 !(*pdenied & mask & 0777)) {
604 *pmode |= mask & 0777;
f96637be 605 cifs_dbg(NOISY, "all perms\n");
d61e5808
SF
606 return;
607 }
0f22053e
SP
608
609 if (((flags & GENERIC_WRITE) ||
610 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
611 !(*pdenied & mask & 0222))
612 *pmode |= mask & 0222;
613
614 if (((flags & GENERIC_READ) ||
615 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
616 !(*pdenied & mask & 0444))
617 *pmode |= mask & 0444;
618
619 if (((flags & GENERIC_EXECUTE) ||
620 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
621 !(*pdenied & mask & 0111))
622 *pmode |= mask & 0111;
630f3f0c 623
f2156d35
SP
624 /* If DELETE_CHILD is set only on an owner ACE, set sticky bit */
625 if (flags & FILE_DELETE_CHILD) {
626 if (mask == ACL_OWNER_MASK) {
627 if (!(*pdenied & 01000))
628 *pmode |= 01000;
629 } else if (!(*pdenied & 01000)) {
630 *pmode &= ~01000;
631 *pdenied |= 01000;
632 }
633 }
634
f52aa79d 635 cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode);
630f3f0c
SF
636 return;
637}
638
ce06c9f0
SF
639/*
640 Generate access flags to reflect permissions mode is the existing mode.
641 This function is called for every ACE in the DACL whose SID matches
642 with either owner or group or everyone.
643*/
644
645static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
646 __u32 *pace_flags)
647{
648 /* reset access mask */
649 *pace_flags = 0x0;
650
651 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
652 mode &= bits_to_use;
653
654 /* check for R/W/X UGO since we do not know whose flags
655 is this but we have cleared all the bits sans RWX for
656 either user or group or other as per bits_to_use */
657 if (mode & S_IRUGO)
658 *pace_flags |= SET_FILE_READ_RIGHTS;
659 if (mode & S_IWUGO)
660 *pace_flags |= SET_FILE_WRITE_RIGHTS;
661 if (mode & S_IXUGO)
662 *pace_flags |= SET_FILE_EXEC_RIGHTS;
663
f52aa79d 664 cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n",
f96637be 665 mode, *pace_flags);
ce06c9f0
SF
666 return;
667}
668
bc3e9dd9 669static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct cifs_sid *psid)
f5065508
SP
670{
671 __u16 size = 1 + 1 + 2 + 4;
672
673 dst->type = src->type;
674 dst->flags = src->flags;
f5065508 675 dst->access_req = src->access_req;
bc3e9dd9
SP
676
677 /* Check if there's a replacement sid specified */
678 if (psid)
679 size += cifs_copy_sid(&dst->sid, psid);
680 else
681 size += cifs_copy_sid(&dst->sid, &src->sid);
682
683 dst->size = cpu_to_le16(size);
f5065508
SP
684
685 return size;
686}
687
2b210adc 688static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
f2156d35
SP
689 const struct cifs_sid *psid, __u64 nmode,
690 umode_t bits, __u8 access_type,
691 bool allow_delete_child)
97837582
SF
692{
693 int i;
694 __u16 size = 0;
695 __u32 access_req = 0;
696
0f22053e 697 pntace->type = access_type;
97837582
SF
698 pntace->flags = 0x0;
699 mode_to_access_flags(nmode, bits, &access_req);
f2156d35
SP
700
701 if (access_type == ACCESS_ALLOWED && allow_delete_child)
702 access_req |= FILE_DELETE_CHILD;
703
0f22053e 704 if (access_type == ACCESS_ALLOWED && !access_req)
97837582 705 access_req = SET_MINIMUM_RIGHTS;
0f22053e
SP
706 else if (access_type == ACCESS_DENIED)
707 access_req &= ~SET_MINIMUM_RIGHTS;
f2156d35 708
97837582
SF
709 pntace->access_req = cpu_to_le32(access_req);
710
711 pntace->sid.revision = psid->revision;
712 pntace->sid.num_subauth = psid->num_subauth;
852e2295 713 for (i = 0; i < NUM_AUTHS; i++)
97837582
SF
714 pntace->sid.authority[i] = psid->authority[i];
715 for (i = 0; i < psid->num_subauth; i++)
716 pntace->sid.sub_auth[i] = psid->sub_auth[i];
717
718 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
719 pntace->size = cpu_to_le16(size);
720
ef571cad 721 return size;
97837582
SF
722}
723
297647c2 724
953f8681
SF
725#ifdef CONFIG_CIFS_DEBUG2
726static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
d0d66c44 727{
d0d66c44 728 int num_subauth;
d0d66c44
SP
729
730 /* validate that we do not go past end of acl */
297647c2 731
44093ca2 732 if (le16_to_cpu(pace->size) < 16) {
f96637be 733 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
44093ca2
SF
734 return;
735 }
736
737 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
f96637be 738 cifs_dbg(VFS, "ACL too small to parse ACE\n");
d0d66c44 739 return;
44093ca2 740 }
d0d66c44 741
44093ca2 742 num_subauth = pace->sid.num_subauth;
d0d66c44 743 if (num_subauth) {
8f18c131 744 int i;
f96637be
JP
745 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
746 pace->sid.revision, pace->sid.num_subauth, pace->type,
747 pace->flags, le16_to_cpu(pace->size));
d12fd121 748 for (i = 0; i < num_subauth; ++i) {
f96637be
JP
749 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
750 i, le32_to_cpu(pace->sid.sub_auth[i]));
d12fd121
SF
751 }
752
753 /* BB add length check to make sure that we do not have huge
754 num auths and therefore go off the end */
d12fd121
SF
755 }
756
757 return;
758}
953f8681 759#endif
d12fd121 760
a750e77c 761static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
d61e5808 762 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
e2f8fbfb 763 struct cifs_fattr *fattr, bool mode_from_special_sid)
d0d66c44
SP
764{
765 int i;
766 int num_aces = 0;
767 int acl_size;
768 char *acl_base;
d0d66c44
SP
769 struct cifs_ace **ppace;
770
771 /* BB need to add parm so we can store the SID BB */
772
2b83457b
SF
773 if (!pdacl) {
774 /* no DACL in the security descriptor, set
775 all the permissions for user/group/other */
0f22053e 776 fattr->cf_mode |= 0777;
2b83457b
SF
777 return;
778 }
779
d0d66c44 780 /* validate that we do not go past end of acl */
af6f4612 781 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
f96637be 782 cifs_dbg(VFS, "ACL too small to parse DACL\n");
d0d66c44
SP
783 return;
784 }
785
f96637be
JP
786 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
787 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
788 le32_to_cpu(pdacl->num_aces));
d0d66c44 789
7505e052
SF
790 /* reset rwx permissions for user/group/other.
791 Also, if num_aces is 0 i.e. DACL has no ACEs,
792 user/group/other have no permissions */
0f22053e 793 fattr->cf_mode &= ~(0777);
7505e052 794
d0d66c44
SP
795 acl_base = (char *)pdacl;
796 acl_size = sizeof(struct cifs_acl);
797
adbc0358 798 num_aces = le32_to_cpu(pdacl->num_aces);
a5ff3769 799 if (num_aces > 0) {
0f22053e 800 umode_t denied_mode = 0;
15b03959 801
7250170c
DC
802 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
803 return;
6da2ec56
KC
804 ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
805 GFP_KERNEL);
f96637be 806 if (!ppace)
8132b65b 807 return;
d0d66c44 808
d0d66c44 809 for (i = 0; i < num_aces; ++i) {
44093ca2 810 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
953f8681
SF
811#ifdef CONFIG_CIFS_DEBUG2
812 dump_ace(ppace[i], end_of_acl);
813#endif
e2f8fbfb
SF
814 if (mode_from_special_sid &&
815 (compare_sids(&(ppace[i]->sid),
816 &sid_unix_NFS_mode) == 0)) {
817 /*
818 * Full permissions are:
819 * 07777 = S_ISUID | S_ISGID | S_ISVTX |
820 * S_IRWXU | S_IRWXG | S_IRWXO
821 */
822 fattr->cf_mode &= ~07777;
823 fattr->cf_mode |=
824 le32_to_cpu(ppace[i]->sid.sub_auth[2]);
825 break;
0f22053e
SP
826 } else {
827 if (compare_sids(&(ppace[i]->sid), pownersid) == 0) {
828 access_flags_to_mode(ppace[i]->access_req,
829 ppace[i]->type,
830 &fattr->cf_mode,
831 &denied_mode,
832 ACL_OWNER_MASK);
833 } else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) {
834 access_flags_to_mode(ppace[i]->access_req,
835 ppace[i]->type,
836 &fattr->cf_mode,
837 &denied_mode,
838 ACL_GROUP_MASK);
839 } else if ((compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) ||
840 (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)) {
841 access_flags_to_mode(ppace[i]->access_req,
842 ppace[i]->type,
843 &fattr->cf_mode,
844 &denied_mode,
845 ACL_EVERYONE_MASK);
846 }
847 }
2fbc2f17 848
e01b6400 849
44093ca2 850/* memcpy((void *)(&(cifscred->aces[i])),
d12fd121
SF
851 (void *)ppace[i],
852 sizeof(struct cifs_ace)); */
d0d66c44 853
44093ca2
SF
854 acl_base = (char *)ppace[i];
855 acl_size = le16_to_cpu(ppace[i]->size);
d0d66c44
SP
856 }
857
858 kfree(ppace);
d0d66c44
SP
859 }
860
861 return;
862}
863
643fbcee
SF
864unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
865{
866 int i;
867 unsigned int ace_size = 20;
868
869 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
870 pntace->flags = 0x0;
871 pntace->access_req = cpu_to_le32(GENERIC_ALL);
872 pntace->sid.num_subauth = 1;
873 pntace->sid.revision = 1;
874 for (i = 0; i < NUM_AUTHS; i++)
875 pntace->sid.authority[i] = sid_authusers.authority[i];
876
877 pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
878
879 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
880 pntace->size = cpu_to_le16(ace_size);
881 return ace_size;
882}
883
fdef665b
SF
884/*
885 * Fill in the special SID based on the mode. See
cba22b1c 886 * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
fdef665b
SF
887 */
888unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
889{
890 int i;
891 unsigned int ace_size = 28;
892
893 pntace->type = ACCESS_DENIED_ACE_TYPE;
894 pntace->flags = 0x0;
895 pntace->access_req = 0;
896 pntace->sid.num_subauth = 3;
897 pntace->sid.revision = 1;
898 for (i = 0; i < NUM_AUTHS; i++)
899 pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
900
901 pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
902 pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
903 pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
904
905 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
906 pntace->size = cpu_to_le16(ace_size);
907 return ace_size;
908}
bcb02034 909
975221ec
SF
910unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
911{
912 int i;
913 unsigned int ace_size = 28;
914
915 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
916 pntace->flags = 0x0;
917 pntace->access_req = cpu_to_le32(GENERIC_ALL);
918 pntace->sid.num_subauth = 3;
919 pntace->sid.revision = 1;
920 for (i = 0; i < NUM_AUTHS; i++)
921 pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
922
923 pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
924 pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
925 pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
926
927 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
928 pntace->size = cpu_to_le16(ace_size);
929 return ace_size;
930}
931
f5065508
SP
932static void populate_new_aces(char *nacl_base,
933 struct cifs_sid *pownersid,
934 struct cifs_sid *pgrpsid,
935 __u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
936 bool modefromsid)
97837582 937{
0f22053e 938 __u64 nmode;
f5065508
SP
939 u32 num_aces = 0;
940 u16 nsize = 0;
0f22053e
SP
941 __u64 user_mode;
942 __u64 group_mode;
943 __u64 other_mode;
944 __u64 deny_user_mode = 0;
945 __u64 deny_group_mode = 0;
f2156d35 946 bool sticky_set = false;
f5065508 947 struct cifs_ace *pnntace = NULL;
97837582 948
0f22053e 949 nmode = *pnmode;
f5065508
SP
950 num_aces = *pnum_aces;
951 nsize = *pnsize;
0f22053e 952
22442179 953 if (modefromsid) {
f5065508
SP
954 pnntace = (struct cifs_ace *) (nacl_base + nsize);
955 nsize += setup_special_mode_ACE(pnntace, nmode);
e37a02c7 956 num_aces++;
0c6f4ebf
RS
957 pnntace = (struct cifs_ace *) (nacl_base + nsize);
958 nsize += setup_authusers_ACE(pnntace);
959 num_aces++;
0f22053e 960 goto set_size;
e37a02c7
AA
961 }
962
0f22053e
SP
963 /*
964 * We'll try to keep the mode as requested by the user.
965 * But in cases where we cannot meaningfully convert that
966 * into ACL, return back the updated mode, so that it is
967 * updated in the inode.
968 */
969
970 if (!memcmp(pownersid, pgrpsid, sizeof(struct cifs_sid))) {
971 /*
972 * Case when owner and group SIDs are the same.
973 * Set the more restrictive of the two modes.
974 */
975 user_mode = nmode & (nmode << 3) & 0700;
976 group_mode = nmode & (nmode >> 3) & 0070;
977 } else {
978 user_mode = nmode & 0700;
979 group_mode = nmode & 0070;
980 }
981
982 other_mode = nmode & 0007;
983
984 /* We need DENY ACE when the perm is more restrictive than the next sets. */
985 deny_user_mode = ~(user_mode) & ((group_mode << 3) | (other_mode << 6)) & 0700;
986 deny_group_mode = ~(group_mode) & (other_mode << 3) & 0070;
987
988 *pnmode = user_mode | group_mode | other_mode | (nmode & ~0777);
989
f2156d35
SP
990 /* This tells if we should allow delete child for group and everyone. */
991 if (nmode & 01000)
992 sticky_set = true;
993
0f22053e 994 if (deny_user_mode) {
f5065508
SP
995 pnntace = (struct cifs_ace *) (nacl_base + nsize);
996 nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode,
997 0700, ACCESS_DENIED, false);
0f22053e
SP
998 num_aces++;
999 }
f5065508 1000
0f22053e
SP
1001 /* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/
1002 if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) {
f5065508
SP
1003 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1004 nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
1005 0070, ACCESS_DENIED, false);
0f22053e
SP
1006 num_aces++;
1007 }
f5065508
SP
1008
1009 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1010 nsize += fill_ace_for_sid(pnntace, pownersid, user_mode,
1011 0700, ACCESS_ALLOWED, true);
e37a02c7 1012 num_aces++;
f5065508 1013
0f22053e
SP
1014 /* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
1015 if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) {
f5065508
SP
1016 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1017 nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
1018 0070, ACCESS_DENIED, false);
0f22053e
SP
1019 num_aces++;
1020 }
f5065508
SP
1021
1022 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1023 nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode,
1024 0070, ACCESS_ALLOWED, !sticky_set);
e37a02c7 1025 num_aces++;
f5065508
SP
1026
1027 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1028 nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode,
1029 0007, ACCESS_ALLOWED, !sticky_set);
e37a02c7 1030 num_aces++;
22442179 1031
0f22053e 1032set_size:
f5065508
SP
1033 *pnum_aces = num_aces;
1034 *pnsize = nsize;
1035}
1036
1037static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
1038 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
1039 struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid)
1040{
1041 int i;
1042 u16 size = 0;
1043 struct cifs_ace *pntace = NULL;
1044 char *acl_base = NULL;
1045 u32 src_num_aces = 0;
1046 u16 nsize = 0;
1047 struct cifs_ace *pnntace = NULL;
1048 char *nacl_base = NULL;
1049 u16 ace_size = 0;
1050
1051 acl_base = (char *)pdacl;
1052 size = sizeof(struct cifs_acl);
1053 src_num_aces = le32_to_cpu(pdacl->num_aces);
1054
1055 nacl_base = (char *)pndacl;
1056 nsize = sizeof(struct cifs_acl);
1057
1058 /* Go through all the ACEs */
1059 for (i = 0; i < src_num_aces; ++i) {
1060 pntace = (struct cifs_ace *) (acl_base + size);
1061 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1062
1063 if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
bc3e9dd9 1064 ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
f5065508 1065 else if (pngrpsid && compare_sids(&pntace->sid, pgrpsid) == 0)
bc3e9dd9 1066 ace_size = cifs_copy_ace(pnntace, pntace, pngrpsid);
f5065508 1067 else
bc3e9dd9 1068 ace_size = cifs_copy_ace(pnntace, pntace, NULL);
f5065508
SP
1069
1070 size += le16_to_cpu(pntace->size);
1071 nsize += ace_size;
1072 }
1073
1074 return nsize;
1075}
1076
1077static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
1078 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
1079 __u64 *pnmode, bool mode_from_sid)
1080{
1081 int i;
1082 u16 size = 0;
1083 struct cifs_ace *pntace = NULL;
1084 char *acl_base = NULL;
1085 u32 src_num_aces = 0;
1086 u16 nsize = 0;
1087 struct cifs_ace *pnntace = NULL;
1088 char *nacl_base = NULL;
1089 u32 num_aces = 0;
f5065508
SP
1090 bool new_aces_set = false;
1091
1092 /* Assuming that pndacl and pnmode are never NULL */
f5065508
SP
1093 nacl_base = (char *)pndacl;
1094 nsize = sizeof(struct cifs_acl);
1095
1096 /* If pdacl is NULL, we don't have a src. Simply populate new ACL. */
1097 if (!pdacl) {
1098 populate_new_aces(nacl_base,
1099 pownersid, pgrpsid,
1100 pnmode, &num_aces, &nsize,
1101 mode_from_sid);
1102 goto finalize_dacl;
1103 }
1104
1105 acl_base = (char *)pdacl;
1106 size = sizeof(struct cifs_acl);
1107 src_num_aces = le32_to_cpu(pdacl->num_aces);
1108
1109 /* Retain old ACEs which we can retain */
1110 for (i = 0; i < src_num_aces; ++i) {
1111 pntace = (struct cifs_ace *) (acl_base + size);
f5065508
SP
1112
1113 if (!new_aces_set && (pntace->flags & INHERITED_ACE)) {
1114 /* Place the new ACEs in between existing explicit and inherited */
1115 populate_new_aces(nacl_base,
1116 pownersid, pgrpsid,
1117 pnmode, &num_aces, &nsize,
1118 mode_from_sid);
1119
1120 new_aces_set = true;
1121 }
1122
1123 /* If it's any one of the ACE we're replacing, skip! */
3bffbe9e 1124 if (((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
f5065508
SP
1125 (compare_sids(&pntace->sid, pownersid) == 0) ||
1126 (compare_sids(&pntace->sid, pgrpsid) == 0) ||
1127 (compare_sids(&pntace->sid, &sid_everyone) == 0) ||
5171317d 1128 (compare_sids(&pntace->sid, &sid_authusers) == 0))) {
f5065508
SP
1129 goto next_ace;
1130 }
1131
5171317d
SP
1132 /* update the pointer to the next ACE to populate*/
1133 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1134
bc3e9dd9 1135 nsize += cifs_copy_ace(pnntace, pntace, NULL);
f5065508
SP
1136 num_aces++;
1137
1138next_ace:
23bda5e6 1139 size += le16_to_cpu(pntace->size);
f5065508
SP
1140 }
1141
1142 /* If inherited ACEs are not present, place the new ones at the tail */
1143 if (!new_aces_set) {
1144 populate_new_aces(nacl_base,
1145 pownersid, pgrpsid,
1146 pnmode, &num_aces, &nsize,
1147 mode_from_sid);
1148
1149 new_aces_set = true;
1150 }
1151
1152finalize_dacl:
e37a02c7 1153 pndacl->num_aces = cpu_to_le32(num_aces);
f5065508 1154 pndacl->size = cpu_to_le16(nsize);
97837582 1155
ef571cad 1156 return 0;
97837582
SF
1157}
1158
bcb02034
SF
1159static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
1160{
1161 /* BB need to add parm so we can store the SID BB */
1162
b9c7a2bb
SF
1163 /* validate that we do not go past end of ACL - sid must be at least 8
1164 bytes long (assuming no sub-auths - e.g. the null SID */
1165 if (end_of_acl < (char *)psid + 8) {
f96637be 1166 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
bcb02034
SF
1167 return -EINVAL;
1168 }
d0d66c44 1169
bcb02034 1170#ifdef CONFIG_CIFS_DEBUG2
fc03d8a5 1171 if (psid->num_subauth) {
8f18c131 1172 int i;
f96637be
JP
1173 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
1174 psid->revision, psid->num_subauth);
bcb02034 1175
af6f4612 1176 for (i = 0; i < psid->num_subauth; i++) {
f96637be
JP
1177 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
1178 i, le32_to_cpu(psid->sub_auth[i]));
d0d66c44
SP
1179 }
1180
d12fd121 1181 /* BB add length check to make sure that we do not have huge
d0d66c44 1182 num auths and therefore go off the end */
f96637be
JP
1183 cifs_dbg(FYI, "RID 0x%x\n",
1184 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
d0d66c44 1185 }
fc03d8a5 1186#endif
d0d66c44 1187
bcb02034
SF
1188 return 0;
1189}
1190
d0d66c44 1191
bcb02034 1192/* Convert CIFS ACL to POSIX form */
9409ae58 1193static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
e2f8fbfb
SF
1194 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
1195 bool get_mode_from_special_sid)
bcb02034 1196{
9409ae58 1197 int rc = 0;
bcb02034
SF
1198 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1199 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
bcb02034 1200 char *end_of_acl = ((char *)pntsd) + acl_len;
7505e052 1201 __u32 dacloffset;
bcb02034 1202
0b8f18e3 1203 if (pntsd == NULL)
b9c7a2bb
SF
1204 return -EIO;
1205
bcb02034 1206 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 1207 le32_to_cpu(pntsd->osidoffset));
bcb02034 1208 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 1209 le32_to_cpu(pntsd->gsidoffset));
7505e052 1210 dacloffset = le32_to_cpu(pntsd->dacloffset);
63d2583f 1211 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
f96637be 1212 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
af6f4612
SF
1213 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
1214 le32_to_cpu(pntsd->gsidoffset),
b6b38f70 1215 le32_to_cpu(pntsd->sacloffset), dacloffset);
b9c7a2bb 1216/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
bcb02034 1217 rc = parse_sid(owner_sid_ptr, end_of_acl);
9409ae58 1218 if (rc) {
f96637be 1219 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
9409ae58
SP
1220 return rc;
1221 }
1222 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
1223 if (rc) {
f96637be
JP
1224 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
1225 __func__, rc);
bcb02034 1226 return rc;
9409ae58 1227 }
bcb02034
SF
1228
1229 rc = parse_sid(group_sid_ptr, end_of_acl);
9409ae58 1230 if (rc) {
f96637be
JP
1231 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
1232 __func__, rc);
bcb02034 1233 return rc;
9409ae58
SP
1234 }
1235 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
1236 if (rc) {
f96637be
JP
1237 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
1238 __func__, rc);
9409ae58
SP
1239 return rc;
1240 }
bcb02034 1241
7505e052
SF
1242 if (dacloffset)
1243 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
e2f8fbfb 1244 group_sid_ptr, fattr, get_mode_from_special_sid);
7505e052 1245 else
f96637be 1246 cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
d0d66c44 1247
9409ae58 1248 return rc;
bcb02034 1249}
b9c7a2bb 1250
97837582
SF
1251/* Convert permission bits from mode to equivalent CIFS ACL */
1252static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
f5065508 1253 __u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid,
a6603398 1254 bool mode_from_sid, bool id_from_sid, int *aclflag)
97837582
SF
1255{
1256 int rc = 0;
1257 __u32 dacloffset;
1258 __u32 ndacloffset;
1259 __u32 sidsoffset;
1260 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
bc3e9dd9 1261 struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
97837582
SF
1262 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
1263 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
f5065508 1264 char *end_of_acl = ((char *)pntsd) + secdesclen;
bc3e9dd9 1265 u16 size = 0;
97837582 1266
bc3e9dd9
SP
1267 dacloffset = le32_to_cpu(pntsd->dacloffset);
1268 if (dacloffset) {
1269 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1270 if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
f1ebe48d
SP
1271 cifs_dbg(VFS, "Server returned illegal ACL size\n");
1272 return -EINVAL;
f5065508 1273 }
bc3e9dd9
SP
1274 }
1275
1276 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1277 le32_to_cpu(pntsd->osidoffset));
1278 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1279 le32_to_cpu(pntsd->gsidoffset));
f5065508 1280
bc3e9dd9 1281 if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
a5ff3769
SP
1282 ndacloffset = sizeof(struct cifs_ntsd);
1283 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
f5065508
SP
1284 ndacl_ptr->revision =
1285 dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
a5ff3769 1286
23bda5e6 1287 ndacl_ptr->size = cpu_to_le16(0);
f5065508
SP
1288 ndacl_ptr->num_aces = cpu_to_le32(0);
1289
1290 rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr,
0f22053e 1291 pnmode, mode_from_sid);
bc3e9dd9 1292
a5ff3769 1293 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
bc3e9dd9
SP
1294 /* copy the non-dacl portion of secdesc */
1295 *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
1296 NULL, NULL);
1297
1298 *aclflag |= CIFS_ACL_DACL;
a5ff3769 1299 } else {
f5065508
SP
1300 ndacloffset = sizeof(struct cifs_ntsd);
1301 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1302 ndacl_ptr->revision =
1303 dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
a5628263 1304 ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
f5065508 1305
8abf2775
EB
1306 if (uid_valid(uid)) { /* chown */
1307 uid_t id;
26d3dade 1308 nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid),
a5ff3769 1309 GFP_KERNEL);
bc3e9dd9
SP
1310 if (!nowner_sid_ptr) {
1311 rc = -ENOMEM;
1312 goto chown_chgrp_exit;
1313 }
8abf2775 1314 id = from_kuid(&init_user_ns, uid);
a6603398
SF
1315 if (id_from_sid) {
1316 struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
1317 /* Populate the user ownership fields S-1-5-88-1 */
1318 osid->Revision = 1;
1319 osid->NumAuth = 3;
1320 osid->Authority[5] = 5;
1321 osid->SubAuthorities[0] = cpu_to_le32(88);
1322 osid->SubAuthorities[1] = cpu_to_le32(1);
1323 osid->SubAuthorities[2] = cpu_to_le32(id);
bc3e9dd9 1324
a6603398
SF
1325 } else { /* lookup sid with upcall */
1326 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
1327 if (rc) {
1328 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
1329 __func__, rc, id);
bc3e9dd9 1330 goto chown_chgrp_exit;
a6603398 1331 }
a5ff3769 1332 }
bc3e9dd9 1333 *aclflag |= CIFS_ACL_OWNER;
a5ff3769 1334 }
8abf2775
EB
1335 if (gid_valid(gid)) { /* chgrp */
1336 gid_t id;
26d3dade 1337 ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid),
a5ff3769 1338 GFP_KERNEL);
bc3e9dd9
SP
1339 if (!ngroup_sid_ptr) {
1340 rc = -ENOMEM;
1341 goto chown_chgrp_exit;
1342 }
8abf2775 1343 id = from_kgid(&init_user_ns, gid);
a6603398
SF
1344 if (id_from_sid) {
1345 struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
1346 /* Populate the group ownership fields S-1-5-88-2 */
1347 gsid->Revision = 1;
1348 gsid->NumAuth = 3;
1349 gsid->Authority[5] = 5;
1350 gsid->SubAuthorities[0] = cpu_to_le32(88);
1351 gsid->SubAuthorities[1] = cpu_to_le32(2);
1352 gsid->SubAuthorities[2] = cpu_to_le32(id);
bc3e9dd9 1353
a6603398
SF
1354 } else { /* lookup sid with upcall */
1355 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
1356 if (rc) {
1357 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
1358 __func__, rc, id);
bc3e9dd9 1359 goto chown_chgrp_exit;
a6603398 1360 }
a5ff3769 1361 }
bc3e9dd9 1362 *aclflag |= CIFS_ACL_GROUP;
a5ff3769 1363 }
bc3e9dd9
SP
1364
1365 if (dacloffset) {
1366 /* Replace ACEs for old owner with new one */
1367 size = replace_sids_and_copy_aces(dacl_ptr, ndacl_ptr,
1368 owner_sid_ptr, group_sid_ptr,
1369 nowner_sid_ptr, ngroup_sid_ptr);
1370 ndacl_ptr->size = cpu_to_le16(size);
1371 }
1372
1373 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1374 /* copy the non-dacl portion of secdesc */
1375 *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
1376 nowner_sid_ptr, ngroup_sid_ptr);
1377
1378chown_chgrp_exit:
1379 /* errors could jump here. So make sure we return soon after this */
1380 kfree(nowner_sid_ptr);
1381 kfree(ngroup_sid_ptr);
a5ff3769 1382 }
97837582 1383
ef571cad 1384 return rc;
97837582
SF
1385}
1386
fb157ed2 1387#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
42eacf9e 1388struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
3970acf7
BP
1389 const struct cifs_fid *cifsfid, u32 *pacllen,
1390 u32 __maybe_unused unused)
b9c7a2bb 1391{
b9c7a2bb 1392 struct cifs_ntsd *pntsd = NULL;
6d5786a3
PS
1393 unsigned int xid;
1394 int rc;
7ffec372
JL
1395 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1396
1397 if (IS_ERR(tlink))
987b21d7 1398 return ERR_CAST(tlink);
b9c7a2bb 1399
6d5786a3 1400 xid = get_xid();
42eacf9e
SF
1401 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1402 pacllen);
6d5786a3 1403 free_xid(xid);
b9c7a2bb 1404
7ffec372 1405 cifs_put_tlink(tlink);
b9c7a2bb 1406
f96637be 1407 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
987b21d7
SP
1408 if (rc)
1409 return ERR_PTR(rc);
1bf4072d
CH
1410 return pntsd;
1411}
8b1327f6 1412
1bf4072d
CH
1413static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1414 const char *path, u32 *pacllen)
1415{
1416 struct cifs_ntsd *pntsd = NULL;
1417 int oplock = 0;
6d5786a3 1418 unsigned int xid;
0f060936 1419 int rc;
96daf2b0 1420 struct cifs_tcon *tcon;
7ffec372 1421 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40
PS
1422 struct cifs_fid fid;
1423 struct cifs_open_parms oparms;
7ffec372
JL
1424
1425 if (IS_ERR(tlink))
987b21d7 1426 return ERR_CAST(tlink);
b9c7a2bb 1427
7ffec372 1428 tcon = tlink_tcon(tlink);
6d5786a3 1429 xid = get_xid();
1bf4072d 1430
de036dca
VL
1431 oparms = (struct cifs_open_parms) {
1432 .tcon = tcon,
1433 .cifs_sb = cifs_sb,
1434 .desired_access = READ_CONTROL,
1435 .create_options = cifs_create_options(cifs_sb, 0),
1436 .disposition = FILE_OPEN,
1437 .path = path,
1438 .fid = &fid,
1439 };
d81b8a40
PS
1440
1441 rc = CIFS_open(xid, &oparms, &oplock, NULL);
987b21d7 1442 if (!rc) {
d81b8a40
PS
1443 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1444 CIFSSMBClose(xid, tcon, fid.netfid);
b9c7a2bb
SF
1445 }
1446
7ffec372 1447 cifs_put_tlink(tlink);
6d5786a3 1448 free_xid(xid);
987b21d7 1449
f96637be 1450 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
987b21d7
SP
1451 if (rc)
1452 return ERR_PTR(rc);
7505e052
SF
1453 return pntsd;
1454}
1455
1bf4072d 1456/* Retrieve an ACL from the server */
fbeba8bb 1457struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1bf4072d 1458 struct inode *inode, const char *path,
3970acf7 1459 u32 *pacllen, u32 info)
1bf4072d
CH
1460{
1461 struct cifs_ntsd *pntsd = NULL;
1462 struct cifsFileInfo *open_file = NULL;
1463
1464 if (inode)
6508d904 1465 open_file = find_readable_file(CIFS_I(inode), true);
1bf4072d
CH
1466 if (!open_file)
1467 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1468
3970acf7 1469 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
6ab409b5 1470 cifsFileInfo_put(open_file);
1bf4072d
CH
1471 return pntsd;
1472}
1473
a5ff3769
SP
1474 /* Set an ACL on the server */
1475int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1476 struct inode *inode, const char *path, int aclflag)
b96d31a6
CH
1477{
1478 int oplock = 0;
6d5786a3 1479 unsigned int xid;
0f060936 1480 int rc, access_flags;
96daf2b0 1481 struct cifs_tcon *tcon;
a5ff3769 1482 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec372 1483 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40
PS
1484 struct cifs_fid fid;
1485 struct cifs_open_parms oparms;
97837582 1486
7ffec372
JL
1487 if (IS_ERR(tlink))
1488 return PTR_ERR(tlink);
1489
1490 tcon = tlink_tcon(tlink);
6d5786a3 1491 xid = get_xid();
97837582 1492
a5ff3769
SP
1493 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1494 access_flags = WRITE_OWNER;
1495 else
1496 access_flags = WRITE_DAC;
1497
de036dca
VL
1498 oparms = (struct cifs_open_parms) {
1499 .tcon = tcon,
1500 .cifs_sb = cifs_sb,
1501 .desired_access = access_flags,
1502 .create_options = cifs_create_options(cifs_sb, 0),
1503 .disposition = FILE_OPEN,
1504 .path = path,
1505 .fid = &fid,
1506 };
d81b8a40
PS
1507
1508 rc = CIFS_open(xid, &oparms, &oplock, NULL);
b96d31a6 1509 if (rc) {
f96637be 1510 cifs_dbg(VFS, "Unable to open file to set ACL\n");
b96d31a6 1511 goto out;
97837582
SF
1512 }
1513
d81b8a40 1514 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
f96637be 1515 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
97837582 1516
d81b8a40 1517 CIFSSMBClose(xid, tcon, fid.netfid);
7ffec372 1518out:
6d5786a3 1519 free_xid(xid);
7ffec372 1520 cifs_put_tlink(tlink);
b96d31a6
CH
1521 return rc;
1522}
fb157ed2 1523#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
97837582 1524
36c7ce4a 1525/* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
987b21d7 1526int
0b8f18e3 1527cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
e2f8fbfb
SF
1528 struct inode *inode, bool mode_from_special_sid,
1529 const char *path, const struct cifs_fid *pfid)
7505e052
SF
1530{
1531 struct cifs_ntsd *pntsd = NULL;
1532 u32 acllen = 0;
1533 int rc = 0;
42eacf9e 1534 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
ecdcf622 1535 struct smb_version_operations *ops;
3970acf7 1536 const u32 info = 0;
7505e052 1537
f96637be 1538 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1bf4072d 1539
42eacf9e
SF
1540 if (IS_ERR(tlink))
1541 return PTR_ERR(tlink);
7505e052 1542
ecdcf622
JP
1543 ops = tlink_tcon(tlink)->ses->server->ops;
1544
1545 if (pfid && (ops->get_acl_by_fid))
3970acf7 1546 pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen, info);
ecdcf622 1547 else if (ops->get_acl)
3970acf7 1548 pntsd = ops->get_acl(cifs_sb, inode, path, &acllen, info);
42eacf9e
SF
1549 else {
1550 cifs_put_tlink(tlink);
1551 return -EOPNOTSUPP;
1552 }
7505e052 1553 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
987b21d7
SP
1554 if (IS_ERR(pntsd)) {
1555 rc = PTR_ERR(pntsd);
f96637be 1556 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
e2f8fbfb
SF
1557 } else if (mode_from_special_sid) {
1558 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
98128572 1559 kfree(pntsd);
987b21d7 1560 } else {
e2f8fbfb
SF
1561 /* get approximated mode from ACL */
1562 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
987b21d7
SP
1563 kfree(pntsd);
1564 if (rc)
f96637be 1565 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
987b21d7 1566 }
7505e052 1567
42eacf9e
SF
1568 cifs_put_tlink(tlink);
1569
987b21d7 1570 return rc;
b9c7a2bb 1571}
953f8681 1572
7505e052 1573/* Convert mode bits to an ACL so we can update the ACL on the server */
a5ff3769 1574int
0f22053e 1575id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
8abf2775 1576 kuid_t uid, kgid_t gid)
953f8681
SF
1577{
1578 int rc = 0;
a5ff3769 1579 int aclflag = CIFS_ACL_DACL; /* default flag to set */
cce246ee 1580 __u32 secdesclen = 0;
f5065508
SP
1581 __u32 nsecdesclen = 0;
1582 __u32 dacloffset = 0;
1583 struct cifs_acl *dacl_ptr = NULL;
97837582
SF
1584 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1585 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
83e3bc23
SF
1586 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1587 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
ecdcf622 1588 struct smb_version_operations *ops;
a6603398 1589 bool mode_from_sid, id_from_sid;
3970acf7 1590 const u32 info = 0;
83e3bc23
SF
1591
1592 if (IS_ERR(tlink))
1593 return PTR_ERR(tlink);
ecdcf622
JP
1594
1595 ops = tlink_tcon(tlink)->ses->server->ops;
953f8681 1596
f96637be 1597 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
953f8681
SF
1598
1599 /* Get the security descriptor */
83e3bc23 1600
ecdcf622 1601 if (ops->get_acl == NULL) {
83e3bc23
SF
1602 cifs_put_tlink(tlink);
1603 return -EOPNOTSUPP;
1604 }
1605
3970acf7 1606 pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen, info);
987b21d7
SP
1607 if (IS_ERR(pntsd)) {
1608 rc = PTR_ERR(pntsd);
f96637be 1609 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
83e3bc23
SF
1610 cifs_put_tlink(tlink);
1611 return rc;
c78cd838 1612 }
7505e052 1613
f5065508
SP
1614 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
1615 mode_from_sid = true;
1616 else
1617 mode_from_sid = false;
1618
1619 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
1620 id_from_sid = true;
1621 else
1622 id_from_sid = false;
1623
1624 /* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */
1625 nsecdesclen = secdesclen;
1626 if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
1627 if (mode_from_sid)
0c6f4ebf 1628 nsecdesclen += 2 * sizeof(struct cifs_ace);
f5065508
SP
1629 else /* cifsacl */
1630 nsecdesclen += 5 * sizeof(struct cifs_ace);
bc3e9dd9
SP
1631 } else { /* chown */
1632 /* When ownership changes, changes new owner sid length could be different */
1633 nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2);
1634 dacloffset = le32_to_cpu(pntsd->dacloffset);
1635 if (dacloffset) {
1636 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1637 if (mode_from_sid)
1638 nsecdesclen +=
23bda5e6 1639 le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace);
bc3e9dd9
SP
1640 else /* cifsacl */
1641 nsecdesclen += le16_to_cpu(dacl_ptr->size);
1642 }
f5065508
SP
1643 }
1644
c78cd838
JL
1645 /*
1646 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1647 * as chmod disables ACEs and set the security descriptor. Allocate
1648 * memory for the smb header, set security descriptor request security
c45adff7 1649 * descriptor parameters, and security descriptor itself
c78cd838 1650 */
f5065508
SP
1651 nsecdesclen = max_t(u32, nsecdesclen, DEFAULT_SEC_DESC_LEN);
1652 pnntsd = kmalloc(nsecdesclen, GFP_KERNEL);
c78cd838 1653 if (!pnntsd) {
c78cd838 1654 kfree(pntsd);
83e3bc23 1655 cifs_put_tlink(tlink);
c78cd838
JL
1656 return -ENOMEM;
1657 }
97837582 1658
f5065508 1659 rc = build_sec_desc(pntsd, pnntsd, secdesclen, &nsecdesclen, pnmode, uid, gid,
a6603398 1660 mode_from_sid, id_from_sid, &aclflag);
97837582 1661
f96637be 1662 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
97837582 1663
ecdcf622 1664 if (ops->set_acl == NULL)
83e3bc23
SF
1665 rc = -EOPNOTSUPP;
1666
c78cd838
JL
1667 if (!rc) {
1668 /* Set the security descriptor */
f5065508 1669 rc = ops->set_acl(pnntsd, nsecdesclen, inode, path, aclflag);
f96637be 1670 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
97837582 1671 }
83e3bc23 1672 cifs_put_tlink(tlink);
97837582 1673
c78cd838
JL
1674 kfree(pnntsd);
1675 kfree(pntsd);
ef571cad 1676 return rc;
953f8681 1677}
bd9684b0 1678
77435322 1679struct posix_acl *cifs_get_acl(struct mnt_idmap *idmap,
bd9684b0
CB
1680 struct dentry *dentry, int type)
1681{
1682#if defined(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) && defined(CONFIG_CIFS_POSIX)
1683 struct posix_acl *acl = NULL;
1684 ssize_t rc = -EOPNOTSUPP;
1685 unsigned int xid;
1686 struct super_block *sb = dentry->d_sb;
1687 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1688 struct tcon_link *tlink;
1689 struct cifs_tcon *pTcon;
1690 const char *full_path;
1691 void *page;
1692
1693 tlink = cifs_sb_tlink(cifs_sb);
1694 if (IS_ERR(tlink))
1695 return ERR_CAST(tlink);
1696 pTcon = tlink_tcon(tlink);
1697
1698 xid = get_xid();
1699 page = alloc_dentry_path();
1700
1701 full_path = build_path_from_dentry(dentry, page);
1702 if (IS_ERR(full_path)) {
1703 acl = ERR_CAST(full_path);
1704 goto out;
1705 }
1706
1707 /* return alt name if available as pseudo attr */
1708 switch (type) {
1709 case ACL_TYPE_ACCESS:
1710 if (sb->s_flags & SB_POSIXACL)
1711 rc = cifs_do_get_acl(xid, pTcon, full_path, &acl,
1712 ACL_TYPE_ACCESS,
1713 cifs_sb->local_nls,
1714 cifs_remap(cifs_sb));
1715 break;
1716
1717 case ACL_TYPE_DEFAULT:
1718 if (sb->s_flags & SB_POSIXACL)
1719 rc = cifs_do_get_acl(xid, pTcon, full_path, &acl,
1720 ACL_TYPE_DEFAULT,
1721 cifs_sb->local_nls,
1722 cifs_remap(cifs_sb));
1723 break;
1724 }
1725
1726 if (rc < 0) {
1727 if (rc == -EINVAL)
1728 acl = ERR_PTR(-EOPNOTSUPP);
1729 else
1730 acl = ERR_PTR(rc);
1731 }
1732
1733out:
1734 free_dentry_path(page);
1735 free_xid(xid);
1736 cifs_put_tlink(tlink);
1737 return acl;
1738#else
1739 return ERR_PTR(-EOPNOTSUPP);
1740#endif
1741}
dc1af4c4 1742
13e83a49 1743int cifs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
dc1af4c4
CB
1744 struct posix_acl *acl, int type)
1745{
1746#if defined(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) && defined(CONFIG_CIFS_POSIX)
1747 int rc = -EOPNOTSUPP;
1748 unsigned int xid;
1749 struct super_block *sb = dentry->d_sb;
1750 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1751 struct tcon_link *tlink;
1752 struct cifs_tcon *pTcon;
1753 const char *full_path;
1754 void *page;
1755
1756 tlink = cifs_sb_tlink(cifs_sb);
1757 if (IS_ERR(tlink))
1758 return PTR_ERR(tlink);
1759 pTcon = tlink_tcon(tlink);
1760
1761 xid = get_xid();
1762 page = alloc_dentry_path();
1763
1764 full_path = build_path_from_dentry(dentry, page);
1765 if (IS_ERR(full_path)) {
1766 rc = PTR_ERR(full_path);
1767 goto out;
1768 }
cb2144d6
CB
1769
1770 if (!acl)
1771 goto out;
1772
dc1af4c4
CB
1773 /* return dos attributes as pseudo xattr */
1774 /* return alt name if available as pseudo attr */
1775
1776 /* if proc/fs/cifs/streamstoxattr is set then
1777 search server for EAs or streams to
1778 returns as xattrs */
1779 if (posix_acl_xattr_size(acl->a_count) > CIFSMaxBufSize) {
1780 cifs_dbg(FYI, "size of EA value too large\n");
1781 rc = -EOPNOTSUPP;
1782 goto out;
1783 }
1784
1785 switch (type) {
1786 case ACL_TYPE_ACCESS:
dc1af4c4
CB
1787 if (sb->s_flags & SB_POSIXACL)
1788 rc = cifs_do_set_acl(xid, pTcon, full_path, acl,
1789 ACL_TYPE_ACCESS,
1790 cifs_sb->local_nls,
1791 cifs_remap(cifs_sb));
1792 break;
1793
1794 case ACL_TYPE_DEFAULT:
dc1af4c4
CB
1795 if (sb->s_flags & SB_POSIXACL)
1796 rc = cifs_do_set_acl(xid, pTcon, full_path, acl,
1797 ACL_TYPE_DEFAULT,
1798 cifs_sb->local_nls,
1799 cifs_remap(cifs_sb));
1800 break;
1801 }
1802
1803out:
1804 free_dentry_path(page);
1805 free_xid(xid);
1806 cifs_put_tlink(tlink);
1807 return rc;
1808#else
1809 return -EOPNOTSUPP;
1810#endif
1811}