]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - fs/ksmbd/smb2pdu.c
ksmbd: call mnt_user_ns once in a function
[mirror_ubuntu-jammy-kernel.git] / fs / ksmbd / smb2pdu.c
CommitLineData
e2f34481
NJ
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
4 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
5 */
6
7#include <linux/inetdevice.h>
8#include <net/addrconf.h>
9#include <linux/syscalls.h>
10#include <linux/namei.h>
11#include <linux/statfs.h>
12#include <linux/ethtool.h>
e8c06191 13#include <linux/falloc.h>
e2f34481
NJ
14
15#include "glob.h"
16#include "smb2pdu.h"
17#include "smbfsctl.h"
18#include "oplock.h"
19#include "smbacl.h"
20
21#include "auth.h"
22#include "asn1.h"
e2f34481
NJ
23#include "connection.h"
24#include "transport_ipc.h"
25#include "vfs.h"
26#include "vfs_cache.h"
27#include "misc.h"
28
e2f34481
NJ
29#include "server.h"
30#include "smb_common.h"
31#include "smbstatus.h"
32#include "ksmbd_work.h"
33#include "mgmt/user_config.h"
34#include "mgmt/share_config.h"
35#include "mgmt/tree_connect.h"
36#include "mgmt/user_session.h"
37#include "mgmt/ksmbd_ida.h"
38#include "ndr.h"
39
40static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
41{
42 if (work->next_smb2_rcv_hdr_off) {
8a893315
NJ
43 *req = ksmbd_req_buf_next(work);
44 *rsp = ksmbd_resp_buf_next(work);
e2f34481 45 } else {
e5066499
NJ
46 *req = work->request_buf;
47 *rsp = work->response_buf;
e2f34481
NJ
48 }
49}
50
51#define WORK_BUFFERS(w, rq, rs) __wbuf((w), (void **)&(rq), (void **)&(rs))
52
53/**
54 * check_session_id() - check for valid session id in smb header
55 * @conn: connection instance
56 * @id: session id from smb header
57 *
58 * Return: 1 if valid session id, otherwise 0
59 */
64b39f4a 60static inline int check_session_id(struct ksmbd_conn *conn, u64 id)
e2f34481
NJ
61{
62 struct ksmbd_session *sess;
63
64 if (id == 0 || id == -1)
65 return 0;
66
f5a544e3 67 sess = ksmbd_session_lookup_all(conn, id);
e2f34481
NJ
68 if (sess)
69 return 1;
bde1694a 70 pr_err("Invalid user session id: %llu\n", id);
e2f34481
NJ
71 return 0;
72}
73
f5a544e3 74struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn)
e2f34481
NJ
75{
76 struct channel *chann;
e2f34481 77
6f3d5eee 78 list_for_each_entry(chann, &sess->ksmbd_chann_list, chann_list) {
560ac051 79 if (chann->conn == conn)
e2f34481
NJ
80 return chann;
81 }
82
83 return NULL;
84}
85
86/**
87 * smb2_get_ksmbd_tcon() - get tree connection information for a tree id
95fa1ce9 88 * @work: smb work
e2f34481
NJ
89 *
90 * Return: matching tree connection on success, otherwise error
91 */
92int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
93{
e5066499 94 struct smb2_hdr *req_hdr = work->request_buf;
e2f34481
NJ
95 int tree_id;
96
97 work->tcon = NULL;
64b39f4a
NJ
98 if (work->conn->ops->get_cmd_val(work) == SMB2_TREE_CONNECT_HE ||
99 work->conn->ops->get_cmd_val(work) == SMB2_CANCEL_HE ||
100 work->conn->ops->get_cmd_val(work) == SMB2_LOGOFF_HE) {
e2f34481
NJ
101 ksmbd_debug(SMB, "skip to check tree connect request\n");
102 return 0;
103 }
104
02b68b20 105 if (xa_empty(&work->sess->tree_conns)) {
e2f34481
NJ
106 ksmbd_debug(SMB, "NO tree connected\n");
107 return -1;
108 }
109
110 tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId);
111 work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id);
112 if (!work->tcon) {
bde1694a 113 pr_err("Invalid tid %d\n", tree_id);
e2f34481
NJ
114 return -1;
115 }
116
117 return 1;
118}
119
120/**
121 * smb2_set_err_rsp() - set error response code on smb response
122 * @work: smb work containing response buffer
123 */
124void smb2_set_err_rsp(struct ksmbd_work *work)
125{
126 struct smb2_err_rsp *err_rsp;
127
128 if (work->next_smb2_rcv_hdr_off)
8a893315 129 err_rsp = ksmbd_resp_buf_next(work);
e2f34481 130 else
e5066499 131 err_rsp = work->response_buf;
e2f34481
NJ
132
133 if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
134 err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE;
135 err_rsp->ErrorContextCount = 0;
136 err_rsp->Reserved = 0;
137 err_rsp->ByteCount = 0;
138 err_rsp->ErrorData[0] = 0;
e5066499 139 inc_rfc1001_len(work->response_buf, SMB2_ERROR_STRUCTURE_SIZE2);
e2f34481
NJ
140 }
141}
142
143/**
144 * is_smb2_neg_cmd() - is it smb2 negotiation command
145 * @work: smb work containing smb header
146 *
147 * Return: 1 if smb2 negotiation command, otherwise 0
148 */
149int is_smb2_neg_cmd(struct ksmbd_work *work)
150{
e5066499 151 struct smb2_hdr *hdr = work->request_buf;
e2f34481
NJ
152
153 /* is it SMB2 header ? */
154 if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
155 return 0;
156
157 /* make sure it is request not response message */
158 if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
159 return 0;
160
161 if (hdr->Command != SMB2_NEGOTIATE)
162 return 0;
163
164 return 1;
165}
166
167/**
168 * is_smb2_rsp() - is it smb2 response
169 * @work: smb work containing smb response buffer
170 *
171 * Return: 1 if smb2 response, otherwise 0
172 */
173int is_smb2_rsp(struct ksmbd_work *work)
174{
e5066499 175 struct smb2_hdr *hdr = work->response_buf;
e2f34481
NJ
176
177 /* is it SMB2 header ? */
178 if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
179 return 0;
180
181 /* make sure it is response not request message */
182 if (!(hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR))
183 return 0;
184
185 return 1;
186}
187
188/**
189 * get_smb2_cmd_val() - get smb command code from smb header
190 * @work: smb work containing smb request buffer
191 *
192 * Return: smb2 request command value
193 */
fc2d1b58 194u16 get_smb2_cmd_val(struct ksmbd_work *work)
e2f34481
NJ
195{
196 struct smb2_hdr *rcv_hdr;
197
198 if (work->next_smb2_rcv_hdr_off)
8a893315 199 rcv_hdr = ksmbd_req_buf_next(work);
e2f34481 200 else
e5066499 201 rcv_hdr = work->request_buf;
e2f34481
NJ
202 return le16_to_cpu(rcv_hdr->Command);
203}
204
205/**
206 * set_smb2_rsp_status() - set error response code on smb2 header
207 * @work: smb work containing response buffer
95fa1ce9 208 * @err: error response code
e2f34481
NJ
209 */
210void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
211{
212 struct smb2_hdr *rsp_hdr;
213
214 if (work->next_smb2_rcv_hdr_off)
8a893315 215 rsp_hdr = ksmbd_resp_buf_next(work);
e2f34481 216 else
e5066499 217 rsp_hdr = work->response_buf;
e2f34481
NJ
218 rsp_hdr->Status = err;
219 smb2_set_err_rsp(work);
220}
221
222/**
223 * init_smb2_neg_rsp() - initialize smb2 response for negotiate command
224 * @work: smb work containing smb request buffer
225 *
226 * smb2 negotiate response is sent in reply of smb1 negotiate command for
227 * dialect auto-negotiation.
228 */
229int init_smb2_neg_rsp(struct ksmbd_work *work)
230{
231 struct smb2_hdr *rsp_hdr;
232 struct smb2_negotiate_rsp *rsp;
233 struct ksmbd_conn *conn = work->conn;
234
235 if (conn->need_neg == false)
236 return -EINVAL;
237 if (!(conn->dialect >= SMB20_PROT_ID &&
64b39f4a 238 conn->dialect <= SMB311_PROT_ID))
e2f34481
NJ
239 return -EINVAL;
240
e5066499 241 rsp_hdr = work->response_buf;
e2f34481
NJ
242
243 memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
244
245 rsp_hdr->smb2_buf_length =
d8fb2998 246 cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
e2f34481
NJ
247
248 rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
249 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
250 rsp_hdr->CreditRequest = cpu_to_le16(2);
251 rsp_hdr->Command = SMB2_NEGOTIATE;
252 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
253 rsp_hdr->NextCommand = 0;
254 rsp_hdr->MessageId = 0;
255 rsp_hdr->Id.SyncId.ProcessId = 0;
256 rsp_hdr->Id.SyncId.TreeId = 0;
257 rsp_hdr->SessionId = 0;
258 memset(rsp_hdr->Signature, 0, 16);
259
e5066499 260 rsp = work->response_buf;
e2f34481
NJ
261
262 WARN_ON(ksmbd_conn_good(work));
263
264 rsp->StructureSize = cpu_to_le16(65);
265 ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
266 rsp->DialectRevision = cpu_to_le16(conn->dialect);
267 /* Not setting conn guid rsp->ServerGUID, as it
268 * not used by client for identifying connection
269 */
270 rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
271 /* Default Max Message Size till SMB2.0, 64K*/
272 rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size);
273 rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
274 rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size);
275
276 rsp->SystemTime = cpu_to_le64(ksmbd_systime());
277 rsp->ServerStartTime = 0;
278
279 rsp->SecurityBufferOffset = cpu_to_le16(128);
280 rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
281 ksmbd_copy_gss_neg_header(((char *)(&rsp->hdr) +
282 sizeof(rsp->hdr.smb2_buf_length)) +
283 le16_to_cpu(rsp->SecurityBufferOffset));
284 inc_rfc1001_len(rsp, sizeof(struct smb2_negotiate_rsp) -
285 sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
286 AUTH_GSS_LENGTH);
287 rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
288 if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY)
289 rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
290 conn->use_spnego = true;
291
292 ksmbd_conn_set_need_negotiate(work);
293 return 0;
294}
295
296static int smb2_consume_credit_charge(struct ksmbd_work *work,
070fb21e 297 unsigned short credit_charge)
e2f34481
NJ
298{
299 struct ksmbd_conn *conn = work->conn;
300 unsigned int rsp_credits = 1;
301
302 if (!conn->total_credits)
303 return 0;
304
305 if (credit_charge > 0)
306 rsp_credits = credit_charge;
307
308 conn->total_credits -= rsp_credits;
309 return rsp_credits;
310}
311
312/**
313 * smb2_set_rsp_credits() - set number of credits in response buffer
314 * @work: smb work containing smb response buffer
315 */
316int smb2_set_rsp_credits(struct ksmbd_work *work)
317{
8a893315
NJ
318 struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
319 struct smb2_hdr *hdr = ksmbd_resp_buf_next(work);
e2f34481
NJ
320 struct ksmbd_conn *conn = work->conn;
321 unsigned short credits_requested = le16_to_cpu(req_hdr->CreditRequest);
322 unsigned short credit_charge = 1, credits_granted = 0;
323 unsigned short aux_max, aux_credits, min_credits;
324 int rsp_credit_charge;
325
326 if (hdr->Command == SMB2_CANCEL)
327 goto out;
328
329 /* get default minimum credits by shifting maximum credits by 4 */
330 min_credits = conn->max_credits >> 4;
331
332 if (conn->total_credits >= conn->max_credits) {
bde1694a 333 pr_err("Total credits overflow: %d\n", conn->total_credits);
e2f34481
NJ
334 conn->total_credits = min_credits;
335 }
336
070fb21e
NJ
337 rsp_credit_charge =
338 smb2_consume_credit_charge(work, le16_to_cpu(req_hdr->CreditCharge));
e2f34481
NJ
339 if (rsp_credit_charge < 0)
340 return -EINVAL;
341
342 hdr->CreditCharge = cpu_to_le16(rsp_credit_charge);
343
344 if (credits_requested > 0) {
345 aux_credits = credits_requested - 1;
346 aux_max = 32;
347 if (hdr->Command == SMB2_NEGOTIATE)
348 aux_max = 0;
349 aux_credits = (aux_credits < aux_max) ? aux_credits : aux_max;
350 credits_granted = aux_credits + credit_charge;
351
352 /* if credits granted per client is getting bigger than default
353 * minimum credits then we should wrap it up within the limits.
354 */
355 if ((conn->total_credits + credits_granted) > min_credits)
356 credits_granted = min_credits - conn->total_credits;
357 /*
358 * TODO: Need to adjuct CreditRequest value according to
359 * current cpu load
360 */
361 } else if (conn->total_credits == 0) {
362 credits_granted = 1;
363 }
364
365 conn->total_credits += credits_granted;
366 work->credits_granted += credits_granted;
367
368 if (!req_hdr->NextCommand) {
369 /* Update CreditRequest in last request */
370 hdr->CreditRequest = cpu_to_le16(work->credits_granted);
371 }
372out:
373 ksmbd_debug(SMB,
070fb21e
NJ
374 "credits: requested[%d] granted[%d] total_granted[%d]\n",
375 credits_requested, credits_granted,
376 conn->total_credits);
e2f34481
NJ
377 return 0;
378}
379
380/**
381 * init_chained_smb2_rsp() - initialize smb2 chained response
382 * @work: smb work containing smb response buffer
383 */
384static void init_chained_smb2_rsp(struct ksmbd_work *work)
385{
8a893315
NJ
386 struct smb2_hdr *req = ksmbd_req_buf_next(work);
387 struct smb2_hdr *rsp = ksmbd_resp_buf_next(work);
e2f34481
NJ
388 struct smb2_hdr *rsp_hdr;
389 struct smb2_hdr *rcv_hdr;
390 int next_hdr_offset = 0;
391 int len, new_len;
392
393 /* Len of this response = updated RFC len - offset of previous cmd
394 * in the compound rsp
395 */
396
397 /* Storing the current local FID which may be needed by subsequent
398 * command in the compound request
399 */
400 if (req->Command == SMB2_CREATE && rsp->Status == STATUS_SUCCESS) {
401 work->compound_fid =
402 le64_to_cpu(((struct smb2_create_rsp *)rsp)->
403 VolatileFileId);
404 work->compound_pfid =
405 le64_to_cpu(((struct smb2_create_rsp *)rsp)->
406 PersistentFileId);
407 work->compound_sid = le64_to_cpu(rsp->SessionId);
408 }
409
e5066499 410 len = get_rfc1002_len(work->response_buf) - work->next_smb2_rsp_hdr_off;
e2f34481
NJ
411 next_hdr_offset = le32_to_cpu(req->NextCommand);
412
413 new_len = ALIGN(len, 8);
e5066499 414 inc_rfc1001_len(work->response_buf, ((sizeof(struct smb2_hdr) - 4)
e2f34481
NJ
415 + new_len - len));
416 rsp->NextCommand = cpu_to_le32(new_len);
417
418 work->next_smb2_rcv_hdr_off += next_hdr_offset;
419 work->next_smb2_rsp_hdr_off += new_len;
420 ksmbd_debug(SMB,
070fb21e
NJ
421 "Compound req new_len = %d rcv off = %d rsp off = %d\n",
422 new_len, work->next_smb2_rcv_hdr_off,
423 work->next_smb2_rsp_hdr_off);
e2f34481 424
8a893315
NJ
425 rsp_hdr = ksmbd_resp_buf_next(work);
426 rcv_hdr = ksmbd_req_buf_next(work);
e2f34481
NJ
427
428 if (!(rcv_hdr->Flags & SMB2_FLAGS_RELATED_OPERATIONS)) {
429 ksmbd_debug(SMB, "related flag should be set\n");
430 work->compound_fid = KSMBD_NO_FID;
431 work->compound_pfid = KSMBD_NO_FID;
432 }
433 memset((char *)rsp_hdr + 4, 0, sizeof(struct smb2_hdr) + 2);
434 rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
435 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
436 rsp_hdr->Command = rcv_hdr->Command;
437
438 /*
439 * Message is response. We don't grant oplock yet.
440 */
441 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR |
442 SMB2_FLAGS_RELATED_OPERATIONS);
443 rsp_hdr->NextCommand = 0;
444 rsp_hdr->MessageId = rcv_hdr->MessageId;
445 rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId;
446 rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId;
447 rsp_hdr->SessionId = rcv_hdr->SessionId;
448 memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
449}
450
451/**
452 * is_chained_smb2_message() - check for chained command
453 * @work: smb work containing smb request buffer
454 *
455 * Return: true if chained request, otherwise false
456 */
457bool is_chained_smb2_message(struct ksmbd_work *work)
458{
e5066499 459 struct smb2_hdr *hdr = work->request_buf;
e2f34481
NJ
460 unsigned int len;
461
462 if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
463 return false;
464
8a893315 465 hdr = ksmbd_req_buf_next(work);
e2f34481
NJ
466 if (le32_to_cpu(hdr->NextCommand) > 0) {
467 ksmbd_debug(SMB, "got SMB2 chained command\n");
468 init_chained_smb2_rsp(work);
469 return true;
470 } else if (work->next_smb2_rcv_hdr_off) {
471 /*
472 * This is last request in chained command,
473 * align response to 8 byte
474 */
e5066499
NJ
475 len = ALIGN(get_rfc1002_len(work->response_buf), 8);
476 len = len - get_rfc1002_len(work->response_buf);
e2f34481
NJ
477 if (len) {
478 ksmbd_debug(SMB, "padding len %u\n", len);
e5066499
NJ
479 inc_rfc1001_len(work->response_buf, len);
480 if (work->aux_payload_sz)
e2f34481
NJ
481 work->aux_payload_sz += len;
482 }
483 }
484 return false;
485}
486
487/**
488 * init_smb2_rsp_hdr() - initialize smb2 response
489 * @work: smb work containing smb request buffer
490 *
491 * Return: 0
492 */
493int init_smb2_rsp_hdr(struct ksmbd_work *work)
494{
e5066499
NJ
495 struct smb2_hdr *rsp_hdr = work->response_buf;
496 struct smb2_hdr *rcv_hdr = work->request_buf;
e2f34481
NJ
497 struct ksmbd_conn *conn = work->conn;
498
499 memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
d8fb2998
HL
500 rsp_hdr->smb2_buf_length =
501 cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
e2f34481
NJ
502 rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
503 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
504 rsp_hdr->Command = rcv_hdr->Command;
505
506 /*
507 * Message is response. We don't grant oplock yet.
508 */
509 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
510 rsp_hdr->NextCommand = 0;
511 rsp_hdr->MessageId = rcv_hdr->MessageId;
512 rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId;
513 rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId;
514 rsp_hdr->SessionId = rcv_hdr->SessionId;
515 memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
516
517 work->syncronous = true;
518 if (work->async_id) {
d40012a8 519 ksmbd_release_id(&conn->async_ida, work->async_id);
e2f34481
NJ
520 work->async_id = 0;
521 }
522
523 return 0;
524}
525
526/**
527 * smb2_allocate_rsp_buf() - allocate smb2 response buffer
528 * @work: smb work containing smb request buffer
529 *
530 * Return: 0 on success, otherwise -ENOMEM
531 */
532int smb2_allocate_rsp_buf(struct ksmbd_work *work)
533{
e5066499 534 struct smb2_hdr *hdr = work->request_buf;
e2f34481
NJ
535 size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
536 size_t large_sz = work->conn->vals->max_trans_size + MAX_SMB2_HDR_SIZE;
537 size_t sz = small_sz;
538 int cmd = le16_to_cpu(hdr->Command);
539
c30f4eb8 540 if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE)
e2f34481 541 sz = large_sz;
e2f34481
NJ
542
543 if (cmd == SMB2_QUERY_INFO_HE) {
544 struct smb2_query_info_req *req;
545
e5066499 546 req = work->request_buf;
e2f34481 547 if (req->InfoType == SMB2_O_INFO_FILE &&
64b39f4a 548 (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
c30f4eb8 549 req->FileInfoClass == FILE_ALL_INFORMATION))
e2f34481 550 sz = large_sz;
e2f34481
NJ
551 }
552
553 /* allocate large response buf for chained commands */
554 if (le32_to_cpu(hdr->NextCommand) > 0)
555 sz = large_sz;
556
c30f4eb8 557 work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
63c454f8 558 if (!work->response_buf)
e2f34481 559 return -ENOMEM;
e2f34481
NJ
560
561 work->response_sz = sz;
562 return 0;
563}
564
565/**
566 * smb2_check_user_session() - check for valid session for a user
567 * @work: smb work containing smb request buffer
568 *
569 * Return: 0 on success, otherwise error
570 */
571int smb2_check_user_session(struct ksmbd_work *work)
572{
e5066499 573 struct smb2_hdr *req_hdr = work->request_buf;
e2f34481
NJ
574 struct ksmbd_conn *conn = work->conn;
575 unsigned int cmd = conn->ops->get_cmd_val(work);
576 unsigned long long sess_id;
577
578 work->sess = NULL;
579 /*
580 * SMB2_ECHO, SMB2_NEGOTIATE, SMB2_SESSION_SETUP command do not
581 * require a session id, so no need to validate user session's for
582 * these commands.
583 */
584 if (cmd == SMB2_ECHO_HE || cmd == SMB2_NEGOTIATE_HE ||
64b39f4a 585 cmd == SMB2_SESSION_SETUP_HE)
e2f34481
NJ
586 return 0;
587
588 if (!ksmbd_conn_good(work))
589 return -EINVAL;
590
591 sess_id = le64_to_cpu(req_hdr->SessionId);
592 /* Check for validity of user session */
f5a544e3 593 work->sess = ksmbd_session_lookup_all(conn, sess_id);
e2f34481
NJ
594 if (work->sess)
595 return 1;
596 ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
597 return -EINVAL;
598}
599
64b39f4a 600static void destroy_previous_session(struct ksmbd_user *user, u64 id)
e2f34481
NJ
601{
602 struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id);
603 struct ksmbd_user *prev_user;
604
605 if (!prev_sess)
606 return;
607
608 prev_user = prev_sess->user;
609
1fca8038
MM
610 if (!prev_user ||
611 strcmp(user->name, prev_user->name) ||
e2f34481
NJ
612 user->passkey_sz != prev_user->passkey_sz ||
613 memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) {
614 put_session(prev_sess);
615 return;
616 }
617
618 put_session(prev_sess);
619 ksmbd_session_destroy(prev_sess);
620}
621
622/**
623 * smb2_get_name() - get filename string from on the wire smb format
95fa1ce9 624 * @share: ksmbd_share_config pointer
e2f34481
NJ
625 * @src: source buffer
626 * @maxlen: maxlen of source string
95fa1ce9 627 * @nls_table: nls_table pointer
e2f34481
NJ
628 *
629 * Return: matching converted filename on success, otherwise error ptr
630 */
631static char *
64b39f4a 632smb2_get_name(struct ksmbd_share_config *share, const char *src,
070fb21e 633 const int maxlen, struct nls_table *local_nls)
e2f34481
NJ
634{
635 char *name, *unixname;
636
64b39f4a 637 name = smb_strndup_from_utf16(src, maxlen, 1, local_nls);
e2f34481 638 if (IS_ERR(name)) {
bde1694a 639 pr_err("failed to get name %ld\n", PTR_ERR(name));
e2f34481
NJ
640 return name;
641 }
642
643 /* change it to absolute unix name */
644 ksmbd_conv_path_to_unix(name);
645 ksmbd_strip_last_slash(name);
646
647 unixname = convert_to_unix_name(share, name);
648 kfree(name);
649 if (!unixname) {
bde1694a 650 pr_err("can not convert absolute name\n");
e2f34481
NJ
651 return ERR_PTR(-ENOMEM);
652 }
653
654 ksmbd_debug(SMB, "absolute name = %s\n", unixname);
655 return unixname;
656}
657
e2f34481
NJ
658int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
659{
660 struct smb2_hdr *rsp_hdr;
661 struct ksmbd_conn *conn = work->conn;
662 int id;
663
e5066499 664 rsp_hdr = work->response_buf;
e2f34481
NJ
665 rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
666
d40012a8 667 id = ksmbd_acquire_async_msg_id(&conn->async_ida);
e2f34481 668 if (id < 0) {
bde1694a 669 pr_err("Failed to alloc async message id\n");
e2f34481
NJ
670 return id;
671 }
672 work->syncronous = false;
673 work->async_id = id;
674 rsp_hdr->Id.AsyncId = cpu_to_le64(id);
675
676 ksmbd_debug(SMB,
070fb21e
NJ
677 "Send interim Response to inform async request id : %d\n",
678 work->async_id);
e2f34481
NJ
679
680 work->cancel_fn = fn;
681 work->cancel_argv = arg;
682
6c4e675a
NJ
683 if (list_empty(&work->async_request_entry)) {
684 spin_lock(&conn->request_lock);
685 list_add_tail(&work->async_request_entry, &conn->async_requests);
686 spin_unlock(&conn->request_lock);
687 }
e2f34481
NJ
688
689 return 0;
690}
691
692void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
693{
694 struct smb2_hdr *rsp_hdr;
695
e5066499 696 rsp_hdr = work->response_buf;
e2f34481
NJ
697 smb2_set_err_rsp(work);
698 rsp_hdr->Status = status;
699
700 work->multiRsp = 1;
701 ksmbd_conn_write(work);
702 rsp_hdr->Status = 0;
703 work->multiRsp = 0;
704}
705
706static __le32 smb2_get_reparse_tag_special_file(umode_t mode)
707{
708 if (S_ISDIR(mode) || S_ISREG(mode))
709 return 0;
710
711 if (S_ISLNK(mode))
712 return IO_REPARSE_TAG_LX_SYMLINK_LE;
713 else if (S_ISFIFO(mode))
714 return IO_REPARSE_TAG_LX_FIFO_LE;
715 else if (S_ISSOCK(mode))
716 return IO_REPARSE_TAG_AF_UNIX_LE;
717 else if (S_ISCHR(mode))
718 return IO_REPARSE_TAG_LX_CHR_LE;
719 else if (S_ISBLK(mode))
720 return IO_REPARSE_TAG_LX_BLK_LE;
721
722 return 0;
723}
724
725/**
726 * smb2_get_dos_mode() - get file mode in dos format from unix mode
727 * @stat: kstat containing file mode
95fa1ce9 728 * @attribute: attribute flags
e2f34481
NJ
729 *
730 * Return: converted dos mode
731 */
732static int smb2_get_dos_mode(struct kstat *stat, int attribute)
733{
734 int attr = 0;
735
64b39f4a 736 if (S_ISDIR(stat->mode)) {
e2f34481
NJ
737 attr = ATTR_DIRECTORY |
738 (attribute & (ATTR_HIDDEN | ATTR_SYSTEM));
64b39f4a 739 } else {
e2f34481
NJ
740 attr = (attribute & 0x00005137) | ATTR_ARCHIVE;
741 attr &= ~(ATTR_DIRECTORY);
742 if (S_ISREG(stat->mode) && (server_conf.share_fake_fscaps &
743 FILE_SUPPORTS_SPARSE_FILES))
744 attr |= ATTR_SPARSE;
745
746 if (smb2_get_reparse_tag_special_file(stat->mode))
747 attr |= ATTR_REPARSE;
748 }
749
750 return attr;
751}
752
753static void build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt,
070fb21e 754 __le16 hash_id)
e2f34481
NJ
755{
756 pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
757 pneg_ctxt->DataLength = cpu_to_le16(38);
758 pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
759 pneg_ctxt->Reserved = cpu_to_le32(0);
760 pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE);
761 get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE);
762 pneg_ctxt->HashAlgorithms = hash_id;
763}
764
765static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt,
070fb21e 766 __le16 cipher_type)
e2f34481
NJ
767{
768 pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
769 pneg_ctxt->DataLength = cpu_to_le16(4);
770 pneg_ctxt->Reserved = cpu_to_le32(0);
771 pneg_ctxt->CipherCount = cpu_to_le16(1);
772 pneg_ctxt->Ciphers[0] = cipher_type;
773}
774
775static void build_compression_ctxt(struct smb2_compression_ctx *pneg_ctxt,
070fb21e 776 __le16 comp_algo)
e2f34481
NJ
777{
778 pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
779 pneg_ctxt->DataLength =
780 cpu_to_le16(sizeof(struct smb2_compression_ctx)
781 - sizeof(struct smb2_neg_context));
782 pneg_ctxt->Reserved = cpu_to_le32(0);
783 pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(1);
784 pneg_ctxt->Reserved1 = cpu_to_le32(0);
785 pneg_ctxt->CompressionAlgorithms[0] = comp_algo;
786}
787
64b39f4a 788static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
e2f34481
NJ
789{
790 pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
791 pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
792 /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
793 pneg_ctxt->Name[0] = 0x93;
794 pneg_ctxt->Name[1] = 0xAD;
795 pneg_ctxt->Name[2] = 0x25;
796 pneg_ctxt->Name[3] = 0x50;
797 pneg_ctxt->Name[4] = 0x9C;
798 pneg_ctxt->Name[5] = 0xB4;
799 pneg_ctxt->Name[6] = 0x11;
800 pneg_ctxt->Name[7] = 0xE7;
801 pneg_ctxt->Name[8] = 0xB4;
802 pneg_ctxt->Name[9] = 0x23;
803 pneg_ctxt->Name[10] = 0x83;
804 pneg_ctxt->Name[11] = 0xDE;
805 pneg_ctxt->Name[12] = 0x96;
806 pneg_ctxt->Name[13] = 0x8B;
807 pneg_ctxt->Name[14] = 0xCD;
808 pneg_ctxt->Name[15] = 0x7C;
809}
810
64b39f4a 811static void assemble_neg_contexts(struct ksmbd_conn *conn,
070fb21e 812 struct smb2_negotiate_rsp *rsp)
e2f34481
NJ
813{
814 /* +4 is to account for the RFC1001 len field */
815 char *pneg_ctxt = (char *)rsp +
816 le32_to_cpu(rsp->NegotiateContextOffset) + 4;
817 int neg_ctxt_cnt = 1;
818 int ctxt_size;
819
820 ksmbd_debug(SMB,
070fb21e 821 "assemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
e2f34481 822 build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt,
070fb21e 823 conn->preauth_info->Preauth_HashId);
e2f34481
NJ
824 rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
825 inc_rfc1001_len(rsp, AUTH_GSS_PADDING);
826 ctxt_size = sizeof(struct smb2_preauth_neg_context);
827 /* Round to 8 byte boundary */
828 pneg_ctxt += round_up(sizeof(struct smb2_preauth_neg_context), 8);
829
830 if (conn->cipher_type) {
831 ctxt_size = round_up(ctxt_size, 8);
832 ksmbd_debug(SMB,
070fb21e 833 "assemble SMB2_ENCRYPTION_CAPABILITIES context\n");
64b39f4a 834 build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt,
070fb21e 835 conn->cipher_type);
e2f34481
NJ
836 rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
837 ctxt_size += sizeof(struct smb2_encryption_neg_context);
838 /* Round to 8 byte boundary */
839 pneg_ctxt +=
840 round_up(sizeof(struct smb2_encryption_neg_context),
841 8);
842 }
843
844 if (conn->compress_algorithm) {
845 ctxt_size = round_up(ctxt_size, 8);
846 ksmbd_debug(SMB,
070fb21e 847 "assemble SMB2_COMPRESSION_CAPABILITIES context\n");
e2f34481
NJ
848 /* Temporarily set to SMB3_COMPRESS_NONE */
849 build_compression_ctxt((struct smb2_compression_ctx *)pneg_ctxt,
070fb21e 850 conn->compress_algorithm);
e2f34481
NJ
851 rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
852 ctxt_size += sizeof(struct smb2_compression_ctx);
853 /* Round to 8 byte boundary */
854 pneg_ctxt += round_up(sizeof(struct smb2_compression_ctx), 8);
855 }
856
857 if (conn->posix_ext_supported) {
858 ctxt_size = round_up(ctxt_size, 8);
859 ksmbd_debug(SMB,
070fb21e 860 "assemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
e2f34481
NJ
861 build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
862 rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
863 ctxt_size += sizeof(struct smb2_posix_neg_context);
864 }
865
866 inc_rfc1001_len(rsp, ctxt_size);
867}
868
64b39f4a 869static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
070fb21e 870 struct smb2_preauth_neg_context *pneg_ctxt)
e2f34481
NJ
871{
872 __le32 err = STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP;
873
070fb21e 874 if (pneg_ctxt->HashAlgorithms == SMB2_PREAUTH_INTEGRITY_SHA512) {
e2f34481
NJ
875 conn->preauth_info->Preauth_HashId =
876 SMB2_PREAUTH_INTEGRITY_SHA512;
877 err = STATUS_SUCCESS;
878 }
879
880 return err;
881}
882
883static int decode_encrypt_ctxt(struct ksmbd_conn *conn,
070fb21e 884 struct smb2_encryption_neg_context *pneg_ctxt)
e2f34481
NJ
885{
886 int i;
887 int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
888
889 conn->cipher_type = 0;
890
891 if (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION))
892 goto out;
893
894 for (i = 0; i < cph_cnt; i++) {
895 if (pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_GCM ||
5a0ca770
NJ
896 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_CCM ||
897 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_CCM ||
898 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_GCM) {
e2f34481 899 ksmbd_debug(SMB, "Cipher ID = 0x%x\n",
070fb21e 900 pneg_ctxt->Ciphers[i]);
e2f34481
NJ
901 conn->cipher_type = pneg_ctxt->Ciphers[i];
902 break;
903 }
904 }
905
906out:
907 /*
908 * Return encrypt context size in request.
909 * So need to plus extra number of ciphers size.
910 */
911 return sizeof(struct smb2_encryption_neg_context) +
912 ((cph_cnt - 1) * 2);
913}
914
915static int decode_compress_ctxt(struct ksmbd_conn *conn,
070fb21e 916 struct smb2_compression_ctx *pneg_ctxt)
e2f34481
NJ
917{
918 int algo_cnt = le16_to_cpu(pneg_ctxt->CompressionAlgorithmCount);
919
920 conn->compress_algorithm = SMB3_COMPRESS_NONE;
921
922 /*
923 * Return compression context size in request.
924 * So need to plus extra number of CompressionAlgorithms size.
925 */
926 return sizeof(struct smb2_encryption_neg_context) +
927 ((algo_cnt - 1) * 2);
928}
929
930static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
070fb21e 931 struct smb2_negotiate_req *req)
e2f34481
NJ
932{
933 int i = 0;
934 __le32 status = 0;
935 /* +4 is to account for the RFC1001 len field */
936 char *pneg_ctxt = (char *)req +
937 le32_to_cpu(req->NegotiateContextOffset) + 4;
938 __le16 *ContextType = (__le16 *)pneg_ctxt;
939 int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
940 int ctxt_size;
941
942 ksmbd_debug(SMB, "negotiate context count = %d\n", neg_ctxt_cnt);
943 status = STATUS_INVALID_PARAMETER;
944 while (i++ < neg_ctxt_cnt) {
945 if (*ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
946 ksmbd_debug(SMB,
070fb21e 947 "deassemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
e2f34481
NJ
948 if (conn->preauth_info->Preauth_HashId)
949 break;
950
951 status = decode_preauth_ctxt(conn,
070fb21e 952 (struct smb2_preauth_neg_context *)pneg_ctxt);
64b39f4a 953 pneg_ctxt += DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8;
e2f34481
NJ
954 } else if (*ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
955 ksmbd_debug(SMB,
070fb21e 956 "deassemble SMB2_ENCRYPTION_CAPABILITIES context\n");
e2f34481
NJ
957 if (conn->cipher_type)
958 break;
959
960 ctxt_size = decode_encrypt_ctxt(conn,
64b39f4a 961 (struct smb2_encryption_neg_context *)pneg_ctxt);
e2f34481
NJ
962 pneg_ctxt += DIV_ROUND_UP(ctxt_size, 8) * 8;
963 } else if (*ContextType == SMB2_COMPRESSION_CAPABILITIES) {
964 ksmbd_debug(SMB,
070fb21e 965 "deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
e2f34481
NJ
966 if (conn->compress_algorithm)
967 break;
968
969 ctxt_size = decode_compress_ctxt(conn,
10268f7d 970 (struct smb2_compression_ctx *)pneg_ctxt);
e2f34481
NJ
971 pneg_ctxt += DIV_ROUND_UP(ctxt_size, 8) * 8;
972 } else if (*ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) {
973 ksmbd_debug(SMB,
070fb21e 974 "deassemble SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context\n");
e2f34481 975 ctxt_size = sizeof(struct smb2_netname_neg_context);
64b39f4a 976 ctxt_size += DIV_ROUND_UP(le16_to_cpu(((struct smb2_netname_neg_context *)
070fb21e 977 pneg_ctxt)->DataLength), 8) * 8;
e2f34481
NJ
978 pneg_ctxt += ctxt_size;
979 } else if (*ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) {
980 ksmbd_debug(SMB,
070fb21e 981 "deassemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
e2f34481 982 conn->posix_ext_supported = true;
64b39f4a 983 pneg_ctxt += DIV_ROUND_UP(sizeof(struct smb2_posix_neg_context), 8) * 8;
e2f34481
NJ
984 }
985 ContextType = (__le16 *)pneg_ctxt;
986
987 if (status != STATUS_SUCCESS)
988 break;
989 }
990 return status;
991}
992
993/**
994 * smb2_handle_negotiate() - handler for smb2 negotiate command
995 * @work: smb work containing smb request buffer
996 *
997 * Return: 0
998 */
999int smb2_handle_negotiate(struct ksmbd_work *work)
1000{
1001 struct ksmbd_conn *conn = work->conn;
e5066499
NJ
1002 struct smb2_negotiate_req *req = work->request_buf;
1003 struct smb2_negotiate_rsp *rsp = work->response_buf;
e2f34481
NJ
1004 int rc = 0;
1005 __le32 status;
1006
1007 ksmbd_debug(SMB, "Received negotiate request\n");
1008 conn->need_neg = false;
1009 if (ksmbd_conn_good(work)) {
bde1694a 1010 pr_err("conn->tcp_status is already in CifsGood State\n");
e2f34481
NJ
1011 work->send_no_response = 1;
1012 return rc;
1013 }
1014
1015 if (req->DialectCount == 0) {
bde1694a 1016 pr_err("malformed packet\n");
e2f34481
NJ
1017 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
1018 rc = -EINVAL;
1019 goto err_out;
1020 }
1021
1022 conn->cli_cap = le32_to_cpu(req->Capabilities);
1023 switch (conn->dialect) {
1024 case SMB311_PROT_ID:
1025 conn->preauth_info =
1026 kzalloc(sizeof(struct preauth_integrity_info),
070fb21e 1027 GFP_KERNEL);
e2f34481
NJ
1028 if (!conn->preauth_info) {
1029 rc = -ENOMEM;
1030 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
1031 goto err_out;
1032 }
1033
1034 status = deassemble_neg_contexts(conn, req);
1035 if (status != STATUS_SUCCESS) {
bde1694a
NJ
1036 pr_err("deassemble_neg_contexts error(0x%x)\n",
1037 status);
e2f34481
NJ
1038 rsp->hdr.Status = status;
1039 rc = -EINVAL;
1040 goto err_out;
1041 }
1042
1043 rc = init_smb3_11_server(conn);
1044 if (rc < 0) {
1045 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
1046 goto err_out;
1047 }
1048
1049 ksmbd_gen_preauth_integrity_hash(conn,
070fb21e
NJ
1050 work->request_buf,
1051 conn->preauth_info->Preauth_HashValue);
e2f34481
NJ
1052 rsp->NegotiateContextOffset =
1053 cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
1054 assemble_neg_contexts(conn, rsp);
1055 break;
1056 case SMB302_PROT_ID:
1057 init_smb3_02_server(conn);
1058 break;
1059 case SMB30_PROT_ID:
1060 init_smb3_0_server(conn);
1061 break;
1062 case SMB21_PROT_ID:
1063 init_smb2_1_server(conn);
1064 break;
1065 case SMB20_PROT_ID:
1066 rc = init_smb2_0_server(conn);
1067 if (rc) {
1068 rsp->hdr.Status = STATUS_NOT_SUPPORTED;
1069 goto err_out;
1070 }
1071 break;
1072 case SMB2X_PROT_ID:
1073 case BAD_PROT_ID:
1074 default:
1075 ksmbd_debug(SMB, "Server dialect :0x%x not supported\n",
070fb21e 1076 conn->dialect);
e2f34481
NJ
1077 rsp->hdr.Status = STATUS_NOT_SUPPORTED;
1078 rc = -EINVAL;
1079 goto err_out;
1080 }
1081 rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
1082
1083 /* For stats */
1084 conn->connection_type = conn->dialect;
1085
1086 rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size);
1087 rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
1088 rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size);
1089
1090 if (conn->dialect > SMB20_PROT_ID) {
1091 memcpy(conn->ClientGUID, req->ClientGUID,
070fb21e 1092 SMB2_CLIENT_GUID_SIZE);
e2f34481
NJ
1093 conn->cli_sec_mode = le16_to_cpu(req->SecurityMode);
1094 }
1095
1096 rsp->StructureSize = cpu_to_le16(65);
1097 rsp->DialectRevision = cpu_to_le16(conn->dialect);
1098 /* Not setting conn guid rsp->ServerGUID, as it
1099 * not used by client for identifying server
1100 */
1101 memset(rsp->ServerGUID, 0, SMB2_CLIENT_GUID_SIZE);
1102
1103 rsp->SystemTime = cpu_to_le64(ksmbd_systime());
1104 rsp->ServerStartTime = 0;
1105 ksmbd_debug(SMB, "negotiate context offset %d, count %d\n",
070fb21e
NJ
1106 le32_to_cpu(rsp->NegotiateContextOffset),
1107 le16_to_cpu(rsp->NegotiateContextCount));
e2f34481
NJ
1108
1109 rsp->SecurityBufferOffset = cpu_to_le16(128);
1110 rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
1111 ksmbd_copy_gss_neg_header(((char *)(&rsp->hdr) +
070fb21e
NJ
1112 sizeof(rsp->hdr.smb2_buf_length)) +
1113 le16_to_cpu(rsp->SecurityBufferOffset));
e2f34481 1114 inc_rfc1001_len(rsp, sizeof(struct smb2_negotiate_rsp) -
070fb21e
NJ
1115 sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
1116 AUTH_GSS_LENGTH);
e2f34481
NJ
1117 rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
1118 conn->use_spnego = true;
1119
1120 if ((server_conf.signing == KSMBD_CONFIG_OPT_AUTO ||
64b39f4a
NJ
1121 server_conf.signing == KSMBD_CONFIG_OPT_DISABLED) &&
1122 req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED_LE)
e2f34481
NJ
1123 conn->sign = true;
1124 else if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY) {
1125 server_conf.enforced_signing = true;
1126 rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
1127 conn->sign = true;
1128 }
1129
1130 conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode);
1131 ksmbd_conn_set_need_negotiate(work);
1132
1133err_out:
1134 if (rc < 0)
1135 smb2_set_err_rsp(work);
1136
1137 return rc;
1138}
1139
1140static int alloc_preauth_hash(struct ksmbd_session *sess,
070fb21e 1141 struct ksmbd_conn *conn)
e2f34481
NJ
1142{
1143 if (sess->Preauth_HashValue)
1144 return 0;
1145
86f52978 1146 sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue,
070fb21e 1147 PREAUTH_HASHVALUE_SIZE, GFP_KERNEL);
e2f34481
NJ
1148 if (!sess->Preauth_HashValue)
1149 return -ENOMEM;
1150
e2f34481
NJ
1151 return 0;
1152}
1153
1154static int generate_preauth_hash(struct ksmbd_work *work)
1155{
1156 struct ksmbd_conn *conn = work->conn;
1157 struct ksmbd_session *sess = work->sess;
f5a544e3 1158 u8 *preauth_hash;
e2f34481
NJ
1159
1160 if (conn->dialect != SMB311_PROT_ID)
1161 return 0;
1162
f5a544e3
NJ
1163 if (conn->binding) {
1164 struct preauth_session *preauth_sess;
1165
1166 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
1167 if (!preauth_sess) {
1168 preauth_sess = ksmbd_preauth_session_alloc(conn, sess->id);
1169 if (!preauth_sess)
1170 return -ENOMEM;
1171 }
1172
1173 preauth_hash = preauth_sess->Preauth_HashValue;
1174 } else {
1175 if (!sess->Preauth_HashValue)
1176 if (alloc_preauth_hash(sess, conn))
1177 return -ENOMEM;
1178 preauth_hash = sess->Preauth_HashValue;
e2f34481
NJ
1179 }
1180
f5a544e3 1181 ksmbd_gen_preauth_integrity_hash(conn, work->request_buf, preauth_hash);
e2f34481
NJ
1182 return 0;
1183}
1184
1185static int decode_negotiation_token(struct ksmbd_work *work,
070fb21e 1186 struct negotiate_message *negblob)
e2f34481
NJ
1187{
1188 struct ksmbd_conn *conn = work->conn;
1189 struct smb2_sess_setup_req *req;
1190 int sz;
1191
1192 if (!conn->use_spnego)
1193 return -EINVAL;
1194
e5066499 1195 req = work->request_buf;
e2f34481
NJ
1196 sz = le16_to_cpu(req->SecurityBufferLength);
1197
fad4161b
HL
1198 if (ksmbd_decode_negTokenInit((char *)negblob, sz, conn)) {
1199 if (ksmbd_decode_negTokenTarg((char *)negblob, sz, conn)) {
e2f34481
NJ
1200 conn->auth_mechs |= KSMBD_AUTH_NTLMSSP;
1201 conn->preferred_auth_mech = KSMBD_AUTH_NTLMSSP;
1202 conn->use_spnego = false;
1203 }
1204 }
1205 return 0;
1206}
1207
1208static int ntlm_negotiate(struct ksmbd_work *work,
070fb21e 1209 struct negotiate_message *negblob)
e2f34481 1210{
e5066499
NJ
1211 struct smb2_sess_setup_req *req = work->request_buf;
1212 struct smb2_sess_setup_rsp *rsp = work->response_buf;
e2f34481
NJ
1213 struct challenge_message *chgblob;
1214 unsigned char *spnego_blob = NULL;
1215 u16 spnego_blob_len;
1216 char *neg_blob;
1217 int sz, rc;
1218
1219 ksmbd_debug(SMB, "negotiate phase\n");
1220 sz = le16_to_cpu(req->SecurityBufferLength);
1221 rc = ksmbd_decode_ntlmssp_neg_blob(negblob, sz, work->sess);
1222 if (rc)
1223 return rc;
1224
1225 sz = le16_to_cpu(rsp->SecurityBufferOffset);
1226 chgblob =
1227 (struct challenge_message *)((char *)&rsp->hdr.ProtocolId + sz);
1228 memset(chgblob, 0, sizeof(struct challenge_message));
1229
1230 if (!work->conn->use_spnego) {
1231 sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->sess);
1232 if (sz < 0)
1233 return -ENOMEM;
1234
1235 rsp->SecurityBufferLength = cpu_to_le16(sz);
1236 return 0;
1237 }
1238
1239 sz = sizeof(struct challenge_message);
1240 sz += (strlen(ksmbd_netbios_name()) * 2 + 1 + 4) * 6;
1241
1242 neg_blob = kzalloc(sz, GFP_KERNEL);
1243 if (!neg_blob)
1244 return -ENOMEM;
1245
1246 chgblob = (struct challenge_message *)neg_blob;
1247 sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->sess);
1248 if (sz < 0) {
1249 rc = -ENOMEM;
1250 goto out;
1251 }
1252
070fb21e
NJ
1253 rc = build_spnego_ntlmssp_neg_blob(&spnego_blob, &spnego_blob_len,
1254 neg_blob, sz);
e2f34481
NJ
1255 if (rc) {
1256 rc = -ENOMEM;
1257 goto out;
1258 }
1259
1260 sz = le16_to_cpu(rsp->SecurityBufferOffset);
1261 memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
1262 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
1263
1264out:
1265 kfree(spnego_blob);
1266 kfree(neg_blob);
1267 return rc;
1268}
1269
1270static struct authenticate_message *user_authblob(struct ksmbd_conn *conn,
070fb21e 1271 struct smb2_sess_setup_req *req)
e2f34481
NJ
1272{
1273 int sz;
1274
1275 if (conn->use_spnego && conn->mechToken)
1276 return (struct authenticate_message *)conn->mechToken;
1277
1278 sz = le16_to_cpu(req->SecurityBufferOffset);
1279 return (struct authenticate_message *)((char *)&req->hdr.ProtocolId
1280 + sz);
1281}
1282
1283static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
070fb21e 1284 struct smb2_sess_setup_req *req)
e2f34481
NJ
1285{
1286 struct authenticate_message *authblob;
1287 struct ksmbd_user *user;
1288 char *name;
1289 int sz;
1290
1291 authblob = user_authblob(conn, req);
1292 sz = le32_to_cpu(authblob->UserName.BufferOffset);
1293 name = smb_strndup_from_utf16((const char *)authblob + sz,
1294 le16_to_cpu(authblob->UserName.Length),
1295 true,
1296 conn->local_nls);
1297 if (IS_ERR(name)) {
bde1694a 1298 pr_err("cannot allocate memory\n");
e2f34481
NJ
1299 return NULL;
1300 }
1301
1302 ksmbd_debug(SMB, "session setup request for user %s\n", name);
1303 user = ksmbd_login_user(name);
1304 kfree(name);
1305 return user;
1306}
1307
1308static int ntlm_authenticate(struct ksmbd_work *work)
1309{
e5066499
NJ
1310 struct smb2_sess_setup_req *req = work->request_buf;
1311 struct smb2_sess_setup_rsp *rsp = work->response_buf;
e2f34481
NJ
1312 struct ksmbd_conn *conn = work->conn;
1313 struct ksmbd_session *sess = work->sess;
1314 struct channel *chann = NULL;
1315 struct ksmbd_user *user;
64b39f4a 1316 u64 prev_id;
e2f34481
NJ
1317 int sz, rc;
1318
1319 ksmbd_debug(SMB, "authenticate phase\n");
1320 if (conn->use_spnego) {
1321 unsigned char *spnego_blob;
1322 u16 spnego_blob_len;
1323
1324 rc = build_spnego_ntlmssp_auth_blob(&spnego_blob,
1325 &spnego_blob_len,
1326 0);
1327 if (rc)
1328 return -ENOMEM;
1329
1330 sz = le16_to_cpu(rsp->SecurityBufferOffset);
64b39f4a 1331 memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
e2f34481
NJ
1332 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
1333 kfree(spnego_blob);
1334 inc_rfc1001_len(rsp, spnego_blob_len - 1);
1335 }
1336
1337 user = session_user(conn, req);
1338 if (!user) {
1339 ksmbd_debug(SMB, "Unknown user name or an error\n");
1340 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1341 return -EINVAL;
1342 }
1343
1344 /* Check for previous session */
1345 prev_id = le64_to_cpu(req->PreviousSessionId);
1346 if (prev_id && prev_id != sess->id)
1347 destroy_previous_session(user, prev_id);
1348
1349 if (sess->state == SMB2_SESSION_VALID) {
1350 /*
1351 * Reuse session if anonymous try to connect
1352 * on reauthetication.
1353 */
1354 if (ksmbd_anonymous_user(user)) {
1355 ksmbd_free_user(user);
1356 return 0;
1357 }
1358 ksmbd_free_user(sess->user);
1359 }
1360
1361 sess->user = user;
1362 if (user_guest(sess->user)) {
1363 if (conn->sign) {
64b39f4a 1364 ksmbd_debug(SMB, "Guest login not allowed when signing enabled\n");
e2f34481
NJ
1365 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1366 return -EACCES;
1367 }
1368
1369 rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE;
1370 } else {
1371 struct authenticate_message *authblob;
1372
1373 authblob = user_authblob(conn, req);
1374 sz = le16_to_cpu(req->SecurityBufferLength);
1375 rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, sess);
1376 if (rc) {
1377 set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD);
1378 ksmbd_debug(SMB, "authentication failed\n");
1379 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1380 return -EINVAL;
1381 }
1382
1383 /*
1384 * If session state is SMB2_SESSION_VALID, We can assume
1385 * that it is reauthentication. And the user/password
1386 * has been verified, so return it here.
1387 */
f5a544e3
NJ
1388 if (sess->state == SMB2_SESSION_VALID) {
1389 if (conn->binding)
1390 goto binding_session;
e2f34481 1391 return 0;
f5a544e3 1392 }
e2f34481
NJ
1393
1394 if ((conn->sign || server_conf.enforced_signing) ||
64b39f4a 1395 (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
e2f34481
NJ
1396 sess->sign = true;
1397
1398 if (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION &&
f5a544e3
NJ
1399 conn->ops->generate_encryptionkey &&
1400 !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
e2f34481
NJ
1401 rc = conn->ops->generate_encryptionkey(sess);
1402 if (rc) {
1403 ksmbd_debug(SMB,
070fb21e 1404 "SMB3 encryption key generation failed\n");
e2f34481
NJ
1405 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1406 return rc;
1407 }
1408 sess->enc = true;
1409 rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
1410 /*
1411 * signing is disable if encryption is enable
1412 * on this session
1413 */
1414 sess->sign = false;
1415 }
1416 }
1417
f5a544e3 1418binding_session:
e2f34481 1419 if (conn->dialect >= SMB30_PROT_ID) {
f5a544e3 1420 chann = lookup_chann_list(sess, conn);
e2f34481
NJ
1421 if (!chann) {
1422 chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
1423 if (!chann)
1424 return -ENOMEM;
1425
1426 chann->conn = conn;
1427 INIT_LIST_HEAD(&chann->chann_list);
1428 list_add(&chann->chann_list, &sess->ksmbd_chann_list);
1429 }
1430 }
1431
1432 if (conn->ops->generate_signingkey) {
f5a544e3 1433 rc = conn->ops->generate_signingkey(sess, conn);
e2f34481 1434 if (rc) {
64b39f4a 1435 ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
e2f34481
NJ
1436 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1437 return rc;
1438 }
1439 }
1440
1441 if (conn->dialect > SMB20_PROT_ID) {
1442 if (!ksmbd_conn_lookup_dialect(conn)) {
bde1694a 1443 pr_err("fail to verify the dialect\n");
e2f34481
NJ
1444 rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
1445 return -EPERM;
1446 }
1447 }
1448 return 0;
1449}
1450
1451#ifdef CONFIG_SMB_SERVER_KERBEROS5
1452static int krb5_authenticate(struct ksmbd_work *work)
1453{
e5066499
NJ
1454 struct smb2_sess_setup_req *req = work->request_buf;
1455 struct smb2_sess_setup_rsp *rsp = work->response_buf;
e2f34481
NJ
1456 struct ksmbd_conn *conn = work->conn;
1457 struct ksmbd_session *sess = work->sess;
1458 char *in_blob, *out_blob;
1459 struct channel *chann = NULL;
64b39f4a 1460 u64 prev_sess_id;
e2f34481
NJ
1461 int in_len, out_len;
1462 int retval;
1463
1464 in_blob = (char *)&req->hdr.ProtocolId +
1465 le16_to_cpu(req->SecurityBufferOffset);
1466 in_len = le16_to_cpu(req->SecurityBufferLength);
1467 out_blob = (char *)&rsp->hdr.ProtocolId +
1468 le16_to_cpu(rsp->SecurityBufferOffset);
1469 out_len = work->response_sz -
1470 offsetof(struct smb2_hdr, smb2_buf_length) -
1471 le16_to_cpu(rsp->SecurityBufferOffset);
1472
1473 /* Check previous session */
1474 prev_sess_id = le64_to_cpu(req->PreviousSessionId);
1475 if (prev_sess_id && prev_sess_id != sess->id)
1476 destroy_previous_session(sess->user, prev_sess_id);
1477
1478 if (sess->state == SMB2_SESSION_VALID)
1479 ksmbd_free_user(sess->user);
1480
1481 retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
070fb21e 1482 out_blob, &out_len);
e2f34481
NJ
1483 if (retval) {
1484 ksmbd_debug(SMB, "krb5 authentication failed\n");
1485 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1486 return retval;
1487 }
1488 rsp->SecurityBufferLength = cpu_to_le16(out_len);
1489 inc_rfc1001_len(rsp, out_len - 1);
1490
1491 if ((conn->sign || server_conf.enforced_signing) ||
64b39f4a 1492 (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
e2f34481
NJ
1493 sess->sign = true;
1494
1495 if ((conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) &&
64b39f4a 1496 conn->ops->generate_encryptionkey) {
e2f34481
NJ
1497 retval = conn->ops->generate_encryptionkey(sess);
1498 if (retval) {
1499 ksmbd_debug(SMB,
070fb21e 1500 "SMB3 encryption key generation failed\n");
e2f34481
NJ
1501 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1502 return retval;
1503 }
1504 sess->enc = true;
1505 rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
1506 sess->sign = false;
1507 }
1508
1509 if (conn->dialect >= SMB30_PROT_ID) {
f5a544e3 1510 chann = lookup_chann_list(sess, conn);
e2f34481
NJ
1511 if (!chann) {
1512 chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
1513 if (!chann)
1514 return -ENOMEM;
1515
1516 chann->conn = conn;
1517 INIT_LIST_HEAD(&chann->chann_list);
1518 list_add(&chann->chann_list, &sess->ksmbd_chann_list);
1519 }
1520 }
1521
1522 if (conn->ops->generate_signingkey) {
f5a544e3 1523 retval = conn->ops->generate_signingkey(sess, conn);
e2f34481 1524 if (retval) {
64b39f4a 1525 ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
e2f34481
NJ
1526 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1527 return retval;
1528 }
1529 }
1530
1531 if (conn->dialect > SMB20_PROT_ID) {
1532 if (!ksmbd_conn_lookup_dialect(conn)) {
bde1694a 1533 pr_err("fail to verify the dialect\n");
e2f34481
NJ
1534 rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
1535 return -EPERM;
1536 }
1537 }
1538 return 0;
1539}
1540#else
1541static int krb5_authenticate(struct ksmbd_work *work)
1542{
1543 return -EOPNOTSUPP;
1544}
1545#endif
1546
1547int smb2_sess_setup(struct ksmbd_work *work)
1548{
1549 struct ksmbd_conn *conn = work->conn;
e5066499
NJ
1550 struct smb2_sess_setup_req *req = work->request_buf;
1551 struct smb2_sess_setup_rsp *rsp = work->response_buf;
e2f34481
NJ
1552 struct ksmbd_session *sess;
1553 struct negotiate_message *negblob;
1554 int rc = 0;
1555
1556 ksmbd_debug(SMB, "Received request for session setup\n");
1557
1558 rsp->StructureSize = cpu_to_le16(9);
1559 rsp->SessionFlags = 0;
1560 rsp->SecurityBufferOffset = cpu_to_le16(72);
1561 rsp->SecurityBufferLength = 0;
1562 inc_rfc1001_len(rsp, 9);
1563
1564 if (!req->hdr.SessionId) {
1565 sess = ksmbd_smb2_session_create();
1566 if (!sess) {
1567 rc = -ENOMEM;
1568 goto out_err;
1569 }
1570 rsp->hdr.SessionId = cpu_to_le64(sess->id);
1571 ksmbd_session_register(conn, sess);
f5a544e3
NJ
1572 } else if (conn->dialect >= SMB30_PROT_ID &&
1573 (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
1574 req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) {
1575 u64 sess_id = le64_to_cpu(req->hdr.SessionId);
1576
1577 sess = ksmbd_session_lookup_slowpath(sess_id);
1578 if (!sess) {
1579 rc = -ENOENT;
1580 goto out_err;
1581 }
1582
1583 if (conn->dialect != sess->conn->dialect) {
1584 rc = -EINVAL;
1585 goto out_err;
1586 }
1587
1588 if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
1589 rc = -EINVAL;
1590 goto out_err;
1591 }
1592
1593 if (strncmp(conn->ClientGUID, sess->conn->ClientGUID,
1594 SMB2_CLIENT_GUID_SIZE)) {
1595 rc = -ENOENT;
1596 goto out_err;
1597 }
1598
1599 if (sess->state == SMB2_SESSION_IN_PROGRESS) {
1600 rc = -EACCES;
1601 goto out_err;
1602 }
1603
1604 if (sess->state == SMB2_SESSION_EXPIRED) {
1605 rc = -EFAULT;
1606 goto out_err;
1607 }
1608
1609 if (ksmbd_session_lookup(conn, sess_id)) {
1610 rc = -EACCES;
1611 goto out_err;
1612 }
1613
1614 conn->binding = true;
1615 } else if ((conn->dialect < SMB30_PROT_ID ||
1616 server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
1617 (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
1618 rc = -EACCES;
1619 goto out_err;
e2f34481
NJ
1620 } else {
1621 sess = ksmbd_session_lookup(conn,
070fb21e 1622 le64_to_cpu(req->hdr.SessionId));
e2f34481
NJ
1623 if (!sess) {
1624 rc = -ENOENT;
e2f34481
NJ
1625 goto out_err;
1626 }
1627 }
1628 work->sess = sess;
1629
1630 if (sess->state == SMB2_SESSION_EXPIRED)
1631 sess->state = SMB2_SESSION_IN_PROGRESS;
1632
1633 negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId +
1634 le16_to_cpu(req->SecurityBufferOffset));
1635
1636 if (decode_negotiation_token(work, negblob) == 0) {
1637 if (conn->mechToken)
1638 negblob = (struct negotiate_message *)conn->mechToken;
1639 }
1640
1641 if (server_conf.auth_mechs & conn->auth_mechs) {
f5a544e3
NJ
1642 rc = generate_preauth_hash(work);
1643 if (rc)
1644 goto out_err;
1645
e2f34481
NJ
1646 if (conn->preferred_auth_mech &
1647 (KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5)) {
e2f34481
NJ
1648 rc = krb5_authenticate(work);
1649 if (rc) {
f5a544e3 1650 rc = -EINVAL;
e2f34481
NJ
1651 goto out_err;
1652 }
1653
1654 ksmbd_conn_set_good(work);
1655 sess->state = SMB2_SESSION_VALID;
822bc8ea 1656 kfree(sess->Preauth_HashValue);
e2f34481
NJ
1657 sess->Preauth_HashValue = NULL;
1658 } else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
e2f34481
NJ
1659 if (negblob->MessageType == NtLmNegotiate) {
1660 rc = ntlm_negotiate(work, negblob);
1661 if (rc)
1662 goto out_err;
1663 rsp->hdr.Status =
1664 STATUS_MORE_PROCESSING_REQUIRED;
1665 /*
1666 * Note: here total size -1 is done as an
1667 * adjustment for 0 size blob
1668 */
64b39f4a 1669 inc_rfc1001_len(rsp, le16_to_cpu(rsp->SecurityBufferLength) - 1);
e2f34481
NJ
1670
1671 } else if (negblob->MessageType == NtLmAuthenticate) {
1672 rc = ntlm_authenticate(work);
1673 if (rc)
1674 goto out_err;
1675
1676 ksmbd_conn_set_good(work);
1677 sess->state = SMB2_SESSION_VALID;
f5a544e3
NJ
1678 if (conn->binding) {
1679 struct preauth_session *preauth_sess;
1680
1681 preauth_sess =
1682 ksmbd_preauth_session_lookup(conn, sess->id);
1683 if (preauth_sess) {
1684 list_del(&preauth_sess->preauth_entry);
1685 kfree(preauth_sess);
1686 }
1687 }
822bc8ea 1688 kfree(sess->Preauth_HashValue);
e2f34481
NJ
1689 sess->Preauth_HashValue = NULL;
1690 }
1691 } else {
1692 /* TODO: need one more negotiation */
bde1694a 1693 pr_err("Not support the preferred authentication\n");
e2f34481 1694 rc = -EINVAL;
e2f34481
NJ
1695 }
1696 } else {
bde1694a 1697 pr_err("Not support authentication\n");
e2f34481 1698 rc = -EINVAL;
e2f34481
NJ
1699 }
1700
1701out_err:
f5a544e3
NJ
1702 if (rc == -EINVAL)
1703 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
1704 else if (rc == -ENOENT)
1705 rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
1706 else if (rc == -EACCES)
1707 rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
1708 else if (rc == -EFAULT)
1709 rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED;
1710 else if (rc)
1711 rsp->hdr.Status = STATUS_LOGON_FAILURE;
1712
e2f34481
NJ
1713 if (conn->use_spnego && conn->mechToken) {
1714 kfree(conn->mechToken);
1715 conn->mechToken = NULL;
1716 }
1717
1718 if (rc < 0 && sess) {
1719 ksmbd_session_destroy(sess);
1720 work->sess = NULL;
1721 }
1722
1723 return rc;
1724}
1725
1726/**
1727 * smb2_tree_connect() - handler for smb2 tree connect command
1728 * @work: smb work containing smb request buffer
1729 *
1730 * Return: 0 on success, otherwise error
1731 */
1732int smb2_tree_connect(struct ksmbd_work *work)
1733{
1734 struct ksmbd_conn *conn = work->conn;
e5066499
NJ
1735 struct smb2_tree_connect_req *req = work->request_buf;
1736 struct smb2_tree_connect_rsp *rsp = work->response_buf;
e2f34481
NJ
1737 struct ksmbd_session *sess = work->sess;
1738 char *treename = NULL, *name = NULL;
1739 struct ksmbd_tree_conn_status status;
1740 struct ksmbd_share_config *share;
1741 int rc = -EINVAL;
1742
1743 treename = smb_strndup_from_utf16(req->Buffer,
070fb21e
NJ
1744 le16_to_cpu(req->PathLength), true,
1745 conn->local_nls);
e2f34481 1746 if (IS_ERR(treename)) {
bde1694a 1747 pr_err("treename is NULL\n");
e2f34481
NJ
1748 status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
1749 goto out_err1;
1750 }
1751
36ba3866 1752 name = ksmbd_extract_sharename(treename);
e2f34481
NJ
1753 if (IS_ERR(name)) {
1754 status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
1755 goto out_err1;
1756 }
1757
1758 ksmbd_debug(SMB, "tree connect request for tree %s treename %s\n",
070fb21e 1759 name, treename);
e2f34481
NJ
1760
1761 status = ksmbd_tree_conn_connect(sess, name);
1762 if (status.ret == KSMBD_TREE_CONN_STATUS_OK)
1763 rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id);
1764 else
1765 goto out_err1;
1766
1767 share = status.tree_conn->share_conf;
1768 if (test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
1769 ksmbd_debug(SMB, "IPC share path request\n");
1770 rsp->ShareType = SMB2_SHARE_TYPE_PIPE;
1771 rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE |
1772 FILE_EXECUTE_LE | FILE_READ_ATTRIBUTES_LE |
1773 FILE_DELETE_LE | FILE_READ_CONTROL_LE |
1774 FILE_WRITE_DAC_LE | FILE_WRITE_OWNER_LE |
1775 FILE_SYNCHRONIZE_LE;
1776 } else {
1777 rsp->ShareType = SMB2_SHARE_TYPE_DISK;
1778 rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE |
1779 FILE_EXECUTE_LE | FILE_READ_ATTRIBUTES_LE;
1780 if (test_tree_conn_flag(status.tree_conn,
1781 KSMBD_TREE_CONN_FLAG_WRITABLE)) {
1782 rsp->MaximalAccess |= FILE_WRITE_DATA_LE |
1783 FILE_APPEND_DATA_LE | FILE_WRITE_EA_LE |
3aefd54d
WJ
1784 FILE_DELETE_LE | FILE_WRITE_ATTRIBUTES_LE |
1785 FILE_DELETE_CHILD_LE | FILE_READ_CONTROL_LE |
1786 FILE_WRITE_DAC_LE | FILE_WRITE_OWNER_LE |
1787 FILE_SYNCHRONIZE_LE;
e2f34481
NJ
1788 }
1789 }
1790
1791 status.tree_conn->maximal_access = le32_to_cpu(rsp->MaximalAccess);
1792 if (conn->posix_ext_supported)
1793 status.tree_conn->posix_extensions = true;
1794
1795out_err1:
1796 rsp->StructureSize = cpu_to_le16(16);
1797 rsp->Capabilities = 0;
1798 rsp->Reserved = 0;
1799 /* default manual caching */
1800 rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
1801 inc_rfc1001_len(rsp, 16);
1802
1803 if (!IS_ERR(treename))
1804 kfree(treename);
1805 if (!IS_ERR(name))
1806 kfree(name);
1807
1808 switch (status.ret) {
1809 case KSMBD_TREE_CONN_STATUS_OK:
1810 rsp->hdr.Status = STATUS_SUCCESS;
1811 rc = 0;
1812 break;
1813 case KSMBD_TREE_CONN_STATUS_NO_SHARE:
1814 rsp->hdr.Status = STATUS_BAD_NETWORK_PATH;
1815 break;
1816 case -ENOMEM:
1817 case KSMBD_TREE_CONN_STATUS_NOMEM:
1818 rsp->hdr.Status = STATUS_NO_MEMORY;
1819 break;
1820 case KSMBD_TREE_CONN_STATUS_ERROR:
1821 case KSMBD_TREE_CONN_STATUS_TOO_MANY_CONNS:
1822 case KSMBD_TREE_CONN_STATUS_TOO_MANY_SESSIONS:
1823 rsp->hdr.Status = STATUS_ACCESS_DENIED;
1824 break;
1825 case -EINVAL:
1826 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
1827 break;
1828 default:
1829 rsp->hdr.Status = STATUS_ACCESS_DENIED;
1830 }
1831
1832 return rc;
1833}
1834
1835/**
1836 * smb2_create_open_flags() - convert smb open flags to unix open flags
1837 * @file_present: is file already present
1838 * @access: file access flags
1839 * @disposition: file disposition flags
6c5e36d1 1840 * @may_flags: set with MAY_ flags
e2f34481
NJ
1841 *
1842 * Return: file open flags
1843 */
1844static int smb2_create_open_flags(bool file_present, __le32 access,
6c5e36d1
HL
1845 __le32 disposition,
1846 int *may_flags)
e2f34481
NJ
1847{
1848 int oflags = O_NONBLOCK | O_LARGEFILE;
1849
1850 if (access & FILE_READ_DESIRED_ACCESS_LE &&
6c5e36d1 1851 access & FILE_WRITE_DESIRE_ACCESS_LE) {
e2f34481 1852 oflags |= O_RDWR;
6c5e36d1
HL
1853 *may_flags = MAY_OPEN | MAY_READ | MAY_WRITE;
1854 } else if (access & FILE_WRITE_DESIRE_ACCESS_LE) {
e2f34481 1855 oflags |= O_WRONLY;
6c5e36d1
HL
1856 *may_flags = MAY_OPEN | MAY_WRITE;
1857 } else {
e2f34481 1858 oflags |= O_RDONLY;
6c5e36d1
HL
1859 *may_flags = MAY_OPEN | MAY_READ;
1860 }
e2f34481
NJ
1861
1862 if (access == FILE_READ_ATTRIBUTES_LE)
1863 oflags |= O_PATH;
1864
1865 if (file_present) {
1866 switch (disposition & FILE_CREATE_MASK_LE) {
1867 case FILE_OPEN_LE:
1868 case FILE_CREATE_LE:
1869 break;
1870 case FILE_SUPERSEDE_LE:
1871 case FILE_OVERWRITE_LE:
1872 case FILE_OVERWRITE_IF_LE:
1873 oflags |= O_TRUNC;
1874 break;
1875 default:
1876 break;
1877 }
1878 } else {
1879 switch (disposition & FILE_CREATE_MASK_LE) {
1880 case FILE_SUPERSEDE_LE:
1881 case FILE_CREATE_LE:
1882 case FILE_OPEN_IF_LE:
1883 case FILE_OVERWRITE_IF_LE:
1884 oflags |= O_CREAT;
1885 break;
1886 case FILE_OPEN_LE:
1887 case FILE_OVERWRITE_LE:
1888 oflags &= ~O_CREAT;
1889 break;
1890 default:
1891 break;
1892 }
1893 }
6c5e36d1 1894
e2f34481
NJ
1895 return oflags;
1896}
1897
1898/**
1899 * smb2_tree_disconnect() - handler for smb tree connect request
1900 * @work: smb work containing request buffer
1901 *
1902 * Return: 0
1903 */
1904int smb2_tree_disconnect(struct ksmbd_work *work)
1905{
e5066499 1906 struct smb2_tree_disconnect_rsp *rsp = work->response_buf;
e2f34481
NJ
1907 struct ksmbd_session *sess = work->sess;
1908 struct ksmbd_tree_connect *tcon = work->tcon;
1909
1910 rsp->StructureSize = cpu_to_le16(4);
1911 inc_rfc1001_len(rsp, 4);
1912
1913 ksmbd_debug(SMB, "request\n");
1914
1915 if (!tcon) {
e5066499 1916 struct smb2_tree_disconnect_req *req = work->request_buf;
e2f34481
NJ
1917
1918 ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
1919 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
1920 smb2_set_err_rsp(work);
1921 return 0;
1922 }
1923
1924 ksmbd_close_tree_conn_fds(work);
1925 ksmbd_tree_conn_disconnect(sess, tcon);
1926 return 0;
1927}
1928
1929/**
1930 * smb2_session_logoff() - handler for session log off request
1931 * @work: smb work containing request buffer
1932 *
1933 * Return: 0
1934 */
1935int smb2_session_logoff(struct ksmbd_work *work)
1936{
1937 struct ksmbd_conn *conn = work->conn;
e5066499 1938 struct smb2_logoff_rsp *rsp = work->response_buf;
e2f34481
NJ
1939 struct ksmbd_session *sess = work->sess;
1940
1941 rsp->StructureSize = cpu_to_le16(4);
1942 inc_rfc1001_len(rsp, 4);
1943
1944 ksmbd_debug(SMB, "request\n");
1945
1946 /* Got a valid session, set connection state */
1947 WARN_ON(sess->conn != conn);
1948
1949 /* setting CifsExiting here may race with start_tcp_sess */
1950 ksmbd_conn_set_need_reconnect(work);
1951 ksmbd_close_session_fds(work);
1952 ksmbd_conn_wait_idle(conn);
1953
1954 if (ksmbd_tree_conn_session_logoff(sess)) {
e5066499 1955 struct smb2_logoff_req *req = work->request_buf;
e2f34481
NJ
1956
1957 ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
1958 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
1959 smb2_set_err_rsp(work);
1960 return 0;
1961 }
1962
1963 ksmbd_destroy_file_table(&sess->file_table);
1964 sess->state = SMB2_SESSION_EXPIRED;
1965
1966 ksmbd_free_user(sess->user);
1967 sess->user = NULL;
1968
1969 /* let start_tcp_sess free connection info now */
1970 ksmbd_conn_set_need_negotiate(work);
1971 return 0;
1972}
1973
1974/**
1975 * create_smb2_pipe() - create IPC pipe
1976 * @work: smb work containing request buffer
1977 *
1978 * Return: 0 on success, otherwise error
1979 */
1980static noinline int create_smb2_pipe(struct ksmbd_work *work)
1981{
e5066499
NJ
1982 struct smb2_create_rsp *rsp = work->response_buf;
1983 struct smb2_create_req *req = work->request_buf;
e2f34481
NJ
1984 int id;
1985 int err;
1986 char *name;
1987
1988 name = smb_strndup_from_utf16(req->Buffer, le16_to_cpu(req->NameLength),
070fb21e 1989 1, work->conn->local_nls);
e2f34481
NJ
1990 if (IS_ERR(name)) {
1991 rsp->hdr.Status = STATUS_NO_MEMORY;
1992 err = PTR_ERR(name);
1993 goto out;
1994 }
1995
1996 id = ksmbd_session_rpc_open(work->sess, name);
79caa960 1997 if (id < 0) {
bde1694a 1998 pr_err("Unable to open RPC pipe: %d\n", id);
79caa960
MM
1999 err = id;
2000 goto out;
2001 }
e2f34481 2002
79caa960 2003 rsp->hdr.Status = STATUS_SUCCESS;
e2f34481
NJ
2004 rsp->StructureSize = cpu_to_le16(89);
2005 rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;
2006 rsp->Reserved = 0;
2007 rsp->CreateAction = cpu_to_le32(FILE_OPENED);
2008
2009 rsp->CreationTime = cpu_to_le64(0);
2010 rsp->LastAccessTime = cpu_to_le64(0);
2011 rsp->ChangeTime = cpu_to_le64(0);
2012 rsp->AllocationSize = cpu_to_le64(0);
2013 rsp->EndofFile = cpu_to_le64(0);
2014 rsp->FileAttributes = ATTR_NORMAL_LE;
2015 rsp->Reserved2 = 0;
2016 rsp->VolatileFileId = cpu_to_le64(id);
2017 rsp->PersistentFileId = 0;
2018 rsp->CreateContextsOffset = 0;
2019 rsp->CreateContextsLength = 0;
2020
2021 inc_rfc1001_len(rsp, 88); /* StructureSize - 1*/
2022 kfree(name);
2023 return 0;
2024
2025out:
79caa960
MM
2026 switch (err) {
2027 case -EINVAL:
2028 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
2029 break;
2030 case -ENOSPC:
2031 case -ENOMEM:
2032 rsp->hdr.Status = STATUS_NO_MEMORY;
2033 break;
2034 }
2035
2036 if (!IS_ERR(name))
2037 kfree(name);
2038
e2f34481
NJ
2039 smb2_set_err_rsp(work);
2040 return err;
2041}
2042
e2f34481
NJ
2043/**
2044 * smb2_set_ea() - handler for setting extended attributes using set
2045 * info command
2046 * @eabuf: set info command buffer
2047 * @path: dentry path for get ea
2048 *
2049 * Return: 0 on success, otherwise error
2050 */
2051static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path)
2052{
465d7204 2053 struct user_namespace *user_ns = mnt_user_ns(path->mnt);
e2f34481
NJ
2054 char *attr_name = NULL, *value;
2055 int rc = 0;
2056 int next = 0;
2057
2058 attr_name = kmalloc(XATTR_NAME_MAX + 1, GFP_KERNEL);
2059 if (!attr_name)
2060 return -ENOMEM;
2061
2062 do {
2063 if (!eabuf->EaNameLength)
2064 goto next;
2065
2066 ksmbd_debug(SMB,
070fb21e
NJ
2067 "name : <%s>, name_len : %u, value_len : %u, next : %u\n",
2068 eabuf->name, eabuf->EaNameLength,
2069 le16_to_cpu(eabuf->EaValueLength),
2070 le32_to_cpu(eabuf->NextEntryOffset));
e2f34481
NJ
2071
2072 if (eabuf->EaNameLength >
070fb21e 2073 (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
e2f34481
NJ
2074 rc = -EINVAL;
2075 break;
2076 }
2077
2078 memcpy(attr_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
2079 memcpy(&attr_name[XATTR_USER_PREFIX_LEN], eabuf->name,
070fb21e 2080 eabuf->EaNameLength);
e2f34481
NJ
2081 attr_name[XATTR_USER_PREFIX_LEN + eabuf->EaNameLength] = '\0';
2082 value = (char *)&eabuf->name + eabuf->EaNameLength + 1;
2083
2084 if (!eabuf->EaValueLength) {
465d7204 2085 rc = ksmbd_vfs_casexattr_len(user_ns,
af34983e 2086 path->dentry,
e2f34481
NJ
2087 attr_name,
2088 XATTR_USER_PREFIX_LEN +
2089 eabuf->EaNameLength);
2090
2091 /* delete the EA only when it exits */
2092 if (rc > 0) {
465d7204 2093 rc = ksmbd_vfs_remove_xattr(user_ns,
af34983e 2094 path->dentry,
e2f34481
NJ
2095 attr_name);
2096
2097 if (rc < 0) {
2098 ksmbd_debug(SMB,
070fb21e
NJ
2099 "remove xattr failed(%d)\n",
2100 rc);
e2f34481
NJ
2101 break;
2102 }
2103 }
2104
2105 /* if the EA doesn't exist, just do nothing. */
2106 rc = 0;
2107 } else {
465d7204 2108 rc = ksmbd_vfs_setxattr(user_ns,
af34983e 2109 path->dentry, attr_name, value,
070fb21e 2110 le16_to_cpu(eabuf->EaValueLength), 0);
e2f34481
NJ
2111 if (rc < 0) {
2112 ksmbd_debug(SMB,
070fb21e
NJ
2113 "ksmbd_vfs_setxattr is failed(%d)\n",
2114 rc);
e2f34481
NJ
2115 break;
2116 }
2117 }
2118
2119next:
2120 next = le32_to_cpu(eabuf->NextEntryOffset);
2121 eabuf = (struct smb2_ea_info *)((char *)eabuf + next);
2122 } while (next != 0);
2123
2124 kfree(attr_name);
2125 return rc;
2126}
2127
2128static inline int check_context_err(void *ctx, char *str)
2129{
2130 int err;
2131
2132 err = PTR_ERR(ctx);
2133 ksmbd_debug(SMB, "find context %s err %d\n", str, err);
2134
2135 if (err == -EINVAL) {
bde1694a 2136 pr_err("bad name length\n");
e2f34481
NJ
2137 return err;
2138 }
2139
2140 return 0;
2141}
2142
2143static noinline int smb2_set_stream_name_xattr(struct path *path,
070fb21e
NJ
2144 struct ksmbd_file *fp,
2145 char *stream_name, int s_type)
e2f34481 2146{
465d7204 2147 struct user_namespace *user_ns = mnt_user_ns(path->mnt);
e2f34481
NJ
2148 size_t xattr_stream_size;
2149 char *xattr_stream_name;
2150 int rc;
2151
2152 rc = ksmbd_vfs_xattr_stream_name(stream_name,
2153 &xattr_stream_name,
2154 &xattr_stream_size,
2155 s_type);
2156 if (rc)
2157 return rc;
2158
2159 fp->stream.name = xattr_stream_name;
2160 fp->stream.size = xattr_stream_size;
2161
2162 /* Check if there is stream prefix in xattr space */
465d7204 2163 rc = ksmbd_vfs_casexattr_len(user_ns,
af34983e 2164 path->dentry,
e2f34481
NJ
2165 xattr_stream_name,
2166 xattr_stream_size);
2167 if (rc >= 0)
2168 return 0;
2169
2170 if (fp->cdoption == FILE_OPEN_LE) {
2171 ksmbd_debug(SMB, "XATTR stream name lookup failed: %d\n", rc);
2172 return -EBADF;
2173 }
2174
465d7204
HL
2175 rc = ksmbd_vfs_setxattr(user_ns, path->dentry,
2176 xattr_stream_name, NULL, 0, 0);
e2f34481 2177 if (rc < 0)
bde1694a 2178 pr_err("Failed to store XATTR stream name :%d\n", rc);
e2f34481
NJ
2179 return 0;
2180}
2181
ef24c962 2182static int smb2_remove_smb_xattrs(struct path *path)
e2f34481 2183{
465d7204 2184 struct user_namespace *user_ns = mnt_user_ns(path->mnt);
e2f34481
NJ
2185 char *name, *xattr_list = NULL;
2186 ssize_t xattr_list_len;
2187 int err = 0;
2188
ef24c962 2189 xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
e2f34481
NJ
2190 if (xattr_list_len < 0) {
2191 goto out;
2192 } else if (!xattr_list_len) {
2193 ksmbd_debug(SMB, "empty xattr in the file\n");
2194 goto out;
2195 }
2196
2197 for (name = xattr_list; name - xattr_list < xattr_list_len;
2198 name += strlen(name) + 1) {
2199 ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
2200
2201 if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
64b39f4a
NJ
2202 strncmp(&name[XATTR_USER_PREFIX_LEN], DOS_ATTRIBUTE_PREFIX,
2203 DOS_ATTRIBUTE_PREFIX_LEN) &&
2204 strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN))
e2f34481
NJ
2205 continue;
2206
465d7204 2207 err = ksmbd_vfs_remove_xattr(user_ns, path->dentry, name);
e2f34481
NJ
2208 if (err)
2209 ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
2210 }
2211out:
79f6b11a 2212 kvfree(xattr_list);
e2f34481
NJ
2213 return err;
2214}
2215
2216static int smb2_create_truncate(struct path *path)
2217{
2218 int rc = vfs_truncate(path, 0);
2219
2220 if (rc) {
bde1694a 2221 pr_err("vfs_truncate failed, rc %d\n", rc);
e2f34481
NJ
2222 return rc;
2223 }
2224
ef24c962 2225 rc = smb2_remove_smb_xattrs(path);
e2f34481
NJ
2226 if (rc == -EOPNOTSUPP)
2227 rc = 0;
2228 if (rc)
2229 ksmbd_debug(SMB,
070fb21e
NJ
2230 "ksmbd_truncate_stream_name_xattr failed, rc %d\n",
2231 rc);
e2f34481
NJ
2232 return rc;
2233}
2234
64b39f4a 2235static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, struct path *path,
070fb21e 2236 struct ksmbd_file *fp)
e2f34481
NJ
2237{
2238 struct xattr_dos_attrib da = {0};
2239 int rc;
2240
2241 if (!test_share_config_flag(tcon->share_conf,
2242 KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
2243 return;
2244
2245 da.version = 4;
2246 da.attr = le32_to_cpu(fp->f_ci->m_fattr);
2247 da.itime = da.create_time = fp->create_time;
2248 da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
2249 XATTR_DOSINFO_ITIME;
2250
af34983e
HL
2251 rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt),
2252 path->dentry, &da);
e2f34481
NJ
2253 if (rc)
2254 ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
2255}
2256
2257static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
070fb21e 2258 struct path *path, struct ksmbd_file *fp)
e2f34481
NJ
2259{
2260 struct xattr_dos_attrib da;
2261 int rc;
2262
2263 fp->f_ci->m_fattr &= ~(ATTR_HIDDEN_LE | ATTR_SYSTEM_LE);
2264
2265 /* get FileAttributes from XATTR_NAME_DOS_ATTRIBUTE */
2266 if (!test_share_config_flag(tcon->share_conf,
64b39f4a 2267 KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
e2f34481
NJ
2268 return;
2269
af34983e
HL
2270 rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_user_ns(path->mnt),
2271 path->dentry, &da);
e2f34481
NJ
2272 if (rc > 0) {
2273 fp->f_ci->m_fattr = cpu_to_le32(da.attr);
2274 fp->create_time = da.create_time;
2275 fp->itime = da.itime;
2276 }
2277}
2278
64b39f4a 2279static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
070fb21e 2280 int open_flags, umode_t posix_mode, bool is_dir)
e2f34481
NJ
2281{
2282 struct ksmbd_tree_connect *tcon = work->tcon;
2283 struct ksmbd_share_config *share = tcon->share_conf;
2284 umode_t mode;
2285 int rc;
2286
2287 if (!(open_flags & O_CREAT))
2288 return -EBADF;
2289
2290 ksmbd_debug(SMB, "file does not exist, so creating\n");
2291 if (is_dir == true) {
2292 ksmbd_debug(SMB, "creating directory\n");
2293
2294 mode = share_config_directory_mode(share, posix_mode);
2295 rc = ksmbd_vfs_mkdir(work, name, mode);
2296 if (rc)
2297 return rc;
2298 } else {
2299 ksmbd_debug(SMB, "creating regular file\n");
2300
2301 mode = share_config_create_mode(share, posix_mode);
2302 rc = ksmbd_vfs_create(work, name, mode);
2303 if (rc)
2304 return rc;
2305 }
2306
2307 rc = ksmbd_vfs_kern_path(name, 0, path, 0);
2308 if (rc) {
bde1694a
NJ
2309 pr_err("cannot get linux path (%s), err = %d\n",
2310 name, rc);
e2f34481
NJ
2311 return rc;
2312 }
2313 return 0;
2314}
2315
2316static int smb2_create_sd_buffer(struct ksmbd_work *work,
070fb21e 2317 struct smb2_create_req *req,
ef24c962 2318 struct path *path)
e2f34481
NJ
2319{
2320 struct create_context *context;
2321 int rc = -ENOENT;
2322
2323 if (!req->CreateContextsOffset)
2324 return rc;
2325
2326 /* Parse SD BUFFER create contexts */
2327 context = smb2_find_context_vals(req, SMB2_CREATE_SD_BUFFER);
2328 if (context && !IS_ERR(context)) {
2329 struct create_sd_buf_req *sd_buf;
2330
2331 ksmbd_debug(SMB,
070fb21e 2332 "Set ACLs using SMB2_CREATE_SD_BUFFER context\n");
e2f34481 2333 sd_buf = (struct create_sd_buf_req *)context;
ef24c962
HL
2334 rc = set_info_sec(work->conn, work->tcon,
2335 path, &sd_buf->ntsd,
070fb21e 2336 le32_to_cpu(sd_buf->ccontext.DataLength), true);
e2f34481
NJ
2337 }
2338
2339 return rc;
2340}
2341
3d47e546
NJ
2342static void ksmbd_acls_fattr(struct smb_fattr *fattr, struct inode *inode)
2343{
2344 fattr->cf_uid = inode->i_uid;
2345 fattr->cf_gid = inode->i_gid;
2346 fattr->cf_mode = inode->i_mode;
2347 fattr->cf_dacls = NULL;
2348
67d1c432 2349 fattr->cf_acls = get_acl(inode, ACL_TYPE_ACCESS);
3d47e546 2350 if (S_ISDIR(inode->i_mode))
67d1c432 2351 fattr->cf_dacls = get_acl(inode, ACL_TYPE_DEFAULT);
3d47e546
NJ
2352}
2353
e2f34481
NJ
2354/**
2355 * smb2_open() - handler for smb file open request
2356 * @work: smb work containing request buffer
2357 *
2358 * Return: 0 on success, otherwise error
2359 */
2360int smb2_open(struct ksmbd_work *work)
2361{
2362 struct ksmbd_conn *conn = work->conn;
2363 struct ksmbd_session *sess = work->sess;
2364 struct ksmbd_tree_connect *tcon = work->tcon;
2365 struct smb2_create_req *req;
2366 struct smb2_create_rsp *rsp, *rsp_org;
2367 struct path path;
2368 struct ksmbd_share_config *share = tcon->share_conf;
2369 struct ksmbd_file *fp = NULL;
2370 struct file *filp = NULL;
465d7204 2371 struct user_namespace *user_ns = NULL;
e2f34481
NJ
2372 struct kstat stat;
2373 struct create_context *context;
2374 struct lease_ctx_info *lc = NULL;
2375 struct create_ea_buf_req *ea_buf = NULL;
2376 struct oplock_info *opinfo;
2377 __le32 *next_ptr = NULL;
6c5e36d1 2378 int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0;
e2f34481
NJ
2379 int rc = 0, len = 0;
2380 int contxt_cnt = 0, query_disk_id = 0;
2381 int maximal_access_ctxt = 0, posix_ctxt = 0;
2382 int s_type = 0;
2383 int next_off = 0;
2384 char *name = NULL;
2385 char *stream_name = NULL;
2386 bool file_present = false, created = false, already_permitted = false;
e2f34481
NJ
2387 int share_ret, need_truncate = 0;
2388 u64 time;
2389 umode_t posix_mode = 0;
2390 __le32 daccess, maximal_access = 0;
2391
e5066499 2392 rsp_org = work->response_buf;
e2f34481
NJ
2393 WORK_BUFFERS(work, req, rsp);
2394
2395 if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off &&
64b39f4a 2396 (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)) {
e2f34481
NJ
2397 ksmbd_debug(SMB, "invalid flag in chained command\n");
2398 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
2399 smb2_set_err_rsp(work);
2400 return -EINVAL;
2401 }
2402
2403 if (test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
2404 ksmbd_debug(SMB, "IPC pipe create request\n");
2405 return create_smb2_pipe(work);
2406 }
2407
2408 if (req->NameLength) {
2409 if ((req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
64b39f4a 2410 *(char *)req->Buffer == '\\') {
bde1694a 2411 pr_err("not allow directory name included leading slash\n");
e2f34481
NJ
2412 rc = -EINVAL;
2413 goto err_out1;
2414 }
2415
2416 name = smb2_get_name(share,
2417 req->Buffer,
2418 le16_to_cpu(req->NameLength),
2419 work->conn->local_nls);
2420 if (IS_ERR(name)) {
2421 rc = PTR_ERR(name);
2422 if (rc != -ENOMEM)
2423 rc = -ENOENT;
2424 goto err_out1;
2425 }
2426
2427 ksmbd_debug(SMB, "converted name = %s\n", name);
2428 if (strchr(name, ':')) {
2429 if (!test_share_config_flag(work->tcon->share_conf,
64b39f4a 2430 KSMBD_SHARE_FLAG_STREAMS)) {
e2f34481
NJ
2431 rc = -EBADF;
2432 goto err_out1;
2433 }
2434 rc = parse_stream_name(name, &stream_name, &s_type);
2435 if (rc < 0)
2436 goto err_out1;
2437 }
2438
2439 rc = ksmbd_validate_filename(name);
2440 if (rc < 0)
2441 goto err_out1;
2442
2443 if (ksmbd_share_veto_filename(share, name)) {
2444 rc = -ENOENT;
2445 ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n",
070fb21e 2446 name);
e2f34481
NJ
2447 goto err_out1;
2448 }
2449 } else {
2450 len = strlen(share->path);
2451 ksmbd_debug(SMB, "share path len %d\n", len);
2452 name = kmalloc(len + 1, GFP_KERNEL);
2453 if (!name) {
2454 rsp->hdr.Status = STATUS_NO_MEMORY;
2455 rc = -ENOMEM;
2456 goto err_out1;
2457 }
2458
2459 memcpy(name, share->path, len);
2460 *(name + len) = '\0';
2461 }
2462
2463 req_op_level = req->RequestedOplockLevel;
73f9dad5 2464 if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
e2f34481 2465 lc = parse_lease_state(req);
e2f34481 2466
64b39f4a 2467 if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE_LE)) {
bde1694a
NJ
2468 pr_err("Invalid impersonationlevel : 0x%x\n",
2469 le32_to_cpu(req->ImpersonationLevel));
e2f34481
NJ
2470 rc = -EIO;
2471 rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL;
2472 goto err_out1;
2473 }
2474
2475 if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK)) {
bde1694a
NJ
2476 pr_err("Invalid create options : 0x%x\n",
2477 le32_to_cpu(req->CreateOptions));
e2f34481
NJ
2478 rc = -EINVAL;
2479 goto err_out1;
2480 } else {
e2f34481 2481 if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE &&
64b39f4a 2482 req->CreateOptions & FILE_RANDOM_ACCESS_LE)
e2f34481
NJ
2483 req->CreateOptions = ~(FILE_SEQUENTIAL_ONLY_LE);
2484
070fb21e
NJ
2485 if (req->CreateOptions &
2486 (FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION |
2487 FILE_RESERVE_OPFILTER_LE)) {
e2f34481
NJ
2488 rc = -EOPNOTSUPP;
2489 goto err_out1;
2490 }
2491
2492 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
2493 if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) {
2494 rc = -EINVAL;
2495 goto err_out1;
64b39f4a 2496 } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) {
e2f34481 2497 req->CreateOptions = ~(FILE_NO_COMPRESSION_LE);
64b39f4a 2498 }
e2f34481
NJ
2499 }
2500 }
2501
2502 if (le32_to_cpu(req->CreateDisposition) >
070fb21e 2503 le32_to_cpu(FILE_OVERWRITE_IF_LE)) {
bde1694a
NJ
2504 pr_err("Invalid create disposition : 0x%x\n",
2505 le32_to_cpu(req->CreateDisposition));
e2f34481
NJ
2506 rc = -EINVAL;
2507 goto err_out1;
2508 }
2509
2510 if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) {
bde1694a
NJ
2511 pr_err("Invalid desired access : 0x%x\n",
2512 le32_to_cpu(req->DesiredAccess));
e2f34481
NJ
2513 rc = -EACCES;
2514 goto err_out1;
2515 }
2516
64b39f4a 2517 if (req->FileAttributes && !(req->FileAttributes & ATTR_MASK_LE)) {
bde1694a
NJ
2518 pr_err("Invalid file attribute : 0x%x\n",
2519 le32_to_cpu(req->FileAttributes));
e2f34481
NJ
2520 rc = -EINVAL;
2521 goto err_out1;
2522 }
2523
2524 if (req->CreateContextsOffset) {
2525 /* Parse non-durable handle create contexts */
2526 context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER);
2527 if (IS_ERR(context)) {
2528 rc = check_context_err(context, SMB2_CREATE_EA_BUFFER);
2529 if (rc < 0)
2530 goto err_out1;
2531 } else {
2532 ea_buf = (struct create_ea_buf_req *)context;
2533 if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) {
2534 rsp->hdr.Status = STATUS_ACCESS_DENIED;
2535 rc = -EACCES;
2536 goto err_out1;
2537 }
2538 }
2539
2540 context = smb2_find_context_vals(req,
070fb21e 2541 SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST);
e2f34481
NJ
2542 if (IS_ERR(context)) {
2543 rc = check_context_err(context,
070fb21e 2544 SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST);
e2f34481
NJ
2545 if (rc < 0)
2546 goto err_out1;
2547 } else {
2548 ksmbd_debug(SMB,
070fb21e 2549 "get query maximal access context\n");
e2f34481
NJ
2550 maximal_access_ctxt = 1;
2551 }
2552
2553 context = smb2_find_context_vals(req,
070fb21e 2554 SMB2_CREATE_TIMEWARP_REQUEST);
e2f34481
NJ
2555 if (IS_ERR(context)) {
2556 rc = check_context_err(context,
070fb21e 2557 SMB2_CREATE_TIMEWARP_REQUEST);
e2f34481
NJ
2558 if (rc < 0)
2559 goto err_out1;
2560 } else {
2561 ksmbd_debug(SMB, "get timewarp context\n");
2562 rc = -EBADF;
2563 goto err_out1;
2564 }
2565
2566 if (tcon->posix_extensions) {
2567 context = smb2_find_context_vals(req,
070fb21e 2568 SMB2_CREATE_TAG_POSIX);
e2f34481
NJ
2569 if (IS_ERR(context)) {
2570 rc = check_context_err(context,
070fb21e 2571 SMB2_CREATE_TAG_POSIX);
e2f34481
NJ
2572 if (rc < 0)
2573 goto err_out1;
2574 } else {
2575 struct create_posix *posix =
2576 (struct create_posix *)context;
2577 ksmbd_debug(SMB, "get posix context\n");
2578
2579 posix_mode = le32_to_cpu(posix->Mode);
2580 posix_ctxt = 1;
2581 }
2582 }
2583 }
2584
2585 if (ksmbd_override_fsids(work)) {
2586 rc = -ENOMEM;
2587 goto err_out1;
2588 }
2589
2590 if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) {
2591 /*
2592 * On delete request, instead of following up, need to
2593 * look the current entity
2594 */
2595 rc = ksmbd_vfs_kern_path(name, 0, &path, 1);
2596 if (!rc) {
2597 /*
2598 * If file exists with under flags, return access
2599 * denied error.
2600 */
2601 if (req->CreateDisposition == FILE_OVERWRITE_IF_LE ||
64b39f4a 2602 req->CreateDisposition == FILE_OPEN_IF_LE) {
e2f34481
NJ
2603 rc = -EACCES;
2604 path_put(&path);
2605 goto err_out;
2606 }
2607
64b39f4a 2608 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
e2f34481 2609 ksmbd_debug(SMB,
070fb21e 2610 "User does not have write permission\n");
e2f34481
NJ
2611 rc = -EACCES;
2612 path_put(&path);
2613 goto err_out;
2614 }
2615 }
2616 } else {
2617 if (test_share_config_flag(work->tcon->share_conf,
64b39f4a 2618 KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS)) {
e2f34481
NJ
2619 /*
2620 * Use LOOKUP_FOLLOW to follow the path of
2621 * symlink in path buildup
2622 */
2623 rc = ksmbd_vfs_kern_path(name, LOOKUP_FOLLOW, &path, 1);
2624 if (rc) { /* Case for broken link ?*/
2625 rc = ksmbd_vfs_kern_path(name, 0, &path, 1);
2626 }
2627 } else {
2628 rc = ksmbd_vfs_kern_path(name, 0, &path, 1);
2629 if (!rc && d_is_symlink(path.dentry)) {
2630 rc = -EACCES;
2631 path_put(&path);
2632 goto err_out;
2633 }
2634 }
2635 }
2636
2637 if (rc) {
2638 if (rc == -EACCES) {
2639 ksmbd_debug(SMB,
070fb21e 2640 "User does not have right permission\n");
e2f34481
NJ
2641 goto err_out;
2642 }
2643 ksmbd_debug(SMB, "can not get linux path for %s, rc = %d\n",
070fb21e 2644 name, rc);
e2f34481
NJ
2645 rc = 0;
2646 } else {
2647 file_present = true;
465d7204
HL
2648 user_ns = mnt_user_ns(path.mnt);
2649 generic_fillattr(user_ns, d_inode(path.dentry), &stat);
e2f34481
NJ
2650 }
2651 if (stream_name) {
2652 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
2653 if (s_type == DATA_STREAM) {
2654 rc = -EIO;
2655 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
2656 }
2657 } else {
2658 if (S_ISDIR(stat.mode) && s_type == DATA_STREAM) {
2659 rc = -EIO;
2660 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
2661 }
2662 }
2663
2664 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE &&
64b39f4a 2665 req->FileAttributes & ATTR_NORMAL_LE) {
e2f34481
NJ
2666 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
2667 rc = -EIO;
2668 }
2669
2670 if (rc < 0)
2671 goto err_out;
2672 }
2673
64b39f4a
NJ
2674 if (file_present && req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE &&
2675 S_ISDIR(stat.mode) && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
e2f34481 2676 ksmbd_debug(SMB, "open() argument is a directory: %s, %x\n",
070fb21e 2677 name, req->CreateOptions);
e2f34481
NJ
2678 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
2679 rc = -EIO;
2680 goto err_out;
2681 }
2682
2683 if (file_present && (req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
64b39f4a
NJ
2684 !(req->CreateDisposition == FILE_CREATE_LE) &&
2685 !S_ISDIR(stat.mode)) {
e2f34481
NJ
2686 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
2687 rc = -EIO;
2688 goto err_out;
2689 }
2690
2691 if (!stream_name && file_present &&
64b39f4a 2692 req->CreateDisposition == FILE_CREATE_LE) {
e2f34481
NJ
2693 rc = -EEXIST;
2694 goto err_out;
2695 }
2696
e2f34481
NJ
2697 daccess = smb_map_generic_desired_access(req->DesiredAccess);
2698
2699 if (file_present && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
ef24c962 2700 rc = smb_check_perm_dacl(conn, &path, &daccess,
070fb21e 2701 sess->user->uid);
e2f34481
NJ
2702 if (rc)
2703 goto err_out;
2704 }
2705
2706 if (daccess & FILE_MAXIMAL_ACCESS_LE) {
2707 if (!file_present) {
2708 daccess = cpu_to_le32(GENERIC_ALL_FLAGS);
2709 } else {
465d7204 2710 rc = ksmbd_vfs_query_maximal_access(user_ns,
af34983e 2711 path.dentry,
e2f34481
NJ
2712 &daccess);
2713 if (rc)
2714 goto err_out;
2715 already_permitted = true;
2716 }
2717 maximal_access = daccess;
2718 }
2719
070fb21e 2720 open_flags = smb2_create_open_flags(file_present, daccess,
6c5e36d1
HL
2721 req->CreateDisposition,
2722 &may_flags);
e2f34481
NJ
2723
2724 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
2725 if (open_flags & O_CREAT) {
2726 ksmbd_debug(SMB,
070fb21e 2727 "User does not have write permission\n");
e2f34481
NJ
2728 rc = -EACCES;
2729 goto err_out;
2730 }
2731 }
2732
2733 /*create file if not present */
2734 if (!file_present) {
2735 rc = smb2_creat(work, &path, name, open_flags, posix_mode,
070fb21e 2736 req->CreateOptions & FILE_DIRECTORY_FILE_LE);
e2f34481
NJ
2737 if (rc)
2738 goto err_out;
2739
2740 created = true;
465d7204 2741 user_ns = mnt_user_ns(path.mnt);
e2f34481
NJ
2742 if (ea_buf) {
2743 rc = smb2_set_ea(&ea_buf->ea, &path);
2744 if (rc == -EOPNOTSUPP)
2745 rc = 0;
2746 else if (rc)
2747 goto err_out;
2748 }
2749 } else if (!already_permitted) {
e2f34481
NJ
2750 /* FILE_READ_ATTRIBUTE is allowed without inode_permission,
2751 * because execute(search) permission on a parent directory,
2752 * is already granted.
2753 */
64b39f4a 2754 if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) {
465d7204 2755 rc = inode_permission(user_ns,
6c5e36d1
HL
2756 d_inode(path.dentry),
2757 may_flags);
ff1d5727 2758 if (rc)
e2f34481 2759 goto err_out;
6c5e36d1
HL
2760
2761 if ((daccess & FILE_DELETE_LE) ||
2762 (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
465d7204 2763 rc = ksmbd_vfs_may_delete(user_ns,
af34983e 2764 path.dentry);
6c5e36d1
HL
2765 if (rc)
2766 goto err_out;
2767 }
e2f34481
NJ
2768 }
2769 }
2770
2771 rc = ksmbd_query_inode_status(d_inode(path.dentry->d_parent));
2772 if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) {
2773 rc = -EBUSY;
2774 goto err_out;
2775 }
2776
2777 rc = 0;
2778 filp = dentry_open(&path, open_flags, current_cred());
2779 if (IS_ERR(filp)) {
2780 rc = PTR_ERR(filp);
bde1694a 2781 pr_err("dentry open for dir failed, rc %d\n", rc);
e2f34481
NJ
2782 goto err_out;
2783 }
2784
2785 if (file_present) {
2786 if (!(open_flags & O_TRUNC))
2787 file_info = FILE_OPENED;
2788 else
2789 file_info = FILE_OVERWRITTEN;
2790
070fb21e
NJ
2791 if ((req->CreateDisposition & FILE_CREATE_MASK_LE) ==
2792 FILE_SUPERSEDE_LE)
e2f34481 2793 file_info = FILE_SUPERSEDED;
64b39f4a 2794 } else if (open_flags & O_CREAT) {
e2f34481 2795 file_info = FILE_CREATED;
64b39f4a 2796 }
e2f34481
NJ
2797
2798 ksmbd_vfs_set_fadvise(filp, req->CreateOptions);
2799
2800 /* Obtain Volatile-ID */
2801 fp = ksmbd_open_fd(work, filp);
2802 if (IS_ERR(fp)) {
2803 fput(filp);
2804 rc = PTR_ERR(fp);
2805 fp = NULL;
2806 goto err_out;
2807 }
2808
2809 /* Get Persistent-ID */
2810 ksmbd_open_durable_fd(fp);
2811 if (!HAS_FILE_ID(fp->persistent_id)) {
2812 rc = -ENOMEM;
2813 goto err_out;
2814 }
2815
2816 fp->filename = name;
2817 fp->cdoption = req->CreateDisposition;
2818 fp->daccess = daccess;
2819 fp->saccess = req->ShareAccess;
2820 fp->coption = req->CreateOptions;
2821
2822 /* Set default windows and posix acls if creating new file */
2823 if (created) {
2824 int posix_acl_rc;
fba08fa0 2825 struct inode *inode = d_inode(path.dentry);
e2f34481 2826
465d7204 2827 posix_acl_rc = ksmbd_vfs_inherit_posix_acl(user_ns,
af34983e
HL
2828 inode,
2829 d_inode(path.dentry->d_parent));
e2f34481
NJ
2830 if (posix_acl_rc)
2831 ksmbd_debug(SMB, "inherit posix acl failed : %d\n", posix_acl_rc);
2832
2833 if (test_share_config_flag(work->tcon->share_conf,
64b39f4a 2834 KSMBD_SHARE_FLAG_ACL_XATTR)) {
ef24c962 2835 rc = smb_inherit_dacl(conn, &path, sess->user->uid,
070fb21e 2836 sess->user->gid);
e2f34481
NJ
2837 }
2838
2839 if (rc) {
ef24c962 2840 rc = smb2_create_sd_buffer(work, req, &path);
e2f34481
NJ
2841 if (rc) {
2842 if (posix_acl_rc)
465d7204 2843 ksmbd_vfs_set_init_posix_acl(user_ns,
af34983e 2844 inode);
e2f34481
NJ
2845
2846 if (test_share_config_flag(work->tcon->share_conf,
64b39f4a 2847 KSMBD_SHARE_FLAG_ACL_XATTR)) {
e2f34481
NJ
2848 struct smb_fattr fattr;
2849 struct smb_ntsd *pntsd;
3d47e546 2850 int pntsd_size, ace_num = 0;
e2f34481 2851
3d47e546 2852 ksmbd_acls_fattr(&fattr, inode);
e6b1059f
MM
2853 if (fattr.cf_acls)
2854 ace_num = fattr.cf_acls->a_count;
3d47e546
NJ
2855 if (fattr.cf_dacls)
2856 ace_num += fattr.cf_dacls->a_count;
e2f34481
NJ
2857
2858 pntsd = kmalloc(sizeof(struct smb_ntsd) +
64b39f4a 2859 sizeof(struct smb_sid) * 3 +
e2f34481 2860 sizeof(struct smb_acl) +
64b39f4a 2861 sizeof(struct smb_ace) * ace_num * 2,
e2f34481
NJ
2862 GFP_KERNEL);
2863 if (!pntsd)
2864 goto err_out;
2865
465d7204 2866 rc = build_sec_desc(user_ns,
af34983e 2867 pntsd, NULL,
070fb21e 2868 OWNER_SECINFO |
af34983e
HL
2869 GROUP_SECINFO |
2870 DACL_SECINFO,
070fb21e 2871 &pntsd_size, &fattr);
e2f34481
NJ
2872 posix_acl_release(fattr.cf_acls);
2873 posix_acl_release(fattr.cf_dacls);
2874
2875 rc = ksmbd_vfs_set_sd_xattr(conn,
465d7204 2876 user_ns,
070fb21e
NJ
2877 path.dentry,
2878 pntsd,
2879 pntsd_size);
3d47e546 2880 kfree(pntsd);
e2f34481 2881 if (rc)
bde1694a
NJ
2882 pr_err("failed to store ntacl in xattr : %d\n",
2883 rc);
e2f34481
NJ
2884 }
2885 }
2886 }
2887 rc = 0;
2888 }
2889
2890 if (stream_name) {
2891 rc = smb2_set_stream_name_xattr(&path,
2892 fp,
2893 stream_name,
2894 s_type);
2895 if (rc)
2896 goto err_out;
2897 file_info = FILE_CREATED;
2898 }
2899
2900 fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE |
2901 FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE));
64b39f4a
NJ
2902 if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
2903 !fp->attrib_only && !stream_name) {
e2f34481
NJ
2904 smb_break_all_oplock(work, fp);
2905 need_truncate = 1;
2906 }
2907
2908 /* fp should be searchable through ksmbd_inode.m_fp_list
2909 * after daccess, saccess, attrib_only, and stream are
2910 * initialized.
2911 */
2912 write_lock(&fp->f_ci->m_lock);
2913 list_add(&fp->node, &fp->f_ci->m_fp_list);
2914 write_unlock(&fp->f_ci->m_lock);
2915
2916 rc = ksmbd_vfs_getattr(&path, &stat);
2917 if (rc) {
465d7204 2918 generic_fillattr(user_ns, d_inode(path.dentry), &stat);
e2f34481
NJ
2919 rc = 0;
2920 }
2921
2922 /* Check delete pending among previous fp before oplock break */
2923 if (ksmbd_inode_pending_delete(fp)) {
2924 rc = -EBUSY;
2925 goto err_out;
2926 }
2927
2928 share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
64b39f4a
NJ
2929 if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
2930 (req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
2931 !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) {
ab0b263b 2932 if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
e2f34481
NJ
2933 rc = share_ret;
2934 goto err_out;
2935 }
2936 } else {
2937 if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
2938 req_op_level = smb2_map_lease_to_oplock(lc->req_state);
2939 ksmbd_debug(SMB,
070fb21e
NJ
2940 "lease req for(%s) req oplock state 0x%x, lease state 0x%x\n",
2941 name, req_op_level, lc->req_state);
e2f34481
NJ
2942 rc = find_same_lease_key(sess, fp->f_ci, lc);
2943 if (rc)
2944 goto err_out;
2945 } else if (open_flags == O_RDONLY &&
64b39f4a
NJ
2946 (req_op_level == SMB2_OPLOCK_LEVEL_BATCH ||
2947 req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
e2f34481
NJ
2948 req_op_level = SMB2_OPLOCK_LEVEL_II;
2949
2950 rc = smb_grant_oplock(work, req_op_level,
2951 fp->persistent_id, fp,
2952 le32_to_cpu(req->hdr.Id.SyncId.TreeId),
2953 lc, share_ret);
2954 if (rc < 0)
2955 goto err_out;
2956 }
2957
2958 if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
2959 ksmbd_fd_set_delete_on_close(fp, file_info);
2960
2961 if (need_truncate) {
2962 rc = smb2_create_truncate(&path);
2963 if (rc)
2964 goto err_out;
2965 }
2966
2967 if (req->CreateContextsOffset) {
2968 struct create_alloc_size_req *az_req;
2969
070fb21e
NJ
2970 az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
2971 SMB2_CREATE_ALLOCATION_SIZE);
e2f34481
NJ
2972 if (IS_ERR(az_req)) {
2973 rc = check_context_err(az_req,
070fb21e 2974 SMB2_CREATE_ALLOCATION_SIZE);
e2f34481
NJ
2975 if (rc < 0)
2976 goto err_out;
2977 } else {
2978 loff_t alloc_size = le64_to_cpu(az_req->AllocationSize);
2979 int err;
2980
2981 ksmbd_debug(SMB,
070fb21e
NJ
2982 "request smb2 create allocate size : %llu\n",
2983 alloc_size);
e8c06191
NJ
2984 smb_break_all_levII_oplock(work, fp, 1);
2985 err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
2986 alloc_size);
e2f34481
NJ
2987 if (err < 0)
2988 ksmbd_debug(SMB,
e8c06191 2989 "vfs_fallocate is failed : %d\n",
070fb21e 2990 err);
e2f34481
NJ
2991 }
2992
64b39f4a 2993 context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID);
e2f34481 2994 if (IS_ERR(context)) {
64b39f4a 2995 rc = check_context_err(context, SMB2_CREATE_QUERY_ON_DISK_ID);
e2f34481
NJ
2996 if (rc < 0)
2997 goto err_out;
2998 } else {
2999 ksmbd_debug(SMB, "get query on disk id context\n");
3000 query_disk_id = 1;
3001 }
3002 }
3003
3004 if (stat.result_mask & STATX_BTIME)
3005 fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
3006 else
3007 fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
3008 if (req->FileAttributes || fp->f_ci->m_fattr == 0)
070fb21e
NJ
3009 fp->f_ci->m_fattr =
3010 cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
e2f34481
NJ
3011
3012 if (!created)
3013 smb2_update_xattrs(tcon, &path, fp);
3014 else
3015 smb2_new_xattrs(tcon, &path, fp);
3016
3017 memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
3018
465d7204 3019 generic_fillattr(user_ns, file_inode(fp->filp),
af34983e 3020 &stat);
e2f34481
NJ
3021
3022 rsp->StructureSize = cpu_to_le16(89);
3023 rcu_read_lock();
3024 opinfo = rcu_dereference(fp->f_opinfo);
3025 rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0;
3026 rcu_read_unlock();
3027 rsp->Reserved = 0;
3028 rsp->CreateAction = cpu_to_le32(file_info);
3029 rsp->CreationTime = cpu_to_le64(fp->create_time);
3030 time = ksmbd_UnixTimeToNT(stat.atime);
3031 rsp->LastAccessTime = cpu_to_le64(time);
3032 time = ksmbd_UnixTimeToNT(stat.mtime);
3033 rsp->LastWriteTime = cpu_to_le64(time);
3034 time = ksmbd_UnixTimeToNT(stat.ctime);
3035 rsp->ChangeTime = cpu_to_le64(time);
3036 rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 :
3037 cpu_to_le64(stat.blocks << 9);
3038 rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
3039 rsp->FileAttributes = fp->f_ci->m_fattr;
3040
3041 rsp->Reserved2 = 0;
3042
3043 rsp->PersistentFileId = cpu_to_le64(fp->persistent_id);
3044 rsp->VolatileFileId = cpu_to_le64(fp->volatile_id);
3045
3046 rsp->CreateContextsOffset = 0;
3047 rsp->CreateContextsLength = 0;
3048 inc_rfc1001_len(rsp_org, 88); /* StructureSize - 1*/
3049
3050 /* If lease is request send lease context response */
3051 if (opinfo && opinfo->is_lease) {
3052 struct create_context *lease_ccontext;
3053
3054 ksmbd_debug(SMB, "lease granted on(%s) lease state 0x%x\n",
070fb21e 3055 name, opinfo->o_lease->state);
e2f34481
NJ
3056 rsp->OplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
3057
3058 lease_ccontext = (struct create_context *)rsp->Buffer;
3059 contxt_cnt++;
3060 create_lease_buf(rsp->Buffer, opinfo->o_lease);
3061 le32_add_cpu(&rsp->CreateContextsLength,
3062 conn->vals->create_lease_size);
3063 inc_rfc1001_len(rsp_org, conn->vals->create_lease_size);
3064 next_ptr = &lease_ccontext->Next;
3065 next_off = conn->vals->create_lease_size;
3066 }
3067
e2f34481
NJ
3068 if (maximal_access_ctxt) {
3069 struct create_context *mxac_ccontext;
3070
3071 if (maximal_access == 0)
465d7204 3072 ksmbd_vfs_query_maximal_access(user_ns,
af34983e 3073 path.dentry,
e2f34481
NJ
3074 &maximal_access);
3075 mxac_ccontext = (struct create_context *)(rsp->Buffer +
3076 le32_to_cpu(rsp->CreateContextsLength));
3077 contxt_cnt++;
3078 create_mxac_rsp_buf(rsp->Buffer +
3079 le32_to_cpu(rsp->CreateContextsLength),
3080 le32_to_cpu(maximal_access));
3081 le32_add_cpu(&rsp->CreateContextsLength,
3082 conn->vals->create_mxac_size);
3083 inc_rfc1001_len(rsp_org, conn->vals->create_mxac_size);
3084 if (next_ptr)
3085 *next_ptr = cpu_to_le32(next_off);
3086 next_ptr = &mxac_ccontext->Next;
3087 next_off = conn->vals->create_mxac_size;
3088 }
3089
3090 if (query_disk_id) {
3091 struct create_context *disk_id_ccontext;
3092
3093 disk_id_ccontext = (struct create_context *)(rsp->Buffer +
3094 le32_to_cpu(rsp->CreateContextsLength));
3095 contxt_cnt++;
3096 create_disk_id_rsp_buf(rsp->Buffer +
3097 le32_to_cpu(rsp->CreateContextsLength),
3098 stat.ino, tcon->id);
3099 le32_add_cpu(&rsp->CreateContextsLength,
3100 conn->vals->create_disk_id_size);
3101 inc_rfc1001_len(rsp_org, conn->vals->create_disk_id_size);
3102 if (next_ptr)
3103 *next_ptr = cpu_to_le32(next_off);
3104 next_ptr = &disk_id_ccontext->Next;
3105 next_off = conn->vals->create_disk_id_size;
3106 }
3107
3108 if (posix_ctxt) {
e2f34481
NJ
3109 contxt_cnt++;
3110 create_posix_rsp_buf(rsp->Buffer +
3111 le32_to_cpu(rsp->CreateContextsLength),
3112 fp);
3113 le32_add_cpu(&rsp->CreateContextsLength,
3114 conn->vals->create_posix_size);
3115 inc_rfc1001_len(rsp_org, conn->vals->create_posix_size);
3116 if (next_ptr)
3117 *next_ptr = cpu_to_le32(next_off);
3118 }
3119
3120 if (contxt_cnt > 0) {
3121 rsp->CreateContextsOffset =
3122 cpu_to_le32(offsetof(struct smb2_create_rsp, Buffer)
3123 - 4);
3124 }
3125
3126err_out:
3127 if (file_present || created)
3128 path_put(&path);
3129 ksmbd_revert_fsids(work);
3130err_out1:
3131 if (rc) {
3132 if (rc == -EINVAL)
3133 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
3134 else if (rc == -EOPNOTSUPP)
3135 rsp->hdr.Status = STATUS_NOT_SUPPORTED;
ff1d5727 3136 else if (rc == -EACCES || rc == -ESTALE)
e2f34481
NJ
3137 rsp->hdr.Status = STATUS_ACCESS_DENIED;
3138 else if (rc == -ENOENT)
3139 rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID;
3140 else if (rc == -EPERM)
3141 rsp->hdr.Status = STATUS_SHARING_VIOLATION;
3142 else if (rc == -EBUSY)
3143 rsp->hdr.Status = STATUS_DELETE_PENDING;
3144 else if (rc == -EBADF)
3145 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
3146 else if (rc == -ENOEXEC)
3147 rsp->hdr.Status = STATUS_DUPLICATE_OBJECTID;
3148 else if (rc == -ENXIO)
3149 rsp->hdr.Status = STATUS_NO_SUCH_DEVICE;
3150 else if (rc == -EEXIST)
3151 rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION;
3152 else if (rc == -EMFILE)
3153 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
3154 if (!rsp->hdr.Status)
3155 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
3156
3157 if (!fp || !fp->filename)
3158 kfree(name);
3159 if (fp)
3160 ksmbd_fd_put(work, fp);
3161 smb2_set_err_rsp(work);
3162 ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
3163 }
3164
3165 kfree(lc);
3166
3167 return 0;
3168}
3169
3170static int readdir_info_level_struct_sz(int info_level)
3171{
3172 switch (info_level) {
3173 case FILE_FULL_DIRECTORY_INFORMATION:
3174 return sizeof(struct file_full_directory_info);
3175 case FILE_BOTH_DIRECTORY_INFORMATION:
3176 return sizeof(struct file_both_directory_info);
3177 case FILE_DIRECTORY_INFORMATION:
3178 return sizeof(struct file_directory_info);
3179 case FILE_NAMES_INFORMATION:
3180 return sizeof(struct file_names_info);
3181 case FILEID_FULL_DIRECTORY_INFORMATION:
3182 return sizeof(struct file_id_full_dir_info);
3183 case FILEID_BOTH_DIRECTORY_INFORMATION:
3184 return sizeof(struct file_id_both_directory_info);
3185 case SMB_FIND_FILE_POSIX_INFO:
3186 return sizeof(struct smb2_posix_info);
3187 default:
3188 return -EOPNOTSUPP;
3189 }
3190}
3191
3192static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
3193{
3194 switch (info_level) {
3195 case FILE_FULL_DIRECTORY_INFORMATION:
3196 {
3197 struct file_full_directory_info *ffdinfo;
3198
3199 ffdinfo = (struct file_full_directory_info *)d_info->rptr;
3200 d_info->rptr += le32_to_cpu(ffdinfo->NextEntryOffset);
3201 d_info->name = ffdinfo->FileName;
3202 d_info->name_len = le32_to_cpu(ffdinfo->FileNameLength);
3203 return 0;
3204 }
3205 case FILE_BOTH_DIRECTORY_INFORMATION:
3206 {
3207 struct file_both_directory_info *fbdinfo;
3208
3209 fbdinfo = (struct file_both_directory_info *)d_info->rptr;
3210 d_info->rptr += le32_to_cpu(fbdinfo->NextEntryOffset);
3211 d_info->name = fbdinfo->FileName;
3212 d_info->name_len = le32_to_cpu(fbdinfo->FileNameLength);
3213 return 0;
3214 }
3215 case FILE_DIRECTORY_INFORMATION:
3216 {
3217 struct file_directory_info *fdinfo;
3218
3219 fdinfo = (struct file_directory_info *)d_info->rptr;
3220 d_info->rptr += le32_to_cpu(fdinfo->NextEntryOffset);
3221 d_info->name = fdinfo->FileName;
3222 d_info->name_len = le32_to_cpu(fdinfo->FileNameLength);
3223 return 0;
3224 }
3225 case FILE_NAMES_INFORMATION:
3226 {
3227 struct file_names_info *fninfo;
3228
3229 fninfo = (struct file_names_info *)d_info->rptr;
3230 d_info->rptr += le32_to_cpu(fninfo->NextEntryOffset);
3231 d_info->name = fninfo->FileName;
3232 d_info->name_len = le32_to_cpu(fninfo->FileNameLength);
3233 return 0;
3234 }
3235 case FILEID_FULL_DIRECTORY_INFORMATION:
3236 {
3237 struct file_id_full_dir_info *dinfo;
3238
3239 dinfo = (struct file_id_full_dir_info *)d_info->rptr;
3240 d_info->rptr += le32_to_cpu(dinfo->NextEntryOffset);
3241 d_info->name = dinfo->FileName;
3242 d_info->name_len = le32_to_cpu(dinfo->FileNameLength);
3243 return 0;
3244 }
3245 case FILEID_BOTH_DIRECTORY_INFORMATION:
3246 {
3247 struct file_id_both_directory_info *fibdinfo;
3248
3249 fibdinfo = (struct file_id_both_directory_info *)d_info->rptr;
3250 d_info->rptr += le32_to_cpu(fibdinfo->NextEntryOffset);
3251 d_info->name = fibdinfo->FileName;
3252 d_info->name_len = le32_to_cpu(fibdinfo->FileNameLength);
3253 return 0;
3254 }
3255 case SMB_FIND_FILE_POSIX_INFO:
3256 {
3257 struct smb2_posix_info *posix_info;
3258
3259 posix_info = (struct smb2_posix_info *)d_info->rptr;
3260 d_info->rptr += le32_to_cpu(posix_info->NextEntryOffset);
3261 d_info->name = posix_info->name;
3262 d_info->name_len = le32_to_cpu(posix_info->name_len);
3263 return 0;
3264 }
3265 default:
3266 return -EINVAL;
3267 }
3268}
3269
3270/**
3271 * smb2_populate_readdir_entry() - encode directory entry in smb2 response
3272 * buffer
3273 * @conn: connection instance
3274 * @info_level: smb information level
3275 * @d_info: structure included variables for query dir
af34983e 3276 * @user_ns: user namespace
e2f34481
NJ
3277 * @ksmbd_kstat: ksmbd wrapper of dirent stat information
3278 *
3279 * if directory has many entries, find first can't read it fully.
3280 * find next might be called multiple times to read remaining dir entries
3281 *
3282 * Return: 0 on success, otherwise error
3283 */
64b39f4a 3284static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
070fb21e 3285 struct ksmbd_dir_info *d_info,
af34983e 3286 struct user_namespace *user_ns,
070fb21e 3287 struct ksmbd_kstat *ksmbd_kstat)
e2f34481
NJ
3288{
3289 int next_entry_offset = 0;
3290 char *conv_name;
3291 int conv_len;
3292 void *kstat;
3293 int struct_sz;
3294
3295 conv_name = ksmbd_convert_dir_info_name(d_info,
3296 conn->local_nls,
3297 &conv_len);
3298 if (!conv_name)
3299 return -ENOMEM;
3300
3301 /* Somehow the name has only terminating NULL bytes */
3302 if (conv_len < 0) {
3303 kfree(conv_name);
3304 return -EINVAL;
3305 }
3306
3307 struct_sz = readdir_info_level_struct_sz(info_level);
3308 next_entry_offset = ALIGN(struct_sz - 1 + conv_len,
3309 KSMBD_DIR_INFO_ALIGNMENT);
3310
3311 if (next_entry_offset > d_info->out_buf_len) {
3312 d_info->out_buf_len = 0;
3313 return -ENOSPC;
3314 }
3315
3316 kstat = d_info->wptr;
3317 if (info_level != FILE_NAMES_INFORMATION)
3318 kstat = ksmbd_vfs_init_kstat(&d_info->wptr, ksmbd_kstat);
3319
3320 switch (info_level) {
3321 case FILE_FULL_DIRECTORY_INFORMATION:
3322 {
3323 struct file_full_directory_info *ffdinfo;
3324
3325 ffdinfo = (struct file_full_directory_info *)kstat;
3326 ffdinfo->FileNameLength = cpu_to_le32(conv_len);
3327 ffdinfo->EaSize =
3328 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
3329 if (ffdinfo->EaSize)
3330 ffdinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
3331 if (d_info->hide_dot_file && d_info->name[0] == '.')
3332 ffdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
3333 memcpy(ffdinfo->FileName, conv_name, conv_len);
3334 ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3335 break;
3336 }
3337 case FILE_BOTH_DIRECTORY_INFORMATION:
3338 {
3339 struct file_both_directory_info *fbdinfo;
3340
3341 fbdinfo = (struct file_both_directory_info *)kstat;
3342 fbdinfo->FileNameLength = cpu_to_le32(conv_len);
3343 fbdinfo->EaSize =
3344 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
3345 if (fbdinfo->EaSize)
3346 fbdinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
3347 fbdinfo->ShortNameLength = 0;
3348 fbdinfo->Reserved = 0;
3349 if (d_info->hide_dot_file && d_info->name[0] == '.')
3350 fbdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
3351 memcpy(fbdinfo->FileName, conv_name, conv_len);
3352 fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3353 break;
3354 }
3355 case FILE_DIRECTORY_INFORMATION:
3356 {
3357 struct file_directory_info *fdinfo;
3358
3359 fdinfo = (struct file_directory_info *)kstat;
3360 fdinfo->FileNameLength = cpu_to_le32(conv_len);
3361 if (d_info->hide_dot_file && d_info->name[0] == '.')
3362 fdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
3363 memcpy(fdinfo->FileName, conv_name, conv_len);
3364 fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3365 break;
3366 }
3367 case FILE_NAMES_INFORMATION:
3368 {
3369 struct file_names_info *fninfo;
3370
3371 fninfo = (struct file_names_info *)kstat;
3372 fninfo->FileNameLength = cpu_to_le32(conv_len);
3373 memcpy(fninfo->FileName, conv_name, conv_len);
3374 fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3375 break;
3376 }
3377 case FILEID_FULL_DIRECTORY_INFORMATION:
3378 {
3379 struct file_id_full_dir_info *dinfo;
3380
3381 dinfo = (struct file_id_full_dir_info *)kstat;
3382 dinfo->FileNameLength = cpu_to_le32(conv_len);
3383 dinfo->EaSize =
3384 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
3385 if (dinfo->EaSize)
3386 dinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
3387 dinfo->Reserved = 0;
3388 dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
3389 if (d_info->hide_dot_file && d_info->name[0] == '.')
3390 dinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
3391 memcpy(dinfo->FileName, conv_name, conv_len);
3392 dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3393 break;
3394 }
3395 case FILEID_BOTH_DIRECTORY_INFORMATION:
3396 {
3397 struct file_id_both_directory_info *fibdinfo;
3398
3399 fibdinfo = (struct file_id_both_directory_info *)kstat;
3400 fibdinfo->FileNameLength = cpu_to_le32(conv_len);
3401 fibdinfo->EaSize =
3402 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
3403 if (fibdinfo->EaSize)
3404 fibdinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
3405 fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
3406 fibdinfo->ShortNameLength = 0;
3407 fibdinfo->Reserved = 0;
3408 fibdinfo->Reserved2 = cpu_to_le16(0);
3409 if (d_info->hide_dot_file && d_info->name[0] == '.')
3410 fibdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
3411 memcpy(fibdinfo->FileName, conv_name, conv_len);
3412 fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3413 break;
3414 }
3415 case SMB_FIND_FILE_POSIX_INFO:
3416 {
3417 struct smb2_posix_info *posix_info;
3418 u64 time;
3419
3420 posix_info = (struct smb2_posix_info *)kstat;
3421 posix_info->Ignored = 0;
3422 posix_info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time);
3423 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
3424 posix_info->ChangeTime = cpu_to_le64(time);
3425 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->atime);
3426 posix_info->LastAccessTime = cpu_to_le64(time);
3427 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->mtime);
3428 posix_info->LastWriteTime = cpu_to_le64(time);
3429 posix_info->EndOfFile = cpu_to_le64(ksmbd_kstat->kstat->size);
3430 posix_info->AllocationSize = cpu_to_le64(ksmbd_kstat->kstat->blocks << 9);
3431 posix_info->DeviceId = cpu_to_le32(ksmbd_kstat->kstat->rdev);
3432 posix_info->HardLinks = cpu_to_le32(ksmbd_kstat->kstat->nlink);
3433 posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode);
3434 posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino);
3435 posix_info->DosAttributes =
3436 S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE;
3437 if (d_info->hide_dot_file && d_info->name[0] == '.')
3438 posix_info->DosAttributes |= ATTR_HIDDEN_LE;
af34983e 3439 id_to_sid(from_kuid(user_ns, ksmbd_kstat->kstat->uid),
070fb21e 3440 SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
af34983e 3441 id_to_sid(from_kgid(user_ns, ksmbd_kstat->kstat->gid),
070fb21e 3442 SIDNFS_GROUP, (struct smb_sid *)&posix_info->SidBuffer[20]);
e2f34481
NJ
3443 memcpy(posix_info->name, conv_name, conv_len);
3444 posix_info->name_len = cpu_to_le32(conv_len);
3445 posix_info->NextEntryOffset = cpu_to_le32(next_entry_offset);
3446 break;
3447 }
3448
3449 } /* switch (info_level) */
3450
3451 d_info->last_entry_offset = d_info->data_count;
3452 d_info->data_count += next_entry_offset;
e7735c85 3453 d_info->out_buf_len -= next_entry_offset;
e2f34481
NJ
3454 d_info->wptr += next_entry_offset;
3455 kfree(conv_name);
3456
3457 ksmbd_debug(SMB,
070fb21e
NJ
3458 "info_level : %d, buf_len :%d, next_offset : %d, data_count : %d\n",
3459 info_level, d_info->out_buf_len,
3460 next_entry_offset, d_info->data_count);
e2f34481
NJ
3461
3462 return 0;
3463}
3464
3465struct smb2_query_dir_private {
3466 struct ksmbd_work *work;
3467 char *search_pattern;
3468 struct ksmbd_file *dir_fp;
3469
3470 struct ksmbd_dir_info *d_info;
3471 int info_level;
3472};
3473
3474static void lock_dir(struct ksmbd_file *dir_fp)
3475{
3476 struct dentry *dir = dir_fp->filp->f_path.dentry;
3477
3478 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
3479}
3480
3481static void unlock_dir(struct ksmbd_file *dir_fp)
3482{
3483 struct dentry *dir = dir_fp->filp->f_path.dentry;
3484
3485 inode_unlock(d_inode(dir));
3486}
3487
3488static int process_query_dir_entries(struct smb2_query_dir_private *priv)
3489{
465d7204 3490 struct user_namespace *user_ns = file_mnt_user_ns(priv->dir_fp->filp);
e2f34481
NJ
3491 struct kstat kstat;
3492 struct ksmbd_kstat ksmbd_kstat;
3493 int rc;
3494 int i;
3495
3496 for (i = 0; i < priv->d_info->num_entry; i++) {
3497 struct dentry *dent;
3498
3499 if (dentry_name(priv->d_info, priv->info_level))
3500 return -EINVAL;
3501
3502 lock_dir(priv->dir_fp);
3503 dent = lookup_one_len(priv->d_info->name,
3504 priv->dir_fp->filp->f_path.dentry,
3505 priv->d_info->name_len);
3506 unlock_dir(priv->dir_fp);
3507
3508 if (IS_ERR(dent)) {
3509 ksmbd_debug(SMB, "Cannot lookup `%s' [%ld]\n",
070fb21e
NJ
3510 priv->d_info->name,
3511 PTR_ERR(dent));
e2f34481
NJ
3512 continue;
3513 }
3514 if (unlikely(d_is_negative(dent))) {
3515 dput(dent);
3516 ksmbd_debug(SMB, "Negative dentry `%s'\n",
3517 priv->d_info->name);
3518 continue;
3519 }
3520
3521 ksmbd_kstat.kstat = &kstat;
3522 if (priv->info_level != FILE_NAMES_INFORMATION)
3523 ksmbd_vfs_fill_dentry_attrs(priv->work,
465d7204 3524 user_ns,
e2f34481
NJ
3525 dent,
3526 &ksmbd_kstat);
3527
3528 rc = smb2_populate_readdir_entry(priv->work->conn,
3529 priv->info_level,
3530 priv->d_info,
465d7204 3531 user_ns,
e2f34481
NJ
3532 &ksmbd_kstat);
3533 dput(dent);
3534 if (rc)
3535 return rc;
3536 }
3537 return 0;
3538}
3539
3540static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
070fb21e 3541 int info_level)
e2f34481
NJ
3542{
3543 int struct_sz;
3544 int conv_len;
3545 int next_entry_offset;
3546
3547 struct_sz = readdir_info_level_struct_sz(info_level);
3548 if (struct_sz == -EOPNOTSUPP)
3549 return -EOPNOTSUPP;
3550
3551 conv_len = (d_info->name_len + 1) * 2;
3552 next_entry_offset = ALIGN(struct_sz - 1 + conv_len,
3553 KSMBD_DIR_INFO_ALIGNMENT);
3554
3555 if (next_entry_offset > d_info->out_buf_len) {
3556 d_info->out_buf_len = 0;
3557 return -ENOSPC;
3558 }
3559
3560 switch (info_level) {
3561 case FILE_FULL_DIRECTORY_INFORMATION:
3562 {
3563 struct file_full_directory_info *ffdinfo;
3564
3565 ffdinfo = (struct file_full_directory_info *)d_info->wptr;
3566 memcpy(ffdinfo->FileName, d_info->name, d_info->name_len);
3567 ffdinfo->FileName[d_info->name_len] = 0x00;
3568 ffdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
3569 ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3570 break;
3571 }
3572 case FILE_BOTH_DIRECTORY_INFORMATION:
3573 {
3574 struct file_both_directory_info *fbdinfo;
3575
3576 fbdinfo = (struct file_both_directory_info *)d_info->wptr;
3577 memcpy(fbdinfo->FileName, d_info->name, d_info->name_len);
3578 fbdinfo->FileName[d_info->name_len] = 0x00;
3579 fbdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
3580 fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3581 break;
3582 }
3583 case FILE_DIRECTORY_INFORMATION:
3584 {
3585 struct file_directory_info *fdinfo;
3586
3587 fdinfo = (struct file_directory_info *)d_info->wptr;
3588 memcpy(fdinfo->FileName, d_info->name, d_info->name_len);
3589 fdinfo->FileName[d_info->name_len] = 0x00;
3590 fdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
3591 fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3592 break;
3593 }
3594 case FILE_NAMES_INFORMATION:
3595 {
3596 struct file_names_info *fninfo;
3597
3598 fninfo = (struct file_names_info *)d_info->wptr;
3599 memcpy(fninfo->FileName, d_info->name, d_info->name_len);
3600 fninfo->FileName[d_info->name_len] = 0x00;
3601 fninfo->FileNameLength = cpu_to_le32(d_info->name_len);
3602 fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3603 break;
3604 }
3605 case FILEID_FULL_DIRECTORY_INFORMATION:
3606 {
3607 struct file_id_full_dir_info *dinfo;
3608
3609 dinfo = (struct file_id_full_dir_info *)d_info->wptr;
3610 memcpy(dinfo->FileName, d_info->name, d_info->name_len);
3611 dinfo->FileName[d_info->name_len] = 0x00;
3612 dinfo->FileNameLength = cpu_to_le32(d_info->name_len);
3613 dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3614 break;
3615 }
3616 case FILEID_BOTH_DIRECTORY_INFORMATION:
3617 {
3618 struct file_id_both_directory_info *fibdinfo;
3619
3620 fibdinfo = (struct file_id_both_directory_info *)d_info->wptr;
3621 memcpy(fibdinfo->FileName, d_info->name, d_info->name_len);
3622 fibdinfo->FileName[d_info->name_len] = 0x00;
3623 fibdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
3624 fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
3625 break;
3626 }
3627 case SMB_FIND_FILE_POSIX_INFO:
3628 {
3629 struct smb2_posix_info *posix_info;
3630
3631 posix_info = (struct smb2_posix_info *)d_info->wptr;
3632 memcpy(posix_info->name, d_info->name, d_info->name_len);
3633 posix_info->name[d_info->name_len] = 0x00;
3634 posix_info->name_len = cpu_to_le32(d_info->name_len);
3635 posix_info->NextEntryOffset =
3636 cpu_to_le32(next_entry_offset);
3637 break;
3638 }
3639 } /* switch (info_level) */
3640
3641 d_info->num_entry++;
3642 d_info->out_buf_len -= next_entry_offset;
3643 d_info->wptr += next_entry_offset;
3644 return 0;
3645}
3646
64b39f4a 3647static int __query_dir(struct dir_context *ctx, const char *name, int namlen,
070fb21e 3648 loff_t offset, u64 ino, unsigned int d_type)
e2f34481
NJ
3649{
3650 struct ksmbd_readdir_data *buf;
3651 struct smb2_query_dir_private *priv;
3652 struct ksmbd_dir_info *d_info;
3653 int rc;
3654
3655 buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
3656 priv = buf->private;
3657 d_info = priv->d_info;
3658
3659 /* dot and dotdot entries are already reserved */
3660 if (!strcmp(".", name) || !strcmp("..", name))
3661 return 0;
3662 if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
3663 return 0;
b24c9335 3664 if (!match_pattern(name, namlen, priv->search_pattern))
e2f34481
NJ
3665 return 0;
3666
3667 d_info->name = name;
3668 d_info->name_len = namlen;
3669 rc = reserve_populate_dentry(d_info, priv->info_level);
3670 if (rc)
3671 return rc;
3672 if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) {
3673 d_info->out_buf_len = 0;
3674 return 0;
3675 }
3676 return 0;
3677}
3678
3679static void restart_ctx(struct dir_context *ctx)
3680{
3681 ctx->pos = 0;
3682}
3683
3684static int verify_info_level(int info_level)
3685{
3686 switch (info_level) {
3687 case FILE_FULL_DIRECTORY_INFORMATION:
3688 case FILE_BOTH_DIRECTORY_INFORMATION:
3689 case FILE_DIRECTORY_INFORMATION:
3690 case FILE_NAMES_INFORMATION:
3691 case FILEID_FULL_DIRECTORY_INFORMATION:
3692 case FILEID_BOTH_DIRECTORY_INFORMATION:
3693 case SMB_FIND_FILE_POSIX_INFO:
3694 break;
3695 default:
3696 return -EOPNOTSUPP;
3697 }
3698
3699 return 0;
3700}
3701
3702int smb2_query_dir(struct ksmbd_work *work)
3703{
3704 struct ksmbd_conn *conn = work->conn;
3705 struct smb2_query_directory_req *req;
3706 struct smb2_query_directory_rsp *rsp, *rsp_org;
3707 struct ksmbd_share_config *share = work->tcon->share_conf;
3708 struct ksmbd_file *dir_fp = NULL;
3709 struct ksmbd_dir_info d_info;
3710 int rc = 0;
3711 char *srch_ptr = NULL;
3712 unsigned char srch_flag;
3713 int buffer_sz;
3714 struct smb2_query_dir_private query_dir_private = {NULL, };
3715
e5066499 3716 rsp_org = work->response_buf;
e2f34481
NJ
3717 WORK_BUFFERS(work, req, rsp);
3718
3719 if (ksmbd_override_fsids(work)) {
3720 rsp->hdr.Status = STATUS_NO_MEMORY;
3721 smb2_set_err_rsp(work);
3722 return -ENOMEM;
3723 }
3724
3725 rc = verify_info_level(req->FileInformationClass);
3726 if (rc) {
3727 rc = -EFAULT;
3728 goto err_out2;
3729 }
3730
3731 dir_fp = ksmbd_lookup_fd_slow(work,
070fb21e
NJ
3732 le64_to_cpu(req->VolatileFileId),
3733 le64_to_cpu(req->PersistentFileId));
e2f34481
NJ
3734 if (!dir_fp) {
3735 rc = -EBADF;
3736 goto err_out2;
3737 }
3738
3739 if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) ||
af34983e
HL
3740 inode_permission(file_mnt_user_ns(dir_fp->filp),
3741 file_inode(dir_fp->filp),
070fb21e 3742 MAY_READ | MAY_EXEC)) {
493fa2fb
NJ
3743 pr_err("no right to enumerate directory (%pd)\n",
3744 dir_fp->filp->f_path.dentry);
e2f34481
NJ
3745 rc = -EACCES;
3746 goto err_out2;
3747 }
3748
3749 if (!S_ISDIR(file_inode(dir_fp->filp)->i_mode)) {
bde1694a 3750 pr_err("can't do query dir for a file\n");
e2f34481
NJ
3751 rc = -EINVAL;
3752 goto err_out2;
3753 }
3754
3755 srch_flag = req->Flags;
3756 srch_ptr = smb_strndup_from_utf16(req->Buffer,
070fb21e
NJ
3757 le16_to_cpu(req->FileNameLength), 1,
3758 conn->local_nls);
e2f34481
NJ
3759 if (IS_ERR(srch_ptr)) {
3760 ksmbd_debug(SMB, "Search Pattern not found\n");
3761 rc = -EINVAL;
3762 goto err_out2;
64b39f4a 3763 } else {
e2f34481 3764 ksmbd_debug(SMB, "Search pattern is %s\n", srch_ptr);
64b39f4a 3765 }
e2f34481
NJ
3766
3767 ksmbd_debug(SMB, "Directory name is %s\n", dir_fp->filename);
3768
3769 if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) {
3770 ksmbd_debug(SMB, "Restart directory scan\n");
3771 generic_file_llseek(dir_fp->filp, 0, SEEK_SET);
3772 restart_ctx(&dir_fp->readdir_data.ctx);
3773 }
3774
3775 memset(&d_info, 0, sizeof(struct ksmbd_dir_info));
3776 d_info.wptr = (char *)rsp->Buffer;
3777 d_info.rptr = (char *)rsp->Buffer;
64b39f4a 3778 d_info.out_buf_len = (work->response_sz - (get_rfc1002_len(rsp_org) + 4));
070fb21e
NJ
3779 d_info.out_buf_len = min_t(int, d_info.out_buf_len, le32_to_cpu(req->OutputBufferLength)) -
3780 sizeof(struct smb2_query_directory_rsp);
e2f34481
NJ
3781 d_info.flags = srch_flag;
3782
3783 /*
3784 * reserve dot and dotdot entries in head of buffer
3785 * in first response
3786 */
3787 rc = ksmbd_populate_dot_dotdot_entries(work, req->FileInformationClass,
070fb21e
NJ
3788 dir_fp, &d_info, srch_ptr,
3789 smb2_populate_readdir_entry);
e2f34481
NJ
3790 if (rc == -ENOSPC)
3791 rc = 0;
3792 else if (rc)
3793 goto err_out;
3794
3795 if (test_share_config_flag(share, KSMBD_SHARE_FLAG_HIDE_DOT_FILES))
3796 d_info.hide_dot_file = true;
3797
3798 buffer_sz = d_info.out_buf_len;
3799 d_info.rptr = d_info.wptr;
3800 query_dir_private.work = work;
3801 query_dir_private.search_pattern = srch_ptr;
3802 query_dir_private.dir_fp = dir_fp;
3803 query_dir_private.d_info = &d_info;
3804 query_dir_private.info_level = req->FileInformationClass;
3805 dir_fp->readdir_data.private = &query_dir_private;
3806 set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
3807
e8c06191 3808 rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
e2f34481
NJ
3809 if (rc == 0)
3810 restart_ctx(&dir_fp->readdir_data.ctx);
3811 if (rc == -ENOSPC)
3812 rc = 0;
3813 if (rc)
3814 goto err_out;
3815
3816 d_info.wptr = d_info.rptr;
3817 d_info.out_buf_len = buffer_sz;
3818 rc = process_query_dir_entries(&query_dir_private);
3819 if (rc)
3820 goto err_out;
3821
3822 if (!d_info.data_count && d_info.out_buf_len >= 0) {
64b39f4a 3823 if (srch_flag & SMB2_RETURN_SINGLE_ENTRY && !is_asterisk(srch_ptr)) {
e2f34481 3824 rsp->hdr.Status = STATUS_NO_SUCH_FILE;
64b39f4a 3825 } else {
e2f34481
NJ
3826 dir_fp->dot_dotdot[0] = dir_fp->dot_dotdot[1] = 0;
3827 rsp->hdr.Status = STATUS_NO_MORE_FILES;
3828 }
3829 rsp->StructureSize = cpu_to_le16(9);
3830 rsp->OutputBufferOffset = cpu_to_le16(0);
3831 rsp->OutputBufferLength = cpu_to_le32(0);
3832 rsp->Buffer[0] = 0;
3833 inc_rfc1001_len(rsp_org, 9);
3834 } else {
3835 ((struct file_directory_info *)
3836 ((char *)rsp->Buffer + d_info.last_entry_offset))
3837 ->NextEntryOffset = 0;
3838
3839 rsp->StructureSize = cpu_to_le16(9);
3840 rsp->OutputBufferOffset = cpu_to_le16(72);
3841 rsp->OutputBufferLength = cpu_to_le32(d_info.data_count);
3842 inc_rfc1001_len(rsp_org, 8 + d_info.data_count);
3843 }
3844
3845 kfree(srch_ptr);
3846 ksmbd_fd_put(work, dir_fp);
3847 ksmbd_revert_fsids(work);
3848 return 0;
3849
3850err_out:
bde1694a 3851 pr_err("error while processing smb2 query dir rc = %d\n", rc);
e2f34481
NJ
3852 kfree(srch_ptr);
3853
3854err_out2:
3855 if (rc == -EINVAL)
3856 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
3857 else if (rc == -EACCES)
3858 rsp->hdr.Status = STATUS_ACCESS_DENIED;
3859 else if (rc == -ENOENT)
3860 rsp->hdr.Status = STATUS_NO_SUCH_FILE;
3861 else if (rc == -EBADF)
3862 rsp->hdr.Status = STATUS_FILE_CLOSED;
3863 else if (rc == -ENOMEM)
3864 rsp->hdr.Status = STATUS_NO_MEMORY;
3865 else if (rc == -EFAULT)
3866 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
3867 if (!rsp->hdr.Status)
3868 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
3869
3870 smb2_set_err_rsp(work);
3871 ksmbd_fd_put(work, dir_fp);
3872 ksmbd_revert_fsids(work);
3873 return 0;
3874}
3875
3876/**
3877 * buffer_check_err() - helper function to check buffer errors
3878 * @reqOutputBufferLength: max buffer length expected in command response
3879 * @rsp: query info response buffer contains output buffer length
3880 * @infoclass_size: query info class response buffer size
3881 *
3882 * Return: 0 on success, otherwise error
3883 */
3884static int buffer_check_err(int reqOutputBufferLength,
070fb21e 3885 struct smb2_query_info_rsp *rsp, int infoclass_size)
e2f34481
NJ
3886{
3887 if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) {
3888 if (reqOutputBufferLength < infoclass_size) {
bde1694a 3889 pr_err("Invalid Buffer Size Requested\n");
e2f34481 3890 rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
64b39f4a 3891 rsp->hdr.smb2_buf_length = cpu_to_be32(sizeof(struct smb2_hdr) - 4);
e2f34481
NJ
3892 return -EINVAL;
3893 }
3894
3895 ksmbd_debug(SMB, "Buffer Overflow\n");
3896 rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
64b39f4a
NJ
3897 rsp->hdr.smb2_buf_length = cpu_to_be32(sizeof(struct smb2_hdr) - 4 +
3898 reqOutputBufferLength);
3899 rsp->OutputBufferLength = cpu_to_le32(reqOutputBufferLength);
e2f34481
NJ
3900 }
3901 return 0;
3902}
3903
3904static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp)
3905{
3906 struct smb2_file_standard_info *sinfo;
3907
3908 sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
3909
3910 sinfo->AllocationSize = cpu_to_le64(4096);
3911 sinfo->EndOfFile = cpu_to_le64(0);
3912 sinfo->NumberOfLinks = cpu_to_le32(1);
3913 sinfo->DeletePending = 1;
3914 sinfo->Directory = 0;
3915 rsp->OutputBufferLength =
3916 cpu_to_le32(sizeof(struct smb2_file_standard_info));
3917 inc_rfc1001_len(rsp, sizeof(struct smb2_file_standard_info));
3918}
3919
070fb21e 3920static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num)
e2f34481
NJ
3921{
3922 struct smb2_file_internal_info *file_info;
3923
3924 file_info = (struct smb2_file_internal_info *)rsp->Buffer;
3925
3926 /* any unique number */
3927 file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63));
3928 rsp->OutputBufferLength =
3929 cpu_to_le32(sizeof(struct smb2_file_internal_info));
3930 inc_rfc1001_len(rsp, sizeof(struct smb2_file_internal_info));
3931}
3932
e2f34481 3933static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
070fb21e
NJ
3934 struct smb2_query_info_req *req,
3935 struct smb2_query_info_rsp *rsp)
e2f34481 3936{
64b39f4a 3937 u64 id;
e2f34481
NJ
3938 int rc;
3939
3940 /*
3941 * Windows can sometime send query file info request on
3942 * pipe without opening it, checking error condition here
3943 */
3944 id = le64_to_cpu(req->VolatileFileId);
3945 if (!ksmbd_session_rpc_method(sess, id))
3946 return -ENOENT;
3947
3948 ksmbd_debug(SMB, "FileInfoClass %u, FileId 0x%llx\n",
070fb21e 3949 req->FileInfoClass, le64_to_cpu(req->VolatileFileId));
e2f34481
NJ
3950
3951 switch (req->FileInfoClass) {
3952 case FILE_STANDARD_INFORMATION:
3953 get_standard_info_pipe(rsp);
3954 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
070fb21e 3955 rsp, FILE_STANDARD_INFORMATION_SIZE);
e2f34481
NJ
3956 break;
3957 case FILE_INTERNAL_INFORMATION:
3958 get_internal_info_pipe(rsp, id);
3959 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
070fb21e 3960 rsp, FILE_INTERNAL_INFORMATION_SIZE);
e2f34481
NJ
3961 break;
3962 default:
3963 ksmbd_debug(SMB, "smb2_info_file_pipe for %u not supported\n",
070fb21e 3964 req->FileInfoClass);
e2f34481
NJ
3965 rc = -EOPNOTSUPP;
3966 }
3967 return rc;
3968}
3969
3970/**
3971 * smb2_get_ea() - handler for smb2 get extended attribute command
3972 * @work: smb work containing query info command buffer
95fa1ce9
HL
3973 * @fp: ksmbd_file pointer
3974 * @req: get extended attribute request
3975 * @rsp: response buffer pointer
3976 * @rsp_org: base response buffer pointer in case of chained response
e2f34481
NJ
3977 *
3978 * Return: 0 on success, otherwise error
3979 */
64b39f4a 3980static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e
NJ
3981 struct smb2_query_info_req *req,
3982 struct smb2_query_info_rsp *rsp, void *rsp_org)
e2f34481
NJ
3983{
3984 struct smb2_ea_info *eainfo, *prev_eainfo;
3985 char *name, *ptr, *xattr_list = NULL, *buf;
3986 int rc, name_len, value_len, xattr_list_len, idx;
3987 ssize_t buf_free_len, alignment_bytes, next_offset, rsp_data_cnt = 0;
3988 struct smb2_ea_info_req *ea_req = NULL;
3989 struct path *path;
465d7204 3990 struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
e2f34481
NJ
3991
3992 if (!(fp->daccess & FILE_READ_EA_LE)) {
bde1694a
NJ
3993 pr_err("Not permitted to read ext attr : 0x%x\n",
3994 fp->daccess);
e2f34481
NJ
3995 return -EACCES;
3996 }
3997
3998 path = &fp->filp->f_path;
3999 /* single EA entry is requested with given user.* name */
64b39f4a 4000 if (req->InputBufferLength) {
e2f34481 4001 ea_req = (struct smb2_ea_info_req *)req->Buffer;
64b39f4a 4002 } else {
e2f34481
NJ
4003 /* need to send all EAs, if no specific EA is requested*/
4004 if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY)
4005 ksmbd_debug(SMB,
070fb21e
NJ
4006 "All EAs are requested but need to send single EA entry in rsp flags 0x%x\n",
4007 le32_to_cpu(req->Flags));
e2f34481
NJ
4008 }
4009
4010 buf_free_len = work->response_sz -
4011 (get_rfc1002_len(rsp_org) + 4) -
4012 sizeof(struct smb2_query_info_rsp);
4013
4014 if (le32_to_cpu(req->OutputBufferLength) < buf_free_len)
4015 buf_free_len = le32_to_cpu(req->OutputBufferLength);
4016
4017 rc = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
4018 if (rc < 0) {
4019 rsp->hdr.Status = STATUS_INVALID_HANDLE;
4020 goto out;
4021 } else if (!rc) { /* there is no EA in the file */
4022 ksmbd_debug(SMB, "no ea data in the file\n");
4023 goto done;
4024 }
4025 xattr_list_len = rc;
4026
4027 ptr = (char *)rsp->Buffer;
4028 eainfo = (struct smb2_ea_info *)ptr;
4029 prev_eainfo = eainfo;
4030 idx = 0;
4031
4032 while (idx < xattr_list_len) {
4033 name = xattr_list + idx;
4034 name_len = strlen(name);
4035
4036 ksmbd_debug(SMB, "%s, len %d\n", name, name_len);
4037 idx += name_len + 1;
4038
4039 /*
4040 * CIFS does not support EA other than user.* namespace,
4041 * still keep the framework generic, to list other attrs
4042 * in future.
4043 */
4044 if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
4045 continue;
4046
4047 if (!strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
64b39f4a 4048 STREAM_PREFIX_LEN))
e2f34481
NJ
4049 continue;
4050
4051 if (req->InputBufferLength &&
64b39f4a
NJ
4052 strncmp(&name[XATTR_USER_PREFIX_LEN], ea_req->name,
4053 ea_req->EaNameLength))
e2f34481
NJ
4054 continue;
4055
4056 if (!strncmp(&name[XATTR_USER_PREFIX_LEN],
64b39f4a 4057 DOS_ATTRIBUTE_PREFIX, DOS_ATTRIBUTE_PREFIX_LEN))
e2f34481
NJ
4058 continue;
4059
4060 if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
4061 name_len -= XATTR_USER_PREFIX_LEN;
4062
4063 ptr = (char *)(&eainfo->name + name_len + 1);
4064 buf_free_len -= (offsetof(struct smb2_ea_info, name) +
4065 name_len + 1);
4066 /* bailout if xattr can't fit in buf_free_len */
465d7204
HL
4067 value_len = ksmbd_vfs_getxattr(user_ns, path->dentry,
4068 name, &buf);
e2f34481
NJ
4069 if (value_len <= 0) {
4070 rc = -ENOENT;
4071 rsp->hdr.Status = STATUS_INVALID_HANDLE;
4072 goto out;
4073 }
4074
4075 buf_free_len -= value_len;
4076 if (buf_free_len < 0) {
79f6b11a 4077 kfree(buf);
e2f34481
NJ
4078 break;
4079 }
4080
4081 memcpy(ptr, buf, value_len);
79f6b11a 4082 kfree(buf);
e2f34481
NJ
4083
4084 ptr += value_len;
4085 eainfo->Flags = 0;
4086 eainfo->EaNameLength = name_len;
4087
64b39f4a 4088 if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
e2f34481 4089 memcpy(eainfo->name, &name[XATTR_USER_PREFIX_LEN],
070fb21e 4090 name_len);
e2f34481
NJ
4091 else
4092 memcpy(eainfo->name, name, name_len);
4093
4094 eainfo->name[name_len] = '\0';
4095 eainfo->EaValueLength = cpu_to_le16(value_len);
4096 next_offset = offsetof(struct smb2_ea_info, name) +
4097 name_len + 1 + value_len;
4098
4099 /* align next xattr entry at 4 byte bundary */
4100 alignment_bytes = ((next_offset + 3) & ~3) - next_offset;
4101 if (alignment_bytes) {
4102 memset(ptr, '\0', alignment_bytes);
4103 ptr += alignment_bytes;
4104 next_offset += alignment_bytes;
4105 buf_free_len -= alignment_bytes;
4106 }
4107 eainfo->NextEntryOffset = cpu_to_le32(next_offset);
4108 prev_eainfo = eainfo;
4109 eainfo = (struct smb2_ea_info *)ptr;
4110 rsp_data_cnt += next_offset;
4111
4112 if (req->InputBufferLength) {
4113 ksmbd_debug(SMB, "single entry requested\n");
4114 break;
4115 }
4116 }
4117
4118 /* no more ea entries */
4119 prev_eainfo->NextEntryOffset = 0;
4120done:
4121 rc = 0;
4122 if (rsp_data_cnt == 0)
4123 rsp->hdr.Status = STATUS_NO_EAS_ON_FILE;
4124 rsp->OutputBufferLength = cpu_to_le32(rsp_data_cnt);
4125 inc_rfc1001_len(rsp_org, rsp_data_cnt);
4126out:
79f6b11a 4127 kvfree(xattr_list);
e2f34481
NJ
4128 return rc;
4129}
4130
4131static void get_file_access_info(struct smb2_query_info_rsp *rsp,
070fb21e 4132 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4133{
4134 struct smb2_file_access_info *file_info;
4135
4136 file_info = (struct smb2_file_access_info *)rsp->Buffer;
4137 file_info->AccessFlags = fp->daccess;
4138 rsp->OutputBufferLength =
4139 cpu_to_le32(sizeof(struct smb2_file_access_info));
4140 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_access_info));
4141}
4142
4143static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
070fb21e 4144 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4145{
4146 struct smb2_file_all_info *basic_info;
4147 struct kstat stat;
4148 u64 time;
4149
4150 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
bde1694a
NJ
4151 pr_err("no right to read the attributes : 0x%x\n",
4152 fp->daccess);
e2f34481
NJ
4153 return -EACCES;
4154 }
4155
4156 basic_info = (struct smb2_file_all_info *)rsp->Buffer;
af34983e
HL
4157 generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
4158 &stat);
e2f34481
NJ
4159 basic_info->CreationTime = cpu_to_le64(fp->create_time);
4160 time = ksmbd_UnixTimeToNT(stat.atime);
4161 basic_info->LastAccessTime = cpu_to_le64(time);
4162 time = ksmbd_UnixTimeToNT(stat.mtime);
4163 basic_info->LastWriteTime = cpu_to_le64(time);
4164 time = ksmbd_UnixTimeToNT(stat.ctime);
4165 basic_info->ChangeTime = cpu_to_le64(time);
4166 basic_info->Attributes = fp->f_ci->m_fattr;
4167 basic_info->Pad1 = 0;
4168 rsp->OutputBufferLength =
64b39f4a 4169 cpu_to_le32(offsetof(struct smb2_file_all_info, AllocationSize));
e2f34481
NJ
4170 inc_rfc1001_len(rsp_org, offsetof(struct smb2_file_all_info,
4171 AllocationSize));
4172 return 0;
4173}
4174
4175static unsigned long long get_allocation_size(struct inode *inode,
070fb21e 4176 struct kstat *stat)
e2f34481
NJ
4177{
4178 unsigned long long alloc_size = 0;
4179
4180 if (!S_ISDIR(stat->mode)) {
4181 if ((inode->i_blocks << 9) <= stat->size)
4182 alloc_size = stat->size;
4183 else
4184 alloc_size = inode->i_blocks << 9;
e2f34481
NJ
4185 }
4186
4187 return alloc_size;
4188}
4189
4190static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
070fb21e 4191 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4192{
4193 struct smb2_file_standard_info *sinfo;
4194 unsigned int delete_pending;
4195 struct inode *inode;
4196 struct kstat stat;
4197
ab0b263b 4198 inode = file_inode(fp->filp);
af34983e 4199 generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
e2f34481
NJ
4200
4201 sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
4202 delete_pending = ksmbd_inode_pending_delete(fp);
4203
4204 sinfo->AllocationSize = cpu_to_le64(get_allocation_size(inode, &stat));
4205 sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
4206 sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
4207 sinfo->DeletePending = delete_pending;
4208 sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
4209 rsp->OutputBufferLength =
4210 cpu_to_le32(sizeof(struct smb2_file_standard_info));
4211 inc_rfc1001_len(rsp_org,
4212 sizeof(struct smb2_file_standard_info));
4213}
4214
4215static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
070fb21e 4216 void *rsp_org)
e2f34481
NJ
4217{
4218 struct smb2_file_alignment_info *file_info;
4219
4220 file_info = (struct smb2_file_alignment_info *)rsp->Buffer;
4221 file_info->AlignmentRequirement = 0;
4222 rsp->OutputBufferLength =
4223 cpu_to_le32(sizeof(struct smb2_file_alignment_info));
4224 inc_rfc1001_len(rsp_org,
4225 sizeof(struct smb2_file_alignment_info));
4226}
4227
4228static int get_file_all_info(struct ksmbd_work *work,
070fb21e
NJ
4229 struct smb2_query_info_rsp *rsp,
4230 struct ksmbd_file *fp,
4231 void *rsp_org)
e2f34481
NJ
4232{
4233 struct ksmbd_conn *conn = work->conn;
4234 struct smb2_file_all_info *file_info;
4235 unsigned int delete_pending;
4236 struct inode *inode;
4237 struct kstat stat;
4238 int conv_len;
4239 char *filename;
4240 u64 time;
4241
4242 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
4243 ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n",
070fb21e 4244 fp->daccess);
e2f34481
NJ
4245 return -EACCES;
4246 }
4247
4248 filename = convert_to_nt_pathname(fp->filename,
4249 work->tcon->share_conf->path);
4250 if (!filename)
4251 return -ENOMEM;
4252
ab0b263b 4253 inode = file_inode(fp->filp);
af34983e 4254 generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
e2f34481
NJ
4255
4256 ksmbd_debug(SMB, "filename = %s\n", filename);
4257 delete_pending = ksmbd_inode_pending_delete(fp);
4258 file_info = (struct smb2_file_all_info *)rsp->Buffer;
4259
4260 file_info->CreationTime = cpu_to_le64(fp->create_time);
4261 time = ksmbd_UnixTimeToNT(stat.atime);
4262 file_info->LastAccessTime = cpu_to_le64(time);
4263 time = ksmbd_UnixTimeToNT(stat.mtime);
4264 file_info->LastWriteTime = cpu_to_le64(time);
4265 time = ksmbd_UnixTimeToNT(stat.ctime);
4266 file_info->ChangeTime = cpu_to_le64(time);
4267 file_info->Attributes = fp->f_ci->m_fattr;
4268 file_info->Pad1 = 0;
4269 file_info->AllocationSize =
4270 cpu_to_le64(get_allocation_size(inode, &stat));
4271 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
4272 file_info->NumberOfLinks =
4273 cpu_to_le32(get_nlink(&stat) - delete_pending);
4274 file_info->DeletePending = delete_pending;
4275 file_info->Directory = S_ISDIR(stat.mode) ? 1 : 0;
4276 file_info->Pad2 = 0;
4277 file_info->IndexNumber = cpu_to_le64(stat.ino);
4278 file_info->EASize = 0;
4279 file_info->AccessFlags = fp->daccess;
4280 file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
4281 file_info->Mode = fp->coption;
4282 file_info->AlignmentRequirement = 0;
070fb21e
NJ
4283 conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename,
4284 PATH_MAX, conn->local_nls, 0);
e2f34481
NJ
4285 conv_len *= 2;
4286 file_info->FileNameLength = cpu_to_le32(conv_len);
4287 rsp->OutputBufferLength =
4288 cpu_to_le32(sizeof(struct smb2_file_all_info) + conv_len - 1);
4289 kfree(filename);
4290 inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
4291 return 0;
4292}
4293
4294static void get_file_alternate_info(struct ksmbd_work *work,
070fb21e
NJ
4295 struct smb2_query_info_rsp *rsp,
4296 struct ksmbd_file *fp,
4297 void *rsp_org)
e2f34481
NJ
4298{
4299 struct ksmbd_conn *conn = work->conn;
4300 struct smb2_file_alt_name_info *file_info;
493fa2fb 4301 struct dentry *dentry = fp->filp->f_path.dentry;
e2f34481 4302 int conv_len;
e2f34481 4303
493fa2fb 4304 spin_lock(&dentry->d_lock);
e2f34481
NJ
4305 file_info = (struct smb2_file_alt_name_info *)rsp->Buffer;
4306 conv_len = ksmbd_extract_shortname(conn,
493fa2fb 4307 dentry->d_name.name,
e2f34481 4308 file_info->FileName);
493fa2fb 4309 spin_unlock(&dentry->d_lock);
e2f34481
NJ
4310 file_info->FileNameLength = cpu_to_le32(conv_len);
4311 rsp->OutputBufferLength =
4312 cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
4313 inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
4314}
4315
4316static void get_file_stream_info(struct ksmbd_work *work,
070fb21e
NJ
4317 struct smb2_query_info_rsp *rsp,
4318 struct ksmbd_file *fp,
4319 void *rsp_org)
e2f34481
NJ
4320{
4321 struct ksmbd_conn *conn = work->conn;
4322 struct smb2_file_stream_info *file_info;
4323 char *stream_name, *xattr_list = NULL, *stream_buf;
4324 struct kstat stat;
4325 struct path *path = &fp->filp->f_path;
4326 ssize_t xattr_list_len;
4327 int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
4328
af34983e
HL
4329 generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
4330 &stat);
e2f34481
NJ
4331 file_info = (struct smb2_file_stream_info *)rsp->Buffer;
4332
4333 xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
4334 if (xattr_list_len < 0) {
4335 goto out;
4336 } else if (!xattr_list_len) {
4337 ksmbd_debug(SMB, "empty xattr in the file\n");
4338 goto out;
4339 }
4340
4341 while (idx < xattr_list_len) {
4342 stream_name = xattr_list + idx;
4343 streamlen = strlen(stream_name);
4344 idx += streamlen + 1;
4345
4346 ksmbd_debug(SMB, "%s, len %d\n", stream_name, streamlen);
4347
4348 if (strncmp(&stream_name[XATTR_USER_PREFIX_LEN],
64b39f4a 4349 STREAM_PREFIX, STREAM_PREFIX_LEN))
e2f34481
NJ
4350 continue;
4351
4352 stream_name_len = streamlen - (XATTR_USER_PREFIX_LEN +
4353 STREAM_PREFIX_LEN);
4354 streamlen = stream_name_len;
4355
4356 /* plus : size */
4357 streamlen += 1;
4358 stream_buf = kmalloc(streamlen + 1, GFP_KERNEL);
4359 if (!stream_buf)
4360 break;
4361
4362 streamlen = snprintf(stream_buf, streamlen + 1,
070fb21e 4363 ":%s", &stream_name[XATTR_NAME_STREAM_LEN]);
e2f34481 4364
070fb21e 4365 file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes];
e2f34481 4366 streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName,
070fb21e
NJ
4367 stream_buf, streamlen,
4368 conn->local_nls, 0);
e2f34481
NJ
4369 streamlen *= 2;
4370 kfree(stream_buf);
4371 file_info->StreamNameLength = cpu_to_le32(streamlen);
4372 file_info->StreamSize = cpu_to_le64(stream_name_len);
4373 file_info->StreamAllocationSize = cpu_to_le64(stream_name_len);
4374
4375 next = sizeof(struct smb2_file_stream_info) + streamlen;
4376 nbytes += next;
4377 file_info->NextEntryOffset = cpu_to_le32(next);
4378 }
4379
4380 if (nbytes) {
4381 file_info = (struct smb2_file_stream_info *)
4382 &rsp->Buffer[nbytes];
4383 streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName,
070fb21e 4384 "::$DATA", 7, conn->local_nls, 0);
e2f34481
NJ
4385 streamlen *= 2;
4386 file_info->StreamNameLength = cpu_to_le32(streamlen);
4387 file_info->StreamSize = S_ISDIR(stat.mode) ? 0 :
4388 cpu_to_le64(stat.size);
4389 file_info->StreamAllocationSize = S_ISDIR(stat.mode) ? 0 :
4390 cpu_to_le64(stat.size);
4391 nbytes += sizeof(struct smb2_file_stream_info) + streamlen;
4392 }
4393
4394 /* last entry offset should be 0 */
4395 file_info->NextEntryOffset = 0;
4396out:
79f6b11a 4397 kvfree(xattr_list);
e2f34481
NJ
4398
4399 rsp->OutputBufferLength = cpu_to_le32(nbytes);
4400 inc_rfc1001_len(rsp_org, nbytes);
4401}
4402
4403static void get_file_internal_info(struct smb2_query_info_rsp *rsp,
070fb21e 4404 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4405{
4406 struct smb2_file_internal_info *file_info;
4407 struct kstat stat;
4408
af34983e
HL
4409 generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
4410 &stat);
e2f34481
NJ
4411 file_info = (struct smb2_file_internal_info *)rsp->Buffer;
4412 file_info->IndexNumber = cpu_to_le64(stat.ino);
4413 rsp->OutputBufferLength =
4414 cpu_to_le32(sizeof(struct smb2_file_internal_info));
4415 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
4416}
4417
4418static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
070fb21e 4419 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4420{
4421 struct smb2_file_ntwrk_info *file_info;
4422 struct inode *inode;
4423 struct kstat stat;
4424 u64 time;
4425
4426 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
bde1694a
NJ
4427 pr_err("no right to read the attributes : 0x%x\n",
4428 fp->daccess);
e2f34481
NJ
4429 return -EACCES;
4430 }
4431
4432 file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
4433
ab0b263b 4434 inode = file_inode(fp->filp);
af34983e 4435 generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
e2f34481
NJ
4436
4437 file_info->CreationTime = cpu_to_le64(fp->create_time);
4438 time = ksmbd_UnixTimeToNT(stat.atime);
4439 file_info->LastAccessTime = cpu_to_le64(time);
4440 time = ksmbd_UnixTimeToNT(stat.mtime);
4441 file_info->LastWriteTime = cpu_to_le64(time);
4442 time = ksmbd_UnixTimeToNT(stat.ctime);
4443 file_info->ChangeTime = cpu_to_le64(time);
4444 file_info->Attributes = fp->f_ci->m_fattr;
4445 file_info->AllocationSize =
4446 cpu_to_le64(get_allocation_size(inode, &stat));
4447 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
4448 file_info->Reserved = cpu_to_le32(0);
4449 rsp->OutputBufferLength =
4450 cpu_to_le32(sizeof(struct smb2_file_ntwrk_info));
4451 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ntwrk_info));
4452 return 0;
4453}
4454
64b39f4a 4455static void get_file_ea_info(struct smb2_query_info_rsp *rsp, void *rsp_org)
e2f34481
NJ
4456{
4457 struct smb2_file_ea_info *file_info;
4458
4459 file_info = (struct smb2_file_ea_info *)rsp->Buffer;
4460 file_info->EASize = 0;
4461 rsp->OutputBufferLength =
4462 cpu_to_le32(sizeof(struct smb2_file_ea_info));
4463 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ea_info));
4464}
4465
4466static void get_file_position_info(struct smb2_query_info_rsp *rsp,
070fb21e 4467 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4468{
4469 struct smb2_file_pos_info *file_info;
4470
4471 file_info = (struct smb2_file_pos_info *)rsp->Buffer;
4472 file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
4473 rsp->OutputBufferLength =
4474 cpu_to_le32(sizeof(struct smb2_file_pos_info));
4475 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_pos_info));
4476}
4477
4478static void get_file_mode_info(struct smb2_query_info_rsp *rsp,
070fb21e 4479 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4480{
4481 struct smb2_file_mode_info *file_info;
4482
4483 file_info = (struct smb2_file_mode_info *)rsp->Buffer;
4484 file_info->Mode = fp->coption & FILE_MODE_INFO_MASK;
4485 rsp->OutputBufferLength =
4486 cpu_to_le32(sizeof(struct smb2_file_mode_info));
4487 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_mode_info));
4488}
4489
4490static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
070fb21e 4491 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4492{
4493 struct smb2_file_comp_info *file_info;
4494 struct kstat stat;
4495
af34983e
HL
4496 generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
4497 &stat);
e2f34481
NJ
4498
4499 file_info = (struct smb2_file_comp_info *)rsp->Buffer;
4500 file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9);
4501 file_info->CompressionFormat = COMPRESSION_FORMAT_NONE;
4502 file_info->CompressionUnitShift = 0;
4503 file_info->ChunkShift = 0;
4504 file_info->ClusterShift = 0;
4505 memset(&file_info->Reserved[0], 0, 3);
4506
4507 rsp->OutputBufferLength =
4508 cpu_to_le32(sizeof(struct smb2_file_comp_info));
4509 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_comp_info));
4510}
4511
4512static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
070fb21e 4513 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4514{
4515 struct smb2_file_attr_tag_info *file_info;
4516
4517 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
bde1694a
NJ
4518 pr_err("no right to read the attributes : 0x%x\n",
4519 fp->daccess);
e2f34481
NJ
4520 return -EACCES;
4521 }
4522
4523 file_info = (struct smb2_file_attr_tag_info *)rsp->Buffer;
4524 file_info->FileAttributes = fp->f_ci->m_fattr;
4525 file_info->ReparseTag = 0;
4526 rsp->OutputBufferLength =
4527 cpu_to_le32(sizeof(struct smb2_file_attr_tag_info));
070fb21e 4528 inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_attr_tag_info));
e2f34481
NJ
4529 return 0;
4530}
4531
4532static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
070fb21e 4533 struct ksmbd_file *fp, void *rsp_org)
e2f34481
NJ
4534{
4535 struct smb311_posix_qinfo *file_info;
ab0b263b 4536 struct inode *inode = file_inode(fp->filp);
e2f34481
NJ
4537 u64 time;
4538
4539 file_info = (struct smb311_posix_qinfo *)rsp->Buffer;
4540 file_info->CreationTime = cpu_to_le64(fp->create_time);
4541 time = ksmbd_UnixTimeToNT(inode->i_atime);
4542 file_info->LastAccessTime = cpu_to_le64(time);
4543 time = ksmbd_UnixTimeToNT(inode->i_mtime);
4544 file_info->LastWriteTime = cpu_to_le64(time);
4545 time = ksmbd_UnixTimeToNT(inode->i_ctime);
4546 file_info->ChangeTime = cpu_to_le64(time);
4547 file_info->DosAttributes = fp->f_ci->m_fattr;
4548 file_info->Inode = cpu_to_le64(inode->i_ino);
4549 file_info->EndOfFile = cpu_to_le64(inode->i_size);
4550 file_info->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
4551 file_info->HardLinks = cpu_to_le32(inode->i_nlink);
4552 file_info->Mode = cpu_to_le32(inode->i_mode);
4553 file_info->DeviceId = cpu_to_le32(inode->i_rdev);
4554 rsp->OutputBufferLength =
4555 cpu_to_le32(sizeof(struct smb311_posix_qinfo));
64b39f4a 4556 inc_rfc1001_len(rsp_org, sizeof(struct smb311_posix_qinfo));
e2f34481
NJ
4557 return 0;
4558}
4559
e2f34481 4560static int smb2_get_info_file(struct ksmbd_work *work,
070fb21e
NJ
4561 struct smb2_query_info_req *req,
4562 struct smb2_query_info_rsp *rsp, void *rsp_org)
e2f34481
NJ
4563{
4564 struct ksmbd_file *fp;
4565 int fileinfoclass = 0;
4566 int rc = 0;
4567 int file_infoclass_size;
4568 unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
4569
4570 if (test_share_config_flag(work->tcon->share_conf,
64b39f4a 4571 KSMBD_SHARE_FLAG_PIPE)) {
e2f34481
NJ
4572 /* smb2 info file called for pipe */
4573 return smb2_get_info_file_pipe(work->sess, req, rsp);
4574 }
4575
4576 if (work->next_smb2_rcv_hdr_off) {
4577 if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) {
4578 ksmbd_debug(SMB, "Compound request set FID = %u\n",
070fb21e 4579 work->compound_fid);
e2f34481
NJ
4580 id = work->compound_fid;
4581 pid = work->compound_pfid;
4582 }
4583 }
4584
4585 if (!HAS_FILE_ID(id)) {
4586 id = le64_to_cpu(req->VolatileFileId);
4587 pid = le64_to_cpu(req->PersistentFileId);
4588 }
4589
4590 fp = ksmbd_lookup_fd_slow(work, id, pid);
4591 if (!fp)
4592 return -ENOENT;
4593
4594 fileinfoclass = req->FileInfoClass;
4595
4596 switch (fileinfoclass) {
4597 case FILE_ACCESS_INFORMATION:
4598 get_file_access_info(rsp, fp, rsp_org);
4599 file_infoclass_size = FILE_ACCESS_INFORMATION_SIZE;
4600 break;
4601
4602 case FILE_BASIC_INFORMATION:
4603 rc = get_file_basic_info(rsp, fp, rsp_org);
4604 file_infoclass_size = FILE_BASIC_INFORMATION_SIZE;
4605 break;
4606
4607 case FILE_STANDARD_INFORMATION:
4608 get_file_standard_info(rsp, fp, rsp_org);
4609 file_infoclass_size = FILE_STANDARD_INFORMATION_SIZE;
4610 break;
4611
4612 case FILE_ALIGNMENT_INFORMATION:
4613 get_file_alignment_info(rsp, rsp_org);
4614 file_infoclass_size = FILE_ALIGNMENT_INFORMATION_SIZE;
4615 break;
4616
4617 case FILE_ALL_INFORMATION:
4618 rc = get_file_all_info(work, rsp, fp, rsp_org);
4619 file_infoclass_size = FILE_ALL_INFORMATION_SIZE;
4620 break;
4621
4622 case FILE_ALTERNATE_NAME_INFORMATION:
4623 get_file_alternate_info(work, rsp, fp, rsp_org);
4624 file_infoclass_size = FILE_ALTERNATE_NAME_INFORMATION_SIZE;
4625 break;
4626
4627 case FILE_STREAM_INFORMATION:
4628 get_file_stream_info(work, rsp, fp, rsp_org);
4629 file_infoclass_size = FILE_STREAM_INFORMATION_SIZE;
4630 break;
4631
4632 case FILE_INTERNAL_INFORMATION:
4633 get_file_internal_info(rsp, fp, rsp_org);
4634 file_infoclass_size = FILE_INTERNAL_INFORMATION_SIZE;
4635 break;
4636
4637 case FILE_NETWORK_OPEN_INFORMATION:
4638 rc = get_file_network_open_info(rsp, fp, rsp_org);
4639 file_infoclass_size = FILE_NETWORK_OPEN_INFORMATION_SIZE;
4640 break;
4641
4642 case FILE_EA_INFORMATION:
4643 get_file_ea_info(rsp, rsp_org);
4644 file_infoclass_size = FILE_EA_INFORMATION_SIZE;
4645 break;
4646
4647 case FILE_FULL_EA_INFORMATION:
4648 rc = smb2_get_ea(work, fp, req, rsp, rsp_org);
4649 file_infoclass_size = FILE_FULL_EA_INFORMATION_SIZE;
4650 break;
4651
4652 case FILE_POSITION_INFORMATION:
4653 get_file_position_info(rsp, fp, rsp_org);
4654 file_infoclass_size = FILE_POSITION_INFORMATION_SIZE;
4655 break;
4656
4657 case FILE_MODE_INFORMATION:
4658 get_file_mode_info(rsp, fp, rsp_org);
4659 file_infoclass_size = FILE_MODE_INFORMATION_SIZE;
4660 break;
4661
4662 case FILE_COMPRESSION_INFORMATION:
4663 get_file_compression_info(rsp, fp, rsp_org);
4664 file_infoclass_size = FILE_COMPRESSION_INFORMATION_SIZE;
4665 break;
4666
4667 case FILE_ATTRIBUTE_TAG_INFORMATION:
4668 rc = get_file_attribute_tag_info(rsp, fp, rsp_org);
4669 file_infoclass_size = FILE_ATTRIBUTE_TAG_INFORMATION_SIZE;
4670 break;
4671 case SMB_FIND_FILE_POSIX_INFO:
4672 if (!work->tcon->posix_extensions) {
bde1694a 4673 pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
e2f34481
NJ
4674 rc = -EOPNOTSUPP;
4675 } else {
4676 rc = find_file_posix_info(rsp, fp, rsp_org);
4677 file_infoclass_size = sizeof(struct smb311_posix_qinfo);
4678 }
4679 break;
4680 default:
4681 ksmbd_debug(SMB, "fileinfoclass %d not supported yet\n",
4682 fileinfoclass);
4683 rc = -EOPNOTSUPP;
4684 }
4685 if (!rc)
4686 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
4687 rsp,
4688 file_infoclass_size);
4689 ksmbd_fd_put(work, fp);
4690 return rc;
4691}
4692
e2f34481 4693static int smb2_get_info_filesystem(struct ksmbd_work *work,
070fb21e
NJ
4694 struct smb2_query_info_req *req,
4695 struct smb2_query_info_rsp *rsp, void *rsp_org)
e2f34481
NJ
4696{
4697 struct ksmbd_session *sess = work->sess;
4698 struct ksmbd_conn *conn = sess->conn;
4699 struct ksmbd_share_config *share = work->tcon->share_conf;
4700 int fsinfoclass = 0;
4701 struct kstatfs stfs;
4702 struct path path;
4703 int rc = 0, len;
4704 int fs_infoclass_size = 0;
a6a5fa77 4705 int lookup_flags = 0;
e2f34481 4706
a6a5fa77
HL
4707 if (test_share_config_flag(share, KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS))
4708 lookup_flags = LOOKUP_FOLLOW;
4709
4710 rc = ksmbd_vfs_kern_path(share->path, lookup_flags, &path, 0);
e2f34481 4711 if (rc) {
bde1694a 4712 pr_err("cannot create vfs path\n");
e2f34481
NJ
4713 return -EIO;
4714 }
4715
4716 rc = vfs_statfs(&path, &stfs);
4717 if (rc) {
bde1694a 4718 pr_err("cannot do stat of path %s\n", share->path);
e2f34481
NJ
4719 path_put(&path);
4720 return -EIO;
4721 }
4722
4723 fsinfoclass = req->FileInfoClass;
4724
4725 switch (fsinfoclass) {
4726 case FS_DEVICE_INFORMATION:
4727 {
4728 struct filesystem_device_info *info;
4729
4730 info = (struct filesystem_device_info *)rsp->Buffer;
4731
4732 info->DeviceType = cpu_to_le32(stfs.f_type);
4733 info->DeviceCharacteristics = cpu_to_le32(0x00000020);
4734 rsp->OutputBufferLength = cpu_to_le32(8);
4735 inc_rfc1001_len(rsp_org, 8);
4736 fs_infoclass_size = FS_DEVICE_INFORMATION_SIZE;
4737 break;
4738 }
4739 case FS_ATTRIBUTE_INFORMATION:
4740 {
4741 struct filesystem_attribute_info *info;
4742 size_t sz;
4743
4744 info = (struct filesystem_attribute_info *)rsp->Buffer;
4745 info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS |
4746 FILE_PERSISTENT_ACLS |
4747 FILE_UNICODE_ON_DISK |
4748 FILE_CASE_PRESERVED_NAMES |
eb817368
NJ
4749 FILE_CASE_SENSITIVE_SEARCH |
4750 FILE_SUPPORTS_BLOCK_REFCOUNTING);
e2f34481
NJ
4751
4752 info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
4753
4754 info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
4755 len = smbConvertToUTF16((__le16 *)info->FileSystemName,
4756 "NTFS", PATH_MAX, conn->local_nls, 0);
4757 len = len * 2;
4758 info->FileSystemNameLen = cpu_to_le32(len);
4759 sz = sizeof(struct filesystem_attribute_info) - 2 + len;
4760 rsp->OutputBufferLength = cpu_to_le32(sz);
4761 inc_rfc1001_len(rsp_org, sz);
4762 fs_infoclass_size = FS_ATTRIBUTE_INFORMATION_SIZE;
4763 break;
4764 }
4765 case FS_VOLUME_INFORMATION:
4766 {
4767 struct filesystem_vol_info *info;
4768 size_t sz;
4769
4770 info = (struct filesystem_vol_info *)(rsp->Buffer);
4771 info->VolumeCreationTime = 0;
4772 /* Taking dummy value of serial number*/
4773 info->SerialNumber = cpu_to_le32(0xbc3ac512);
4774 len = smbConvertToUTF16((__le16 *)info->VolumeLabel,
4775 share->name, PATH_MAX,
4776 conn->local_nls, 0);
4777 len = len * 2;
4778 info->VolumeLabelSize = cpu_to_le32(len);
4779 info->Reserved = 0;
4780 sz = sizeof(struct filesystem_vol_info) - 2 + len;
4781 rsp->OutputBufferLength = cpu_to_le32(sz);
4782 inc_rfc1001_len(rsp_org, sz);
4783 fs_infoclass_size = FS_VOLUME_INFORMATION_SIZE;
4784 break;
4785 }
4786 case FS_SIZE_INFORMATION:
4787 {
4788 struct filesystem_info *info;
e2f34481
NJ
4789
4790 info = (struct filesystem_info *)(rsp->Buffer);
e2f34481
NJ
4791 info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
4792 info->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree);
ee81cae1
NJ
4793 info->SectorsPerAllocationUnit = cpu_to_le32(1);
4794 info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
e2f34481
NJ
4795 rsp->OutputBufferLength = cpu_to_le32(24);
4796 inc_rfc1001_len(rsp_org, 24);
4797 fs_infoclass_size = FS_SIZE_INFORMATION_SIZE;
4798 break;
4799 }
4800 case FS_FULL_SIZE_INFORMATION:
4801 {
4802 struct smb2_fs_full_size_info *info;
e2f34481
NJ
4803
4804 info = (struct smb2_fs_full_size_info *)(rsp->Buffer);
e2f34481
NJ
4805 info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
4806 info->CallerAvailableAllocationUnits =
4807 cpu_to_le64(stfs.f_bavail);
4808 info->ActualAvailableAllocationUnits =
4809 cpu_to_le64(stfs.f_bfree);
ee81cae1
NJ
4810 info->SectorsPerAllocationUnit = cpu_to_le32(1);
4811 info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
e2f34481
NJ
4812 rsp->OutputBufferLength = cpu_to_le32(32);
4813 inc_rfc1001_len(rsp_org, 32);
4814 fs_infoclass_size = FS_FULL_SIZE_INFORMATION_SIZE;
4815 break;
4816 }
4817 case FS_OBJECT_ID_INFORMATION:
4818 {
4819 struct object_id_info *info;
4820
4821 info = (struct object_id_info *)(rsp->Buffer);
4822
4823 if (!user_guest(sess->user))
4824 memcpy(info->objid, user_passkey(sess->user), 16);
4825 else
4826 memset(info->objid, 0, 16);
4827
4828 info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC);
4829 info->extended_info.version = cpu_to_le32(1);
4830 info->extended_info.release = cpu_to_le32(1);
4831 info->extended_info.rel_date = 0;
64b39f4a 4832 memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0"));
e2f34481
NJ
4833 rsp->OutputBufferLength = cpu_to_le32(64);
4834 inc_rfc1001_len(rsp_org, 64);
4835 fs_infoclass_size = FS_OBJECT_ID_INFORMATION_SIZE;
4836 break;
4837 }
4838 case FS_SECTOR_SIZE_INFORMATION:
4839 {
4840 struct smb3_fs_ss_info *info;
e2f34481
NJ
4841
4842 info = (struct smb3_fs_ss_info *)(rsp->Buffer);
e2f34481 4843
131bac1e 4844 info->LogicalBytesPerSector = cpu_to_le32(stfs.f_bsize);
e2f34481 4845 info->PhysicalBytesPerSectorForAtomicity =
131bac1e
NJ
4846 cpu_to_le32(stfs.f_bsize);
4847 info->PhysicalBytesPerSectorForPerf = cpu_to_le32(stfs.f_bsize);
e2f34481 4848 info->FSEffPhysicalBytesPerSectorForAtomicity =
131bac1e 4849 cpu_to_le32(stfs.f_bsize);
e2f34481
NJ
4850 info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE |
4851 SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
4852 info->ByteOffsetForSectorAlignment = 0;
4853 info->ByteOffsetForPartitionAlignment = 0;
4854 rsp->OutputBufferLength = cpu_to_le32(28);
4855 inc_rfc1001_len(rsp_org, 28);
4856 fs_infoclass_size = FS_SECTOR_SIZE_INFORMATION_SIZE;
4857 break;
4858 }
4859 case FS_CONTROL_INFORMATION:
4860 {
4861 /*
4862 * TODO : The current implementation is based on
4863 * test result with win7(NTFS) server. It's need to
4864 * modify this to get valid Quota values
4865 * from Linux kernel
4866 */
4867 struct smb2_fs_control_info *info;
4868
4869 info = (struct smb2_fs_control_info *)(rsp->Buffer);
4870 info->FreeSpaceStartFiltering = 0;
4871 info->FreeSpaceThreshold = 0;
4872 info->FreeSpaceStopFiltering = 0;
4873 info->DefaultQuotaThreshold = cpu_to_le64(SMB2_NO_FID);
4874 info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID);
4875 info->Padding = 0;
4876 rsp->OutputBufferLength = cpu_to_le32(48);
4877 inc_rfc1001_len(rsp_org, 48);
4878 fs_infoclass_size = FS_CONTROL_INFORMATION_SIZE;
4879 break;
4880 }
4881 case FS_POSIX_INFORMATION:
4882 {
4883 struct filesystem_posix_info *info;
e2f34481
NJ
4884
4885 if (!work->tcon->posix_extensions) {
bde1694a 4886 pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
e2f34481
NJ
4887 rc = -EOPNOTSUPP;
4888 } else {
4889 info = (struct filesystem_posix_info *)(rsp->Buffer);
ee81cae1 4890 info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize);
e2f34481
NJ
4891 info->BlockSize = cpu_to_le32(stfs.f_bsize);
4892 info->TotalBlocks = cpu_to_le64(stfs.f_blocks);
4893 info->BlocksAvail = cpu_to_le64(stfs.f_bfree);
4894 info->UserBlocksAvail = cpu_to_le64(stfs.f_bavail);
4895 info->TotalFileNodes = cpu_to_le64(stfs.f_files);
4896 info->FreeFileNodes = cpu_to_le64(stfs.f_ffree);
4897 rsp->OutputBufferLength = cpu_to_le32(56);
4898 inc_rfc1001_len(rsp_org, 56);
4899 fs_infoclass_size = FS_POSIX_INFORMATION_SIZE;
4900 }
4901 break;
4902 }
4903 default:
4904 path_put(&path);
4905 return -EOPNOTSUPP;
4906 }
4907 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
4908 rsp,
4909 fs_infoclass_size);
4910 path_put(&path);
4911 return rc;
4912}
4913
4914static int smb2_get_info_sec(struct ksmbd_work *work,
070fb21e
NJ
4915 struct smb2_query_info_req *req,
4916 struct smb2_query_info_rsp *rsp, void *rsp_org)
e2f34481
NJ
4917{
4918 struct ksmbd_file *fp;
465d7204 4919 struct user_namespace *user_ns;
e2f34481
NJ
4920 struct smb_ntsd *pntsd = (struct smb_ntsd *)rsp->Buffer, *ppntsd = NULL;
4921 struct smb_fattr fattr = {{0}};
4922 struct inode *inode;
4923 __u32 secdesclen;
4924 unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
4925 int addition_info = le32_to_cpu(req->AdditionalInformation);
4926 int rc;
4927
e294f78d
NJ
4928 if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
4929 PROTECTED_DACL_SECINFO |
4930 UNPROTECTED_DACL_SECINFO)) {
4931 pr_err("Unsupported addition info: 0x%x)\n",
4932 addition_info);
ced2b26a
SG
4933
4934 pntsd->revision = cpu_to_le16(1);
4935 pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PROTECTED);
4936 pntsd->osidoffset = 0;
4937 pntsd->gsidoffset = 0;
4938 pntsd->sacloffset = 0;
4939 pntsd->dacloffset = 0;
4940
4941 secdesclen = sizeof(struct smb_ntsd);
4942 rsp->OutputBufferLength = cpu_to_le32(secdesclen);
4943 inc_rfc1001_len(rsp_org, secdesclen);
4944
4945 return 0;
4946 }
4947
e2f34481
NJ
4948 if (work->next_smb2_rcv_hdr_off) {
4949 if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) {
4950 ksmbd_debug(SMB, "Compound request set FID = %u\n",
070fb21e 4951 work->compound_fid);
e2f34481
NJ
4952 id = work->compound_fid;
4953 pid = work->compound_pfid;
4954 }
4955 }
4956
4957 if (!HAS_FILE_ID(id)) {
4958 id = le64_to_cpu(req->VolatileFileId);
4959 pid = le64_to_cpu(req->PersistentFileId);
4960 }
4961
4962 fp = ksmbd_lookup_fd_slow(work, id, pid);
4963 if (!fp)
4964 return -ENOENT;
4965
465d7204 4966 user_ns = file_mnt_user_ns(fp->filp);
ab0b263b 4967 inode = file_inode(fp->filp);
3d47e546 4968 ksmbd_acls_fattr(&fattr, inode);
e2f34481
NJ
4969
4970 if (test_share_config_flag(work->tcon->share_conf,
64b39f4a 4971 KSMBD_SHARE_FLAG_ACL_XATTR))
465d7204 4972 ksmbd_vfs_get_sd_xattr(work->conn, user_ns,
af34983e 4973 fp->filp->f_path.dentry, &ppntsd);
e2f34481 4974
465d7204
HL
4975 rc = build_sec_desc(user_ns, pntsd, ppntsd, addition_info,
4976 &secdesclen, &fattr);
e2f34481
NJ
4977 posix_acl_release(fattr.cf_acls);
4978 posix_acl_release(fattr.cf_dacls);
4979 kfree(ppntsd);
4980 ksmbd_fd_put(work, fp);
4981 if (rc)
4982 return rc;
4983
4984 rsp->OutputBufferLength = cpu_to_le32(secdesclen);
4985 inc_rfc1001_len(rsp_org, secdesclen);
4986 return 0;
4987}
4988
4989/**
4990 * smb2_query_info() - handler for smb2 query info command
4991 * @work: smb work containing query info request buffer
4992 *
4993 * Return: 0 on success, otherwise error
4994 */
4995int smb2_query_info(struct ksmbd_work *work)
4996{
4997 struct smb2_query_info_req *req;
4998 struct smb2_query_info_rsp *rsp, *rsp_org;
4999 int rc = 0;
5000
e5066499 5001 rsp_org = work->response_buf;
e2f34481
NJ
5002 WORK_BUFFERS(work, req, rsp);
5003
5004 ksmbd_debug(SMB, "GOT query info request\n");
5005
5006 switch (req->InfoType) {
5007 case SMB2_O_INFO_FILE:
5008 ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
5009 rc = smb2_get_info_file(work, req, rsp, (void *)rsp_org);
5010 break;
5011 case SMB2_O_INFO_FILESYSTEM:
5012 ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILESYSTEM\n");
5013 rc = smb2_get_info_filesystem(work, req, rsp, (void *)rsp_org);
5014 break;
5015 case SMB2_O_INFO_SECURITY:
5016 ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
5017 rc = smb2_get_info_sec(work, req, rsp, (void *)rsp_org);
5018 break;
5019 default:
5020 ksmbd_debug(SMB, "InfoType %d not supported yet\n",
070fb21e 5021 req->InfoType);
e2f34481
NJ
5022 rc = -EOPNOTSUPP;
5023 }
5024
5025 if (rc < 0) {
5026 if (rc == -EACCES)
5027 rsp->hdr.Status = STATUS_ACCESS_DENIED;
5028 else if (rc == -ENOENT)
5029 rsp->hdr.Status = STATUS_FILE_CLOSED;
5030 else if (rc == -EIO)
5031 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
5032 else if (rc == -EOPNOTSUPP || rsp->hdr.Status == 0)
5033 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
5034 smb2_set_err_rsp(work);
5035
5036 ksmbd_debug(SMB, "error while processing smb2 query rc = %d\n",
070fb21e 5037 rc);
e2f34481
NJ
5038 return rc;
5039 }
5040 rsp->StructureSize = cpu_to_le16(9);
5041 rsp->OutputBufferOffset = cpu_to_le16(72);
5042 inc_rfc1001_len(rsp_org, 8);
5043 return 0;
5044}
5045
5046/**
5047 * smb2_close_pipe() - handler for closing IPC pipe
5048 * @work: smb work containing close request buffer
5049 *
5050 * Return: 0
5051 */
5052static noinline int smb2_close_pipe(struct ksmbd_work *work)
5053{
64b39f4a 5054 u64 id;
e5066499
NJ
5055 struct smb2_close_req *req = work->request_buf;
5056 struct smb2_close_rsp *rsp = work->response_buf;
e2f34481
NJ
5057
5058 id = le64_to_cpu(req->VolatileFileId);
5059 ksmbd_session_rpc_close(work->sess, id);
5060
5061 rsp->StructureSize = cpu_to_le16(60);
5062 rsp->Flags = 0;
5063 rsp->Reserved = 0;
5064 rsp->CreationTime = 0;
5065 rsp->LastAccessTime = 0;
5066 rsp->LastWriteTime = 0;
5067 rsp->ChangeTime = 0;
5068 rsp->AllocationSize = 0;
5069 rsp->EndOfFile = 0;
5070 rsp->Attributes = 0;
5071 inc_rfc1001_len(rsp, 60);
5072 return 0;
5073}
5074
5075/**
5076 * smb2_close() - handler for smb2 close file command
5077 * @work: smb work containing close request buffer
5078 *
5079 * Return: 0
5080 */
5081int smb2_close(struct ksmbd_work *work)
5082{
5083 unsigned int volatile_id = KSMBD_NO_FID;
64b39f4a 5084 u64 sess_id;
e2f34481
NJ
5085 struct smb2_close_req *req;
5086 struct smb2_close_rsp *rsp;
5087 struct smb2_close_rsp *rsp_org;
5088 struct ksmbd_conn *conn = work->conn;
5089 struct ksmbd_file *fp;
5090 struct inode *inode;
5091 u64 time;
5092 int err = 0;
5093
e5066499 5094 rsp_org = work->response_buf;
e2f34481
NJ
5095 WORK_BUFFERS(work, req, rsp);
5096
5097 if (test_share_config_flag(work->tcon->share_conf,
5098 KSMBD_SHARE_FLAG_PIPE)) {
5099 ksmbd_debug(SMB, "IPC pipe close request\n");
5100 return smb2_close_pipe(work);
5101 }
5102
5103 sess_id = le64_to_cpu(req->hdr.SessionId);
5104 if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)
5105 sess_id = work->compound_sid;
5106
5107 work->compound_sid = 0;
64b39f4a 5108 if (check_session_id(conn, sess_id)) {
e2f34481 5109 work->compound_sid = sess_id;
64b39f4a 5110 } else {
e2f34481
NJ
5111 rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
5112 if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)
5113 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
5114 err = -EBADF;
5115 goto out;
5116 }
5117
5118 if (work->next_smb2_rcv_hdr_off &&
64b39f4a 5119 !HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) {
e2f34481
NJ
5120 if (!HAS_FILE_ID(work->compound_fid)) {
5121 /* file already closed, return FILE_CLOSED */
5122 ksmbd_debug(SMB, "file already closed\n");
5123 rsp->hdr.Status = STATUS_FILE_CLOSED;
5124 err = -EBADF;
5125 goto out;
5126 } else {
5127 ksmbd_debug(SMB, "Compound request set FID = %u:%u\n",
070fb21e
NJ
5128 work->compound_fid,
5129 work->compound_pfid);
e2f34481
NJ
5130 volatile_id = work->compound_fid;
5131
5132 /* file closed, stored id is not valid anymore */
5133 work->compound_fid = KSMBD_NO_FID;
5134 work->compound_pfid = KSMBD_NO_FID;
5135 }
5136 } else {
5137 volatile_id = le64_to_cpu(req->VolatileFileId);
5138 }
5139 ksmbd_debug(SMB, "volatile_id = %u\n", volatile_id);
5140
5141 rsp->StructureSize = cpu_to_le16(60);
5142 rsp->Reserved = 0;
5143
5144 if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) {
5145 fp = ksmbd_lookup_fd_fast(work, volatile_id);
5146 if (!fp) {
5147 err = -ENOENT;
5148 goto out;
5149 }
5150
ab0b263b 5151 inode = file_inode(fp->filp);
e2f34481
NJ
5152 rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
5153 rsp->AllocationSize = S_ISDIR(inode->i_mode) ? 0 :
5154 cpu_to_le64(inode->i_blocks << 9);
5155 rsp->EndOfFile = cpu_to_le64(inode->i_size);
5156 rsp->Attributes = fp->f_ci->m_fattr;
5157 rsp->CreationTime = cpu_to_le64(fp->create_time);
5158 time = ksmbd_UnixTimeToNT(inode->i_atime);
5159 rsp->LastAccessTime = cpu_to_le64(time);
5160 time = ksmbd_UnixTimeToNT(inode->i_mtime);
5161 rsp->LastWriteTime = cpu_to_le64(time);
5162 time = ksmbd_UnixTimeToNT(inode->i_ctime);
5163 rsp->ChangeTime = cpu_to_le64(time);
5164 ksmbd_fd_put(work, fp);
5165 } else {
5166 rsp->Flags = 0;
5167 rsp->AllocationSize = 0;
5168 rsp->EndOfFile = 0;
5169 rsp->Attributes = 0;
5170 rsp->CreationTime = 0;
5171 rsp->LastAccessTime = 0;
5172 rsp->LastWriteTime = 0;
5173 rsp->ChangeTime = 0;
5174 }
5175
5176 err = ksmbd_close_fd(work, volatile_id);
5177out:
5178 if (err) {
5179 if (rsp->hdr.Status == 0)
5180 rsp->hdr.Status = STATUS_FILE_CLOSED;
5181 smb2_set_err_rsp(work);
5182 } else {
5183 inc_rfc1001_len(rsp_org, 60);
5184 }
5185
5186 return 0;
5187}
5188
5189/**
5190 * smb2_echo() - handler for smb2 echo(ping) command
5191 * @work: smb work containing echo request buffer
5192 *
5193 * Return: 0
5194 */
5195int smb2_echo(struct ksmbd_work *work)
5196{
e5066499 5197 struct smb2_echo_rsp *rsp = work->response_buf;
e2f34481
NJ
5198
5199 rsp->StructureSize = cpu_to_le16(4);
5200 rsp->Reserved = 0;
5201 inc_rfc1001_len(rsp, 4);
5202 return 0;
5203}
5204
e2f34481 5205static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e
NJ
5206 struct smb2_file_rename_info *file_info,
5207 struct nls_table *local_nls)
e2f34481
NJ
5208{
5209 struct ksmbd_share_config *share = fp->tcon->share_conf;
5210 char *new_name = NULL, *abs_oldname = NULL, *old_name = NULL;
5211 char *pathname = NULL;
5212 struct path path;
5213 bool file_present = true;
5214 int rc;
5215
5216 ksmbd_debug(SMB, "setting FILE_RENAME_INFO\n");
5217 pathname = kmalloc(PATH_MAX, GFP_KERNEL);
5218 if (!pathname)
5219 return -ENOMEM;
5220
5221 abs_oldname = d_path(&fp->filp->f_path, pathname, PATH_MAX);
5222 if (IS_ERR(abs_oldname)) {
5223 rc = -EINVAL;
5224 goto out;
5225 }
5226 old_name = strrchr(abs_oldname, '/');
64b39f4a 5227 if (old_name && old_name[1] != '\0') {
e2f34481 5228 old_name++;
64b39f4a 5229 } else {
e2f34481 5230 ksmbd_debug(SMB, "can't get last component in path %s\n",
070fb21e 5231 abs_oldname);
e2f34481
NJ
5232 rc = -ENOENT;
5233 goto out;
5234 }
5235
5236 new_name = smb2_get_name(share,
5237 file_info->FileName,
5238 le32_to_cpu(file_info->FileNameLength),
5239 local_nls);
5240 if (IS_ERR(new_name)) {
5241 rc = PTR_ERR(new_name);
5242 goto out;
5243 }
5244
5245 if (strchr(new_name, ':')) {
5246 int s_type;
5247 char *xattr_stream_name, *stream_name = NULL;
5248 size_t xattr_stream_size;
5249 int len;
5250
5251 rc = parse_stream_name(new_name, &stream_name, &s_type);
5252 if (rc < 0)
5253 goto out;
5254
5255 len = strlen(new_name);
5256 if (new_name[len - 1] != '/') {
bde1694a 5257 pr_err("not allow base filename in rename\n");
e2f34481
NJ
5258 rc = -ESHARE;
5259 goto out;
5260 }
5261
5262 rc = ksmbd_vfs_xattr_stream_name(stream_name,
5263 &xattr_stream_name,
5264 &xattr_stream_size,
5265 s_type);
5266 if (rc)
5267 goto out;
5268
af34983e
HL
5269 rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp),
5270 fp->filp->f_path.dentry,
e2f34481
NJ
5271 xattr_stream_name,
5272 NULL, 0, 0);
5273 if (rc < 0) {
bde1694a
NJ
5274 pr_err("failed to store stream name in xattr: %d\n",
5275 rc);
e2f34481
NJ
5276 rc = -EINVAL;
5277 goto out;
5278 }
5279
5280 goto out;
5281 }
5282
5283 ksmbd_debug(SMB, "new name %s\n", new_name);
5284 rc = ksmbd_vfs_kern_path(new_name, 0, &path, 1);
5285 if (rc)
5286 file_present = false;
5287 else
5288 path_put(&path);
5289
5290 if (ksmbd_share_veto_filename(share, new_name)) {
5291 rc = -ENOENT;
5292 ksmbd_debug(SMB, "Can't rename vetoed file: %s\n", new_name);
5293 goto out;
5294 }
5295
5296 if (file_info->ReplaceIfExists) {
5297 if (file_present) {
5298 rc = ksmbd_vfs_remove_file(work, new_name);
5299 if (rc) {
5300 if (rc != -ENOTEMPTY)
5301 rc = -EINVAL;
5302 ksmbd_debug(SMB, "cannot delete %s, rc %d\n",
070fb21e 5303 new_name, rc);
e2f34481
NJ
5304 goto out;
5305 }
5306 }
5307 } else {
5308 if (file_present &&
64b39f4a 5309 strncmp(old_name, path.dentry->d_name.name, strlen(old_name))) {
e2f34481
NJ
5310 rc = -EEXIST;
5311 ksmbd_debug(SMB,
070fb21e 5312 "cannot rename already existing file\n");
e2f34481
NJ
5313 goto out;
5314 }
5315 }
5316
5317 rc = ksmbd_vfs_fp_rename(work, fp, new_name);
5318out:
5319 kfree(pathname);
5320 if (!IS_ERR(new_name))
915f570a 5321 kfree(new_name);
e2f34481
NJ
5322 return rc;
5323}
5324
e2f34481 5325static int smb2_create_link(struct ksmbd_work *work,
070fb21e
NJ
5326 struct ksmbd_share_config *share,
5327 struct smb2_file_link_info *file_info,
5328 struct file *filp,
5329 struct nls_table *local_nls)
e2f34481
NJ
5330{
5331 char *link_name = NULL, *target_name = NULL, *pathname = NULL;
5332 struct path path;
5333 bool file_present = true;
5334 int rc;
5335
5336 ksmbd_debug(SMB, "setting FILE_LINK_INFORMATION\n");
5337 pathname = kmalloc(PATH_MAX, GFP_KERNEL);
5338 if (!pathname)
5339 return -ENOMEM;
5340
5341 link_name = smb2_get_name(share,
5342 file_info->FileName,
5343 le32_to_cpu(file_info->FileNameLength),
5344 local_nls);
5345 if (IS_ERR(link_name) || S_ISDIR(file_inode(filp)->i_mode)) {
5346 rc = -EINVAL;
5347 goto out;
5348 }
5349
5350 ksmbd_debug(SMB, "link name is %s\n", link_name);
5351 target_name = d_path(&filp->f_path, pathname, PATH_MAX);
5352 if (IS_ERR(target_name)) {
5353 rc = -EINVAL;
5354 goto out;
5355 }
5356
5357 ksmbd_debug(SMB, "target name is %s\n", target_name);
5358 rc = ksmbd_vfs_kern_path(link_name, 0, &path, 0);
5359 if (rc)
5360 file_present = false;
5361 else
5362 path_put(&path);
5363
5364 if (file_info->ReplaceIfExists) {
5365 if (file_present) {
5366 rc = ksmbd_vfs_remove_file(work, link_name);
5367 if (rc) {
5368 rc = -EINVAL;
5369 ksmbd_debug(SMB, "cannot delete %s\n",
070fb21e 5370 link_name);
e2f34481
NJ
5371 goto out;
5372 }
5373 }
5374 } else {
5375 if (file_present) {
5376 rc = -EEXIST;
5377 ksmbd_debug(SMB, "link already exists\n");
5378 goto out;
5379 }
5380 }
5381
5382 rc = ksmbd_vfs_link(work, target_name, link_name);
5383 if (rc)
5384 rc = -EINVAL;
5385out:
5386 if (!IS_ERR(link_name))
915f570a 5387 kfree(link_name);
e2f34481
NJ
5388 kfree(pathname);
5389 return rc;
5390}
5391
64b39f4a 5392static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
070fb21e 5393 struct ksmbd_share_config *share)
e2f34481
NJ
5394{
5395 struct smb2_file_all_info *file_info;
5396 struct iattr attrs;
5397 struct iattr temp_attrs;
5398 struct file *filp;
5399 struct inode *inode;
465d7204 5400 struct user_namespace *user_ns;
e2f34481
NJ
5401 int rc;
5402
7adfd4f6 5403 if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE))
e2f34481
NJ
5404 return -EACCES;
5405
5406 file_info = (struct smb2_file_all_info *)buf;
5407 attrs.ia_valid = 0;
5408 filp = fp->filp;
5409 inode = file_inode(filp);
465d7204 5410 user_ns = file_mnt_user_ns(filp);
e2f34481
NJ
5411
5412 if (file_info->CreationTime)
5413 fp->create_time = le64_to_cpu(file_info->CreationTime);
5414
5415 if (file_info->LastAccessTime) {
5416 attrs.ia_atime = ksmbd_NTtimeToUnix(file_info->LastAccessTime);
5417 attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
5418 }
5419
5420 if (file_info->ChangeTime) {
5421 temp_attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
5422 attrs.ia_ctime = temp_attrs.ia_ctime;
5423 attrs.ia_valid |= ATTR_CTIME;
64b39f4a 5424 } else {
e2f34481 5425 temp_attrs.ia_ctime = inode->i_ctime;
64b39f4a 5426 }
e2f34481
NJ
5427
5428 if (file_info->LastWriteTime) {
5429 attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
5430 attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
5431 }
5432
5433 if (file_info->Attributes) {
5434 if (!S_ISDIR(inode->i_mode) &&
64b39f4a 5435 file_info->Attributes & ATTR_DIRECTORY_LE) {
bde1694a 5436 pr_err("can't change a file to a directory\n");
e2f34481
NJ
5437 return -EINVAL;
5438 }
5439
5440 if (!(S_ISDIR(inode->i_mode) && file_info->Attributes == ATTR_NORMAL_LE))
5441 fp->f_ci->m_fattr = file_info->Attributes |
5442 (fp->f_ci->m_fattr & ATTR_DIRECTORY_LE);
5443 }
5444
5445 if (test_share_config_flag(share, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS) &&
5446 (file_info->CreationTime || file_info->Attributes)) {
5447 struct xattr_dos_attrib da = {0};
5448
5449 da.version = 4;
5450 da.itime = fp->itime;
5451 da.create_time = fp->create_time;
5452 da.attr = le32_to_cpu(fp->f_ci->m_fattr);
5453 da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
5454 XATTR_DOSINFO_ITIME;
5455
465d7204 5456 rc = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
af34983e 5457 filp->f_path.dentry, &da);
e2f34481
NJ
5458 if (rc)
5459 ksmbd_debug(SMB,
070fb21e 5460 "failed to restore file attribute in EA\n");
e2f34481
NJ
5461 rc = 0;
5462 }
5463
5464 /*
5465 * HACK : set ctime here to avoid ctime changed
5466 * when file_info->ChangeTime is zero.
5467 */
5468 attrs.ia_ctime = temp_attrs.ia_ctime;
5469 attrs.ia_valid |= ATTR_CTIME;
5470
5471 if (attrs.ia_valid) {
5472 struct dentry *dentry = filp->f_path.dentry;
5473 struct inode *inode = d_inode(dentry);
5474
5475 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
5476 return -EACCES;
5477
465d7204 5478 rc = setattr_prepare(user_ns, dentry, &attrs);
e2f34481
NJ
5479 if (rc)
5480 return -EINVAL;
5481
5482 inode_lock(inode);
465d7204 5483 setattr_copy(user_ns, inode, &attrs);
e2f34481 5484 attrs.ia_valid &= ~ATTR_CTIME;
465d7204 5485 rc = notify_change(user_ns, dentry, &attrs, NULL);
e2f34481
NJ
5486 inode_unlock(inode);
5487 }
5488 return 0;
5489}
5490
5491static int set_file_allocation_info(struct ksmbd_work *work,
070fb21e 5492 struct ksmbd_file *fp, char *buf)
e2f34481
NJ
5493{
5494 /*
5495 * TODO : It's working fine only when store dos attributes
5496 * is not yes. need to implement a logic which works
5497 * properly with any smb.conf option
5498 */
5499
5500 struct smb2_file_alloc_info *file_alloc_info;
5501 loff_t alloc_blks;
5502 struct inode *inode;
5503 int rc;
5504
a299669b 5505 if (!(fp->daccess & FILE_WRITE_DATA_LE))
e2f34481
NJ
5506 return -EACCES;
5507
5508 file_alloc_info = (struct smb2_file_alloc_info *)buf;
5509 alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9;
5510 inode = file_inode(fp->filp);
5511
5512 if (alloc_blks > inode->i_blocks) {
e8c06191
NJ
5513 smb_break_all_levII_oplock(work, fp, 1);
5514 rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
5515 alloc_blks * 512);
e2f34481 5516 if (rc && rc != -EOPNOTSUPP) {
e8c06191 5517 pr_err("vfs_fallocate is failed : %d\n", rc);
e2f34481
NJ
5518 return rc;
5519 }
5520 } else if (alloc_blks < inode->i_blocks) {
5521 loff_t size;
5522
5523 /*
5524 * Allocation size could be smaller than original one
5525 * which means allocated blocks in file should be
5526 * deallocated. use truncate to cut out it, but inode
5527 * size is also updated with truncate offset.
5528 * inode size is retained by backup inode size.
5529 */
5530 size = i_size_read(inode);
5531 rc = ksmbd_vfs_truncate(work, NULL, fp, alloc_blks * 512);
5532 if (rc) {
bde1694a
NJ
5533 pr_err("truncate failed! filename : %s, err %d\n",
5534 fp->filename, rc);
e2f34481
NJ
5535 return rc;
5536 }
5537 if (size < alloc_blks * 512)
5538 i_size_write(inode, size);
5539 }
5540 return 0;
5541}
5542
64b39f4a 5543static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e 5544 char *buf)
e2f34481
NJ
5545{
5546 struct smb2_file_eof_info *file_eof_info;
5547 loff_t newsize;
5548 struct inode *inode;
5549 int rc;
5550
a299669b 5551 if (!(fp->daccess & FILE_WRITE_DATA_LE))
e2f34481
NJ
5552 return -EACCES;
5553
5554 file_eof_info = (struct smb2_file_eof_info *)buf;
5555 newsize = le64_to_cpu(file_eof_info->EndOfFile);
5556 inode = file_inode(fp->filp);
5557
5558 /*
5559 * If FILE_END_OF_FILE_INFORMATION of set_info_file is called
5560 * on FAT32 shared device, truncate execution time is too long
5561 * and network error could cause from windows client. because
5562 * truncate of some filesystem like FAT32 fill zero data in
5563 * truncated range.
5564 */
5565 if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
5566 ksmbd_debug(SMB, "filename : %s truncated to newsize %lld\n",
070fb21e 5567 fp->filename, newsize);
e2f34481
NJ
5568 rc = ksmbd_vfs_truncate(work, NULL, fp, newsize);
5569 if (rc) {
64b39f4a 5570 ksmbd_debug(SMB, "truncate failed! filename : %s err %d\n",
070fb21e 5571 fp->filename, rc);
e2f34481
NJ
5572 if (rc != -EAGAIN)
5573 rc = -EBADF;
5574 return rc;
5575 }
5576 }
5577 return 0;
5578}
5579
64b39f4a 5580static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e 5581 char *buf)
e2f34481
NJ
5582{
5583 struct ksmbd_file *parent_fp;
12202c05
NJ
5584 struct dentry *parent;
5585 struct dentry *dentry = fp->filp->f_path.dentry;
5586 int ret;
e2f34481
NJ
5587
5588 if (!(fp->daccess & FILE_DELETE_LE)) {
bde1694a 5589 pr_err("no right to delete : 0x%x\n", fp->daccess);
e2f34481
NJ
5590 return -EACCES;
5591 }
5592
5593 if (ksmbd_stream_fd(fp))
5594 goto next;
5595
12202c05
NJ
5596 parent = dget_parent(dentry);
5597 ret = ksmbd_vfs_lock_parent(parent, dentry);
5598 if (ret) {
5599 dput(parent);
5600 return ret;
5601 }
5602
5603 parent_fp = ksmbd_lookup_fd_inode(d_inode(parent));
5604 inode_unlock(d_inode(parent));
5605 dput(parent);
5606
e2f34481
NJ
5607 if (parent_fp) {
5608 if (parent_fp->daccess & FILE_DELETE_LE) {
bde1694a 5609 pr_err("parent dir is opened with delete access\n");
e2f34481
NJ
5610 return -ESHARE;
5611 }
5612 }
5613next:
5614 return smb2_rename(work, fp,
5615 (struct smb2_file_rename_info *)buf,
5616 work->sess->conn->local_nls);
5617}
5618
64b39f4a 5619static int set_file_disposition_info(struct ksmbd_file *fp, char *buf)
e2f34481
NJ
5620{
5621 struct smb2_file_disposition_info *file_info;
5622 struct inode *inode;
5623
5624 if (!(fp->daccess & FILE_DELETE_LE)) {
bde1694a 5625 pr_err("no right to delete : 0x%x\n", fp->daccess);
e2f34481
NJ
5626 return -EACCES;
5627 }
5628
5629 inode = file_inode(fp->filp);
5630 file_info = (struct smb2_file_disposition_info *)buf;
5631 if (file_info->DeletePending) {
5632 if (S_ISDIR(inode->i_mode) &&
64b39f4a 5633 ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY)
e2f34481
NJ
5634 return -EBUSY;
5635 ksmbd_set_inode_pending_delete(fp);
5636 } else {
5637 ksmbd_clear_inode_pending_delete(fp);
5638 }
5639 return 0;
5640}
5641
64b39f4a 5642static int set_file_position_info(struct ksmbd_file *fp, char *buf)
e2f34481
NJ
5643{
5644 struct smb2_file_pos_info *file_info;
5645 loff_t current_byte_offset;
ee81cae1 5646 unsigned long sector_size;
e2f34481
NJ
5647 struct inode *inode;
5648
5649 inode = file_inode(fp->filp);
5650 file_info = (struct smb2_file_pos_info *)buf;
5651 current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset);
ee81cae1 5652 sector_size = inode->i_sb->s_blocksize;
e2f34481
NJ
5653
5654 if (current_byte_offset < 0 ||
64b39f4a
NJ
5655 (fp->coption == FILE_NO_INTERMEDIATE_BUFFERING_LE &&
5656 current_byte_offset & (sector_size - 1))) {
bde1694a
NJ
5657 pr_err("CurrentByteOffset is not valid : %llu\n",
5658 current_byte_offset);
e2f34481
NJ
5659 return -EINVAL;
5660 }
5661
5662 fp->filp->f_pos = current_byte_offset;
5663 return 0;
5664}
5665
64b39f4a 5666static int set_file_mode_info(struct ksmbd_file *fp, char *buf)
e2f34481
NJ
5667{
5668 struct smb2_file_mode_info *file_info;
5669 __le32 mode;
5670
5671 file_info = (struct smb2_file_mode_info *)buf;
5672 mode = file_info->Mode;
5673
64b39f4a
NJ
5674 if ((mode & ~FILE_MODE_INFO_MASK) ||
5675 (mode & FILE_SYNCHRONOUS_IO_ALERT_LE &&
5676 mode & FILE_SYNCHRONOUS_IO_NONALERT_LE)) {
bde1694a 5677 pr_err("Mode is not valid : 0x%x\n", le32_to_cpu(mode));
e2f34481
NJ
5678 return -EINVAL;
5679 }
5680
5681 /*
5682 * TODO : need to implement consideration for
5683 * FILE_SYNCHRONOUS_IO_ALERT and FILE_SYNCHRONOUS_IO_NONALERT
5684 */
5685 ksmbd_vfs_set_fadvise(fp->filp, mode);
5686 fp->coption = mode;
5687 return 0;
5688}
5689
5690/**
5691 * smb2_set_info_file() - handler for smb2 set info command
5692 * @work: smb work containing set info command buffer
95fa1ce9
HL
5693 * @fp: ksmbd_file pointer
5694 * @info_class: smb2 set info class
5695 * @share: ksmbd_share_config pointer
e2f34481
NJ
5696 *
5697 * Return: 0 on success, otherwise error
5698 * TODO: need to implement an error handling for STATUS_INFO_LENGTH_MISMATCH
5699 */
64b39f4a 5700static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e
NJ
5701 int info_class, char *buf,
5702 struct ksmbd_share_config *share)
e2f34481
NJ
5703{
5704 switch (info_class) {
5705 case FILE_BASIC_INFORMATION:
5706 return set_file_basic_info(fp, buf, share);
5707
5708 case FILE_ALLOCATION_INFORMATION:
5709 return set_file_allocation_info(work, fp, buf);
5710
5711 case FILE_END_OF_FILE_INFORMATION:
5712 return set_end_of_file_info(work, fp, buf);
5713
5714 case FILE_RENAME_INFORMATION:
64b39f4a 5715 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
e2f34481 5716 ksmbd_debug(SMB,
070fb21e 5717 "User does not have write permission\n");
e2f34481
NJ
5718 return -EACCES;
5719 }
5720 return set_rename_info(work, fp, buf);
5721
5722 case FILE_LINK_INFORMATION:
5723 return smb2_create_link(work, work->tcon->share_conf,
070fb21e
NJ
5724 (struct smb2_file_link_info *)buf, fp->filp,
5725 work->sess->conn->local_nls);
e2f34481
NJ
5726
5727 case FILE_DISPOSITION_INFORMATION:
64b39f4a 5728 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
e2f34481 5729 ksmbd_debug(SMB,
070fb21e 5730 "User does not have write permission\n");
e2f34481
NJ
5731 return -EACCES;
5732 }
5733 return set_file_disposition_info(fp, buf);
5734
5735 case FILE_FULL_EA_INFORMATION:
5736 {
5737 if (!(fp->daccess & FILE_WRITE_EA_LE)) {
bde1694a
NJ
5738 pr_err("Not permitted to write ext attr: 0x%x\n",
5739 fp->daccess);
e2f34481
NJ
5740 return -EACCES;
5741 }
5742
5743 return smb2_set_ea((struct smb2_ea_info *)buf,
5744 &fp->filp->f_path);
5745 }
5746
5747 case FILE_POSITION_INFORMATION:
5748 return set_file_position_info(fp, buf);
5749
5750 case FILE_MODE_INFORMATION:
5751 return set_file_mode_info(fp, buf);
5752 }
5753
bde1694a 5754 pr_err("Unimplemented Fileinfoclass :%d\n", info_class);
e2f34481
NJ
5755 return -EOPNOTSUPP;
5756}
5757
64b39f4a 5758static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
070fb21e 5759 char *buffer, int buf_len)
e2f34481
NJ
5760{
5761 struct smb_ntsd *pntsd = (struct smb_ntsd *)buffer;
5762
5763 fp->saccess |= FILE_SHARE_DELETE_LE;
5764
ef24c962 5765 return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd,
e2f34481
NJ
5766 buf_len, false);
5767}
5768
5769/**
5770 * smb2_set_info() - handler for smb2 set info command handler
5771 * @work: smb work containing set info request buffer
5772 *
5773 * Return: 0 on success, otherwise error
5774 */
5775int smb2_set_info(struct ksmbd_work *work)
5776{
5777 struct smb2_set_info_req *req;
5778 struct smb2_set_info_rsp *rsp, *rsp_org;
5779 struct ksmbd_file *fp;
5780 int rc = 0;
5781 unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
5782
5783 ksmbd_debug(SMB, "Received set info request\n");
5784
e5066499 5785 rsp_org = work->response_buf;
e2f34481 5786 if (work->next_smb2_rcv_hdr_off) {
8a893315
NJ
5787 req = ksmbd_req_buf_next(work);
5788 rsp = ksmbd_resp_buf_next(work);
e2f34481
NJ
5789 if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) {
5790 ksmbd_debug(SMB, "Compound request set FID = %u\n",
070fb21e 5791 work->compound_fid);
e2f34481
NJ
5792 id = work->compound_fid;
5793 pid = work->compound_pfid;
5794 }
5795 } else {
e5066499
NJ
5796 req = work->request_buf;
5797 rsp = work->response_buf;
e2f34481
NJ
5798 }
5799
5800 if (!HAS_FILE_ID(id)) {
5801 id = le64_to_cpu(req->VolatileFileId);
5802 pid = le64_to_cpu(req->PersistentFileId);
5803 }
5804
5805 fp = ksmbd_lookup_fd_slow(work, id, pid);
5806 if (!fp) {
5807 ksmbd_debug(SMB, "Invalid id for close: %u\n", id);
5808 rc = -ENOENT;
5809 goto err_out;
5810 }
5811
5812 switch (req->InfoType) {
5813 case SMB2_O_INFO_FILE:
5814 ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
5815 rc = smb2_set_info_file(work, fp, req->FileInfoClass,
5816 req->Buffer, work->tcon->share_conf);
5817 break;
5818 case SMB2_O_INFO_SECURITY:
5819 ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
5820 rc = smb2_set_info_sec(fp,
070fb21e
NJ
5821 le32_to_cpu(req->AdditionalInformation),
5822 req->Buffer,
5823 le32_to_cpu(req->BufferLength));
e2f34481
NJ
5824 break;
5825 default:
5826 rc = -EOPNOTSUPP;
5827 }
5828
5829 if (rc < 0)
5830 goto err_out;
5831
5832 rsp->StructureSize = cpu_to_le16(2);
5833 inc_rfc1001_len(rsp_org, 2);
5834 ksmbd_fd_put(work, fp);
5835 return 0;
5836
5837err_out:
5838 if (rc == -EACCES || rc == -EPERM)
5839 rsp->hdr.Status = STATUS_ACCESS_DENIED;
5840 else if (rc == -EINVAL)
5841 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
5842 else if (rc == -ESHARE)
5843 rsp->hdr.Status = STATUS_SHARING_VIOLATION;
5844 else if (rc == -ENOENT)
5845 rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID;
5846 else if (rc == -EBUSY || rc == -ENOTEMPTY)
5847 rsp->hdr.Status = STATUS_DIRECTORY_NOT_EMPTY;
5848 else if (rc == -EAGAIN)
5849 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
ff1d5727 5850 else if (rc == -EBADF || rc == -ESTALE)
e2f34481
NJ
5851 rsp->hdr.Status = STATUS_INVALID_HANDLE;
5852 else if (rc == -EEXIST)
5853 rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION;
5854 else if (rsp->hdr.Status == 0 || rc == -EOPNOTSUPP)
5855 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
5856 smb2_set_err_rsp(work);
5857 ksmbd_fd_put(work, fp);
070fb21e 5858 ksmbd_debug(SMB, "error while processing smb2 query rc = %d\n", rc);
e2f34481
NJ
5859 return rc;
5860}
5861
5862/**
5863 * smb2_read_pipe() - handler for smb2 read from IPC pipe
5864 * @work: smb work containing read IPC pipe command buffer
5865 *
5866 * Return: 0 on success, otherwise error
5867 */
5868static noinline int smb2_read_pipe(struct ksmbd_work *work)
5869{
5870 int nbytes = 0, err;
64b39f4a 5871 u64 id;
e2f34481 5872 struct ksmbd_rpc_command *rpc_resp;
e5066499
NJ
5873 struct smb2_read_req *req = work->request_buf;
5874 struct smb2_read_rsp *rsp = work->response_buf;
e2f34481
NJ
5875
5876 id = le64_to_cpu(req->VolatileFileId);
5877
5878 inc_rfc1001_len(rsp, 16);
5879 rpc_resp = ksmbd_rpc_read(work->sess, id);
5880 if (rpc_resp) {
5881 if (rpc_resp->flags != KSMBD_RPC_OK) {
5882 err = -EINVAL;
5883 goto out;
5884 }
5885
5886 work->aux_payload_buf =
79f6b11a 5887 kvmalloc(rpc_resp->payload_sz, GFP_KERNEL | __GFP_ZERO);
e2f34481
NJ
5888 if (!work->aux_payload_buf) {
5889 err = -ENOMEM;
5890 goto out;
5891 }
5892
5893 memcpy(work->aux_payload_buf, rpc_resp->payload,
070fb21e 5894 rpc_resp->payload_sz);
e2f34481
NJ
5895
5896 nbytes = rpc_resp->payload_sz;
5897 work->resp_hdr_sz = get_rfc1002_len(rsp) + 4;
5898 work->aux_payload_sz = nbytes;
79f6b11a 5899 kvfree(rpc_resp);
e2f34481
NJ
5900 }
5901
5902 rsp->StructureSize = cpu_to_le16(17);
5903 rsp->DataOffset = 80;
5904 rsp->Reserved = 0;
5905 rsp->DataLength = cpu_to_le32(nbytes);
5906 rsp->DataRemaining = 0;
5907 rsp->Reserved2 = 0;
5908 inc_rfc1001_len(rsp, nbytes);
5909 return 0;
5910
5911out:
5912 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
5913 smb2_set_err_rsp(work);
79f6b11a 5914 kvfree(rpc_resp);
e2f34481
NJ
5915 return err;
5916}
5917
5918static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work,
070fb21e
NJ
5919 struct smb2_read_req *req, void *data_buf,
5920 size_t length)
e2f34481
NJ
5921{
5922 struct smb2_buffer_desc_v1 *desc =
5923 (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
5924 int err;
5925
64b39f4a
NJ
5926 if (work->conn->dialect == SMB30_PROT_ID &&
5927 req->Channel != SMB2_CHANNEL_RDMA_V1)
e2f34481
NJ
5928 return -EINVAL;
5929
64b39f4a
NJ
5930 if (req->ReadChannelInfoOffset == 0 ||
5931 le16_to_cpu(req->ReadChannelInfoLength) < sizeof(*desc))
e2f34481
NJ
5932 return -EINVAL;
5933
5934 work->need_invalidate_rkey =
5935 (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
5936 work->remote_key = le32_to_cpu(desc->token);
5937
64b39f4a 5938 err = ksmbd_conn_rdma_write(work->conn, data_buf, length,
070fb21e
NJ
5939 le32_to_cpu(desc->token),
5940 le64_to_cpu(desc->offset),
5941 le32_to_cpu(desc->length));
e2f34481
NJ
5942 if (err)
5943 return err;
5944
5945 return length;
5946}
5947
5948/**
5949 * smb2_read() - handler for smb2 read from file
5950 * @work: smb work containing read command buffer
5951 *
5952 * Return: 0 on success, otherwise error
5953 */
5954int smb2_read(struct ksmbd_work *work)
5955{
5956 struct ksmbd_conn *conn = work->conn;
5957 struct smb2_read_req *req;
5958 struct smb2_read_rsp *rsp, *rsp_org;
5959 struct ksmbd_file *fp;
5960 loff_t offset;
5961 size_t length, mincount;
5962 ssize_t nbytes = 0, remain_bytes = 0;
5963 int err = 0;
5964
e5066499 5965 rsp_org = work->response_buf;
e2f34481
NJ
5966 WORK_BUFFERS(work, req, rsp);
5967
5968 if (test_share_config_flag(work->tcon->share_conf,
5969 KSMBD_SHARE_FLAG_PIPE)) {
5970 ksmbd_debug(SMB, "IPC pipe read request\n");
5971 return smb2_read_pipe(work);
5972 }
5973
070fb21e
NJ
5974 fp = ksmbd_lookup_fd_slow(work, le64_to_cpu(req->VolatileFileId),
5975 le64_to_cpu(req->PersistentFileId));
e2f34481 5976 if (!fp) {
a4382db9
MM
5977 err = -ENOENT;
5978 goto out;
e2f34481
NJ
5979 }
5980
5981 if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
bde1694a 5982 pr_err("Not permitted to read : 0x%x\n", fp->daccess);
e2f34481
NJ
5983 err = -EACCES;
5984 goto out;
5985 }
5986
5987 offset = le64_to_cpu(req->Offset);
5988 length = le32_to_cpu(req->Length);
5989 mincount = le32_to_cpu(req->MinimumCount);
5990
5991 if (length > conn->vals->max_read_size) {
5992 ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
5993 conn->vals->max_read_size);
5994 err = -EINVAL;
5995 goto out;
5996 }
5997
493fa2fb
NJ
5998 ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
5999 fp->filp->f_path.dentry, offset, length);
e2f34481 6000
c30f4eb8 6001 work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
e2f34481 6002 if (!work->aux_payload_buf) {
c1ea111f 6003 err = -ENOMEM;
e2f34481
NJ
6004 goto out;
6005 }
6006
6007 nbytes = ksmbd_vfs_read(work, fp, length, &offset);
6008 if (nbytes < 0) {
6009 err = nbytes;
6010 goto out;
6011 }
6012
6013 if ((nbytes == 0 && length != 0) || nbytes < mincount) {
c30f4eb8 6014 kvfree(work->aux_payload_buf);
e5066499 6015 work->aux_payload_buf = NULL;
e2f34481
NJ
6016 rsp->hdr.Status = STATUS_END_OF_FILE;
6017 smb2_set_err_rsp(work);
6018 ksmbd_fd_put(work, fp);
6019 return 0;
6020 }
6021
6022 ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
070fb21e 6023 nbytes, offset, mincount);
e2f34481
NJ
6024
6025 if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
64b39f4a 6026 req->Channel == SMB2_CHANNEL_RDMA_V1) {
e2f34481
NJ
6027 /* write data to the client using rdma channel */
6028 remain_bytes = smb2_read_rdma_channel(work, req,
070fb21e
NJ
6029 work->aux_payload_buf,
6030 nbytes);
c30f4eb8 6031 kvfree(work->aux_payload_buf);
e5066499 6032 work->aux_payload_buf = NULL;
e2f34481
NJ
6033
6034 nbytes = 0;
6035 if (remain_bytes < 0) {
6036 err = (int)remain_bytes;
6037 goto out;
6038 }
6039 }
6040
6041 rsp->StructureSize = cpu_to_le16(17);
6042 rsp->DataOffset = 80;
6043 rsp->Reserved = 0;
6044 rsp->DataLength = cpu_to_le32(nbytes);
6045 rsp->DataRemaining = cpu_to_le32(remain_bytes);
6046 rsp->Reserved2 = 0;
6047 inc_rfc1001_len(rsp_org, 16);
6048 work->resp_hdr_sz = get_rfc1002_len(rsp_org) + 4;
6049 work->aux_payload_sz = nbytes;
6050 inc_rfc1001_len(rsp_org, nbytes);
6051 ksmbd_fd_put(work, fp);
6052 return 0;
6053
6054out:
6055 if (err) {
6056 if (err == -EISDIR)
6057 rsp->hdr.Status = STATUS_INVALID_DEVICE_REQUEST;
6058 else if (err == -EAGAIN)
6059 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
6060 else if (err == -ENOENT)
6061 rsp->hdr.Status = STATUS_FILE_CLOSED;
6062 else if (err == -EACCES)
6063 rsp->hdr.Status = STATUS_ACCESS_DENIED;
6064 else if (err == -ESHARE)
6065 rsp->hdr.Status = STATUS_SHARING_VIOLATION;
6066 else if (err == -EINVAL)
6067 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6068 else
6069 rsp->hdr.Status = STATUS_INVALID_HANDLE;
6070
6071 smb2_set_err_rsp(work);
6072 }
6073 ksmbd_fd_put(work, fp);
6074 return err;
6075}
6076
6077/**
6078 * smb2_write_pipe() - handler for smb2 write on IPC pipe
6079 * @work: smb work containing write IPC pipe command buffer
6080 *
6081 * Return: 0 on success, otherwise error
6082 */
6083static noinline int smb2_write_pipe(struct ksmbd_work *work)
6084{
e5066499
NJ
6085 struct smb2_write_req *req = work->request_buf;
6086 struct smb2_write_rsp *rsp = work->response_buf;
e2f34481 6087 struct ksmbd_rpc_command *rpc_resp;
64b39f4a 6088 u64 id = 0;
e2f34481
NJ
6089 int err = 0, ret = 0;
6090 char *data_buf;
6091 size_t length;
6092
6093 length = le32_to_cpu(req->Length);
6094 id = le64_to_cpu(req->VolatileFileId);
6095
6096 if (le16_to_cpu(req->DataOffset) ==
64b39f4a 6097 (offsetof(struct smb2_write_req, Buffer) - 4)) {
e2f34481
NJ
6098 data_buf = (char *)&req->Buffer[0];
6099 } else {
6100 if ((le16_to_cpu(req->DataOffset) > get_rfc1002_len(req)) ||
64b39f4a 6101 (le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(req))) {
bde1694a
NJ
6102 pr_err("invalid write data offset %u, smb_len %u\n",
6103 le16_to_cpu(req->DataOffset),
6104 get_rfc1002_len(req));
e2f34481
NJ
6105 err = -EINVAL;
6106 goto out;
6107 }
6108
6109 data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
6110 le16_to_cpu(req->DataOffset));
6111 }
6112
6113 rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length);
6114 if (rpc_resp) {
6115 if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
6116 rsp->hdr.Status = STATUS_NOT_SUPPORTED;
79f6b11a 6117 kvfree(rpc_resp);
e2f34481
NJ
6118 smb2_set_err_rsp(work);
6119 return -EOPNOTSUPP;
6120 }
6121 if (rpc_resp->flags != KSMBD_RPC_OK) {
6122 rsp->hdr.Status = STATUS_INVALID_HANDLE;
6123 smb2_set_err_rsp(work);
79f6b11a 6124 kvfree(rpc_resp);
e2f34481
NJ
6125 return ret;
6126 }
79f6b11a 6127 kvfree(rpc_resp);
e2f34481
NJ
6128 }
6129
6130 rsp->StructureSize = cpu_to_le16(17);
6131 rsp->DataOffset = 0;
6132 rsp->Reserved = 0;
6133 rsp->DataLength = cpu_to_le32(length);
6134 rsp->DataRemaining = 0;
6135 rsp->Reserved2 = 0;
6136 inc_rfc1001_len(rsp, 16);
6137 return 0;
6138out:
6139 if (err) {
6140 rsp->hdr.Status = STATUS_INVALID_HANDLE;
6141 smb2_set_err_rsp(work);
6142 }
6143
6144 return err;
6145}
6146
6147static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
070fb21e
NJ
6148 struct smb2_write_req *req,
6149 struct ksmbd_file *fp,
6150 loff_t offset, size_t length, bool sync)
e2f34481
NJ
6151{
6152 struct smb2_buffer_desc_v1 *desc;
6153 char *data_buf;
6154 int ret;
6155 ssize_t nbytes;
6156
6157 desc = (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
6158
6159 if (work->conn->dialect == SMB30_PROT_ID &&
64b39f4a 6160 req->Channel != SMB2_CHANNEL_RDMA_V1)
e2f34481
NJ
6161 return -EINVAL;
6162
6163 if (req->Length != 0 || req->DataOffset != 0)
6164 return -EINVAL;
6165
64b39f4a
NJ
6166 if (req->WriteChannelInfoOffset == 0 ||
6167 le16_to_cpu(req->WriteChannelInfoLength) < sizeof(*desc))
e2f34481
NJ
6168 return -EINVAL;
6169
6170 work->need_invalidate_rkey =
6171 (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
6172 work->remote_key = le32_to_cpu(desc->token);
6173
79f6b11a 6174 data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
e2f34481
NJ
6175 if (!data_buf)
6176 return -ENOMEM;
6177
6178 ret = ksmbd_conn_rdma_read(work->conn, data_buf, length,
070fb21e
NJ
6179 le32_to_cpu(desc->token),
6180 le64_to_cpu(desc->offset),
6181 le32_to_cpu(desc->length));
e2f34481 6182 if (ret < 0) {
79f6b11a 6183 kvfree(data_buf);
e2f34481
NJ
6184 return ret;
6185 }
6186
64b39f4a 6187 ret = ksmbd_vfs_write(work, fp, data_buf, length, &offset, sync, &nbytes);
79f6b11a 6188 kvfree(data_buf);
e2f34481
NJ
6189 if (ret < 0)
6190 return ret;
6191
6192 return nbytes;
6193}
6194
6195/**
6196 * smb2_write() - handler for smb2 write from file
6197 * @work: smb work containing write command buffer
6198 *
6199 * Return: 0 on success, otherwise error
6200 */
6201int smb2_write(struct ksmbd_work *work)
6202{
6203 struct smb2_write_req *req;
6204 struct smb2_write_rsp *rsp, *rsp_org;
bcd62a36 6205 struct ksmbd_file *fp = NULL;
e2f34481
NJ
6206 loff_t offset;
6207 size_t length;
6208 ssize_t nbytes;
6209 char *data_buf;
6210 bool writethrough = false;
6211 int err = 0;
6212
e5066499 6213 rsp_org = work->response_buf;
e2f34481
NJ
6214 WORK_BUFFERS(work, req, rsp);
6215
64b39f4a 6216 if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) {
e2f34481
NJ
6217 ksmbd_debug(SMB, "IPC pipe write request\n");
6218 return smb2_write_pipe(work);
6219 }
6220
6221 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
6222 ksmbd_debug(SMB, "User does not have write permission\n");
6223 err = -EACCES;
6224 goto out;
6225 }
6226
64b39f4a 6227 fp = ksmbd_lookup_fd_slow(work, le64_to_cpu(req->VolatileFileId),
070fb21e 6228 le64_to_cpu(req->PersistentFileId));
e2f34481 6229 if (!fp) {
a4382db9
MM
6230 err = -ENOENT;
6231 goto out;
e2f34481
NJ
6232 }
6233
6234 if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
bde1694a 6235 pr_err("Not permitted to write : 0x%x\n", fp->daccess);
e2f34481
NJ
6236 err = -EACCES;
6237 goto out;
6238 }
6239
6240 offset = le64_to_cpu(req->Offset);
6241 length = le32_to_cpu(req->Length);
6242
6243 if (length > work->conn->vals->max_write_size) {
6244 ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
6245 work->conn->vals->max_write_size);
6246 err = -EINVAL;
6247 goto out;
6248 }
6249
6250 if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
6251 writethrough = true;
6252
6253 if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
64b39f4a 6254 req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
e2f34481 6255 if (le16_to_cpu(req->DataOffset) ==
070fb21e 6256 (offsetof(struct smb2_write_req, Buffer) - 4)) {
e2f34481
NJ
6257 data_buf = (char *)&req->Buffer[0];
6258 } else {
64b39f4a
NJ
6259 if ((le16_to_cpu(req->DataOffset) > get_rfc1002_len(req)) ||
6260 (le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(req))) {
bde1694a
NJ
6261 pr_err("invalid write data offset %u, smb_len %u\n",
6262 le16_to_cpu(req->DataOffset),
6263 get_rfc1002_len(req));
e2f34481
NJ
6264 err = -EINVAL;
6265 goto out;
6266 }
6267
6268 data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
6269 le16_to_cpu(req->DataOffset));
6270 }
6271
6272 ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
6273 if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
6274 writethrough = true;
6275
493fa2fb
NJ
6276 ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
6277 fp->filp->f_path.dentry, offset, length);
e2f34481
NJ
6278 err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
6279 writethrough, &nbytes);
6280 if (err < 0)
6281 goto out;
6282 } else {
6283 /* read data from the client using rdma channel, and
6284 * write the data.
6285 */
6286 nbytes = smb2_write_rdma_channel(work, req, fp, offset,
070fb21e
NJ
6287 le32_to_cpu(req->RemainingBytes),
6288 writethrough);
e2f34481
NJ
6289 if (nbytes < 0) {
6290 err = (int)nbytes;
6291 goto out;
6292 }
6293 }
6294
6295 rsp->StructureSize = cpu_to_le16(17);
6296 rsp->DataOffset = 0;
6297 rsp->Reserved = 0;
6298 rsp->DataLength = cpu_to_le32(nbytes);
6299 rsp->DataRemaining = 0;
6300 rsp->Reserved2 = 0;
6301 inc_rfc1001_len(rsp_org, 16);
6302 ksmbd_fd_put(work, fp);
6303 return 0;
6304
6305out:
6306 if (err == -EAGAIN)
6307 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
6308 else if (err == -ENOSPC || err == -EFBIG)
6309 rsp->hdr.Status = STATUS_DISK_FULL;
6310 else if (err == -ENOENT)
6311 rsp->hdr.Status = STATUS_FILE_CLOSED;
6312 else if (err == -EACCES)
6313 rsp->hdr.Status = STATUS_ACCESS_DENIED;
6314 else if (err == -ESHARE)
6315 rsp->hdr.Status = STATUS_SHARING_VIOLATION;
6316 else if (err == -EINVAL)
6317 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6318 else
6319 rsp->hdr.Status = STATUS_INVALID_HANDLE;
6320
6321 smb2_set_err_rsp(work);
6322 ksmbd_fd_put(work, fp);
6323 return err;
6324}
6325
6326/**
6327 * smb2_flush() - handler for smb2 flush file - fsync
6328 * @work: smb work containing flush command buffer
6329 *
6330 * Return: 0 on success, otherwise error
6331 */
6332int smb2_flush(struct ksmbd_work *work)
6333{
6334 struct smb2_flush_req *req;
6335 struct smb2_flush_rsp *rsp, *rsp_org;
6336 int err;
6337
e5066499 6338 rsp_org = work->response_buf;
e2f34481
NJ
6339 WORK_BUFFERS(work, req, rsp);
6340
6341 ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n",
070fb21e 6342 le64_to_cpu(req->VolatileFileId));
e2f34481
NJ
6343
6344 err = ksmbd_vfs_fsync(work,
6345 le64_to_cpu(req->VolatileFileId),
6346 le64_to_cpu(req->PersistentFileId));
6347 if (err)
6348 goto out;
6349
6350 rsp->StructureSize = cpu_to_le16(4);
6351 rsp->Reserved = 0;
6352 inc_rfc1001_len(rsp_org, 4);
6353 return 0;
6354
6355out:
6356 if (err) {
6357 rsp->hdr.Status = STATUS_INVALID_HANDLE;
6358 smb2_set_err_rsp(work);
6359 }
6360
6361 return err;
6362}
6363
6364/**
6365 * smb2_cancel() - handler for smb2 cancel command
6366 * @work: smb work containing cancel command buffer
6367 *
6368 * Return: 0 on success, otherwise error
6369 */
6370int smb2_cancel(struct ksmbd_work *work)
6371{
6372 struct ksmbd_conn *conn = work->conn;
e5066499 6373 struct smb2_hdr *hdr = work->request_buf;
e2f34481
NJ
6374 struct smb2_hdr *chdr;
6375 struct ksmbd_work *cancel_work = NULL;
e2f34481
NJ
6376 int canceled = 0;
6377 struct list_head *command_list;
6378
6379 ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
070fb21e 6380 hdr->MessageId, hdr->Flags);
e2f34481
NJ
6381
6382 if (hdr->Flags & SMB2_FLAGS_ASYNC_COMMAND) {
6383 command_list = &conn->async_requests;
6384
6385 spin_lock(&conn->request_lock);
6f3d5eee
NJ
6386 list_for_each_entry(cancel_work, command_list,
6387 async_request_entry) {
e5066499 6388 chdr = cancel_work->request_buf;
e2f34481
NJ
6389
6390 if (cancel_work->async_id !=
64b39f4a 6391 le64_to_cpu(hdr->Id.AsyncId))
e2f34481
NJ
6392 continue;
6393
6394 ksmbd_debug(SMB,
070fb21e
NJ
6395 "smb2 with AsyncId %llu cancelled command = 0x%x\n",
6396 le64_to_cpu(hdr->Id.AsyncId),
6397 le16_to_cpu(chdr->Command));
e2f34481
NJ
6398 canceled = 1;
6399 break;
6400 }
6401 spin_unlock(&conn->request_lock);
6402 } else {
6403 command_list = &conn->requests;
6404
6405 spin_lock(&conn->request_lock);
6f3d5eee 6406 list_for_each_entry(cancel_work, command_list, request_entry) {
e5066499 6407 chdr = cancel_work->request_buf;
e2f34481
NJ
6408
6409 if (chdr->MessageId != hdr->MessageId ||
64b39f4a 6410 cancel_work == work)
e2f34481
NJ
6411 continue;
6412
6413 ksmbd_debug(SMB,
070fb21e
NJ
6414 "smb2 with mid %llu cancelled command = 0x%x\n",
6415 le64_to_cpu(hdr->MessageId),
6416 le16_to_cpu(chdr->Command));
e2f34481
NJ
6417 canceled = 1;
6418 break;
6419 }
6420 spin_unlock(&conn->request_lock);
6421 }
6422
6423 if (canceled) {
6424 cancel_work->state = KSMBD_WORK_CANCELLED;
6425 if (cancel_work->cancel_fn)
6426 cancel_work->cancel_fn(cancel_work->cancel_argv);
6427 }
6428
6429 /* For SMB2_CANCEL command itself send no response*/
6430 work->send_no_response = 1;
6431 return 0;
6432}
6433
6434struct file_lock *smb_flock_init(struct file *f)
6435{
6436 struct file_lock *fl;
6437
6438 fl = locks_alloc_lock();
6439 if (!fl)
6440 goto out;
6441
6442 locks_init_lock(fl);
6443
6444 fl->fl_owner = f;
6445 fl->fl_pid = current->tgid;
6446 fl->fl_file = f;
6447 fl->fl_flags = FL_POSIX;
6448 fl->fl_ops = NULL;
6449 fl->fl_lmops = NULL;
6450
6451out:
6452 return fl;
6453}
6454
6455static int smb2_set_flock_flags(struct file_lock *flock, int flags)
6456{
6457 int cmd = -EINVAL;
6458
6459 /* Checking for wrong flag combination during lock request*/
6460 switch (flags) {
6461 case SMB2_LOCKFLAG_SHARED:
6462 ksmbd_debug(SMB, "received shared request\n");
6463 cmd = F_SETLKW;
6464 flock->fl_type = F_RDLCK;
6465 flock->fl_flags |= FL_SLEEP;
6466 break;
6467 case SMB2_LOCKFLAG_EXCLUSIVE:
6468 ksmbd_debug(SMB, "received exclusive request\n");
6469 cmd = F_SETLKW;
6470 flock->fl_type = F_WRLCK;
6471 flock->fl_flags |= FL_SLEEP;
6472 break;
64b39f4a 6473 case SMB2_LOCKFLAG_SHARED | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
e2f34481 6474 ksmbd_debug(SMB,
070fb21e 6475 "received shared & fail immediately request\n");
e2f34481
NJ
6476 cmd = F_SETLK;
6477 flock->fl_type = F_RDLCK;
6478 break;
64b39f4a 6479 case SMB2_LOCKFLAG_EXCLUSIVE | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
e2f34481 6480 ksmbd_debug(SMB,
070fb21e 6481 "received exclusive & fail immediately request\n");
e2f34481
NJ
6482 cmd = F_SETLK;
6483 flock->fl_type = F_WRLCK;
6484 break;
6485 case SMB2_LOCKFLAG_UNLOCK:
6486 ksmbd_debug(SMB, "received unlock request\n");
6487 flock->fl_type = F_UNLCK;
6488 cmd = 0;
6489 break;
6490 }
6491
6492 return cmd;
6493}
6494
6495static struct ksmbd_lock *smb2_lock_init(struct file_lock *flock,
070fb21e
NJ
6496 unsigned int cmd, int flags,
6497 struct list_head *lock_list)
e2f34481
NJ
6498{
6499 struct ksmbd_lock *lock;
6500
6501 lock = kzalloc(sizeof(struct ksmbd_lock), GFP_KERNEL);
6502 if (!lock)
6503 return NULL;
6504
6505 lock->cmd = cmd;
6506 lock->fl = flock;
6507 lock->start = flock->fl_start;
6508 lock->end = flock->fl_end;
6509 lock->flags = flags;
6510 if (lock->start == lock->end)
6511 lock->zero_len = 1;
6512 INIT_LIST_HEAD(&lock->llist);
6513 INIT_LIST_HEAD(&lock->glist);
6514 list_add_tail(&lock->llist, lock_list);
6515
6516 return lock;
6517}
6518
6519static void smb2_remove_blocked_lock(void **argv)
6520{
6521 struct file_lock *flock = (struct file_lock *)argv[0];
6522
6523 ksmbd_vfs_posix_lock_unblock(flock);
6524 wake_up(&flock->fl_wait);
6525}
6526
6527static inline bool lock_defer_pending(struct file_lock *fl)
6528{
6529 /* check pending lock waiters */
6530 return waitqueue_active(&fl->fl_wait);
6531}
6532
6533/**
6534 * smb2_lock() - handler for smb2 file lock command
6535 * @work: smb work containing lock command buffer
6536 *
6537 * Return: 0 on success, otherwise error
6538 */
6539int smb2_lock(struct ksmbd_work *work)
6540{
e5066499
NJ
6541 struct smb2_lock_req *req = work->request_buf;
6542 struct smb2_lock_rsp *rsp = work->response_buf;
e2f34481
NJ
6543 struct smb2_lock_element *lock_ele;
6544 struct ksmbd_file *fp = NULL;
6545 struct file_lock *flock = NULL;
6546 struct file *filp = NULL;
6547 int lock_count;
6548 int flags = 0;
6549 int cmd = 0;
6550 int err = 0, i;
50bf80a5 6551 u64 lock_start, lock_length;
e2f34481
NJ
6552 struct ksmbd_lock *smb_lock = NULL, *cmp_lock, *tmp;
6553 int nolock = 0;
6554 LIST_HEAD(lock_list);
6555 LIST_HEAD(rollback_list);
6556 int prior_lock = 0;
6557
6558 ksmbd_debug(SMB, "Received lock request\n");
6559 fp = ksmbd_lookup_fd_slow(work,
070fb21e
NJ
6560 le64_to_cpu(req->VolatileFileId),
6561 le64_to_cpu(req->PersistentFileId));
e2f34481
NJ
6562 if (!fp) {
6563 ksmbd_debug(SMB, "Invalid file id for lock : %llu\n",
070fb21e 6564 le64_to_cpu(req->VolatileFileId));
e2f34481
NJ
6565 rsp->hdr.Status = STATUS_FILE_CLOSED;
6566 goto out2;
6567 }
6568
6569 filp = fp->filp;
6570 lock_count = le16_to_cpu(req->LockCount);
6571 lock_ele = req->locks;
6572
6573 ksmbd_debug(SMB, "lock count is %d\n", lock_count);
070fb21e 6574 if (!lock_count) {
e2f34481
NJ
6575 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6576 goto out2;
6577 }
6578
6579 for (i = 0; i < lock_count; i++) {
6580 flags = le32_to_cpu(lock_ele[i].Flags);
6581
6582 flock = smb_flock_init(filp);
6583 if (!flock) {
6584 rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
6585 goto out;
6586 }
6587
6588 cmd = smb2_set_flock_flags(flock, flags);
6589
50bf80a5
NJ
6590 lock_start = le64_to_cpu(lock_ele[i].Offset);
6591 lock_length = le64_to_cpu(lock_ele[i].Length);
6592 if (lock_start > U64_MAX - lock_length) {
bde1694a 6593 pr_err("Invalid lock range requested\n");
e2f34481
NJ
6594 rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
6595 goto out;
6596 }
6597
50bf80a5
NJ
6598 if (lock_start > OFFSET_MAX)
6599 flock->fl_start = OFFSET_MAX;
6600 else
6601 flock->fl_start = lock_start;
6602
e2f34481 6603 lock_length = le64_to_cpu(lock_ele[i].Length);
50bf80a5
NJ
6604 if (lock_length > OFFSET_MAX - flock->fl_start)
6605 lock_length = OFFSET_MAX - flock->fl_start;
e2f34481
NJ
6606
6607 flock->fl_end = flock->fl_start + lock_length;
6608
6609 if (flock->fl_end < flock->fl_start) {
6610 ksmbd_debug(SMB,
070fb21e
NJ
6611 "the end offset(%llx) is smaller than the start offset(%llx)\n",
6612 flock->fl_end, flock->fl_start);
e2f34481
NJ
6613 rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
6614 goto out;
6615 }
6616
6617 /* Check conflict locks in one request */
6618 list_for_each_entry(cmp_lock, &lock_list, llist) {
6619 if (cmp_lock->fl->fl_start <= flock->fl_start &&
64b39f4a 6620 cmp_lock->fl->fl_end >= flock->fl_end) {
e2f34481 6621 if (cmp_lock->fl->fl_type != F_UNLCK &&
64b39f4a 6622 flock->fl_type != F_UNLCK) {
bde1694a 6623 pr_err("conflict two locks in one request\n");
e2f34481
NJ
6624 rsp->hdr.Status =
6625 STATUS_INVALID_PARAMETER;
6626 goto out;
6627 }
6628 }
6629 }
6630
6631 smb_lock = smb2_lock_init(flock, cmd, flags, &lock_list);
6632 if (!smb_lock) {
6633 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6634 goto out;
6635 }
6636 }
6637
6638 list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
6639 if (smb_lock->cmd < 0) {
6640 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6641 goto out;
6642 }
6643
6644 if (!(smb_lock->flags & SMB2_LOCKFLAG_MASK)) {
6645 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6646 goto out;
6647 }
6648
64b39f4a
NJ
6649 if ((prior_lock & (SMB2_LOCKFLAG_EXCLUSIVE | SMB2_LOCKFLAG_SHARED) &&
6650 smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) ||
6651 (prior_lock == SMB2_LOCKFLAG_UNLOCK &&
6652 !(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK))) {
e2f34481
NJ
6653 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6654 goto out;
6655 }
6656
6657 prior_lock = smb_lock->flags;
6658
6659 if (!(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) &&
64b39f4a 6660 !(smb_lock->flags & SMB2_LOCKFLAG_FAIL_IMMEDIATELY))
e2f34481
NJ
6661 goto no_check_gl;
6662
6663 nolock = 1;
6664 /* check locks in global list */
6665 list_for_each_entry(cmp_lock, &global_lock_list, glist) {
6666 if (file_inode(cmp_lock->fl->fl_file) !=
64b39f4a 6667 file_inode(smb_lock->fl->fl_file))
e2f34481
NJ
6668 continue;
6669
6670 if (smb_lock->fl->fl_type == F_UNLCK) {
64b39f4a
NJ
6671 if (cmp_lock->fl->fl_file == smb_lock->fl->fl_file &&
6672 cmp_lock->start == smb_lock->start &&
6673 cmp_lock->end == smb_lock->end &&
6674 !lock_defer_pending(cmp_lock->fl)) {
e2f34481
NJ
6675 nolock = 0;
6676 locks_free_lock(cmp_lock->fl);
6677 list_del(&cmp_lock->glist);
6678 kfree(cmp_lock);
6679 break;
6680 }
6681 continue;
6682 }
6683
6684 if (cmp_lock->fl->fl_file == smb_lock->fl->fl_file) {
6685 if (smb_lock->flags & SMB2_LOCKFLAG_SHARED)
6686 continue;
6687 } else {
6688 if (cmp_lock->flags & SMB2_LOCKFLAG_SHARED)
6689 continue;
6690 }
6691
6692 /* check zero byte lock range */
6693 if (cmp_lock->zero_len && !smb_lock->zero_len &&
64b39f4a
NJ
6694 cmp_lock->start > smb_lock->start &&
6695 cmp_lock->start < smb_lock->end) {
bde1694a 6696 pr_err("previous lock conflict with zero byte lock range\n");
e2f34481
NJ
6697 rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
6698 goto out;
6699 }
6700
6701 if (smb_lock->zero_len && !cmp_lock->zero_len &&
64b39f4a
NJ
6702 smb_lock->start > cmp_lock->start &&
6703 smb_lock->start < cmp_lock->end) {
bde1694a 6704 pr_err("current lock conflict with zero byte lock range\n");
e2f34481
NJ
6705 rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
6706 goto out;
6707 }
6708
6709 if (((cmp_lock->start <= smb_lock->start &&
64b39f4a
NJ
6710 cmp_lock->end > smb_lock->start) ||
6711 (cmp_lock->start < smb_lock->end && cmp_lock->end >= smb_lock->end)) &&
6712 !cmp_lock->zero_len && !smb_lock->zero_len) {
bde1694a 6713 pr_err("Not allow lock operation on exclusive lock range\n");
e2f34481
NJ
6714 rsp->hdr.Status =
6715 STATUS_LOCK_NOT_GRANTED;
6716 goto out;
6717 }
6718 }
6719
6720 if (smb_lock->fl->fl_type == F_UNLCK && nolock) {
bde1694a 6721 pr_err("Try to unlock nolocked range\n");
e2f34481
NJ
6722 rsp->hdr.Status = STATUS_RANGE_NOT_LOCKED;
6723 goto out;
6724 }
6725
6726no_check_gl:
6727 if (smb_lock->zero_len) {
6728 err = 0;
6729 goto skip;
6730 }
6731
6732 flock = smb_lock->fl;
6733 list_del(&smb_lock->llist);
6734retry:
e8c06191 6735 err = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
e2f34481
NJ
6736skip:
6737 if (flags & SMB2_LOCKFLAG_UNLOCK) {
64b39f4a 6738 if (!err) {
e2f34481 6739 ksmbd_debug(SMB, "File unlocked\n");
64b39f4a 6740 } else if (err == -ENOENT) {
e2f34481
NJ
6741 rsp->hdr.Status = STATUS_NOT_LOCKED;
6742 goto out;
6743 }
6744 locks_free_lock(flock);
6745 kfree(smb_lock);
6746 } else {
6747 if (err == FILE_LOCK_DEFERRED) {
6748 void **argv;
6749
6750 ksmbd_debug(SMB,
070fb21e 6751 "would have to wait for getting lock\n");
e2f34481 6752 list_add_tail(&smb_lock->glist,
070fb21e 6753 &global_lock_list);
e2f34481
NJ
6754 list_add(&smb_lock->llist, &rollback_list);
6755
6756 argv = kmalloc(sizeof(void *), GFP_KERNEL);
6757 if (!argv) {
6758 err = -ENOMEM;
6759 goto out;
6760 }
6761 argv[0] = flock;
6762
6763 err = setup_async_work(work,
070fb21e
NJ
6764 smb2_remove_blocked_lock,
6765 argv);
e2f34481
NJ
6766 if (err) {
6767 rsp->hdr.Status =
6768 STATUS_INSUFFICIENT_RESOURCES;
6769 goto out;
6770 }
6771 spin_lock(&fp->f_lock);
6772 list_add(&work->fp_entry, &fp->blocked_works);
6773 spin_unlock(&fp->f_lock);
6774
6775 smb2_send_interim_resp(work, STATUS_PENDING);
6776
6777 err = ksmbd_vfs_posix_lock_wait(flock);
6778
d4075abb 6779 if (work->state != KSMBD_WORK_ACTIVE) {
e2f34481
NJ
6780 list_del(&smb_lock->llist);
6781 list_del(&smb_lock->glist);
6782 locks_free_lock(flock);
6783
d4075abb 6784 if (work->state == KSMBD_WORK_CANCELLED) {
e2f34481
NJ
6785 spin_lock(&fp->f_lock);
6786 list_del(&work->fp_entry);
6787 spin_unlock(&fp->f_lock);
6788 rsp->hdr.Status =
6789 STATUS_CANCELLED;
6790 kfree(smb_lock);
6791 smb2_send_interim_resp(work,
070fb21e 6792 STATUS_CANCELLED);
e2f34481
NJ
6793 work->send_no_response = 1;
6794 goto out;
6795 }
6796 init_smb2_rsp_hdr(work);
6797 smb2_set_err_rsp(work);
6798 rsp->hdr.Status =
6799 STATUS_RANGE_NOT_LOCKED;
6800 kfree(smb_lock);
6801 goto out2;
6802 }
6803
6804 list_del(&smb_lock->llist);
6805 list_del(&smb_lock->glist);
6806 spin_lock(&fp->f_lock);
6807 list_del(&work->fp_entry);
6808 spin_unlock(&fp->f_lock);
6809 goto retry;
6810 } else if (!err) {
6811 list_add_tail(&smb_lock->glist,
070fb21e 6812 &global_lock_list);
e2f34481
NJ
6813 list_add(&smb_lock->llist, &rollback_list);
6814 ksmbd_debug(SMB, "successful in taking lock\n");
6815 } else {
6816 rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
6817 goto out;
6818 }
6819 }
6820 }
6821
6822 if (atomic_read(&fp->f_ci->op_count) > 1)
6823 smb_break_all_oplock(work, fp);
6824
6825 rsp->StructureSize = cpu_to_le16(4);
6826 ksmbd_debug(SMB, "successful in taking lock\n");
6827 rsp->hdr.Status = STATUS_SUCCESS;
6828 rsp->Reserved = 0;
6829 inc_rfc1001_len(rsp, 4);
6830 ksmbd_fd_put(work, fp);
6831 return err;
6832
6833out:
6834 list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
6835 locks_free_lock(smb_lock->fl);
6836 list_del(&smb_lock->llist);
6837 kfree(smb_lock);
6838 }
6839
6840 list_for_each_entry_safe(smb_lock, tmp, &rollback_list, llist) {
6841 struct file_lock *rlock = NULL;
6842
6843 rlock = smb_flock_init(filp);
6844 rlock->fl_type = F_UNLCK;
6845 rlock->fl_start = smb_lock->start;
6846 rlock->fl_end = smb_lock->end;
6847
e8c06191 6848 err = vfs_lock_file(filp, 0, rlock, NULL);
e2f34481 6849 if (err)
bde1694a 6850 pr_err("rollback unlock fail : %d\n", err);
e2f34481
NJ
6851 list_del(&smb_lock->llist);
6852 list_del(&smb_lock->glist);
6853 locks_free_lock(smb_lock->fl);
6854 locks_free_lock(rlock);
6855 kfree(smb_lock);
6856 }
6857out2:
6858 ksmbd_debug(SMB, "failed in taking lock(flags : %x)\n", flags);
6859 smb2_set_err_rsp(work);
6860 ksmbd_fd_put(work, fp);
6861 return 0;
6862}
6863
64b39f4a 6864static int fsctl_copychunk(struct ksmbd_work *work, struct smb2_ioctl_req *req,
070fb21e 6865 struct smb2_ioctl_rsp *rsp)
e2f34481
NJ
6866{
6867 struct copychunk_ioctl_req *ci_req;
6868 struct copychunk_ioctl_rsp *ci_rsp;
6869 struct ksmbd_file *src_fp = NULL, *dst_fp = NULL;
6870 struct srv_copychunk *chunks;
6871 unsigned int i, chunk_count, chunk_count_written = 0;
6872 unsigned int chunk_size_written = 0;
6873 loff_t total_size_written = 0;
6874 int ret, cnt_code;
6875
6876 cnt_code = le32_to_cpu(req->CntCode);
6877 ci_req = (struct copychunk_ioctl_req *)&req->Buffer[0];
6878 ci_rsp = (struct copychunk_ioctl_rsp *)&rsp->Buffer[0];
6879
6880 rsp->VolatileFileId = req->VolatileFileId;
6881 rsp->PersistentFileId = req->PersistentFileId;
64b39f4a
NJ
6882 ci_rsp->ChunksWritten =
6883 cpu_to_le32(ksmbd_server_side_copy_max_chunk_count());
6884 ci_rsp->ChunkBytesWritten =
6885 cpu_to_le32(ksmbd_server_side_copy_max_chunk_size());
6886 ci_rsp->TotalBytesWritten =
6887 cpu_to_le32(ksmbd_server_side_copy_max_total_size());
e2f34481
NJ
6888
6889 chunks = (struct srv_copychunk *)&ci_req->Chunks[0];
6890 chunk_count = le32_to_cpu(ci_req->ChunkCount);
6891 total_size_written = 0;
6892
6893 /* verify the SRV_COPYCHUNK_COPY packet */
6894 if (chunk_count > ksmbd_server_side_copy_max_chunk_count() ||
64b39f4a
NJ
6895 le32_to_cpu(req->InputCount) <
6896 offsetof(struct copychunk_ioctl_req, Chunks) +
6897 chunk_count * sizeof(struct srv_copychunk)) {
e2f34481
NJ
6898 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6899 return -EINVAL;
6900 }
6901
6902 for (i = 0; i < chunk_count; i++) {
6903 if (le32_to_cpu(chunks[i].Length) == 0 ||
64b39f4a 6904 le32_to_cpu(chunks[i].Length) > ksmbd_server_side_copy_max_chunk_size())
e2f34481
NJ
6905 break;
6906 total_size_written += le32_to_cpu(chunks[i].Length);
6907 }
64b39f4a
NJ
6908
6909 if (i < chunk_count ||
6910 total_size_written > ksmbd_server_side_copy_max_total_size()) {
e2f34481
NJ
6911 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6912 return -EINVAL;
6913 }
6914
6915 src_fp = ksmbd_lookup_foreign_fd(work,
070fb21e 6916 le64_to_cpu(ci_req->ResumeKey[0]));
e2f34481 6917 dst_fp = ksmbd_lookup_fd_slow(work,
070fb21e
NJ
6918 le64_to_cpu(req->VolatileFileId),
6919 le64_to_cpu(req->PersistentFileId));
e2f34481 6920 ret = -EINVAL;
64b39f4a
NJ
6921 if (!src_fp ||
6922 src_fp->persistent_id != le64_to_cpu(ci_req->ResumeKey[1])) {
e2f34481
NJ
6923 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
6924 goto out;
6925 }
64b39f4a 6926
e2f34481
NJ
6927 if (!dst_fp) {
6928 rsp->hdr.Status = STATUS_FILE_CLOSED;
6929 goto out;
6930 }
6931
6932 /*
6933 * FILE_READ_DATA should only be included in
6934 * the FSCTL_COPYCHUNK case
6935 */
070fb21e
NJ
6936 if (cnt_code == FSCTL_COPYCHUNK &&
6937 !(dst_fp->daccess & (FILE_READ_DATA_LE | FILE_GENERIC_READ_LE))) {
e2f34481
NJ
6938 rsp->hdr.Status = STATUS_ACCESS_DENIED;
6939 goto out;
6940 }
6941
6942 ret = ksmbd_vfs_copy_file_ranges(work, src_fp, dst_fp,
070fb21e
NJ
6943 chunks, chunk_count,
6944 &chunk_count_written,
6945 &chunk_size_written,
6946 &total_size_written);
e2f34481
NJ
6947 if (ret < 0) {
6948 if (ret == -EACCES)
6949 rsp->hdr.Status = STATUS_ACCESS_DENIED;
6950 if (ret == -EAGAIN)
6951 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
6952 else if (ret == -EBADF)
6953 rsp->hdr.Status = STATUS_INVALID_HANDLE;
6954 else if (ret == -EFBIG || ret == -ENOSPC)
6955 rsp->hdr.Status = STATUS_DISK_FULL;
6956 else if (ret == -EINVAL)
6957 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
6958 else if (ret == -EISDIR)
6959 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
6960 else if (ret == -E2BIG)
6961 rsp->hdr.Status = STATUS_INVALID_VIEW_SIZE;
6962 else
6963 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
6964 }
6965
6966 ci_rsp->ChunksWritten = cpu_to_le32(chunk_count_written);
6967 ci_rsp->ChunkBytesWritten = cpu_to_le32(chunk_size_written);
6968 ci_rsp->TotalBytesWritten = cpu_to_le32(total_size_written);
6969out:
6970 ksmbd_fd_put(work, src_fp);
6971 ksmbd_fd_put(work, dst_fp);
6972 return ret;
6973}
6974
6975static __be32 idev_ipv4_address(struct in_device *idev)
6976{
6977 __be32 addr = 0;
6978
6979 struct in_ifaddr *ifa;
6980
6981 rcu_read_lock();
6982 in_dev_for_each_ifa_rcu(ifa, idev) {
6983 if (ifa->ifa_flags & IFA_F_SECONDARY)
6984 continue;
6985
6986 addr = ifa->ifa_address;
6987 break;
6988 }
6989 rcu_read_unlock();
6990 return addr;
6991}
6992
6993static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
070fb21e
NJ
6994 struct smb2_ioctl_req *req,
6995 struct smb2_ioctl_rsp *rsp)
e2f34481
NJ
6996{
6997 struct network_interface_info_ioctl_rsp *nii_rsp = NULL;
6998 int nbytes = 0;
6999 struct net_device *netdev;
7000 struct sockaddr_storage_rsp *sockaddr_storage;
7001 unsigned int flags;
7002 unsigned long long speed;
7003
7004 rtnl_lock();
7005 for_each_netdev(&init_net, netdev) {
7006 if (unlikely(!netdev)) {
7007 rtnl_unlock();
7008 return -EINVAL;
7009 }
7010
7011 if (netdev->type == ARPHRD_LOOPBACK)
7012 continue;
7013
7014 flags = dev_get_flags(netdev);
7015 if (!(flags & IFF_RUNNING))
7016 continue;
7017
7018 nii_rsp = (struct network_interface_info_ioctl_rsp *)
7019 &rsp->Buffer[nbytes];
7020 nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex);
7021
7022 /* TODO: specify the RDMA capabilities */
7023 if (netdev->num_tx_queues > 1)
7024 nii_rsp->Capability = cpu_to_le32(RSS_CAPABLE);
7025 else
7026 nii_rsp->Capability = 0;
7027
7028 nii_rsp->Next = cpu_to_le32(152);
7029 nii_rsp->Reserved = 0;
7030
7031 if (netdev->ethtool_ops->get_link_ksettings) {
7032 struct ethtool_link_ksettings cmd;
7033
7034 netdev->ethtool_ops->get_link_ksettings(netdev, &cmd);
7035 speed = cmd.base.speed;
7036 } else {
bde1694a
NJ
7037 pr_err("%s %s\n", netdev->name,
7038 "speed is unknown, defaulting to 1Gb/sec");
e2f34481
NJ
7039 speed = SPEED_1000;
7040 }
7041
7042 speed *= 1000000;
7043 nii_rsp->LinkSpeed = cpu_to_le64(speed);
7044
7045 sockaddr_storage = (struct sockaddr_storage_rsp *)
7046 nii_rsp->SockAddr_Storage;
7047 memset(sockaddr_storage, 0, 128);
7048
7049 if (conn->peer_addr.ss_family == PF_INET) {
7050 struct in_device *idev;
7051
7052 sockaddr_storage->Family = cpu_to_le16(INTERNETWORK);
7053 sockaddr_storage->addr4.Port = 0;
7054
7055 idev = __in_dev_get_rtnl(netdev);
7056 if (!idev)
7057 continue;
7058 sockaddr_storage->addr4.IPv4address =
7059 idev_ipv4_address(idev);
7060 } else {
7061 struct inet6_dev *idev6;
7062 struct inet6_ifaddr *ifa;
7063 __u8 *ipv6_addr = sockaddr_storage->addr6.IPv6address;
7064
7065 sockaddr_storage->Family = cpu_to_le16(INTERNETWORKV6);
7066 sockaddr_storage->addr6.Port = 0;
7067 sockaddr_storage->addr6.FlowInfo = 0;
7068
7069 idev6 = __in6_dev_get(netdev);
7070 if (!idev6)
7071 continue;
7072
7073 list_for_each_entry(ifa, &idev6->addr_list, if_list) {
7074 if (ifa->flags & (IFA_F_TENTATIVE |
7075 IFA_F_DEPRECATED))
7076 continue;
7077 memcpy(ipv6_addr, ifa->addr.s6_addr, 16);
7078 break;
7079 }
7080 sockaddr_storage->addr6.ScopeId = 0;
7081 }
7082
7083 nbytes += sizeof(struct network_interface_info_ioctl_rsp);
7084 }
7085 rtnl_unlock();
7086
7087 /* zero if this is last one */
7088 if (nii_rsp)
7089 nii_rsp->Next = 0;
7090
7091 if (!nbytes) {
7092 rsp->hdr.Status = STATUS_BUFFER_TOO_SMALL;
7093 return -EINVAL;
7094 }
7095
7096 rsp->PersistentFileId = cpu_to_le64(SMB2_NO_FID);
7097 rsp->VolatileFileId = cpu_to_le64(SMB2_NO_FID);
7098 return nbytes;
7099}
7100
e2f34481 7101static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
070fb21e
NJ
7102 struct validate_negotiate_info_req *neg_req,
7103 struct validate_negotiate_info_rsp *neg_rsp)
e2f34481
NJ
7104{
7105 int ret = 0;
7106 int dialect;
7107
7108 dialect = ksmbd_lookup_dialect_by_id(neg_req->Dialects,
070fb21e 7109 neg_req->DialectCount);
e2f34481
NJ
7110 if (dialect == BAD_PROT_ID || dialect != conn->dialect) {
7111 ret = -EINVAL;
7112 goto err_out;
7113 }
7114
7115 if (strncmp(neg_req->Guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE)) {
7116 ret = -EINVAL;
7117 goto err_out;
7118 }
7119
7120 if (le16_to_cpu(neg_req->SecurityMode) != conn->cli_sec_mode) {
7121 ret = -EINVAL;
7122 goto err_out;
7123 }
7124
7125 if (le32_to_cpu(neg_req->Capabilities) != conn->cli_cap) {
7126 ret = -EINVAL;
7127 goto err_out;
7128 }
7129
7130 neg_rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
7131 memset(neg_rsp->Guid, 0, SMB2_CLIENT_GUID_SIZE);
7132 neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode);
7133 neg_rsp->Dialect = cpu_to_le16(conn->dialect);
7134err_out:
7135 return ret;
7136}
7137
64b39f4a 7138static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
070fb21e
NJ
7139 struct file_allocated_range_buffer *qar_req,
7140 struct file_allocated_range_buffer *qar_rsp,
7141 int in_count, int *out_count)
e2f34481
NJ
7142{
7143 struct ksmbd_file *fp;
7144 loff_t start, length;
7145 int ret = 0;
7146
7147 *out_count = 0;
7148 if (in_count == 0)
7149 return -EINVAL;
7150
7151 fp = ksmbd_lookup_fd_fast(work, id);
7152 if (!fp)
7153 return -ENOENT;
7154
7155 start = le64_to_cpu(qar_req->file_offset);
7156 length = le64_to_cpu(qar_req->length);
7157
7158 ret = ksmbd_vfs_fqar_lseek(fp, start, length,
070fb21e 7159 qar_rsp, in_count, out_count);
e2f34481
NJ
7160 if (ret && ret != -E2BIG)
7161 *out_count = 0;
7162
7163 ksmbd_fd_put(work, fp);
7164 return ret;
7165}
7166
64b39f4a 7167static int fsctl_pipe_transceive(struct ksmbd_work *work, u64 id,
070fb21e
NJ
7168 int out_buf_len, struct smb2_ioctl_req *req,
7169 struct smb2_ioctl_rsp *rsp)
e2f34481
NJ
7170{
7171 struct ksmbd_rpc_command *rpc_resp;
7172 char *data_buf = (char *)&req->Buffer[0];
7173 int nbytes = 0;
7174
64b39f4a 7175 rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf,
070fb21e 7176 le32_to_cpu(req->InputCount));
e2f34481
NJ
7177 if (rpc_resp) {
7178 if (rpc_resp->flags == KSMBD_RPC_SOME_NOT_MAPPED) {
7179 /*
7180 * set STATUS_SOME_NOT_MAPPED response
7181 * for unknown domain sid.
7182 */
7183 rsp->hdr.Status = STATUS_SOME_NOT_MAPPED;
7184 } else if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
7185 rsp->hdr.Status = STATUS_NOT_SUPPORTED;
7186 goto out;
7187 } else if (rpc_resp->flags != KSMBD_RPC_OK) {
7188 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
7189 goto out;
7190 }
7191
7192 nbytes = rpc_resp->payload_sz;
7193 if (rpc_resp->payload_sz > out_buf_len) {
7194 rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
7195 nbytes = out_buf_len;
7196 }
7197
7198 if (!rpc_resp->payload_sz) {
7199 rsp->hdr.Status =
7200 STATUS_UNEXPECTED_IO_ERROR;
7201 goto out;
7202 }
7203
7204 memcpy((char *)rsp->Buffer, rpc_resp->payload, nbytes);
7205 }
7206out:
79f6b11a 7207 kvfree(rpc_resp);
e2f34481
NJ
7208 return nbytes;
7209}
7210
64b39f4a 7211static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
070fb21e 7212 struct file_sparse *sparse)
e2f34481
NJ
7213{
7214 struct ksmbd_file *fp;
465d7204 7215 struct user_namespace *user_ns;
e2f34481
NJ
7216 int ret = 0;
7217 __le32 old_fattr;
7218
7219 fp = ksmbd_lookup_fd_fast(work, id);
7220 if (!fp)
7221 return -ENOENT;
465d7204 7222 user_ns = file_mnt_user_ns(fp->filp);
e2f34481
NJ
7223
7224 old_fattr = fp->f_ci->m_fattr;
7225 if (sparse->SetSparse)
7226 fp->f_ci->m_fattr |= ATTR_SPARSE_FILE_LE;
7227 else
7228 fp->f_ci->m_fattr &= ~ATTR_SPARSE_FILE_LE;
7229
7230 if (fp->f_ci->m_fattr != old_fattr &&
64b39f4a
NJ
7231 test_share_config_flag(work->tcon->share_conf,
7232 KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
e2f34481
NJ
7233 struct xattr_dos_attrib da;
7234
465d7204 7235 ret = ksmbd_vfs_get_dos_attrib_xattr(user_ns,
af34983e 7236 fp->filp->f_path.dentry, &da);
e2f34481
NJ
7237 if (ret <= 0)
7238 goto out;
7239
7240 da.attr = le32_to_cpu(fp->f_ci->m_fattr);
465d7204 7241 ret = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
af34983e 7242 fp->filp->f_path.dentry, &da);
e2f34481
NJ
7243 if (ret)
7244 fp->f_ci->m_fattr = old_fattr;
7245 }
7246
7247out:
7248 ksmbd_fd_put(work, fp);
7249 return ret;
7250}
7251
7252static int fsctl_request_resume_key(struct ksmbd_work *work,
070fb21e
NJ
7253 struct smb2_ioctl_req *req,
7254 struct resume_key_ioctl_rsp *key_rsp)
e2f34481
NJ
7255{
7256 struct ksmbd_file *fp;
7257
7258 fp = ksmbd_lookup_fd_slow(work,
070fb21e
NJ
7259 le64_to_cpu(req->VolatileFileId),
7260 le64_to_cpu(req->PersistentFileId));
e2f34481
NJ
7261 if (!fp)
7262 return -ENOENT;
7263
7264 memset(key_rsp, 0, sizeof(*key_rsp));
7265 key_rsp->ResumeKey[0] = req->VolatileFileId;
7266 key_rsp->ResumeKey[1] = req->PersistentFileId;
7267 ksmbd_fd_put(work, fp);
7268
7269 return 0;
7270}
7271
7272/**
7273 * smb2_ioctl() - handler for smb2 ioctl command
7274 * @work: smb work containing ioctl command buffer
7275 *
7276 * Return: 0 on success, otherwise error
7277 */
7278int smb2_ioctl(struct ksmbd_work *work)
7279{
7280 struct smb2_ioctl_req *req;
7281 struct smb2_ioctl_rsp *rsp, *rsp_org;
7282 int cnt_code, nbytes = 0;
7283 int out_buf_len;
64b39f4a 7284 u64 id = KSMBD_NO_FID;
e2f34481
NJ
7285 struct ksmbd_conn *conn = work->conn;
7286 int ret = 0;
7287
e5066499 7288 rsp_org = work->response_buf;
e2f34481 7289 if (work->next_smb2_rcv_hdr_off) {
8a893315
NJ
7290 req = ksmbd_req_buf_next(work);
7291 rsp = ksmbd_resp_buf_next(work);
e2f34481
NJ
7292 if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) {
7293 ksmbd_debug(SMB, "Compound request set FID = %u\n",
070fb21e 7294 work->compound_fid);
e2f34481
NJ
7295 id = work->compound_fid;
7296 }
7297 } else {
e5066499
NJ
7298 req = work->request_buf;
7299 rsp = work->response_buf;
e2f34481
NJ
7300 }
7301
7302 if (!HAS_FILE_ID(id))
7303 id = le64_to_cpu(req->VolatileFileId);
7304
7305 if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) {
7306 rsp->hdr.Status = STATUS_NOT_SUPPORTED;
7307 goto out;
7308 }
7309
7310 cnt_code = le32_to_cpu(req->CntCode);
7311 out_buf_len = le32_to_cpu(req->MaxOutputResponse);
7312 out_buf_len = min(KSMBD_IPC_MAX_PAYLOAD, out_buf_len);
7313
7314 switch (cnt_code) {
7315 case FSCTL_DFS_GET_REFERRALS:
7316 case FSCTL_DFS_GET_REFERRALS_EX:
7317 /* Not support DFS yet */
7318 rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED;
7319 goto out;
7320 case FSCTL_CREATE_OR_GET_OBJECT_ID:
7321 {
7322 struct file_object_buf_type1_ioctl_rsp *obj_buf;
7323
7324 nbytes = sizeof(struct file_object_buf_type1_ioctl_rsp);
7325 obj_buf = (struct file_object_buf_type1_ioctl_rsp *)
7326 &rsp->Buffer[0];
7327
7328 /*
7329 * TODO: This is dummy implementation to pass smbtorture
7330 * Need to check correct response later
7331 */
7332 memset(obj_buf->ObjectId, 0x0, 16);
7333 memset(obj_buf->BirthVolumeId, 0x0, 16);
7334 memset(obj_buf->BirthObjectId, 0x0, 16);
7335 memset(obj_buf->DomainId, 0x0, 16);
7336
7337 break;
7338 }
7339 case FSCTL_PIPE_TRANSCEIVE:
7340 nbytes = fsctl_pipe_transceive(work, id, out_buf_len, req, rsp);
7341 break;
7342 case FSCTL_VALIDATE_NEGOTIATE_INFO:
7343 if (conn->dialect < SMB30_PROT_ID) {
7344 ret = -EOPNOTSUPP;
7345 goto out;
7346 }
7347
7348 ret = fsctl_validate_negotiate_info(conn,
7349 (struct validate_negotiate_info_req *)&req->Buffer[0],
7350 (struct validate_negotiate_info_rsp *)&rsp->Buffer[0]);
7351 if (ret < 0)
7352 goto out;
7353
7354 nbytes = sizeof(struct validate_negotiate_info_rsp);
7355 rsp->PersistentFileId = cpu_to_le64(SMB2_NO_FID);
7356 rsp->VolatileFileId = cpu_to_le64(SMB2_NO_FID);
7357 break;
7358 case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
7359 nbytes = fsctl_query_iface_info_ioctl(conn, req, rsp);
7360 if (nbytes < 0)
7361 goto out;
7362 break;
7363 case FSCTL_REQUEST_RESUME_KEY:
7364 if (out_buf_len < sizeof(struct resume_key_ioctl_rsp)) {
7365 ret = -EINVAL;
7366 goto out;
7367 }
7368
7369 ret = fsctl_request_resume_key(work, req,
070fb21e 7370 (struct resume_key_ioctl_rsp *)&rsp->Buffer[0]);
e2f34481
NJ
7371 if (ret < 0)
7372 goto out;
7373 rsp->PersistentFileId = req->PersistentFileId;
7374 rsp->VolatileFileId = req->VolatileFileId;
7375 nbytes = sizeof(struct resume_key_ioctl_rsp);
7376 break;
7377 case FSCTL_COPYCHUNK:
7378 case FSCTL_COPYCHUNK_WRITE:
64b39f4a 7379 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
e2f34481 7380 ksmbd_debug(SMB,
070fb21e 7381 "User does not have write permission\n");
e2f34481
NJ
7382 ret = -EACCES;
7383 goto out;
7384 }
7385
7386 if (out_buf_len < sizeof(struct copychunk_ioctl_rsp)) {
7387 ret = -EINVAL;
7388 goto out;
7389 }
7390
7391 nbytes = sizeof(struct copychunk_ioctl_rsp);
7392 fsctl_copychunk(work, req, rsp);
7393 break;
7394 case FSCTL_SET_SPARSE:
7395 ret = fsctl_set_sparse(work, id,
070fb21e 7396 (struct file_sparse *)&req->Buffer[0]);
e2f34481
NJ
7397 if (ret < 0)
7398 goto out;
7399 break;
7400 case FSCTL_SET_ZERO_DATA:
7401 {
7402 struct file_zero_data_information *zero_data;
7403 struct ksmbd_file *fp;
7404 loff_t off, len;
7405
64b39f4a 7406 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
e2f34481 7407 ksmbd_debug(SMB,
070fb21e 7408 "User does not have write permission\n");
e2f34481
NJ
7409 ret = -EACCES;
7410 goto out;
7411 }
7412
7413 zero_data =
7414 (struct file_zero_data_information *)&req->Buffer[0];
7415
7416 fp = ksmbd_lookup_fd_fast(work, id);
7417 if (!fp) {
7418 ret = -ENOENT;
7419 goto out;
7420 }
7421
7422 off = le64_to_cpu(zero_data->FileOffset);
7423 len = le64_to_cpu(zero_data->BeyondFinalZero) - off;
7424
7425 ret = ksmbd_vfs_zero_data(work, fp, off, len);
7426 ksmbd_fd_put(work, fp);
7427 if (ret < 0)
7428 goto out;
7429 break;
7430 }
7431 case FSCTL_QUERY_ALLOCATED_RANGES:
7432 ret = fsctl_query_allocated_ranges(work, id,
7433 (struct file_allocated_range_buffer *)&req->Buffer[0],
7434 (struct file_allocated_range_buffer *)&rsp->Buffer[0],
7435 out_buf_len /
7436 sizeof(struct file_allocated_range_buffer), &nbytes);
7437 if (ret == -E2BIG) {
7438 rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
7439 } else if (ret < 0) {
7440 nbytes = 0;
7441 goto out;
7442 }
7443
7444 nbytes *= sizeof(struct file_allocated_range_buffer);
7445 break;
7446 case FSCTL_GET_REPARSE_POINT:
7447 {
7448 struct reparse_data_buffer *reparse_ptr;
7449 struct ksmbd_file *fp;
7450
7451 reparse_ptr = (struct reparse_data_buffer *)&rsp->Buffer[0];
7452 fp = ksmbd_lookup_fd_fast(work, id);
7453 if (!fp) {
bde1694a 7454 pr_err("not found fp!!\n");
e2f34481
NJ
7455 ret = -ENOENT;
7456 goto out;
7457 }
7458
7459 reparse_ptr->ReparseTag =
ab0b263b 7460 smb2_get_reparse_tag_special_file(file_inode(fp->filp)->i_mode);
e2f34481
NJ
7461 reparse_ptr->ReparseDataLength = 0;
7462 ksmbd_fd_put(work, fp);
7463 nbytes = sizeof(struct reparse_data_buffer);
7464 break;
7465 }
eb817368
NJ
7466 case FSCTL_DUPLICATE_EXTENTS_TO_FILE:
7467 {
7468 struct ksmbd_file *fp_in, *fp_out = NULL;
7469 struct duplicate_extents_to_file *dup_ext;
7470 loff_t src_off, dst_off, length, cloned;
7471
7472 dup_ext = (struct duplicate_extents_to_file *)&req->Buffer[0];
7473
7474 fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle,
070fb21e 7475 dup_ext->PersistentFileHandle);
eb817368 7476 if (!fp_in) {
bde1694a 7477 pr_err("not found file handle in duplicate extent to file\n");
eb817368
NJ
7478 ret = -ENOENT;
7479 goto out;
7480 }
7481
7482 fp_out = ksmbd_lookup_fd_fast(work, id);
7483 if (!fp_out) {
bde1694a 7484 pr_err("not found fp\n");
eb817368
NJ
7485 ret = -ENOENT;
7486 goto dup_ext_out;
7487 }
7488
7489 src_off = le64_to_cpu(dup_ext->SourceFileOffset);
7490 dst_off = le64_to_cpu(dup_ext->TargetFileOffset);
7491 length = le64_to_cpu(dup_ext->ByteCount);
7492 cloned = vfs_clone_file_range(fp_in->filp, src_off, fp_out->filp,
070fb21e 7493 dst_off, length, 0);
eb817368
NJ
7494 if (cloned == -EXDEV || cloned == -EOPNOTSUPP) {
7495 ret = -EOPNOTSUPP;
7496 goto dup_ext_out;
7497 } else if (cloned != length) {
f8524776
NJ
7498 cloned = vfs_copy_file_range(fp_in->filp, src_off,
7499 fp_out->filp, dst_off, length, 0);
eb817368
NJ
7500 if (cloned != length) {
7501 if (cloned < 0)
7502 ret = cloned;
7503 else
7504 ret = -EINVAL;
7505 }
7506 }
7507
7508dup_ext_out:
7509 ksmbd_fd_put(work, fp_in);
7510 ksmbd_fd_put(work, fp_out);
7511 if (ret < 0)
7512 goto out;
7513 break;
7514 }
e2f34481
NJ
7515 default:
7516 ksmbd_debug(SMB, "not implemented yet ioctl command 0x%x\n",
070fb21e 7517 cnt_code);
e2f34481
NJ
7518 ret = -EOPNOTSUPP;
7519 goto out;
7520 }
7521
7522 rsp->CntCode = cpu_to_le32(cnt_code);
7523 rsp->InputCount = cpu_to_le32(0);
7524 rsp->InputOffset = cpu_to_le32(112);
7525 rsp->OutputOffset = cpu_to_le32(112);
7526 rsp->OutputCount = cpu_to_le32(nbytes);
7527 rsp->StructureSize = cpu_to_le16(49);
7528 rsp->Reserved = cpu_to_le16(0);
7529 rsp->Flags = cpu_to_le32(0);
7530 rsp->Reserved2 = cpu_to_le32(0);
7531 inc_rfc1001_len(rsp_org, 48 + nbytes);
7532
7533 return 0;
7534
7535out:
7536 if (ret == -EACCES)
7537 rsp->hdr.Status = STATUS_ACCESS_DENIED;
7538 else if (ret == -ENOENT)
7539 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
7540 else if (ret == -EOPNOTSUPP)
7541 rsp->hdr.Status = STATUS_NOT_SUPPORTED;
7542 else if (ret < 0 || rsp->hdr.Status == 0)
7543 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
7544 smb2_set_err_rsp(work);
7545 return 0;
7546}
7547
7548/**
7549 * smb20_oplock_break_ack() - handler for smb2.0 oplock break command
7550 * @work: smb work containing oplock break command buffer
7551 *
7552 * Return: 0
7553 */
7554static void smb20_oplock_break_ack(struct ksmbd_work *work)
7555{
e5066499
NJ
7556 struct smb2_oplock_break *req = work->request_buf;
7557 struct smb2_oplock_break *rsp = work->response_buf;
e2f34481
NJ
7558 struct ksmbd_file *fp;
7559 struct oplock_info *opinfo = NULL;
7560 __le32 err = 0;
7561 int ret = 0;
64b39f4a 7562 u64 volatile_id, persistent_id;
e2f34481
NJ
7563 char req_oplevel = 0, rsp_oplevel = 0;
7564 unsigned int oplock_change_type;
7565
7566 volatile_id = le64_to_cpu(req->VolatileFid);
7567 persistent_id = le64_to_cpu(req->PersistentFid);
7568 req_oplevel = req->OplockLevel;
7569 ksmbd_debug(OPLOCK, "v_id %llu, p_id %llu request oplock level %d\n",
7570 volatile_id, persistent_id, req_oplevel);
7571
7572 fp = ksmbd_lookup_fd_slow(work, volatile_id, persistent_id);
7573 if (!fp) {
7574 rsp->hdr.Status = STATUS_FILE_CLOSED;
7575 smb2_set_err_rsp(work);
7576 return;
7577 }
7578
7579 opinfo = opinfo_get(fp);
7580 if (!opinfo) {
bde1694a 7581 pr_err("unexpected null oplock_info\n");
e2f34481
NJ
7582 rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
7583 smb2_set_err_rsp(work);
7584 ksmbd_fd_put(work, fp);
7585 return;
7586 }
7587
7588 if (opinfo->level == SMB2_OPLOCK_LEVEL_NONE) {
7589 rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
7590 goto err_out;
7591 }
7592
7593 if (opinfo->op_state == OPLOCK_STATE_NONE) {
7594 ksmbd_debug(SMB, "unexpected oplock state 0x%x\n", opinfo->op_state);
7595 rsp->hdr.Status = STATUS_UNSUCCESSFUL;
7596 goto err_out;
7597 }
7598
64b39f4a
NJ
7599 if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
7600 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
7601 (req_oplevel != SMB2_OPLOCK_LEVEL_II &&
7602 req_oplevel != SMB2_OPLOCK_LEVEL_NONE)) {
e2f34481
NJ
7603 err = STATUS_INVALID_OPLOCK_PROTOCOL;
7604 oplock_change_type = OPLOCK_WRITE_TO_NONE;
64b39f4a
NJ
7605 } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II &&
7606 req_oplevel != SMB2_OPLOCK_LEVEL_NONE) {
e2f34481
NJ
7607 err = STATUS_INVALID_OPLOCK_PROTOCOL;
7608 oplock_change_type = OPLOCK_READ_TO_NONE;
64b39f4a
NJ
7609 } else if (req_oplevel == SMB2_OPLOCK_LEVEL_II ||
7610 req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
e2f34481 7611 err = STATUS_INVALID_DEVICE_STATE;
64b39f4a
NJ
7612 if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
7613 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
7614 req_oplevel == SMB2_OPLOCK_LEVEL_II) {
e2f34481 7615 oplock_change_type = OPLOCK_WRITE_TO_READ;
64b39f4a
NJ
7616 } else if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
7617 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
7618 req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
e2f34481 7619 oplock_change_type = OPLOCK_WRITE_TO_NONE;
64b39f4a
NJ
7620 } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II &&
7621 req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
e2f34481 7622 oplock_change_type = OPLOCK_READ_TO_NONE;
64b39f4a 7623 } else {
e2f34481 7624 oplock_change_type = 0;
64b39f4a
NJ
7625 }
7626 } else {
e2f34481 7627 oplock_change_type = 0;
64b39f4a 7628 }
e2f34481
NJ
7629
7630 switch (oplock_change_type) {
7631 case OPLOCK_WRITE_TO_READ:
7632 ret = opinfo_write_to_read(opinfo);
7633 rsp_oplevel = SMB2_OPLOCK_LEVEL_II;
7634 break;
7635 case OPLOCK_WRITE_TO_NONE:
7636 ret = opinfo_write_to_none(opinfo);
7637 rsp_oplevel = SMB2_OPLOCK_LEVEL_NONE;
7638 break;
7639 case OPLOCK_READ_TO_NONE:
7640 ret = opinfo_read_to_none(opinfo);
7641 rsp_oplevel = SMB2_OPLOCK_LEVEL_NONE;
7642 break;
7643 default:
bde1694a
NJ
7644 pr_err("unknown oplock change 0x%x -> 0x%x\n",
7645 opinfo->level, rsp_oplevel);
e2f34481
NJ
7646 }
7647
7648 if (ret < 0) {
7649 rsp->hdr.Status = err;
7650 goto err_out;
7651 }
7652
7653 opinfo_put(opinfo);
7654 ksmbd_fd_put(work, fp);
7655 opinfo->op_state = OPLOCK_STATE_NONE;
7656 wake_up_interruptible_all(&opinfo->oplock_q);
7657
7658 rsp->StructureSize = cpu_to_le16(24);
7659 rsp->OplockLevel = rsp_oplevel;
7660 rsp->Reserved = 0;
7661 rsp->Reserved2 = 0;
7662 rsp->VolatileFid = cpu_to_le64(volatile_id);
7663 rsp->PersistentFid = cpu_to_le64(persistent_id);
7664 inc_rfc1001_len(rsp, 24);
7665 return;
7666
7667err_out:
7668 opinfo->op_state = OPLOCK_STATE_NONE;
7669 wake_up_interruptible_all(&opinfo->oplock_q);
7670
7671 opinfo_put(opinfo);
7672 ksmbd_fd_put(work, fp);
7673 smb2_set_err_rsp(work);
7674}
7675
7676static int check_lease_state(struct lease *lease, __le32 req_state)
7677{
7678 if ((lease->new_state ==
64b39f4a
NJ
7679 (SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE)) &&
7680 !(req_state & SMB2_LEASE_WRITE_CACHING_LE)) {
e2f34481
NJ
7681 lease->new_state = req_state;
7682 return 0;
7683 }
7684
7685 if (lease->new_state == req_state)
7686 return 0;
7687
7688 return 1;
7689}
7690
7691/**
7692 * smb21_lease_break_ack() - handler for smb2.1 lease break command
7693 * @work: smb work containing lease break command buffer
7694 *
7695 * Return: 0
7696 */
7697static void smb21_lease_break_ack(struct ksmbd_work *work)
7698{
7699 struct ksmbd_conn *conn = work->conn;
e5066499
NJ
7700 struct smb2_lease_ack *req = work->request_buf;
7701 struct smb2_lease_ack *rsp = work->response_buf;
e2f34481
NJ
7702 struct oplock_info *opinfo;
7703 __le32 err = 0;
7704 int ret = 0;
7705 unsigned int lease_change_type;
7706 __le32 lease_state;
7707 struct lease *lease;
7708
7709 ksmbd_debug(OPLOCK, "smb21 lease break, lease state(0x%x)\n",
070fb21e 7710 le32_to_cpu(req->LeaseState));
e2f34481
NJ
7711 opinfo = lookup_lease_in_table(conn, req->LeaseKey);
7712 if (!opinfo) {
7713 ksmbd_debug(OPLOCK, "file not opened\n");
7714 smb2_set_err_rsp(work);
7715 rsp->hdr.Status = STATUS_UNSUCCESSFUL;
7716 return;
7717 }
7718 lease = opinfo->o_lease;
7719
7720 if (opinfo->op_state == OPLOCK_STATE_NONE) {
bde1694a
NJ
7721 pr_err("unexpected lease break state 0x%x\n",
7722 opinfo->op_state);
e2f34481
NJ
7723 rsp->hdr.Status = STATUS_UNSUCCESSFUL;
7724 goto err_out;
7725 }
7726
7727 if (check_lease_state(lease, req->LeaseState)) {
7728 rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
7729 ksmbd_debug(OPLOCK,
070fb21e
NJ
7730 "req lease state: 0x%x, expected state: 0x%x\n",
7731 req->LeaseState, lease->new_state);
e2f34481
NJ
7732 goto err_out;
7733 }
7734
7735 if (!atomic_read(&opinfo->breaking_cnt)) {
7736 rsp->hdr.Status = STATUS_UNSUCCESSFUL;
7737 goto err_out;
7738 }
7739
7740 /* check for bad lease state */
070fb21e
NJ
7741 if (req->LeaseState &
7742 (~(SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE))) {
e2f34481
NJ
7743 err = STATUS_INVALID_OPLOCK_PROTOCOL;
7744 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
7745 lease_change_type = OPLOCK_WRITE_TO_NONE;
7746 else
7747 lease_change_type = OPLOCK_READ_TO_NONE;
7748 ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n",
070fb21e
NJ
7749 le32_to_cpu(lease->state),
7750 le32_to_cpu(req->LeaseState));
64b39f4a
NJ
7751 } else if (lease->state == SMB2_LEASE_READ_CACHING_LE &&
7752 req->LeaseState != SMB2_LEASE_NONE_LE) {
e2f34481
NJ
7753 err = STATUS_INVALID_OPLOCK_PROTOCOL;
7754 lease_change_type = OPLOCK_READ_TO_NONE;
7755 ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n",
070fb21e
NJ
7756 le32_to_cpu(lease->state),
7757 le32_to_cpu(req->LeaseState));
e2f34481
NJ
7758 } else {
7759 /* valid lease state changes */
7760 err = STATUS_INVALID_DEVICE_STATE;
7761 if (req->LeaseState == SMB2_LEASE_NONE_LE) {
7762 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
7763 lease_change_type = OPLOCK_WRITE_TO_NONE;
7764 else
7765 lease_change_type = OPLOCK_READ_TO_NONE;
7766 } else if (req->LeaseState & SMB2_LEASE_READ_CACHING_LE) {
7767 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
7768 lease_change_type = OPLOCK_WRITE_TO_READ;
7769 else
7770 lease_change_type = OPLOCK_READ_HANDLE_TO_READ;
64b39f4a 7771 } else {
e2f34481 7772 lease_change_type = 0;
64b39f4a 7773 }
e2f34481
NJ
7774 }
7775
7776 switch (lease_change_type) {
7777 case OPLOCK_WRITE_TO_READ:
7778 ret = opinfo_write_to_read(opinfo);
7779 break;
7780 case OPLOCK_READ_HANDLE_TO_READ:
7781 ret = opinfo_read_handle_to_read(opinfo);
7782 break;
7783 case OPLOCK_WRITE_TO_NONE:
7784 ret = opinfo_write_to_none(opinfo);
7785 break;
7786 case OPLOCK_READ_TO_NONE:
7787 ret = opinfo_read_to_none(opinfo);
7788 break;
7789 default:
7790 ksmbd_debug(OPLOCK, "unknown lease change 0x%x -> 0x%x\n",
070fb21e
NJ
7791 le32_to_cpu(lease->state),
7792 le32_to_cpu(req->LeaseState));
e2f34481
NJ
7793 }
7794
7795 lease_state = lease->state;
7796 opinfo->op_state = OPLOCK_STATE_NONE;
7797 wake_up_interruptible_all(&opinfo->oplock_q);
7798 atomic_dec(&opinfo->breaking_cnt);
7799 wake_up_interruptible_all(&opinfo->oplock_brk);
7800 opinfo_put(opinfo);
7801
7802 if (ret < 0) {
7803 rsp->hdr.Status = err;
7804 goto err_out;
7805 }
7806
7807 rsp->StructureSize = cpu_to_le16(36);
7808 rsp->Reserved = 0;
7809 rsp->Flags = 0;
7810 memcpy(rsp->LeaseKey, req->LeaseKey, 16);
7811 rsp->LeaseState = lease_state;
7812 rsp->LeaseDuration = 0;
7813 inc_rfc1001_len(rsp, 36);
7814 return;
7815
7816err_out:
7817 opinfo->op_state = OPLOCK_STATE_NONE;
7818 wake_up_interruptible_all(&opinfo->oplock_q);
7819 atomic_dec(&opinfo->breaking_cnt);
7820 wake_up_interruptible_all(&opinfo->oplock_brk);
7821
7822 opinfo_put(opinfo);
7823 smb2_set_err_rsp(work);
7824}
7825
7826/**
7827 * smb2_oplock_break() - dispatcher for smb2.0 and 2.1 oplock/lease break
7828 * @work: smb work containing oplock/lease break command buffer
7829 *
7830 * Return: 0
7831 */
7832int smb2_oplock_break(struct ksmbd_work *work)
7833{
e5066499
NJ
7834 struct smb2_oplock_break *req = work->request_buf;
7835 struct smb2_oplock_break *rsp = work->response_buf;
e2f34481
NJ
7836
7837 switch (le16_to_cpu(req->StructureSize)) {
7838 case OP_BREAK_STRUCT_SIZE_20:
7839 smb20_oplock_break_ack(work);
7840 break;
7841 case OP_BREAK_STRUCT_SIZE_21:
7842 smb21_lease_break_ack(work);
7843 break;
7844 default:
7845 ksmbd_debug(OPLOCK, "invalid break cmd %d\n",
070fb21e 7846 le16_to_cpu(req->StructureSize));
e2f34481
NJ
7847 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
7848 smb2_set_err_rsp(work);
7849 }
7850
7851 return 0;
7852}
7853
7854/**
7855 * smb2_notify() - handler for smb2 notify request
95fa1ce9 7856 * @work: smb work containing notify command buffer
e2f34481
NJ
7857 *
7858 * Return: 0
7859 */
7860int smb2_notify(struct ksmbd_work *work)
7861{
7862 struct smb2_notify_req *req;
7863 struct smb2_notify_rsp *rsp;
7864
7865 WORK_BUFFERS(work, req, rsp);
7866
7867 if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) {
7868 rsp->hdr.Status = STATUS_INTERNAL_ERROR;
7869 smb2_set_err_rsp(work);
7870 return 0;
7871 }
7872
7873 smb2_set_err_rsp(work);
7874 rsp->hdr.Status = STATUS_NOT_IMPLEMENTED;
7875 return 0;
7876}
7877
7878/**
7879 * smb2_is_sign_req() - handler for checking packet signing status
95fa1ce9
HL
7880 * @work: smb work containing notify command buffer
7881 * @command: SMB2 command id
e2f34481
NJ
7882 *
7883 * Return: true if packed is signed, false otherwise
7884 */
7885bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
7886{
e5066499 7887 struct smb2_hdr *rcv_hdr2 = work->request_buf;
e2f34481
NJ
7888
7889 if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) &&
64b39f4a
NJ
7890 command != SMB2_NEGOTIATE_HE &&
7891 command != SMB2_SESSION_SETUP_HE &&
7892 command != SMB2_OPLOCK_BREAK_HE)
e2f34481
NJ
7893 return true;
7894
5616015f 7895 return false;
e2f34481
NJ
7896}
7897
7898/**
7899 * smb2_check_sign_req() - handler for req packet sign processing
7900 * @work: smb work containing notify command buffer
7901 *
7902 * Return: 1 on success, 0 otherwise
7903 */
7904int smb2_check_sign_req(struct ksmbd_work *work)
7905{
7906 struct smb2_hdr *hdr, *hdr_org;
7907 char signature_req[SMB2_SIGNATURE_SIZE];
7908 char signature[SMB2_HMACSHA256_SIZE];
7909 struct kvec iov[1];
7910 size_t len;
7911
e5066499 7912 hdr_org = hdr = work->request_buf;
e2f34481 7913 if (work->next_smb2_rcv_hdr_off)
8a893315 7914 hdr = ksmbd_req_buf_next(work);
e2f34481
NJ
7915
7916 if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
7917 len = be32_to_cpu(hdr_org->smb2_buf_length);
7918 else if (hdr->NextCommand)
7919 len = le32_to_cpu(hdr->NextCommand);
7920 else
7921 len = be32_to_cpu(hdr_org->smb2_buf_length) -
7922 work->next_smb2_rcv_hdr_off;
7923
7924 memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
7925 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
7926
7927 iov[0].iov_base = (char *)&hdr->ProtocolId;
7928 iov[0].iov_len = len;
7929
7930 if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
64b39f4a 7931 signature))
e2f34481
NJ
7932 return 0;
7933
7934 if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
bde1694a 7935 pr_err("bad smb2 signature\n");
e2f34481
NJ
7936 return 0;
7937 }
7938
7939 return 1;
7940}
7941
7942/**
7943 * smb2_set_sign_rsp() - handler for rsp packet sign processing
7944 * @work: smb work containing notify command buffer
7945 *
7946 */
7947void smb2_set_sign_rsp(struct ksmbd_work *work)
7948{
7949 struct smb2_hdr *hdr, *hdr_org;
7950 struct smb2_hdr *req_hdr;
7951 char signature[SMB2_HMACSHA256_SIZE];
7952 struct kvec iov[2];
7953 size_t len;
7954 int n_vec = 1;
7955
e5066499 7956 hdr_org = hdr = work->response_buf;
e2f34481 7957 if (work->next_smb2_rsp_hdr_off)
8a893315 7958 hdr = ksmbd_resp_buf_next(work);
e2f34481 7959
8a893315 7960 req_hdr = ksmbd_req_buf_next(work);
e2f34481
NJ
7961
7962 if (!work->next_smb2_rsp_hdr_off) {
7963 len = get_rfc1002_len(hdr_org);
7964 if (req_hdr->NextCommand)
7965 len = ALIGN(len, 8);
7966 } else {
7967 len = get_rfc1002_len(hdr_org) - work->next_smb2_rsp_hdr_off;
7968 len = ALIGN(len, 8);
7969 }
7970
7971 if (req_hdr->NextCommand)
7972 hdr->NextCommand = cpu_to_le32(len);
7973
7974 hdr->Flags |= SMB2_FLAGS_SIGNED;
7975 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
7976
7977 iov[0].iov_base = (char *)&hdr->ProtocolId;
7978 iov[0].iov_len = len;
7979
e5066499
NJ
7980 if (work->aux_payload_sz) {
7981 iov[0].iov_len -= work->aux_payload_sz;
e2f34481 7982
e5066499
NJ
7983 iov[1].iov_base = work->aux_payload_buf;
7984 iov[1].iov_len = work->aux_payload_sz;
e2f34481
NJ
7985 n_vec++;
7986 }
7987
7988 if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
64b39f4a 7989 signature))
e2f34481
NJ
7990 memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
7991}
7992
7993/**
7994 * smb3_check_sign_req() - handler for req packet sign processing
7995 * @work: smb work containing notify command buffer
7996 *
7997 * Return: 1 on success, 0 otherwise
7998 */
7999int smb3_check_sign_req(struct ksmbd_work *work)
8000{
f5a544e3 8001 struct ksmbd_conn *conn = work->conn;
e2f34481
NJ
8002 char *signing_key;
8003 struct smb2_hdr *hdr, *hdr_org;
8004 struct channel *chann;
8005 char signature_req[SMB2_SIGNATURE_SIZE];
8006 char signature[SMB2_CMACAES_SIZE];
8007 struct kvec iov[1];
8008 size_t len;
8009
e5066499 8010 hdr_org = hdr = work->request_buf;
e2f34481 8011 if (work->next_smb2_rcv_hdr_off)
8a893315 8012 hdr = ksmbd_req_buf_next(work);
e2f34481
NJ
8013
8014 if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
8015 len = be32_to_cpu(hdr_org->smb2_buf_length);
8016 else if (hdr->NextCommand)
8017 len = le32_to_cpu(hdr->NextCommand);
8018 else
8019 len = be32_to_cpu(hdr_org->smb2_buf_length) -
8020 work->next_smb2_rcv_hdr_off;
8021
8022 if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
8023 signing_key = work->sess->smb3signingkey;
e2f34481 8024 } else {
f5a544e3 8025 chann = lookup_chann_list(work->sess, conn);
e2f34481
NJ
8026 if (!chann)
8027 return 0;
8028 signing_key = chann->smb3signingkey;
e2f34481
NJ
8029 }
8030
8031 if (!signing_key) {
bde1694a 8032 pr_err("SMB3 signing key is not generated\n");
e2f34481
NJ
8033 return 0;
8034 }
8035
8036 memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
8037 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
8038 iov[0].iov_base = (char *)&hdr->ProtocolId;
8039 iov[0].iov_len = len;
8040
8041 if (ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature))
8042 return 0;
8043
8044 if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
bde1694a 8045 pr_err("bad smb2 signature\n");
e2f34481
NJ
8046 return 0;
8047 }
8048
8049 return 1;
8050}
8051
8052/**
8053 * smb3_set_sign_rsp() - handler for rsp packet sign processing
8054 * @work: smb work containing notify command buffer
8055 *
8056 */
8057void smb3_set_sign_rsp(struct ksmbd_work *work)
8058{
f5a544e3 8059 struct ksmbd_conn *conn = work->conn;
e2f34481
NJ
8060 struct smb2_hdr *req_hdr;
8061 struct smb2_hdr *hdr, *hdr_org;
8062 struct channel *chann;
8063 char signature[SMB2_CMACAES_SIZE];
8064 struct kvec iov[2];
8065 int n_vec = 1;
8066 size_t len;
8067 char *signing_key;
8068
e5066499 8069 hdr_org = hdr = work->response_buf;
e2f34481 8070 if (work->next_smb2_rsp_hdr_off)
8a893315 8071 hdr = ksmbd_resp_buf_next(work);
e2f34481 8072
8a893315 8073 req_hdr = ksmbd_req_buf_next(work);
e2f34481
NJ
8074
8075 if (!work->next_smb2_rsp_hdr_off) {
8076 len = get_rfc1002_len(hdr_org);
8077 if (req_hdr->NextCommand)
8078 len = ALIGN(len, 8);
8079 } else {
8080 len = get_rfc1002_len(hdr_org) - work->next_smb2_rsp_hdr_off;
8081 len = ALIGN(len, 8);
8082 }
8083
8084 if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
8085 signing_key = work->sess->smb3signingkey;
e2f34481 8086 } else {
f5a544e3 8087 chann = lookup_chann_list(work->sess, work->conn);
e2f34481
NJ
8088 if (!chann)
8089 return;
8090 signing_key = chann->smb3signingkey;
e2f34481
NJ
8091 }
8092
8093 if (!signing_key)
8094 return;
8095
8096 if (req_hdr->NextCommand)
8097 hdr->NextCommand = cpu_to_le32(len);
8098
8099 hdr->Flags |= SMB2_FLAGS_SIGNED;
8100 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
8101 iov[0].iov_base = (char *)&hdr->ProtocolId;
8102 iov[0].iov_len = len;
e5066499
NJ
8103 if (work->aux_payload_sz) {
8104 iov[0].iov_len -= work->aux_payload_sz;
8105 iov[1].iov_base = work->aux_payload_buf;
8106 iov[1].iov_len = work->aux_payload_sz;
e2f34481
NJ
8107 n_vec++;
8108 }
8109
8110 if (!ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec, signature))
8111 memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
8112}
8113
8114/**
8115 * smb3_preauth_hash_rsp() - handler for computing preauth hash on response
8116 * @work: smb work containing response buffer
8117 *
8118 */
8119void smb3_preauth_hash_rsp(struct ksmbd_work *work)
8120{
8121 struct ksmbd_conn *conn = work->conn;
8122 struct ksmbd_session *sess = work->sess;
8123 struct smb2_hdr *req, *rsp;
8124
8125 if (conn->dialect != SMB311_PROT_ID)
8126 return;
8127
8128 WORK_BUFFERS(work, req, rsp);
8129
8130 if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE)
8131 ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
070fb21e 8132 conn->preauth_info->Preauth_HashValue);
e2f34481 8133
f5a544e3 8134 if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) {
e2f34481
NJ
8135 __u8 *hash_value;
8136
f5a544e3
NJ
8137 if (conn->binding) {
8138 struct preauth_session *preauth_sess;
8139
8140 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
8141 if (!preauth_sess)
8142 return;
8143 hash_value = preauth_sess->Preauth_HashValue;
8144 } else {
8145 hash_value = sess->Preauth_HashValue;
8146 if (!hash_value)
8147 return;
8148 }
e2f34481 8149 ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
070fb21e 8150 hash_value);
e2f34481
NJ
8151 }
8152}
8153
64b39f4a 8154static void fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, char *old_buf,
070fb21e 8155 __le16 cipher_type)
e2f34481
NJ
8156{
8157 struct smb2_hdr *hdr = (struct smb2_hdr *)old_buf;
8158 unsigned int orig_len = get_rfc1002_len(old_buf);
8159
8160 memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
8161 tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
8162 tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
8163 tr_hdr->Flags = cpu_to_le16(0x01);
5a0ca770
NJ
8164 if (cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
8165 cipher_type == SMB2_ENCRYPTION_AES256_GCM)
8166 get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
e2f34481 8167 else
5a0ca770 8168 get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
e2f34481
NJ
8169 memcpy(&tr_hdr->SessionId, &hdr->SessionId, 8);
8170 inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - 4);
8171 inc_rfc1001_len(tr_hdr, orig_len);
8172}
8173
8174int smb3_encrypt_resp(struct ksmbd_work *work)
8175{
e5066499 8176 char *buf = work->response_buf;
e2f34481
NJ
8177 struct smb2_transform_hdr *tr_hdr;
8178 struct kvec iov[3];
8179 int rc = -ENOMEM;
e5066499 8180 int buf_size = 0, rq_nvec = 2 + (work->aux_payload_sz ? 1 : 0);
e2f34481
NJ
8181
8182 if (ARRAY_SIZE(iov) < rq_nvec)
8183 return -ENOMEM;
8184
20ea7fd2 8185 tr_hdr = kzalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
e2f34481
NJ
8186 if (!tr_hdr)
8187 return rc;
8188
8189 /* fill transform header */
8190 fill_transform_hdr(tr_hdr, buf, work->conn->cipher_type);
8191
8192 iov[0].iov_base = tr_hdr;
8193 iov[0].iov_len = sizeof(struct smb2_transform_hdr);
8194 buf_size += iov[0].iov_len - 4;
8195
8196 iov[1].iov_base = buf + 4;
8197 iov[1].iov_len = get_rfc1002_len(buf);
e5066499
NJ
8198 if (work->aux_payload_sz) {
8199 iov[1].iov_len = work->resp_hdr_sz - 4;
e2f34481 8200
e5066499
NJ
8201 iov[2].iov_base = work->aux_payload_buf;
8202 iov[2].iov_len = work->aux_payload_sz;
e2f34481
NJ
8203 buf_size += iov[2].iov_len;
8204 }
8205 buf_size += iov[1].iov_len;
8206 work->resp_hdr_sz = iov[1].iov_len;
8207
8208 rc = ksmbd_crypt_message(work->conn, iov, rq_nvec, 1);
8209 if (rc)
8210 return rc;
8211
8212 memmove(buf, iov[1].iov_base, iov[1].iov_len);
8213 tr_hdr->smb2_buf_length = cpu_to_be32(buf_size);
8214 work->tr_buf = tr_hdr;
8215
8216 return rc;
8217}
8218
8219int smb3_is_transform_hdr(void *buf)
8220{
8221 struct smb2_transform_hdr *trhdr = buf;
8222
8223 return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
8224}
8225
8226int smb3_decrypt_req(struct ksmbd_work *work)
8227{
8228 struct ksmbd_conn *conn = work->conn;
8229 struct ksmbd_session *sess;
e5066499 8230 char *buf = work->request_buf;
e2f34481
NJ
8231 struct smb2_hdr *hdr;
8232 unsigned int pdu_length = get_rfc1002_len(buf);
8233 struct kvec iov[2];
8234 unsigned int buf_data_size = pdu_length + 4 -
8235 sizeof(struct smb2_transform_hdr);
8236 struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
8237 unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
8238 int rc = 0;
8239
f5a544e3 8240 sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId));
e2f34481 8241 if (!sess) {
bde1694a
NJ
8242 pr_err("invalid session id(%llx) in transform header\n",
8243 le64_to_cpu(tr_hdr->SessionId));
e2f34481
NJ
8244 return -ECONNABORTED;
8245 }
8246
070fb21e
NJ
8247 if (pdu_length + 4 <
8248 sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr)) {
bde1694a
NJ
8249 pr_err("Transform message is too small (%u)\n",
8250 pdu_length);
e2f34481
NJ
8251 return -ECONNABORTED;
8252 }
8253
8254 if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) {
bde1694a 8255 pr_err("Transform message is broken\n");
e2f34481
NJ
8256 return -ECONNABORTED;
8257 }
8258
8259 iov[0].iov_base = buf;
8260 iov[0].iov_len = sizeof(struct smb2_transform_hdr);
8261 iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
8262 iov[1].iov_len = buf_data_size;
8263 rc = ksmbd_crypt_message(conn, iov, 2, 0);
8264 if (rc)
8265 return rc;
8266
8267 memmove(buf + 4, iov[1].iov_base, buf_data_size);
8268 hdr = (struct smb2_hdr *)buf;
8269 hdr->smb2_buf_length = cpu_to_be32(buf_data_size);
8270
8271 return rc;
8272}
8273
8274bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
8275{
8276 struct ksmbd_conn *conn = work->conn;
e5066499 8277 struct smb2_hdr *rsp = work->response_buf;
e2f34481
NJ
8278
8279 if (conn->dialect < SMB30_PROT_ID)
8280 return false;
8281
8282 if (work->next_smb2_rcv_hdr_off)
8a893315 8283 rsp = ksmbd_resp_buf_next(work);
e2f34481
NJ
8284
8285 if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE &&
64b39f4a 8286 rsp->Status == STATUS_SUCCESS)
e2f34481
NJ
8287 return true;
8288 return false;
8289}