blob: 43d3123d8b62ed8731b1b7e4ad3b07ce8e9eb2d5 [file] [log] [blame]
Namjae Jeone2f34482021-03-16 10:49:09 +09001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
4 * Copyright (C) 2018 Namjae Jeon <linkinjeon@kernel.org>
5 */
6
7#include "smb_common.h"
8#include "server.h"
9#include "misc.h"
10#include "smbstatus.h"
Namjae Jeone2f34482021-03-16 10:49:09 +090011#include "connection.h"
12#include "ksmbd_work.h"
13#include "mgmt/user_session.h"
14#include "mgmt/user_config.h"
15#include "mgmt/tree_connect.h"
16#include "mgmt/share_config.h"
17
18/*for shortname implementation */
19static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
Namjae Jeon64b39f42021-03-30 14:25:35 +090020#define MANGLE_BASE (sizeof(basechars) / sizeof(char) - 1)
Namjae Jeone2f34482021-03-16 10:49:09 +090021#define MAGIC_CHAR '~'
22#define PERIOD '.'
23#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
24#define KSMBD_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr))
25
Namjae Jeone2f34482021-03-16 10:49:09 +090026struct smb_protocol {
27 int index;
28 char *name;
29 char *prot;
30 __u16 prot_id;
31};
32
Marios Makassikiseebff912021-08-12 10:12:35 +090033static struct smb_protocol smb1_protos[] = {
Namjae Jeone2f34482021-03-16 10:49:09 +090034 {
35 SMB21_PROT,
36 "\2SMB 2.1",
37 "SMB2_10",
38 SMB21_PROT_ID
39 },
40 {
41 SMB2X_PROT,
42 "\2SMB 2.???",
43 "SMB2_22",
44 SMB2X_PROT_ID
45 },
Marios Makassikiseebff912021-08-12 10:12:35 +090046};
47
48static struct smb_protocol smb2_protos[] = {
49 {
50 SMB21_PROT,
51 "\2SMB 2.1",
52 "SMB2_10",
53 SMB21_PROT_ID
54 },
Namjae Jeone2f34482021-03-16 10:49:09 +090055 {
56 SMB30_PROT,
57 "\2SMB 3.0",
58 "SMB3_00",
59 SMB30_PROT_ID
60 },
61 {
62 SMB302_PROT,
63 "\2SMB 3.02",
64 "SMB3_02",
65 SMB302_PROT_ID
66 },
67 {
68 SMB311_PROT,
69 "\2SMB 3.1.1",
70 "SMB3_11",
71 SMB311_PROT_ID
72 },
73};
74
75unsigned int ksmbd_server_side_copy_max_chunk_count(void)
76{
77 return 256;
78}
79
80unsigned int ksmbd_server_side_copy_max_chunk_size(void)
81{
82 return (2U << 30) - 1;
83}
84
85unsigned int ksmbd_server_side_copy_max_total_size(void)
86{
87 return (2U << 30) - 1;
88}
89
90inline int ksmbd_min_protocol(void)
91{
92 return SMB2_PROT;
93}
94
95inline int ksmbd_max_protocol(void)
96{
97 return SMB311_PROT;
98}
99
100int ksmbd_lookup_protocol_idx(char *str)
101{
Marios Makassikiseebff912021-08-12 10:12:35 +0900102 int offt = ARRAY_SIZE(smb1_protos) - 1;
Namjae Jeone2f34482021-03-16 10:49:09 +0900103 int len = strlen(str);
104
105 while (offt >= 0) {
Marios Makassikiseebff912021-08-12 10:12:35 +0900106 if (!strncmp(str, smb1_protos[offt].prot, len)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900107 ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
Marios Makassikiseebff912021-08-12 10:12:35 +0900108 smb1_protos[offt].prot, offt);
109 return smb1_protos[offt].index;
110 }
111 offt--;
112 }
113
114 offt = ARRAY_SIZE(smb2_protos) - 1;
115 while (offt >= 0) {
116 if (!strncmp(str, smb2_protos[offt].prot, len)) {
117 ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
118 smb2_protos[offt].prot, offt);
119 return smb2_protos[offt].index;
Namjae Jeone2f34482021-03-16 10:49:09 +0900120 }
121 offt--;
122 }
123 return -1;
124}
125
126/**
Hyunchul Lee95fa1ce2021-03-21 17:05:56 +0900127 * ksmbd_verify_smb_message() - check for valid smb2 request header
128 * @work: smb work
Namjae Jeone2f34482021-03-16 10:49:09 +0900129 *
130 * check for valid smb signature and packet direction(request/response)
131 *
132 * Return: 0 on success, otherwise 1
133 */
134int ksmbd_verify_smb_message(struct ksmbd_work *work)
135{
Namjae Jeone5066492021-03-30 12:35:23 +0900136 struct smb2_hdr *smb2_hdr = work->request_buf;
Namjae Jeone2f34482021-03-16 10:49:09 +0900137
138 if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
139 return ksmbd_smb2_check_message(work);
140
141 return 0;
142}
143
144/**
Hyunchul Lee95fa1ce2021-03-21 17:05:56 +0900145 * ksmbd_smb_request() - check for valid smb request type
Namjae Jeone2f34482021-03-16 10:49:09 +0900146 * @conn: connection instance
Namjae Jeone2f34482021-03-16 10:49:09 +0900147 *
148 * Return: true on success, otherwise false
149 */
150bool ksmbd_smb_request(struct ksmbd_conn *conn)
151{
152 int type = *(char *)conn->request_buf;
153
154 switch (type) {
155 case RFC1002_SESSION_MESSAGE:
156 /* Regular SMB request */
157 return true;
158 case RFC1002_SESSION_KEEP_ALIVE:
159 ksmbd_debug(SMB, "RFC 1002 session keep alive\n");
160 break;
161 default:
162 ksmbd_debug(SMB, "RFC 1002 unknown request type 0x%x\n", type);
163 }
164
165 return false;
166}
167
168static bool supported_protocol(int idx)
169{
170 if (idx == SMB2X_PROT &&
171 (server_conf.min_protocol >= SMB21_PROT ||
172 server_conf.max_protocol <= SMB311_PROT))
173 return true;
174
175 return (server_conf.min_protocol <= idx &&
Namjae Jeon070fb212021-05-26 17:57:12 +0900176 idx <= server_conf.max_protocol);
Namjae Jeone2f34482021-03-16 10:49:09 +0900177}
178
179static char *next_dialect(char *dialect, int *next_off)
180{
181 dialect = dialect + *next_off;
182 *next_off = strlen(dialect);
183 return dialect;
184}
185
186static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count)
187{
188 int i, seq_num, bcount, next;
189 char *dialect;
190
Marios Makassikiseebff912021-08-12 10:12:35 +0900191 for (i = ARRAY_SIZE(smb1_protos) - 1; i >= 0; i--) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900192 seq_num = 0;
193 next = 0;
194 dialect = cli_dialects;
195 bcount = le16_to_cpu(byte_count);
196 do {
197 dialect = next_dialect(dialect, &next);
198 ksmbd_debug(SMB, "client requested dialect %s\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900199 dialect);
Marios Makassikiseebff912021-08-12 10:12:35 +0900200 if (!strcmp(dialect, smb1_protos[i].name)) {
201 if (supported_protocol(smb1_protos[i].index)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900202 ksmbd_debug(SMB,
Namjae Jeon070fb212021-05-26 17:57:12 +0900203 "selected %s dialect\n",
Marios Makassikiseebff912021-08-12 10:12:35 +0900204 smb1_protos[i].name);
205 if (smb1_protos[i].index == SMB1_PROT)
Namjae Jeone2f34482021-03-16 10:49:09 +0900206 return seq_num;
Marios Makassikiseebff912021-08-12 10:12:35 +0900207 return smb1_protos[i].prot_id;
Namjae Jeone2f34482021-03-16 10:49:09 +0900208 }
209 }
210 seq_num++;
211 bcount -= (++next);
212 } while (bcount > 0);
213 }
214
215 return BAD_PROT_ID;
216}
217
218int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
219{
220 int i;
221 int count;
222
Marios Makassikiseebff912021-08-12 10:12:35 +0900223 for (i = ARRAY_SIZE(smb2_protos) - 1; i >= 0; i--) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900224 count = le16_to_cpu(dialects_count);
225 while (--count >= 0) {
226 ksmbd_debug(SMB, "client requested dialect 0x%x\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900227 le16_to_cpu(cli_dialects[count]));
Namjae Jeone2f34482021-03-16 10:49:09 +0900228 if (le16_to_cpu(cli_dialects[count]) !=
Marios Makassikiseebff912021-08-12 10:12:35 +0900229 smb2_protos[i].prot_id)
Namjae Jeone2f34482021-03-16 10:49:09 +0900230 continue;
231
Marios Makassikiseebff912021-08-12 10:12:35 +0900232 if (supported_protocol(smb2_protos[i].index)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900233 ksmbd_debug(SMB, "selected %s dialect\n",
Marios Makassikiseebff912021-08-12 10:12:35 +0900234 smb2_protos[i].name);
235 return smb2_protos[i].prot_id;
Namjae Jeone2f34482021-03-16 10:49:09 +0900236 }
237 }
238 }
239
240 return BAD_PROT_ID;
241}
242
Marios Makassikiseebff912021-08-12 10:12:35 +0900243static int ksmbd_negotiate_smb_dialect(void *buf)
Namjae Jeone2f34482021-03-16 10:49:09 +0900244{
245 __le32 proto;
246
247 proto = ((struct smb2_hdr *)buf)->ProtocolId;
248 if (proto == SMB2_PROTO_NUMBER) {
249 struct smb2_negotiate_req *req;
250
251 req = (struct smb2_negotiate_req *)buf;
252 return ksmbd_lookup_dialect_by_id(req->Dialects,
253 req->DialectCount);
254 }
255
256 proto = *(__le32 *)((struct smb_hdr *)buf)->Protocol;
257 if (proto == SMB1_PROTO_NUMBER) {
258 struct smb_negotiate_req *req;
259
260 req = (struct smb_negotiate_req *)buf;
261 return ksmbd_lookup_dialect_by_name(req->DialectsArray,
262 req->ByteCount);
263 }
264
265 return BAD_PROT_ID;
266}
267
268#define SMB_COM_NEGOTIATE 0x72
269int ksmbd_init_smb_server(struct ksmbd_work *work)
270{
271 struct ksmbd_conn *conn = work->conn;
272
273 if (conn->need_neg == false)
274 return 0;
275
276 init_smb3_11_server(conn);
277
278 if (conn->ops->get_cmd_val(work) != SMB_COM_NEGOTIATE)
279 conn->need_neg = false;
280 return 0;
281}
282
283bool ksmbd_pdu_size_has_room(unsigned int pdu)
284{
285 return (pdu >= KSMBD_MIN_SUPPORTED_HEADER_SIZE - 4);
286}
287
Namjae Jeon64b39f42021-03-30 14:25:35 +0900288int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
Namjae Jeon070fb212021-05-26 17:57:12 +0900289 struct ksmbd_file *dir,
290 struct ksmbd_dir_info *d_info,
291 char *search_pattern,
292 int (*fn)(struct ksmbd_conn *, int,
293 struct ksmbd_dir_info *,
294 struct ksmbd_kstat *))
Namjae Jeone2f34482021-03-16 10:49:09 +0900295{
296 int i, rc = 0;
297 struct ksmbd_conn *conn = work->conn;
Hyunchul Lee465d7202021-07-03 12:10:36 +0900298 struct user_namespace *user_ns = file_mnt_user_ns(dir->filp);
Namjae Jeone2f34482021-03-16 10:49:09 +0900299
300 for (i = 0; i < 2; i++) {
301 struct kstat kstat;
302 struct ksmbd_kstat ksmbd_kstat;
303
304 if (!dir->dot_dotdot[i]) { /* fill dot entry info */
305 if (i == 0) {
306 d_info->name = ".";
307 d_info->name_len = 1;
308 } else {
309 d_info->name = "..";
310 d_info->name_len = 2;
311 }
312
Namjae Jeonb24c9332021-03-21 17:32:19 +0900313 if (!match_pattern(d_info->name, d_info->name_len,
Namjae Jeon64b39f42021-03-30 14:25:35 +0900314 search_pattern)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900315 dir->dot_dotdot[i] = 1;
316 continue;
317 }
318
319 ksmbd_kstat.kstat = &kstat;
320 ksmbd_vfs_fill_dentry_attrs(work,
Hyunchul Lee465d7202021-07-03 12:10:36 +0900321 user_ns,
Namjae Jeon070fb212021-05-26 17:57:12 +0900322 dir->filp->f_path.dentry->d_parent,
323 &ksmbd_kstat);
Christian Brauner475d6f92021-08-23 17:13:48 +0200324 rc = fn(conn, info_level, d_info, &ksmbd_kstat);
Namjae Jeone2f34482021-03-16 10:49:09 +0900325 if (rc)
326 break;
327 if (d_info->out_buf_len <= 0)
328 break;
329
330 dir->dot_dotdot[i] = 1;
331 if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) {
332 d_info->out_buf_len = 0;
333 break;
334 }
335 }
336 }
337
338 return rc;
339}
340
341/**
342 * ksmbd_extract_shortname() - get shortname from long filename
343 * @conn: connection instance
344 * @longname: source long filename
345 * @shortname: destination short filename
346 *
347 * Return: shortname length or 0 when source long name is '.' or '..'
348 * TODO: Though this function comforms the restriction of 8.3 Filename spec,
349 * but the result is different with Windows 7's one. need to check.
350 */
Namjae Jeon64b39f42021-03-30 14:25:35 +0900351int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
Namjae Jeon070fb212021-05-26 17:57:12 +0900352 char *shortname)
Namjae Jeone2f34482021-03-16 10:49:09 +0900353{
354 const char *p;
355 char base[9], extension[4];
356 char out[13] = {0};
357 int baselen = 0;
358 int extlen = 0, len = 0;
359 unsigned int csum = 0;
360 const unsigned char *ptr;
361 bool dot_present = true;
362
363 p = longname;
364 if ((*p == '.') || (!(strcmp(p, "..")))) {
365 /*no mangling required */
366 return 0;
367 }
368
369 p = strrchr(longname, '.');
370 if (p == longname) { /*name starts with a dot*/
371 strscpy(extension, "___", strlen("___"));
372 } else {
Namjae Jeon64b39f42021-03-30 14:25:35 +0900373 if (p) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900374 p++;
375 while (*p && extlen < 3) {
376 if (*p != '.')
377 extension[extlen++] = toupper(*p);
378 p++;
379 }
380 extension[extlen] = '\0';
Namjae Jeon64b39f42021-03-30 14:25:35 +0900381 } else {
Namjae Jeone2f34482021-03-16 10:49:09 +0900382 dot_present = false;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900383 }
Namjae Jeone2f34482021-03-16 10:49:09 +0900384 }
385
386 p = longname;
387 if (*p == '.') {
388 p++;
389 longname++;
390 }
391 while (*p && (baselen < 5)) {
392 if (*p != '.')
393 base[baselen++] = toupper(*p);
394 p++;
395 }
396
397 base[baselen] = MAGIC_CHAR;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900398 memcpy(out, base, baselen + 1);
Namjae Jeone2f34482021-03-16 10:49:09 +0900399
400 ptr = longname;
401 len = strlen(longname);
402 for (; len > 0; len--, ptr++)
403 csum += *ptr;
404
405 csum = csum % (MANGLE_BASE * MANGLE_BASE);
Namjae Jeon64b39f42021-03-30 14:25:35 +0900406 out[baselen + 1] = mangle(csum / MANGLE_BASE);
407 out[baselen + 2] = mangle(csum);
408 out[baselen + 3] = PERIOD;
Namjae Jeone2f34482021-03-16 10:49:09 +0900409
410 if (dot_present)
Namjae Jeon64b39f42021-03-30 14:25:35 +0900411 memcpy(&out[baselen + 4], extension, 4);
Namjae Jeone2f34482021-03-16 10:49:09 +0900412 else
Namjae Jeon64b39f42021-03-30 14:25:35 +0900413 out[baselen + 4] = '\0';
Namjae Jeone2f34482021-03-16 10:49:09 +0900414 smbConvertToUTF16((__le16 *)shortname, out, PATH_MAX,
Namjae Jeon070fb212021-05-26 17:57:12 +0900415 conn->local_nls, 0);
Namjae Jeone2f34482021-03-16 10:49:09 +0900416 len = strlen(out) * 2;
417 return len;
418}
419
420static int __smb2_negotiate(struct ksmbd_conn *conn)
421{
422 return (conn->dialect >= SMB20_PROT_ID &&
Namjae Jeon070fb212021-05-26 17:57:12 +0900423 conn->dialect <= SMB311_PROT_ID);
Namjae Jeone2f34482021-03-16 10:49:09 +0900424}
425
426static int smb_handle_negotiate(struct ksmbd_work *work)
427{
Namjae Jeone5066492021-03-30 12:35:23 +0900428 struct smb_negotiate_rsp *neg_rsp = work->response_buf;
Namjae Jeone2f34482021-03-16 10:49:09 +0900429
430 ksmbd_debug(SMB, "Unsupported SMB protocol\n");
431 neg_rsp->hdr.Status.CifsError = STATUS_INVALID_LOGON_TYPE;
432 return -EINVAL;
433}
434
435int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
436{
437 struct ksmbd_conn *conn = work->conn;
438 int ret;
439
Namjae Jeone5066492021-03-30 12:35:23 +0900440 conn->dialect = ksmbd_negotiate_smb_dialect(work->request_buf);
Namjae Jeone2f34482021-03-16 10:49:09 +0900441 ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
442
443 if (command == SMB2_NEGOTIATE_HE) {
Namjae Jeone5066492021-03-30 12:35:23 +0900444 struct smb2_hdr *smb2_hdr = work->request_buf;
Namjae Jeone2f34482021-03-16 10:49:09 +0900445
446 if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
447 ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
448 command = SMB_COM_NEGOTIATE;
449 }
450 }
451
452 if (command == SMB2_NEGOTIATE_HE) {
453 ret = smb2_handle_negotiate(work);
454 init_smb2_neg_rsp(work);
455 return ret;
456 }
457
458 if (command == SMB_COM_NEGOTIATE) {
459 if (__smb2_negotiate(conn)) {
460 conn->need_neg = true;
461 init_smb3_11_server(conn);
462 init_smb2_neg_rsp(work);
463 ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
464 return 0;
465 }
466 return smb_handle_negotiate(work);
467 }
468
Namjae Jeonbde16942021-06-28 15:23:19 +0900469 pr_err("Unknown SMB negotiation command: %u\n", command);
Namjae Jeone2f34482021-03-16 10:49:09 +0900470 return -EINVAL;
471}
472
473enum SHARED_MODE_ERRORS {
474 SHARE_DELETE_ERROR,
475 SHARE_READ_ERROR,
476 SHARE_WRITE_ERROR,
477 FILE_READ_ERROR,
478 FILE_WRITE_ERROR,
479 FILE_DELETE_ERROR,
480};
481
482static const char * const shared_mode_errors[] = {
483 "Current access mode does not permit SHARE_DELETE",
484 "Current access mode does not permit SHARE_READ",
485 "Current access mode does not permit SHARE_WRITE",
486 "Desired access mode does not permit FILE_READ",
487 "Desired access mode does not permit FILE_WRITE",
488 "Desired access mode does not permit FILE_DELETE",
489};
490
Namjae Jeon64b39f42021-03-30 14:25:35 +0900491static void smb_shared_mode_error(int error, struct ksmbd_file *prev_fp,
Namjae Jeon070fb212021-05-26 17:57:12 +0900492 struct ksmbd_file *curr_fp)
Namjae Jeone2f34482021-03-16 10:49:09 +0900493{
494 ksmbd_debug(SMB, "%s\n", shared_mode_errors[error]);
495 ksmbd_debug(SMB, "Current mode: 0x%x Desired mode: 0x%x\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900496 prev_fp->saccess, curr_fp->daccess);
Namjae Jeone2f34482021-03-16 10:49:09 +0900497}
498
499int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
500{
501 int rc = 0;
502 struct ksmbd_file *prev_fp;
Namjae Jeone2f34482021-03-16 10:49:09 +0900503
504 /*
505 * Lookup fp in master fp list, and check desired access and
506 * shared mode between previous open and current open.
507 */
508 read_lock(&curr_fp->f_ci->m_lock);
Namjae Jeon6f3d5ee2021-06-18 10:28:52 +0900509 list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
Namjae Jeonab0b2632021-06-29 09:20:13 +0900510 if (file_inode(filp) != file_inode(prev_fp->filp))
Namjae Jeone2f34482021-03-16 10:49:09 +0900511 continue;
512
513 if (filp == prev_fp->filp)
514 continue;
515
516 if (ksmbd_stream_fd(prev_fp) && ksmbd_stream_fd(curr_fp))
517 if (strcmp(prev_fp->stream.name, curr_fp->stream.name))
518 continue;
519
Namjae Jeone2f34482021-03-16 10:49:09 +0900520 if (prev_fp->attrib_only != curr_fp->attrib_only)
521 continue;
522
523 if (!(prev_fp->saccess & FILE_SHARE_DELETE_LE) &&
Namjae Jeon64b39f42021-03-30 14:25:35 +0900524 curr_fp->daccess & FILE_DELETE_LE) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900525 smb_shared_mode_error(SHARE_DELETE_ERROR,
526 prev_fp,
527 curr_fp);
528 rc = -EPERM;
529 break;
530 }
531
532 /*
533 * Only check FILE_SHARE_DELETE if stream opened and
534 * normal file opened.
535 */
536 if (ksmbd_stream_fd(prev_fp) && !ksmbd_stream_fd(curr_fp))
537 continue;
538
539 if (!(prev_fp->saccess & FILE_SHARE_READ_LE) &&
Namjae Jeon64b39f42021-03-30 14:25:35 +0900540 curr_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900541 smb_shared_mode_error(SHARE_READ_ERROR,
542 prev_fp,
543 curr_fp);
544 rc = -EPERM;
545 break;
546 }
547
548 if (!(prev_fp->saccess & FILE_SHARE_WRITE_LE) &&
Namjae Jeon64b39f42021-03-30 14:25:35 +0900549 curr_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900550 smb_shared_mode_error(SHARE_WRITE_ERROR,
551 prev_fp,
552 curr_fp);
553 rc = -EPERM;
554 break;
555 }
556
Namjae Jeon64b39f42021-03-30 14:25:35 +0900557 if (prev_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE) &&
558 !(curr_fp->saccess & FILE_SHARE_READ_LE)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900559 smb_shared_mode_error(FILE_READ_ERROR,
560 prev_fp,
561 curr_fp);
562 rc = -EPERM;
563 break;
564 }
565
Namjae Jeon64b39f42021-03-30 14:25:35 +0900566 if (prev_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE) &&
567 !(curr_fp->saccess & FILE_SHARE_WRITE_LE)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900568 smb_shared_mode_error(FILE_WRITE_ERROR,
569 prev_fp,
570 curr_fp);
571 rc = -EPERM;
572 break;
573 }
574
575 if (prev_fp->daccess & FILE_DELETE_LE &&
Namjae Jeon64b39f42021-03-30 14:25:35 +0900576 !(curr_fp->saccess & FILE_SHARE_DELETE_LE)) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900577 smb_shared_mode_error(FILE_DELETE_ERROR,
578 prev_fp,
579 curr_fp);
580 rc = -EPERM;
581 break;
582 }
583 }
584 read_unlock(&curr_fp->f_ci->m_lock);
585
586 return rc;
587}
588
589bool is_asterisk(char *p)
590{
591 return p && p[0] == '*';
592}
593
594int ksmbd_override_fsids(struct ksmbd_work *work)
595{
596 struct ksmbd_session *sess = work->sess;
597 struct ksmbd_share_config *share = work->tcon->share_conf;
598 struct cred *cred;
599 struct group_info *gi;
600 unsigned int uid;
601 unsigned int gid;
602
603 uid = user_uid(sess->user);
604 gid = user_gid(sess->user);
605 if (share->force_uid != KSMBD_SHARE_INVALID_UID)
606 uid = share->force_uid;
607 if (share->force_gid != KSMBD_SHARE_INVALID_GID)
608 gid = share->force_gid;
609
610 cred = prepare_kernel_cred(NULL);
611 if (!cred)
612 return -ENOMEM;
613
614 cred->fsuid = make_kuid(current_user_ns(), uid);
615 cred->fsgid = make_kgid(current_user_ns(), gid);
616
617 gi = groups_alloc(0);
618 if (!gi) {
619 abort_creds(cred);
620 return -ENOMEM;
621 }
622 set_groups(cred, gi);
623 put_group_info(gi);
624
625 if (!uid_eq(cred->fsuid, GLOBAL_ROOT_UID))
626 cred->cap_effective = cap_drop_fs_set(cred->cap_effective);
627
Namjae Jeon64b39f42021-03-30 14:25:35 +0900628 WARN_ON(work->saved_cred);
Namjae Jeone2f34482021-03-16 10:49:09 +0900629 work->saved_cred = override_creds(cred);
630 if (!work->saved_cred) {
631 abort_creds(cred);
632 return -EINVAL;
633 }
634 return 0;
635}
636
637void ksmbd_revert_fsids(struct ksmbd_work *work)
638{
639 const struct cred *cred;
640
Namjae Jeon64b39f42021-03-30 14:25:35 +0900641 WARN_ON(!work->saved_cred);
Namjae Jeone2f34482021-03-16 10:49:09 +0900642
643 cred = current_cred();
644 revert_creds(work->saved_cred);
645 put_cred(cred);
646 work->saved_cred = NULL;
647}
648
649__le32 smb_map_generic_desired_access(__le32 daccess)
650{
651 if (daccess & FILE_GENERIC_READ_LE) {
652 daccess |= cpu_to_le32(GENERIC_READ_FLAGS);
653 daccess &= ~FILE_GENERIC_READ_LE;
654 }
655
656 if (daccess & FILE_GENERIC_WRITE_LE) {
657 daccess |= cpu_to_le32(GENERIC_WRITE_FLAGS);
658 daccess &= ~FILE_GENERIC_WRITE_LE;
659 }
660
661 if (daccess & FILE_GENERIC_EXECUTE_LE) {
662 daccess |= cpu_to_le32(GENERIC_EXECUTE_FLAGS);
663 daccess &= ~FILE_GENERIC_EXECUTE_LE;
664 }
665
666 if (daccess & FILE_GENERIC_ALL_LE) {
667 daccess |= cpu_to_le32(GENERIC_ALL_FLAGS);
668 daccess &= ~FILE_GENERIC_ALL_LE;
669 }
670
671 return daccess;
672}