blob: ee3aab3dd4ac6f2f748b6c58e47dc423b4edb2f3 [file] [log] [blame]
Steve French929be902021-06-18 00:31:49 -05001// SPDX-License-Identifier: LGPL-2.1
Steve Frenchbcb02032007-09-25 16:17:24 +00002/*
Steve Frenchbcb02032007-09-25 16:17:24 +00003 *
Steve French8b1327f2008-03-14 22:37:16 +00004 * Copyright (C) International Business Machines Corp., 2007,2008
Steve Frenchbcb02032007-09-25 16:17:24 +00005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for mapping CIFS/NTFS ACLs
8 *
Steve Frenchbcb02032007-09-25 16:17:24 +00009 */
10
Steve French65874002007-09-25 19:53:44 +000011#include <linux/fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050013#include <linux/string.h>
14#include <linux/keyctl.h>
15#include <linux/key-type.h>
16#include <keys/user-type.h>
Steve French65874002007-09-25 19:53:44 +000017#include "cifspdu.h"
18#include "cifsglob.h"
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +000019#include "cifsacl.h"
Steve French65874002007-09-25 19:53:44 +000020#include "cifsproto.h"
21#include "cifs_debug.h"
Ronnie Sahlberg8401e932020-12-12 13:40:50 -060022#include "fs_context.h"
Steve French65874002007-09-25 19:53:44 +000023
Shirish Pargaonkar2fbc2f12010-12-06 14:56:46 -060024/* security id for everyone/world system group */
Shirish Pargaonkare01b6402007-10-30 04:45:14 +000025static const struct cifs_sid sid_everyone = {
26 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
Shirish Pargaonkar2fbc2f12010-12-06 14:56:46 -060027/* security id for Authenticated Users system group */
28static const struct cifs_sid sid_authusers = {
Fabian Frederickbc09d142014-12-10 15:41:15 -080029 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +000030
Steve French3514de32016-10-13 19:06:23 -050031/* S-1-22-1 Unmapped Unix users */
32static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
33 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
34
35/* S-1-22-2 Unmapped Unix groups */
36static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
37 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
38
39/*
Alexander A. Klimovcba22b12020-06-27 12:31:25 +020040 * See https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
Steve French3514de32016-10-13 19:06:23 -050041 */
42
43/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
44
45/* S-1-5-88-1 Unix uid */
46static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
47 {cpu_to_le32(88),
48 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
49
50/* S-1-5-88-2 Unix gid */
51static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
52 {cpu_to_le32(88),
53 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
54
55/* S-1-5-88-3 Unix mode */
56static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
57 {cpu_to_le32(88),
58 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
59
Jeff Laytonb1a6dc22012-11-25 08:00:38 -050060static const struct cred *root_cred;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -050061
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050062static int
David Howellscf7f6012012-09-13 13:06:29 +010063cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050064{
65 char *payload;
66
Jeff Layton41a9f1f2012-12-03 06:05:29 -050067 /*
68 * If the payload is less than or equal to the size of a pointer, then
69 * an allocation here is wasteful. Just copy the data directly to the
70 * payload.value union member instead.
71 *
72 * With this however, you must check the datalen before trying to
73 * dereference payload.data!
74 */
Jeff Layton1f630682012-12-03 06:05:31 -050075 if (prep->datalen <= sizeof(key->payload)) {
David Howells146aa8b2015-10-21 14:04:48 +010076 key->payload.data[0] = NULL;
77 memcpy(&key->payload, prep->data, prep->datalen);
78 } else {
79 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
80 if (!payload)
81 return -ENOMEM;
82 key->payload.data[0] = payload;
Jeff Layton41a9f1f2012-12-03 06:05:29 -050083 }
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050084
David Howellscf7f6012012-09-13 13:06:29 +010085 key->datalen = prep->datalen;
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050086 return 0;
87}
88
89static inline void
90cifs_idmap_key_destroy(struct key *key)
91{
Jeff Layton1f630682012-12-03 06:05:31 -050092 if (key->datalen > sizeof(key->payload))
David Howells146aa8b2015-10-21 14:04:48 +010093 kfree(key->payload.data[0]);
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050094}
95
Jeff Laytonb1a6dc22012-11-25 08:00:38 -050096static struct key_type cifs_idmap_key_type = {
Shirish Pargaonkarc4aca0c2011-05-06 02:35:00 -050097 .name = "cifs.idmap",
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -050098 .instantiate = cifs_idmap_key_instantiate,
99 .destroy = cifs_idmap_key_destroy,
100 .describe = user_describe,
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500101};
102
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500103static char *
104sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500105{
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500106 int i, len;
Jeff Laytonee13b2b2012-11-25 08:00:38 -0500107 unsigned int saval;
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500108 char *sidstr, *strptr;
Jeff Layton193cdd82012-12-10 06:10:44 -0500109 unsigned long long id_auth_val;
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500110
111 /* 3 bytes for prefix */
112 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
113 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
114 GFP_KERNEL);
115 if (!sidstr)
116 return sidstr;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500117
118 strptr = sidstr;
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500119 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
120 sidptr->revision);
121 strptr += len;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500122
Jeff Layton193cdd82012-12-10 06:10:44 -0500123 /* The authority field is a single 48-bit number */
124 id_auth_val = (unsigned long long)sidptr->authority[5];
125 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
126 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
127 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
128 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
129 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
130
131 /*
132 * MS-DTYP states that if the authority is >= 2^32, then it should be
133 * expressed as a hex value.
134 */
135 if (id_auth_val <= UINT_MAX)
136 len = sprintf(strptr, "-%llu", id_auth_val);
137 else
138 len = sprintf(strptr, "-0x%llx", id_auth_val);
139
140 strptr += len;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500141
142 for (i = 0; i < sidptr->num_subauth; ++i) {
143 saval = le32_to_cpu(sidptr->sub_auth[i]);
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500144 len = sprintf(strptr, "-%u", saval);
145 strptr += len;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500146 }
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500147
148 return sidstr;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500149}
150
Jeff Layton436bb432012-11-25 08:00:36 -0500151/*
152 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
153 * the same returns zero, if they do not match returns non-zero.
154 */
155static int
156compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
157{
158 int i;
159 int num_subauth, num_sat, num_saw;
160
161 if ((!ctsid) || (!cwsid))
162 return 1;
163
164 /* compare the revision */
165 if (ctsid->revision != cwsid->revision) {
166 if (ctsid->revision > cwsid->revision)
167 return 1;
168 else
169 return -1;
170 }
171
172 /* compare all of the six auth values */
173 for (i = 0; i < NUM_AUTHS; ++i) {
174 if (ctsid->authority[i] != cwsid->authority[i]) {
175 if (ctsid->authority[i] > cwsid->authority[i])
176 return 1;
177 else
178 return -1;
179 }
180 }
181
182 /* compare all of the subauth values if any */
183 num_sat = ctsid->num_subauth;
184 num_saw = cwsid->num_subauth;
185 num_subauth = num_sat < num_saw ? num_sat : num_saw;
186 if (num_subauth) {
187 for (i = 0; i < num_subauth; ++i) {
188 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
189 if (le32_to_cpu(ctsid->sub_auth[i]) >
190 le32_to_cpu(cwsid->sub_auth[i]))
191 return 1;
192 else
193 return -1;
194 }
195 }
196 }
197
198 return 0; /* sids compare/match */
199}
200
Steve French3514de32016-10-13 19:06:23 -0500201static bool
202is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
203{
204 int i;
205 int num_subauth;
206 const struct cifs_sid *pwell_known_sid;
207
208 if (!psid || (puid == NULL))
209 return false;
210
211 num_subauth = psid->num_subauth;
212
213 /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
214 if (num_subauth == 2) {
215 if (is_group)
216 pwell_known_sid = &sid_unix_groups;
217 else
218 pwell_known_sid = &sid_unix_users;
219 } else if (num_subauth == 3) {
220 if (is_group)
221 pwell_known_sid = &sid_unix_NFS_groups;
222 else
223 pwell_known_sid = &sid_unix_NFS_users;
224 } else
225 return false;
226
227 /* compare the revision */
228 if (psid->revision != pwell_known_sid->revision)
229 return false;
230
231 /* compare all of the six auth values */
232 for (i = 0; i < NUM_AUTHS; ++i) {
233 if (psid->authority[i] != pwell_known_sid->authority[i]) {
234 cifs_dbg(FYI, "auth %d did not match\n", i);
235 return false;
236 }
237 }
238
239 if (num_subauth == 2) {
240 if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
241 return false;
242
243 *puid = le32_to_cpu(psid->sub_auth[1]);
244 } else /* 3 subauths, ie Windows/Mac style */ {
245 *puid = le32_to_cpu(psid->sub_auth[0]);
246 if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
247 (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
248 return false;
249
250 *puid = le32_to_cpu(psid->sub_auth[2]);
251 }
252
253 cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
254 return true; /* well known sid found, uid returned */
255}
256
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800257static __u16
Jeff Layton36960e42012-11-03 09:37:28 -0400258cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
259{
Jeff Layton36f87ee2012-11-25 08:00:37 -0500260 int i;
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800261 __u16 size = 1 + 1 + 6;
Jeff Layton36f87ee2012-11-25 08:00:37 -0500262
263 dst->revision = src->revision;
Jeff Layton30c9d6c2012-11-25 08:00:37 -0500264 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
Jeff Layton36f87ee2012-11-25 08:00:37 -0500265 for (i = 0; i < NUM_AUTHS; ++i)
266 dst->authority[i] = src->authority[i];
267 for (i = 0; i < dst->num_subauth; ++i)
268 dst->sub_auth[i] = src->sub_auth[i];
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800269 size += (dst->num_subauth * 4);
270
271 return size;
Jeff Layton36960e42012-11-03 09:37:28 -0400272}
273
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500274static int
275id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500276{
277 int rc;
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500278 struct key *sidkey;
Jeff Layton2ae03022012-12-03 06:05:30 -0500279 struct cifs_sid *ksid;
280 unsigned int ksid_size;
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500281 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500282 const struct cred *saved_cred;
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500283
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500284 rc = snprintf(desc, sizeof(desc), "%ci:%u",
285 sidtype == SIDOWNER ? 'o' : 'g', cid);
286 if (rc >= sizeof(desc))
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500287 return -EINVAL;
288
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500289 rc = 0;
290 saved_cred = override_creds(root_cred);
Linus Torvalds028db3e2019-07-10 18:43:43 -0700291 sidkey = request_key(&cifs_idmap_key_type, desc, "");
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500292 if (IS_ERR(sidkey)) {
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500293 rc = -EINVAL;
Joe Perchesf96637b2013-05-04 22:12:25 -0500294 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
295 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500296 goto out_revert_creds;
297 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
298 rc = -EIO;
Joe Perchesf96637b2013-05-04 22:12:25 -0500299 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
300 __func__, sidkey->datalen);
Jeff Layton2ae03022012-12-03 06:05:30 -0500301 goto invalidate_key;
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500302 }
Jeff Layton2ae03022012-12-03 06:05:30 -0500303
Jeff Layton1f630682012-12-03 06:05:31 -0500304 /*
305 * A sid is usually too large to be embedded in payload.value, but if
306 * there are no subauthorities and the host has 8-byte pointers, then
307 * it could be.
308 */
309 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
David Howells146aa8b2015-10-21 14:04:48 +0100310 (struct cifs_sid *)&sidkey->payload :
311 (struct cifs_sid *)sidkey->payload.data[0];
Jeff Layton1f630682012-12-03 06:05:31 -0500312
Jeff Layton2ae03022012-12-03 06:05:30 -0500313 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
314 if (ksid_size > sidkey->datalen) {
315 rc = -EIO;
Joe Perchesf96637b2013-05-04 22:12:25 -0500316 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
317 __func__, sidkey->datalen, ksid_size);
Jeff Layton2ae03022012-12-03 06:05:30 -0500318 goto invalidate_key;
319 }
Jeff Layton1f630682012-12-03 06:05:31 -0500320
Jeff Layton2ae03022012-12-03 06:05:30 -0500321 cifs_copy_sid(ssid, ksid);
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500322out_key_put:
323 key_put(sidkey);
324out_revert_creds:
325 revert_creds(saved_cred);
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500326 return rc;
Jeff Layton2ae03022012-12-03 06:05:30 -0500327
328invalidate_key:
329 key_invalidate(sidkey);
330 goto out_key_put;
Shirish Pargaonkar21fed0d2011-08-09 14:30:48 -0500331}
332
Steve French99344302020-10-20 02:02:02 -0500333int
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500334sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
335 struct cifs_fattr *fattr, uint sidtype)
336{
Qiujun Huangf2d67932020-03-04 15:42:51 +0800337 int rc = 0;
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500338 struct key *sidkey;
339 char *sidstr;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500340 const struct cred *saved_cred;
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600341 kuid_t fuid = cifs_sb->ctx->linux_uid;
342 kgid_t fgid = cifs_sb->ctx->linux_gid;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500343
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500344 /*
345 * If we have too many subauthorities, then something is really wrong.
346 * Just return an error.
347 */
348 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500349 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
350 __func__, psid->num_subauth);
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500351 return -EIO;
352 }
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500353
Steve French99344302020-10-20 02:02:02 -0500354 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
355 (cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
Steve French3514de32016-10-13 19:06:23 -0500356 uint32_t unix_id;
357 bool is_group;
358
359 if (sidtype != SIDOWNER)
360 is_group = true;
361 else
362 is_group = false;
363
364 if (is_well_known_sid(psid, &unix_id, is_group) == false)
365 goto try_upcall_to_get_id;
366
367 if (is_group) {
368 kgid_t gid;
369 gid_t id;
370
371 id = (gid_t)unix_id;
372 gid = make_kgid(&init_user_ns, id);
373 if (gid_valid(gid)) {
374 fgid = gid;
375 goto got_valid_id;
376 }
377 } else {
378 kuid_t uid;
379 uid_t id;
380
381 id = (uid_t)unix_id;
382 uid = make_kuid(&init_user_ns, id);
383 if (uid_valid(uid)) {
384 fuid = uid;
385 goto got_valid_id;
386 }
387 }
388 /* If unable to find uid/gid easily from SID try via upcall */
389 }
390
391try_upcall_to_get_id:
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500392 sidstr = sid_to_key_str(psid, sidtype);
393 if (!sidstr)
394 return -ENOMEM;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500395
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500396 saved_cred = override_creds(root_cred);
Linus Torvalds028db3e2019-07-10 18:43:43 -0700397 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500398 if (IS_ERR(sidkey)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500399 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
400 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500401 goto out_revert_creds;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500402 }
403
404 /*
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500405 * FIXME: Here we assume that uid_t and gid_t are same size. It's
406 * probably a safe assumption but might be better to check based on
407 * sidtype.
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500408 */
Eric W. Biederman355958f2013-02-06 00:10:23 -0800409 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
Jeff Layton41a9f1f2012-12-03 06:05:29 -0500410 if (sidkey->datalen != sizeof(uid_t)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500411 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
412 __func__, sidkey->datalen);
Jeff Layton2ae03022012-12-03 06:05:30 -0500413 key_invalidate(sidkey);
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500414 goto out_key_put;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500415 }
416
Eric W. Biederman8abf2772013-02-06 00:33:17 -0800417 if (sidtype == SIDOWNER) {
418 kuid_t uid;
419 uid_t id;
David Howells146aa8b2015-10-21 14:04:48 +0100420 memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
Eric W. Biederman8abf2772013-02-06 00:33:17 -0800421 uid = make_kuid(&init_user_ns, id);
422 if (uid_valid(uid))
423 fuid = uid;
424 } else {
425 kgid_t gid;
426 gid_t id;
David Howells146aa8b2015-10-21 14:04:48 +0100427 memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
Eric W. Biederman8abf2772013-02-06 00:33:17 -0800428 gid = make_kgid(&init_user_ns, id);
429 if (gid_valid(gid))
430 fgid = gid;
431 }
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500432
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500433out_key_put:
434 key_put(sidkey);
435out_revert_creds:
436 revert_creds(saved_cred);
437 kfree(sidstr);
438
439 /*
440 * Note that we return 0 here unconditionally. If the mapping
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600441 * fails then we just fall back to using the ctx->linux_uid/linux_gid.
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500442 */
Steve French3514de32016-10-13 19:06:23 -0500443got_valid_id:
Qiujun Huangf2d67932020-03-04 15:42:51 +0800444 rc = 0;
Jeff Laytonfaa65f02012-12-03 06:05:29 -0500445 if (sidtype == SIDOWNER)
446 fattr->cf_uid = fuid;
447 else
448 fattr->cf_gid = fgid;
Qiujun Huangf2d67932020-03-04 15:42:51 +0800449 return rc;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -0500450}
451
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500452int
453init_cifs_idmap(void)
454{
455 struct cred *cred;
456 struct key *keyring;
457 int ret;
458
Joe Perchesf96637b2013-05-04 22:12:25 -0500459 cifs_dbg(FYI, "Registering the %s key type\n",
460 cifs_idmap_key_type.name);
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500461
462 /* create an override credential set with a special thread keyring in
463 * which requests are cached
464 *
465 * this is used to prevent malicious redirections from being installed
466 * with add_key().
467 */
468 cred = prepare_kernel_cred(NULL);
469 if (!cred)
470 return -ENOMEM;
471
Eric W. Biederman8e3028b2013-02-06 00:21:22 -0800472 keyring = keyring_alloc(".cifs_idmap",
473 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
Linus Torvalds028db3e2019-07-10 18:43:43 -0700474 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
475 KEY_USR_VIEW | KEY_USR_READ,
David Howells5ac7eac2016-04-06 16:14:24 +0100476 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500477 if (IS_ERR(keyring)) {
478 ret = PTR_ERR(keyring);
479 goto failed_put_cred;
480 }
481
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500482 ret = register_key_type(&cifs_idmap_key_type);
483 if (ret < 0)
484 goto failed_put_key;
485
486 /* instruct request_key() to use this special keyring as a cache for
487 * the results it looks up */
David Howells700920e2012-01-18 15:31:45 +0000488 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500489 cred->thread_keyring = keyring;
490 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
491 root_cred = cred;
492
Joe Perchesf96637b2013-05-04 22:12:25 -0500493 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500494 return 0;
495
496failed_put_key:
497 key_put(keyring);
498failed_put_cred:
499 put_cred(cred);
500 return ret;
501}
502
503void
504exit_cifs_idmap(void)
505{
506 key_revoke(root_cred->thread_keyring);
507 unregister_key_type(&cifs_idmap_key_type);
508 put_cred(root_cred);
Joe Perchesf96637b2013-05-04 22:12:25 -0500509 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -0500510}
511
Steve French97837582007-12-31 07:47:21 +0000512/* copy ntsd, owner sid, and group sid from a security descriptor to another */
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +0000513static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd,
514 struct cifs_ntsd *pnntsd,
515 __u32 sidsoffset,
516 struct cifs_sid *pownersid,
517 struct cifs_sid *pgrpsid)
Steve French97837582007-12-31 07:47:21 +0000518{
Steve French97837582007-12-31 07:47:21 +0000519 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
520 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
521
522 /* copy security descriptor control portion */
523 pnntsd->revision = pntsd->revision;
524 pnntsd->type = pntsd->type;
525 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
526 pnntsd->sacloffset = 0;
527 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
528 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
529
530 /* copy owner sid */
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +0000531 if (pownersid)
532 owner_sid_ptr = pownersid;
533 else
534 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve French97837582007-12-31 07:47:21 +0000535 le32_to_cpu(pntsd->osidoffset));
536 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
Jeff Layton36960e42012-11-03 09:37:28 -0400537 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
Steve French97837582007-12-31 07:47:21 +0000538
539 /* copy group sid */
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +0000540 if (pgrpsid)
541 group_sid_ptr = pgrpsid;
542 else
543 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve French97837582007-12-31 07:47:21 +0000544 le32_to_cpu(pntsd->gsidoffset));
545 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
546 sizeof(struct cifs_sid));
Jeff Layton36960e42012-11-03 09:37:28 -0400547 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
Steve French97837582007-12-31 07:47:21 +0000548
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +0000549 return sidsoffset + (2 * sizeof(struct cifs_sid));
Steve French97837582007-12-31 07:47:21 +0000550}
551
552
Steve French630f3f0c2007-10-25 21:17:17 +0000553/*
554 change posix mode to reflect permissions
555 pmode is the existing mode (we only want to overwrite part of this
556 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
557*/
Al Viro9b5e6852007-12-05 08:24:38 +0000558static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
Shyam Prasad N0f220532020-08-17 03:23:12 -0700559 umode_t *pdenied, umode_t mask)
Steve French4879b442007-10-19 21:57:39 +0000560{
Al Viro9b5e6852007-12-05 08:24:38 +0000561 __u32 flags = le32_to_cpu(ace_flags);
Shyam Prasad N0f220532020-08-17 03:23:12 -0700562 /*
563 * Do not assume "preferred" or "canonical" order.
564 * The first DENY or ALLOW ACE which matches perfectly is
565 * the permission to be used. Once allowed or denied, same
566 * permission in later ACEs do not matter.
567 */
Steve French15b03952007-11-08 17:57:40 +0000568
Shyam Prasad N0f220532020-08-17 03:23:12 -0700569 /* If not already allowed, deny these bits */
Steve French15b03952007-11-08 17:57:40 +0000570 if (type == ACCESS_DENIED) {
Shyam Prasad N0f220532020-08-17 03:23:12 -0700571 if (flags & GENERIC_ALL &&
572 !(*pmode & mask & 0777))
573 *pdenied |= mask & 0777;
Steve Frenchad7a2922008-02-07 23:25:02 +0000574
Shyam Prasad N0f220532020-08-17 03:23:12 -0700575 if (((flags & GENERIC_WRITE) ||
576 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
577 !(*pmode & mask & 0222))
578 *pdenied |= mask & 0222;
579
580 if (((flags & GENERIC_READ) ||
581 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
582 !(*pmode & mask & 0444))
583 *pdenied |= mask & 0444;
584
585 if (((flags & GENERIC_EXECUTE) ||
586 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
587 !(*pmode & mask & 0111))
588 *pdenied |= mask & 0111;
589
Steve French15b03952007-11-08 17:57:40 +0000590 return;
591 } else if (type != ACCESS_ALLOWED) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500592 cifs_dbg(VFS, "unknown access control type %d\n", type);
Steve French15b03952007-11-08 17:57:40 +0000593 return;
594 }
595 /* else ACCESS_ALLOWED type */
Steve French44093ca2007-10-23 21:22:55 +0000596
Shyam Prasad N0f220532020-08-17 03:23:12 -0700597 if ((flags & GENERIC_ALL) &&
598 !(*pdenied & mask & 0777)) {
599 *pmode |= mask & 0777;
Joe Perchesf96637b2013-05-04 22:12:25 -0500600 cifs_dbg(NOISY, "all perms\n");
Steve Frenchd61e5802007-10-26 04:32:43 +0000601 return;
602 }
Shyam Prasad N0f220532020-08-17 03:23:12 -0700603
604 if (((flags & GENERIC_WRITE) ||
605 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
606 !(*pdenied & mask & 0222))
607 *pmode |= mask & 0222;
608
609 if (((flags & GENERIC_READ) ||
610 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
611 !(*pdenied & mask & 0444))
612 *pmode |= mask & 0444;
613
614 if (((flags & GENERIC_EXECUTE) ||
615 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
616 !(*pdenied & mask & 0111))
617 *pmode |= mask & 0111;
Steve Frenchd61e5802007-10-26 04:32:43 +0000618
Shyam Prasad Nf2156d32020-11-09 06:12:49 -0800619 /* If DELETE_CHILD is set only on an owner ACE, set sticky bit */
620 if (flags & FILE_DELETE_CHILD) {
621 if (mask == ACL_OWNER_MASK) {
622 if (!(*pdenied & 01000))
623 *pmode |= 01000;
624 } else if (!(*pdenied & 01000)) {
625 *pmode &= ~01000;
626 *pdenied |= 01000;
627 }
628 }
629
Frank Sorensonf52aa792020-02-12 15:31:48 -0600630 cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode);
Steve French630f3f0c2007-10-25 21:17:17 +0000631 return;
632}
633
Steve Frenchce06c9f2007-11-08 21:12:01 +0000634/*
635 Generate access flags to reflect permissions mode is the existing mode.
636 This function is called for every ACE in the DACL whose SID matches
637 with either owner or group or everyone.
638*/
639
640static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
641 __u32 *pace_flags)
642{
643 /* reset access mask */
644 *pace_flags = 0x0;
645
646 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
647 mode &= bits_to_use;
648
649 /* check for R/W/X UGO since we do not know whose flags
650 is this but we have cleared all the bits sans RWX for
651 either user or group or other as per bits_to_use */
652 if (mode & S_IRUGO)
653 *pace_flags |= SET_FILE_READ_RIGHTS;
654 if (mode & S_IWUGO)
655 *pace_flags |= SET_FILE_WRITE_RIGHTS;
656 if (mode & S_IXUGO)
657 *pace_flags |= SET_FILE_EXEC_RIGHTS;
658
Frank Sorensonf52aa792020-02-12 15:31:48 -0600659 cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n",
Joe Perchesf96637b2013-05-04 22:12:25 -0500660 mode, *pace_flags);
Steve Frenchce06c9f2007-11-08 21:12:01 +0000661 return;
662}
663
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +0000664static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct cifs_sid *psid)
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800665{
666 __u16 size = 1 + 1 + 2 + 4;
667
668 dst->type = src->type;
669 dst->flags = src->flags;
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800670 dst->access_req = src->access_req;
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +0000671
672 /* Check if there's a replacement sid specified */
673 if (psid)
674 size += cifs_copy_sid(&dst->sid, psid);
675 else
676 size += cifs_copy_sid(&dst->sid, &src->sid);
677
678 dst->size = cpu_to_le16(size);
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800679
680 return size;
681}
682
Al Viro2b210ad2008-03-29 03:09:18 +0000683static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
Shyam Prasad Nf2156d32020-11-09 06:12:49 -0800684 const struct cifs_sid *psid, __u64 nmode,
685 umode_t bits, __u8 access_type,
686 bool allow_delete_child)
Steve French97837582007-12-31 07:47:21 +0000687{
688 int i;
689 __u16 size = 0;
690 __u32 access_req = 0;
691
Shyam Prasad N0f220532020-08-17 03:23:12 -0700692 pntace->type = access_type;
Steve French97837582007-12-31 07:47:21 +0000693 pntace->flags = 0x0;
694 mode_to_access_flags(nmode, bits, &access_req);
Shyam Prasad Nf2156d32020-11-09 06:12:49 -0800695
696 if (access_type == ACCESS_ALLOWED && allow_delete_child)
697 access_req |= FILE_DELETE_CHILD;
698
Shyam Prasad N0f220532020-08-17 03:23:12 -0700699 if (access_type == ACCESS_ALLOWED && !access_req)
Steve French97837582007-12-31 07:47:21 +0000700 access_req = SET_MINIMUM_RIGHTS;
Shyam Prasad N0f220532020-08-17 03:23:12 -0700701 else if (access_type == ACCESS_DENIED)
702 access_req &= ~SET_MINIMUM_RIGHTS;
Shyam Prasad Nf2156d32020-11-09 06:12:49 -0800703
Steve French97837582007-12-31 07:47:21 +0000704 pntace->access_req = cpu_to_le32(access_req);
705
706 pntace->sid.revision = psid->revision;
707 pntace->sid.num_subauth = psid->num_subauth;
Jeff Layton852e2292012-11-25 08:00:36 -0500708 for (i = 0; i < NUM_AUTHS; i++)
Steve French97837582007-12-31 07:47:21 +0000709 pntace->sid.authority[i] = psid->authority[i];
710 for (i = 0; i < psid->num_subauth; i++)
711 pntace->sid.sub_auth[i] = psid->sub_auth[i];
712
713 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
714 pntace->size = cpu_to_le16(size);
715
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000716 return size;
Steve French97837582007-12-31 07:47:21 +0000717}
718
Steve French297647c2007-10-12 04:11:59 +0000719
Steve French953f8682007-10-31 04:54:42 +0000720#ifdef CONFIG_CIFS_DEBUG2
721static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000722{
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000723 int num_subauth;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000724
725 /* validate that we do not go past end of acl */
Steve French297647c2007-10-12 04:11:59 +0000726
Steve French44093ca2007-10-23 21:22:55 +0000727 if (le16_to_cpu(pace->size) < 16) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500728 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
Steve French44093ca2007-10-23 21:22:55 +0000729 return;
730 }
731
732 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500733 cifs_dbg(VFS, "ACL too small to parse ACE\n");
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000734 return;
Steve French44093ca2007-10-23 21:22:55 +0000735 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000736
Steve French44093ca2007-10-23 21:22:55 +0000737 num_subauth = pace->sid.num_subauth;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000738 if (num_subauth) {
Steve French8f18c132007-10-12 18:54:12 +0000739 int i;
Joe Perchesf96637b2013-05-04 22:12:25 -0500740 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
741 pace->sid.revision, pace->sid.num_subauth, pace->type,
742 pace->flags, le16_to_cpu(pace->size));
Steve Frenchd12fd122007-10-03 19:43:19 +0000743 for (i = 0; i < num_subauth; ++i) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500744 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
745 i, le32_to_cpu(pace->sid.sub_auth[i]));
Steve Frenchd12fd122007-10-03 19:43:19 +0000746 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000747
Steve Frenchd12fd122007-10-03 19:43:19 +0000748 /* BB add length check to make sure that we do not have huge
749 num auths and therefore go off the end */
Steve Frenchd12fd122007-10-03 19:43:19 +0000750 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000751
Steve Frenchd12fd122007-10-03 19:43:19 +0000752 return;
753}
Steve French953f8682007-10-31 04:54:42 +0000754#endif
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000755
Steve Frencha750e772007-10-17 22:50:39 +0000756static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
Steve Frenchd61e5802007-10-26 04:32:43 +0000757 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
Steve Frenche2f8fbf2019-07-19 06:30:07 +0000758 struct cifs_fattr *fattr, bool mode_from_special_sid)
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000759{
760 int i;
761 int num_aces = 0;
762 int acl_size;
763 char *acl_base;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000764 struct cifs_ace **ppace;
765
766 /* BB need to add parm so we can store the SID BB */
767
Steve French2b834572007-11-25 10:01:00 +0000768 if (!pdacl) {
769 /* no DACL in the security descriptor, set
770 all the permissions for user/group/other */
Shyam Prasad N0f220532020-08-17 03:23:12 -0700771 fattr->cf_mode |= 0777;
Steve French2b834572007-11-25 10:01:00 +0000772 return;
773 }
774
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000775 /* validate that we do not go past end of acl */
Steve Frenchaf6f4612007-10-16 18:40:37 +0000776 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500777 cifs_dbg(VFS, "ACL too small to parse DACL\n");
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000778 return;
779 }
780
Joe Perchesf96637b2013-05-04 22:12:25 -0500781 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
782 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
783 le32_to_cpu(pdacl->num_aces));
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000784
Steve French7505e052007-11-01 18:03:01 +0000785 /* reset rwx permissions for user/group/other.
786 Also, if num_aces is 0 i.e. DACL has no ACEs,
787 user/group/other have no permissions */
Shyam Prasad N0f220532020-08-17 03:23:12 -0700788 fattr->cf_mode &= ~(0777);
Steve French7505e052007-11-01 18:03:01 +0000789
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000790 acl_base = (char *)pdacl;
791 acl_size = sizeof(struct cifs_acl);
792
Steve Frenchadbc0352007-10-17 02:12:46 +0000793 num_aces = le32_to_cpu(pdacl->num_aces);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -0500794 if (num_aces > 0) {
Shyam Prasad N0f220532020-08-17 03:23:12 -0700795 umode_t denied_mode = 0;
Steve French15b03952007-11-08 17:57:40 +0000796
Dan Carpenter72501702012-01-11 10:46:27 +0300797 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
798 return;
Kees Cook6da2ec52018-06-12 13:55:00 -0700799 ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
800 GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -0500801 if (!ppace)
Stanislav Fomichev8132b652011-02-06 02:05:28 +0300802 return;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000803
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000804 for (i = 0; i < num_aces; ++i) {
Steve French44093ca2007-10-23 21:22:55 +0000805 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
Steve French953f8682007-10-31 04:54:42 +0000806#ifdef CONFIG_CIFS_DEBUG2
807 dump_ace(ppace[i], end_of_acl);
808#endif
Steve Frenche2f8fbf2019-07-19 06:30:07 +0000809 if (mode_from_special_sid &&
810 (compare_sids(&(ppace[i]->sid),
811 &sid_unix_NFS_mode) == 0)) {
812 /*
813 * Full permissions are:
814 * 07777 = S_ISUID | S_ISGID | S_ISVTX |
815 * S_IRWXU | S_IRWXG | S_IRWXO
816 */
817 fattr->cf_mode &= ~07777;
818 fattr->cf_mode |=
819 le32_to_cpu(ppace[i]->sid.sub_auth[2]);
820 break;
Shyam Prasad N0f220532020-08-17 03:23:12 -0700821 } else {
822 if (compare_sids(&(ppace[i]->sid), pownersid) == 0) {
823 access_flags_to_mode(ppace[i]->access_req,
824 ppace[i]->type,
825 &fattr->cf_mode,
826 &denied_mode,
827 ACL_OWNER_MASK);
828 } else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) {
829 access_flags_to_mode(ppace[i]->access_req,
830 ppace[i]->type,
831 &fattr->cf_mode,
832 &denied_mode,
833 ACL_GROUP_MASK);
834 } else if ((compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) ||
835 (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)) {
836 access_flags_to_mode(ppace[i]->access_req,
837 ppace[i]->type,
838 &fattr->cf_mode,
839 &denied_mode,
840 ACL_EVERYONE_MASK);
841 }
842 }
Shirish Pargaonkar2fbc2f12010-12-06 14:56:46 -0600843
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000844
Steve French44093ca2007-10-23 21:22:55 +0000845/* memcpy((void *)(&(cifscred->aces[i])),
Steve Frenchd12fd122007-10-03 19:43:19 +0000846 (void *)ppace[i],
847 sizeof(struct cifs_ace)); */
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000848
Steve French44093ca2007-10-23 21:22:55 +0000849 acl_base = (char *)ppace[i];
850 acl_size = le16_to_cpu(ppace[i]->size);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000851 }
852
853 kfree(ppace);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000854 }
855
856 return;
857}
858
Steve French643fbce2020-01-16 19:55:33 -0600859unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
860{
861 int i;
862 unsigned int ace_size = 20;
863
864 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
865 pntace->flags = 0x0;
866 pntace->access_req = cpu_to_le32(GENERIC_ALL);
867 pntace->sid.num_subauth = 1;
868 pntace->sid.revision = 1;
869 for (i = 0; i < NUM_AUTHS; i++)
870 pntace->sid.authority[i] = sid_authusers.authority[i];
871
872 pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
873
874 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
875 pntace->size = cpu_to_le16(ace_size);
876 return ace_size;
877}
878
Steve Frenchfdef6652019-12-06 02:02:38 -0600879/*
880 * Fill in the special SID based on the mode. See
Alexander A. Klimovcba22b12020-06-27 12:31:25 +0200881 * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
Steve Frenchfdef6652019-12-06 02:02:38 -0600882 */
883unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
884{
885 int i;
886 unsigned int ace_size = 28;
887
888 pntace->type = ACCESS_DENIED_ACE_TYPE;
889 pntace->flags = 0x0;
890 pntace->access_req = 0;
891 pntace->sid.num_subauth = 3;
892 pntace->sid.revision = 1;
893 for (i = 0; i < NUM_AUTHS; i++)
894 pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
895
896 pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
897 pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
898 pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
899
900 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
901 pntace->size = cpu_to_le16(ace_size);
902 return ace_size;
903}
Steve Frenchbcb02032007-09-25 16:17:24 +0000904
Steve French975221e2020-06-12 09:25:21 -0500905unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
906{
907 int i;
908 unsigned int ace_size = 28;
909
910 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
911 pntace->flags = 0x0;
912 pntace->access_req = cpu_to_le32(GENERIC_ALL);
913 pntace->sid.num_subauth = 3;
914 pntace->sid.revision = 1;
915 for (i = 0; i < NUM_AUTHS; i++)
916 pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
917
918 pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
919 pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
920 pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
921
922 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
923 pntace->size = cpu_to_le16(ace_size);
924 return ace_size;
925}
926
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800927static void populate_new_aces(char *nacl_base,
928 struct cifs_sid *pownersid,
929 struct cifs_sid *pgrpsid,
930 __u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
931 bool modefromsid)
Steve French97837582007-12-31 07:47:21 +0000932{
Shyam Prasad N0f220532020-08-17 03:23:12 -0700933 __u64 nmode;
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800934 u32 num_aces = 0;
935 u16 nsize = 0;
Shyam Prasad N0f220532020-08-17 03:23:12 -0700936 __u64 user_mode;
937 __u64 group_mode;
938 __u64 other_mode;
939 __u64 deny_user_mode = 0;
940 __u64 deny_group_mode = 0;
Shyam Prasad Nf2156d32020-11-09 06:12:49 -0800941 bool sticky_set = false;
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800942 struct cifs_ace *pnntace = NULL;
Steve French97837582007-12-31 07:47:21 +0000943
Shyam Prasad N0f220532020-08-17 03:23:12 -0700944 nmode = *pnmode;
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800945 num_aces = *pnum_aces;
946 nsize = *pnsize;
Shyam Prasad N0f220532020-08-17 03:23:12 -0700947
Steve French22442172019-07-19 08:15:55 +0000948 if (modefromsid) {
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800949 pnntace = (struct cifs_ace *) (nacl_base + nsize);
950 nsize += setup_special_mode_ACE(pnntace, nmode);
Aurelien Aptele37a02c2019-09-17 01:47:27 +0200951 num_aces++;
Shyam Prasad N0f220532020-08-17 03:23:12 -0700952 goto set_size;
Aurelien Aptele37a02c2019-09-17 01:47:27 +0200953 }
Steve French22442172019-07-19 08:15:55 +0000954
Shyam Prasad N0f220532020-08-17 03:23:12 -0700955 /*
956 * We'll try to keep the mode as requested by the user.
957 * But in cases where we cannot meaningfully convert that
958 * into ACL, return back the updated mode, so that it is
959 * updated in the inode.
960 */
961
962 if (!memcmp(pownersid, pgrpsid, sizeof(struct cifs_sid))) {
963 /*
964 * Case when owner and group SIDs are the same.
965 * Set the more restrictive of the two modes.
966 */
967 user_mode = nmode & (nmode << 3) & 0700;
968 group_mode = nmode & (nmode >> 3) & 0070;
969 } else {
970 user_mode = nmode & 0700;
971 group_mode = nmode & 0070;
972 }
973
974 other_mode = nmode & 0007;
975
976 /* We need DENY ACE when the perm is more restrictive than the next sets. */
977 deny_user_mode = ~(user_mode) & ((group_mode << 3) | (other_mode << 6)) & 0700;
978 deny_group_mode = ~(group_mode) & (other_mode << 3) & 0070;
979
980 *pnmode = user_mode | group_mode | other_mode | (nmode & ~0777);
981
Shyam Prasad Nf2156d32020-11-09 06:12:49 -0800982 /* This tells if we should allow delete child for group and everyone. */
983 if (nmode & 01000)
984 sticky_set = true;
985
Shyam Prasad N0f220532020-08-17 03:23:12 -0700986 if (deny_user_mode) {
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800987 pnntace = (struct cifs_ace *) (nacl_base + nsize);
988 nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode,
989 0700, ACCESS_DENIED, false);
Shyam Prasad N0f220532020-08-17 03:23:12 -0700990 num_aces++;
991 }
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800992
Shyam Prasad N0f220532020-08-17 03:23:12 -0700993 /* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/
994 if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) {
Shyam Prasad Nf5065502021-02-12 04:38:43 -0800995 pnntace = (struct cifs_ace *) (nacl_base + nsize);
996 nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
997 0070, ACCESS_DENIED, false);
Shyam Prasad N0f220532020-08-17 03:23:12 -0700998 num_aces++;
999 }
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001000
1001 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1002 nsize += fill_ace_for_sid(pnntace, pownersid, user_mode,
1003 0700, ACCESS_ALLOWED, true);
Shyam Prasad N0f220532020-08-17 03:23:12 -07001004 num_aces++;
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001005
Shyam Prasad N0f220532020-08-17 03:23:12 -07001006 /* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
1007 if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) {
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001008 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1009 nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
1010 0070, ACCESS_DENIED, false);
Shyam Prasad N0f220532020-08-17 03:23:12 -07001011 num_aces++;
1012 }
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001013
1014 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1015 nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode,
1016 0070, ACCESS_ALLOWED, !sticky_set);
Aurelien Aptele37a02c2019-09-17 01:47:27 +02001017 num_aces++;
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001018
1019 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1020 nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode,
1021 0007, ACCESS_ALLOWED, !sticky_set);
Aurelien Aptele37a02c2019-09-17 01:47:27 +02001022 num_aces++;
1023
Shyam Prasad N0f220532020-08-17 03:23:12 -07001024set_size:
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001025 *pnum_aces = num_aces;
1026 *pnsize = nsize;
1027}
1028
1029static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
1030 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
1031 struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid)
1032{
1033 int i;
1034 u16 size = 0;
1035 struct cifs_ace *pntace = NULL;
1036 char *acl_base = NULL;
1037 u32 src_num_aces = 0;
1038 u16 nsize = 0;
1039 struct cifs_ace *pnntace = NULL;
1040 char *nacl_base = NULL;
1041 u16 ace_size = 0;
1042
1043 acl_base = (char *)pdacl;
1044 size = sizeof(struct cifs_acl);
1045 src_num_aces = le32_to_cpu(pdacl->num_aces);
1046
1047 nacl_base = (char *)pndacl;
1048 nsize = sizeof(struct cifs_acl);
1049
1050 /* Go through all the ACEs */
1051 for (i = 0; i < src_num_aces; ++i) {
1052 pntace = (struct cifs_ace *) (acl_base + size);
1053 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1054
1055 if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001056 ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001057 else if (pngrpsid && compare_sids(&pntace->sid, pgrpsid) == 0)
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001058 ace_size = cifs_copy_ace(pnntace, pntace, pngrpsid);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001059 else
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001060 ace_size = cifs_copy_ace(pnntace, pntace, NULL);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001061
1062 size += le16_to_cpu(pntace->size);
1063 nsize += ace_size;
1064 }
1065
1066 return nsize;
1067}
1068
1069static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
1070 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
1071 __u64 *pnmode, bool mode_from_sid)
1072{
1073 int i;
1074 u16 size = 0;
1075 struct cifs_ace *pntace = NULL;
1076 char *acl_base = NULL;
1077 u32 src_num_aces = 0;
1078 u16 nsize = 0;
1079 struct cifs_ace *pnntace = NULL;
1080 char *nacl_base = NULL;
1081 u32 num_aces = 0;
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001082 bool new_aces_set = false;
1083
1084 /* Assuming that pndacl and pnmode are never NULL */
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001085 nacl_base = (char *)pndacl;
1086 nsize = sizeof(struct cifs_acl);
1087
1088 /* If pdacl is NULL, we don't have a src. Simply populate new ACL. */
1089 if (!pdacl) {
1090 populate_new_aces(nacl_base,
1091 pownersid, pgrpsid,
1092 pnmode, &num_aces, &nsize,
1093 mode_from_sid);
1094 goto finalize_dacl;
1095 }
1096
1097 acl_base = (char *)pdacl;
1098 size = sizeof(struct cifs_acl);
1099 src_num_aces = le32_to_cpu(pdacl->num_aces);
1100
1101 /* Retain old ACEs which we can retain */
1102 for (i = 0; i < src_num_aces; ++i) {
1103 pntace = (struct cifs_ace *) (acl_base + size);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001104
1105 if (!new_aces_set && (pntace->flags & INHERITED_ACE)) {
1106 /* Place the new ACEs in between existing explicit and inherited */
1107 populate_new_aces(nacl_base,
1108 pownersid, pgrpsid,
1109 pnmode, &num_aces, &nsize,
1110 mode_from_sid);
1111
1112 new_aces_set = true;
1113 }
1114
1115 /* If it's any one of the ACE we're replacing, skip! */
Shyam Prasad N3bffbe92021-03-26 10:28:16 +00001116 if (((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001117 (compare_sids(&pntace->sid, pownersid) == 0) ||
1118 (compare_sids(&pntace->sid, pgrpsid) == 0) ||
1119 (compare_sids(&pntace->sid, &sid_everyone) == 0) ||
Shyam Prasad N51713172021-03-10 10:22:27 +00001120 (compare_sids(&pntace->sid, &sid_authusers) == 0))) {
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001121 goto next_ace;
1122 }
1123
Shyam Prasad N51713172021-03-10 10:22:27 +00001124 /* update the pointer to the next ACE to populate*/
1125 pnntace = (struct cifs_ace *) (nacl_base + nsize);
1126
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001127 nsize += cifs_copy_ace(pnntace, pntace, NULL);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001128 num_aces++;
1129
1130next_ace:
Steve French23bda5e2021-02-22 14:40:43 -06001131 size += le16_to_cpu(pntace->size);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001132 }
1133
1134 /* If inherited ACEs are not present, place the new ones at the tail */
1135 if (!new_aces_set) {
1136 populate_new_aces(nacl_base,
1137 pownersid, pgrpsid,
1138 pnmode, &num_aces, &nsize,
1139 mode_from_sid);
1140
1141 new_aces_set = true;
1142 }
1143
1144finalize_dacl:
Aurelien Aptele37a02c2019-09-17 01:47:27 +02001145 pndacl->num_aces = cpu_to_le32(num_aces);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001146 pndacl->size = cpu_to_le16(nsize);
Steve French97837582007-12-31 07:47:21 +00001147
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +00001148 return 0;
Steve French97837582007-12-31 07:47:21 +00001149}
1150
Steve Frenchbcb02032007-09-25 16:17:24 +00001151static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
1152{
1153 /* BB need to add parm so we can store the SID BB */
1154
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001155 /* validate that we do not go past end of ACL - sid must be at least 8
1156 bytes long (assuming no sub-auths - e.g. the null SID */
1157 if (end_of_acl < (char *)psid + 8) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001158 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
Steve Frenchbcb02032007-09-25 16:17:24 +00001159 return -EINVAL;
1160 }
Steve Frenchbcb02032007-09-25 16:17:24 +00001161
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001162#ifdef CONFIG_CIFS_DEBUG2
Jeff Laytonfc03d8a2012-11-25 08:00:35 -05001163 if (psid->num_subauth) {
Steve French8f18c132007-10-12 18:54:12 +00001164 int i;
Joe Perchesf96637b2013-05-04 22:12:25 -05001165 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
1166 psid->revision, psid->num_subauth);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001167
Steve Frenchaf6f4612007-10-16 18:40:37 +00001168 for (i = 0; i < psid->num_subauth; i++) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001169 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
1170 i, le32_to_cpu(psid->sub_auth[i]));
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001171 }
1172
Steve Frenchd12fd122007-10-03 19:43:19 +00001173 /* BB add length check to make sure that we do not have huge
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001174 num auths and therefore go off the end */
Joe Perchesf96637b2013-05-04 22:12:25 -05001175 cifs_dbg(FYI, "RID 0x%x\n",
1176 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001177 }
Jeff Laytonfc03d8a2012-11-25 08:00:35 -05001178#endif
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001179
Steve Frenchbcb02032007-09-25 16:17:24 +00001180 return 0;
1181}
1182
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001183
Steve Frenchbcb02032007-09-25 16:17:24 +00001184/* Convert CIFS ACL to POSIX form */
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001185static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001186 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
1187 bool get_mode_from_special_sid)
Steve Frenchbcb02032007-09-25 16:17:24 +00001188{
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001189 int rc = 0;
Steve Frenchbcb02032007-09-25 16:17:24 +00001190 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1191 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
Steve Frenchbcb02032007-09-25 16:17:24 +00001192 char *end_of_acl = ((char *)pntsd) + acl_len;
Steve French7505e052007-11-01 18:03:01 +00001193 __u32 dacloffset;
Steve Frenchbcb02032007-09-25 16:17:24 +00001194
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001195 if (pntsd == NULL)
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001196 return -EIO;
1197
Steve Frenchbcb02032007-09-25 16:17:24 +00001198 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve Frenchaf6f4612007-10-16 18:40:37 +00001199 le32_to_cpu(pntsd->osidoffset));
Steve Frenchbcb02032007-09-25 16:17:24 +00001200 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve Frenchaf6f4612007-10-16 18:40:37 +00001201 le32_to_cpu(pntsd->gsidoffset));
Steve French7505e052007-11-01 18:03:01 +00001202 dacloffset = le32_to_cpu(pntsd->dacloffset);
Steve French63d25832007-11-05 21:46:10 +00001203 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
Joe Perchesf96637b2013-05-04 22:12:25 -05001204 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
Steve Frenchaf6f4612007-10-16 18:40:37 +00001205 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
1206 le32_to_cpu(pntsd->gsidoffset),
Joe Perchesb6b38f72010-04-21 03:50:45 +00001207 le32_to_cpu(pntsd->sacloffset), dacloffset);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001208/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
Steve Frenchbcb02032007-09-25 16:17:24 +00001209 rc = parse_sid(owner_sid_ptr, end_of_acl);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001210 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001211 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
Steve Frenchbcb02032007-09-25 16:17:24 +00001212 return rc;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001213 }
1214 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
1215 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001216 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
1217 __func__, rc);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001218 return rc;
1219 }
Steve Frenchbcb02032007-09-25 16:17:24 +00001220
1221 rc = parse_sid(group_sid_ptr, end_of_acl);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001222 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001223 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
1224 __func__, rc);
Steve Frenchbcb02032007-09-25 16:17:24 +00001225 return rc;
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001226 }
1227 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
1228 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001229 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
1230 __func__, rc);
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001231 return rc;
1232 }
Steve Frenchbcb02032007-09-25 16:17:24 +00001233
Steve French7505e052007-11-01 18:03:01 +00001234 if (dacloffset)
1235 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001236 group_sid_ptr, fattr, get_mode_from_special_sid);
Steve French7505e052007-11-01 18:03:01 +00001237 else
Joe Perchesf96637b2013-05-04 22:12:25 -05001238 cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +00001239
Shirish Pargaonkar9409ae52011-04-22 12:09:36 -05001240 return rc;
Steve Frenchbcb02032007-09-25 16:17:24 +00001241}
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001242
Steve French97837582007-12-31 07:47:21 +00001243/* Convert permission bits from mode to equivalent CIFS ACL */
1244static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001245 __u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid,
Steve Frencha6603392020-06-12 10:36:37 -05001246 bool mode_from_sid, bool id_from_sid, int *aclflag)
Steve French97837582007-12-31 07:47:21 +00001247{
1248 int rc = 0;
1249 __u32 dacloffset;
1250 __u32 ndacloffset;
1251 __u32 sidsoffset;
1252 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001253 struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
Steve French97837582007-12-31 07:47:21 +00001254 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
1255 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001256 char *end_of_acl = ((char *)pntsd) + secdesclen;
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001257 u16 size = 0;
1258
1259 dacloffset = le32_to_cpu(pntsd->dacloffset);
1260 if (dacloffset) {
1261 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1262 if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
Shyam Prasad Nf1ebe482021-02-24 15:04:02 +00001263 cifs_dbg(VFS, "Server returned illegal ACL size\n");
1264 return -EINVAL;
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001265 }
1266 }
1267
1268 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1269 le32_to_cpu(pntsd->osidoffset));
1270 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1271 le32_to_cpu(pntsd->gsidoffset));
Steve French97837582007-12-31 07:47:21 +00001272
Shyam Prasad N0f220532020-08-17 03:23:12 -07001273 if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001274 ndacloffset = sizeof(struct cifs_ntsd);
1275 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001276 ndacl_ptr->revision =
1277 dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
Steve French97837582007-12-31 07:47:21 +00001278
Steve French23bda5e2021-02-22 14:40:43 -06001279 ndacl_ptr->size = cpu_to_le16(0);
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001280 ndacl_ptr->num_aces = cpu_to_le32(0);
1281
1282 rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr,
Shyam Prasad N0f220532020-08-17 03:23:12 -07001283 pnmode, mode_from_sid);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001284
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001285 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001286 /* copy the non-dacl portion of secdesc */
1287 *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
1288 NULL, NULL);
1289
1290 *aclflag |= CIFS_ACL_DACL;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001291 } else {
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001292 ndacloffset = sizeof(struct cifs_ntsd);
1293 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1294 ndacl_ptr->revision =
1295 dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
Steve Frencha5628262021-06-22 17:54:50 -05001296 ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001297
Eric W. Biederman8abf2772013-02-06 00:33:17 -08001298 if (uid_valid(uid)) { /* chown */
1299 uid_t id;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001300 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1301 GFP_KERNEL);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001302 if (!nowner_sid_ptr) {
1303 rc = -ENOMEM;
1304 goto chown_chgrp_exit;
1305 }
Eric W. Biederman8abf2772013-02-06 00:33:17 -08001306 id = from_kuid(&init_user_ns, uid);
Steve Frencha6603392020-06-12 10:36:37 -05001307 if (id_from_sid) {
1308 struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
1309 /* Populate the user ownership fields S-1-5-88-1 */
1310 osid->Revision = 1;
1311 osid->NumAuth = 3;
1312 osid->Authority[5] = 5;
1313 osid->SubAuthorities[0] = cpu_to_le32(88);
1314 osid->SubAuthorities[1] = cpu_to_le32(1);
1315 osid->SubAuthorities[2] = cpu_to_le32(id);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001316
Steve Frencha6603392020-06-12 10:36:37 -05001317 } else { /* lookup sid with upcall */
1318 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
1319 if (rc) {
1320 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
1321 __func__, rc, id);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001322 goto chown_chgrp_exit;
Steve Frencha6603392020-06-12 10:36:37 -05001323 }
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001324 }
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001325 *aclflag |= CIFS_ACL_OWNER;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001326 }
Eric W. Biederman8abf2772013-02-06 00:33:17 -08001327 if (gid_valid(gid)) { /* chgrp */
1328 gid_t id;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001329 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1330 GFP_KERNEL);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001331 if (!ngroup_sid_ptr) {
1332 rc = -ENOMEM;
1333 goto chown_chgrp_exit;
1334 }
Eric W. Biederman8abf2772013-02-06 00:33:17 -08001335 id = from_kgid(&init_user_ns, gid);
Steve Frencha6603392020-06-12 10:36:37 -05001336 if (id_from_sid) {
1337 struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
1338 /* Populate the group ownership fields S-1-5-88-2 */
1339 gsid->Revision = 1;
1340 gsid->NumAuth = 3;
1341 gsid->Authority[5] = 5;
1342 gsid->SubAuthorities[0] = cpu_to_le32(88);
1343 gsid->SubAuthorities[1] = cpu_to_le32(2);
1344 gsid->SubAuthorities[2] = cpu_to_le32(id);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001345
Steve Frencha6603392020-06-12 10:36:37 -05001346 } else { /* lookup sid with upcall */
1347 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
1348 if (rc) {
1349 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
1350 __func__, rc, id);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001351 goto chown_chgrp_exit;
Steve Frencha6603392020-06-12 10:36:37 -05001352 }
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001353 }
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001354 *aclflag |= CIFS_ACL_GROUP;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001355 }
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001356
1357 if (dacloffset) {
1358 /* Replace ACEs for old owner with new one */
1359 size = replace_sids_and_copy_aces(dacl_ptr, ndacl_ptr,
1360 owner_sid_ptr, group_sid_ptr,
1361 nowner_sid_ptr, ngroup_sid_ptr);
1362 ndacl_ptr->size = cpu_to_le16(size);
1363 }
1364
1365 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1366 /* copy the non-dacl portion of secdesc */
1367 *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
1368 nowner_sid_ptr, ngroup_sid_ptr);
1369
1370chown_chgrp_exit:
1371 /* errors could jump here. So make sure we return soon after this */
1372 kfree(nowner_sid_ptr);
1373 kfree(ngroup_sid_ptr);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001374 }
Steve French97837582007-12-31 07:47:21 +00001375
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +00001376 return rc;
Steve French97837582007-12-31 07:47:21 +00001377}
1378
Steve French42eacf92014-02-10 14:08:16 -06001379struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
Boris Protopopov3970acf2020-12-18 11:30:12 -06001380 const struct cifs_fid *cifsfid, u32 *pacllen,
1381 u32 __maybe_unused unused)
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001382{
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001383 struct cifs_ntsd *pntsd = NULL;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001384 unsigned int xid;
1385 int rc;
Jeff Layton7ffec372010-09-29 19:51:11 -04001386 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1387
1388 if (IS_ERR(tlink))
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001389 return ERR_CAST(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001390
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001391 xid = get_xid();
Steve French42eacf92014-02-10 14:08:16 -06001392 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1393 pacllen);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001394 free_xid(xid);
Steve French8b1327f2008-03-14 22:37:16 +00001395
Jeff Layton7ffec372010-09-29 19:51:11 -04001396 cifs_put_tlink(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001397
Joe Perchesf96637b2013-05-04 22:12:25 -05001398 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001399 if (rc)
1400 return ERR_PTR(rc);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001401 return pntsd;
1402}
1403
1404static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1405 const char *path, u32 *pacllen)
1406{
1407 struct cifs_ntsd *pntsd = NULL;
1408 int oplock = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001409 unsigned int xid;
Amir Goldstein0f060932020-02-03 21:46:43 +02001410 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00001411 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -04001412 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001413 struct cifs_fid fid;
1414 struct cifs_open_parms oparms;
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001415
Jeff Layton7ffec372010-09-29 19:51:11 -04001416 if (IS_ERR(tlink))
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001417 return ERR_CAST(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001418
1419 tcon = tlink_tcon(tlink);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001420 xid = get_xid();
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001421
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001422 oparms.tcon = tcon;
1423 oparms.cifs_sb = cifs_sb;
1424 oparms.desired_access = READ_CONTROL;
Amir Goldstein0f060932020-02-03 21:46:43 +02001425 oparms.create_options = cifs_create_options(cifs_sb, 0);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001426 oparms.disposition = FILE_OPEN;
1427 oparms.path = path;
1428 oparms.fid = &fid;
1429 oparms.reconnect = false;
1430
1431 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001432 if (!rc) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001433 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1434 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001435 }
1436
Jeff Layton7ffec372010-09-29 19:51:11 -04001437 cifs_put_tlink(tlink);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001438 free_xid(xid);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001439
Joe Perchesf96637b2013-05-04 22:12:25 -05001440 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001441 if (rc)
1442 return ERR_PTR(rc);
Steve French7505e052007-11-01 18:03:01 +00001443 return pntsd;
1444}
1445
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001446/* Retrieve an ACL from the server */
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -06001447struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001448 struct inode *inode, const char *path,
Boris Protopopov3970acf2020-12-18 11:30:12 -06001449 u32 *pacllen, u32 info)
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001450{
1451 struct cifs_ntsd *pntsd = NULL;
1452 struct cifsFileInfo *open_file = NULL;
1453
1454 if (inode)
Jeff Layton6508d902010-09-29 19:51:11 -04001455 open_file = find_readable_file(CIFS_I(inode), true);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001456 if (!open_file)
1457 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1458
Boris Protopopov3970acf2020-12-18 11:30:12 -06001459 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001460 cifsFileInfo_put(open_file);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001461 return pntsd;
1462}
1463
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001464 /* Set an ACL on the server */
1465int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1466 struct inode *inode, const char *path, int aclflag)
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001467{
1468 int oplock = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001469 unsigned int xid;
Amir Goldstein0f060932020-02-03 21:46:43 +02001470 int rc, access_flags;
Steve French96daf2b2011-05-27 04:34:02 +00001471 struct cifs_tcon *tcon;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001472 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001473 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001474 struct cifs_fid fid;
1475 struct cifs_open_parms oparms;
Steve French97837582007-12-31 07:47:21 +00001476
Jeff Layton7ffec372010-09-29 19:51:11 -04001477 if (IS_ERR(tlink))
1478 return PTR_ERR(tlink);
1479
1480 tcon = tlink_tcon(tlink);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001481 xid = get_xid();
Steve French97837582007-12-31 07:47:21 +00001482
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001483 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1484 access_flags = WRITE_OWNER;
1485 else
1486 access_flags = WRITE_DAC;
1487
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001488 oparms.tcon = tcon;
1489 oparms.cifs_sb = cifs_sb;
1490 oparms.desired_access = access_flags;
Amir Goldstein0f060932020-02-03 21:46:43 +02001491 oparms.create_options = cifs_create_options(cifs_sb, 0);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001492 oparms.disposition = FILE_OPEN;
1493 oparms.path = path;
1494 oparms.fid = &fid;
1495 oparms.reconnect = false;
1496
1497 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001498 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001499 cifs_dbg(VFS, "Unable to open file to set ACL\n");
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001500 goto out;
Steve French97837582007-12-31 07:47:21 +00001501 }
1502
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001503 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
Joe Perchesf96637b2013-05-04 22:12:25 -05001504 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
Steve French97837582007-12-31 07:47:21 +00001505
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001506 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001507out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001508 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001509 cifs_put_tlink(tlink);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -04001510 return rc;
1511}
Steve French97837582007-12-31 07:47:21 +00001512
Achilles Gaikwad36c7ce42018-01-28 13:39:48 +05301513/* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001514int
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001515cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001516 struct inode *inode, bool mode_from_special_sid,
1517 const char *path, const struct cifs_fid *pfid)
Steve French7505e052007-11-01 18:03:01 +00001518{
1519 struct cifs_ntsd *pntsd = NULL;
1520 u32 acllen = 0;
1521 int rc = 0;
Steve French42eacf92014-02-10 14:08:16 -06001522 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Joe Perches via samba-technicalecdcf622017-05-07 01:31:47 -07001523 struct smb_version_operations *ops;
Boris Protopopov3970acf2020-12-18 11:30:12 -06001524 const u32 info = 0;
Steve French7505e052007-11-01 18:03:01 +00001525
Joe Perchesf96637b2013-05-04 22:12:25 -05001526 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
Christoph Hellwig1bf40722009-05-27 09:37:33 -04001527
Steve French42eacf92014-02-10 14:08:16 -06001528 if (IS_ERR(tlink))
1529 return PTR_ERR(tlink);
Steve French7505e052007-11-01 18:03:01 +00001530
Joe Perches via samba-technicalecdcf622017-05-07 01:31:47 -07001531 ops = tlink_tcon(tlink)->ses->server->ops;
1532
1533 if (pfid && (ops->get_acl_by_fid))
Boris Protopopov3970acf2020-12-18 11:30:12 -06001534 pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen, info);
Joe Perches via samba-technicalecdcf622017-05-07 01:31:47 -07001535 else if (ops->get_acl)
Boris Protopopov3970acf2020-12-18 11:30:12 -06001536 pntsd = ops->get_acl(cifs_sb, inode, path, &acllen, info);
Steve French42eacf92014-02-10 14:08:16 -06001537 else {
1538 cifs_put_tlink(tlink);
1539 return -EOPNOTSUPP;
1540 }
Steve French7505e052007-11-01 18:03:01 +00001541 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001542 if (IS_ERR(pntsd)) {
1543 rc = PTR_ERR(pntsd);
Joe Perchesf96637b2013-05-04 22:12:25 -05001544 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001545 } else if (mode_from_special_sid) {
1546 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
Namjae Jeon98128572020-11-09 17:35:33 +09001547 kfree(pntsd);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001548 } else {
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001549 /* get approximated mode from ACL */
1550 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001551 kfree(pntsd);
1552 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001553 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001554 }
Steve French7505e052007-11-01 18:03:01 +00001555
Steve French42eacf92014-02-10 14:08:16 -06001556 cifs_put_tlink(tlink);
1557
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001558 return rc;
Steve Frenchb9c7a2b2007-10-26 23:40:20 +00001559}
Steve French953f8682007-10-31 04:54:42 +00001560
Steve French7505e052007-11-01 18:03:01 +00001561/* Convert mode bits to an ACL so we can update the ACL on the server */
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001562int
Shyam Prasad N0f220532020-08-17 03:23:12 -07001563id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08001564 kuid_t uid, kgid_t gid)
Steve French953f8682007-10-31 04:54:42 +00001565{
1566 int rc = 0;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05001567 int aclflag = CIFS_ACL_DACL; /* default flag to set */
Steve Frenchcce246e2008-04-09 20:55:31 +00001568 __u32 secdesclen = 0;
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001569 __u32 nsecdesclen = 0;
1570 __u32 dacloffset = 0;
1571 struct cifs_acl *dacl_ptr = NULL;
Steve French97837582007-12-31 07:47:21 +00001572 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1573 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
Steve French83e3bc22014-02-02 23:31:47 -06001574 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1575 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Joe Perches via samba-technicalecdcf622017-05-07 01:31:47 -07001576 struct smb_version_operations *ops;
Steve Frencha6603392020-06-12 10:36:37 -05001577 bool mode_from_sid, id_from_sid;
Boris Protopopov3970acf2020-12-18 11:30:12 -06001578 const u32 info = 0;
Steve French83e3bc22014-02-02 23:31:47 -06001579
1580 if (IS_ERR(tlink))
1581 return PTR_ERR(tlink);
Joe Perches via samba-technicalecdcf622017-05-07 01:31:47 -07001582
1583 ops = tlink_tcon(tlink)->ses->server->ops;
Steve French953f8682007-10-31 04:54:42 +00001584
Joe Perchesf96637b2013-05-04 22:12:25 -05001585 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
Steve French953f8682007-10-31 04:54:42 +00001586
1587 /* Get the security descriptor */
Steve French83e3bc22014-02-02 23:31:47 -06001588
Joe Perches via samba-technicalecdcf622017-05-07 01:31:47 -07001589 if (ops->get_acl == NULL) {
Steve French83e3bc22014-02-02 23:31:47 -06001590 cifs_put_tlink(tlink);
1591 return -EOPNOTSUPP;
1592 }
1593
Boris Protopopov3970acf2020-12-18 11:30:12 -06001594 pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen, info);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -06001595 if (IS_ERR(pntsd)) {
1596 rc = PTR_ERR(pntsd);
Joe Perchesf96637b2013-05-04 22:12:25 -05001597 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
Steve French83e3bc22014-02-02 23:31:47 -06001598 cifs_put_tlink(tlink);
1599 return rc;
Steve French97837582007-12-31 07:47:21 +00001600 }
1601
Steve French22442172019-07-19 08:15:55 +00001602 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
1603 mode_from_sid = true;
1604 else
1605 mode_from_sid = false;
1606
Steve Frencha6603392020-06-12 10:36:37 -05001607 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
1608 id_from_sid = true;
1609 else
1610 id_from_sid = false;
1611
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001612 /* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */
1613 nsecdesclen = secdesclen;
1614 if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
1615 if (mode_from_sid)
1616 nsecdesclen += sizeof(struct cifs_ace);
1617 else /* cifsacl */
1618 nsecdesclen += 5 * sizeof(struct cifs_ace);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001619 } else { /* chown */
1620 /* When ownership changes, changes new owner sid length could be different */
1621 nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2);
1622 dacloffset = le32_to_cpu(pntsd->dacloffset);
1623 if (dacloffset) {
1624 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1625 if (mode_from_sid)
1626 nsecdesclen +=
Steve French23bda5e2021-02-22 14:40:43 -06001627 le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace);
Shyam Prasad Nbc3e9dd2021-02-18 13:03:23 +00001628 else /* cifsacl */
1629 nsecdesclen += le16_to_cpu(dacl_ptr->size);
1630 }
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001631 }
1632
1633 /*
1634 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1635 * as chmod disables ACEs and set the security descriptor. Allocate
1636 * memory for the smb header, set security descriptor request security
jack1.li_cpc45adff2021-04-09 22:00:37 -05001637 * descriptor parameters, and security descriptor itself
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001638 */
1639 nsecdesclen = max_t(u32, nsecdesclen, DEFAULT_SEC_DESC_LEN);
1640 pnntsd = kmalloc(nsecdesclen, GFP_KERNEL);
1641 if (!pnntsd) {
1642 kfree(pntsd);
1643 cifs_put_tlink(tlink);
1644 return -ENOMEM;
1645 }
1646
1647 rc = build_sec_desc(pntsd, pnntsd, secdesclen, &nsecdesclen, pnmode, uid, gid,
Steve Frencha6603392020-06-12 10:36:37 -05001648 mode_from_sid, id_from_sid, &aclflag);
Jeff Laytonc78cd832012-11-25 08:00:35 -05001649
Joe Perchesf96637b2013-05-04 22:12:25 -05001650 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
Jeff Laytonc78cd832012-11-25 08:00:35 -05001651
Joe Perches via samba-technicalecdcf622017-05-07 01:31:47 -07001652 if (ops->set_acl == NULL)
Steve French83e3bc22014-02-02 23:31:47 -06001653 rc = -EOPNOTSUPP;
1654
Jeff Laytonc78cd832012-11-25 08:00:35 -05001655 if (!rc) {
1656 /* Set the security descriptor */
Shyam Prasad Nf5065502021-02-12 04:38:43 -08001657 rc = ops->set_acl(pnntsd, nsecdesclen, inode, path, aclflag);
Joe Perchesf96637b2013-05-04 22:12:25 -05001658 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
Jeff Laytonc78cd832012-11-25 08:00:35 -05001659 }
Steve French83e3bc22014-02-02 23:31:47 -06001660 cifs_put_tlink(tlink);
Jeff Laytonc78cd832012-11-25 08:00:35 -05001661
1662 kfree(pnntsd);
1663 kfree(pntsd);
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +00001664 return rc;
Steve French953f8682007-10-31 04:54:42 +00001665}