Blame view

fs/cifs/cifsacl.c 37.2 KB
bcb020341   Steve French   [CIFS] move cifs ...
1
2
3
  /*
   *   fs/cifs/cifsacl.c
   *
8b1327f6e   Steve French   [CIFS] file creat...
4
   *   Copyright (C) International Business Machines  Corp., 2007,2008
bcb020341   Steve French   [CIFS] move cifs ...
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *
   *   Contains the routines for mapping CIFS/NTFS ACLs
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
65874007c   Steve French   [CIFS] fix cut an...
23
  #include <linux/fs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
25
26
27
28
  #include <linux/string.h>
  #include <linux/keyctl.h>
  #include <linux/key-type.h>
  #include <keys/user-type.h>
65874007c   Steve French   [CIFS] fix cut an...
29
30
  #include "cifspdu.h"
  #include "cifsglob.h"
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
31
  #include "cifsacl.h"
65874007c   Steve French   [CIFS] fix cut an...
32
33
  #include "cifsproto.h"
  #include "cifs_debug.h"
65874007c   Steve French   [CIFS] fix cut an...
34

2fbc2f172   Shirish Pargaonkar   cifs: Use mask of...
35
  /* security id for everyone/world system group */
e01b64001   Shirish Pargaonkar   [CIFS] enable get...
36
37
  static const struct cifs_sid sid_everyone = {
  	1, 1, {0, 0, 0, 0, 0, 1}, {0} };
