Linux Audio

Check our new training course

Loading...
v3.1
   1/*
   2 *   fs/cifs/cifsacl.c
   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 *   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
  24#include <linux/fs.h>
  25#include <linux/slab.h>
  26#include <linux/string.h>
  27#include <linux/keyctl.h>
  28#include <linux/key-type.h>
  29#include <keys/user-type.h>
  30#include "cifspdu.h"
  31#include "cifsglob.h"
  32#include "cifsacl.h"
  33#include "cifsproto.h"
  34#include "cifs_debug.h"
  35
  36/* security id for everyone/world system group */
  37static const struct cifs_sid sid_everyone = {
  38	1, 1, {0, 0, 0, 0, 0, 1}, {0} };
  39/* security id for Authenticated Users system group */
  40static const struct cifs_sid sid_authusers = {
  41	1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
  42/* group users */
  43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
  44
  45const struct cred *root_cred;
  46
  47static void
  48shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
  49			int *nr_del)
  50{
  51	struct rb_node *node;
  52	struct rb_node *tmp;
  53	struct cifs_sid_id *psidid;
  54
  55	node = rb_first(root);
  56	while (node) {
  57		tmp = node;
  58		node = rb_next(tmp);
  59		psidid = rb_entry(tmp, struct cifs_sid_id, rbnode);
  60		if (nr_to_scan == 0 || *nr_del == nr_to_scan)
  61			++(*nr_rem);
  62		else {
  63			if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE)
  64						&& psidid->refcount == 0) {
  65				rb_erase(tmp, root);
  66				++(*nr_del);
  67			} else
  68				++(*nr_rem);
  69		}
  70	}
  71}
  72
  73/*
  74 * Run idmap cache shrinker.
  75 */
  76static int
  77cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
  78{
  79	int nr_to_scan = sc->nr_to_scan;
  80	int nr_del = 0;
  81	int nr_rem = 0;
  82	struct rb_root *root;
  83
  84	root = &uidtree;
  85	spin_lock(&siduidlock);
  86	shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
  87	spin_unlock(&siduidlock);
  88
  89	root = &gidtree;
  90	spin_lock(&sidgidlock);
  91	shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
  92	spin_unlock(&sidgidlock);
 
 
 
 
 
 
 
 
 
 
  93
  94	return nr_rem;
  95}
  96
  97static struct shrinker cifs_shrinker = {
  98	.shrink = cifs_idmap_shrinker,
  99	.seeks = DEFAULT_SEEKS,
 100};
 101
 102static int
 103cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen)
 104{
 105	char *payload;
 106
 107	payload = kmalloc(datalen, GFP_KERNEL);
 108	if (!payload)
 109		return -ENOMEM;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 110
 111	memcpy(payload, data, datalen);
 112	key->payload.data = payload;
 113	return 0;
 114}
 115
 116static inline void
 117cifs_idmap_key_destroy(struct key *key)
 118{
 119	kfree(key->payload.data);
 
 120}
 121
 122struct key_type cifs_idmap_key_type = {
 123	.name        = "cifs.idmap",
 124	.instantiate = cifs_idmap_key_instantiate,
 125	.destroy     = cifs_idmap_key_destroy,
 126	.describe    = user_describe,
 127	.match       = user_match,
 128};
 129
 130static void
 131sid_to_str(struct cifs_sid *sidptr, char *sidstr)
 132{
 133	int i;
 134	unsigned long saval;
 135	char *strptr;
 
 
 
 
 
 
 
 
 136
 137	strptr = sidstr;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 138
 139	sprintf(strptr, "%s", "S");
 140	strptr = sidstr + strlen(sidstr);
 
 
 
 141
 142	sprintf(strptr, "-%d", sidptr->revision);
 143	strptr = sidstr + strlen(sidstr);
 144
 145	for (i = 0; i < 6; ++i) {
 146		if (sidptr->authority[i]) {
 147			sprintf(strptr, "-%d", sidptr->authority[i]);
 148			strptr = sidstr + strlen(sidstr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 149		}
 150	}
 151
 152	for (i = 0; i < sidptr->num_subauth; ++i) {
 153		saval = le32_to_cpu(sidptr->sub_auth[i]);
 154		sprintf(strptr, "-%ld", saval);
 155		strptr = sidstr + strlen(sidstr);
 
 
 
 
 
 
 
 
 
 
 156	}
 
 
 157}
 158
 159static void
 160id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
 161		struct cifs_sid_id **psidid, char *typestr)
 162{
 163	int rc;
 164	char *strptr;
 165	struct rb_node *node = root->rb_node;
 166	struct rb_node *parent = NULL;
 167	struct rb_node **linkto = &(root->rb_node);
 168	struct cifs_sid_id *lsidid;
 169
 170	while (node) {
 171		lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
 172		parent = node;
 173		rc = compare_sids(sidptr, &((lsidid)->sid));
 174		if (rc > 0) {
 175			linkto = &(node->rb_left);
 176			node = node->rb_left;
 177		} else if (rc < 0) {
 178			linkto = &(node->rb_right);
 179			node = node->rb_right;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 180		}
 181	}
 182
 183	memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
 184	(*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
 185	(*psidid)->refcount = 0;
 
 
 
 
 
 
 
 
 
 
 186
 187	sprintf((*psidid)->sidstr, "%s", typestr);
 188	strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
 189	sid_to_str(&(*psidid)->sid, strptr);
 190
 191	clear_bit(SID_ID_PENDING, &(*psidid)->state);
 192	clear_bit(SID_ID_MAPPED, &(*psidid)->state);
 
 
 193
 194	rb_link_node(&(*psidid)->rbnode, parent, linkto);
 195	rb_insert_color(&(*psidid)->rbnode, root);
 
 
 
 
 196}
 197
 198static struct cifs_sid_id *
 199id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
 200{
 201	int rc;
 202	struct rb_node *node = root->rb_node;
 203	struct cifs_sid_id *lsidid;
 
 
 
 
 
 
 
 
 204
 205	while (node) {
 206		lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
 207		rc = compare_sids(sidptr, &((lsidid)->sid));
 208		if (rc > 0) {
 209			node = node->rb_left;
 210		} else if (rc < 0) {
 211			node = node->rb_right;
 212		} else /* node found */
 213			return lsidid;
 
 
 
 
 214	}
 215
 216	return NULL;
 217}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 218
 219static int
 220sidid_pending_wait(void *unused)
 221{
 222	schedule();
 223	return signal_pending(current) ? -ERESTARTSYS : 0;
 224}
 225
 226static int
 227sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
 228		struct cifs_fattr *fattr, uint sidtype)
 229{
 230	int rc;
 231	unsigned long cid;
 232	struct key *idkey;
 233	const struct cred *saved_cred;
 234	struct cifs_sid_id *psidid, *npsidid;
 235	struct rb_root *cidtree;
 236	spinlock_t *cidlock;
 237
 238	if (sidtype == SIDOWNER) {
 239		cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
 240		cidlock = &siduidlock;
 241		cidtree = &uidtree;
 242	} else if (sidtype == SIDGROUP) {
 243		cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
 244		cidlock = &sidgidlock;
 245		cidtree = &gidtree;
 246	} else
 247		return -ENOENT;
 248
 249	spin_lock(cidlock);
 250	psidid = id_rb_search(cidtree, psid);
 
 251
 252	if (!psidid) { /* node does not exist, allocate one & attempt adding */
 253		spin_unlock(cidlock);
 254		npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
 255		if (!npsidid)
 256			return -ENOMEM;
 257
 258		npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
 259		if (!npsidid->sidstr) {
 260			kfree(npsidid);
 261			return -ENOMEM;
 262		}
 263
 264		spin_lock(cidlock);
 265		psidid = id_rb_search(cidtree, psid);
 266		if (psidid) { /* node happened to get inserted meanwhile */
 267			++psidid->refcount;
 268			spin_unlock(cidlock);
 269			kfree(npsidid->sidstr);
 270			kfree(npsidid);
 
 
 
 271		} else {
 272			psidid = npsidid;
 273			id_rb_insert(cidtree, psid, &psidid,
 274					sidtype == SIDOWNER ? "os:" : "gs:");
 275			++psidid->refcount;
 276			spin_unlock(cidlock);
 
 
 
 
 277		}
 278	} else {
 279		++psidid->refcount;
 280		spin_unlock(cidlock);
 
 
 
 
 
 
 
 
 
 
 
 
 281	}
 282
 283	/*
 284	 * If we are here, it is safe to access psidid and its fields
 285	 * since a reference was taken earlier while holding the spinlock.
 286	 * A reference on the node is put without holding the spinlock
 287	 * and it is OK to do so in this case, shrinker will not erase
 288	 * this node until all references are put and we do not access
 289	 * any fields of the node after a reference is put .
 290	 */
 291	if (test_bit(SID_ID_MAPPED, &psidid->state)) {
 292		cid = psidid->id;
 293		psidid->time = jiffies; /* update ts for accessing */
 294		goto sid_to_id_out;
 295	}
 296
 297	if (time_after(psidid->time + SID_MAP_RETRY, jiffies))
 298		goto sid_to_id_out;
 299
 300	if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
 301		saved_cred = override_creds(root_cred);
 302		idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
 303		if (IS_ERR(idkey))
 304			cFYI(1, "%s: Can't map SID to an id", __func__);
 305		else {
 306			cid = *(unsigned long *)idkey->payload.value;
 307			psidid->id = cid;
 308			set_bit(SID_ID_MAPPED, &psidid->state);
 309			key_put(idkey);
 310			kfree(psidid->sidstr);
 311		}
 312		revert_creds(saved_cred);
 313		psidid->time = jiffies; /* update ts for accessing */
 314		clear_bit(SID_ID_PENDING, &psidid->state);
 315		wake_up_bit(&psidid->state, SID_ID_PENDING);
 316	} else {
 317		rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
 318				sidid_pending_wait, TASK_INTERRUPTIBLE);
 319		if (rc) {
 320			cFYI(1, "%s: sidid_pending_wait interrupted %d",
 321					__func__, rc);
 322			--psidid->refcount; /* decremented without spinlock */
 323			return rc;
 324		}
 325		if (test_bit(SID_ID_MAPPED, &psidid->state))
 326			cid = psidid->id;
 327	}
 328
 329sid_to_id_out:
 330	--psidid->refcount; /* decremented without spinlock */
 
 
 
 
 
 
 
 
 
 331	if (sidtype == SIDOWNER)
 332		fattr->cf_uid = cid;
 333	else
 334		fattr->cf_gid = cid;
 335
 336	return 0;
 337}
 338
 339int
 340init_cifs_idmap(void)
 341{
 342	struct cred *cred;
 343	struct key *keyring;
 344	int ret;
 345
 346	cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name);
 
 347
 348	/* create an override credential set with a special thread keyring in
 349	 * which requests are cached
 350	 *
 351	 * this is used to prevent malicious redirections from being installed
 352	 * with add_key().
 353	 */
 354	cred = prepare_kernel_cred(NULL);
 355	if (!cred)
 356		return -ENOMEM;
 357
 358	keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
 359			    (KEY_POS_ALL & ~KEY_POS_SETATTR) |
 360			    KEY_USR_VIEW | KEY_USR_READ,
 361			    KEY_ALLOC_NOT_IN_QUOTA);
 
 362	if (IS_ERR(keyring)) {
 363		ret = PTR_ERR(keyring);
 364		goto failed_put_cred;
 365	}
 366
 367	ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
 368	if (ret < 0)
 369		goto failed_put_key;
 370
 371	ret = register_key_type(&cifs_idmap_key_type);
 372	if (ret < 0)
 373		goto failed_put_key;
 374
 375	/* instruct request_key() to use this special keyring as a cache for
 376	 * the results it looks up */
 
 377	cred->thread_keyring = keyring;
 378	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 379	root_cred = cred;
 380
 381	spin_lock_init(&siduidlock);
 382	uidtree = RB_ROOT;
 383	spin_lock_init(&sidgidlock);
 384	gidtree = RB_ROOT;
 385
 386	register_shrinker(&cifs_shrinker);
 387
 388	cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring));
 389	return 0;
 390
 391failed_put_key:
 392	key_put(keyring);
 393failed_put_cred:
 394	put_cred(cred);
 395	return ret;
 396}
 397
 398void
 399exit_cifs_idmap(void)
 400{
 401	key_revoke(root_cred->thread_keyring);
 402	unregister_key_type(&cifs_idmap_key_type);
 403	put_cred(root_cred);
 404	unregister_shrinker(&cifs_shrinker);
 405	cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name);
 406}
 407
 408void
 409cifs_destroy_idmaptrees(void)
 410{
 411	struct rb_root *root;
 412	struct rb_node *node;
 413
 414	root = &uidtree;
 415	spin_lock(&siduidlock);
 416	while ((node = rb_first(root)))
 417		rb_erase(node, root);
 418	spin_unlock(&siduidlock);
 419
 420	root = &gidtree;
 421	spin_lock(&sidgidlock);
 422	while ((node = rb_first(root)))
 423		rb_erase(node, root);
 424	spin_unlock(&sidgidlock);
 425}
 426
 427/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
 428   the same returns 1, if they do not match returns 0 */
 429int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 430{
 431	int i;
 432	int num_subauth, num_sat, num_saw;
 433
 434	if ((!ctsid) || (!cwsid))
 435		return 1;
 436
 437	/* compare the revision */
 438	if (ctsid->revision != cwsid->revision) {
 439		if (ctsid->revision > cwsid->revision)
 440			return 1;
 441		else
 442			return -1;
 443	}
 444
 445	/* compare all of the six auth values */
 446	for (i = 0; i < 6; ++i) {
 447		if (ctsid->authority[i] != cwsid->authority[i]) {
 448			if (ctsid->authority[i] > cwsid->authority[i])
 449				return 1;
 450			else
 451				return -1;
 452		}
 453	}
 454
 455	/* compare all of the subauth values if any */
 456	num_sat = ctsid->num_subauth;
 457	num_saw = cwsid->num_subauth;
 458	num_subauth = num_sat < num_saw ? num_sat : num_saw;
 459	if (num_subauth) {
 460		for (i = 0; i < num_subauth; ++i) {
 461			if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
 462				if (le32_to_cpu(ctsid->sub_auth[i]) >
 463					le32_to_cpu(cwsid->sub_auth[i]))
 464					return 1;
 465				else
 466					return -1;
 467			}
 468		}
 469	}
 470
 471	return 0; /* sids compare/match */
 472}
 473
 474
 475/* copy ntsd, owner sid, and group sid from a security descriptor to another */
 476static void copy_sec_desc(const struct cifs_ntsd *pntsd,
 477				struct cifs_ntsd *pnntsd, __u32 sidsoffset)
 478{
 479	int i;
 480
 481	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 482	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 483
 484	/* copy security descriptor control portion */
 485	pnntsd->revision = pntsd->revision;
 486	pnntsd->type = pntsd->type;
 487	pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
 488	pnntsd->sacloffset = 0;
 489	pnntsd->osidoffset = cpu_to_le32(sidsoffset);
 490	pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
 491
 492	/* copy owner sid */
 493	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 494				le32_to_cpu(pntsd->osidoffset));
 495	nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
 496
 497	nowner_sid_ptr->revision = owner_sid_ptr->revision;
 498	nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
 499	for (i = 0; i < 6; i++)
 500		nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
 501	for (i = 0; i < 5; i++)
 502		nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
 503
 504	/* copy group sid */
 505	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 506				le32_to_cpu(pntsd->gsidoffset));
 507	ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
 508					sizeof(struct cifs_sid));
 509
 510	ngroup_sid_ptr->revision = group_sid_ptr->revision;
 511	ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
 512	for (i = 0; i < 6; i++)
 513		ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
 514	for (i = 0; i < 5; i++)
 515		ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
 516
 517	return;
 518}
 519
 520
 521/*
 522   change posix mode to reflect permissions
 523   pmode is the existing mode (we only want to overwrite part of this
 524   bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
 525*/
 526static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
 527				 umode_t *pbits_to_set)
 528{
 529	__u32 flags = le32_to_cpu(ace_flags);
 530	/* the order of ACEs is important.  The canonical order is to begin with
 531	   DENY entries followed by ALLOW, otherwise an allow entry could be
 532	   encountered first, making the subsequent deny entry like "dead code"
 533	   which would be superflous since Windows stops when a match is made
 534	   for the operation you are trying to perform for your user */
 535
 536	/* For deny ACEs we change the mask so that subsequent allow access
 537	   control entries do not turn on the bits we are denying */
 538	if (type == ACCESS_DENIED) {
 539		if (flags & GENERIC_ALL)
 540			*pbits_to_set &= ~S_IRWXUGO;
 541
 542		if ((flags & GENERIC_WRITE) ||
 543			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
 544			*pbits_to_set &= ~S_IWUGO;
 545		if ((flags & GENERIC_READ) ||
 546			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
 547			*pbits_to_set &= ~S_IRUGO;
 548		if ((flags & GENERIC_EXECUTE) ||
 549			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
 550			*pbits_to_set &= ~S_IXUGO;
 551		return;
 552	} else if (type != ACCESS_ALLOWED) {
 553		cERROR(1, "unknown access control type %d", type);
 554		return;
 555	}
 556	/* else ACCESS_ALLOWED type */
 557
 558	if (flags & GENERIC_ALL) {
 559		*pmode |= (S_IRWXUGO & (*pbits_to_set));
 560		cFYI(DBG2, "all perms");
 561		return;
 562	}
 563	if ((flags & GENERIC_WRITE) ||
 564			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
 565		*pmode |= (S_IWUGO & (*pbits_to_set));
 566	if ((flags & GENERIC_READ) ||
 567			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
 568		*pmode |= (S_IRUGO & (*pbits_to_set));
 569	if ((flags & GENERIC_EXECUTE) ||
 570			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
 571		*pmode |= (S_IXUGO & (*pbits_to_set));
 572
 573	cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
 574	return;
 575}
 576
 577/*
 578   Generate access flags to reflect permissions mode is the existing mode.
 579   This function is called for every ACE in the DACL whose SID matches
 580   with either owner or group or everyone.
 581*/
 582
 583static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
 584				__u32 *pace_flags)
 585{
 586	/* reset access mask */
 587	*pace_flags = 0x0;
 588
 589	/* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
 590	mode &= bits_to_use;
 591
 592	/* check for R/W/X UGO since we do not know whose flags
 593	   is this but we have cleared all the bits sans RWX for
 594	   either user or group or other as per bits_to_use */
 595	if (mode & S_IRUGO)
 596		*pace_flags |= SET_FILE_READ_RIGHTS;
 597	if (mode & S_IWUGO)
 598		*pace_flags |= SET_FILE_WRITE_RIGHTS;
 599	if (mode & S_IXUGO)
 600		*pace_flags |= SET_FILE_EXEC_RIGHTS;
 601
 602	cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
 
 603	return;
 604}
 605
 606static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
 607			const struct cifs_sid *psid, __u64 nmode, umode_t bits)
 608{
 609	int i;
 610	__u16 size = 0;
 611	__u32 access_req = 0;
 612
 613	pntace->type = ACCESS_ALLOWED;
 614	pntace->flags = 0x0;
 615	mode_to_access_flags(nmode, bits, &access_req);
 616	if (!access_req)
 617		access_req = SET_MINIMUM_RIGHTS;
 618	pntace->access_req = cpu_to_le32(access_req);
 619
 620	pntace->sid.revision = psid->revision;
 621	pntace->sid.num_subauth = psid->num_subauth;
 622	for (i = 0; i < 6; i++)
 623		pntace->sid.authority[i] = psid->authority[i];
 624	for (i = 0; i < psid->num_subauth; i++)
 625		pntace->sid.sub_auth[i] = psid->sub_auth[i];
 626
 627	size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
 628	pntace->size = cpu_to_le16(size);
 629
 630	return size;
 631}
 632
 633
 634#ifdef CONFIG_CIFS_DEBUG2
 635static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 636{
 637	int num_subauth;
 638
 639	/* validate that we do not go past end of acl */
 640
 641	if (le16_to_cpu(pace->size) < 16) {
 642		cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
 643		return;
 644	}
 645
 646	if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
 647		cERROR(1, "ACL too small to parse ACE");
 648		return;
 649	}
 650
 651	num_subauth = pace->sid.num_subauth;
 652	if (num_subauth) {
 653		int i;
 654		cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
 655			pace->sid.revision, pace->sid.num_subauth, pace->type,
 656			pace->flags, le16_to_cpu(pace->size));
 657		for (i = 0; i < num_subauth; ++i) {
 658			cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
 659				le32_to_cpu(pace->sid.sub_auth[i]));
 660		}
 661
 662		/* BB add length check to make sure that we do not have huge
 663			num auths and therefore go off the end */
 664	}
 665
 666	return;
 667}
 668#endif
 669
 670
 671static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 672		       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
 673		       struct cifs_fattr *fattr)
 674{
 675	int i;
 676	int num_aces = 0;
 677	int acl_size;
 678	char *acl_base;
 679	struct cifs_ace **ppace;
 680
 681	/* BB need to add parm so we can store the SID BB */
 682
 683	if (!pdacl) {
 684		/* no DACL in the security descriptor, set
 685		   all the permissions for user/group/other */
 686		fattr->cf_mode |= S_IRWXUGO;
 687		return;
 688	}
 689
 690	/* validate that we do not go past end of acl */
 691	if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
 692		cERROR(1, "ACL too small to parse DACL");
 693		return;
 694	}
 695
 696	cFYI(DBG2, "DACL revision %d size %d num aces %d",
 697		le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
 698		le32_to_cpu(pdacl->num_aces));
 699
 700	/* reset rwx permissions for user/group/other.
 701	   Also, if num_aces is 0 i.e. DACL has no ACEs,
 702	   user/group/other have no permissions */
 703	fattr->cf_mode &= ~(S_IRWXUGO);
 704
 705	acl_base = (char *)pdacl;
 706	acl_size = sizeof(struct cifs_acl);
 707
 708	num_aces = le32_to_cpu(pdacl->num_aces);
 709	if (num_aces  > 0) {
 710		umode_t user_mask = S_IRWXU;
 711		umode_t group_mask = S_IRWXG;
 712		umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
 713
 
 
 714		ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
 715				GFP_KERNEL);
 716		if (!ppace) {
 717			cERROR(1, "DACL memory allocation error");
 718			return;
 719		}
 720
 721		for (i = 0; i < num_aces; ++i) {
 722			ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
 723#ifdef CONFIG_CIFS_DEBUG2
 724			dump_ace(ppace[i], end_of_acl);
 725#endif
 726			if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
 727				access_flags_to_mode(ppace[i]->access_req,
 728						     ppace[i]->type,
 729						     &fattr->cf_mode,
 730						     &user_mask);
 731			if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
 732				access_flags_to_mode(ppace[i]->access_req,
 733						     ppace[i]->type,
 734						     &fattr->cf_mode,
 735						     &group_mask);
 736			if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
 737				access_flags_to_mode(ppace[i]->access_req,
 738						     ppace[i]->type,
 739						     &fattr->cf_mode,
 740						     &other_mask);
 741			if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
 742				access_flags_to_mode(ppace[i]->access_req,
 743						     ppace[i]->type,
 744						     &fattr->cf_mode,
 745						     &other_mask);
 746
 747
 748/*			memcpy((void *)(&(cifscred->aces[i])),
 749				(void *)ppace[i],
 750				sizeof(struct cifs_ace)); */
 751
 752			acl_base = (char *)ppace[i];
 753			acl_size = le16_to_cpu(ppace[i]->size);
 754		}
 755
 756		kfree(ppace);
 757	}
 758
 759	return;
 760}
 761
 762
 763static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
 764			struct cifs_sid *pgrpsid, __u64 nmode)
 765{
 766	u16 size = 0;
 767	struct cifs_acl *pnndacl;
 768
 769	pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
 770
 771	size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
 772					pownersid, nmode, S_IRWXU);
 773	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 774					pgrpsid, nmode, S_IRWXG);
 775	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 776					 &sid_everyone, nmode, S_IRWXO);
 777
 778	pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
 779	pndacl->num_aces = cpu_to_le32(3);
 780
 781	return 0;
 782}
 783
 784
 785static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 786{
 787	/* BB need to add parm so we can store the SID BB */
 788
 789	/* validate that we do not go past end of ACL - sid must be at least 8
 790	   bytes long (assuming no sub-auths - e.g. the null SID */
 791	if (end_of_acl < (char *)psid + 8) {
 792		cERROR(1, "ACL too small to parse SID %p", psid);
 793		return -EINVAL;
 794	}
 795
 796	if (psid->num_subauth) {
 797#ifdef CONFIG_CIFS_DEBUG2
 
 798		int i;
 799		cFYI(1, "SID revision %d num_auth %d",
 800			psid->revision, psid->num_subauth);
 801
 802		for (i = 0; i < psid->num_subauth; i++) {
 803			cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
 804				le32_to_cpu(psid->sub_auth[i]));
 805		}
 806
 807		/* BB add length check to make sure that we do not have huge
 808			num auths and therefore go off the end */
 809		cFYI(1, "RID 0x%x",
 810			le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
 811#endif
 812	}
 
 813
 814	return 0;
 815}
 816
 817
 818/* Convert CIFS ACL to POSIX form */
 819static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 820		struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
 821{
 822	int rc = 0;
 823	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 824	struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
 825	char *end_of_acl = ((char *)pntsd) + acl_len;
 826	__u32 dacloffset;
 827
 828	if (pntsd == NULL)
 829		return -EIO;
 830
 831	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 832				le32_to_cpu(pntsd->osidoffset));
 833	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 834				le32_to_cpu(pntsd->gsidoffset));
 835	dacloffset = le32_to_cpu(pntsd->dacloffset);
 836	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 837	cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
 838		 "sacloffset 0x%x dacloffset 0x%x",
 839		 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
 840		 le32_to_cpu(pntsd->gsidoffset),
 841		 le32_to_cpu(pntsd->sacloffset), dacloffset);
 842/*	cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
 843	rc = parse_sid(owner_sid_ptr, end_of_acl);
 844	if (rc) {
 845		cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
 846		return rc;
 847	}
 848	rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
 849	if (rc) {
 850		cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
 
 851		return rc;
 852	}
 853
 854	rc = parse_sid(group_sid_ptr, end_of_acl);
 855	if (rc) {
 856		cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
 
 857		return rc;
 858	}
 859	rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
 860	if (rc) {
 861		cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
 
 862		return rc;
 863	}
 864
 865	if (dacloffset)
 866		parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
 867			   group_sid_ptr, fattr);
 868	else
 869		cFYI(1, "no ACL"); /* BB grant all or default perms? */
 870
 871/*	cifscred->uid = owner_sid_ptr->rid;
 872	cifscred->gid = group_sid_ptr->rid;
 873	memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
 874			sizeof(struct cifs_sid));
 875	memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
 876			sizeof(struct cifs_sid)); */
 877
 878	return rc;
 879}
 880
 881
 882/* Convert permission bits from mode to equivalent CIFS ACL */
 883static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
 884				struct inode *inode, __u64 nmode)
 885{
 886	int rc = 0;
 887	__u32 dacloffset;
 888	__u32 ndacloffset;
 889	__u32 sidsoffset;
 890	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 
 891	struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
 892	struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
 893
 894	if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
 895		return -EIO;
 896
 897	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 898				le32_to_cpu(pntsd->osidoffset));
 899	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 900				le32_to_cpu(pntsd->gsidoffset));
 901
 902	dacloffset = le32_to_cpu(pntsd->dacloffset);
 903	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 904
 905	ndacloffset = sizeof(struct cifs_ntsd);
 906	ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
 907	ndacl_ptr->revision = dacl_ptr->revision;
 908	ndacl_ptr->size = 0;
 909	ndacl_ptr->num_aces = 0;
 910
 911	rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode);
 912
 913	sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
 914
 915	/* copy security descriptor control portion and owner and group sid */
 916	copy_sec_desc(pntsd, pnntsd, sidsoffset);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 917
 918	return rc;
 919}
 920
 921static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 922		__u16 fid, u32 *pacllen)
 923{
 924	struct cifs_ntsd *pntsd = NULL;
 925	int xid, rc;
 
 926	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 927
 928	if (IS_ERR(tlink))
 929		return ERR_CAST(tlink);
 930
 931	xid = GetXid();
 932	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
 933	FreeXid(xid);
 
 934
 935	cifs_put_tlink(tlink);
 936
 937	cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
 938	if (rc)
 939		return ERR_PTR(rc);
 940	return pntsd;
 941}
 942
 943static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
 944		const char *path, u32 *pacllen)
 945{
 946	struct cifs_ntsd *pntsd = NULL;
 947	int oplock = 0;
 948	int xid, rc;
 949	__u16 fid;
 950	struct cifs_tcon *tcon;
 951	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
 
 952
 953	if (IS_ERR(tlink))
 954		return ERR_CAST(tlink);
 955
 956	tcon = tlink_tcon(tlink);
 957	xid = GetXid();
 958
 959	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
 960			 &fid, &oplock, NULL, cifs_sb->local_nls,
 961			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
 
 
 
 
 
 
 
 
 
 962	if (!rc) {
 963		rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
 964		CIFSSMBClose(xid, tcon, fid);
 965	}
 966
 967	cifs_put_tlink(tlink);
 968	FreeXid(xid);
 969
 970	cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
 971	if (rc)
 972		return ERR_PTR(rc);
 973	return pntsd;
 974}
 975
 976/* Retrieve an ACL from the server */
 977struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
 978				      struct inode *inode, const char *path,
 979				      u32 *pacllen)
 980{
 981	struct cifs_ntsd *pntsd = NULL;
 982	struct cifsFileInfo *open_file = NULL;
 983
 984	if (inode)
 985		open_file = find_readable_file(CIFS_I(inode), true);
 986	if (!open_file)
 987		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 988
 989	pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
 990	cifsFileInfo_put(open_file);
 991	return pntsd;
 992}
 993
 994static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
 995		struct cifs_ntsd *pnntsd, u32 acllen)
 
 996{
 997	int oplock = 0;
 998	int xid, rc;
 999	__u16 fid;
1000	struct cifs_tcon *tcon;
 
1001	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
 
1002
1003	if (IS_ERR(tlink))
1004		return PTR_ERR(tlink);
1005
1006	tcon = tlink_tcon(tlink);
1007	xid = GetXid();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1008
1009	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
1010			 &fid, &oplock, NULL, cifs_sb->local_nls,
1011			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1012	if (rc) {
1013		cERROR(1, "Unable to open file to set ACL");
1014		goto out;
1015	}
1016
1017	rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
1018	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
1019
1020	CIFSSMBClose(xid, tcon, fid);
1021out:
1022	FreeXid(xid);
1023	cifs_put_tlink(tlink);
1024	return rc;
1025}
1026
1027/* Set an ACL on the server */
1028int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1029				struct inode *inode, const char *path)
1030{
1031	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1032
1033	cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
1034
1035	return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
1036}
1037
1038/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1039int
1040cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1041		  struct inode *inode, const char *path, const __u16 *pfid)
 
