blob: d385c7045cc04e6f31d1856d1ec7e538f23c99e7 [file] [log] [blame]
Namjae Jeone2f34482021-03-16 10:49:09 +09001// SPDX-License-Identifier: LGPL-2.1+
2/*
3 * Copyright (C) International Business Machines Corp., 2007,2008
4 * Author(s): Steve French (sfrench@us.ibm.com)
5 * Copyright (C) 2020 Samsung Electronics Co., Ltd.
6 * Author(s): Namjae Jeon <linkinjeon@kernel.org>
7 */
8
9#include <linux/fs.h>
10#include <linux/slab.h>
11#include <linux/string.h>
12
13#include "smbacl.h"
14#include "smb_common.h"
15#include "server.h"
16#include "misc.h"
Namjae Jeone2f34482021-03-16 10:49:09 +090017#include "mgmt/share_config.h"
18
19static const struct smb_sid domain = {1, 4, {0, 0, 0, 0, 0, 5},
20 {cpu_to_le32(21), cpu_to_le32(1), cpu_to_le32(2), cpu_to_le32(3),
21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
22
23/* security id for everyone/world system group */
24static const struct smb_sid creator_owner = {
25 1, 1, {0, 0, 0, 0, 0, 3}, {0} };
26/* security id for everyone/world system group */
27static const struct smb_sid creator_group = {
28 1, 1, {0, 0, 0, 0, 0, 3}, {cpu_to_le32(1)} };
29
30/* security id for everyone/world system group */
31static const struct smb_sid sid_everyone = {
32 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
33/* security id for Authenticated Users system group */
34static const struct smb_sid sid_authusers = {
35 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
36
37/* S-1-22-1 Unmapped Unix users */
38static const struct smb_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
39 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
40
41/* S-1-22-2 Unmapped Unix groups */
42static const struct smb_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
43 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
44
45/*
46 * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
47 */
48
49/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
50
51/* S-1-5-88-1 Unix uid */
52static const struct smb_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
53 {cpu_to_le32(88),
54 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
55
56/* S-1-5-88-2 Unix gid */
57static const struct smb_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
58 {cpu_to_le32(88),
59 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
60
61/* S-1-5-88-3 Unix mode */
62static const struct smb_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
63 {cpu_to_le32(88),
64 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
65
66/*
67 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
68 * the same returns zero, if they do not match returns non-zero.
69 */
Namjae Jeon64b39f42021-03-30 14:25:35 +090070int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid)
Namjae Jeone2f34482021-03-16 10:49:09 +090071{
72 int i;
73 int num_subauth, num_sat, num_saw;
74
Namjae Jeon64b39f42021-03-30 14:25:35 +090075 if (!ctsid || !cwsid)
Namjae Jeone2f34482021-03-16 10:49:09 +090076 return 1;
77
78 /* compare the revision */
79 if (ctsid->revision != cwsid->revision) {
80 if (ctsid->revision > cwsid->revision)
81 return 1;
82 else
83 return -1;
84 }
85
86 /* compare all of the six auth values */
87 for (i = 0; i < NUM_AUTHS; ++i) {
88 if (ctsid->authority[i] != cwsid->authority[i]) {
89 if (ctsid->authority[i] > cwsid->authority[i])
90 return 1;
91 else
92 return -1;
93 }
94 }
95
96 /* compare all of the subauth values if any */
97 num_sat = ctsid->num_subauth;
98 num_saw = cwsid->num_subauth;
99 num_subauth = num_sat < num_saw ? num_sat : num_saw;
100 if (num_subauth) {
101 for (i = 0; i < num_subauth; ++i) {
102 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
103 if (le32_to_cpu(ctsid->sub_auth[i]) >
Namjae Jeon64b39f42021-03-30 14:25:35 +0900104 le32_to_cpu(cwsid->sub_auth[i]))
Namjae Jeone2f34482021-03-16 10:49:09 +0900105 return 1;
106 else
107 return -1;
108 }
109 }
110 }
111
112 return 0; /* sids compare/match */
113}
114
Namjae Jeon64b39f42021-03-30 14:25:35 +0900115static void smb_copy_sid(struct smb_sid *dst, const struct smb_sid *src)
Namjae Jeone2f34482021-03-16 10:49:09 +0900116{
117 int i;
118
119 dst->revision = src->revision;
120 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
121 for (i = 0; i < NUM_AUTHS; ++i)
122 dst->authority[i] = src->authority[i];
123 for (i = 0; i < dst->num_subauth; ++i)
124 dst->sub_auth[i] = src->sub_auth[i];
125}
126
127/*
128 * change posix mode to reflect permissions
129 * pmode is the existing mode (we only want to overwrite part of this
130 * bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
131 */
132static umode_t access_flags_to_mode(struct smb_fattr *fattr, __le32 ace_flags,
Namjae Jeon070fb212021-05-26 17:57:12 +0900133 int type)
Namjae Jeone2f34482021-03-16 10:49:09 +0900134{
135 __u32 flags = le32_to_cpu(ace_flags);
136 umode_t mode = 0;
137
138 if (flags & GENERIC_ALL) {
139 mode = 0777;
140 ksmbd_debug(SMB, "all perms\n");
141 return mode;
142 }
143
Namjae Jeon64b39f42021-03-30 14:25:35 +0900144 if ((flags & GENERIC_READ) || (flags & FILE_READ_RIGHTS))
Namjae Jeone2f34482021-03-16 10:49:09 +0900145 mode = 0444;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900146 if ((flags & GENERIC_WRITE) || (flags & FILE_WRITE_RIGHTS)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900147 mode |= 0222;
148 if (S_ISDIR(fattr->cf_mode))
149 mode |= 0111;
150 }
Namjae Jeon64b39f42021-03-30 14:25:35 +0900151 if ((flags & GENERIC_EXECUTE) || (flags & FILE_EXEC_RIGHTS))
Namjae Jeone2f34482021-03-16 10:49:09 +0900152 mode |= 0111;
153
Namjae Jeon64b39f42021-03-30 14:25:35 +0900154 if (type == ACCESS_DENIED_ACE_TYPE || type == ACCESS_DENIED_OBJECT_ACE_TYPE)
Namjae Jeone2f34482021-03-16 10:49:09 +0900155 mode = ~mode;
156
157 ksmbd_debug(SMB, "access flags 0x%x mode now %04o\n", flags, mode);
158
159 return mode;
160}
161
162/*
163 * Generate access flags to reflect permissions mode is the existing mode.
164 * This function is called for every ACE in the DACL whose SID matches
165 * with either owner or group or everyone.
166 */
167static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
Namjae Jeon070fb212021-05-26 17:57:12 +0900168 __u32 *pace_flags)
Namjae Jeone2f34482021-03-16 10:49:09 +0900169{
170 /* reset access mask */
171 *pace_flags = 0x0;
172
173 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
174 mode &= bits_to_use;
175
176 /*
177 * check for R/W/X UGO since we do not know whose flags
178 * is this but we have cleared all the bits sans RWX for
179 * either user or group or other as per bits_to_use
180 */
181 if (mode & 0444)
182 *pace_flags |= SET_FILE_READ_RIGHTS;
183 if (mode & 0222)
184 *pace_flags |= FILE_WRITE_RIGHTS;
185 if (mode & 0111)
186 *pace_flags |= SET_FILE_EXEC_RIGHTS;
187
188 ksmbd_debug(SMB, "mode: %o, access flags now 0x%x\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900189 mode, *pace_flags);
Namjae Jeone2f34482021-03-16 10:49:09 +0900190}
191
192static __u16 fill_ace_for_sid(struct smb_ace *pntace,
Namjae Jeon070fb212021-05-26 17:57:12 +0900193 const struct smb_sid *psid, int type, int flags,
194 umode_t mode, umode_t bits)
Namjae Jeone2f34482021-03-16 10:49:09 +0900195{
196 int i;
197 __u16 size = 0;
198 __u32 access_req = 0;
199
200 pntace->type = type;
201 pntace->flags = flags;
202 mode_to_access_flags(mode, bits, &access_req);
203 if (!access_req)
204 access_req = SET_MINIMUM_RIGHTS;
205 pntace->access_req = cpu_to_le32(access_req);
206
207 pntace->sid.revision = psid->revision;
208 pntace->sid.num_subauth = psid->num_subauth;
209 for (i = 0; i < NUM_AUTHS; i++)
210 pntace->sid.authority[i] = psid->authority[i];
211 for (i = 0; i < psid->num_subauth; i++)
212 pntace->sid.sub_auth[i] = psid->sub_auth[i];
213
214 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
215 pntace->size = cpu_to_le16(size);
216
217 return size;
218}
219
220void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
221{
222 switch (sidtype) {
223 case SIDOWNER:
224 smb_copy_sid(ssid, &server_conf.domain_sid);
225 break;
226 case SIDUNIX_USER:
227 smb_copy_sid(ssid, &sid_unix_users);
228 break;
229 case SIDUNIX_GROUP:
230 smb_copy_sid(ssid, &sid_unix_groups);
231 break;
232 case SIDCREATOR_OWNER:
233 smb_copy_sid(ssid, &creator_owner);
234 return;
235 case SIDCREATOR_GROUP:
236 smb_copy_sid(ssid, &creator_group);
237 return;
238 case SIDNFS_USER:
239 smb_copy_sid(ssid, &sid_unix_NFS_users);
240 break;
241 case SIDNFS_GROUP:
242 smb_copy_sid(ssid, &sid_unix_NFS_groups);
243 break;
244 case SIDNFS_MODE:
245 smb_copy_sid(ssid, &sid_unix_NFS_mode);
246 break;
247 default:
248 return;
249 }
250
251 /* RID */
252 ssid->sub_auth[ssid->num_subauth] = cpu_to_le32(cid);
253 ssid->num_subauth++;
254}
255
256static int sid_to_id(struct smb_sid *psid, uint sidtype,
Namjae Jeon070fb212021-05-26 17:57:12 +0900257 struct smb_fattr *fattr)
Namjae Jeone2f34482021-03-16 10:49:09 +0900258{
259 int rc = -EINVAL;
260
261 /*
262 * If we have too many subauthorities, then something is really wrong.
263 * Just return an error.
264 */
265 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900266 pr_err("%s: %u subauthorities is too many!\n",
267 __func__, psid->num_subauth);
Namjae Jeone2f34482021-03-16 10:49:09 +0900268 return -EIO;
269 }
270
271 if (sidtype == SIDOWNER) {
272 kuid_t uid;
273 uid_t id;
274
275 id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
276 if (id > 0) {
277 uid = make_kuid(&init_user_ns, id);
Namjae Jeon64b39f42021-03-30 14:25:35 +0900278 if (uid_valid(uid) && kuid_has_mapping(&init_user_ns, uid)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900279 fattr->cf_uid = uid;
280 rc = 0;
281 }
282 }
283 } else {
284 kgid_t gid;
285 gid_t id;
286
287 id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
288 if (id > 0) {
289 gid = make_kgid(&init_user_ns, id);
Namjae Jeon64b39f42021-03-30 14:25:35 +0900290 if (gid_valid(gid) && kgid_has_mapping(&init_user_ns, gid)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900291 fattr->cf_gid = gid;
292 rc = 0;
293 }
294 }
295 }
296
297 return rc;
298}
299
300void posix_state_to_acl(struct posix_acl_state *state,
Namjae Jeon070fb212021-05-26 17:57:12 +0900301 struct posix_acl_entry *pace)
Namjae Jeone2f34482021-03-16 10:49:09 +0900302{
303 int i;
304
305 pace->e_tag = ACL_USER_OBJ;
306 pace->e_perm = state->owner.allow;
307 for (i = 0; i < state->users->n; i++) {
308 pace++;
309 pace->e_tag = ACL_USER;
310 pace->e_uid = state->users->aces[i].uid;
311 pace->e_perm = state->users->aces[i].perms.allow;
312 }
313
314 pace++;
315 pace->e_tag = ACL_GROUP_OBJ;
316 pace->e_perm = state->group.allow;
317
318 for (i = 0; i < state->groups->n; i++) {
319 pace++;
320 pace->e_tag = ACL_GROUP;
321 pace->e_gid = state->groups->aces[i].gid;
322 pace->e_perm = state->groups->aces[i].perms.allow;
323 }
324
325 if (state->users->n || state->groups->n) {
326 pace++;
327 pace->e_tag = ACL_MASK;
328 pace->e_perm = state->mask.allow;
329 }
330
331 pace++;
332 pace->e_tag = ACL_OTHER;
333 pace->e_perm = state->other.allow;
334}
335
336int init_acl_state(struct posix_acl_state *state, int cnt)
337{
338 int alloc;
339
340 memset(state, 0, sizeof(struct posix_acl_state));
341 /*
342 * In the worst case, each individual acl could be for a distinct
343 * named user or group, but we don't know which, so we allocate
344 * enough space for either:
345 */
346 alloc = sizeof(struct posix_ace_state_array)
Namjae Jeon64b39f42021-03-30 14:25:35 +0900347 + cnt * sizeof(struct posix_user_ace_state);
Namjae Jeone2f34482021-03-16 10:49:09 +0900348 state->users = kzalloc(alloc, GFP_KERNEL);
349 if (!state->users)
350 return -ENOMEM;
351 state->groups = kzalloc(alloc, GFP_KERNEL);
352 if (!state->groups) {
353 kfree(state->users);
354 return -ENOMEM;
355 }
356 return 0;
357}
358
359void free_acl_state(struct posix_acl_state *state)
360{
361 kfree(state->users);
362 kfree(state->groups);
363}
364
365static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
Namjae Jeon070fb212021-05-26 17:57:12 +0900366 struct smb_sid *pownersid, struct smb_sid *pgrpsid,
367 struct smb_fattr *fattr)
Namjae Jeone2f34482021-03-16 10:49:09 +0900368{
369 int i, ret;
370 int num_aces = 0;
371 int acl_size;
372 char *acl_base;
373 struct smb_ace **ppace;
374 struct posix_acl_entry *cf_pace, *cf_pdace;
375 struct posix_acl_state acl_state, default_acl_state;
376 umode_t mode = 0, acl_mode;
377 bool owner_found = false, group_found = false, others_found = false;
378
379 if (!pdacl)
380 return;
381
382 /* validate that we do not go past end of acl */
Namjae Jeon548e9ad2021-03-21 17:30:49 +0900383 if (end_of_acl <= (char *)pdacl ||
384 end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900385 pr_err("ACL too small to parse DACL\n");
Namjae Jeone2f34482021-03-16 10:49:09 +0900386 return;
387 }
388
389 ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900390 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
391 le32_to_cpu(pdacl->num_aces));
Namjae Jeone2f34482021-03-16 10:49:09 +0900392
393 acl_base = (char *)pdacl;
394 acl_size = sizeof(struct smb_acl);
395
396 num_aces = le32_to_cpu(pdacl->num_aces);
397 if (num_aces <= 0)
398 return;
399
400 if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
401 return;
402
Namjae Jeon070fb212021-05-26 17:57:12 +0900403 ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL);
Namjae Jeone2f34482021-03-16 10:49:09 +0900404 if (!ppace)
405 return;
406
407 ret = init_acl_state(&acl_state, num_aces);
408 if (ret)
409 return;
410 ret = init_acl_state(&default_acl_state, num_aces);
411 if (ret) {
412 free_acl_state(&acl_state);
413 return;
414 }
415
416 /*
417 * reset rwx permissions for user/group/other.
418 * Also, if num_aces is 0 i.e. DACL has no ACEs,
419 * user/group/other have no permissions
420 */
421 for (i = 0; i < num_aces; ++i) {
Namjae Jeon64b39f42021-03-30 14:25:35 +0900422 ppace[i] = (struct smb_ace *)(acl_base + acl_size);
Namjae Jeone2f34482021-03-16 10:49:09 +0900423 acl_base = (char *)ppace[i];
424 acl_size = le16_to_cpu(ppace[i]->size);
425 ppace[i]->access_req =
426 smb_map_generic_desired_access(ppace[i]->access_req);
427
Namjae Jeon64b39f42021-03-30 14:25:35 +0900428 if (!(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900429 fattr->cf_mode =
430 le32_to_cpu(ppace[i]->sid.sub_auth[2]);
431 break;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900432 } else if (!compare_sids(&ppace[i]->sid, pownersid)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900433 acl_mode = access_flags_to_mode(fattr,
Namjae Jeon070fb212021-05-26 17:57:12 +0900434 ppace[i]->access_req,
435 ppace[i]->type);
Namjae Jeone2f34482021-03-16 10:49:09 +0900436 acl_mode &= 0700;
437
438 if (!owner_found) {
439 mode &= ~(0700);
440 mode |= acl_mode;
441 }
442 owner_found = true;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900443 } else if (!compare_sids(&ppace[i]->sid, pgrpsid) ||
444 ppace[i]->sid.sub_auth[ppace[i]->sid.num_subauth - 1] ==
445 DOMAIN_USER_RID_LE) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900446 acl_mode = access_flags_to_mode(fattr,
Namjae Jeon070fb212021-05-26 17:57:12 +0900447 ppace[i]->access_req,
448 ppace[i]->type);
Namjae Jeone2f34482021-03-16 10:49:09 +0900449 acl_mode &= 0070;
450 if (!group_found) {
451 mode &= ~(0070);
452 mode |= acl_mode;
453 }
454 group_found = true;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900455 } else if (!compare_sids(&ppace[i]->sid, &sid_everyone)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900456 acl_mode = access_flags_to_mode(fattr,
Namjae Jeon070fb212021-05-26 17:57:12 +0900457 ppace[i]->access_req,
458 ppace[i]->type);
Namjae Jeone2f34482021-03-16 10:49:09 +0900459 acl_mode &= 0007;
460 if (!others_found) {
461 mode &= ~(0007);
462 mode |= acl_mode;
463 }
464 others_found = true;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900465 } else if (!compare_sids(&ppace[i]->sid, &creator_owner)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900466 continue;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900467 } else if (!compare_sids(&ppace[i]->sid, &creator_group)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900468 continue;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900469 } else if (!compare_sids(&ppace[i]->sid, &sid_authusers)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900470 continue;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900471 } else {
Namjae Jeone2f34482021-03-16 10:49:09 +0900472 struct smb_fattr temp_fattr;
473
474 acl_mode = access_flags_to_mode(fattr, ppace[i]->access_req,
Namjae Jeon070fb212021-05-26 17:57:12 +0900475 ppace[i]->type);
Namjae Jeone2f34482021-03-16 10:49:09 +0900476 temp_fattr.cf_uid = INVALID_UID;
477 ret = sid_to_id(&ppace[i]->sid, SIDOWNER, &temp_fattr);
478 if (ret || uid_eq(temp_fattr.cf_uid, INVALID_UID)) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900479 pr_err("%s: Error %d mapping Owner SID to uid\n",
480 __func__, ret);
Namjae Jeone2f34482021-03-16 10:49:09 +0900481 continue;
482 }
483
484 acl_state.owner.allow = ((acl_mode & 0700) >> 6) | 0004;
485 acl_state.users->aces[acl_state.users->n].uid =
486 temp_fattr.cf_uid;
487 acl_state.users->aces[acl_state.users->n++].perms.allow =
488 ((acl_mode & 0700) >> 6) | 0004;
489 default_acl_state.owner.allow = ((acl_mode & 0700) >> 6) | 0004;
490 default_acl_state.users->aces[default_acl_state.users->n].uid =
491 temp_fattr.cf_uid;
492 default_acl_state.users->aces[default_acl_state.users->n++].perms.allow =
493 ((acl_mode & 0700) >> 6) | 0004;
494 }
495 }
496 kfree(ppace);
497
498 if (owner_found) {
499 /* The owner must be set to at least read-only. */
500 acl_state.owner.allow = ((mode & 0700) >> 6) | 0004;
501 acl_state.users->aces[acl_state.users->n].uid = fattr->cf_uid;
502 acl_state.users->aces[acl_state.users->n++].perms.allow =
503 ((mode & 0700) >> 6) | 0004;
504 default_acl_state.owner.allow = ((mode & 0700) >> 6) | 0004;
505 default_acl_state.users->aces[default_acl_state.users->n].uid =
506 fattr->cf_uid;
507 default_acl_state.users->aces[default_acl_state.users->n++].perms.allow =
508 ((mode & 0700) >> 6) | 0004;
509 }
510
511 if (group_found) {
512 acl_state.group.allow = (mode & 0070) >> 3;
513 acl_state.groups->aces[acl_state.groups->n].gid =
514 fattr->cf_gid;
515 acl_state.groups->aces[acl_state.groups->n++].perms.allow =
516 (mode & 0070) >> 3;
Dan Carpenter86df49e2021-03-18 16:10:21 +0300517 default_acl_state.group.allow = (mode & 0070) >> 3;
Namjae Jeone2f34482021-03-16 10:49:09 +0900518 default_acl_state.groups->aces[default_acl_state.groups->n].gid =
519 fattr->cf_gid;
520 default_acl_state.groups->aces[default_acl_state.groups->n++].perms.allow =
521 (mode & 0070) >> 3;
522 }
523
524 if (others_found) {
525 fattr->cf_mode &= ~(0007);
526 fattr->cf_mode |= mode & 0007;
527
528 acl_state.other.allow = mode & 0007;
529 default_acl_state.other.allow = mode & 0007;
530 }
531
532 if (acl_state.users->n || acl_state.groups->n) {
533 acl_state.mask.allow = 0x07;
Namjae Jeon67d1c432021-06-22 11:42:29 +0900534 fattr->cf_acls = posix_acl_alloc(acl_state.users->n +
Namjae Jeone2f34482021-03-16 10:49:09 +0900535 acl_state.groups->n + 4, GFP_KERNEL);
536 if (fattr->cf_acls) {
537 cf_pace = fattr->cf_acls->a_entries;
538 posix_state_to_acl(&acl_state, cf_pace);
539 }
540 }
541
542 if (default_acl_state.users->n || default_acl_state.groups->n) {
543 default_acl_state.mask.allow = 0x07;
544 fattr->cf_dacls =
Namjae Jeon67d1c432021-06-22 11:42:29 +0900545 posix_acl_alloc(default_acl_state.users->n +
Namjae Jeone2f34482021-03-16 10:49:09 +0900546 default_acl_state.groups->n + 4, GFP_KERNEL);
547 if (fattr->cf_dacls) {
548 cf_pdace = fattr->cf_dacls->a_entries;
549 posix_state_to_acl(&default_acl_state, cf_pdace);
550 }
551 }
552 free_acl_state(&acl_state);
553 free_acl_state(&default_acl_state);
554}
555
556static void set_posix_acl_entries_dacl(struct smb_ace *pndace,
Namjae Jeon070fb212021-05-26 17:57:12 +0900557 struct smb_fattr *fattr, u32 *num_aces,
558 u16 *size, u32 nt_aces_num)
Namjae Jeone2f34482021-03-16 10:49:09 +0900559{
560 struct posix_acl_entry *pace;
561 struct smb_sid *sid;
562 struct smb_ace *ntace;
563 int i, j;
564
565 if (!fattr->cf_acls)
566 goto posix_default_acl;
567
568 pace = fattr->cf_acls->a_entries;
569 for (i = 0; i < fattr->cf_acls->a_count; i++, pace++) {
570 int flags = 0;
571
572 sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
573 if (!sid)
574 break;
575
576 if (pace->e_tag == ACL_USER) {
577 uid_t uid;
578 unsigned int sid_type = SIDOWNER;
579
580 uid = from_kuid(&init_user_ns, pace->e_uid);
581 if (!uid)
582 sid_type = SIDUNIX_USER;
583 id_to_sid(uid, sid_type, sid);
584 } else if (pace->e_tag == ACL_GROUP) {
585 gid_t gid;
586
587 gid = from_kgid(&init_user_ns, pace->e_gid);
588 id_to_sid(gid, SIDUNIX_GROUP, sid);
589 } else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
590 smb_copy_sid(sid, &sid_everyone);
591 } else {
592 kfree(sid);
593 continue;
594 }
595 ntace = pndace;
596 for (j = 0; j < nt_aces_num; j++) {
597 if (ntace->sid.sub_auth[ntace->sid.num_subauth - 1] ==
598 sid->sub_auth[sid->num_subauth - 1])
599 goto pass_same_sid;
600 ntace = (struct smb_ace *)((char *)ntace +
601 le16_to_cpu(ntace->size));
602 }
603
604 if (S_ISDIR(fattr->cf_mode) && pace->e_tag == ACL_OTHER)
605 flags = 0x03;
606
Namjae Jeon64b39f42021-03-30 14:25:35 +0900607 ntace = (struct smb_ace *)((char *)pndace + *size);
Namjae Jeone2f34482021-03-16 10:49:09 +0900608 *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
609 pace->e_perm, 0777);
610 (*num_aces)++;
611 if (pace->e_tag == ACL_USER)
612 ntace->access_req |=
613 FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
614
615 if (S_ISDIR(fattr->cf_mode) &&
Namjae Jeon64b39f42021-03-30 14:25:35 +0900616 (pace->e_tag == ACL_USER || pace->e_tag == ACL_GROUP)) {
617 ntace = (struct smb_ace *)((char *)pndace + *size);
Namjae Jeone2f34482021-03-16 10:49:09 +0900618 *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
619 0x03, pace->e_perm, 0777);
620 (*num_aces)++;
621 if (pace->e_tag == ACL_USER)
622 ntace->access_req |=
623 FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
624 }
625
626pass_same_sid:
627 kfree(sid);
628 }
629
630 if (nt_aces_num)
631 return;
632
633posix_default_acl:
634 if (!fattr->cf_dacls)
635 return;
636
637 pace = fattr->cf_dacls->a_entries;
638 for (i = 0; i < fattr->cf_dacls->a_count; i++, pace++) {
639 sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
640 if (!sid)
641 break;
642
643 if (pace->e_tag == ACL_USER) {
644 uid_t uid;
645
646 uid = from_kuid(&init_user_ns, pace->e_uid);
647 id_to_sid(uid, SIDCREATOR_OWNER, sid);
648 } else if (pace->e_tag == ACL_GROUP) {
649 gid_t gid;
650
651 gid = from_kgid(&init_user_ns, pace->e_gid);
652 id_to_sid(gid, SIDCREATOR_GROUP, sid);
653 } else {
654 kfree(sid);
655 continue;
656 }
657
Namjae Jeon64b39f42021-03-30 14:25:35 +0900658 ntace = (struct smb_ace *)((char *)pndace + *size);
Namjae Jeone2f34482021-03-16 10:49:09 +0900659 *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
660 pace->e_perm, 0777);
661 (*num_aces)++;
662 if (pace->e_tag == ACL_USER)
663 ntace->access_req |=
664 FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
665 kfree(sid);
666 }
667}
668
669static void set_ntacl_dacl(struct smb_acl *pndacl, struct smb_acl *nt_dacl,
Namjae Jeon070fb212021-05-26 17:57:12 +0900670 const struct smb_sid *pownersid,
671 const struct smb_sid *pgrpsid,
672 struct smb_fattr *fattr)
Namjae Jeone2f34482021-03-16 10:49:09 +0900673{
674 struct smb_ace *ntace, *pndace;
675 int nt_num_aces = le32_to_cpu(nt_dacl->num_aces), num_aces = 0;
676 unsigned short size = 0;
677 int i;
678
679 pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
680 if (nt_num_aces) {
681 ntace = (struct smb_ace *)((char *)nt_dacl + sizeof(struct smb_acl));
682 for (i = 0; i < nt_num_aces; i++) {
683 memcpy((char *)pndace + size, ntace, le16_to_cpu(ntace->size));
684 size += le16_to_cpu(ntace->size);
685 ntace = (struct smb_ace *)((char *)ntace + le16_to_cpu(ntace->size));
686 num_aces++;
687 }
688 }
689
690 set_posix_acl_entries_dacl(pndace, fattr, &num_aces, &size, nt_num_aces);
691 pndacl->num_aces = cpu_to_le32(num_aces);
692 pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
693}
694
695static void set_mode_dacl(struct smb_acl *pndacl, struct smb_fattr *fattr)
696{
697 struct smb_ace *pace, *pndace;
698 u32 num_aces = 0;
699 u16 size = 0, ace_size = 0;
700 uid_t uid;
701 const struct smb_sid *sid;
702
703 pace = pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
704
705 if (fattr->cf_acls) {
706 set_posix_acl_entries_dacl(pndace, fattr, &num_aces, &size, num_aces);
707 goto out;
708 }
709
710 /* owner RID */
711 uid = from_kuid(&init_user_ns, fattr->cf_uid);
712 if (uid)
713 sid = &server_conf.domain_sid;
714 else
715 sid = &sid_unix_users;
716 ace_size = fill_ace_for_sid(pace, sid, ACCESS_ALLOWED, 0,
Namjae Jeon070fb212021-05-26 17:57:12 +0900717 fattr->cf_mode, 0700);
Namjae Jeone2f34482021-03-16 10:49:09 +0900718 pace->sid.sub_auth[pace->sid.num_subauth++] = cpu_to_le32(uid);
719 pace->access_req |= FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
720 pace->size = cpu_to_le16(ace_size + 4);
721 size += le16_to_cpu(pace->size);
722 pace = (struct smb_ace *)((char *)pndace + size);
723
724 /* Group RID */
725 ace_size = fill_ace_for_sid(pace, &sid_unix_groups,
Namjae Jeon070fb212021-05-26 17:57:12 +0900726 ACCESS_ALLOWED, 0, fattr->cf_mode, 0070);
Namjae Jeone2f34482021-03-16 10:49:09 +0900727 pace->sid.sub_auth[pace->sid.num_subauth++] =
728 cpu_to_le32(from_kgid(&init_user_ns, fattr->cf_gid));
729 pace->size = cpu_to_le16(ace_size + 4);
730 size += le16_to_cpu(pace->size);
731 pace = (struct smb_ace *)((char *)pndace + size);
732 num_aces = 3;
733
734 if (S_ISDIR(fattr->cf_mode)) {
735 pace = (struct smb_ace *)((char *)pndace + size);
736
737 /* creator owner */
738 size += fill_ace_for_sid(pace, &creator_owner, ACCESS_ALLOWED,
Namjae Jeon070fb212021-05-26 17:57:12 +0900739 0x0b, fattr->cf_mode, 0700);
Namjae Jeone2f34482021-03-16 10:49:09 +0900740 pace->access_req |= FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
741 pace = (struct smb_ace *)((char *)pndace + size);
742
743 /* creator group */
744 size += fill_ace_for_sid(pace, &creator_group, ACCESS_ALLOWED,
Namjae Jeon070fb212021-05-26 17:57:12 +0900745 0x0b, fattr->cf_mode, 0070);
Namjae Jeone2f34482021-03-16 10:49:09 +0900746 pace = (struct smb_ace *)((char *)pndace + size);
747 num_aces = 5;
748 }
749
750 /* other */
751 size += fill_ace_for_sid(pace, &sid_everyone, ACCESS_ALLOWED, 0,
Namjae Jeon070fb212021-05-26 17:57:12 +0900752 fattr->cf_mode, 0007);
Namjae Jeone2f34482021-03-16 10:49:09 +0900753
754out:
755 pndacl->num_aces = cpu_to_le32(num_aces);
756 pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
757}
758
759static int parse_sid(struct smb_sid *psid, char *end_of_acl)
760{
761 /*
762 * validate that we do not go past end of ACL - sid must be at least 8
763 * bytes long (assuming no sub-auths - e.g. the null SID
764 */
765 if (end_of_acl < (char *)psid + 8) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900766 pr_err("ACL too small to parse SID %p\n", psid);
Namjae Jeone2f34482021-03-16 10:49:09 +0900767 return -EINVAL;
768 }
769
770 return 0;
771}
772
773/* Convert CIFS ACL to POSIX form */
774int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
Namjae Jeon070fb212021-05-26 17:57:12 +0900775 struct smb_fattr *fattr)
Namjae Jeone2f34482021-03-16 10:49:09 +0900776{
777 int rc = 0;
778 struct smb_sid *owner_sid_ptr, *group_sid_ptr;
779 struct smb_acl *dacl_ptr; /* no need for SACL ptr */
780 char *end_of_acl = ((char *)pntsd) + acl_len;
781 __u32 dacloffset;
Namjae Jeon548e9ad2021-03-21 17:30:49 +0900782 int pntsd_type;
Namjae Jeone2f34482021-03-16 10:49:09 +0900783
Namjae Jeon64b39f42021-03-30 14:25:35 +0900784 if (!pntsd)
Namjae Jeone2f34482021-03-16 10:49:09 +0900785 return -EIO;
786
787 owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
788 le32_to_cpu(pntsd->osidoffset));
789 group_sid_ptr = (struct smb_sid *)((char *)pntsd +
790 le32_to_cpu(pntsd->gsidoffset));
791 dacloffset = le32_to_cpu(pntsd->dacloffset);
792 dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
793 ksmbd_debug(SMB,
Namjae Jeon070fb212021-05-26 17:57:12 +0900794 "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
795 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
796 le32_to_cpu(pntsd->gsidoffset),
797 le32_to_cpu(pntsd->sacloffset), dacloffset);
Namjae Jeone2f34482021-03-16 10:49:09 +0900798
Namjae Jeone2f34482021-03-16 10:49:09 +0900799 pntsd_type = le16_to_cpu(pntsd->type);
Namjae Jeone2f34482021-03-16 10:49:09 +0900800 if (!(pntsd_type & DACL_PRESENT)) {
801 ksmbd_debug(SMB, "DACL_PRESENT in DACL type is not set\n");
802 return rc;
803 }
804
805 pntsd->type = cpu_to_le16(DACL_PRESENT);
806
807 if (pntsd->osidoffset) {
808 rc = parse_sid(owner_sid_ptr, end_of_acl);
809 if (rc) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900810 pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
Namjae Jeone2f34482021-03-16 10:49:09 +0900811 return rc;
812 }
813
814 rc = sid_to_id(owner_sid_ptr, SIDOWNER, fattr);
815 if (rc) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900816 pr_err("%s: Error %d mapping Owner SID to uid\n",
817 __func__, rc);
Namjae Jeone2f34482021-03-16 10:49:09 +0900818 owner_sid_ptr = NULL;
819 }
820 }
821
822 if (pntsd->gsidoffset) {
823 rc = parse_sid(group_sid_ptr, end_of_acl);
824 if (rc) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900825 pr_err("%s: Error %d mapping Owner SID to gid\n",
826 __func__, rc);
Namjae Jeone2f34482021-03-16 10:49:09 +0900827 return rc;
828 }
829 rc = sid_to_id(group_sid_ptr, SIDUNIX_GROUP, fattr);
830 if (rc) {
Namjae Jeonbde16942021-06-28 15:23:19 +0900831 pr_err("%s: Error %d mapping Group SID to gid\n",
832 __func__, rc);
Namjae Jeone2f34482021-03-16 10:49:09 +0900833 group_sid_ptr = NULL;
834 }
835 }
836
Namjae Jeon070fb212021-05-26 17:57:12 +0900837 if ((pntsd_type & (DACL_AUTO_INHERITED | DACL_AUTO_INHERIT_REQ)) ==
Namjae Jeone2f34482021-03-16 10:49:09 +0900838 (DACL_AUTO_INHERITED | DACL_AUTO_INHERIT_REQ))
839 pntsd->type |= cpu_to_le16(DACL_AUTO_INHERITED);
840 if (pntsd_type & DACL_PROTECTED)
841 pntsd->type |= cpu_to_le16(DACL_PROTECTED);
842
843 if (dacloffset) {
844 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr,
Namjae Jeon070fb212021-05-26 17:57:12 +0900845 fattr);
Namjae Jeone2f34482021-03-16 10:49:09 +0900846 }
847
848 return 0;
849}
850
851/* Convert permission bits from mode to equivalent CIFS ACL */
852int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
Namjae Jeon070fb212021-05-26 17:57:12 +0900853 int addition_info, __u32 *secdesclen,
854 struct smb_fattr *fattr)
Namjae Jeone2f34482021-03-16 10:49:09 +0900855{
856 int rc = 0;
857 __u32 offset;
858 struct smb_sid *owner_sid_ptr, *group_sid_ptr;
859 struct smb_sid *nowner_sid_ptr, *ngroup_sid_ptr;
860 struct smb_acl *dacl_ptr = NULL; /* no need for SACL ptr */
861 uid_t uid;
862 gid_t gid;
863 unsigned int sid_type = SIDOWNER;
864
865 nowner_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
866 if (!nowner_sid_ptr)
867 return -ENOMEM;
868
869 uid = from_kuid(&init_user_ns, fattr->cf_uid);
870 if (!uid)
871 sid_type = SIDUNIX_USER;
872 id_to_sid(uid, sid_type, nowner_sid_ptr);
873
874 ngroup_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
875 if (!ngroup_sid_ptr) {
876 kfree(nowner_sid_ptr);
877 return -ENOMEM;
878 }
879
880 gid = from_kgid(&init_user_ns, fattr->cf_gid);
881 id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr);
882
883 offset = sizeof(struct smb_ntsd);
884 pntsd->sacloffset = 0;
885 pntsd->revision = cpu_to_le16(1);
886 pntsd->type = cpu_to_le16(SELF_RELATIVE);
887 if (ppntsd)
888 pntsd->type |= ppntsd->type;
889
890 if (addition_info & OWNER_SECINFO) {
891 pntsd->osidoffset = cpu_to_le32(offset);
892 owner_sid_ptr = (struct smb_sid *)((char *)pntsd + offset);
893 smb_copy_sid(owner_sid_ptr, nowner_sid_ptr);
894 offset += 1 + 1 + 6 + (nowner_sid_ptr->num_subauth * 4);
895 }
896
897 if (addition_info & GROUP_SECINFO) {
898 pntsd->gsidoffset = cpu_to_le32(offset);
899 group_sid_ptr = (struct smb_sid *)((char *)pntsd + offset);
900 smb_copy_sid(group_sid_ptr, ngroup_sid_ptr);
901 offset += 1 + 1 + 6 + (ngroup_sid_ptr->num_subauth * 4);
902 }
903
904 if (addition_info & DACL_SECINFO) {
905 pntsd->type |= cpu_to_le16(DACL_PRESENT);
906 dacl_ptr = (struct smb_acl *)((char *)pntsd + offset);
907 dacl_ptr->revision = cpu_to_le16(2);
908 dacl_ptr->size = cpu_to_le16(sizeof(struct smb_acl));
909 dacl_ptr->num_aces = 0;
910
Namjae Jeon64b39f42021-03-30 14:25:35 +0900911 if (!ppntsd) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900912 set_mode_dacl(dacl_ptr, fattr);
Namjae Jeon64b39f42021-03-30 14:25:35 +0900913 } else if (!ppntsd->dacloffset) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900914 goto out;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900915 } else {
Namjae Jeone2f34482021-03-16 10:49:09 +0900916 struct smb_acl *ppdacl_ptr;
917
918 ppdacl_ptr = (struct smb_acl *)((char *)ppntsd +
919 le32_to_cpu(ppntsd->dacloffset));
920 set_ntacl_dacl(dacl_ptr, ppdacl_ptr, nowner_sid_ptr,
921 ngroup_sid_ptr, fattr);
922 }
923 pntsd->dacloffset = cpu_to_le32(offset);
924 offset += le16_to_cpu(dacl_ptr->size);
925 }
926
927out:
928 kfree(nowner_sid_ptr);
929 kfree(ngroup_sid_ptr);
930 *secdesclen = offset;
931 return rc;
932}
933
934static void smb_set_ace(struct smb_ace *ace, const struct smb_sid *sid, u8 type,
Namjae Jeon070fb212021-05-26 17:57:12 +0900935 u8 flags, __le32 access_req)
Namjae Jeone2f34482021-03-16 10:49:09 +0900936{
937 ace->type = type;
938 ace->flags = flags;
939 ace->access_req = access_req;
940 smb_copy_sid(&ace->sid, sid);
941 ace->size = cpu_to_le16(1 + 1 + 2 + 4 + 1 + 1 + 6 + (sid->num_subauth * 4));
942}
943
944int smb_inherit_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
Namjae Jeon070fb212021-05-26 17:57:12 +0900945 unsigned int uid, unsigned int gid)
Namjae Jeone2f34482021-03-16 10:49:09 +0900946{
947 const struct smb_sid *psid, *creator = NULL;
948 struct smb_ace *parent_aces, *aces;
949 struct smb_acl *parent_pdacl;
950 struct smb_ntsd *parent_pntsd = NULL;
951 struct smb_sid owner_sid, group_sid;
952 struct dentry *parent = dentry->d_parent;
953 int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0;
954 int rc = -ENOENT, num_aces, dacloffset, pntsd_type, acl_len;
955 char *aces_base;
Namjae Jeonfba08fa2021-04-15 10:29:39 +0900956 bool is_dir = S_ISDIR(d_inode(dentry)->i_mode);
Namjae Jeone2f34482021-03-16 10:49:09 +0900957
958 acl_len = ksmbd_vfs_get_sd_xattr(conn, parent, &parent_pntsd);
959 if (acl_len <= 0)
960 return rc;
961 dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
962 if (!dacloffset)
963 goto out;
964
965 parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
966 num_aces = le32_to_cpu(parent_pdacl->num_aces);
967 pntsd_type = le16_to_cpu(parent_pntsd->type);
968
969 aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2, GFP_KERNEL);
970 if (!aces_base)
971 goto out;
972
973 aces = (struct smb_ace *)aces_base;
974 parent_aces = (struct smb_ace *)((char *)parent_pdacl +
975 sizeof(struct smb_acl));
976
977 if (pntsd_type & DACL_AUTO_INHERITED)
978 inherited_flags = INHERITED_ACE;
979
980 for (i = 0; i < num_aces; i++) {
981 flags = parent_aces->flags;
982 if (!smb_inherit_flags(flags, is_dir))
983 goto pass;
984 if (is_dir) {
985 flags &= ~(INHERIT_ONLY_ACE | INHERITED_ACE);
986 if (!(flags & CONTAINER_INHERIT_ACE))
987 flags |= INHERIT_ONLY_ACE;
988 if (flags & NO_PROPAGATE_INHERIT_ACE)
989 flags = 0;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900990 } else {
Namjae Jeone2f34482021-03-16 10:49:09 +0900991 flags = 0;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900992 }
Namjae Jeone2f34482021-03-16 10:49:09 +0900993
994 if (!compare_sids(&creator_owner, &parent_aces->sid)) {
995 creator = &creator_owner;
996 id_to_sid(uid, SIDOWNER, &owner_sid);
997 psid = &owner_sid;
998 } else if (!compare_sids(&creator_group, &parent_aces->sid)) {
999 creator = &creator_group;
1000 id_to_sid(gid, SIDUNIX_GROUP, &group_sid);
1001 psid = &group_sid;
1002 } else {
1003 creator = NULL;
1004 psid = &parent_aces->sid;
1005 }
1006
1007 if (is_dir && creator && flags & CONTAINER_INHERIT_ACE) {
1008 smb_set_ace(aces, psid, parent_aces->type, inherited_flags,
Namjae Jeon070fb212021-05-26 17:57:12 +09001009 parent_aces->access_req);
Namjae Jeone2f34482021-03-16 10:49:09 +09001010 nt_size += le16_to_cpu(aces->size);
1011 ace_cnt++;
1012 aces = (struct smb_ace *)((char *)aces + le16_to_cpu(aces->size));
1013 flags |= INHERIT_ONLY_ACE;
1014 psid = creator;
Namjae Jeon64b39f42021-03-30 14:25:35 +09001015 } else if (is_dir && !(parent_aces->flags & NO_PROPAGATE_INHERIT_ACE)) {
Namjae Jeone2f34482021-03-16 10:49:09 +09001016 psid = &parent_aces->sid;
Namjae Jeon64b39f42021-03-30 14:25:35 +09001017 }
Namjae Jeone2f34482021-03-16 10:49:09 +09001018
1019 smb_set_ace(aces, psid, parent_aces->type, flags | inherited_flags,
Namjae Jeon070fb212021-05-26 17:57:12 +09001020 parent_aces->access_req);
Namjae Jeone2f34482021-03-16 10:49:09 +09001021 nt_size += le16_to_cpu(aces->size);
1022 aces = (struct smb_ace *)((char *)aces + le16_to_cpu(aces->size));
1023 ace_cnt++;
1024pass:
1025 parent_aces =
1026 (struct smb_ace *)((char *)parent_aces + le16_to_cpu(parent_aces->size));
1027 }
1028
1029 if (nt_size > 0) {
1030 struct smb_ntsd *pntsd;
1031 struct smb_acl *pdacl;
1032 struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
1033 int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
1034
1035 if (parent_pntsd->osidoffset) {
1036 powner_sid = (struct smb_sid *)((char *)parent_pntsd +
1037 le32_to_cpu(parent_pntsd->osidoffset));
1038 powner_sid_size = 1 + 1 + 6 + (powner_sid->num_subauth * 4);
1039 }
1040 if (parent_pntsd->gsidoffset) {
1041 pgroup_sid = (struct smb_sid *)((char *)parent_pntsd +
1042 le32_to_cpu(parent_pntsd->gsidoffset));
1043 pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
1044 }
1045
1046 pntsd = kzalloc(sizeof(struct smb_ntsd) + powner_sid_size +
1047 pgroup_sid_size + sizeof(struct smb_acl) +
1048 nt_size, GFP_KERNEL);
1049 if (!pntsd) {
1050 rc = -ENOMEM;
1051 goto out;
1052 }
1053
1054 pntsd->revision = cpu_to_le16(1);
1055 pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PRESENT);
1056 if (le16_to_cpu(parent_pntsd->type) & DACL_AUTO_INHERITED)
1057 pntsd->type |= cpu_to_le16(DACL_AUTO_INHERITED);
1058 pntsd_size = sizeof(struct smb_ntsd);
1059 pntsd->osidoffset = parent_pntsd->osidoffset;
1060 pntsd->gsidoffset = parent_pntsd->gsidoffset;
1061 pntsd->dacloffset = parent_pntsd->dacloffset;
1062
1063 if (pntsd->osidoffset) {
1064 struct smb_sid *owner_sid = (struct smb_sid *)((char *)pntsd +
1065 le32_to_cpu(pntsd->osidoffset));
1066 memcpy(owner_sid, powner_sid, powner_sid_size);
1067 pntsd_size += powner_sid_size;
1068 }
1069
1070 if (pntsd->gsidoffset) {
1071 struct smb_sid *group_sid = (struct smb_sid *)((char *)pntsd +
1072 le32_to_cpu(pntsd->gsidoffset));
1073 memcpy(group_sid, pgroup_sid, pgroup_sid_size);
1074 pntsd_size += pgroup_sid_size;
1075 }
1076
1077 if (pntsd->dacloffset) {
1078 struct smb_ace *pace;
1079
1080 pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
1081 pdacl->revision = cpu_to_le16(2);
1082 pdacl->size = cpu_to_le16(sizeof(struct smb_acl) + nt_size);
1083 pdacl->num_aces = cpu_to_le32(ace_cnt);
1084 pace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
1085 memcpy(pace, aces_base, nt_size);
1086 pntsd_size += sizeof(struct smb_acl) + nt_size;
1087 }
1088
1089 ksmbd_vfs_set_sd_xattr(conn, dentry, pntsd, pntsd_size);
1090 kfree(pntsd);
1091 rc = 0;
1092 }
1093
1094 kfree(aces_base);
1095out:
1096 return rc;
1097}
1098
1099bool smb_inherit_flags(int flags, bool is_dir)
1100{
1101 if (!is_dir)
1102 return (flags & OBJECT_INHERIT_ACE) != 0;
1103
1104 if (flags & OBJECT_INHERIT_ACE && !(flags & NO_PROPAGATE_INHERIT_ACE))
1105 return true;
1106
1107 if (flags & CONTAINER_INHERIT_ACE)
1108 return true;
1109 return false;
1110}
1111
1112int smb_check_perm_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
Namjae Jeon070fb212021-05-26 17:57:12 +09001113 __le32 *pdaccess, int uid)
Namjae Jeone2f34482021-03-16 10:49:09 +09001114{
1115 struct smb_ntsd *pntsd = NULL;
1116 struct smb_acl *pdacl;
1117 struct posix_acl *posix_acls;
1118 int rc = 0, acl_size;
1119 struct smb_sid sid;
1120 int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE);
1121 struct smb_ace *ace;
1122 int i, found = 0;
1123 unsigned int access_bits = 0;
1124 struct smb_ace *others_ace = NULL;
1125 struct posix_acl_entry *pa_entry;
1126 unsigned int sid_type = SIDOWNER;
Namjae Jeon50355b02021-03-19 13:52:12 +09001127 char *end_of_acl;
Namjae Jeone2f34482021-03-16 10:49:09 +09001128
1129 ksmbd_debug(SMB, "check permission using windows acl\n");
1130 acl_size = ksmbd_vfs_get_sd_xattr(conn, dentry, &pntsd);
Namjae Jeon50355b02021-03-19 13:52:12 +09001131 if (acl_size <= 0 || !pntsd || !pntsd->dacloffset) {
1132 kfree(pntsd);
Namjae Jeone2f34482021-03-16 10:49:09 +09001133 return 0;
Namjae Jeon50355b02021-03-19 13:52:12 +09001134 }
Namjae Jeone2f34482021-03-16 10:49:09 +09001135
1136 pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
Namjae Jeon50355b02021-03-19 13:52:12 +09001137 end_of_acl = ((char *)pntsd) + acl_size;
1138 if (end_of_acl <= (char *)pdacl) {
1139 kfree(pntsd);
1140 return 0;
1141 }
1142
1143 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size) ||
1144 le16_to_cpu(pdacl->size) < sizeof(struct smb_acl)) {
1145 kfree(pntsd);
1146 return 0;
1147 }
1148
Namjae Jeone2f34482021-03-16 10:49:09 +09001149 if (!pdacl->num_aces) {
1150 if (!(le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) &&
1151 *pdaccess & ~(FILE_READ_CONTROL_LE | FILE_WRITE_DAC_LE)) {
1152 rc = -EACCES;
1153 goto err_out;
1154 }
1155 kfree(pntsd);
1156 return 0;
1157 }
1158
1159 if (*pdaccess & FILE_MAXIMAL_ACCESS_LE) {
1160 granted = READ_CONTROL | WRITE_DAC | FILE_READ_ATTRIBUTES |
1161 DELETE;
1162
1163 ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
1164 for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
1165 granted |= le32_to_cpu(ace->access_req);
Namjae Jeon64b39f42021-03-30 14:25:35 +09001166 ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
Namjae Jeon50355b02021-03-19 13:52:12 +09001167 if (end_of_acl < (char *)ace)
1168 goto err_out;
Namjae Jeone2f34482021-03-16 10:49:09 +09001169 }
1170
1171 if (!pdacl->num_aces)
1172 granted = GENERIC_ALL_FLAGS;
1173 }
1174
1175 if (!uid)
1176 sid_type = SIDUNIX_USER;
1177 id_to_sid(uid, sid_type, &sid);
1178
1179 ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
1180 for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
1181 if (!compare_sids(&sid, &ace->sid) ||
1182 !compare_sids(&sid_unix_NFS_mode, &ace->sid)) {
1183 found = 1;
1184 break;
1185 }
1186 if (!compare_sids(&sid_everyone, &ace->sid))
1187 others_ace = ace;
1188
Namjae Jeon64b39f42021-03-30 14:25:35 +09001189 ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
Namjae Jeon50355b02021-03-19 13:52:12 +09001190 if (end_of_acl < (char *)ace)
1191 goto err_out;
Namjae Jeone2f34482021-03-16 10:49:09 +09001192 }
1193
1194 if (*pdaccess & FILE_MAXIMAL_ACCESS_LE && found) {
1195 granted = READ_CONTROL | WRITE_DAC | FILE_READ_ATTRIBUTES |
1196 DELETE;
1197
1198 granted |= le32_to_cpu(ace->access_req);
1199
1200 if (!pdacl->num_aces)
1201 granted = GENERIC_ALL_FLAGS;
1202 }
1203
Namjae Jeon67d1c432021-06-22 11:42:29 +09001204 posix_acls = get_acl(d_inode(dentry), ACL_TYPE_ACCESS);
Namjae Jeone2f34482021-03-16 10:49:09 +09001205 if (posix_acls && !found) {
1206 unsigned int id = -1;
1207
1208 pa_entry = posix_acls->a_entries;
1209 for (i = 0; i < posix_acls->a_count; i++, pa_entry++) {
1210 if (pa_entry->e_tag == ACL_USER)
1211 id = from_kuid(&init_user_ns, pa_entry->e_uid);
1212 else if (pa_entry->e_tag == ACL_GROUP)
1213 id = from_kgid(&init_user_ns, pa_entry->e_gid);
1214 else
1215 continue;
1216
1217 if (id == uid) {
1218 mode_to_access_flags(pa_entry->e_perm, 0777, &access_bits);
1219 if (!access_bits)
1220 access_bits = SET_MINIMUM_RIGHTS;
1221 goto check_access_bits;
1222 }
1223 }
1224 }
1225 if (posix_acls)
1226 posix_acl_release(posix_acls);
1227
1228 if (!found) {
Namjae Jeon64b39f42021-03-30 14:25:35 +09001229 if (others_ace) {
Namjae Jeone2f34482021-03-16 10:49:09 +09001230 ace = others_ace;
Namjae Jeon64b39f42021-03-30 14:25:35 +09001231 } else {
Namjae Jeone2f34482021-03-16 10:49:09 +09001232 ksmbd_debug(SMB, "Can't find corresponding sid\n");
1233 rc = -EACCES;
1234 goto err_out;
1235 }
1236 }
1237
1238 switch (ace->type) {
1239 case ACCESS_ALLOWED_ACE_TYPE:
1240 access_bits = le32_to_cpu(ace->access_req);
1241 break;
1242 case ACCESS_DENIED_ACE_TYPE:
1243 case ACCESS_DENIED_CALLBACK_ACE_TYPE:
1244 access_bits = le32_to_cpu(~ace->access_req);
1245 break;
1246 }
1247
1248check_access_bits:
Namjae Jeon070fb212021-05-26 17:57:12 +09001249 if (granted &
1250 ~(access_bits | FILE_READ_ATTRIBUTES | READ_CONTROL | WRITE_DAC | DELETE)) {
Namjae Jeone2f34482021-03-16 10:49:09 +09001251 ksmbd_debug(SMB, "Access denied with winACL, granted : %x, access_req : %x\n",
Namjae Jeon070fb212021-05-26 17:57:12 +09001252 granted, le32_to_cpu(ace->access_req));
Namjae Jeone2f34482021-03-16 10:49:09 +09001253 rc = -EACCES;
1254 goto err_out;
1255 }
1256
1257 *pdaccess = cpu_to_le32(granted);
1258err_out:
1259 kfree(pntsd);
1260 return rc;
1261}
1262
1263int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
Namjae Jeon070fb212021-05-26 17:57:12 +09001264 struct dentry *dentry, struct smb_ntsd *pntsd, int ntsd_len,
1265 bool type_check)
Namjae Jeone2f34482021-03-16 10:49:09 +09001266{
1267 int rc;
1268 struct smb_fattr fattr = {{0}};
Namjae Jeonfba08fa2021-04-15 10:29:39 +09001269 struct inode *inode = d_inode(dentry);
Namjae Jeone2f34482021-03-16 10:49:09 +09001270
1271 fattr.cf_uid = INVALID_UID;
1272 fattr.cf_gid = INVALID_GID;
1273 fattr.cf_mode = inode->i_mode;
1274
1275 rc = parse_sec_desc(pntsd, ntsd_len, &fattr);
1276 if (rc)
1277 goto out;
1278
1279 inode->i_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
1280 if (!uid_eq(fattr.cf_uid, INVALID_UID))
1281 inode->i_uid = fattr.cf_uid;
1282 if (!gid_eq(fattr.cf_gid, INVALID_GID))
1283 inode->i_gid = fattr.cf_gid;
1284 mark_inode_dirty(inode);
1285
1286 ksmbd_vfs_remove_acl_xattrs(dentry);
1287 /* Update posix acls */
1288 if (fattr.cf_dacls) {
Namjae Jeon67d1c432021-06-22 11:42:29 +09001289 rc = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS,
1290 fattr.cf_acls);
Namjae Jeone2f34482021-03-16 10:49:09 +09001291 if (S_ISDIR(inode->i_mode) && fattr.cf_dacls)
Namjae Jeon67d1c432021-06-22 11:42:29 +09001292 rc = set_posix_acl(&init_user_ns, inode,
1293 ACL_TYPE_DEFAULT, fattr.cf_dacls);
Namjae Jeone2f34482021-03-16 10:49:09 +09001294 }
1295
1296 /* Check it only calling from SD BUFFER context */
1297 if (type_check && !(le16_to_cpu(pntsd->type) & DACL_PRESENT))
1298 goto out;
1299
Namjae Jeon64b39f42021-03-30 14:25:35 +09001300 if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
Namjae Jeone2f34482021-03-16 10:49:09 +09001301 /* Update WinACL in xattr */
1302 ksmbd_vfs_remove_sd_xattrs(dentry);
1303 ksmbd_vfs_set_sd_xattr(conn, dentry, pntsd, ntsd_len);
1304 }
1305
1306out:
1307 posix_acl_release(fattr.cf_acls);
1308 posix_acl_release(fattr.cf_dacls);
1309 mark_inode_dirty(inode);
1310 return rc;
1311}
1312
1313void ksmbd_init_domain(u32 *sub_auth)
1314{
1315 int i;
1316
1317 memcpy(&server_conf.domain_sid, &domain, sizeof(struct smb_sid));
1318 for (i = 0; i < 3; ++i)
1319 server_conf.domain_sid.sub_auth[i + 1] = cpu_to_le32(sub_auth[i]);
1320}