2fbc2f172   Shirish Pargaonkar   cifs: Use mask of...
38
39
  /* security id for Authenticated Users system group */
  static const struct cifs_sid sid_authusers = {
bc09d141e   Fabian Frederick   fs/cifs: remove o...
40
  	1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
41

3514de3fd   Steve French   CIFS: Retrieve ui...
42
43
44
45
46
47
48
49
50
  /* S-1-22-1 Unmapped Unix users */
  static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
  		{cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  
  /* S-1-22-2 Unmapped Unix groups */
  static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
  		{cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  
  /*
cba22b1c5   Alexander A. Klimov   Replace HTTP link...
51
   * See https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
3514de3fd   Steve French   CIFS: Retrieve ui...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
   */
  
  /* S-1-5-88 MS NFS and Apple style UID/GID/mode */
  
  /* S-1-5-88-1 Unix uid */
  static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
  	{cpu_to_le32(88),
  	 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  
  /* S-1-5-88-2 Unix gid */
  static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
  	{cpu_to_le32(88),
  	 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
  
  /* S-1-5-88-3 Unix mode */
  static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
  	{cpu_to_le32(88),
  	 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
b1a6dc21d   Jeff Layton   cifs: remove unee...
70
  static const struct cred *root_cred;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
71

4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
72
  static int
cf7f601c0   David Howells   KEYS: Add payload...
73
  cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
74
75
  {
  	char *payload;
41a9f1f6b   Jeff Layton   cifs: avoid extra...
76
77
78
79
80
81
82
83
  	/*
  	 * If the payload is less than or equal to the size of a pointer, then
  	 * an allocation here is wasteful. Just copy the data directly to the
  	 * payload.value union member instead.
  	 *
  	 * With this however, you must check the datalen before trying to
  	 * dereference payload.data!
  	 */
1f6306806   Jeff Layton   cifs: deal with i...
84
  	if (prep->datalen <= sizeof(key->payload)) {
146aa8b14   David Howells   KEYS: Merge the t...
85
86
87
88
89
90
91
  		key->payload.data[0] = NULL;
  		memcpy(&key->payload, prep->data, prep->datalen);
  	} else {
  		payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
  		if (!payload)
  			return -ENOMEM;
  		key->payload.data[0] = payload;
41a9f1f6b   Jeff Layton   cifs: avoid extra...
92
  	}
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
93

cf7f601c0   David Howells   KEYS: Add payload...
94
  	key->datalen = prep->datalen;
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
95
96
97
98
99
100
  	return 0;
  }
  
  static inline void
  cifs_idmap_key_destroy(struct key *key)
  {
1f6306806   Jeff Layton   cifs: deal with i...
101
  	if (key->datalen > sizeof(key->payload))
146aa8b14   David Howells   KEYS: Merge the t...
102
  		kfree(key->payload.data[0]);
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
103
  }
b1a6dc21d   Jeff Layton   cifs: remove unee...
104
  static struct key_type cifs_idmap_key_type = {
c4aca0c09   Shirish Pargaonkar   cifs: Change key ...
105
  	.name        = "cifs.idmap",
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
106
107
108
  	.instantiate = cifs_idmap_key_instantiate,
  	.destroy     = cifs_idmap_key_destroy,
  	.describe    = user_describe,
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
109
  };
faa65f07d   Jeff Layton   cifs: simplify id...
110
111
  static char *
  sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
112
  {
faa65f07d   Jeff Layton   cifs: simplify id...
113
  	int i, len;
ee13b2ba7   Jeff Layton   cifs: fix the for...
114
  	unsigned int saval;
faa65f07d   Jeff Layton   cifs: simplify id...
115
  	char *sidstr, *strptr;
193cdd8a2   Jeff Layton   cifs: fix SID bin...
116
  	unsigned long long id_auth_val;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
117

faa65f07d   Jeff Layton   cifs: simplify id...
118
119
120
121
122
123
  	/* 3 bytes for prefix */
  	sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
  			 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
  			 GFP_KERNEL);
  	if (!sidstr)
  		return sidstr;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
124

faa65f07d   Jeff Layton   cifs: simplify id...
125
126
127
128
  	strptr = sidstr;
  	len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
  			sidptr->revision);
  	strptr += len;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
129

193cdd8a2   Jeff Layton   cifs: fix SID bin...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  	/* The authority field is a single 48-bit number */
  	id_auth_val = (unsigned long long)sidptr->authority[5];
  	id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
  	id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
  	id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
  	id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
  	id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
  
  	/*
  	 * MS-DTYP states that if the authority is >= 2^32, then it should be
  	 * expressed as a hex value.
  	 */
  	if (id_auth_val <= UINT_MAX)
  		len = sprintf(strptr, "-%llu", id_auth_val);
  	else
  		len = sprintf(strptr, "-0x%llx", id_auth_val);
  
  	strptr += len;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
148
149
150
  
  	for (i = 0; i < sidptr->num_subauth; ++i) {
  		saval = le32_to_cpu(sidptr->sub_auth[i]);
faa65f07d   Jeff Layton   cifs: simplify id...
151
152
  		len = sprintf(strptr, "-%u", saval);
  		strptr += len;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
153
  	}
faa65f07d   Jeff Layton   cifs: simplify id...
154
155
  
  	return sidstr;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
156
  }
436bb435f   Jeff Layton   cifs: make compar...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  /*
   * if the two SIDs (roughly equivalent to a UUID for a user or group) are
   * the same returns zero, if they do not match returns non-zero.
   */
  static int
  compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
  {
  	int i;
  	int num_subauth, num_sat, num_saw;
  
  	if ((!ctsid) || (!cwsid))
  		return 1;
  
  	/* compare the revision */
  	if (ctsid->revision != cwsid->revision) {
  		if (ctsid->revision > cwsid->revision)
  			return 1;
  		else
  			return -1;
  	}
  
  	/* compare all of the six auth values */
  	for (i = 0; i < NUM_AUTHS; ++i) {
  		if (ctsid->authority[i] != cwsid->authority[i]) {
  			if (ctsid->authority[i] > cwsid->authority[i])
  				return 1;
  			else
  				return -1;
  		}
  	}
  
  	/* compare all of the subauth values if any */
  	num_sat = ctsid->num_subauth;
  	num_saw = cwsid->num_subauth;
  	num_subauth = num_sat < num_saw ? num_sat : num_saw;
  	if (num_subauth) {
  		for (i = 0; i < num_subauth; ++i) {
  			if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
  				if (le32_to_cpu(ctsid->sub_auth[i]) >
  					le32_to_cpu(cwsid->sub_auth[i]))
  					return 1;
  				else
  					return -1;
  			}
  		}
  	}
  
  	return 0; /* sids compare/match */
  }
3514de3fd   Steve French   CIFS: Retrieve ui...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  static bool
  is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
  {
  	int i;
  	int num_subauth;
  	const struct cifs_sid *pwell_known_sid;
  
  	if (!psid || (puid == NULL))
  		return false;
  
  	num_subauth = psid->num_subauth;
  
  	/* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
  	if (num_subauth == 2) {
  		if (is_group)
  			pwell_known_sid = &sid_unix_groups;
  		else
  			pwell_known_sid = &sid_unix_users;
  	} else if (num_subauth == 3) {
  		if (is_group)
  			pwell_known_sid = &sid_unix_NFS_groups;
  		else
  			pwell_known_sid = &sid_unix_NFS_users;
  	} else
  		return false;
  
  	/* compare the revision */
  	if (psid->revision != pwell_known_sid->revision)
  		return false;
  
  	/* compare all of the six auth values */
  	for (i = 0; i < NUM_AUTHS; ++i) {
  		if (psid->authority[i] != pwell_known_sid->authority[i]) {
  			cifs_dbg(FYI, "auth %d did not match
  ", i);
  			return false;
  		}
  	}
  
  	if (num_subauth == 2) {
  		if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
  			return false;
  
  		*puid = le32_to_cpu(psid->sub_auth[1]);
  	} else /* 3 subauths, ie Windows/Mac style */ {
  		*puid = le32_to_cpu(psid->sub_auth[0]);
  		if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
  		    (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
  			return false;
  
  		*puid = le32_to_cpu(psid->sub_auth[2]);
  	}
  
  	cifs_dbg(FYI, "Unix UID %d returned from SID
  ", *puid);
  	return true; /* well known sid found, uid returned */
  }
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
263
  static void
36960e440   Jeff Layton   cifs: fix potenti...
264
265
  cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
  {
36f87ee70   Jeff Layton   cifs: make cifs_c...
266
267
268
  	int i;
  
  	dst->revision = src->revision;
30c9d6cca   Jeff Layton   cifs: redefine NU...
269
  	dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
36f87ee70   Jeff Layton   cifs: make cifs_c...
270
271
272
273
  	for (i = 0; i < NUM_AUTHS; ++i)
  		dst->authority[i] = src->authority[i];
  	for (i = 0; i < dst->num_subauth; ++i)
  		dst->sub_auth[i] = src->sub_auth[i];
36960e440   Jeff Layton   cifs: fix potenti...
274
  }
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
275
  static int
faa65f07d   Jeff Layton   cifs: simplify id...
276
  id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
277
  {
faa65f07d   Jeff Layton   cifs: simplify id...
278
  	int rc;
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
279
  	struct key *sidkey;
2ae03025d   Jeff Layton   cifs: extra sanit...
280
281
  	struct cifs_sid *ksid;
  	unsigned int ksid_size;
faa65f07d   Jeff Layton   cifs: simplify id...
282
  	char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
283
  	const struct cred *saved_cred;
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
284

faa65f07d   Jeff Layton   cifs: simplify id...
285
286
287
288
  	rc = snprintf(desc, sizeof(desc), "%ci:%u",
  			sidtype == SIDOWNER ? 'o' : 'g', cid);
  	if (rc >= sizeof(desc))
  		return -EINVAL;
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
289

faa65f07d   Jeff Layton   cifs: simplify id...
290
291
  	rc = 0;
  	saved_cred = override_creds(root_cred);
028db3e29   Linus Torvalds   Revert "Merge tag...
292
  	sidkey = request_key(&cifs_idmap_key_type, desc, "");
faa65f07d   Jeff Layton   cifs: simplify id...
293
  	if (IS_ERR(sidkey)) {
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
294
  		rc = -EINVAL;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
295
296
297
  		cifs_dbg(FYI, "%s: Can't map %cid %u to a SID
  ",
  			 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
faa65f07d   Jeff Layton   cifs: simplify id...
298
299
300
  		goto out_revert_creds;
  	} else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
  		rc = -EIO;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
301
302
303
  		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)
  ",
  			 __func__, sidkey->datalen);
2ae03025d   Jeff Layton   cifs: extra sanit...
304
  		goto invalidate_key;
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
305
  	}
2ae03025d   Jeff Layton   cifs: extra sanit...
306

1f6306806   Jeff Layton   cifs: deal with i...
307
308
309
310
311
312
  	/*
  	 * A sid is usually too large to be embedded in payload.value, but if
  	 * there are no subauthorities and the host has 8-byte pointers, then
  	 * it could be.
  	 */
  	ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
146aa8b14   David Howells   KEYS: Merge the t...
313
314
  		(struct cifs_sid *)&sidkey->payload :
  		(struct cifs_sid *)sidkey->payload.data[0];
1f6306806   Jeff Layton   cifs: deal with i...
315

2ae03025d   Jeff Layton   cifs: extra sanit...
316
317
318
  	ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
  	if (ksid_size > sidkey->datalen) {
  		rc = -EIO;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
319
320
321
  		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)
  ",
  			 __func__, sidkey->datalen, ksid_size);
2ae03025d   Jeff Layton   cifs: extra sanit...
322
323
  		goto invalidate_key;
  	}
1f6306806   Jeff Layton   cifs: deal with i...
324

2ae03025d   Jeff Layton   cifs: extra sanit...
325
  	cifs_copy_sid(ssid, ksid);
faa65f07d   Jeff Layton   cifs: simplify id...
326
327
328
329
  out_key_put:
  	key_put(sidkey);
  out_revert_creds:
  	revert_creds(saved_cred);
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
330
  	return rc;
2ae03025d   Jeff Layton   cifs: extra sanit...
331
332
333
334
  
  invalidate_key:
  	key_invalidate(sidkey);
  	goto out_key_put;
21fed0d5b   Shirish Pargaonkar   cifs: Add data st...
335
  }
9934430e2   Steve French   SMB3.1.1: Fix ids...
336
  int
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
337
338
339
  sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
  		struct cifs_fattr *fattr, uint sidtype)
  {
f2d67931f   Qiujun Huang   fs/cifs: fix gcc ...
340
  	int rc = 0;
faa65f07d   Jeff Layton   cifs: simplify id...
341
342
  	struct key *sidkey;
  	char *sidstr;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
343
  	const struct cred *saved_cred;
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
344
345
  	kuid_t fuid = cifs_sb->mnt_uid;
  	kgid_t fgid = cifs_sb->mnt_gid;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
346
347
  
  	/*
faa65f07d   Jeff Layton   cifs: simplify id...
348
349
  	 * If we have too many subauthorities, then something is really wrong.
  	 * Just return an error.
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
350
  	 */
faa65f07d   Jeff Layton   cifs: simplify id...
351
  	if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
352
353
354
  		cifs_dbg(FYI, "%s: %u subauthorities is too many!
  ",
  			 __func__, psid->num_subauth);
faa65f07d   Jeff Layton   cifs: simplify id...
355
  		return -EIO;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
356
  	}
9934430e2   Steve French   SMB3.1.1: Fix ids...
357
358
  	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
  	    (cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
3514de3fd   Steve French   CIFS: Retrieve ui...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  		uint32_t unix_id;
  		bool is_group;
  
  		if (sidtype != SIDOWNER)
  			is_group = true;
  		else
  			is_group = false;
  
  		if (is_well_known_sid(psid, &unix_id, is_group) == false)
  			goto try_upcall_to_get_id;
  
  		if (is_group) {
  			kgid_t gid;
  			gid_t id;
  
  			id = (gid_t)unix_id;
  			gid = make_kgid(&init_user_ns, id);
  			if (gid_valid(gid)) {
  				fgid = gid;
  				goto got_valid_id;
  			}
  		} else {
  			kuid_t uid;
  			uid_t id;
  
  			id = (uid_t)unix_id;
  			uid = make_kuid(&init_user_ns, id);
  			if (uid_valid(uid)) {
  				fuid = uid;
  				goto got_valid_id;
  			}
  		}
  		/* If unable to find uid/gid easily from SID try via upcall */
  	}
  
  try_upcall_to_get_id:
faa65f07d   Jeff Layton   cifs: simplify id...
395
396
397
398
399
  	sidstr = sid_to_key_str(psid, sidtype);
  	if (!sidstr)
  		return -ENOMEM;
  
  	saved_cred = override_creds(root_cred);
028db3e29   Linus Torvalds   Revert "Merge tag...
400
  	sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
faa65f07d   Jeff Layton   cifs: simplify id...
401
402
  	if (IS_ERR(sidkey)) {
  		rc = -EINVAL;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
403
404
405
  		cifs_dbg(FYI, "%s: Can't map SID %s to a %cid
  ",
  			 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
faa65f07d   Jeff Layton   cifs: simplify id...
406
407
408
409
410
411
412
413
  		goto out_revert_creds;
  	}
  
  	/*
  	 * FIXME: Here we assume that uid_t and gid_t are same size. It's
  	 * probably a safe assumption but might be better to check based on
  	 * sidtype.
  	 */
355958f28   Eric W. Biederman   cifs: Use BUILD_B...
414
  	BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
41a9f1f6b   Jeff Layton   cifs: avoid extra...
415
  	if (sidkey->datalen != sizeof(uid_t)) {
faa65f07d   Jeff Layton   cifs: simplify id...
416
  		rc = -EIO;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
417
418
419
  		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)
  ",
  			 __func__, sidkey->datalen);
2ae03025d   Jeff Layton   cifs: extra sanit...
420
  		key_invalidate(sidkey);
faa65f07d   Jeff Layton   cifs: simplify id...
421
  		goto out_key_put;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
422
  	}
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
423
424
425
  	if (sidtype == SIDOWNER) {
  		kuid_t uid;
  		uid_t id;
146aa8b14   David Howells   KEYS: Merge the t...
426
  		memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
427
428
429
430
431
432
  		uid = make_kuid(&init_user_ns, id);
  		if (uid_valid(uid))
  			fuid = uid;
  	} else {
  		kgid_t gid;
  		gid_t id;
146aa8b14   David Howells   KEYS: Merge the t...
433
  		memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
434
435
436
437
  		gid = make_kgid(&init_user_ns, id);
  		if (gid_valid(gid))
  			fgid = gid;
  	}
