xref: /openbmc/linux/fs/smb/server/smb_common.c (revision 38c8a9a52082579090e34c033d439ed2cd1a462d)
1*38c8a9a5SSteve French // SPDX-License-Identifier: GPL-2.0-or-later
2*38c8a9a5SSteve French /*
3*38c8a9a5SSteve French  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
4*38c8a9a5SSteve French  *   Copyright (C) 2018 Namjae Jeon <linkinjeon@kernel.org>
5*38c8a9a5SSteve French  */
6*38c8a9a5SSteve French 
7*38c8a9a5SSteve French #include <linux/user_namespace.h>
8*38c8a9a5SSteve French 
9*38c8a9a5SSteve French #include "smb_common.h"
10*38c8a9a5SSteve French #include "server.h"
11*38c8a9a5SSteve French #include "misc.h"
12*38c8a9a5SSteve French #include "smbstatus.h"
13*38c8a9a5SSteve French #include "connection.h"
14*38c8a9a5SSteve French #include "ksmbd_work.h"
15*38c8a9a5SSteve French #include "mgmt/user_session.h"
16*38c8a9a5SSteve French #include "mgmt/user_config.h"
17*38c8a9a5SSteve French #include "mgmt/tree_connect.h"
18*38c8a9a5SSteve French #include "mgmt/share_config.h"
19*38c8a9a5SSteve French 
20*38c8a9a5SSteve French /*for shortname implementation */
21*38c8a9a5SSteve French static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
22*38c8a9a5SSteve French #define MANGLE_BASE (sizeof(basechars) / sizeof(char) - 1)
23*38c8a9a5SSteve French #define MAGIC_CHAR '~'
24*38c8a9a5SSteve French #define PERIOD '.'
25*38c8a9a5SSteve French #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
26*38c8a9a5SSteve French 
27*38c8a9a5SSteve French struct smb_protocol {
28*38c8a9a5SSteve French 	int		index;
29*38c8a9a5SSteve French 	char		*name;
30*38c8a9a5SSteve French 	char		*prot;
31*38c8a9a5SSteve French 	__u16		prot_id;
32*38c8a9a5SSteve French };
33*38c8a9a5SSteve French 
34*38c8a9a5SSteve French static struct smb_protocol smb1_protos[] = {
35*38c8a9a5SSteve French 	{
36*38c8a9a5SSteve French 		SMB21_PROT,
37*38c8a9a5SSteve French 		"\2SMB 2.1",
38*38c8a9a5SSteve French 		"SMB2_10",
39*38c8a9a5SSteve French 		SMB21_PROT_ID
40*38c8a9a5SSteve French 	},
41*38c8a9a5SSteve French 	{
42*38c8a9a5SSteve French 		SMB2X_PROT,
43*38c8a9a5SSteve French 		"\2SMB 2.???",
44*38c8a9a5SSteve French 		"SMB2_22",
45*38c8a9a5SSteve French 		SMB2X_PROT_ID
46*38c8a9a5SSteve French 	},
47*38c8a9a5SSteve French };
48*38c8a9a5SSteve French 
49*38c8a9a5SSteve French static struct smb_protocol smb2_protos[] = {
50*38c8a9a5SSteve French 	{
51*38c8a9a5SSteve French 		SMB21_PROT,
52*38c8a9a5SSteve French 		"\2SMB 2.1",
53*38c8a9a5SSteve French 		"SMB2_10",
54*38c8a9a5SSteve French 		SMB21_PROT_ID
55*38c8a9a5SSteve French 	},
56*38c8a9a5SSteve French 	{
57*38c8a9a5SSteve French 		SMB30_PROT,
58*38c8a9a5SSteve French 		"\2SMB 3.0",
59*38c8a9a5SSteve French 		"SMB3_00",
60*38c8a9a5SSteve French 		SMB30_PROT_ID
61*38c8a9a5SSteve French 	},
62*38c8a9a5SSteve French 	{
63*38c8a9a5SSteve French 		SMB302_PROT,
64*38c8a9a5SSteve French 		"\2SMB 3.02",
65*38c8a9a5SSteve French 		"SMB3_02",
66*38c8a9a5SSteve French 		SMB302_PROT_ID
67*38c8a9a5SSteve French 	},
68*38c8a9a5SSteve French 	{
69*38c8a9a5SSteve French 		SMB311_PROT,
70*38c8a9a5SSteve French 		"\2SMB 3.1.1",
71*38c8a9a5SSteve French 		"SMB3_11",
72*38c8a9a5SSteve French 		SMB311_PROT_ID
73*38c8a9a5SSteve French 	},
74*38c8a9a5SSteve French };
75*38c8a9a5SSteve French 
76*38c8a9a5SSteve French unsigned int ksmbd_server_side_copy_max_chunk_count(void)
77*38c8a9a5SSteve French {
78*38c8a9a5SSteve French 	return 256;
79*38c8a9a5SSteve French }
80*38c8a9a5SSteve French 
81*38c8a9a5SSteve French unsigned int ksmbd_server_side_copy_max_chunk_size(void)
82*38c8a9a5SSteve French {
83*38c8a9a5SSteve French 	return (2U << 30) - 1;
84*38c8a9a5SSteve French }
85*38c8a9a5SSteve French 
86*38c8a9a5SSteve French unsigned int ksmbd_server_side_copy_max_total_size(void)
87*38c8a9a5SSteve French {
88*38c8a9a5SSteve French 	return (2U << 30) - 1;
89*38c8a9a5SSteve French }
90*38c8a9a5SSteve French 
91*38c8a9a5SSteve French inline int ksmbd_min_protocol(void)
92*38c8a9a5SSteve French {
93*38c8a9a5SSteve French 	return SMB21_PROT;
94*38c8a9a5SSteve French }
95*38c8a9a5SSteve French 
96*38c8a9a5SSteve French inline int ksmbd_max_protocol(void)
97*38c8a9a5SSteve French {
98*38c8a9a5SSteve French 	return SMB311_PROT;
99*38c8a9a5SSteve French }
100*38c8a9a5SSteve French 
101*38c8a9a5SSteve French int ksmbd_lookup_protocol_idx(char *str)
102*38c8a9a5SSteve French {
103*38c8a9a5SSteve French 	int offt = ARRAY_SIZE(smb1_protos) - 1;
104*38c8a9a5SSteve French 	int len = strlen(str);
105*38c8a9a5SSteve French 
106*38c8a9a5SSteve French 	while (offt >= 0) {
107*38c8a9a5SSteve French 		if (!strncmp(str, smb1_protos[offt].prot, len)) {
108*38c8a9a5SSteve French 			ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
109*38c8a9a5SSteve French 				    smb1_protos[offt].prot, offt);
110*38c8a9a5SSteve French 			return smb1_protos[offt].index;
111*38c8a9a5SSteve French 		}
112*38c8a9a5SSteve French 		offt--;
113*38c8a9a5SSteve French 	}
114*38c8a9a5SSteve French 
115*38c8a9a5SSteve French 	offt = ARRAY_SIZE(smb2_protos) - 1;
116*38c8a9a5SSteve French 	while (offt >= 0) {
117*38c8a9a5SSteve French 		if (!strncmp(str, smb2_protos[offt].prot, len)) {
118*38c8a9a5SSteve French 			ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
119*38c8a9a5SSteve French 				    smb2_protos[offt].prot, offt);
120*38c8a9a5SSteve French 			return smb2_protos[offt].index;
121*38c8a9a5SSteve French 		}
122*38c8a9a5SSteve French 		offt--;
123*38c8a9a5SSteve French 	}
124*38c8a9a5SSteve French 	return -1;
125*38c8a9a5SSteve French }
126*38c8a9a5SSteve French 
127*38c8a9a5SSteve French /**
128*38c8a9a5SSteve French  * ksmbd_verify_smb_message() - check for valid smb2 request header
129*38c8a9a5SSteve French  * @work:	smb work
130*38c8a9a5SSteve French  *
131*38c8a9a5SSteve French  * check for valid smb signature and packet direction(request/response)
132*38c8a9a5SSteve French  *
133*38c8a9a5SSteve French  * Return:      0 on success, otherwise -EINVAL
134*38c8a9a5SSteve French  */
135*38c8a9a5SSteve French int ksmbd_verify_smb_message(struct ksmbd_work *work)
136*38c8a9a5SSteve French {
137*38c8a9a5SSteve French 	struct smb2_hdr *smb2_hdr = ksmbd_req_buf_next(work);
138*38c8a9a5SSteve French 	struct smb_hdr *hdr;
139*38c8a9a5SSteve French 
140*38c8a9a5SSteve French 	if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
141*38c8a9a5SSteve French 		return ksmbd_smb2_check_message(work);
142*38c8a9a5SSteve French 
143*38c8a9a5SSteve French 	hdr = work->request_buf;
144*38c8a9a5SSteve French 	if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER &&
145*38c8a9a5SSteve French 	    hdr->Command == SMB_COM_NEGOTIATE) {
146*38c8a9a5SSteve French 		work->conn->outstanding_credits++;
147*38c8a9a5SSteve French 		return 0;
148*38c8a9a5SSteve French 	}
149*38c8a9a5SSteve French 
150*38c8a9a5SSteve French 	return -EINVAL;
151*38c8a9a5SSteve French }
152*38c8a9a5SSteve French 
153*38c8a9a5SSteve French /**
154*38c8a9a5SSteve French  * ksmbd_smb_request() - check for valid smb request type
155*38c8a9a5SSteve French  * @conn:	connection instance
156*38c8a9a5SSteve French  *
157*38c8a9a5SSteve French  * Return:      true on success, otherwise false
158*38c8a9a5SSteve French  */
159*38c8a9a5SSteve French bool ksmbd_smb_request(struct ksmbd_conn *conn)
160*38c8a9a5SSteve French {
161*38c8a9a5SSteve French 	return conn->request_buf[0] == 0;
162*38c8a9a5SSteve French }
163*38c8a9a5SSteve French 
164*38c8a9a5SSteve French static bool supported_protocol(int idx)
165*38c8a9a5SSteve French {
166*38c8a9a5SSteve French 	if (idx == SMB2X_PROT &&
167*38c8a9a5SSteve French 	    (server_conf.min_protocol >= SMB21_PROT ||
168*38c8a9a5SSteve French 	     server_conf.max_protocol <= SMB311_PROT))
169*38c8a9a5SSteve French 		return true;
170*38c8a9a5SSteve French 
171*38c8a9a5SSteve French 	return (server_conf.min_protocol <= idx &&
172*38c8a9a5SSteve French 		idx <= server_conf.max_protocol);
173*38c8a9a5SSteve French }
174*38c8a9a5SSteve French 
175*38c8a9a5SSteve French static char *next_dialect(char *dialect, int *next_off, int bcount)
176*38c8a9a5SSteve French {
177*38c8a9a5SSteve French 	dialect = dialect + *next_off;
178*38c8a9a5SSteve French 	*next_off = strnlen(dialect, bcount);
179*38c8a9a5SSteve French 	if (dialect[*next_off] != '\0')
180*38c8a9a5SSteve French 		return NULL;
181*38c8a9a5SSteve French 	return dialect;
182*38c8a9a5SSteve French }
183*38c8a9a5SSteve French 
184*38c8a9a5SSteve French static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count)
185*38c8a9a5SSteve French {
186*38c8a9a5SSteve French 	int i, seq_num, bcount, next;
187*38c8a9a5SSteve French 	char *dialect;
188*38c8a9a5SSteve French 
189*38c8a9a5SSteve French 	for (i = ARRAY_SIZE(smb1_protos) - 1; i >= 0; i--) {
190*38c8a9a5SSteve French 		seq_num = 0;
191*38c8a9a5SSteve French 		next = 0;
192*38c8a9a5SSteve French 		dialect = cli_dialects;
193*38c8a9a5SSteve French 		bcount = le16_to_cpu(byte_count);
194*38c8a9a5SSteve French 		do {
195*38c8a9a5SSteve French 			dialect = next_dialect(dialect, &next, bcount);
196*38c8a9a5SSteve French 			if (!dialect)
197*38c8a9a5SSteve French 				break;
198*38c8a9a5SSteve French 			ksmbd_debug(SMB, "client requested dialect %s\n",
199*38c8a9a5SSteve French 				    dialect);
200*38c8a9a5SSteve French 			if (!strcmp(dialect, smb1_protos[i].name)) {
201*38c8a9a5SSteve French 				if (supported_protocol(smb1_protos[i].index)) {
202*38c8a9a5SSteve French 					ksmbd_debug(SMB,
203*38c8a9a5SSteve French 						    "selected %s dialect\n",
204*38c8a9a5SSteve French 						    smb1_protos[i].name);
205*38c8a9a5SSteve French 					if (smb1_protos[i].index == SMB1_PROT)
206*38c8a9a5SSteve French 						return seq_num;
207*38c8a9a5SSteve French 					return smb1_protos[i].prot_id;
208*38c8a9a5SSteve French 				}
209*38c8a9a5SSteve French 			}
210*38c8a9a5SSteve French 			seq_num++;
211*38c8a9a5SSteve French 			bcount -= (++next);
212*38c8a9a5SSteve French 		} while (bcount > 0);
213*38c8a9a5SSteve French 	}
214*38c8a9a5SSteve French 
215*38c8a9a5SSteve French 	return BAD_PROT_ID;
216*38c8a9a5SSteve French }
217*38c8a9a5SSteve French 
218*38c8a9a5SSteve French int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
219*38c8a9a5SSteve French {
220*38c8a9a5SSteve French 	int i;
221*38c8a9a5SSteve French 	int count;
222*38c8a9a5SSteve French 
223*38c8a9a5SSteve French 	for (i = ARRAY_SIZE(smb2_protos) - 1; i >= 0; i--) {
224*38c8a9a5SSteve French 		count = le16_to_cpu(dialects_count);
225*38c8a9a5SSteve French 		while (--count >= 0) {
226*38c8a9a5SSteve French 			ksmbd_debug(SMB, "client requested dialect 0x%x\n",
227*38c8a9a5SSteve French 				    le16_to_cpu(cli_dialects[count]));
228*38c8a9a5SSteve French 			if (le16_to_cpu(cli_dialects[count]) !=
229*38c8a9a5SSteve French 					smb2_protos[i].prot_id)
230*38c8a9a5SSteve French 				continue;
231*38c8a9a5SSteve French 
232*38c8a9a5SSteve French 			if (supported_protocol(smb2_protos[i].index)) {
233*38c8a9a5SSteve French 				ksmbd_debug(SMB, "selected %s dialect\n",
234*38c8a9a5SSteve French 					    smb2_protos[i].name);
235*38c8a9a5SSteve French 				return smb2_protos[i].prot_id;
236*38c8a9a5SSteve French 			}
237*38c8a9a5SSteve French 		}
238*38c8a9a5SSteve French 	}
239*38c8a9a5SSteve French 
240*38c8a9a5SSteve French 	return BAD_PROT_ID;
241*38c8a9a5SSteve French }
242*38c8a9a5SSteve French 
243*38c8a9a5SSteve French static int ksmbd_negotiate_smb_dialect(void *buf)
244*38c8a9a5SSteve French {
245*38c8a9a5SSteve French 	int smb_buf_length = get_rfc1002_len(buf);
246*38c8a9a5SSteve French 	__le32 proto = ((struct smb2_hdr *)smb2_get_msg(buf))->ProtocolId;
247*38c8a9a5SSteve French 
248*38c8a9a5SSteve French 	if (proto == SMB2_PROTO_NUMBER) {
249*38c8a9a5SSteve French 		struct smb2_negotiate_req *req;
250*38c8a9a5SSteve French 		int smb2_neg_size =
251*38c8a9a5SSteve French 			offsetof(struct smb2_negotiate_req, Dialects);
252*38c8a9a5SSteve French 
253*38c8a9a5SSteve French 		req = (struct smb2_negotiate_req *)smb2_get_msg(buf);
254*38c8a9a5SSteve French 		if (smb2_neg_size > smb_buf_length)
255*38c8a9a5SSteve French 			goto err_out;
256*38c8a9a5SSteve French 
257*38c8a9a5SSteve French 		if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
258*38c8a9a5SSteve French 		    smb_buf_length)
259*38c8a9a5SSteve French 			goto err_out;
260*38c8a9a5SSteve French 
261*38c8a9a5SSteve French 		return ksmbd_lookup_dialect_by_id(req->Dialects,
262*38c8a9a5SSteve French 						  req->DialectCount);
263*38c8a9a5SSteve French 	}
264*38c8a9a5SSteve French 
265*38c8a9a5SSteve French 	proto = *(__le32 *)((struct smb_hdr *)buf)->Protocol;
266*38c8a9a5SSteve French 	if (proto == SMB1_PROTO_NUMBER) {
267*38c8a9a5SSteve French 		struct smb_negotiate_req *req;
268*38c8a9a5SSteve French 
269*38c8a9a5SSteve French 		req = (struct smb_negotiate_req *)buf;
270*38c8a9a5SSteve French 		if (le16_to_cpu(req->ByteCount) < 2)
271*38c8a9a5SSteve French 			goto err_out;
272*38c8a9a5SSteve French 
273*38c8a9a5SSteve French 		if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 +
274*38c8a9a5SSteve French 			le16_to_cpu(req->ByteCount) > smb_buf_length) {
275*38c8a9a5SSteve French 			goto err_out;
276*38c8a9a5SSteve French 		}
277*38c8a9a5SSteve French 
278*38c8a9a5SSteve French 		return ksmbd_lookup_dialect_by_name(req->DialectsArray,
279*38c8a9a5SSteve French 						    req->ByteCount);
280*38c8a9a5SSteve French 	}
281*38c8a9a5SSteve French 
282*38c8a9a5SSteve French err_out:
283*38c8a9a5SSteve French 	return BAD_PROT_ID;
284*38c8a9a5SSteve French }
285*38c8a9a5SSteve French 
286*38c8a9a5SSteve French #define SMB_COM_NEGOTIATE_EX	0x0
287*38c8a9a5SSteve French 
288*38c8a9a5SSteve French /**
289*38c8a9a5SSteve French  * get_smb1_cmd_val() - get smb command value from smb header
290*38c8a9a5SSteve French  * @work:	smb work containing smb header
291*38c8a9a5SSteve French  *
292*38c8a9a5SSteve French  * Return:      smb command value
293*38c8a9a5SSteve French  */
294*38c8a9a5SSteve French static u16 get_smb1_cmd_val(struct ksmbd_work *work)
295*38c8a9a5SSteve French {
296*38c8a9a5SSteve French 	return SMB_COM_NEGOTIATE_EX;
297*38c8a9a5SSteve French }
298*38c8a9a5SSteve French 
299*38c8a9a5SSteve French /**
300*38c8a9a5SSteve French  * init_smb1_rsp_hdr() - initialize smb negotiate response header
301*38c8a9a5SSteve French  * @work:	smb work containing smb request
302*38c8a9a5SSteve French  *
303*38c8a9a5SSteve French  * Return:      0 on success, otherwise -EINVAL
304*38c8a9a5SSteve French  */
305*38c8a9a5SSteve French static int init_smb1_rsp_hdr(struct ksmbd_work *work)
306*38c8a9a5SSteve French {
307*38c8a9a5SSteve French 	struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
308*38c8a9a5SSteve French 	struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
309*38c8a9a5SSteve French 
310*38c8a9a5SSteve French 	/*
311*38c8a9a5SSteve French 	 * Remove 4 byte direct TCP header.
312*38c8a9a5SSteve French 	 */
313*38c8a9a5SSteve French 	*(__be32 *)work->response_buf =
314*38c8a9a5SSteve French 		cpu_to_be32(sizeof(struct smb_hdr) - 4);
315*38c8a9a5SSteve French 
316*38c8a9a5SSteve French 	rsp_hdr->Command = SMB_COM_NEGOTIATE;
317*38c8a9a5SSteve French 	*(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
318*38c8a9a5SSteve French 	rsp_hdr->Flags = SMBFLG_RESPONSE;
319*38c8a9a5SSteve French 	rsp_hdr->Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
320*38c8a9a5SSteve French 		SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
321*38c8a9a5SSteve French 	rsp_hdr->Pid = rcv_hdr->Pid;
322*38c8a9a5SSteve French 	rsp_hdr->Mid = rcv_hdr->Mid;
323*38c8a9a5SSteve French 	return 0;
324*38c8a9a5SSteve French }
325*38c8a9a5SSteve French 
326*38c8a9a5SSteve French /**
327*38c8a9a5SSteve French  * smb1_check_user_session() - check for valid session for a user
328*38c8a9a5SSteve French  * @work:	smb work containing smb request buffer
329*38c8a9a5SSteve French  *
330*38c8a9a5SSteve French  * Return:      0 on success, otherwise error
331*38c8a9a5SSteve French  */
332*38c8a9a5SSteve French static int smb1_check_user_session(struct ksmbd_work *work)
333*38c8a9a5SSteve French {
334*38c8a9a5SSteve French 	unsigned int cmd = work->conn->ops->get_cmd_val(work);
335*38c8a9a5SSteve French 
336*38c8a9a5SSteve French 	if (cmd == SMB_COM_NEGOTIATE_EX)
337*38c8a9a5SSteve French 		return 0;
338*38c8a9a5SSteve French 
339*38c8a9a5SSteve French 	return -EINVAL;
340*38c8a9a5SSteve French }
341*38c8a9a5SSteve French 
342*38c8a9a5SSteve French /**
343*38c8a9a5SSteve French  * smb1_allocate_rsp_buf() - allocate response buffer for a command
344*38c8a9a5SSteve French  * @work:	smb work containing smb request
345*38c8a9a5SSteve French  *
346*38c8a9a5SSteve French  * Return:      0 on success, otherwise -ENOMEM
347*38c8a9a5SSteve French  */
348*38c8a9a5SSteve French static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
349*38c8a9a5SSteve French {
350*38c8a9a5SSteve French 	work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
351*38c8a9a5SSteve French 			GFP_KERNEL | __GFP_ZERO);
352*38c8a9a5SSteve French 	work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
353*38c8a9a5SSteve French 
354*38c8a9a5SSteve French 	if (!work->response_buf) {
355*38c8a9a5SSteve French 		pr_err("Failed to allocate %u bytes buffer\n",
356*38c8a9a5SSteve French 				MAX_CIFS_SMALL_BUFFER_SIZE);
357*38c8a9a5SSteve French 		return -ENOMEM;
358*38c8a9a5SSteve French 	}
359*38c8a9a5SSteve French 
360*38c8a9a5SSteve French 	return 0;
361*38c8a9a5SSteve French }
362*38c8a9a5SSteve French 
363*38c8a9a5SSteve French static struct smb_version_ops smb1_server_ops = {
364*38c8a9a5SSteve French 	.get_cmd_val = get_smb1_cmd_val,
365*38c8a9a5SSteve French 	.init_rsp_hdr = init_smb1_rsp_hdr,
366*38c8a9a5SSteve French 	.allocate_rsp_buf = smb1_allocate_rsp_buf,
367*38c8a9a5SSteve French 	.check_user_session = smb1_check_user_session,
368*38c8a9a5SSteve French };
369*38c8a9a5SSteve French 
370*38c8a9a5SSteve French static int smb1_negotiate(struct ksmbd_work *work)
371*38c8a9a5SSteve French {
372*38c8a9a5SSteve French 	return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
373*38c8a9a5SSteve French }
374*38c8a9a5SSteve French 
375*38c8a9a5SSteve French static struct smb_version_cmds smb1_server_cmds[1] = {
376*38c8a9a5SSteve French 	[SMB_COM_NEGOTIATE_EX]	= { .proc = smb1_negotiate, },
377*38c8a9a5SSteve French };
378*38c8a9a5SSteve French 
379*38c8a9a5SSteve French static void init_smb1_server(struct ksmbd_conn *conn)
380*38c8a9a5SSteve French {
381*38c8a9a5SSteve French 	conn->ops = &smb1_server_ops;
382*38c8a9a5SSteve French 	conn->cmds = smb1_server_cmds;
383*38c8a9a5SSteve French 	conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
384*38c8a9a5SSteve French }
385*38c8a9a5SSteve French 
386*38c8a9a5SSteve French void ksmbd_init_smb_server(struct ksmbd_work *work)
387*38c8a9a5SSteve French {
388*38c8a9a5SSteve French 	struct ksmbd_conn *conn = work->conn;
389*38c8a9a5SSteve French 	__le32 proto;
390*38c8a9a5SSteve French 
391*38c8a9a5SSteve French 	if (conn->need_neg == false)
392*38c8a9a5SSteve French 		return;
393*38c8a9a5SSteve French 
394*38c8a9a5SSteve French 	proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
395*38c8a9a5SSteve French 	if (proto == SMB1_PROTO_NUMBER)
396*38c8a9a5SSteve French 		init_smb1_server(conn);
397*38c8a9a5SSteve French 	else
398*38c8a9a5SSteve French 		init_smb3_11_server(conn);
399*38c8a9a5SSteve French }
400*38c8a9a5SSteve French 
401*38c8a9a5SSteve French int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
402*38c8a9a5SSteve French 				      struct ksmbd_file *dir,
403*38c8a9a5SSteve French 				      struct ksmbd_dir_info *d_info,
404*38c8a9a5SSteve French 				      char *search_pattern,
405*38c8a9a5SSteve French 				      int (*fn)(struct ksmbd_conn *, int,
406*38c8a9a5SSteve French 						struct ksmbd_dir_info *,
407*38c8a9a5SSteve French 						struct ksmbd_kstat *))
408*38c8a9a5SSteve French {
409*38c8a9a5SSteve French 	int i, rc = 0;
410*38c8a9a5SSteve French 	struct ksmbd_conn *conn = work->conn;
411*38c8a9a5SSteve French 	struct mnt_idmap *idmap = file_mnt_idmap(dir->filp);
412*38c8a9a5SSteve French 
413*38c8a9a5SSteve French 	for (i = 0; i < 2; i++) {
414*38c8a9a5SSteve French 		struct kstat kstat;
415*38c8a9a5SSteve French 		struct ksmbd_kstat ksmbd_kstat;
416*38c8a9a5SSteve French 		struct dentry *dentry;
417*38c8a9a5SSteve French 
418*38c8a9a5SSteve French 		if (!dir->dot_dotdot[i]) { /* fill dot entry info */
419*38c8a9a5SSteve French 			if (i == 0) {
420*38c8a9a5SSteve French 				d_info->name = ".";
421*38c8a9a5SSteve French 				d_info->name_len = 1;
422*38c8a9a5SSteve French 				dentry = dir->filp->f_path.dentry;
423*38c8a9a5SSteve French 			} else {
424*38c8a9a5SSteve French 				d_info->name = "..";
425*38c8a9a5SSteve French 				d_info->name_len = 2;
426*38c8a9a5SSteve French 				dentry = dir->filp->f_path.dentry->d_parent;
427*38c8a9a5SSteve French 			}
428*38c8a9a5SSteve French 
429*38c8a9a5SSteve French 			if (!match_pattern(d_info->name, d_info->name_len,
430*38c8a9a5SSteve French 					   search_pattern)) {
431*38c8a9a5SSteve French 				dir->dot_dotdot[i] = 1;
432*38c8a9a5SSteve French 				continue;
433*38c8a9a5SSteve French 			}
434*38c8a9a5SSteve French 
435*38c8a9a5SSteve French 			ksmbd_kstat.kstat = &kstat;
436*38c8a9a5SSteve French 			ksmbd_vfs_fill_dentry_attrs(work,
437*38c8a9a5SSteve French 						    idmap,
438*38c8a9a5SSteve French 						    dentry,
439*38c8a9a5SSteve French 						    &ksmbd_kstat);
440*38c8a9a5SSteve French 			rc = fn(conn, info_level, d_info, &ksmbd_kstat);
441*38c8a9a5SSteve French 			if (rc)
442*38c8a9a5SSteve French 				break;
443*38c8a9a5SSteve French 			if (d_info->out_buf_len <= 0)
444*38c8a9a5SSteve French 				break;
445*38c8a9a5SSteve French 
446*38c8a9a5SSteve French 			dir->dot_dotdot[i] = 1;
447*38c8a9a5SSteve French 			if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) {
448*38c8a9a5SSteve French 				d_info->out_buf_len = 0;
449*38c8a9a5SSteve French 				break;
450*38c8a9a5SSteve French 			}
451*38c8a9a5SSteve French 		}
452*38c8a9a5SSteve French 	}
453*38c8a9a5SSteve French 
454*38c8a9a5SSteve French 	return rc;
455*38c8a9a5SSteve French }
456*38c8a9a5SSteve French 
457*38c8a9a5SSteve French /**
458*38c8a9a5SSteve French  * ksmbd_extract_shortname() - get shortname from long filename
459*38c8a9a5SSteve French  * @conn:	connection instance
460*38c8a9a5SSteve French  * @longname:	source long filename
461*38c8a9a5SSteve French  * @shortname:	destination short filename
462*38c8a9a5SSteve French  *
463*38c8a9a5SSteve French  * Return:	shortname length or 0 when source long name is '.' or '..'
464*38c8a9a5SSteve French  * TODO: Though this function comforms the restriction of 8.3 Filename spec,
465*38c8a9a5SSteve French  * but the result is different with Windows 7's one. need to check.
466*38c8a9a5SSteve French  */
467*38c8a9a5SSteve French int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
468*38c8a9a5SSteve French 			    char *shortname)
469*38c8a9a5SSteve French {
470*38c8a9a5SSteve French 	const char *p;
471*38c8a9a5SSteve French 	char base[9], extension[4];
472*38c8a9a5SSteve French 	char out[13] = {0};
473*38c8a9a5SSteve French 	int baselen = 0;
474*38c8a9a5SSteve French 	int extlen = 0, len = 0;
475*38c8a9a5SSteve French 	unsigned int csum = 0;
476*38c8a9a5SSteve French 	const unsigned char *ptr;
477*38c8a9a5SSteve French 	bool dot_present = true;
478*38c8a9a5SSteve French 
479*38c8a9a5SSteve French 	p = longname;
480*38c8a9a5SSteve French 	if ((*p == '.') || (!(strcmp(p, "..")))) {
481*38c8a9a5SSteve French 		/*no mangling required */
482*38c8a9a5SSteve French 		return 0;
483*38c8a9a5SSteve French 	}
484*38c8a9a5SSteve French 
485*38c8a9a5SSteve French 	p = strrchr(longname, '.');
486*38c8a9a5SSteve French 	if (p == longname) { /*name starts with a dot*/
487*38c8a9a5SSteve French 		strscpy(extension, "___", strlen("___"));
488*38c8a9a5SSteve French 	} else {
489*38c8a9a5SSteve French 		if (p) {
490*38c8a9a5SSteve French 			p++;
491*38c8a9a5SSteve French 			while (*p && extlen < 3) {
492*38c8a9a5SSteve French 				if (*p != '.')
493*38c8a9a5SSteve French 					extension[extlen++] = toupper(*p);
494*38c8a9a5SSteve French 				p++;
495*38c8a9a5SSteve French 			}
496*38c8a9a5SSteve French 			extension[extlen] = '\0';
497*38c8a9a5SSteve French 		} else {
498*38c8a9a5SSteve French 			dot_present = false;
499*38c8a9a5SSteve French 		}
500*38c8a9a5SSteve French 	}
501*38c8a9a5SSteve French 
502*38c8a9a5SSteve French 	p = longname;
503*38c8a9a5SSteve French 	if (*p == '.') {
504*38c8a9a5SSteve French 		p++;
505*38c8a9a5SSteve French 		longname++;
506*38c8a9a5SSteve French 	}
507*38c8a9a5SSteve French 	while (*p && (baselen < 5)) {
508*38c8a9a5SSteve French 		if (*p != '.')
509*38c8a9a5SSteve French 			base[baselen++] = toupper(*p);
510*38c8a9a5SSteve French 		p++;
511*38c8a9a5SSteve French 	}
512*38c8a9a5SSteve French 
513*38c8a9a5SSteve French 	base[baselen] = MAGIC_CHAR;
514*38c8a9a5SSteve French 	memcpy(out, base, baselen + 1);
515*38c8a9a5SSteve French 
516*38c8a9a5SSteve French 	ptr = longname;
517*38c8a9a5SSteve French 	len = strlen(longname);
518*38c8a9a5SSteve French 	for (; len > 0; len--, ptr++)
519*38c8a9a5SSteve French 		csum += *ptr;
520*38c8a9a5SSteve French 
521*38c8a9a5SSteve French 	csum = csum % (MANGLE_BASE * MANGLE_BASE);
522*38c8a9a5SSteve French 	out[baselen + 1] = mangle(csum / MANGLE_BASE);
523*38c8a9a5SSteve French 	out[baselen + 2] = mangle(csum);
524*38c8a9a5SSteve French 	out[baselen + 3] = PERIOD;
525*38c8a9a5SSteve French 
526*38c8a9a5SSteve French 	if (dot_present)
527*38c8a9a5SSteve French 		memcpy(&out[baselen + 4], extension, 4);
528*38c8a9a5SSteve French 	else
529*38c8a9a5SSteve French 		out[baselen + 4] = '\0';
530*38c8a9a5SSteve French 	smbConvertToUTF16((__le16 *)shortname, out, PATH_MAX,
531*38c8a9a5SSteve French 			  conn->local_nls, 0);
532*38c8a9a5SSteve French 	len = strlen(out) * 2;
533*38c8a9a5SSteve French 	return len;
534*38c8a9a5SSteve French }
535*38c8a9a5SSteve French 
536*38c8a9a5SSteve French static int __smb2_negotiate(struct ksmbd_conn *conn)
537*38c8a9a5SSteve French {
538*38c8a9a5SSteve French 	return (conn->dialect >= SMB20_PROT_ID &&
539*38c8a9a5SSteve French 		conn->dialect <= SMB311_PROT_ID);
540*38c8a9a5SSteve French }
541*38c8a9a5SSteve French 
542*38c8a9a5SSteve French static int smb_handle_negotiate(struct ksmbd_work *work)
543*38c8a9a5SSteve French {
544*38c8a9a5SSteve French 	struct smb_negotiate_rsp *neg_rsp = work->response_buf;
545*38c8a9a5SSteve French 
546*38c8a9a5SSteve French 	ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
547*38c8a9a5SSteve French 
548*38c8a9a5SSteve French 	/* Add 2 byte bcc and 2 byte DialectIndex. */
549*38c8a9a5SSteve French 	inc_rfc1001_len(work->response_buf, 4);
550*38c8a9a5SSteve French 	neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
551*38c8a9a5SSteve French 
552*38c8a9a5SSteve French 	neg_rsp->hdr.WordCount = 1;
553*38c8a9a5SSteve French 	neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
554*38c8a9a5SSteve French 	neg_rsp->ByteCount = 0;
555*38c8a9a5SSteve French 	return 0;
556*38c8a9a5SSteve French }
557*38c8a9a5SSteve French 
558*38c8a9a5SSteve French int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
559*38c8a9a5SSteve French {
560*38c8a9a5SSteve French 	struct ksmbd_conn *conn = work->conn;
561*38c8a9a5SSteve French 	int ret;
562*38c8a9a5SSteve French 
563*38c8a9a5SSteve French 	conn->dialect =
564*38c8a9a5SSteve French 		ksmbd_negotiate_smb_dialect(work->request_buf);
565*38c8a9a5SSteve French 	ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
566*38c8a9a5SSteve French 
567*38c8a9a5SSteve French 	if (command == SMB2_NEGOTIATE_HE) {
568*38c8a9a5SSteve French 		ret = smb2_handle_negotiate(work);
569*38c8a9a5SSteve French 		return ret;
570*38c8a9a5SSteve French 	}
571*38c8a9a5SSteve French 
572*38c8a9a5SSteve French 	if (command == SMB_COM_NEGOTIATE) {
573*38c8a9a5SSteve French 		if (__smb2_negotiate(conn)) {
574*38c8a9a5SSteve French 			init_smb3_11_server(conn);
575*38c8a9a5SSteve French 			init_smb2_neg_rsp(work);
576*38c8a9a5SSteve French 			ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
577*38c8a9a5SSteve French 			return 0;
578*38c8a9a5SSteve French 		}
579*38c8a9a5SSteve French 		return smb_handle_negotiate(work);
580*38c8a9a5SSteve French 	}
581*38c8a9a5SSteve French 
582*38c8a9a5SSteve French 	pr_err("Unknown SMB negotiation command: %u\n", command);
583*38c8a9a5SSteve French 	return -EINVAL;
584*38c8a9a5SSteve French }
585*38c8a9a5SSteve French 
586*38c8a9a5SSteve French enum SHARED_MODE_ERRORS {
587*38c8a9a5SSteve French 	SHARE_DELETE_ERROR,
588*38c8a9a5SSteve French 	SHARE_READ_ERROR,
589*38c8a9a5SSteve French 	SHARE_WRITE_ERROR,
590*38c8a9a5SSteve French 	FILE_READ_ERROR,
591*38c8a9a5SSteve French 	FILE_WRITE_ERROR,
592*38c8a9a5SSteve French 	FILE_DELETE_ERROR,
593*38c8a9a5SSteve French };
594*38c8a9a5SSteve French 
595*38c8a9a5SSteve French static const char * const shared_mode_errors[] = {
596*38c8a9a5SSteve French 	"Current access mode does not permit SHARE_DELETE",
597*38c8a9a5SSteve French 	"Current access mode does not permit SHARE_READ",
598*38c8a9a5SSteve French 	"Current access mode does not permit SHARE_WRITE",
599*38c8a9a5SSteve French 	"Desired access mode does not permit FILE_READ",
600*38c8a9a5SSteve French 	"Desired access mode does not permit FILE_WRITE",
601*38c8a9a5SSteve French 	"Desired access mode does not permit FILE_DELETE",
602*38c8a9a5SSteve French };
603*38c8a9a5SSteve French 
604*38c8a9a5SSteve French static void smb_shared_mode_error(int error, struct ksmbd_file *prev_fp,
605*38c8a9a5SSteve French 				  struct ksmbd_file *curr_fp)
606*38c8a9a5SSteve French {
607*38c8a9a5SSteve French 	ksmbd_debug(SMB, "%s\n", shared_mode_errors[error]);
608*38c8a9a5SSteve French 	ksmbd_debug(SMB, "Current mode: 0x%x Desired mode: 0x%x\n",
609*38c8a9a5SSteve French 		    prev_fp->saccess, curr_fp->daccess);
610*38c8a9a5SSteve French }
611*38c8a9a5SSteve French 
612*38c8a9a5SSteve French int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
613*38c8a9a5SSteve French {
614*38c8a9a5SSteve French 	int rc = 0;
615*38c8a9a5SSteve French 	struct ksmbd_file *prev_fp;
616*38c8a9a5SSteve French 
617*38c8a9a5SSteve French 	/*
618*38c8a9a5SSteve French 	 * Lookup fp in master fp list, and check desired access and
619*38c8a9a5SSteve French 	 * shared mode between previous open and current open.
620*38c8a9a5SSteve French 	 */
621*38c8a9a5SSteve French 	read_lock(&curr_fp->f_ci->m_lock);
622*38c8a9a5SSteve French 	list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
623*38c8a9a5SSteve French 		if (file_inode(filp) != file_inode(prev_fp->filp))
624*38c8a9a5SSteve French 			continue;
625*38c8a9a5SSteve French 
626*38c8a9a5SSteve French 		if (filp == prev_fp->filp)
627*38c8a9a5SSteve French 			continue;
628*38c8a9a5SSteve French 
629*38c8a9a5SSteve French 		if (ksmbd_stream_fd(prev_fp) && ksmbd_stream_fd(curr_fp))
630*38c8a9a5SSteve French 			if (strcmp(prev_fp->stream.name, curr_fp->stream.name))
631*38c8a9a5SSteve French 				continue;
632*38c8a9a5SSteve French 
633*38c8a9a5SSteve French 		if (prev_fp->attrib_only != curr_fp->attrib_only)
634*38c8a9a5SSteve French 			continue;
635*38c8a9a5SSteve French 
636*38c8a9a5SSteve French 		if (!(prev_fp->saccess & FILE_SHARE_DELETE_LE) &&
637*38c8a9a5SSteve French 		    curr_fp->daccess & FILE_DELETE_LE) {
638*38c8a9a5SSteve French 			smb_shared_mode_error(SHARE_DELETE_ERROR,
639*38c8a9a5SSteve French 					      prev_fp,
640*38c8a9a5SSteve French 					      curr_fp);
641*38c8a9a5SSteve French 			rc = -EPERM;
642*38c8a9a5SSteve French 			break;
643*38c8a9a5SSteve French 		}
644*38c8a9a5SSteve French 
645*38c8a9a5SSteve French 		/*
646*38c8a9a5SSteve French 		 * Only check FILE_SHARE_DELETE if stream opened and
647*38c8a9a5SSteve French 		 * normal file opened.
648*38c8a9a5SSteve French 		 */
649*38c8a9a5SSteve French 		if (ksmbd_stream_fd(prev_fp) && !ksmbd_stream_fd(curr_fp))
650*38c8a9a5SSteve French 			continue;
651*38c8a9a5SSteve French 
652*38c8a9a5SSteve French 		if (!(prev_fp->saccess & FILE_SHARE_READ_LE) &&
653*38c8a9a5SSteve French 		    curr_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE)) {
654*38c8a9a5SSteve French 			smb_shared_mode_error(SHARE_READ_ERROR,
655*38c8a9a5SSteve French 					      prev_fp,
656*38c8a9a5SSteve French 					      curr_fp);
657*38c8a9a5SSteve French 			rc = -EPERM;
658*38c8a9a5SSteve French 			break;
659*38c8a9a5SSteve French 		}
660*38c8a9a5SSteve French 
661*38c8a9a5SSteve French 		if (!(prev_fp->saccess & FILE_SHARE_WRITE_LE) &&
662*38c8a9a5SSteve French 		    curr_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE)) {
663*38c8a9a5SSteve French 			smb_shared_mode_error(SHARE_WRITE_ERROR,
664*38c8a9a5SSteve French 					      prev_fp,
665*38c8a9a5SSteve French 					      curr_fp);
666*38c8a9a5SSteve French 			rc = -EPERM;
667*38c8a9a5SSteve French 			break;
668*38c8a9a5SSteve French 		}
669*38c8a9a5SSteve French 
670*38c8a9a5SSteve French 		if (prev_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE) &&
671*38c8a9a5SSteve French 		    !(curr_fp->saccess & FILE_SHARE_READ_LE)) {
672*38c8a9a5SSteve French 			smb_shared_mode_error(FILE_READ_ERROR,
673*38c8a9a5SSteve French 					      prev_fp,
674*38c8a9a5SSteve French 					      curr_fp);
675*38c8a9a5SSteve French 			rc = -EPERM;
676*38c8a9a5SSteve French 			break;
677*38c8a9a5SSteve French 		}
678*38c8a9a5SSteve French 
679*38c8a9a5SSteve French 		if (prev_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE) &&
680*38c8a9a5SSteve French 		    !(curr_fp->saccess & FILE_SHARE_WRITE_LE)) {
681*38c8a9a5SSteve French 			smb_shared_mode_error(FILE_WRITE_ERROR,
682*38c8a9a5SSteve French 					      prev_fp,
683*38c8a9a5SSteve French 					      curr_fp);
684*38c8a9a5SSteve French 			rc = -EPERM;
685*38c8a9a5SSteve French 			break;
686*38c8a9a5SSteve French 		}
687*38c8a9a5SSteve French 
688*38c8a9a5SSteve French 		if (prev_fp->daccess & FILE_DELETE_LE &&
689*38c8a9a5SSteve French 		    !(curr_fp->saccess & FILE_SHARE_DELETE_LE)) {
690*38c8a9a5SSteve French 			smb_shared_mode_error(FILE_DELETE_ERROR,
691*38c8a9a5SSteve French 					      prev_fp,
692*38c8a9a5SSteve French 					      curr_fp);
693*38c8a9a5SSteve French 			rc = -EPERM;
694*38c8a9a5SSteve French 			break;
695*38c8a9a5SSteve French 		}
696*38c8a9a5SSteve French 	}
697*38c8a9a5SSteve French 	read_unlock(&curr_fp->f_ci->m_lock);
698*38c8a9a5SSteve French 
699*38c8a9a5SSteve French 	return rc;
700*38c8a9a5SSteve French }
701*38c8a9a5SSteve French 
702*38c8a9a5SSteve French bool is_asterisk(char *p)
703*38c8a9a5SSteve French {
704*38c8a9a5SSteve French 	return p && p[0] == '*';
705*38c8a9a5SSteve French }
706*38c8a9a5SSteve French 
707*38c8a9a5SSteve French int ksmbd_override_fsids(struct ksmbd_work *work)
708*38c8a9a5SSteve French {
709*38c8a9a5SSteve French 	struct ksmbd_session *sess = work->sess;
710*38c8a9a5SSteve French 	struct ksmbd_share_config *share = work->tcon->share_conf;
711*38c8a9a5SSteve French 	struct cred *cred;
712*38c8a9a5SSteve French 	struct group_info *gi;
713*38c8a9a5SSteve French 	unsigned int uid;
714*38c8a9a5SSteve French 	unsigned int gid;
715*38c8a9a5SSteve French 
716*38c8a9a5SSteve French 	uid = user_uid(sess->user);
717*38c8a9a5SSteve French 	gid = user_gid(sess->user);
718*38c8a9a5SSteve French 	if (share->force_uid != KSMBD_SHARE_INVALID_UID)
719*38c8a9a5SSteve French 		uid = share->force_uid;
720*38c8a9a5SSteve French 	if (share->force_gid != KSMBD_SHARE_INVALID_GID)
721*38c8a9a5SSteve French 		gid = share->force_gid;
722*38c8a9a5SSteve French 
723*38c8a9a5SSteve French 	cred = prepare_kernel_cred(&init_task);
724*38c8a9a5SSteve French 	if (!cred)
725*38c8a9a5SSteve French 		return -ENOMEM;
726*38c8a9a5SSteve French 
727*38c8a9a5SSteve French 	cred->fsuid = make_kuid(&init_user_ns, uid);
728*38c8a9a5SSteve French 	cred->fsgid = make_kgid(&init_user_ns, gid);
729*38c8a9a5SSteve French 
730*38c8a9a5SSteve French 	gi = groups_alloc(0);
731*38c8a9a5SSteve French 	if (!gi) {
732*38c8a9a5SSteve French 		abort_creds(cred);
733*38c8a9a5SSteve French 		return -ENOMEM;
734*38c8a9a5SSteve French 	}
735*38c8a9a5SSteve French 	set_groups(cred, gi);
736*38c8a9a5SSteve French 	put_group_info(gi);
737*38c8a9a5SSteve French 
738*38c8a9a5SSteve French 	if (!uid_eq(cred->fsuid, GLOBAL_ROOT_UID))
739*38c8a9a5SSteve French 		cred->cap_effective = cap_drop_fs_set(cred->cap_effective);
740*38c8a9a5SSteve French 
741*38c8a9a5SSteve French 	WARN_ON(work->saved_cred);
742*38c8a9a5SSteve French 	work->saved_cred = override_creds(cred);
743*38c8a9a5SSteve French 	if (!work->saved_cred) {
744*38c8a9a5SSteve French 		abort_creds(cred);
745*38c8a9a5SSteve French 		return -EINVAL;
746*38c8a9a5SSteve French 	}
747*38c8a9a5SSteve French 	return 0;
748*38c8a9a5SSteve French }
749*38c8a9a5SSteve French 
750*38c8a9a5SSteve French void ksmbd_revert_fsids(struct ksmbd_work *work)
751*38c8a9a5SSteve French {
752*38c8a9a5SSteve French 	const struct cred *cred;
753*38c8a9a5SSteve French 
754*38c8a9a5SSteve French 	WARN_ON(!work->saved_cred);
755*38c8a9a5SSteve French 
756*38c8a9a5SSteve French 	cred = current_cred();
757*38c8a9a5SSteve French 	revert_creds(work->saved_cred);
758*38c8a9a5SSteve French 	put_cred(cred);
759*38c8a9a5SSteve French 	work->saved_cred = NULL;
760*38c8a9a5SSteve French }
761*38c8a9a5SSteve French 
762*38c8a9a5SSteve French __le32 smb_map_generic_desired_access(__le32 daccess)
763*38c8a9a5SSteve French {
764*38c8a9a5SSteve French 	if (daccess & FILE_GENERIC_READ_LE) {
765*38c8a9a5SSteve French 		daccess |= cpu_to_le32(GENERIC_READ_FLAGS);
766*38c8a9a5SSteve French 		daccess &= ~FILE_GENERIC_READ_LE;
767*38c8a9a5SSteve French 	}
768*38c8a9a5SSteve French 
769*38c8a9a5SSteve French 	if (daccess & FILE_GENERIC_WRITE_LE) {
770*38c8a9a5SSteve French 		daccess |= cpu_to_le32(GENERIC_WRITE_FLAGS);
771*38c8a9a5SSteve French 		daccess &= ~FILE_GENERIC_WRITE_LE;
772*38c8a9a5SSteve French 	}
773*38c8a9a5SSteve French 
774*38c8a9a5SSteve French 	if (daccess & FILE_GENERIC_EXECUTE_LE) {
775*38c8a9a5SSteve French 		daccess |= cpu_to_le32(GENERIC_EXECUTE_FLAGS);
776*38c8a9a5SSteve French 		daccess &= ~FILE_GENERIC_EXECUTE_LE;
777*38c8a9a5SSteve French 	}
778*38c8a9a5SSteve French 
779*38c8a9a5SSteve French 	if (daccess & FILE_GENERIC_ALL_LE) {
780*38c8a9a5SSteve French 		daccess |= cpu_to_le32(GENERIC_ALL_FLAGS);
781*38c8a9a5SSteve French 		daccess &= ~FILE_GENERIC_ALL_LE;
782*38c8a9a5SSteve French 	}
783*38c8a9a5SSteve French 
784*38c8a9a5SSteve French 	return daccess;
785*38c8a9a5SSteve French }
786