1042{
1043	struct cifs_ntsd *pntsd = NULL;
1044	u32 acllen = 0;
1045	int rc = 0;
 
 
1046
1047	cFYI(DBG2, "converting ACL to mode for %s", path);
1048
1049	if (pfid)
1050		pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
1051	else
1052		pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
1053
 
 
 
 
 
 
 
 
 
 
1054	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1055	if (IS_ERR(pntsd)) {
1056		rc = PTR_ERR(pntsd);
1057		cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1058	} else {
1059		rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1060		kfree(pntsd);
1061		if (rc)
1062			cERROR(1, "parse sec desc failed rc = %d", rc);
1063	}
1064
 
 
1065	return rc;
1066}
1067
1068/* Convert mode bits to an ACL so we can update the ACL on the server */
1069int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
 
 
1070{
1071	int rc = 0;
 
1072	__u32 secdesclen = 0;
1073	struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1074	struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
 
 
 
 
 
 
 
1075
1076	cFYI(DBG2, "set ACL from mode for %s", path);
1077
1078	/* Get the security descriptor */
1079	pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1080
1081	/* Add three ACEs for owner, group, everyone getting rid of
1082	   other ACEs as chmod disables ACEs and set the security descriptor */
 
 
1083
 
 
1084	if (IS_ERR(pntsd)) {
1085		rc = PTR_ERR(pntsd);
1086		cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1087	} else {
1088		/* allocate memory for the smb header,
1089		   set security descriptor request security descriptor
1090		   parameters, and secuirty descriptor itself */
1091
1092		secdesclen = secdesclen < DEFSECDESCLEN ?
1093					DEFSECDESCLEN : secdesclen;
1094		pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1095		if (!pnntsd) {
1096			cERROR(1, "Unable to allocate security descriptor");
1097			kfree(pntsd);
1098			return -ENOMEM;
1099		}
 
 
 
 
1100
1101		rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
 
1102
1103		cFYI(DBG2, "build_sec_desc rc: %d", rc);
1104
1105		if (!rc) {
1106			/* Set the security descriptor */
1107			rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
1108			cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1109		}
1110
1111		kfree(pnntsd);
1112		kfree(pntsd);
 
 
 
1113	}
 
1114
 
 
1115	return rc;
1116}
v4.10.11
   1/*
   2 *   fs/cifs/cifsacl.c
   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 *   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
  24#include <linux/fs.h>
  25#include <linux/slab.h>
  26#include <linux/string.h>
  27#include <linux/keyctl.h>
  28#include <linux/key-type.h>
  29#include <keys/user-type.h>
  30#include "cifspdu.h"
  31#include "cifsglob.h"
  32#include "cifsacl.h"
  33#include "cifsproto.h"
  34#include "cifs_debug.h"
  35
  36/* security id for everyone/world system group */
  37static const struct cifs_sid sid_everyone = {
  38	1, 1, {0, 0, 0, 0, 0, 1}, {0} };
  39/* security id for Authenticated Users system group */
  40static const struct cifs_sid sid_authusers = {
  41	1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
  42/* group users */
  43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
  44
  45/* S-1-22-1 Unmapped Unix users */
  46static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
  47		{cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  48
  49/* S-1-22-2 Unmapped Unix groups */
  50static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
  51		{cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  52
  53/*
  54 * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
  55 */
 
 
 
 
 
 
 
  56
  57/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
 
 
 
  58
  59/* S-1-5-88-1 Unix uid */
  60static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
  61	{cpu_to_le32(88),
  62	 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  63
  64/* S-1-5-88-2 Unix gid */
  65static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
  66	{cpu_to_le32(88),
  67	 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  68
  69/* S-1-5-88-3 Unix mode */
  70static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
  71	{cpu_to_le32(88),
  72	 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  73
  74static const struct cred *root_cred;
 
 
 
 
 
 
  75
  76static int
  77cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
  78{
  79	char *payload;
  80
  81	/*
  82	 * If the payload is less than or equal to the size of a pointer, then
  83	 * an allocation here is wasteful. Just copy the data directly to the
  84	 * payload.value union member instead.
  85	 *
  86	 * With this however, you must check the datalen before trying to
  87	 * dereference payload.data!
  88	 */
  89	if (prep->datalen <= sizeof(key->payload)) {
  90		key->payload.data[0] = NULL;
  91		memcpy(&key->payload, prep->data, prep->datalen);
  92	} else {
  93		payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
  94		if (!payload)
  95			return -ENOMEM;
  96		key->payload.data[0] = payload;
  97	}
  98
  99	key->datalen = prep->datalen;
 
 100	return 0;
 101}
 102
 103static inline void
 104cifs_idmap_key_destroy(struct key *key)
 105{
 106	if (key->datalen > sizeof(key->payload))
 107		kfree(key->payload.data[0]);
 108}
 109
 110static struct key_type cifs_idmap_key_type = {
 111	.name        = "cifs.idmap",
 112	.instantiate = cifs_idmap_key_instantiate,
 113	.destroy     = cifs_idmap_key_destroy,
 114	.describe    = user_describe,
 
 115};
 116
 117static char *
 118sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
 119{
 120	int i, len;
 121	unsigned int saval;
 122	char *sidstr, *strptr;
 123	unsigned long long id_auth_val;
 124
 125	/* 3 bytes for prefix */
 126	sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
 127			 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
 128			 GFP_KERNEL);
 129	if (!sidstr)
 130		return sidstr;
 131
 132	strptr = sidstr;
 133	len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
 134			sidptr->revision);
 135	strptr += len;
 136
 137	/* The authority field is a single 48-bit number */
 138	id_auth_val = (unsigned long long)sidptr->authority[5];
 139	id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
 140	id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
 141	id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
 142	id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
 143	id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
 144
 145	/*
 146	 * MS-DTYP states that if the authority is >= 2^32, then it should be
 147	 * expressed as a hex value.
 148	 */
 149	if (id_auth_val <= UINT_MAX)
 150		len = sprintf(strptr, "-%llu", id_auth_val);
 151	else
 152		len = sprintf(strptr, "-0x%llx", id_auth_val);
 153
 154	strptr += len;
 155
 156	for (i = 0; i < sidptr->num_subauth; ++i) {
 157		saval = le32_to_cpu(sidptr->sub_auth[i]);
 158		len = sprintf(strptr, "-%u", saval);
 159		strptr += len;
 160	}
 161
 162	return sidstr;
 163}
 164
 165/*
 166 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
 167 * the same returns zero, if they do not match returns non-zero.
 168 */
 169static int
 170compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 171{
 172	int i;
 173	int num_subauth, num_sat, num_saw;
 174
 175	if ((!ctsid) || (!cwsid))
 176		return 1;
 177
 178	/* compare the revision */
 179	if (ctsid->revision != cwsid->revision) {
 180		if (ctsid->revision > cwsid->revision)
 181			return 1;
 182		else
 183			return -1;
 184	}
 185
 186	/* compare all of the six auth values */
 187	for (i = 0; i < NUM_AUTHS; ++i) {
 188		if (ctsid->authority[i] != cwsid->authority[i]) {
 189			if (ctsid->authority[i] > cwsid->authority[i])
 190				return 1;
 191			else
 192				return -1;
 193		}
 194	}
 195
 196	/* compare all of the subauth values if any */
 197	num_sat = ctsid->num_subauth;
 198	num_saw = cwsid->num_subauth;
 199	num_subauth = num_sat < num_saw ? num_sat : num_saw;
 200	if (num_subauth) {
 201		for (i = 0; i < num_subauth; ++i) {
 202			if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
 203				if (le32_to_cpu(ctsid->sub_auth[i]) >
 204					le32_to_cpu(cwsid->sub_auth[i]))
 205					return 1;
 206				else
 207					return -1;
 208			}
 209		}
 210	}
 211
 212	return 0; /* sids compare/match */
 213}
 214
 215static bool
 216is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
 
 217{
 218	int i;
 219	int num_subauth;
 220	const struct cifs_sid *pwell_known_sid;
 221
 222	if (!psid || (puid == NULL))
 223		return false;
 224
 225	num_subauth = psid->num_subauth;
 226
 227	/* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
 228	if (num_subauth == 2) {
 229		if (is_group)
 230			pwell_known_sid = &sid_unix_groups;
 231		else
 232			pwell_known_sid = &sid_unix_users;
 233	} else if (num_subauth == 3) {
 234		if (is_group)
 235			pwell_known_sid = &sid_unix_NFS_groups;
 236		else
 237			pwell_known_sid = &sid_unix_NFS_users;
 238	} else
 239		return false;
 240
 241	/* compare the revision */
 242	if (psid->revision != pwell_known_sid->revision)
 243		return false;
 244
 245	/* compare all of the six auth values */
 246	for (i = 0; i < NUM_AUTHS; ++i) {
 247		if (psid->authority[i] != pwell_known_sid->authority[i]) {
 248			cifs_dbg(FYI, "auth %d did not match\n", i);
 249			return false;
 250		}
 251	}
 252
 253	if (num_subauth == 2) {
 254		if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
 255			return false;
 256
 257		*puid = le32_to_cpu(psid->sub_auth[1]);
 258	} else /* 3 subauths, ie Windows/Mac style */ {
 259		*puid = le32_to_cpu(psid->sub_auth[0]);
 260		if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
 261		    (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
 262			return false;
 263
 264		*puid = le32_to_cpu(psid->sub_auth[2]);
 265	}
 266
 267	cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
 268	return true; /* well known sid found, uid returned */
 269}
 270
 271static void
 272cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
 273{
 274	int i;
 275
 276	dst->revision = src->revision;
 277	dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
 278	for (i = 0; i < NUM_AUTHS; ++i)
 279		dst->authority[i] = src->authority[i];
 280	for (i = 0; i < dst->num_subauth; ++i)
 281		dst->sub_auth[i] = src->sub_auth[i];
 282}
 283
 284static int
 285id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
 286{
 287	int rc;
 288	struct key *sidkey;
 289	struct cifs_sid *ksid;
 290	unsigned int ksid_size;
 291	char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
 292	const struct cred *saved_cred;
 293
 294	rc = snprintf(desc, sizeof(desc), "%ci:%u",
 295			sidtype == SIDOWNER ? 'o' : 'g', cid);
 296	if (rc >= sizeof(desc))
 297		return -EINVAL;
 298
 299	rc = 0;
 300	saved_cred = override_creds(root_cred);
 301	sidkey = request_key(&cifs_idmap_key_type, desc, "");
 302	if (IS_ERR(sidkey)) {
 303		rc = -EINVAL;
 304		cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
 305			 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
 306		goto out_revert_creds;
 307	} else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
 308		rc = -EIO;
 309		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
 310			 __func__, sidkey->datalen);
 311		goto invalidate_key;
 312	}
 313
 314	/*
 315	 * A sid is usually too large to be embedded in payload.value, but if
 316	 * there are no subauthorities and the host has 8-byte pointers, then
 317	 * it could be.
 318	 */
 319	ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
 320		(struct cifs_sid *)&sidkey->payload :
 321		(struct cifs_sid *)sidkey->payload.data[0];
 322
 323	ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
 324	if (ksid_size > sidkey->datalen) {
 325		rc = -EIO;
 326		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
 327			 __func__, sidkey->datalen, ksid_size);
 328		goto invalidate_key;
 329	}
 330
 331	cifs_copy_sid(ssid, ksid);
 332out_key_put:
 333	key_put(sidkey);
 334out_revert_creds:
 335	revert_creds(saved_cred);
 336	return rc;
 337
 338invalidate_key:
 339	key_invalidate(sidkey);
 340	goto out_key_put;
 
 
 341}
 342
 343static int
 344sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
 345		struct cifs_fattr *fattr, uint sidtype)
 346{
 347	int rc;
 348	struct key *sidkey;
 349	char *sidstr;
 350	const struct cred *saved_cred;
 351	kuid_t fuid = cifs_sb->mnt_uid;
 352	kgid_t fgid = cifs_sb->mnt_gid;
 
 353
 354	/*
 355	 * If we have too many subauthorities, then something is really wrong.
 356	 * Just return an error.
 357	 */
 358	if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
 359		cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
 360			 __func__, psid->num_subauth);
 361		return -EIO;
 362	}
 
 363
 364	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
 365		uint32_t unix_id;
 366		bool is_group;
 367
 368		if (sidtype != SIDOWNER)
 369			is_group = true;
 370		else
 371			is_group = false;
 
 372
 373		if (is_well_known_sid(psid, &unix_id, is_group) == false)
 374			goto try_upcall_to_get_id;
 
 
 
 375
 376		if (is_group) {
 377			kgid_t gid;
 378			gid_t id;
 379
 380			id = (gid_t)unix_id;
 381			gid = make_kgid(&init_user_ns, id);
 382			if (gid_valid(gid)) {
 383				fgid = gid;
 384				goto got_valid_id;
 385			}
 386		} else {
 387			kuid_t uid;
 388			uid_t id;
 389
 390			id = (uid_t)unix_id;
 391			uid = make_kuid(&init_user_ns, id);
 392			if (uid_valid(uid)) {
 393				fuid = uid;
 394				goto got_valid_id;
 395			}
 396		}
 397		/* If unable to find uid/gid easily from SID try via upcall */
 398	}
 399
 400try_upcall_to_get_id:
 401	sidstr = sid_to_key_str(psid, sidtype);
 402	if (!sidstr)
 403		return -ENOMEM;
 404
 405	saved_cred = override_creds(root_cred);
 406	sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
 407	if (IS_ERR(sidkey)) {
 408		rc = -EINVAL;
 409		cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
 410			 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
 411		goto out_revert_creds;
 412	}
 413
 414	/*
 415	 * FIXME: Here we assume that uid_t and gid_t are same size. It's
 416	 * probably a safe assumption but might be better to check based on
 417	 * sidtype.
 
 
 
 418	 */
 419	BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
 420	if (sidkey->datalen != sizeof(uid_t)) {
 421		rc = -EIO;
 422		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
 423			 __func__, sidkey->datalen);
 424		key_invalidate(sidkey);
 425		goto out_key_put;
 426	}
 427
 428	if (sidtype == SIDOWNER) {
 429		kuid_t uid;
 430		uid_t id;
 431		memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
 432		uid = make_kuid(&init_user_ns, id);
 433		if (uid_valid(uid))
 434			fuid = uid;
 
 
 
 
 
 
 
 
 
 435	} else {
 436		kgid_t gid;
 437		gid_t id;
 438		memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
 439		gid = make_kgid(&init_user_ns, id);
 440		if (gid_valid(gid))
 441			fgid = gid;
 
 
 
 
 442	}
 443
 444out_key_put:
 445	key_put(sidkey);
 446out_revert_creds:
 447	revert_creds(saved_cred);
 448	kfree(sidstr);
 449
 450	/*
 451	 * Note that we return 0 here unconditionally. If the mapping
 452	 * fails then we just fall back to using the mnt_uid/mnt_gid.
 453	 */
 454got_valid_id:
 455	if (sidtype == SIDOWNER)
 456		fattr->cf_uid = fuid;
 457	else
 458		fattr->cf_gid = fgid;
 
 459	return 0;
 460}
 461
 462int
 463init_cifs_idmap(void)
 464{
 465	struct cred *cred;
 466	struct key *keyring;
 467	int ret;
 468
 469	cifs_dbg(FYI, "Registering the %s key type\n",
 470		 cifs_idmap_key_type.name);
 471
 472	/* create an override credential set with a special thread keyring in
 473	 * which requests are cached
 474	 *
 475	 * this is used to prevent malicious redirections from being installed
 476	 * with add_key().
 477	 */
 478	cred = prepare_kernel_cred(NULL);
 479	if (!cred)
 480		return -ENOMEM;
 481
 482	keyring = keyring_alloc(".cifs_idmap",
 483				GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
 484				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
 485				KEY_USR_VIEW | KEY_USR_READ,
 486				KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
 487	if (IS_ERR(keyring)) {
 488		ret = PTR_ERR(keyring);
 489		goto failed_put_cred;
 490	}
 491
 
 
 
 
 492	ret = register_key_type(&cifs_idmap_key_type);
 493	if (ret < 0)
 494		goto failed_put_key;
 495
 496	/* instruct request_key() to use this special keyring as a cache for
 497	 * the results it looks up */
 498	set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
 499	cred->thread_keyring = keyring;
 500	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 501	root_cred = cred;
 502
 503	cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
 
 
 
 
 
 
 
 504	return 0;
 505
 506failed_put_key:
 507	key_put(keyring);
 508failed_put_cred:
 509	put_cred(cred);
 510	return ret;
 511}
 512
 513void
 514exit_cifs_idmap(void)
 515{
 516	key_revoke(root_cred->thread_keyring);
 517	unregister_key_type(&cifs_idmap_key_type);
 518	put_cred(root_cred);
 519	cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
 
 520}
 521
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 522/* copy ntsd, owner sid, and group sid from a security descriptor to another */
 523static void copy_sec_desc(const struct cifs_ntsd *pntsd,
 524				struct cifs_ntsd *pnntsd, __u32 sidsoffset)
 525{
 
 
 526	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 527	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 528
 529	/* copy security descriptor control portion */
 530	pnntsd->revision = pntsd->revision;
 531	pnntsd->type = pntsd->type;
 532	pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
 533	pnntsd->sacloffset = 0;
 534	pnntsd->osidoffset = cpu_to_le32(sidsoffset);
 535	pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
 536
 537	/* copy owner sid */
 538	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 539				le32_to_cpu(pntsd->osidoffset));
 540	nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
 541	cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
 
 
 
 
 
 
 542
 543	/* copy group sid */
 544	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 545				le32_to_cpu(pntsd->gsidoffset));
 546	ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
 547					sizeof(struct cifs_sid));
 548	cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
 
 
 
 
 
 
 549
 550	return;
 551}
 552
 553
 554/*
 555   change posix mode to reflect permissions
 556   pmode is the existing mode (we only want to overwrite part of this
 557   bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
 558*/
 559static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
 560				 umode_t *pbits_to_set)
 561{
 562	__u32 flags = le32_to_cpu(ace_flags);
 563	/* the order of ACEs is important.  The canonical order is to begin with
 564	   DENY entries followed by ALLOW, otherwise an allow entry could be
 565	   encountered first, making the subsequent deny entry like "dead code"
 566	   which would be superflous since Windows stops when a match is made
 567	   for the operation you are trying to perform for your user */
 568
 569	/* For deny ACEs we change the mask so that subsequent allow access
 570	   control entries do not turn on the bits we are denying */
 571	if (type == ACCESS_DENIED) {
 572		if (flags & GENERIC_ALL)
 573			*pbits_to_set &= ~S_IRWXUGO;
 574
 575		if ((flags & GENERIC_WRITE) ||
 576			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
 577			*pbits_to_set &= ~S_IWUGO;
 578		if ((flags & GENERIC_READ) ||
 579			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
 580			*pbits_to_set &= ~S_IRUGO;
 581		if ((flags & GENERIC_EXECUTE) ||
 582			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
 583			*pbits_to_set &= ~S_IXUGO;
 584		return;
 585	} else if (type != ACCESS_ALLOWED) {
 586		cifs_dbg(VFS, "unknown access control type %d\n", type);
 587		return;
 588	}
 589	/* else ACCESS_ALLOWED type */
 590
 591	if (flags & GENERIC_ALL) {
 592		*pmode |= (S_IRWXUGO & (*pbits_to_set));
 593		cifs_dbg(NOISY, "all perms\n");
 594		return;
 595	}
 596	if ((flags & GENERIC_WRITE) ||
 597			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
 598		*pmode |= (S_IWUGO & (*pbits_to_set));
 599	if ((flags & GENERIC_READ) ||
 600			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
 601		*pmode |= (S_IRUGO & (*pbits_to_set));
 602	if ((flags & GENERIC_EXECUTE) ||
 603			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
 604		*pmode |= (S_IXUGO & (*pbits_to_set));
 605
 606	cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode);
 607	return;
 608}
 609
 610/*
 611   Generate access flags to reflect permissions mode is the existing mode.
 612   This function is called for every ACE in the DACL whose SID matches
 613   with either owner or group or everyone.
 614*/
 615
 616static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
 617				__u32 *pace_flags)
 618{
 619	/* reset access mask */
 620	*pace_flags = 0x0;
 621
 622	/* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
 623	mode &= bits_to_use;
 624
 625	/* check for R/W/X UGO since we do not know whose flags
 626	   is this but we have cleared all the bits sans RWX for
 627	   either user or group or other as per bits_to_use */
 628	if (mode & S_IRUGO)
 629		*pace_flags |= SET_FILE_READ_RIGHTS;
 630	if (mode & S_IWUGO)
 631		*pace_flags |= SET_FILE_WRITE_RIGHTS;
 632	if (mode & S_IXUGO)
 633		*pace_flags |= SET_FILE_EXEC_RIGHTS;
 634
 635	cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n",
 636		 mode, *pace_flags);
 637	return;
 638}
 639
 640static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
 641			const struct cifs_sid *psid, __u64 nmode, umode_t bits)
 642{
 643	int i;
 644	__u16 size = 0;
 645	__u32 access_req = 0;
 646
 647	pntace->type = ACCESS_ALLOWED;
 648	pntace->flags = 0x0;
 649	mode_to_access_flags(nmode, bits, &access_req);
 650	if (!access_req)
 651		access_req = SET_MINIMUM_RIGHTS;
 652	pntace->access_req = cpu_to_le32(access_req);
 653
 654	pntace->sid.revision = psid->revision;
 655	pntace->sid.num_subauth = psid->num_subauth;
 656	for (i = 0; i < NUM_AUTHS; i++)
 657		pntace->sid.authority[i] = psid->authority[i];
 658	for (i = 0; i < psid->num_subauth; i++)
 659		pntace->sid.sub_auth[i] = psid->sub_auth[i];
 660
 661	size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
 662	pntace->size = cpu_to_le16(size);
 663
 664	return size;
 665}
 666
 667
 668#ifdef CONFIG_CIFS_DEBUG2
 669static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 670{
 671	int num_subauth;
 672
 673	/* validate that we do not go past end of acl */
 674
 675	if (le16_to_cpu(pace->size) < 16) {
 676		cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
 677		return;
 678	}
 679
 680	if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
 681		cifs_dbg(VFS, "ACL too small to parse ACE\n");
 682		return;
 683	}
 684
 685	num_subauth = pace->sid.num_subauth;
 686	if (num_subauth) {
 687		int i;
 688		cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
 689			 pace->sid.revision, pace->sid.num_subauth, pace->type,
 690			 pace->flags, le16_to_cpu(pace->size));
 691		for (i = 0; i < num_subauth; ++i) {
 692			cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
 693				 i, le32_to_cpu(pace->sid.sub_auth[i]));
 694		}
 695
 696		/* BB add length check to make sure that we do not have huge
 697			num auths and therefore go off the end */
 698	}
 699
 700	return;
 701}
 702#endif
 703
 704
 705static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 706		       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
 707		       struct cifs_fattr *fattr)
 708{
 709	int i;
 710	int num_aces = 0;
 711	int acl_size;
 712	char *acl_base;
 713	struct cifs_ace **ppace;
 714
 715	/* BB need to add parm so we can store the SID BB */
 716
 717	if (!pdacl) {
 718		/* no DACL in the security descriptor, set
 719		   all the permissions for user/group/other */
 720		fattr->cf_mode |= S_IRWXUGO;
 721		return;
 722	}
 723
 724	/* validate that we do not go past end of acl */
 725	if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
 726		cifs_dbg(VFS, "ACL too small to parse DACL\n");
 727		return;
 728	}
 729
 730	cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
 731		 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
 732		 le32_to_cpu(pdacl->num_aces));
 733
 734	/* reset rwx permissions for user/group/other.
 735	   Also, if num_aces is 0 i.e. DACL has no ACEs,
 736	   user/group/other have no permissions */
 737	fattr->cf_mode &= ~(S_IRWXUGO);
 738
 739	acl_base = (char *)pdacl;
 740	acl_size = sizeof(struct cifs_acl);
 741
 742	num_aces = le32_to_cpu(pdacl->num_aces);
 743	if (num_aces > 0) {
 744		umode_t user_mask = S_IRWXU;
 745		umode_t group_mask = S_IRWXG;
 746		umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
 747
 748		if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
 749			return;
 750		ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
 751				GFP_KERNEL);
 752		if (!ppace)
 
 753			return;
 
 754
 755		for (i = 0; i < num_aces; ++i) {
 756			ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
 757#ifdef CONFIG_CIFS_DEBUG2
 758			dump_ace(ppace[i], end_of_acl);
 759#endif
 760			if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
 761				access_flags_to_mode(ppace[i]->access_req,
 762						     ppace[i]->type,
 763						     &fattr->cf_mode,
 764						     &user_mask);
 765			if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
 766				access_flags_to_mode(ppace[i]->access_req,
 767						     ppace[i]->type,
 768						     &fattr->cf_mode,
 769						     &group_mask);
 770			if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
 771				access_flags_to_mode(ppace[i]->access_req,
 772						     ppace[i]->type,
 773						     &fattr->cf_mode,
 774						     &other_mask);
 775			if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
 776				access_flags_to_mode(ppace[i]->access_req,
 777						     ppace[i]->type,
 778						     &fattr->cf_mode,
 779						     &other_mask);
 780
 781
 782/*			memcpy((void *)(&(cifscred->aces[i])),
 783				(void *)ppace[i],
 784				sizeof(struct cifs_ace)); */
 785
 786			acl_base = (char *)ppace[i];
 787			acl_size = le16_to_cpu(ppace[i]->size);
 788		}
 789
 790		kfree(ppace);
 791	}
 792
 793	return;
 794}
 795
 796
 797static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
 798			struct cifs_sid *pgrpsid, __u64 nmode)
 799{
 800	u16 size = 0;
 801	struct cifs_acl *pnndacl;
 802
 803	pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
 804
 805	size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
 806					pownersid, nmode, S_IRWXU);
 807	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 808					pgrpsid, nmode, S_IRWXG);
 809	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 810					 &sid_everyone, nmode, S_IRWXO);
 811
 812	pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
 813	pndacl->num_aces = cpu_to_le32(3);
 814
 815	return 0;
 816}
 817
 818
 819static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 820{
 821	/* BB need to add parm so we can store the SID BB */
 822
 823	/* validate that we do not go past end of ACL - sid must be at least 8
 824	   bytes long (assuming no sub-auths - e.g. the null SID */
 825	if (end_of_acl < (char *)psid + 8) {
 826		cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
 827		return -EINVAL;
 828	}
 829
 
 830#ifdef CONFIG_CIFS_DEBUG2
 831	if (psid->num_subauth) {
 832		int i;
 833		cifs_dbg(FYI, "SID revision %d num_auth %d\n",
 834			 psid->revision, psid->num_subauth);
 835
 836		for (i = 0; i < psid->num_subauth; i++) {
 837			cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
 838				 i, le32_to_cpu(psid->sub_auth[i]));
 839		}
 840
 841		/* BB add length check to make sure that we do not have huge
 842			num auths and therefore go off the end */
 843		cifs_dbg(FYI, "RID 0x%x\n",
 844			 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
 
 845	}
 846#endif
 847
 848	return 0;
 849}
 850
 851
 852/* Convert CIFS ACL to POSIX form */
 853static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 854		struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
 855{
 856	int rc = 0;
 857	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 858	struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
 859	char *end_of_acl = ((char *)pntsd) + acl_len;
 860	__u32 dacloffset;
 861
 862	if (pntsd == NULL)
 863		return -EIO;
 864
 865	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 866				le32_to_cpu(pntsd->osidoffset));
 867	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 868				le32_to_cpu(pntsd->gsidoffset));
 869	dacloffset = le32_to_cpu(pntsd->dacloffset);
 870	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 871	cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
 
 872		 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
 873		 le32_to_cpu(pntsd->gsidoffset),
 874		 le32_to_cpu(pntsd->sacloffset), dacloffset);
 875/*	cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
 876	rc = parse_sid(owner_sid_ptr, end_of_acl);
 877	if (rc) {
 878		cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
 879		return rc;
 880	}
 881	rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
 882	if (rc) {
 883		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
 884			 __func__, rc);
 885		return rc;
 886	}
 887
 888	rc = parse_sid(group_sid_ptr, end_of_acl);
 889	if (rc) {
 890		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
 891			 __func__, rc);
 892		return rc;
 893	}
 894	rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
 895	if (rc) {
 896		cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
 897			 __func__, rc);
 898		return rc;
 899	}
 900
 901	if (dacloffset)
 902		parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
 903			   group_sid_ptr, fattr);
 904	else
 905		cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
 
 
 
 
 
 
 
 906
 907	return rc;
 908}
 909
 
 910/* Convert permission bits from mode to equivalent CIFS ACL */
 911static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
 912	__u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
 913{
 914	int rc = 0;
 915	__u32 dacloffset;
 916	__u32 ndacloffset;
 917	__u32 sidsoffset;
 918	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 919	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 920	struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
 921	struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
 922
 923	if (nmode != NO_CHANGE_64) { /* chmod */
 924		owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 
 
 925				le32_to_cpu(pntsd->osidoffset));
 926		group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 927				le32_to_cpu(pntsd->gsidoffset));
 928		dacloffset = le32_to_cpu(pntsd->dacloffset);
 929		dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 930		ndacloffset = sizeof(struct cifs_ntsd);
 931		ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
 932		ndacl_ptr->revision = dacl_ptr->revision;
 933		ndacl_ptr->size = 0;
 934		ndacl_ptr->num_aces = 0;
 935
 936		rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
 937					nmode);
 938		sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
 939		/* copy sec desc control portion & owner and group sids */
 940		copy_sec_desc(pntsd, pnntsd, sidsoffset);
 941		*aclflag = CIFS_ACL_DACL;
 942	} else {
 943		memcpy(pnntsd, pntsd, secdesclen);
 944		if (uid_valid(uid)) { /* chown */
 945			uid_t id;
 946			owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
 947					le32_to_cpu(pnntsd->osidoffset));
 948			nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
 949								GFP_KERNEL);
 950			if (!nowner_sid_ptr)
 951				return -ENOMEM;
 952			id = from_kuid(&init_user_ns, uid);
 953			rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
 954			if (rc) {
 955				cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
 956					 __func__, rc, id);
 957				kfree(nowner_sid_ptr);
 958				return rc;
 959			}
 960			cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
 961			kfree(nowner_sid_ptr);
 962			*aclflag = CIFS_ACL_OWNER;
 963		}
 964		if (gid_valid(gid)) { /* chgrp */
 965			gid_t id;
 966			group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
 967					le32_to_cpu(pnntsd->gsidoffset));
 968			ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
 969								GFP_KERNEL);
 970			if (!ngroup_sid_ptr)
 971				return -ENOMEM;
 972			id = from_kgid(&init_user_ns, gid);
 973			rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
 974			if (rc) {
 975				cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
 976					 __func__, rc, id);
 977				kfree(ngroup_sid_ptr);
 978				return rc;
 979			}
 980			cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
 981			kfree(ngroup_sid_ptr);
 982			*aclflag = CIFS_ACL_GROUP;
 983		}
 984	}
 985
 986	return rc;
 987}
 988
 989struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 990		const struct cifs_fid *cifsfid, u32 *pacllen)
 991{
 992	struct cifs_ntsd *pntsd = NULL;
 993	unsigned int xid;
 994	int rc;
 995	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 996
 997	if (IS_ERR(tlink))
 998		return ERR_CAST(tlink);
 999
1000	xid = get_xid();
1001	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1002				pacllen);
1003	free_xid(xid);
1004
1005	cifs_put_tlink(tlink);
1006
1007	cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1008	if (rc)
1009		return ERR_PTR(rc);
1010	return pntsd;
1011}
1012
1013static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1014		const char *path, u32 *pacllen)
1015{
1016	struct cifs_ntsd *pntsd = NULL;
1017	int oplock = 0;
1018	unsigned int xid;
1019	int rc, create_options = 0;
1020	struct cifs_tcon *tcon;
1021	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1022	struct cifs_fid fid;
1023	struct cifs_open_parms oparms;
1024
1025	if (IS_ERR(tlink))
1026		return ERR_CAST(tlink);
1027
1028	tcon = tlink_tcon(tlink);
1029	xid = get_xid();
1030
1031	if (backup_cred(cifs_sb))
1032		create_options |= CREATE_OPEN_BACKUP_INTENT;
1033
1034	oparms.tcon = tcon;
1035	oparms.cifs_sb = cifs_sb;
1036	oparms.desired_access = READ_CONTROL;
1037	oparms.create_options = create_options;
1038	oparms.disposition = FILE_OPEN;
1039	oparms.path = path;
1040	oparms.fid = &fid;
1041	oparms.reconnect = false;
1042
1043	rc = CIFS_open(xid, &oparms, &oplock, NULL);
1044	if (!rc) {
1045		rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1046		CIFSSMBClose(xid, tcon, fid.netfid);
1047	}
1048
1049	cifs_put_tlink(tlink);
1050	free_xid(xid);
1051
1052	cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1053	if (rc)
1054		return ERR_PTR(rc);
1055	return pntsd;
1056}
1057
1058/* Retrieve an ACL from the server */
1059struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1060				      struct inode *inode, const char *path,
1061				      u32 *pacllen)
1062{
1063	struct cifs_ntsd *pntsd = NULL;
1064	struct cifsFileInfo *open_file = NULL;
1065
1066	if (inode)
1067		open_file = find_readable_file(CIFS_I(inode), true);
1068	if (!open_file)
1069		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1070
1071	pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
1072	cifsFileInfo_put(open_file);
1073	return pntsd;
1074}
1075
1076 /* Set an ACL on the server */
1077int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1078			struct inode *inode, const char *path, int aclflag)
1079{
1080	int oplock = 0;
1081	unsigned int xid;
1082	int rc, access_flags, create_options = 0;
1083	struct cifs_tcon *tcon;
1084	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1085	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1086	struct cifs_fid fid;
1087	struct cifs_open_parms oparms;
1088
1089	if (IS_ERR(tlink))
1090		return PTR_ERR(tlink);
1091
1092	tcon = tlink_tcon(tlink);
1093	xid = get_xid();
1094
1095	if (backup_cred(cifs_sb))
1096		create_options |= CREATE_OPEN_BACKUP_INTENT;
1097
1098	if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1099		access_flags = WRITE_OWNER;
1100	else
1101		access_flags = WRITE_DAC;
1102
1103	oparms.tcon = tcon;
1104	oparms.cifs_sb = cifs_sb;
1105	oparms.desired_access = access_flags;
1106	oparms.create_options = create_options;
1107	oparms.disposition = FILE_OPEN;
1108	oparms.path = path;
1109	oparms.fid = &fid;
1110	oparms.reconnect = false;
1111
1112	rc = CIFS_open(xid, &oparms, &oplock, NULL);
 
 
1113	if (rc) {
1114		cifs_dbg(VFS, "Unable to open file to set ACL\n");
1115		goto out;
1116	}
1117
1118	rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
1119	cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
1120
1121	CIFSSMBClose(xid, tcon, fid.netfid);
1122out:
1123	free_xid(xid);
1124	cifs_put_tlink(tlink);
1125	return rc;
1126}
1127
 
 
 
 
 
 
 
 
 
 
 
