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