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