faa65f07d   Jeff Layton   cifs: simplify id...
438
439
440
441
442
443
  
  out_key_put:
  	key_put(sidkey);
  out_revert_creds:
  	revert_creds(saved_cred);
  	kfree(sidstr);
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
444

faa65f07d   Jeff Layton   cifs: simplify id...
445
446
447
448
  	/*
  	 * Note that we return 0 here unconditionally. If the mapping
  	 * fails then we just fall back to using the mnt_uid/mnt_gid.
  	 */
3514de3fd   Steve French   CIFS: Retrieve ui...
449
  got_valid_id:
f2d67931f   Qiujun Huang   fs/cifs: fix gcc ...
450
  	rc = 0;
faa65f07d   Jeff Layton   cifs: simplify id...
451
452
453
454
  	if (sidtype == SIDOWNER)
  		fattr->cf_uid = fuid;
  	else
  		fattr->cf_gid = fgid;
f2d67931f   Qiujun Huang   fs/cifs: fix gcc ...
455
  	return rc;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
456
  }
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
457
458
459
460
461
462
  int
  init_cifs_idmap(void)
  {
  	struct cred *cred;
  	struct key *keyring;
  	int ret;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
463
464
465
  	cifs_dbg(FYI, "Registering the %s key type
  ",
  		 cifs_idmap_key_type.name);
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
466
467
468
469
470
471
472
473
474
475
  
  	/* create an override credential set with a special thread keyring in
  	 * which requests are cached
  	 *
  	 * this is used to prevent malicious redirections from being installed
  	 * with add_key().
  	 */
  	cred = prepare_kernel_cred(NULL);
  	if (!cred)
  		return -ENOMEM;
8e3028b90   Eric W. Biederman   cifs: Pass GLOBAL...
476
477
  	keyring = keyring_alloc(".cifs_idmap",
  				GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
028db3e29   Linus Torvalds   Revert "Merge tag...
478
479
  				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
  				KEY_USR_VIEW | KEY_USR_READ,
5ac7eace2   David Howells   KEYS: Add a facil...
480
  				KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
481
482
483
484
  	if (IS_ERR(keyring)) {
  		ret = PTR_ERR(keyring);
  		goto failed_put_cred;
  	}
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
485
486
487
488
489
490
  	ret = register_key_type(&cifs_idmap_key_type);
  	if (ret < 0)
  		goto failed_put_key;
  
  	/* instruct request_key() to use this special keyring as a cache for
  	 * the results it looks up */
700920eb5   David Howells   KEYS: Allow speci...
491
  	set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
492
493
494
  	cred->thread_keyring = keyring;
  	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
  	root_cred = cred;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
495
496
  	cifs_dbg(FYI, "cifs idmap keyring: %d
  ", key_serial(keyring));
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  	return 0;
  
  failed_put_key:
  	key_put(keyring);
  failed_put_cred:
  	put_cred(cred);
  	return ret;
  }
  
  void
  exit_cifs_idmap(void)
  {
  	key_revoke(root_cred->thread_keyring);
  	unregister_key_type(&cifs_idmap_key_type);
  	put_cred(root_cred);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
512
513
  	cifs_dbg(FYI, "Unregistered %s key type
  ", cifs_idmap_key_type.name);
4d79dba0e   Shirish Pargaonkar   cifs: Add idmap k...
514
  }
97837582b   Steve French   [CIFS] Allow sett...
515
516
517
518
  /* copy ntsd, owner sid, and group sid from a security descriptor to another */
  static void copy_sec_desc(const struct cifs_ntsd *pntsd,
  				struct cifs_ntsd *pnntsd, __u32 sidsoffset)
  {
97837582b   Steve French   [CIFS] Allow sett...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
  	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
  
  	/* copy security descriptor control portion */
  	pnntsd->revision = pntsd->revision;
  	pnntsd->type = pntsd->type;
  	pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
  	pnntsd->sacloffset = 0;
  	pnntsd->osidoffset = cpu_to_le32(sidsoffset);
  	pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
  
  	/* copy owner sid */
  	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
  				le32_to_cpu(pntsd->osidoffset));
  	nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
36960e440   Jeff Layton   cifs: fix potenti...
534
  	cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
97837582b   Steve French   [CIFS] Allow sett...
535
536
537
538
539
540
  
  	/* copy group sid */
  	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
  				le32_to_cpu(pntsd->gsidoffset));
  	ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
  					sizeof(struct cifs_sid));
36960e440   Jeff Layton   cifs: fix potenti...
541
  	cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
97837582b   Steve French   [CIFS] Allow sett...
542
543
544
  
  	return;
  }
630f3f0c4   Steve French   [CIFS] acl suppor...
545
546
547
548
549
  /*
     change posix mode to reflect permissions
     pmode is the existing mode (we only want to overwrite part of this
     bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
  */
9b5e6857b   Al Viro   regression: cifs ...
550
  static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
15b039591   Steve French   [CIFS] Fix incorr...
551
  				 umode_t *pbits_to_set)
