Merge tag 'overflow-v5.8-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees...
[linux-2.6-block.git] / fs / cifs / cifsacl.c
CommitLineData
bcb02034
SF
1/*
2 * fs/cifs/cifsacl.c
3 *
8b1327f6 4 * Copyright (C) International Business Machines Corp., 2007,2008
bcb02034
SF
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for mapping CIFS/NTFS ACLs
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
65874007 24#include <linux/fs.h>
5a0e3ad6 25#include <linux/slab.h>
4d79dba0
SP
26#include <linux/string.h>
27#include <linux/keyctl.h>
28#include <linux/key-type.h>
29#include <keys/user-type.h>
65874007
SF
30#include "cifspdu.h"
31#include "cifsglob.h"
d0d66c44 32#include "cifsacl.h"
65874007
SF
33#include "cifsproto.h"
34#include "cifs_debug.h"
65874007 35
2fbc2f17 36/* security id for everyone/world system group */
e01b6400
SP
37static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
2fbc2f17
SP
39/* security id for Authenticated Users system group */
40static const struct cifs_sid sid_authusers = {
bc09d141 41 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
d0d66c44 42
3514de3f
SF
43/* S-1-22-1 Unmapped Unix users */
44static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
45 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
46
47/* S-1-22-2 Unmapped Unix groups */
48static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
49 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
50
51/*
52 * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
53 */
54
55/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
56
57/* S-1-5-88-1 Unix uid */
58static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
59 {cpu_to_le32(88),
60 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
61
62/* S-1-5-88-2 Unix gid */
63static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
64 {cpu_to_le32(88),
65 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
66
67/* S-1-5-88-3 Unix mode */
68static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
69 {cpu_to_le32(88),
70 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
71
b1a6dc21 72static const struct cred *root_cred;
9409ae58 73
4d79dba0 74static int
cf7f601c 75cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
4d79dba0
SP
76{
77 char *payload;
78
41a9f1f6
JL
79 /*
80 * If the payload is less than or equal to the size of a pointer, then
81 * an allocation here is wasteful. Just copy the data directly to the
82 * payload.value union member instead.
83 *
84 * With this however, you must check the datalen before trying to
85 * dereference payload.data!
86 */
1f630680 87 if (prep->datalen <= sizeof(key->payload)) {
146aa8b1
DH
88 key->payload.data[0] = NULL;
89 memcpy(&key->payload, prep->data, prep->datalen);
90 } else {
91 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
92 if (!payload)
93 return -ENOMEM;
94 key->payload.data[0] = payload;
41a9f1f6 95 }
4d79dba0 96
cf7f601c 97 key->datalen = prep->datalen;
4d79dba0
SP
98 return 0;
99}
100
101static inline void
102cifs_idmap_key_destroy(struct key *key)
103{
1f630680 104 if (key->datalen > sizeof(key->payload))
146aa8b1 105 kfree(key->payload.data[0]);
4d79dba0
SP
106}
107
b1a6dc21 108static struct key_type cifs_idmap_key_type = {
c4aca0c0 109 .name = "cifs.idmap",
4d79dba0
SP
110 .instantiate = cifs_idmap_key_instantiate,
111 .destroy = cifs_idmap_key_destroy,
112 .describe = user_describe,
4d79dba0
SP
113};
114
faa65f07
JL
115static char *
116sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
9409ae58 117{
faa65f07 118 int i, len;
ee13b2ba 119 unsigned int saval;
faa65f07 120 char *sidstr, *strptr;
193cdd8a 121 unsigned long long id_auth_val;
9409ae58 122
faa65f07
JL
123 /* 3 bytes for prefix */
124 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
125 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
126 GFP_KERNEL);
127 if (!sidstr)
128 return sidstr;
9409ae58 129
faa65f07
JL
130 strptr = sidstr;
131 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
132 sidptr->revision);
133 strptr += len;
9409ae58 134
193cdd8a
JL
135 /* The authority field is a single 48-bit number */
136 id_auth_val = (unsigned long long)sidptr->authority[5];
137 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
138 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
139 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
140 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
141 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
142
143 /*
144 * MS-DTYP states that if the authority is >= 2^32, then it should be
145 * expressed as a hex value.
146 */
147 if (id_auth_val <= UINT_MAX)
148 len = sprintf(strptr, "-%llu", id_auth_val);
149 else
150 len = sprintf(strptr, "-0x%llx", id_auth_val);
151
152 strptr += len;
9409ae58
SP
153
154 for (i = 0; i < sidptr->num_subauth; ++i) {
155 saval = le32_to_cpu(sidptr->sub_auth[i]);
faa65f07
JL
156 len = sprintf(strptr, "-%u", saval);
157 strptr += len;
9409ae58 158 }
faa65f07
JL
159
160 return sidstr;
9409ae58
SP
161}
162
436bb435
JL
163/*
164 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
165 * the same returns zero, if they do not match returns non-zero.
166 */
167static int
168compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
169{
170 int i;
171 int num_subauth, num_sat, num_saw;
172
173 if ((!ctsid) || (!cwsid))
174 return 1;
175
176 /* compare the revision */
177 if (ctsid->revision != cwsid->revision) {
178 if (ctsid->revision > cwsid->revision)
179 return 1;
180 else
181 return -1;
182 }
183
184 /* compare all of the six auth values */
185 for (i = 0; i < NUM_AUTHS; ++i) {
186 if (ctsid->authority[i] != cwsid->authority[i]) {
187 if (ctsid->authority[i] > cwsid->authority[i])
188 return 1;
189 else
190 return -1;
191 }
192 }
193
194 /* compare all of the subauth values if any */
195 num_sat = ctsid->num_subauth;
196 num_saw = cwsid->num_subauth;
197 num_subauth = num_sat < num_saw ? num_sat : num_saw;
198 if (num_subauth) {
199 for (i = 0; i < num_subauth; ++i) {
200 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
201 if (le32_to_cpu(ctsid->sub_auth[i]) >
202 le32_to_cpu(cwsid->sub_auth[i]))
203 return 1;
204 else
205 return -1;
206 }
207 }
208 }
209
210 return 0; /* sids compare/match */
211}
212
3514de3f
SF
213static bool
214is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
215{
216 int i;
217 int num_subauth;
218 const struct cifs_sid *pwell_known_sid;
219
220 if (!psid || (puid == NULL))
221 return false;
222
223 num_subauth = psid->num_subauth;
224
225 /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
226 if (num_subauth == 2) {
227 if (is_group)
228 pwell_known_sid = &sid_unix_groups;
229 else
230 pwell_known_sid = &sid_unix_users;
231 } else if (num_subauth == 3) {
232 if (is_group)
233 pwell_known_sid = &sid_unix_NFS_groups;
234 else
235 pwell_known_sid = &sid_unix_NFS_users;
236 } else
237 return false;
238
239 /* compare the revision */
240 if (psid->revision != pwell_known_sid->revision)
241 return false;
242
243 /* compare all of the six auth values */
244 for (i = 0; i < NUM_AUTHS; ++i) {
245 if (psid->authority[i] != pwell_known_sid->authority[i]) {
246 cifs_dbg(FYI, "auth %d did not match\n", i);
247 return false;
248 }
249 }
250
251 if (num_subauth == 2) {
252 if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
253 return false;
254
255 *puid = le32_to_cpu(psid->sub_auth[1]);
256 } else /* 3 subauths, ie Windows/Mac style */ {
257 *puid = le32_to_cpu(psid->sub_auth[0]);
258 if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
259 (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
260 return false;
261
262 *puid = le32_to_cpu(psid->sub_auth[2]);
263 }
264
265 cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
266 return true; /* well known sid found, uid returned */
267}
268
36960e44
JL
269static void
270cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
271{
36f87ee7
JL
272 int i;
273
274 dst->revision = src->revision;
30c9d6cc 275 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
36f87ee7
JL
276 for (i = 0; i < NUM_AUTHS; ++i)
277 dst->authority[i] = src->authority[i];
278 for (i = 0; i < dst->num_subauth; ++i)
279 dst->sub_auth[i] = src->sub_auth[i];
36960e44
JL
280}
281
9409ae58 282static int
faa65f07 283id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
9409ae58 284{
faa65f07 285 int rc;
21fed0d5 286 struct key *sidkey;
2ae03025
JL
287 struct cifs_sid *ksid;
288 unsigned int ksid_size;
faa65f07 289 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
21fed0d5 290 const struct cred *saved_cred;
21fed0d5 291
faa65f07
JL
292 rc = snprintf(desc, sizeof(desc), "%ci:%u",
293 sidtype == SIDOWNER ? 'o' : 'g', cid);
294 if (rc >= sizeof(desc))
295 return -EINVAL;
21fed0d5 296
faa65f07
JL
297 rc = 0;
298 saved_cred = override_creds(root_cred);
028db3e2 299 sidkey = request_key(&cifs_idmap_key_type, desc, "");
faa65f07 300 if (IS_ERR(sidkey)) {
21fed0d5 301 rc = -EINVAL;
f96637be
JP
302 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
303 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
faa65f07
JL
304 goto out_revert_creds;
305 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
306 rc = -EIO;
f96637be
JP
307 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
308 __func__, sidkey->datalen);
2ae03025 309 goto invalidate_key;
21fed0d5 310 }
2ae03025 311
1f630680
JL
312 /*
313 * A sid is usually too large to be embedded in payload.value, but if
314 * there are no subauthorities and the host has 8-byte pointers, then
315 * it could be.
316 */
317 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
146aa8b1
DH
318 (struct cifs_sid *)&sidkey->payload :
319 (struct cifs_sid *)sidkey->payload.data[0];
1f630680 320
2ae03025
JL
321 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
322 if (ksid_size > sidkey->datalen) {
323 rc = -EIO;
f96637be
JP
324 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
325 __func__, sidkey->datalen, ksid_size);
2ae03025
JL
326 goto invalidate_key;
327 }
1f630680 328
2ae03025 329 cifs_copy_sid(ssid, ksid);
faa65f07
JL
330out_key_put:
331 key_put(sidkey);
332out_revert_creds:
333 revert_creds(saved_cred);
21fed0d5 334 return rc;
2ae03025
JL
335
336invalidate_key:
337 key_invalidate(sidkey);
338 goto out_key_put;
21fed0d5
SP
339}
340
9409ae58
SP
341static int
342sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
343 struct cifs_fattr *fattr, uint sidtype)
344{
f2d67931 345 int rc = 0;
faa65f07
JL
346 struct key *sidkey;
347 char *sidstr;
9409ae58 348 const struct cred *saved_cred;
8abf2775
EB
349 kuid_t fuid = cifs_sb->mnt_uid;
350 kgid_t fgid = cifs_sb->mnt_gid;
9409ae58
SP
351
352 /*
faa65f07
JL
353 * If we have too many subauthorities, then something is really wrong.
354 * Just return an error.
9409ae58 355 */
faa65f07 356 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
f96637be
JP
357 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
358 __func__, psid->num_subauth);
faa65f07 359 return -EIO;
9409ae58
SP
360 }
361
3514de3f
SF
362 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
363 uint32_t unix_id;
364 bool is_group;
365
366 if (sidtype != SIDOWNER)
367 is_group = true;
368 else
369 is_group = false;
370
371 if (is_well_known_sid(psid, &unix_id, is_group) == false)
372 goto try_upcall_to_get_id;
373
374 if (is_group) {
375 kgid_t gid;
376 gid_t id;
377
378 id = (gid_t)unix_id;
379 gid = make_kgid(&init_user_ns, id);
380 if (gid_valid(gid)) {
381 fgid = gid;
382 goto got_valid_id;
383 }
384 } else {
385 kuid_t uid;
386 uid_t id;
387
388 id = (uid_t)unix_id;
389 uid = make_kuid(&init_user_ns, id);
390 if (uid_valid(uid)) {
391 fuid = uid;
392 goto got_valid_id;
393 }
394 }
395 /* If unable to find uid/gid easily from SID try via upcall */
396 }
397
398try_upcall_to_get_id:
faa65f07
JL
399 sidstr = sid_to_key_str(psid, sidtype);
400 if (!sidstr)
401 return -ENOMEM;
402
403 saved_cred = override_creds(root_cred);
028db3e2 404 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
faa65f07
JL
405 if (IS_ERR(sidkey)) {
406 rc = -EINVAL;
f96637be
JP
407 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
408 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
faa65f07
JL
409 goto out_revert_creds;
410 }
411
412 /*
413 * FIXME: Here we assume that uid_t and gid_t are same size. It's
414 * probably a safe assumption but might be better to check based on
415 * sidtype.
416 */
355958f2 417 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
41a9f1f6 418 if (sidkey->datalen != sizeof(uid_t)) {
faa65f07 419 rc = -EIO;
f96637be
JP
420 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
421 __func__, sidkey->datalen);
2ae03025 422 key_invalidate(sidkey);
faa65f07 423 goto out_key_put;
9409ae58
SP
424 }
425
8abf2775
EB
426 if (sidtype == SIDOWNER) {
427 kuid_t uid;
428 uid_t id;
146aa8b1 429 memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
8abf2775
EB
430 uid = make_kuid(&init_user_ns, id);
431 if (uid_valid(uid))
432 fuid = uid;
433 } else {
434 kgid_t gid;
435 gid_t id;
146aa8b1 436 memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
8abf2775
EB
437 gid = make_kgid(&init_user_ns, id);
438 if (gid_valid(gid))
439 fgid = gid;
440 }
faa65f07
JL
441
442out_key_put:
443 key_put(sidkey);
444out_revert_creds:
445 revert_creds(saved_cred);
446 kfree(sidstr);
9409ae58 447
faa65f07
JL
448 /*
449 * Note that we return 0 here unconditionally. If the mapping
450 * fails then we just fall back to using the mnt_uid/mnt_gid.
451 */
3514de3f 452got_valid_id:
f2d67931 453 rc = 0;
faa65f07
JL
454 if (sidtype == SIDOWNER)
455 fattr->cf_uid = fuid;
456 else
457 fattr->cf_gid = fgid;
f2d67931 458 return rc;
9409ae58
SP
459}
460
4d79dba0
SP
461int
462init_cifs_idmap(void)
463{
464 struct cred *cred;
465 struct key *keyring;
466 int ret;
467
f96637be
JP
468 cifs_dbg(FYI, "Registering the %s key type\n",
469 cifs_idmap_key_type.name);
4d79dba0
SP
470
471 /* create an override credential set with a special thread keyring in
472 * which requests are cached
473 *
474 * this is used to prevent malicious redirections from being installed
475 * with add_key().
476 */
477 cred = prepare_kernel_cred(NULL);
478 if (!cred)
479 return -ENOMEM;
480
8e3028b9
EB
481 keyring = keyring_alloc(".cifs_idmap",
482 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
028db3e2
LT
483 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
484 KEY_USR_VIEW | KEY_USR_READ,
5ac7eace 485 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
4d79dba0
SP
486 if (IS_ERR(keyring)) {
487 ret = PTR_ERR(keyring);
488 goto failed_put_cred;
489 }
490
4d79dba0
SP
491 ret = register_key_type(&cifs_idmap_key_type);
492 if (ret < 0)
493 goto failed_put_key;
494
495 /* instruct request_key() to use this special keyring as a cache for
496 * the results it looks up */
700920eb 497 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
4d79dba0
SP
498 cred->thread_keyring = keyring;
499 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
500 root_cred = cred;
501
f96637be 502 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
4d79dba0
SP
503 return 0;
504
505failed_put_key:
506 key_put(keyring);
507failed_put_cred:
508 put_cred(cred);
509 return ret;
510}
511
512void
513exit_cifs_idmap(void)
514{
515 key_revoke(root_cred->thread_keyring);
516 unregister_key_type(&cifs_idmap_key_type);
517 put_cred(root_cred);
f96637be 518 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
4d79dba0
SP
519}
520
97837582
SF
521/* copy ntsd, owner sid, and group sid from a security descriptor to another */
522static void copy_sec_desc(const struct cifs_ntsd *pntsd,
523 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
524{
97837582
SF
525 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
526 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
527
528 /* copy security descriptor control portion */
529 pnntsd->revision = pntsd->revision;
530 pnntsd->type = pntsd->type;
531 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
532 pnntsd->sacloffset = 0;
533 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
534 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
535
536 /* copy owner sid */
537 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
538 le32_to_cpu(pntsd->osidoffset));
539 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
36960e44 540 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
97837582
SF
541
542 /* copy group sid */
543 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
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
SF
548
549 return;
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,
15b03959 559 umode_t *pbits_to_set)
630f3f0c 560{
9b5e6857 561 __u32 flags = le32_to_cpu(ace_flags);
15b03959 562 /* the order of ACEs is important. The canonical order is to begin with
ce06c9f0 563 DENY entries followed by ALLOW, otherwise an allow entry could be
15b03959 564 encountered first, making the subsequent deny entry like "dead code"
ce06c9f0 565 which would be superflous since Windows stops when a match is made
15b03959
SF
566 for the operation you are trying to perform for your user */
567
568 /* For deny ACEs we change the mask so that subsequent allow access
569 control entries do not turn on the bits we are denying */
570 if (type == ACCESS_DENIED) {
ad7a2926 571 if (flags & GENERIC_ALL)
15b03959 572 *pbits_to_set &= ~S_IRWXUGO;
ad7a2926 573
9b5e6857
AV
574 if ((flags & GENERIC_WRITE) ||
575 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 576 *pbits_to_set &= ~S_IWUGO;
9b5e6857
AV
577 if ((flags & GENERIC_READ) ||
578 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 579 *pbits_to_set &= ~S_IRUGO;
9b5e6857
AV
580 if ((flags & GENERIC_EXECUTE) ||
581 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959
SF
582 *pbits_to_set &= ~S_IXUGO;
583 return;
584 } else if (type != ACCESS_ALLOWED) {
f96637be 585 cifs_dbg(VFS, "unknown access control type %d\n", type);
15b03959
SF
586 return;
587 }
588 /* else ACCESS_ALLOWED type */
630f3f0c 589
9b5e6857 590 if (flags & GENERIC_ALL) {
15b03959 591 *pmode |= (S_IRWXUGO & (*pbits_to_set));
f96637be 592 cifs_dbg(NOISY, "all perms\n");
d61e5808
SF
593 return;
594 }
9b5e6857
AV
595 if ((flags & GENERIC_WRITE) ||
596 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 597 *pmode |= (S_IWUGO & (*pbits_to_set));
9b5e6857
AV
598 if ((flags & GENERIC_READ) ||
599 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 600 *pmode |= (S_IRUGO & (*pbits_to_set));
9b5e6857
AV
601 if ((flags & GENERIC_EXECUTE) ||
602 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959 603 *pmode |= (S_IXUGO & (*pbits_to_set));
630f3f0c 604
f52aa79d 605 cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode);
630f3f0c
SF
606 return;
607}
608
ce06c9f0
SF
609/*
610 Generate access flags to reflect permissions mode is the existing mode.
611 This function is called for every ACE in the DACL whose SID matches
612 with either owner or group or everyone.
613*/
614
615static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
616 __u32 *pace_flags)
617{
618 /* reset access mask */
619 *pace_flags = 0x0;
620
621 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
622 mode &= bits_to_use;
623
624 /* check for R/W/X UGO since we do not know whose flags
625 is this but we have cleared all the bits sans RWX for
626 either user or group or other as per bits_to_use */
627 if (mode & S_IRUGO)
628 *pace_flags |= SET_FILE_READ_RIGHTS;
629 if (mode & S_IWUGO)
630 *pace_flags |= SET_FILE_WRITE_RIGHTS;
631 if (mode & S_IXUGO)
632 *pace_flags |= SET_FILE_EXEC_RIGHTS;
633
f52aa79d 634 cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n",
f96637be 635 mode, *pace_flags);
ce06c9f0
SF
636 return;
637}
638
2b210adc 639static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
97837582
SF
640 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
641{
642 int i;
643 __u16 size = 0;
644 __u32 access_req = 0;
645
646 pntace->type = ACCESS_ALLOWED;
647 pntace->flags = 0x0;
648 mode_to_access_flags(nmode, bits, &access_req);
649 if (!access_req)
650 access_req = SET_MINIMUM_RIGHTS;
651 pntace->access_req = cpu_to_le32(access_req);
652
653 pntace->sid.revision = psid->revision;
654 pntace->sid.num_subauth = psid->num_subauth;
852e2295 655 for (i = 0; i < NUM_AUTHS; i++)
97837582
SF
656 pntace->sid.authority[i] = psid->authority[i];
657 for (i = 0; i < psid->num_subauth; i++)
658 pntace->sid.sub_auth[i] = psid->sub_auth[i];
659
660 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
661 pntace->size = cpu_to_le16(size);
662
ef571cad 663 return size;
97837582
SF
664}
665
297647c2 666
953f8681
SF
667#ifdef CONFIG_CIFS_DEBUG2
668static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
d0d66c44 669{
d0d66c44 670 int num_subauth;
d0d66c44
SP
671
672 /* validate that we do not go past end of acl */
297647c2 673
44093ca2 674 if (le16_to_cpu(pace->size) < 16) {
f96637be 675 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
44093ca2
SF
676 return;
677 }
678
679 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
f96637be 680 cifs_dbg(VFS, "ACL too small to parse ACE\n");
d0d66c44 681 return;
44093ca2 682 }
d0d66c44 683
44093ca2 684 num_subauth = pace->sid.num_subauth;
d0d66c44 685 if (num_subauth) {
8f18c131 686 int i;
f96637be
JP
687 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
688 pace->sid.revision, pace->sid.num_subauth, pace->type,
689 pace->flags, le16_to_cpu(pace->size));
d12fd121 690 for (i = 0; i < num_subauth; ++i) {
f96637be
JP
691 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
692 i, le32_to_cpu(pace->sid.sub_auth[i]));
d12fd121
SF
693 }
694
695 /* BB add length check to make sure that we do not have huge
696 num auths and therefore go off the end */
d12fd121
SF
697 }
698
699 return;
700}
953f8681 701#endif
d12fd121 702
a750e77c 703static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
d61e5808 704 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
e2f8fbfb 705 struct cifs_fattr *fattr, bool mode_from_special_sid)
d0d66c44
SP
706{
707 int i;
708 int num_aces = 0;
709 int acl_size;
710 char *acl_base;
d0d66c44
SP
711 struct cifs_ace **ppace;
712
713 /* BB need to add parm so we can store the SID BB */
714
2b83457b
SF
715 if (!pdacl) {
716 /* no DACL in the security descriptor, set
717 all the permissions for user/group/other */
0b8f18e3 718 fattr->cf_mode |= S_IRWXUGO;
2b83457b
SF
719 return;
720 }
721
d0d66c44 722 /* validate that we do not go past end of acl */
af6f4612 723 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
f96637be 724 cifs_dbg(VFS, "ACL too small to parse DACL\n");
d0d66c44
SP
725 return;
726 }
727
f96637be
JP
728 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
729 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
730 le32_to_cpu(pdacl->num_aces));
d0d66c44 731
7505e052
SF
732 /* reset rwx permissions for user/group/other.
733 Also, if num_aces is 0 i.e. DACL has no ACEs,
734 user/group/other have no permissions */
0b8f18e3 735 fattr->cf_mode &= ~(S_IRWXUGO);
7505e052 736
d0d66c44
SP
737 acl_base = (char *)pdacl;
738 acl_size = sizeof(struct cifs_acl);
739
adbc0358 740 num_aces = le32_to_cpu(pdacl->num_aces);
a5ff3769 741 if (num_aces > 0) {
15b03959
SF
742 umode_t user_mask = S_IRWXU;
743 umode_t group_mask = S_IRWXG;
2fbc2f17 744 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
15b03959 745
7250170c
DC
746 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
747 return;
6da2ec56
KC
748 ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
749 GFP_KERNEL);
f96637be 750 if (!ppace)
8132b65b 751 return;
d0d66c44 752
d0d66c44 753 for (i = 0; i < num_aces; ++i) {
44093ca2 754 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
953f8681
SF
755#ifdef CONFIG_CIFS_DEBUG2
756 dump_ace(ppace[i], end_of_acl);
757#endif
e2f8fbfb
SF
758 if (mode_from_special_sid &&
759 (compare_sids(&(ppace[i]->sid),
760 &sid_unix_NFS_mode) == 0)) {
761 /*
762 * Full permissions are:
763 * 07777 = S_ISUID | S_ISGID | S_ISVTX |
764 * S_IRWXU | S_IRWXG | S_IRWXO
765 */
766 fattr->cf_mode &= ~07777;
767 fattr->cf_mode |=
768 le32_to_cpu(ppace[i]->sid.sub_auth[2]);
769 break;
770 } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
e01b6400 771 access_flags_to_mode(ppace[i]->access_req,
15b03959 772 ppace[i]->type,
0b8f18e3 773 &fattr->cf_mode,
15b03959 774 &user_mask);
e2f8fbfb 775 else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
e01b6400 776 access_flags_to_mode(ppace[i]->access_req,
15b03959 777 ppace[i]->type,
0b8f18e3 778 &fattr->cf_mode,
15b03959 779 &group_mask);
e2f8fbfb 780 else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
e01b6400 781 access_flags_to_mode(ppace[i]->access_req,
15b03959 782 ppace[i]->type,
0b8f18e3 783 &fattr->cf_mode,
15b03959 784 &other_mask);
e2f8fbfb 785 else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
2fbc2f17
SP
786 access_flags_to_mode(ppace[i]->access_req,
787 ppace[i]->type,
788 &fattr->cf_mode,
789 &other_mask);
790
e01b6400 791
44093ca2 792/* memcpy((void *)(&(cifscred->aces[i])),
d12fd121
SF
793 (void *)ppace[i],
794 sizeof(struct cifs_ace)); */
d0d66c44 795
44093ca2
SF
796 acl_base = (char *)ppace[i];
797 acl_size = le16_to_cpu(ppace[i]->size);
d0d66c44
SP
798 }
799
800 kfree(ppace);
d0d66c44
SP
801 }
802
803 return;
804}
805
643fbcee
SF
806unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
807{
808 int i;
809 unsigned int ace_size = 20;
810
811 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
812 pntace->flags = 0x0;
813 pntace->access_req = cpu_to_le32(GENERIC_ALL);
814 pntace->sid.num_subauth = 1;
815 pntace->sid.revision = 1;
816 for (i = 0; i < NUM_AUTHS; i++)
817 pntace->sid.authority[i] = sid_authusers.authority[i];
818
819 pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
820
821 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
822 pntace->size = cpu_to_le16(ace_size);
823 return ace_size;
824}
825
fdef665b
SF
826/*
827 * Fill in the special SID based on the mode. See
828 * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
829 */
830unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
831{
832 int i;
833 unsigned int ace_size = 28;
834
835 pntace->type = ACCESS_DENIED_ACE_TYPE;
836 pntace->flags = 0x0;
837 pntace->access_req = 0;
838 pntace->sid.num_subauth = 3;
839 pntace->sid.revision = 1;
840 for (i = 0; i < NUM_AUTHS; i++)
841 pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
842
843 pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
844 pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
845 pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
846
847 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
848 pntace->size = cpu_to_le16(ace_size);
849 return ace_size;
850}
bcb02034 851
975221ec
SF
852unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
853{
854 int i;
855 unsigned int ace_size = 28;
856
857 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
858 pntace->flags = 0x0;
859 pntace->access_req = cpu_to_le32(GENERIC_ALL);
860 pntace->sid.num_subauth = 3;
861 pntace->sid.revision = 1;
862 for (i = 0; i < NUM_AUTHS; i++)
863 pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
864
865 pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
866 pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
867 pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
868
869 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
870 pntace->size = cpu_to_le16(ace_size);
871 return ace_size;
872}
873
97837582 874static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
22442179 875 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
97837582 876{
2b210adc 877 u16 size = 0;
e37a02c7 878 u32 num_aces = 0;
97837582
SF
879 struct cifs_acl *pnndacl;
880
881 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
882
22442179
SF
883 if (modefromsid) {
884 struct cifs_ace *pntace =
885 (struct cifs_ace *)((char *)pnndacl + size);
22442179 886
fdef665b 887 size += setup_special_mode_ACE(pntace, nmode);
e37a02c7
AA
888 num_aces++;
889 }
890
891 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
892 pownersid, nmode, S_IRWXU);
893 num_aces++;
894 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
895 pgrpsid, nmode, S_IRWXG);
896 num_aces++;
897 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
898 &sid_everyone, nmode, S_IRWXO);
899 num_aces++;
22442179 900
e37a02c7 901 pndacl->num_aces = cpu_to_le32(num_aces);
97837582 902 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
97837582 903
ef571cad 904 return 0;
97837582
SF
905}
906
907
bcb02034
SF
908static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
909{
910 /* BB need to add parm so we can store the SID BB */
911
b9c7a2bb
SF
912 /* validate that we do not go past end of ACL - sid must be at least 8
913 bytes long (assuming no sub-auths - e.g. the null SID */
914 if (end_of_acl < (char *)psid + 8) {
f96637be 915 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
bcb02034
SF
916 return -EINVAL;
917 }
d0d66c44 918
bcb02034 919#ifdef CONFIG_CIFS_DEBUG2
fc03d8a5 920 if (psid->num_subauth) {
8f18c131 921 int i;
f96637be
JP
922 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
923 psid->revision, psid->num_subauth);
bcb02034 924
af6f4612 925 for (i = 0; i < psid->num_subauth; i++) {
f96637be
JP
926 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
927 i, le32_to_cpu(psid->sub_auth[i]));
d0d66c44
SP
928 }
929
d12fd121 930 /* BB add length check to make sure that we do not have huge
d0d66c44 931 num auths and therefore go off the end */
f96637be
JP
932 cifs_dbg(FYI, "RID 0x%x\n",
933 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
d0d66c44 934 }
fc03d8a5 935#endif
d0d66c44 936
bcb02034
SF
937 return 0;
938}
939
d0d66c44 940
bcb02034 941/* Convert CIFS ACL to POSIX form */
9409ae58 942static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
e2f8fbfb
SF
943 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
944 bool get_mode_from_special_sid)
bcb02034 945{
9409ae58 946 int rc = 0;
bcb02034
SF
947 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
948 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
bcb02034 949 char *end_of_acl = ((char *)pntsd) + acl_len;
7505e052 950 __u32 dacloffset;
bcb02034 951
0b8f18e3 952 if (pntsd == NULL)
b9c7a2bb
SF
953 return -EIO;
954
bcb02034 955 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 956 le32_to_cpu(pntsd->osidoffset));
bcb02034 957 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 958 le32_to_cpu(pntsd->gsidoffset));
7505e052 959 dacloffset = le32_to_cpu(pntsd->dacloffset);
63d2583f 960 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
f96637be 961 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
af6f4612
SF
962 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
963 le32_to_cpu(pntsd->gsidoffset),
b6b38f70 964 le32_to_cpu(pntsd->sacloffset), dacloffset);
b9c7a2bb 965/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
bcb02034 966 rc = parse_sid(owner_sid_ptr, end_of_acl);
9409ae58 967 if (rc) {
f96637be 968 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
9409ae58
SP
969 return rc;
970 }
971 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
972 if (rc) {
f96637be
JP
973 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
974 __func__, rc);
bcb02034 975 return rc;
9409ae58 976 }
bcb02034
SF
977
978 rc = parse_sid(group_sid_ptr, end_of_acl);
9409ae58 979 if (rc) {
f96637be
JP
980 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
981 __func__, rc);
bcb02034 982 return rc;
9409ae58
SP
983 }
984 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
985 if (rc) {
f96637be
JP
986 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
987 __func__, rc);
9409ae58
SP
988 return rc;
989 }
bcb02034 990
7505e052
SF
991 if (dacloffset)
992 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
e2f8fbfb 993 group_sid_ptr, fattr, get_mode_from_special_sid);
7505e052 994 else
f96637be 995 cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
d0d66c44 996
9409ae58 997 return rc;
bcb02034 998}
b9c7a2bb 999
97837582
SF
1000/* Convert permission bits from mode to equivalent CIFS ACL */
1001static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
22442179 1002 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
a6603398 1003 bool mode_from_sid, bool id_from_sid, int *aclflag)
97837582
SF
1004{
1005 int rc = 0;
1006 __u32 dacloffset;
1007 __u32 ndacloffset;
1008 __u32 sidsoffset;
1009 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
a5ff3769 1010 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
97837582
SF
1011 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
1012 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
1013
a5ff3769
SP
1014 if (nmode != NO_CHANGE_64) { /* chmod */
1015 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 1016 le32_to_cpu(pntsd->osidoffset));
a5ff3769 1017 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 1018 le32_to_cpu(pntsd->gsidoffset));
a5ff3769
SP
1019 dacloffset = le32_to_cpu(pntsd->dacloffset);
1020 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1021 ndacloffset = sizeof(struct cifs_ntsd);
1022 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1023 ndacl_ptr->revision = dacl_ptr->revision;
1024 ndacl_ptr->size = 0;
1025 ndacl_ptr->num_aces = 0;
1026
1027 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
22442179 1028 nmode, mode_from_sid);
a5ff3769
SP
1029 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1030 /* copy sec desc control portion & owner and group sids */
1031 copy_sec_desc(pntsd, pnntsd, sidsoffset);
1032 *aclflag = CIFS_ACL_DACL;
1033 } else {
1034 memcpy(pnntsd, pntsd, secdesclen);
8abf2775
EB
1035 if (uid_valid(uid)) { /* chown */
1036 uid_t id;
a5ff3769
SP
1037 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1038 le32_to_cpu(pnntsd->osidoffset));
1039 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1040 GFP_KERNEL);
1041 if (!nowner_sid_ptr)
1042 return -ENOMEM;
8abf2775 1043 id = from_kuid(&init_user_ns, uid);
a6603398
SF
1044 if (id_from_sid) {
1045 struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
1046 /* Populate the user ownership fields S-1-5-88-1 */
1047 osid->Revision = 1;
1048 osid->NumAuth = 3;
1049 osid->Authority[5] = 5;
1050 osid->SubAuthorities[0] = cpu_to_le32(88);
1051 osid->SubAuthorities[1] = cpu_to_le32(1);
1052 osid->SubAuthorities[2] = cpu_to_le32(id);
1053 } else { /* lookup sid with upcall */
1054 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
1055 if (rc) {
1056 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
1057 __func__, rc, id);
1058 kfree(nowner_sid_ptr);
1059 return rc;
1060 }
a5ff3769 1061 }
36960e44 1062 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
a5ff3769
SP
1063 kfree(nowner_sid_ptr);
1064 *aclflag = CIFS_ACL_OWNER;
1065 }
8abf2775
EB
1066 if (gid_valid(gid)) { /* chgrp */
1067 gid_t id;
a5ff3769
SP
1068 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1069 le32_to_cpu(pnntsd->gsidoffset));
1070 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1071 GFP_KERNEL);
1072 if (!ngroup_sid_ptr)
1073 return -ENOMEM;
8abf2775 1074 id = from_kgid(&init_user_ns, gid);
a6603398
SF
1075 if (id_from_sid) {
1076 struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
1077 /* Populate the group ownership fields S-1-5-88-2 */
1078 gsid->Revision = 1;
1079 gsid->NumAuth = 3;
1080 gsid->Authority[5] = 5;
1081 gsid->SubAuthorities[0] = cpu_to_le32(88);
1082 gsid->SubAuthorities[1] = cpu_to_le32(2);
1083 gsid->SubAuthorities[2] = cpu_to_le32(id);
1084 } else { /* lookup sid with upcall */
1085 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
1086 if (rc) {
1087 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
1088 __func__, rc, id);
1089 kfree(ngroup_sid_ptr);
1090 return rc;
1091 }
a5ff3769 1092 }
36960e44 1093 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
a5ff3769
SP
1094 kfree(ngroup_sid_ptr);
1095 *aclflag = CIFS_ACL_GROUP;
1096 }
1097 }
97837582 1098
ef571cad 1099 return rc;
97837582
SF
1100}
1101
42eacf9e
SF
1102struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1103 const struct cifs_fid *cifsfid, u32 *pacllen)
b9c7a2bb 1104{
b9c7a2bb 1105 struct cifs_ntsd *pntsd = NULL;
6d5786a3
PS
1106 unsigned int xid;
1107 int rc;
7ffec372
JL
1108 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1109
1110 if (IS_ERR(tlink))
987b21d7 1111 return ERR_CAST(tlink);
b9c7a2bb 1112
6d5786a3 1113 xid = get_xid();
42eacf9e
SF
1114 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1115 pacllen);
6d5786a3 1116 free_xid(xid);
b9c7a2bb 1117
7ffec372 1118 cifs_put_tlink(tlink);
b9c7a2bb 1119
f96637be 1120 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
987b21d7
SP
1121 if (rc)
1122 return ERR_PTR(rc);
1bf4072d
CH
1123 return pntsd;
1124}
8b1327f6 1125
1bf4072d
CH
1126static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1127 const char *path, u32 *pacllen)
1128{
1129 struct cifs_ntsd *pntsd = NULL;
1130 int oplock = 0;
6d5786a3 1131 unsigned int xid;
0f060936 1132 int rc;
96daf2b0 1133 struct cifs_tcon *tcon;
7ffec372 1134 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40
PS
1135 struct cifs_fid fid;
1136 struct cifs_open_parms oparms;
7ffec372
JL
1137
1138 if (IS_ERR(tlink))
987b21d7 1139 return ERR_CAST(tlink);
b9c7a2bb 1140
7ffec372 1141 tcon = tlink_tcon(tlink);
6d5786a3 1142 xid = get_xid();
1bf4072d 1143
d81b8a40
PS
1144 oparms.tcon = tcon;
1145 oparms.cifs_sb = cifs_sb;
1146 oparms.desired_access = READ_CONTROL;
0f060936 1147 oparms.create_options = cifs_create_options(cifs_sb, 0);
d81b8a40
PS
1148 oparms.disposition = FILE_OPEN;
1149 oparms.path = path;
1150 oparms.fid = &fid;
1151 oparms.reconnect = false;
1152
1153 rc = CIFS_open(xid, &oparms, &oplock, NULL);
987b21d7 1154 if (!rc) {
d81b8a40
PS
1155 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1156 CIFSSMBClose(xid, tcon, fid.netfid);
b9c7a2bb
SF
1157 }
1158
7ffec372 1159 cifs_put_tlink(tlink);
6d5786a3 1160 free_xid(xid);
987b21d7 1161
f96637be 1162 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
987b21d7
SP
1163 if (rc)
1164 return ERR_PTR(rc);
7505e052
SF
1165 return pntsd;
1166}
1167
1bf4072d 1168/* Retrieve an ACL from the server */
fbeba8bb 1169struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1bf4072d
CH
1170 struct inode *inode, const char *path,
1171 u32 *pacllen)
1172{
1173 struct cifs_ntsd *pntsd = NULL;
1174 struct cifsFileInfo *open_file = NULL;
1175
1176 if (inode)
6508d904 1177 open_file = find_readable_file(CIFS_I(inode), true);
1bf4072d
CH
1178 if (!open_file)
1179 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1180
42eacf9e 1181 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
6ab409b5 1182 cifsFileInfo_put(open_file);
1bf4072d
CH
1183 return pntsd;
1184}
1185
a5ff3769
SP
1186 /* Set an ACL on the server */
1187int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1188 struct inode *inode, const char *path, int aclflag)
b96d31a6
CH
1189{
1190 int oplock = 0;
6d5786a3 1191 unsigned int xid;
0f060936 1192 int rc, access_flags;
96daf2b0 1193 struct cifs_tcon *tcon;
a5ff3769 1194 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec372 1195 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40
PS
1196 struct cifs_fid fid;
1197 struct cifs_open_parms oparms;
97837582 1198
7ffec372
JL
1199 if (IS_ERR(tlink))
1200 return PTR_ERR(tlink);
1201
1202 tcon = tlink_tcon(tlink);
6d5786a3 1203 xid = get_xid();
97837582 1204
a5ff3769
SP
1205 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1206 access_flags = WRITE_OWNER;
1207 else
1208 access_flags = WRITE_DAC;
1209
d81b8a40
PS
1210 oparms.tcon = tcon;
1211 oparms.cifs_sb = cifs_sb;
1212 oparms.desired_access = access_flags;
0f060936 1213 oparms.create_options = cifs_create_options(cifs_sb, 0);
d81b8a40
PS
1214 oparms.disposition = FILE_OPEN;
1215 oparms.path = path;
1216 oparms.fid = &fid;
1217 oparms.reconnect = false;
1218
1219 rc = CIFS_open(xid, &oparms, &oplock, NULL);
b96d31a6 1220 if (rc) {
f96637be 1221 cifs_dbg(VFS, "Unable to open file to set ACL\n");
b96d31a6 1222 goto out;
97837582
SF
1223 }
1224
d81b8a40 1225 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
f96637be 1226 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
97837582 1227
d81b8a40 1228 CIFSSMBClose(xid, tcon, fid.netfid);
7ffec372 1229out:
6d5786a3 1230 free_xid(xid);
7ffec372 1231 cifs_put_tlink(tlink);
b96d31a6
CH
1232 return rc;
1233}
97837582 1234
36c7ce4a 1235/* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
987b21d7 1236int
0b8f18e3 1237cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
e2f8fbfb
SF
1238 struct inode *inode, bool mode_from_special_sid,
1239 const char *path, const struct cifs_fid *pfid)
7505e052
SF
1240{
1241 struct cifs_ntsd *pntsd = NULL;
1242 u32 acllen = 0;
1243 int rc = 0;
42eacf9e 1244 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
ecdcf622 1245 struct smb_version_operations *ops;
7505e052 1246
f96637be 1247 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1bf4072d 1248
42eacf9e
SF
1249 if (IS_ERR(tlink))
1250 return PTR_ERR(tlink);
7505e052 1251
ecdcf622
JP
1252 ops = tlink_tcon(tlink)->ses->server->ops;
1253
1254 if (pfid && (ops->get_acl_by_fid))
1255 pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
1256 else if (ops->get_acl)
1257 pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
42eacf9e
SF
1258 else {
1259 cifs_put_tlink(tlink);
1260 return -EOPNOTSUPP;
1261 }
7505e052 1262 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
987b21d7
SP
1263 if (IS_ERR(pntsd)) {
1264 rc = PTR_ERR(pntsd);
f96637be 1265 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
e2f8fbfb
SF
1266 } else if (mode_from_special_sid) {
1267 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
987b21d7 1268 } else {
e2f8fbfb
SF
1269 /* get approximated mode from ACL */
1270 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
987b21d7
SP
1271 kfree(pntsd);
1272 if (rc)
f96637be 1273 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
987b21d7 1274 }
7505e052 1275
42eacf9e
SF
1276 cifs_put_tlink(tlink);
1277
987b21d7 1278 return rc;
b9c7a2bb 1279}
953f8681 1280
7505e052 1281/* Convert mode bits to an ACL so we can update the ACL on the server */
a5ff3769
SP
1282int
1283id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
8abf2775 1284 kuid_t uid, kgid_t gid)
953f8681
SF
1285{
1286 int rc = 0;
a5ff3769 1287 int aclflag = CIFS_ACL_DACL; /* default flag to set */
cce246ee 1288 __u32 secdesclen = 0;
97837582
SF
1289 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1290 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
83e3bc23
SF
1291 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1292 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
ecdcf622 1293 struct smb_version_operations *ops;
a6603398 1294 bool mode_from_sid, id_from_sid;
83e3bc23
SF
1295
1296 if (IS_ERR(tlink))
1297 return PTR_ERR(tlink);
ecdcf622
JP
1298
1299 ops = tlink_tcon(tlink)->ses->server->ops;
953f8681 1300
f96637be 1301 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
953f8681
SF
1302
1303 /* Get the security descriptor */
83e3bc23 1304
ecdcf622 1305 if (ops->get_acl == NULL) {
83e3bc23
SF
1306 cifs_put_tlink(tlink);
1307 return -EOPNOTSUPP;
1308 }
1309
ecdcf622 1310 pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
987b21d7
SP
1311 if (IS_ERR(pntsd)) {
1312 rc = PTR_ERR(pntsd);
f96637be 1313 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
83e3bc23
SF
1314 cifs_put_tlink(tlink);
1315 return rc;
c78cd838 1316 }
7505e052 1317
c78cd838
JL
1318 /*
1319 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1320 * as chmod disables ACEs and set the security descriptor. Allocate
1321 * memory for the smb header, set security descriptor request security
1322 * descriptor parameters, and secuirty descriptor itself
1323 */
7ee0b4c6 1324 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
c78cd838
JL
1325 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1326 if (!pnntsd) {
c78cd838 1327 kfree(pntsd);
83e3bc23 1328 cifs_put_tlink(tlink);
c78cd838
JL
1329 return -ENOMEM;
1330 }
97837582 1331
22442179
SF
1332 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
1333 mode_from_sid = true;
1334 else
1335 mode_from_sid = false;
1336
a6603398
SF
1337 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
1338 id_from_sid = true;
1339 else
1340 id_from_sid = false;
1341
c78cd838 1342 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
a6603398 1343 mode_from_sid, id_from_sid, &aclflag);
97837582 1344
f96637be 1345 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
97837582 1346
ecdcf622 1347 if (ops->set_acl == NULL)
83e3bc23
SF
1348 rc = -EOPNOTSUPP;
1349
c78cd838
JL
1350 if (!rc) {
1351 /* Set the security descriptor */
ecdcf622 1352 rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
f96637be 1353 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
97837582 1354 }
83e3bc23 1355 cifs_put_tlink(tlink);
97837582 1356
c78cd838
JL
1357 kfree(pnntsd);
1358 kfree(pntsd);
ef571cad 1359 return rc;
953f8681 1360}