1128/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1129int
1130cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1131		  struct inode *inode, const char *path,
1132		  const struct cifs_fid *pfid)
1133{
1134	struct cifs_ntsd *pntsd = NULL;
1135	u32 acllen = 0;
1136	int rc = 0;
1137	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1138	struct cifs_tcon *tcon;
1139
1140	cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1141
1142	if (IS_ERR(tlink))
1143		return PTR_ERR(tlink);
1144	tcon = tlink_tcon(tlink);
 
1145
1146	if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
1147		pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
1148							  &acllen);
1149	else if (tcon->ses->server->ops->get_acl)
1150		pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1151							&acllen);
1152	else {
1153		cifs_put_tlink(tlink);
1154		return -EOPNOTSUPP;
1155	}
1156	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1157	if (IS_ERR(pntsd)) {
1158		rc = PTR_ERR(pntsd);
1159		cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1160	} else {
1161		rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1162		kfree(pntsd);
1163		if (rc)
1164			cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
1165	}
1166
1167	cifs_put_tlink(tlink);
1168
1169	return rc;
1170}
1171
1172/* Convert mode bits to an ACL so we can update the ACL on the server */
1173int
1174id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1175			kuid_t uid, kgid_t gid)
1176{
1177	int rc = 0;
1178	int aclflag = CIFS_ACL_DACL; /* default flag to set */
1179	__u32 secdesclen = 0;
1180	struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1181	struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1182	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1183	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1184	struct cifs_tcon *tcon;
1185
1186	if (IS_ERR(tlink))
1187		return PTR_ERR(tlink);
1188	tcon = tlink_tcon(tlink);
1189
1190	cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1191
1192	/* Get the security descriptor */
 
1193
1194	if (tcon->ses->server->ops->get_acl == NULL) {
1195		cifs_put_tlink(tlink);
1196		return -EOPNOTSUPP;
1197	}
1198
1199	pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1200						&secdesclen);
1201	if (IS_ERR(pntsd)) {
1202		rc = PTR_ERR(pntsd);
1203		cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1204		cifs_put_tlink(tlink);
1205		return rc;
1206	}
1207
1208	/*
1209	 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1210	 * as chmod disables ACEs and set the security descriptor. Allocate
1211	 * memory for the smb header, set security descriptor request security
1212	 * descriptor parameters, and secuirty descriptor itself
1213	 */
1214	secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1215	pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1216	if (!pnntsd) {
1217		kfree(pntsd);
1218		cifs_put_tlink(tlink);
1219		return -ENOMEM;
1220	}
1221
1222	rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1223				&aclflag);
1224
1225	cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1226
1227	if (tcon->ses->server->ops->set_acl == NULL)
1228		rc = -EOPNOTSUPP;
 
 
 
1229
1230	if (!rc) {
1231		/* Set the security descriptor */
1232		rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
1233						     path, aclflag);
1234		cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1235	}
1236	cifs_put_tlink(tlink);
1237
1238	kfree(pnntsd);
1239	kfree(pntsd);
1240	return rc;
1241}