630f3f0c4   Steve French   [CIFS] acl suppor...
552
  {
9b5e6857b   Al Viro   regression: cifs ...
553
  	__u32 flags = le32_to_cpu(ace_flags);
15b039591   Steve French   [CIFS] Fix incorr...
554
  	/* the order of ACEs is important.  The canonical order is to begin with
ce06c9f02   Steve French   [CIFS] add mode t...
555
  	   DENY entries followed by ALLOW, otherwise an allow entry could be
15b039591   Steve French   [CIFS] Fix incorr...
556
  	   encountered first, making the subsequent deny entry like "dead code"
ce06c9f02   Steve French   [CIFS] add mode t...
557
  	   which would be superflous since Windows stops when a match is made
15b039591   Steve French   [CIFS] Fix incorr...
558
559
560
561
562
  	   for the operation you are trying to perform for your user */
  
  	/* For deny ACEs we change the mask so that subsequent allow access
  	   control entries do not turn on the bits we are denying */
  	if (type == ACCESS_DENIED) {
ad7a2926b   Steve French   [CIFS] reduce che...
563
  		if (flags & GENERIC_ALL)
15b039591   Steve French   [CIFS] Fix incorr...
564
  			*pbits_to_set &= ~S_IRWXUGO;
ad7a2926b   Steve French   [CIFS] reduce che...
565

9b5e6857b   Al Viro   regression: cifs ...
566
567
  		if ((flags & GENERIC_WRITE) ||
  			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b039591   Steve French   [CIFS] Fix incorr...
568
  			*pbits_to_set &= ~S_IWUGO;
9b5e6857b   Al Viro   regression: cifs ...
569
570
  		if ((flags & GENERIC_READ) ||
  			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b039591   Steve French   [CIFS] Fix incorr...
571
  			*pbits_to_set &= ~S_IRUGO;
9b5e6857b   Al Viro   regression: cifs ...
572
573
  		if ((flags & GENERIC_EXECUTE) ||
  			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b039591   Steve French   [CIFS] Fix incorr...
574
575
576
  			*pbits_to_set &= ~S_IXUGO;
  		return;
  	} else if (type != ACCESS_ALLOWED) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
577
578
  		cifs_dbg(VFS, "unknown access control type %d
  ", type);
15b039591   Steve French   [CIFS] Fix incorr...
579
580
581
  		return;
  	}
  	/* else ACCESS_ALLOWED type */
630f3f0c4   Steve French   [CIFS] acl suppor...
582

9b5e6857b   Al Viro   regression: cifs ...
583
  	if (flags & GENERIC_ALL) {
15b039591   Steve French   [CIFS] Fix incorr...
584
  		*pmode |= (S_IRWXUGO & (*pbits_to_set));
f96637be0   Joe Perches   [CIFS] cifs: Rena...
585
586
  		cifs_dbg(NOISY, "all perms
  ");
d61e5808d   Steve French   [CIFS] acl suppor...
587
588
  		return;
  	}
9b5e6857b   Al Viro   regression: cifs ...
589
590
  	if ((flags & GENERIC_WRITE) ||
  			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b039591   Steve French   [CIFS] Fix incorr...
591
  		*pmode |= (S_IWUGO & (*pbits_to_set));
9b5e6857b   Al Viro   regression: cifs ...
592
593
  	if ((flags & GENERIC_READ) ||
  			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b039591   Steve French   [CIFS] Fix incorr...
594
  		*pmode |= (S_IRUGO & (*pbits_to_set));
9b5e6857b   Al Viro   regression: cifs ...
595
596
  	if ((flags & GENERIC_EXECUTE) ||
  			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b039591   Steve French   [CIFS] Fix incorr...
597
  		*pmode |= (S_IXUGO & (*pbits_to_set));
630f3f0c4   Steve French   [CIFS] acl suppor...
598

f52aa79df   Frank Sorenson   cifs: Fix mode ou...
599
600
  	cifs_dbg(NOISY, "access flags 0x%x mode now %04o
  ", flags, *pmode);
630f3f0c4   Steve French   [CIFS] acl suppor...
601
602
  	return;
  }
ce06c9f02   Steve French   [CIFS] add mode t...
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  /*
     Generate access flags to reflect permissions mode is the existing mode.
     This function is called for every ACE in the DACL whose SID matches
     with either owner or group or everyone.
  */
  
  static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
  				__u32 *pace_flags)
  {
  	/* reset access mask */
  	*pace_flags = 0x0;
  
  	/* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
  	mode &= bits_to_use;
  
  	/* check for R/W/X UGO since we do not know whose flags
  	   is this but we have cleared all the bits sans RWX for
  	   either user or group or other as per bits_to_use */
  	if (mode & S_IRUGO)
  		*pace_flags |= SET_FILE_READ_RIGHTS;
  	if (mode & S_IWUGO)
  		*pace_flags |= SET_FILE_WRITE_RIGHTS;
  	if (mode & S_IXUGO)
  		*pace_flags |= SET_FILE_EXEC_RIGHTS;
f52aa79df   Frank Sorenson   cifs: Fix mode ou...
627
628
  	cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x
  ",
f96637be0   Joe Perches   [CIFS] cifs: Rena...
629
  		 mode, *pace_flags);
ce06c9f02   Steve French   [CIFS] add mode t...
630
631
  	return;
  }
2b210adcb   Al Viro   cifs: fix misanno...
632
  static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
97837582b   Steve French   [CIFS] Allow sett...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
  			const struct cifs_sid *psid, __u64 nmode, umode_t bits)
  {
  	int i;
  	__u16 size = 0;
  	__u32 access_req = 0;
  
  	pntace->type = ACCESS_ALLOWED;
  	pntace->flags = 0x0;
  	mode_to_access_flags(nmode, bits, &access_req);
  	if (!access_req)
  		access_req = SET_MINIMUM_RIGHTS;
  	pntace->access_req = cpu_to_le32(access_req);
  
  	pntace->sid.revision = psid->revision;
  	pntace->sid.num_subauth = psid->num_subauth;
852e22950   Jeff Layton   cifs: use the NUM...
648
  	for (i = 0; i < NUM_AUTHS; i++)
97837582b   Steve French   [CIFS] Allow sett...
649
650
651
652
653
654
  		pntace->sid.authority[i] = psid->authority[i];
  	for (i = 0; i < psid->num_subauth; i++)
  		pntace->sid.sub_auth[i] = psid->sub_auth[i];
  
  	size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
  	pntace->size = cpu_to_le16(size);
ef571cadd   Shirish Pargaonkar   [CIFS] Fix warnin...
655
  	return size;
97837582b   Steve French   [CIFS] Allow sett...
656
  }
297647c21   Steve French   [CIFS] CIFS ACL s...
657

953f86813   Steve French   [CIFS] Don't requ...
658
659
  #ifdef CONFIG_CIFS_DEBUG2
  static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
660
  {
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
661
  	int num_subauth;
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
662
663
  
  	/* validate that we do not go past end of acl */
297647c21   Steve French   [CIFS] CIFS ACL s...
664

44093ca2f   Steve French   [CIFS] acl suppor...
665
  	if (le16_to_cpu(pace->size) < 16) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
666
667
  		cifs_dbg(VFS, "ACE too small %d
  ", le16_to_cpu(pace->size));
44093ca2f   Steve French   [CIFS] acl suppor...
668
669
670
671
  		return;
  	}
  
  	if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
672
673
  		cifs_dbg(VFS, "ACL too small to parse ACE
  ");
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
674
  		return;
44093ca2f   Steve French   [CIFS] acl suppor...
675
  	}
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
676

44093ca2f   Steve French   [CIFS] acl suppor...
677
  	num_subauth = pace->sid.num_subauth;
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
678
  	if (num_subauth) {
8f18c1316   Steve French   [CIFS] remove com...
679
  		int i;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
680
681
682
683
  		cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d
  ",
  			 pace->sid.revision, pace->sid.num_subauth, pace->type,
  			 pace->flags, le16_to_cpu(pace->size));
d12fd121a   Steve French   [CIFS] Cleanup fo...
684
  		for (i = 0; i < num_subauth; ++i) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
685
686
687
  			cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x
  ",
  				 i, le32_to_cpu(pace->sid.sub_auth[i]));
d12fd121a   Steve French   [CIFS] Cleanup fo...
688
689
690
691
  		}
  
  		/* BB add length check to make sure that we do not have huge
  			num auths and therefore go off the end */
d12fd121a   Steve French   [CIFS] Cleanup fo...
692
693
694
695
  	}
  
  	return;
  }
953f86813   Steve French   [CIFS] Don't requ...
696
  #endif
d12fd121a   Steve French   [CIFS] Cleanup fo...
697

a750e77c2   Steve French   [CIFS] acl suppor...
698
  static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
d61e5808d   Steve French   [CIFS] acl suppor...
699
  		       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
e2f8fbfb8   Steve French   cifs: get mode bi...
700
  		       struct cifs_fattr *fattr, bool mode_from_special_sid)
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
701
702
703
704
705
  {
  	int i;
  	int num_aces = 0;
  	int acl_size;
  	char *acl_base;
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
706
707
708
  	struct cifs_ace **ppace;
  
  	/* BB need to add parm so we can store the SID BB */
2b83457bd   Steve French   [CIFS] Fix check ...
709
710
711
  	if (!pdacl) {
  		/* no DACL in the security descriptor, set
  		   all the permissions for user/group/other */
0b8f18e35   Jeff Layton   cifs: convert cif...
712
  		fattr->cf_mode |= S_IRWXUGO;
2b83457bd   Steve French   [CIFS] Fix check ...
713
714
  		return;
  	}
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
715
  	/* validate that we do not go past end of acl */
af6f4612f   Steve French   [CIFS] Fix some e...
716
  	if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
717
718
  		cifs_dbg(VFS, "ACL too small to parse DACL
  ");
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
719
720
  		return;
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
721
722
723
724
  	cifs_dbg(NOISY, "DACL revision %d size %d num aces %d
  ",
  		 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
  		 le32_to_cpu(pdacl->num_aces));
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
725

7505e0525   Steve French   [CIFS] If no Acce...
726
727
728
  	/* reset rwx permissions for user/group/other.
  	   Also, if num_aces is 0 i.e. DACL has no ACEs,
  	   user/group/other have no permissions */
0b8f18e35   Jeff Layton   cifs: convert cif...
729
  	fattr->cf_mode &= ~(S_IRWXUGO);
7505e0525   Steve French   [CIFS] If no Acce...
730

d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
731
732
  	acl_base = (char *)pdacl;
  	acl_size = sizeof(struct cifs_acl);
adbc03587   Steve French   [CIFS] endian fixes
733
  	num_aces = le32_to_cpu(pdacl->num_aces);
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
734
  	if (num_aces > 0) {
15b039591   Steve French   [CIFS] Fix incorr...
735
736
  		umode_t user_mask = S_IRWXU;
  		umode_t group_mask = S_IRWXG;
2fbc2f172   Shirish Pargaonkar   cifs: Use mask of...
737
  		umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
15b039591   Steve French   [CIFS] Fix incorr...
738

7250170c9   Dan Carpenter   cifs: integer ove...
739
740
  		if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
  			return;
6da2ec560   Kees Cook   treewide: kmalloc...
741
742
  		ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
  				      GFP_KERNEL);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
743
  		if (!ppace)
8132b65bc   Stanislav Fomichev   cifs: add check f...
744
  			return;
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
745

d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
746
  		for (i = 0; i < num_aces; ++i) {
44093ca2f   Steve French   [CIFS] acl suppor...
747
  			ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
953f86813   Steve French   [CIFS] Don't requ...
748
749
750
  #ifdef CONFIG_CIFS_DEBUG2
  			dump_ace(ppace[i], end_of_acl);
  #endif
e2f8fbfb8   Steve French   cifs: get mode bi...
751
752
753
754
755
756
757
758
759
760
761
762
763
  			if (mode_from_special_sid &&
  			    (compare_sids(&(ppace[i]->sid),
  					  &sid_unix_NFS_mode) == 0)) {
  				/*
  				 * Full permissions are:
  				 * 07777 = S_ISUID | S_ISGID | S_ISVTX |
  				 *         S_IRWXU | S_IRWXG | S_IRWXO
  				 */
  				fattr->cf_mode &= ~07777;
  				fattr->cf_mode |=
  					le32_to_cpu(ppace[i]->sid.sub_auth[2]);
  				break;
  			} else if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
e01b64001   Shirish Pargaonkar   [CIFS] enable get...
764
  				access_flags_to_mode(ppace[i]->access_req,
15b039591   Steve French   [CIFS] Fix incorr...
765
  						     ppace[i]->type,
0b8f18e35   Jeff Layton   cifs: convert cif...
766
  						     &fattr->cf_mode,
15b039591   Steve French   [CIFS] Fix incorr...
767
  						     &user_mask);
e2f8fbfb8   Steve French   cifs: get mode bi...
768
  			else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
e01b64001   Shirish Pargaonkar   [CIFS] enable get...
769
  				access_flags_to_mode(ppace[i]->access_req,
15b039591   Steve French   [CIFS] Fix incorr...
770
  						     ppace[i]->type,
0b8f18e35   Jeff Layton   cifs: convert cif...
771
  						     &fattr->cf_mode,
15b039591   Steve French   [CIFS] Fix incorr...
772
  						     &group_mask);
e2f8fbfb8   Steve French   cifs: get mode bi...
773
  			else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
e01b64001   Shirish Pargaonkar   [CIFS] enable get...
774
  				access_flags_to_mode(ppace[i]->access_req,
15b039591   Steve French   [CIFS] Fix incorr...
775
  						     ppace[i]->type,
0b8f18e35   Jeff Layton   cifs: convert cif...
776
  						     &fattr->cf_mode,
15b039591   Steve French   [CIFS] Fix incorr...
777
  						     &other_mask);
e2f8fbfb8   Steve French   cifs: get mode bi...
778
  			else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
2fbc2f172   Shirish Pargaonkar   cifs: Use mask of...
779
780
781
782
  				access_flags_to_mode(ppace[i]->access_req,
  						     ppace[i]->type,
  						     &fattr->cf_mode,
  						     &other_mask);
e01b64001   Shirish Pargaonkar   [CIFS] enable get...
783

44093ca2f   Steve French   [CIFS] acl suppor...
784
  /*			memcpy((void *)(&(cifscred->aces[i])),
d12fd121a   Steve French   [CIFS] Cleanup fo...
785
786
  				(void *)ppace[i],
  				sizeof(struct cifs_ace)); */
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
787

44093ca2f   Steve French   [CIFS] acl suppor...
788
789
  			acl_base = (char *)ppace[i];
  			acl_size = le16_to_cpu(ppace[i]->size);
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
790
791
792
  		}
  
  		kfree(ppace);
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
793
794
795
796
  	}
  
  	return;
  }
643fbceef   Steve French   smb3: fix default...
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
  {
  	int i;
  	unsigned int ace_size = 20;
  
  	pntace->type = ACCESS_ALLOWED_ACE_TYPE;
  	pntace->flags = 0x0;
  	pntace->access_req = cpu_to_le32(GENERIC_ALL);
  	pntace->sid.num_subauth = 1;
  	pntace->sid.revision = 1;
  	for (i = 0; i < NUM_AUTHS; i++)
  		pntace->sid.authority[i] =  sid_authusers.authority[i];
  
  	pntace->sid.sub_auth[0] =  sid_authusers.sub_auth[0];
  
  	/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
  	pntace->size = cpu_to_le16(ace_size);
  	return ace_size;
  }
fdef665ba   Steve French   smb3: fix mode pa...
816
817
  /*
   * Fill in the special SID based on the mode. See
cba22b1c5   Alexander A. Klimov   Replace HTTP link...
818
   * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
fdef665ba   Steve French   smb3: fix mode pa...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
   */
  unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
  {
  	int i;
  	unsigned int ace_size = 28;
  
  	pntace->type = ACCESS_DENIED_ACE_TYPE;
  	pntace->flags = 0x0;
  	pntace->access_req = 0;
  	pntace->sid.num_subauth = 3;
  	pntace->sid.revision = 1;
  	for (i = 0; i < NUM_AUTHS; i++)
  		pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
  
  	pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
  	pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
  	pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
  
  	/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
  	pntace->size = cpu_to_le16(ace_size);
  	return ace_size;
  }
bcb020341   Steve French   [CIFS] move cifs ...
841

975221eca   Steve French   smb3: allow uid a...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
  unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
  {
  	int i;
  	unsigned int ace_size = 28;
  
  	pntace->type = ACCESS_ALLOWED_ACE_TYPE;
  	pntace->flags = 0x0;
  	pntace->access_req = cpu_to_le32(GENERIC_ALL);
  	pntace->sid.num_subauth = 3;
  	pntace->sid.revision = 1;
  	for (i = 0; i < NUM_AUTHS; i++)
  		pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
  
  	pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
  	pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
  	pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
  
  	/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
  	pntace->size = cpu_to_le16(ace_size);
  	return ace_size;
  }
97837582b   Steve French   [CIFS] Allow sett...
863
  static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
22442179a   Steve French   cifs: allow chmod...
864
  			struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
97837582b   Steve French   [CIFS] Allow sett...
865
  {
2b210adcb   Al Viro   cifs: fix misanno...
866
  	u16 size = 0;
e37a02c7e   Aurelien Aptel   cifs: modefromsid...
867
  	u32 num_aces = 0;
97837582b   Steve French   [CIFS] Allow sett...
868
869
870
  	struct cifs_acl *pnndacl;
  
  	pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
22442179a   Steve French   cifs: allow chmod...
871
872
873
  	if (modefromsid) {
  		struct cifs_ace *pntace =
  			(struct cifs_ace *)((char *)pnndacl + size);
22442179a   Steve French   cifs: allow chmod...
874

fdef665ba   Steve French   smb3: fix mode pa...
875
  		size += setup_special_mode_ACE(pntace, nmode);
e37a02c7e   Aurelien Aptel   cifs: modefromsid...
876
877
878
879
880
881
882
883
884
885
886
887
  		num_aces++;
  	}
  
  	size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
  					pownersid, nmode, S_IRWXU);
  	num_aces++;
  	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
  					pgrpsid, nmode, S_IRWXG);
  	num_aces++;
  	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
  					 &sid_everyone, nmode, S_IRWXO);
  	num_aces++;
