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