File Index
Files and directories
Sign in
FILE

cifsacl.c

File preview with syntax highlighting.

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