22442179a   Steve French   cifs: allow chmod...
888

e37a02c7e   Aurelien Aptel   cifs: modefromsid...
889
  	pndacl->num_aces = cpu_to_le32(num_aces);
97837582b   Steve French   [CIFS] Allow sett...
890
  	pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
97837582b   Steve French   [CIFS] Allow sett...
891

ef571cadd   Shirish Pargaonkar   [CIFS] Fix warnin...
892
  	return 0;
97837582b   Steve French   [CIFS] Allow sett...
893
  }
bcb020341   Steve French   [CIFS] move cifs ...
894
895
896
  static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
  {
  	/* BB need to add parm so we can store the SID BB */
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
897
898
899
  	/* validate that we do not go past end of ACL - sid must be at least 8
  	   bytes long (assuming no sub-auths - e.g. the null SID */
  	if (end_of_acl < (char *)psid + 8) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
900
901
  		cifs_dbg(VFS, "ACL too small to parse SID %p
  ", psid);
bcb020341   Steve French   [CIFS] move cifs ...
902
903
  		return -EINVAL;
  	}
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
904

bcb020341   Steve French   [CIFS] move cifs ...
905
  #ifdef CONFIG_CIFS_DEBUG2
fc03d8a5a   Jeff Layton   cifs: move num_su...
906
  	if (psid->num_subauth) {
8f18c1316   Steve French   [CIFS] remove com...
907
  		int i;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
908
909
910
  		cifs_dbg(FYI, "SID revision %d num_auth %d
  ",
  			 psid->revision, psid->num_subauth);
bcb020341   Steve French   [CIFS] move cifs ...
911

af6f4612f   Steve French   [CIFS] Fix some e...
912
  		for (i = 0; i < psid->num_subauth; i++) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
913
914
915
  			cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x
  ",
  				 i, le32_to_cpu(psid->sub_auth[i]));
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
916
  		}
d12fd121a   Steve French   [CIFS] Cleanup fo...
917
  		/* BB add length check to make sure that we do not have huge
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
918
  			num auths and therefore go off the end */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
919
920
921
  		cifs_dbg(FYI, "RID 0x%x
  ",
  			 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
922
  	}
fc03d8a5a   Jeff Layton   cifs: move num_su...
923
  #endif
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
924

bcb020341   Steve French   [CIFS] move cifs ...
925
926
  	return 0;
  }
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
927

bcb020341   Steve French   [CIFS] move cifs ...
928
  /* Convert CIFS ACL to POSIX form */
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
929
  static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
e2f8fbfb8   Steve French   cifs: get mode bi...
930
931
  		struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
  		bool get_mode_from_special_sid)
bcb020341   Steve French   [CIFS] move cifs ...
932
  {
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
933
  	int rc = 0;
bcb020341   Steve French   [CIFS] move cifs ...
934
935
  	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
  	struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
bcb020341   Steve French   [CIFS] move cifs ...
936
  	char *end_of_acl = ((char *)pntsd) + acl_len;
7505e0525   Steve French   [CIFS] If no Acce...
937
  	__u32 dacloffset;
bcb020341   Steve French   [CIFS] move cifs ...
938

0b8f18e35   Jeff Layton   cifs: convert cif...
939
  	if (pntsd == NULL)
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
940
  		return -EIO;
bcb020341   Steve French   [CIFS] move cifs ...
941
  	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612f   Steve French   [CIFS] Fix some e...
942
  				le32_to_cpu(pntsd->osidoffset));
bcb020341   Steve French   [CIFS] move cifs ...
943
  	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612f   Steve French   [CIFS] Fix some e...
944
  				le32_to_cpu(pntsd->gsidoffset));
7505e0525   Steve French   [CIFS] If no Acce...
945
  	dacloffset = le32_to_cpu(pntsd->dacloffset);
63d2583f5   Steve French   [CIFS] Fix walkin...
946
  	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
947
948
  	cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x
  ",
af6f4612f   Steve French   [CIFS] Fix some e...
949
950
  		 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
  		 le32_to_cpu(pntsd->gsidoffset),
b6b38f704   Joe Perches   [CIFS] Neaten cER...
951
  		 le32_to_cpu(pntsd->sacloffset), dacloffset);
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
952
  /*	cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
bcb020341   Steve French   [CIFS] move cifs ...
953
  	rc = parse_sid(owner_sid_ptr, end_of_acl);
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
954
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
955
956
  		cifs_dbg(FYI, "%s: Error %d parsing Owner SID
  ", __func__, rc);
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
957
958
959
960
  		return rc;
  	}
  	rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
961
962
963
  		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid
  ",
  			 __func__, rc);
bcb020341   Steve French   [CIFS] move cifs ...
964
  		return rc;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
965
  	}
bcb020341   Steve French   [CIFS] move cifs ...
966
967
  
  	rc = parse_sid(group_sid_ptr, end_of_acl);
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
968
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
969
970
971
  		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid
  ",
  			 __func__, rc);
bcb020341   Steve French   [CIFS] move cifs ...
972
  		return rc;
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
973
974
975
  	}
  	rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
976
977
978
  		cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid
  ",
  			 __func__, rc);
9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
979
980
  		return rc;
  	}
bcb020341   Steve French   [CIFS] move cifs ...
981

7505e0525   Steve French   [CIFS] If no Acce...
982
983
  	if (dacloffset)
  		parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
e2f8fbfb8   Steve French   cifs: get mode bi...
984
  			   group_sid_ptr, fattr, get_mode_from_special_sid);
7505e0525   Steve French   [CIFS] If no Acce...
985
  	else
f96637be0   Joe Perches   [CIFS] cifs: Rena...
986
987
  		cifs_dbg(FYI, "no ACL
  "); /* BB grant all or default perms? */
d0d66c443   Shirish Pargaonkar   [CIFS] CIFS ACL s...
988

9409ae58e   Shirish Pargaonkar   cifs: Invoke id m...
989
  	return rc;
bcb020341   Steve French   [CIFS] move cifs ...
990
  }
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
991

97837582b   Steve French   [CIFS] Allow sett...
992
993
  /* Convert permission bits from mode to equivalent CIFS ACL */
  static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
22442179a   Steve French   cifs: allow chmod...
994
  	__u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
a66033982   Steve French   cifs: fix chown a...
995
  	bool mode_from_sid, bool id_from_sid, int *aclflag)
97837582b   Steve French   [CIFS] Allow sett...
996
997
998
999
1000
1001
  {
  	int rc = 0;
  	__u32 dacloffset;
  	__u32 ndacloffset;
  	__u32 sidsoffset;
  	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1002
  	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
97837582b   Steve French   [CIFS] Allow sett...
1003
1004
  	struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
  	struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1005
1006
  	if (nmode != NO_CHANGE_64) { /* chmod */
  		owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582b   Steve French   [CIFS] Allow sett...
1007
  				le32_to_cpu(pntsd->osidoffset));
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1008
  		group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582b   Steve French   [CIFS] Allow sett...
1009
  				le32_to_cpu(pntsd->gsidoffset));
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1010
1011
1012
1013
1014
1015
1016
1017
1018
  		dacloffset = le32_to_cpu(pntsd->dacloffset);
  		dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
  		ndacloffset = sizeof(struct cifs_ntsd);
  		ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
  		ndacl_ptr->revision = dacl_ptr->revision;
  		ndacl_ptr->size = 0;
  		ndacl_ptr->num_aces = 0;
  
  		rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
22442179a   Steve French   cifs: allow chmod...
1019
  				    nmode, mode_from_sid);
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1020
1021
1022
1023
1024
1025
  		sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
  		/* copy sec desc control portion & owner and group sids */
  		copy_sec_desc(pntsd, pnntsd, sidsoffset);
  		*aclflag = CIFS_ACL_DACL;
  	} else {
  		memcpy(pnntsd, pntsd, secdesclen);
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
1026
1027
  		if (uid_valid(uid)) { /* chown */
  			uid_t id;
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1028
1029
1030
1031
1032
1033
  			owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
  					le32_to_cpu(pnntsd->osidoffset));
  			nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
  								GFP_KERNEL);
  			if (!nowner_sid_ptr)
  				return -ENOMEM;
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
1034
  			id = from_kuid(&init_user_ns, uid);
a66033982   Steve French   cifs: fix chown a...
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
  			if (id_from_sid) {
  				struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
  				/* Populate the user ownership fields S-1-5-88-1 */
  				osid->Revision = 1;
  				osid->NumAuth = 3;
  				osid->Authority[5] = 5;
  				osid->SubAuthorities[0] = cpu_to_le32(88);
  				osid->SubAuthorities[1] = cpu_to_le32(1);
  				osid->SubAuthorities[2] = cpu_to_le32(id);
  			} else { /* lookup sid with upcall */
  				rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
  				if (rc) {
  					cifs_dbg(FYI, "%s: Mapping error %d for owner id %d
  ",
  						 __func__, rc, id);
  					kfree(nowner_sid_ptr);
  					return rc;
  				}
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1053
  			}
36960e440   Jeff Layton   cifs: fix potenti...
1054
  			cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1055
1056
1057
  			kfree(nowner_sid_ptr);
  			*aclflag = CIFS_ACL_OWNER;
  		}
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
1058
1059
  		if (gid_valid(gid)) { /* chgrp */
  			gid_t id;
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1060
1061
1062
1063
1064
1065
  			group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
  					le32_to_cpu(pnntsd->gsidoffset));
  			ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
  								GFP_KERNEL);
  			if (!ngroup_sid_ptr)
  				return -ENOMEM;
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
1066
  			id = from_kgid(&init_user_ns, gid);
a66033982   Steve French   cifs: fix chown a...
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
  			if (id_from_sid) {
  				struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
  				/* Populate the group ownership fields S-1-5-88-2 */
  				gsid->Revision = 1;
  				gsid->NumAuth = 3;
  				gsid->Authority[5] = 5;
  				gsid->SubAuthorities[0] = cpu_to_le32(88);
  				gsid->SubAuthorities[1] = cpu_to_le32(2);
  				gsid->SubAuthorities[2] = cpu_to_le32(id);
  			} else { /* lookup sid with upcall */
  				rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
  				if (rc) {
  					cifs_dbg(FYI, "%s: Mapping error %d for group id %d
  ",
  						 __func__, rc, id);
  					kfree(ngroup_sid_ptr);
  					return rc;
  				}
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1085
  			}
36960e440   Jeff Layton   cifs: fix potenti...
1086
  			cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1087
1088
1089
1090
  			kfree(ngroup_sid_ptr);
  			*aclflag = CIFS_ACL_GROUP;
  		}
  	}
97837582b   Steve French   [CIFS] Allow sett...
1091

ef571cadd   Shirish Pargaonkar   [CIFS] Fix warnin...
1092
  	return rc;
97837582b   Steve French   [CIFS] Allow sett...
1093
  }
42eacf9e5   Steve French   [CIFS] Fix cifsac...
1094
1095
  struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
  		const struct cifs_fid *cifsfid, u32 *pacllen)
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1096
  {
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1097
  	struct cifs_ntsd *pntsd = NULL;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1098
1099
  	unsigned int xid;
  	int rc;
7ffec3724   Jeff Layton   cifs: add refcoun...
1100
1101
1102
  	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
  
  	if (IS_ERR(tlink))
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1103
  		return ERR_CAST(tlink);
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1104

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1105
  	xid = get_xid();
42eacf9e5   Steve French   [CIFS] Fix cifsac...
1106
1107
  	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
  				pacllen);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1108
  	free_xid(xid);
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1109

7ffec3724   Jeff Layton   cifs: add refcoun...
1110
  	cifs_put_tlink(tlink);
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1111

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1112
1113
  	cifs_dbg(FYI, "%s: rc = %d ACL len %d
  ", __func__, rc, *pacllen);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1114
1115
  	if (rc)
  		return ERR_PTR(rc);
1bf4072da   Christoph Hellwig   cifs: reorganize ...
1116
1117
  	return pntsd;
  }
8b1327f6e   Steve French   [CIFS] file creat...
1118

1bf4072da   Christoph Hellwig   cifs: reorganize ...
1119
1120
1121
1122
1123
  static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
  		const char *path, u32 *pacllen)
  {
  	struct cifs_ntsd *pntsd = NULL;
  	int oplock = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1124
  	unsigned int xid;
0f060936e   Amir Goldstein   SMB3: Backup inte...
1125
  	int rc;
96daf2b09   Steve French   [CIFS] Rename thr...
1126
  	struct cifs_tcon *tcon;
7ffec3724   Jeff Layton   cifs: add refcoun...
1127
  	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1128
1129
  	struct cifs_fid fid;
  	struct cifs_open_parms oparms;
7ffec3724   Jeff Layton   cifs: add refcoun...
1130
1131
  
  	if (IS_ERR(tlink))
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1132
  		return ERR_CAST(tlink);
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1133

7ffec3724   Jeff Layton   cifs: add refcoun...
1134
  	tcon = tlink_tcon(tlink);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1135
  	xid = get_xid();
1bf4072da   Christoph Hellwig   cifs: reorganize ...
1136

d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1137
1138
1139
  	oparms.tcon = tcon;
  	oparms.cifs_sb = cifs_sb;
  	oparms.desired_access = READ_CONTROL;
0f060936e   Amir Goldstein   SMB3: Backup inte...
1140
  	oparms.create_options = cifs_create_options(cifs_sb, 0);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1141
1142
1143
1144
1145
1146
  	oparms.disposition = FILE_OPEN;
  	oparms.path = path;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
  
  	rc = CIFS_open(xid, &oparms, &oplock, NULL);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1147
  	if (!rc) {
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1148
1149
  		rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
  		CIFSSMBClose(xid, tcon, fid.netfid);
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1150
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1151
  	cifs_put_tlink(tlink);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1152
  	free_xid(xid);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1153

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1154
1155
  	cifs_dbg(FYI, "%s: rc = %d ACL len %d
  ", __func__, rc, *pacllen);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1156
1157
  	if (rc)
  		return ERR_PTR(rc);
7505e0525   Steve French   [CIFS] If no Acce...
1158
1159
  	return pntsd;
  }
1bf4072da   Christoph Hellwig   cifs: reorganize ...
1160
  /* Retrieve an ACL from the server */
fbeba8bb1   Shirish Pargaonkar   cifs: Handle exte...
1161
  struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1bf4072da   Christoph Hellwig   cifs: reorganize ...
1162
1163
1164
1165
1166
1167
1168
  				      struct inode *inode, const char *path,
  				      u32 *pacllen)
  {
  	struct cifs_ntsd *pntsd = NULL;
  	struct cifsFileInfo *open_file = NULL;
  
  	if (inode)
6508d904e   Jeff Layton   cifs: have find_r...
1169
  		open_file = find_readable_file(CIFS_I(inode), true);
1bf4072da   Christoph Hellwig   cifs: reorganize ...
1170
1171
  	if (!open_file)
  		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
42eacf9e5   Steve French   [CIFS] Fix cifsac...
1172
  	pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
6ab409b53   Dave Kleikamp   cifs: Replace wrt...
1173
  	cifsFileInfo_put(open_file);
1bf4072da   Christoph Hellwig   cifs: reorganize ...
1174
1175
  	return pntsd;
  }
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1176
1177
1178
   /* Set an ACL on the server */
  int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
  			struct inode *inode, const char *path, int aclflag)
b96d31a62   Christoph Hellwig   cifs: clean up se...
1179
1180
  {
  	int oplock = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1181
  	unsigned int xid;
0f060936e   Amir Goldstein   SMB3: Backup inte...
1182
  	int rc, access_flags;
96daf2b09   Steve French   [CIFS] Rename thr...
1183
  	struct cifs_tcon *tcon;
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1184
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1185
  	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1186
1187
  	struct cifs_fid fid;
  	struct cifs_open_parms oparms;
97837582b   Steve French   [CIFS] Allow sett...
1188

7ffec3724   Jeff Layton   cifs: add refcoun...
1189
1190
1191
1192
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  
  	tcon = tlink_tcon(tlink);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1193
  	xid = get_xid();
97837582b   Steve French   [CIFS] Allow sett...
1194

a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1195
1196
1197
1198
  	if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
  		access_flags = WRITE_OWNER;
  	else
  		access_flags = WRITE_DAC;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1199
1200
1201
  	oparms.tcon = tcon;
  	oparms.cifs_sb = cifs_sb;
  	oparms.desired_access = access_flags;
0f060936e   Amir Goldstein   SMB3: Backup inte...
1202
  	oparms.create_options = cifs_create_options(cifs_sb, 0);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1203
1204
1205
1206
1207
1208
  	oparms.disposition = FILE_OPEN;
  	oparms.path = path;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
  
  	rc = CIFS_open(xid, &oparms, &oplock, NULL);
b96d31a62   Christoph Hellwig   cifs: clean up se...
1209
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1210
1211
  		cifs_dbg(VFS, "Unable to open file to set ACL
  ");
b96d31a62   Christoph Hellwig   cifs: clean up se...
1212
  		goto out;
97837582b   Steve French   [CIFS] Allow sett...
1213
  	}
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1214
  	rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1215
1216
  	cifs_dbg(NOISY, "SetCIFSACL rc = %d
  ", rc);
97837582b   Steve French   [CIFS] Allow sett...
1217

d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1218
  	CIFSSMBClose(xid, tcon, fid.netfid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1219
  out:
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1220
  	free_xid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1221
  	cifs_put_tlink(tlink);
b96d31a62   Christoph Hellwig   cifs: clean up se...
1222
1223
  	return rc;
  }
97837582b   Steve French   [CIFS] Allow sett...
1224

36c7ce4a1   Achilles Gaikwad   fs/cifs/cifsacl.c...
1225
  /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1226
  int
0b8f18e35   Jeff Layton   cifs: convert cif...
1227
  cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
e2f8fbfb8   Steve French   cifs: get mode bi...
1228
1229
  		  struct inode *inode, bool mode_from_special_sid,
  		  const char *path, const struct cifs_fid *pfid)
7505e0525   Steve French   [CIFS] If no Acce...
1230
1231
1232
1233
  {
  	struct cifs_ntsd *pntsd = NULL;
  	u32 acllen = 0;
  	int rc = 0;
42eacf9e5   Steve French   [CIFS] Fix cifsac...
1234
  	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1235
  	struct smb_version_operations *ops;
7505e0525   Steve French   [CIFS] If no Acce...
1236

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1237
1238
  	cifs_dbg(NOISY, "converting ACL to mode for %s
  ", path);
1bf4072da   Christoph Hellwig   cifs: reorganize ...
1239

42eacf9e5   Steve French   [CIFS] Fix cifsac...
1240
1241
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
7505e0525   Steve French   [CIFS] If no Acce...
1242

ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1243
1244
1245
1246
1247
1248
  	ops = tlink_tcon(tlink)->ses->server->ops;
  
  	if (pfid && (ops->get_acl_by_fid))
  		pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
  	else if (ops->get_acl)
  		pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
42eacf9e5   Steve French   [CIFS] Fix cifsac...
1249
1250
1251
1252
  	else {
  		cifs_put_tlink(tlink);
  		return -EOPNOTSUPP;
  	}
7505e0525   Steve French   [CIFS] If no Acce...
1253
  	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1254
1255
  	if (IS_ERR(pntsd)) {
  		rc = PTR_ERR(pntsd);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1256
1257
  		cifs_dbg(VFS, "%s: error %d getting sec desc
  ", __func__, rc);
e2f8fbfb8   Steve French   cifs: get mode bi...
1258
1259
  	} else if (mode_from_special_sid) {
  		rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
981285720   Namjae Jeon   cifs: fix a memle...
1260
  		kfree(pntsd);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1261
  	} else {
e2f8fbfb8   Steve French   cifs: get mode bi...
1262
1263
  		/* get approximated mode from ACL */
  		rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1264
1265
  		kfree(pntsd);
  		if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1266
1267
  			cifs_dbg(VFS, "parse sec desc failed rc = %d
  ", rc);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1268
  	}
7505e0525   Steve French   [CIFS] If no Acce...
1269

42eacf9e5   Steve French   [CIFS] Fix cifsac...
1270
  	cifs_put_tlink(tlink);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1271
  	return rc;
b9c7a2bb1   Steve French   [CIFS] ACL suppor...
1272
  }
953f86813   Steve French   [CIFS] Don't requ...
1273

7505e0525   Steve French   [CIFS] If no Acce...
1274
  /* Convert mode bits to an ACL so we can update the ACL on the server */
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1275
1276
  int
  id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
1277
  			kuid_t uid, kgid_t gid)
953f86813   Steve French   [CIFS] Don't requ...
1278
1279
  {
  	int rc = 0;
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
1280
  	int aclflag = CIFS_ACL_DACL; /* default flag to set */
cce246ee5   Steve French   [CIFS] Fix acl le...
1281
  	__u32 secdesclen = 0;
97837582b   Steve French   [CIFS] Allow sett...
1282
1283
  	struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
  	struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
83e3bc23e   Steve French   retrieving CIFS A...
1284
1285
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
  	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1286
  	struct smb_version_operations *ops;
a66033982   Steve French   cifs: fix chown a...
1287
  	bool mode_from_sid, id_from_sid;
83e3bc23e   Steve French   retrieving CIFS A...
1288
1289
1290
  
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1291
1292
  
  	ops = tlink_tcon(tlink)->ses->server->ops;
953f86813   Steve French   [CIFS] Don't requ...
1293

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1294
1295
  	cifs_dbg(NOISY, "set ACL from mode for %s
  ", path);
953f86813   Steve French   [CIFS] Don't requ...
1296
1297
  
  	/* Get the security descriptor */
83e3bc23e   Steve French   retrieving CIFS A...
1298

ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1299
  	if (ops->get_acl == NULL) {
83e3bc23e   Steve French   retrieving CIFS A...
1300
1301
1302
  		cifs_put_tlink(tlink);
  		return -EOPNOTSUPP;
  	}
ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1303
  	pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
987b21d7d   Shirish Pargaonkar   cifs: Percolate e...
1304
1305
  	if (IS_ERR(pntsd)) {
  		rc = PTR_ERR(pntsd);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1306
1307
  		cifs_dbg(VFS, "%s: error %d getting sec desc
  ", __func__, rc);
83e3bc23e   Steve French   retrieving CIFS A...
1308
1309
  		cifs_put_tlink(tlink);
  		return rc;
c78cd8380   Jeff Layton   cifs: clean up id...
1310
  	}
7505e0525   Steve French   [CIFS] If no Acce...
1311

c78cd8380   Jeff Layton   cifs: clean up id...
1312
1313
1314
1315
1316
1317
  	/*
  	 * Add three ACEs for owner, group, everyone getting rid of other ACEs
  	 * as chmod disables ACEs and set the security descriptor. Allocate
  	 * memory for the smb header, set security descriptor request security
  	 * descriptor parameters, and secuirty descriptor itself
  	 */
7ee0b4c63   Jeff Layton   cifs: fix hardcod...
1318
  	secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
c78cd8380   Jeff Layton   cifs: clean up id...
1319
1320
  	pnntsd = kmalloc(secdesclen, GFP_KERNEL);
  	if (!pnntsd) {
c78cd8380   Jeff Layton   cifs: clean up id...
1321
  		kfree(pntsd);
83e3bc23e   Steve French   retrieving CIFS A...
1322
  		cifs_put_tlink(tlink);
c78cd8380   Jeff Layton   cifs: clean up id...
1323
1324
  		return -ENOMEM;
  	}
97837582b   Steve French   [CIFS] Allow sett...
1325

22442179a   Steve French   cifs: allow chmod...
1326
1327
1328
1329
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
  		mode_from_sid = true;
  	else
  		mode_from_sid = false;
a66033982   Steve French   cifs: fix chown a...
1330
1331
1332
1333
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
  		id_from_sid = true;
  	else
  		id_from_sid = false;
c78cd8380   Jeff Layton   cifs: clean up id...
1334
  	rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
a66033982   Steve French   cifs: fix chown a...
1335
  			    mode_from_sid, id_from_sid, &aclflag);
97837582b   Steve French   [CIFS] Allow sett...
1336

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1337
1338
  	cifs_dbg(NOISY, "build_sec_desc rc: %d
  ", rc);
97837582b   Steve French   [CIFS] Allow sett...
1339

ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1340
  	if (ops->set_acl == NULL)
83e3bc23e   Steve French   retrieving CIFS A...
1341
  		rc = -EOPNOTSUPP;
c78cd8380   Jeff Layton   cifs: clean up id...
1342
1343
  	if (!rc) {
  		/* Set the security descriptor */
ecdcf622e   Joe Perches via samba-technical   cifs: cifsacl: Us...
1344
  		rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1345
1346
  		cifs_dbg(NOISY, "set_cifs_acl rc: %d
  ", rc);
97837582b   Steve French   [CIFS] Allow sett...
1347
  	}
83e3bc23e   Steve French   retrieving CIFS A...
1348
  	cifs_put_tlink(tlink);
97837582b   Steve French   [CIFS] Allow sett...
1349

c78cd8380   Jeff Layton   cifs: clean up id...
1350
1351
  	kfree(pnntsd);
  	kfree(pntsd);
ef571cadd   Shirish Pargaonkar   [CIFS] Fix warnin...
1352
  	return rc;
953f86813   Steve French   [CIFS] Don't requ...
1353
  }