Lines Matching +full:tcon +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0-or-later
45 if (work->next_smb2_rcv_hdr_off) { in __wbuf()
49 *req = smb2_get_msg(work->request_buf); in __wbuf()
50 *rsp = smb2_get_msg(work->response_buf); in __wbuf()
57 * check_session_id() - check for valid session id in smb header
67 if (id == 0 || id == -1) in check_session_id()
79 struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn) in lookup_chann_list()
81 return xa_load(&sess->ksmbd_chann_list, (long)conn); in lookup_chann_list()
85 * smb2_get_ksmbd_tcon() - get tree connection information using a tree id.
94 unsigned int cmd = le16_to_cpu(req_hdr->Command); in smb2_get_ksmbd_tcon()
104 if (xa_empty(&work->sess->tree_conns)) { in smb2_get_ksmbd_tcon()
106 return -ENOENT; in smb2_get_ksmbd_tcon()
109 tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId); in smb2_get_ksmbd_tcon()
113 * Just validate tree id in header with work->tcon->id. in smb2_get_ksmbd_tcon()
115 if (work->next_smb2_rcv_hdr_off) { in smb2_get_ksmbd_tcon()
116 if (!work->tcon) { in smb2_get_ksmbd_tcon()
117 pr_err("The first operation in the compound does not have tcon\n"); in smb2_get_ksmbd_tcon()
118 return -EINVAL; in smb2_get_ksmbd_tcon()
120 if (tree_id != UINT_MAX && work->tcon->id != tree_id) { in smb2_get_ksmbd_tcon()
122 tree_id, work->tcon->id); in smb2_get_ksmbd_tcon()
123 return -EINVAL; in smb2_get_ksmbd_tcon()
128 work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id); in smb2_get_ksmbd_tcon()
129 if (!work->tcon) { in smb2_get_ksmbd_tcon()
131 return -ENOENT; in smb2_get_ksmbd_tcon()
138 * smb2_set_err_rsp() - set error response code on smb response
145 if (work->next_smb2_rcv_hdr_off) in smb2_set_err_rsp()
148 err_rsp = smb2_get_msg(work->response_buf); in smb2_set_err_rsp()
150 if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) { in smb2_set_err_rsp()
153 err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE; in smb2_set_err_rsp()
154 err_rsp->ErrorContextCount = 0; in smb2_set_err_rsp()
155 err_rsp->Reserved = 0; in smb2_set_err_rsp()
156 err_rsp->ByteCount = 0; in smb2_set_err_rsp()
157 err_rsp->ErrorData[0] = 0; in smb2_set_err_rsp()
162 work->send_no_response = 1; in smb2_set_err_rsp()
167 * is_smb2_neg_cmd() - is it smb2 negotiation command
174 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in is_smb2_neg_cmd()
177 if (hdr->ProtocolId != SMB2_PROTO_NUMBER) in is_smb2_neg_cmd()
181 if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) in is_smb2_neg_cmd()
184 if (hdr->Command != SMB2_NEGOTIATE) in is_smb2_neg_cmd()
191 * is_smb2_rsp() - is it smb2 response
198 struct smb2_hdr *hdr = smb2_get_msg(work->response_buf); in is_smb2_rsp()
201 if (hdr->ProtocolId != SMB2_PROTO_NUMBER) in is_smb2_rsp()
205 if (!(hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)) in is_smb2_rsp()
212 * get_smb2_cmd_val() - get smb command code from smb header
221 if (work->next_smb2_rcv_hdr_off) in get_smb2_cmd_val()
224 rcv_hdr = smb2_get_msg(work->request_buf); in get_smb2_cmd_val()
225 return le16_to_cpu(rcv_hdr->Command); in get_smb2_cmd_val()
229 * set_smb2_rsp_status() - set error response code on smb2 header
237 rsp_hdr = smb2_get_msg(work->response_buf); in set_smb2_rsp_status()
238 rsp_hdr->Status = err; in set_smb2_rsp_status()
240 work->iov_idx = 0; in set_smb2_rsp_status()
241 work->iov_cnt = 0; in set_smb2_rsp_status()
242 work->next_smb2_rcv_hdr_off = 0; in set_smb2_rsp_status()
247 * init_smb2_neg_rsp() - initialize smb2 response for negotiate command
251 * dialect auto-negotiation.
257 struct ksmbd_conn *conn = work->conn; in init_smb2_neg_rsp()
260 rsp_hdr = smb2_get_msg(work->response_buf); in init_smb2_neg_rsp()
262 rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER; in init_smb2_neg_rsp()
263 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; in init_smb2_neg_rsp()
264 rsp_hdr->CreditRequest = cpu_to_le16(2); in init_smb2_neg_rsp()
265 rsp_hdr->Command = SMB2_NEGOTIATE; in init_smb2_neg_rsp()
266 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR); in init_smb2_neg_rsp()
267 rsp_hdr->NextCommand = 0; in init_smb2_neg_rsp()
268 rsp_hdr->MessageId = 0; in init_smb2_neg_rsp()
269 rsp_hdr->Id.SyncId.ProcessId = 0; in init_smb2_neg_rsp()
270 rsp_hdr->Id.SyncId.TreeId = 0; in init_smb2_neg_rsp()
271 rsp_hdr->SessionId = 0; in init_smb2_neg_rsp()
272 memset(rsp_hdr->Signature, 0, 16); in init_smb2_neg_rsp()
274 rsp = smb2_get_msg(work->response_buf); in init_smb2_neg_rsp()
278 rsp->StructureSize = cpu_to_le16(65); in init_smb2_neg_rsp()
279 ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect); in init_smb2_neg_rsp()
280 rsp->DialectRevision = cpu_to_le16(conn->dialect); in init_smb2_neg_rsp()
281 /* Not setting conn guid rsp->ServerGUID, as it in init_smb2_neg_rsp()
284 rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); in init_smb2_neg_rsp()
286 rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size); in init_smb2_neg_rsp()
287 rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size); in init_smb2_neg_rsp()
288 rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size); in init_smb2_neg_rsp()
290 rsp->SystemTime = cpu_to_le64(ksmbd_systime()); in init_smb2_neg_rsp()
291 rsp->ServerStartTime = 0; in init_smb2_neg_rsp()
293 rsp->SecurityBufferOffset = cpu_to_le16(128); in init_smb2_neg_rsp()
294 rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH); in init_smb2_neg_rsp()
295 ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) + in init_smb2_neg_rsp()
296 le16_to_cpu(rsp->SecurityBufferOffset)); in init_smb2_neg_rsp()
297 rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE; in init_smb2_neg_rsp()
299 rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE; in init_smb2_neg_rsp()
304 conn->use_spnego = true; in init_smb2_neg_rsp()
311 * smb2_set_rsp_credits() - set number of credits in response buffer
318 struct ksmbd_conn *conn = work->conn; in smb2_set_rsp_credits()
322 if (work->send_no_response) in smb2_set_rsp_credits()
325 hdr->CreditCharge = req_hdr->CreditCharge; in smb2_set_rsp_credits()
327 if (conn->total_credits > conn->vals->max_credits) { in smb2_set_rsp_credits()
328 hdr->CreditRequest = 0; in smb2_set_rsp_credits()
329 pr_err("Total credits overflow: %d\n", conn->total_credits); in smb2_set_rsp_credits()
330 return -EINVAL; in smb2_set_rsp_credits()
334 le16_to_cpu(req_hdr->CreditCharge), 1); in smb2_set_rsp_credits()
335 if (credit_charge > conn->total_credits) { in smb2_set_rsp_credits()
337 credit_charge, conn->total_credits); in smb2_set_rsp_credits()
338 return -EINVAL; in smb2_set_rsp_credits()
341 conn->total_credits -= credit_charge; in smb2_set_rsp_credits()
342 conn->outstanding_credits -= credit_charge; in smb2_set_rsp_credits()
344 le16_to_cpu(req_hdr->CreditRequest), 1); in smb2_set_rsp_credits()
352 if (hdr->Command == SMB2_NEGOTIATE) in smb2_set_rsp_credits()
355 aux_max = conn->vals->max_credits - conn->total_credits; in smb2_set_rsp_credits()
358 conn->total_credits += credits_granted; in smb2_set_rsp_credits()
359 work->credits_granted += credits_granted; in smb2_set_rsp_credits()
361 if (!req_hdr->NextCommand) { in smb2_set_rsp_credits()
363 hdr->CreditRequest = cpu_to_le16(work->credits_granted); in smb2_set_rsp_credits()
368 conn->total_credits); in smb2_set_rsp_credits()
373 * init_chained_smb2_rsp() - initialize smb2 chained response
385 /* Len of this response = updated RFC len - offset of previous cmd in init_chained_smb2_rsp()
392 if (req->Command == SMB2_CREATE && rsp->Status == STATUS_SUCCESS) { in init_chained_smb2_rsp()
393 work->compound_fid = ((struct smb2_create_rsp *)rsp)->VolatileFileId; in init_chained_smb2_rsp()
394 work->compound_pfid = ((struct smb2_create_rsp *)rsp)->PersistentFileId; in init_chained_smb2_rsp()
395 work->compound_sid = le64_to_cpu(rsp->SessionId); in init_chained_smb2_rsp()
398 len = get_rfc1002_len(work->response_buf) - work->next_smb2_rsp_hdr_off; in init_chained_smb2_rsp()
399 next_hdr_offset = le32_to_cpu(req->NextCommand); in init_chained_smb2_rsp()
402 work->iov[work->iov_idx].iov_len += (new_len - len); in init_chained_smb2_rsp()
403 inc_rfc1001_len(work->response_buf, new_len - len); in init_chained_smb2_rsp()
404 rsp->NextCommand = cpu_to_le32(new_len); in init_chained_smb2_rsp()
406 work->next_smb2_rcv_hdr_off += next_hdr_offset; in init_chained_smb2_rsp()
407 work->curr_smb2_rsp_hdr_off = work->next_smb2_rsp_hdr_off; in init_chained_smb2_rsp()
408 work->next_smb2_rsp_hdr_off += new_len; in init_chained_smb2_rsp()
411 new_len, work->next_smb2_rcv_hdr_off, in init_chained_smb2_rsp()
412 work->next_smb2_rsp_hdr_off); in init_chained_smb2_rsp()
417 if (!(rcv_hdr->Flags & SMB2_FLAGS_RELATED_OPERATIONS)) { in init_chained_smb2_rsp()
419 work->compound_fid = KSMBD_NO_FID; in init_chained_smb2_rsp()
420 work->compound_pfid = KSMBD_NO_FID; in init_chained_smb2_rsp()
423 rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER; in init_chained_smb2_rsp()
424 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; in init_chained_smb2_rsp()
425 rsp_hdr->Command = rcv_hdr->Command; in init_chained_smb2_rsp()
430 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR | in init_chained_smb2_rsp()
432 rsp_hdr->NextCommand = 0; in init_chained_smb2_rsp()
433 rsp_hdr->MessageId = rcv_hdr->MessageId; in init_chained_smb2_rsp()
434 rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId; in init_chained_smb2_rsp()
435 rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId; in init_chained_smb2_rsp()
436 rsp_hdr->SessionId = rcv_hdr->SessionId; in init_chained_smb2_rsp()
437 memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16); in init_chained_smb2_rsp()
441 * is_chained_smb2_message() - check for chained command
448 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in is_chained_smb2_message()
451 if (hdr->ProtocolId != SMB2_PROTO_NUMBER) in is_chained_smb2_message()
455 next_cmd = le32_to_cpu(hdr->NextCommand); in is_chained_smb2_message()
457 if ((u64)work->next_smb2_rcv_hdr_off + next_cmd + in is_chained_smb2_message()
459 get_rfc1002_len(work->request_buf)) { in is_chained_smb2_message()
465 if ((u64)get_rfc1002_len(work->response_buf) + MAX_CIFS_SMALL_BUFFER_SIZE > in is_chained_smb2_message()
466 work->response_sz) { in is_chained_smb2_message()
474 } else if (work->next_smb2_rcv_hdr_off) { in is_chained_smb2_message()
479 len = ALIGN(get_rfc1002_len(work->response_buf), 8); in is_chained_smb2_message()
480 len = len - get_rfc1002_len(work->response_buf); in is_chained_smb2_message()
483 work->iov[work->iov_idx].iov_len += len; in is_chained_smb2_message()
484 inc_rfc1001_len(work->response_buf, len); in is_chained_smb2_message()
486 work->curr_smb2_rsp_hdr_off = work->next_smb2_rsp_hdr_off; in is_chained_smb2_message()
492 * init_smb2_rsp_hdr() - initialize smb2 response
499 struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf); in init_smb2_rsp_hdr()
500 struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf); in init_smb2_rsp_hdr()
503 rsp_hdr->ProtocolId = rcv_hdr->ProtocolId; in init_smb2_rsp_hdr()
504 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; in init_smb2_rsp_hdr()
505 rsp_hdr->Command = rcv_hdr->Command; in init_smb2_rsp_hdr()
510 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR); in init_smb2_rsp_hdr()
511 rsp_hdr->NextCommand = 0; in init_smb2_rsp_hdr()
512 rsp_hdr->MessageId = rcv_hdr->MessageId; in init_smb2_rsp_hdr()
513 rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId; in init_smb2_rsp_hdr()
514 rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId; in init_smb2_rsp_hdr()
515 rsp_hdr->SessionId = rcv_hdr->SessionId; in init_smb2_rsp_hdr()
516 memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16); in init_smb2_rsp_hdr()
522 * smb2_allocate_rsp_buf() - allocate smb2 response buffer
529 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in smb2_allocate_rsp_buf()
531 size_t large_sz = small_sz + work->conn->vals->max_trans_size; in smb2_allocate_rsp_buf()
533 int cmd = le16_to_cpu(hdr->Command); in smb2_allocate_rsp_buf()
541 if (get_rfc1002_len(work->request_buf) < in smb2_allocate_rsp_buf()
543 return -EINVAL; in smb2_allocate_rsp_buf()
545 req = smb2_get_msg(work->request_buf); in smb2_allocate_rsp_buf()
546 if ((req->InfoType == SMB2_O_INFO_FILE && in smb2_allocate_rsp_buf()
547 (req->FileInfoClass == FILE_FULL_EA_INFORMATION || in smb2_allocate_rsp_buf()
548 req->FileInfoClass == FILE_ALL_INFORMATION)) || in smb2_allocate_rsp_buf()
549 req->InfoType == SMB2_O_INFO_SECURITY) in smb2_allocate_rsp_buf()
554 if (le32_to_cpu(hdr->NextCommand) > 0) in smb2_allocate_rsp_buf()
557 work->response_buf = kvzalloc(sz, KSMBD_DEFAULT_GFP); in smb2_allocate_rsp_buf()
558 if (!work->response_buf) in smb2_allocate_rsp_buf()
559 return -ENOMEM; in smb2_allocate_rsp_buf()
561 work->response_sz = sz; in smb2_allocate_rsp_buf()
566 * smb2_check_user_session() - check for valid session for a user
574 struct ksmbd_conn *conn = work->conn; in smb2_check_user_session()
575 unsigned int cmd = le16_to_cpu(req_hdr->Command); in smb2_check_user_session()
588 return -EIO; in smb2_check_user_session()
590 sess_id = le64_to_cpu(req_hdr->SessionId); in smb2_check_user_session()
594 * Just validate session id in header with work->sess->id. in smb2_check_user_session()
596 if (work->next_smb2_rcv_hdr_off) { in smb2_check_user_session()
597 if (!work->sess) { in smb2_check_user_session()
599 return -EINVAL; in smb2_check_user_session()
601 if (sess_id != ULLONG_MAX && work->sess->id != sess_id) { in smb2_check_user_session()
603 sess_id, work->sess->id); in smb2_check_user_session()
604 return -EINVAL; in smb2_check_user_session()
610 work->sess = ksmbd_session_lookup_all(conn, sess_id); in smb2_check_user_session()
611 if (work->sess) in smb2_check_user_session()
614 return -ENOENT; in smb2_check_user_session()
618 * smb2_get_name() - get filename string from on the wire smb format
639 return ERR_PTR(-EINVAL); in smb2_get_name()
649 struct ksmbd_conn *conn = work->conn; in setup_async_work()
652 id = ksmbd_acquire_async_msg_id(&conn->async_ida); in setup_async_work()
657 work->asynchronous = true; in setup_async_work()
658 work->async_id = id; in setup_async_work()
662 work->async_id); in setup_async_work()
664 work->cancel_fn = fn; in setup_async_work()
665 work->cancel_argv = arg; in setup_async_work()
667 if (list_empty(&work->async_request_entry)) { in setup_async_work()
668 spin_lock(&conn->request_lock); in setup_async_work()
669 list_add_tail(&work->async_request_entry, &conn->async_requests); in setup_async_work()
670 spin_unlock(&conn->request_lock); in setup_async_work()
678 struct ksmbd_conn *conn = work->conn; in release_async_work()
680 spin_lock(&conn->request_lock); in release_async_work()
681 list_del_init(&work->async_request_entry); in release_async_work()
682 spin_unlock(&conn->request_lock); in release_async_work()
684 work->asynchronous = 0; in release_async_work()
685 work->cancel_fn = NULL; in release_async_work()
686 kfree(work->cancel_argv); in release_async_work()
687 work->cancel_argv = NULL; in release_async_work()
688 if (work->async_id) { in release_async_work()
689 ksmbd_release_id(&conn->async_ida, work->async_id); in release_async_work()
690 work->async_id = 0; in release_async_work()
708 in_work->conn = work->conn; in smb2_send_interim_resp()
709 memcpy(smb2_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work), in smb2_send_interim_resp()
712 rsp_hdr = smb2_get_msg(in_work->response_buf); in smb2_send_interim_resp()
713 rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND; in smb2_send_interim_resp()
714 rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id); in smb2_send_interim_resp()
716 rsp_hdr->Status = status; in smb2_send_interim_resp()
742 * smb2_get_dos_mode() - get file mode in dos format from unix mode
752 if (S_ISDIR(stat->mode)) { in smb2_get_dos_mode()
758 if (S_ISREG(stat->mode) && (server_conf.share_fake_fscaps & in smb2_get_dos_mode()
762 if (smb2_get_reparse_tag_special_file(stat->mode)) in smb2_get_dos_mode()
772 pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES; in build_preauth_ctxt()
773 pneg_ctxt->DataLength = cpu_to_le16(38); in build_preauth_ctxt()
774 pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1); in build_preauth_ctxt()
775 pneg_ctxt->Reserved = cpu_to_le32(0); in build_preauth_ctxt()
776 pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE); in build_preauth_ctxt()
777 get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE); in build_preauth_ctxt()
778 pneg_ctxt->HashAlgorithms = hash_id; in build_preauth_ctxt()
784 pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES; in build_encrypt_ctxt()
785 pneg_ctxt->DataLength = cpu_to_le16(4); in build_encrypt_ctxt()
786 pneg_ctxt->Reserved = cpu_to_le32(0); in build_encrypt_ctxt()
787 pneg_ctxt->CipherCount = cpu_to_le16(1); in build_encrypt_ctxt()
788 pneg_ctxt->Ciphers[0] = cipher_type; in build_encrypt_ctxt()
794 pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES; in build_sign_cap_ctxt()
795 pneg_ctxt->DataLength = in build_sign_cap_ctxt()
797 - sizeof(struct smb2_neg_context)); in build_sign_cap_ctxt()
798 pneg_ctxt->Reserved = cpu_to_le32(0); in build_sign_cap_ctxt()
799 pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(1); in build_sign_cap_ctxt()
800 pneg_ctxt->SigningAlgorithms[0] = sign_algo; in build_sign_cap_ctxt()
805 pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE; in build_posix_ctxt()
806 pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN); in build_posix_ctxt()
808 pneg_ctxt->Name[0] = 0x93; in build_posix_ctxt()
809 pneg_ctxt->Name[1] = 0xAD; in build_posix_ctxt()
810 pneg_ctxt->Name[2] = 0x25; in build_posix_ctxt()
811 pneg_ctxt->Name[3] = 0x50; in build_posix_ctxt()
812 pneg_ctxt->Name[4] = 0x9C; in build_posix_ctxt()
813 pneg_ctxt->Name[5] = 0xB4; in build_posix_ctxt()
814 pneg_ctxt->Name[6] = 0x11; in build_posix_ctxt()
815 pneg_ctxt->Name[7] = 0xE7; in build_posix_ctxt()
816 pneg_ctxt->Name[8] = 0xB4; in build_posix_ctxt()
817 pneg_ctxt->Name[9] = 0x23; in build_posix_ctxt()
818 pneg_ctxt->Name[10] = 0x83; in build_posix_ctxt()
819 pneg_ctxt->Name[11] = 0xDE; in build_posix_ctxt()
820 pneg_ctxt->Name[12] = 0x96; in build_posix_ctxt()
821 pneg_ctxt->Name[13] = 0x8B; in build_posix_ctxt()
822 pneg_ctxt->Name[14] = 0xCD; in build_posix_ctxt()
823 pneg_ctxt->Name[15] = 0x7C; in build_posix_ctxt()
830 le32_to_cpu(rsp->NegotiateContextOffset); in assemble_neg_contexts()
837 conn->preauth_info->Preauth_HashId); in assemble_neg_contexts()
840 if (conn->cipher_type) { in assemble_neg_contexts()
847 conn->cipher_type); in assemble_neg_contexts()
853 WARN_ON(conn->compress_algorithm != SMB3_COMPRESS_NONE); in assemble_neg_contexts()
855 if (conn->posix_ext_supported) { in assemble_neg_contexts()
865 if (conn->signing_negotiated) { in assemble_neg_contexts()
871 conn->signing_algorithm); in assemble_neg_contexts()
876 rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt); in assemble_neg_contexts()
892 if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512) in decode_preauth_ctxt()
895 conn->preauth_info->Preauth_HashId = SMB2_PREAUTH_INTEGRITY_SHA512; in decode_preauth_ctxt()
911 conn->cipher_type = 0; in decode_encrypt_ctxt()
913 cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount); in decode_encrypt_ctxt()
926 if (pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_GCM || in decode_encrypt_ctxt()
927 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_CCM || in decode_encrypt_ctxt()
928 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_CCM || in decode_encrypt_ctxt()
929 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_GCM) { in decode_encrypt_ctxt()
931 pneg_ctxt->Ciphers[i]); in decode_encrypt_ctxt()
932 conn->cipher_type = pneg_ctxt->Ciphers[i]; in decode_encrypt_ctxt()
939 * smb3_encryption_negotiated() - checks if server and client agreed on enabling encryption
946 if (!conn->ops->generate_encryptionkey) in smb3_encryption_negotiated()
953 return (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) || in smb3_encryption_negotiated()
954 conn->cipher_type; in smb3_encryption_negotiated()
960 conn->compress_algorithm = SMB3_COMPRESS_NONE; in decode_compress_ctxt()
975 conn->signing_negotiated = false; in decode_sign_cap_ctxt()
976 sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount); in decode_sign_cap_ctxt()
986 if (pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_HMAC_SHA256_LE || in decode_sign_cap_ctxt()
987 pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_AES_CMAC_LE) { in decode_sign_cap_ctxt()
989 pneg_ctxt->SigningAlgorithms[i]); in decode_sign_cap_ctxt()
990 conn->signing_negotiated = true; in decode_sign_cap_ctxt()
991 conn->signing_algorithm = in decode_sign_cap_ctxt()
992 pneg_ctxt->SigningAlgorithms[i]; in decode_sign_cap_ctxt()
1005 unsigned int offset = le32_to_cpu(req->NegotiateContextOffset); in deassemble_neg_contexts()
1006 unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount); in deassemble_neg_contexts()
1015 len_of_ctxts = len_of_smb - offset; in deassemble_neg_contexts()
1024 clen = le16_to_cpu(pctx->DataLength); in deassemble_neg_contexts()
1030 if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) { in deassemble_neg_contexts()
1033 if (conn->preauth_info->Preauth_HashId) in deassemble_neg_contexts()
1041 } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) { in deassemble_neg_contexts()
1044 if (conn->cipher_type) in deassemble_neg_contexts()
1050 } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) { in deassemble_neg_contexts()
1053 if (conn->compress_algorithm) in deassemble_neg_contexts()
1058 } else if (pctx->ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) { in deassemble_neg_contexts()
1061 } else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) { in deassemble_neg_contexts()
1064 conn->posix_ext_supported = true; in deassemble_neg_contexts()
1065 } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) { in deassemble_neg_contexts()
1076 len_of_ctxts -= offset; in deassemble_neg_contexts()
1082 * smb2_handle_negotiate() - handler for smb2 negotiate command
1089 struct ksmbd_conn *conn = work->conn; in smb2_handle_negotiate()
1090 struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf); in smb2_handle_negotiate()
1091 struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf); in smb2_handle_negotiate()
1097 conn->need_neg = false; in smb2_handle_negotiate()
1099 pr_err("conn->tcp_status is already in CifsGood State\n"); in smb2_handle_negotiate()
1100 work->send_no_response = 1; in smb2_handle_negotiate()
1105 smb2_buf_len = get_rfc1002_len(work->request_buf); in smb2_handle_negotiate()
1108 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1109 rc = -EINVAL; in smb2_handle_negotiate()
1113 if (req->DialectCount == 0) { in smb2_handle_negotiate()
1115 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1116 rc = -EINVAL; in smb2_handle_negotiate()
1120 if (conn->dialect == SMB311_PROT_ID) { in smb2_handle_negotiate()
1121 unsigned int nego_ctxt_off = le32_to_cpu(req->NegotiateContextOffset); in smb2_handle_negotiate()
1124 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1125 rc = -EINVAL; in smb2_handle_negotiate()
1130 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1131 rc = -EINVAL; in smb2_handle_negotiate()
1135 if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > in smb2_handle_negotiate()
1137 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1138 rc = -EINVAL; in smb2_handle_negotiate()
1142 if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > in smb2_handle_negotiate()
1144 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1145 rc = -EINVAL; in smb2_handle_negotiate()
1150 conn->cli_cap = le32_to_cpu(req->Capabilities); in smb2_handle_negotiate()
1151 switch (conn->dialect) { in smb2_handle_negotiate()
1153 conn->preauth_info = in smb2_handle_negotiate()
1156 if (!conn->preauth_info) { in smb2_handle_negotiate()
1157 rc = -ENOMEM; in smb2_handle_negotiate()
1158 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1163 get_rfc1002_len(work->request_buf)); in smb2_handle_negotiate()
1167 rsp->hdr.Status = status; in smb2_handle_negotiate()
1168 rc = -EINVAL; in smb2_handle_negotiate()
1169 kfree(conn->preauth_info); in smb2_handle_negotiate()
1170 conn->preauth_info = NULL; in smb2_handle_negotiate()
1176 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1177 kfree(conn->preauth_info); in smb2_handle_negotiate()
1178 conn->preauth_info = NULL; in smb2_handle_negotiate()
1183 work->request_buf, in smb2_handle_negotiate()
1184 conn->preauth_info->Preauth_HashValue); in smb2_handle_negotiate()
1185 rsp->NegotiateContextOffset = in smb2_handle_negotiate()
1202 conn->dialect); in smb2_handle_negotiate()
1203 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_handle_negotiate()
1204 rc = -EINVAL; in smb2_handle_negotiate()
1207 rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); in smb2_handle_negotiate()
1210 conn->connection_type = conn->dialect; in smb2_handle_negotiate()
1212 rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size); in smb2_handle_negotiate()
1213 rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size); in smb2_handle_negotiate()
1214 rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size); in smb2_handle_negotiate()
1216 memcpy(conn->ClientGUID, req->ClientGUID, in smb2_handle_negotiate()
1218 conn->cli_sec_mode = le16_to_cpu(req->SecurityMode); in smb2_handle_negotiate()
1220 rsp->StructureSize = cpu_to_le16(65); in smb2_handle_negotiate()
1221 rsp->DialectRevision = cpu_to_le16(conn->dialect); in smb2_handle_negotiate()
1222 /* Not setting conn guid rsp->ServerGUID, as it in smb2_handle_negotiate()
1225 memset(rsp->ServerGUID, 0, SMB2_CLIENT_GUID_SIZE); in smb2_handle_negotiate()
1227 rsp->SystemTime = cpu_to_le64(ksmbd_systime()); in smb2_handle_negotiate()
1228 rsp->ServerStartTime = 0; in smb2_handle_negotiate()
1230 le32_to_cpu(rsp->NegotiateContextOffset), in smb2_handle_negotiate()
1231 le16_to_cpu(rsp->NegotiateContextCount)); in smb2_handle_negotiate()
1233 rsp->SecurityBufferOffset = cpu_to_le16(128); in smb2_handle_negotiate()
1234 rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH); in smb2_handle_negotiate()
1235 ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) + in smb2_handle_negotiate()
1236 le16_to_cpu(rsp->SecurityBufferOffset)); in smb2_handle_negotiate()
1238 rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE; in smb2_handle_negotiate()
1239 conn->use_spnego = true; in smb2_handle_negotiate()
1243 req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED_LE) in smb2_handle_negotiate()
1244 conn->sign = true; in smb2_handle_negotiate()
1247 rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE; in smb2_handle_negotiate()
1248 conn->sign = true; in smb2_handle_negotiate()
1251 conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode); in smb2_handle_negotiate()
1257 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_handle_negotiate()
1271 if (sess->Preauth_HashValue) in alloc_preauth_hash()
1274 if (!conn->preauth_info) in alloc_preauth_hash()
1275 return -ENOMEM; in alloc_preauth_hash()
1277 sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue, in alloc_preauth_hash()
1279 if (!sess->Preauth_HashValue) in alloc_preauth_hash()
1280 return -ENOMEM; in alloc_preauth_hash()
1287 struct ksmbd_conn *conn = work->conn; in generate_preauth_hash()
1288 struct ksmbd_session *sess = work->sess; in generate_preauth_hash()
1291 if (conn->dialect != SMB311_PROT_ID) in generate_preauth_hash()
1294 if (conn->binding) { in generate_preauth_hash()
1297 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id); in generate_preauth_hash()
1299 preauth_sess = ksmbd_preauth_session_alloc(conn, sess->id); in generate_preauth_hash()
1301 return -ENOMEM; in generate_preauth_hash()
1304 preauth_hash = preauth_sess->Preauth_HashValue; in generate_preauth_hash()
1306 if (!sess->Preauth_HashValue) in generate_preauth_hash()
1308 return -ENOMEM; in generate_preauth_hash()
1309 preauth_hash = sess->Preauth_HashValue; in generate_preauth_hash()
1312 ksmbd_gen_preauth_integrity_hash(conn, work->request_buf, preauth_hash); in generate_preauth_hash()
1320 if (!conn->use_spnego) in decode_negotiation_token()
1321 return -EINVAL; in decode_negotiation_token()
1325 conn->auth_mechs |= KSMBD_AUTH_NTLMSSP; in decode_negotiation_token()
1326 conn->preferred_auth_mech = KSMBD_AUTH_NTLMSSP; in decode_negotiation_token()
1327 conn->use_spnego = false; in decode_negotiation_token()
1344 rc = ksmbd_decode_ntlmssp_neg_blob(negblob, negblob_len, work->conn); in ntlm_negotiate()
1348 sz = le16_to_cpu(rsp->SecurityBufferOffset); in ntlm_negotiate()
1349 chgblob = (struct challenge_message *)rsp->Buffer; in ntlm_negotiate()
1352 if (!work->conn->use_spnego) { in ntlm_negotiate()
1353 sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn); in ntlm_negotiate()
1355 return -ENOMEM; in ntlm_negotiate()
1357 rsp->SecurityBufferLength = cpu_to_le16(sz); in ntlm_negotiate()
1366 return -ENOMEM; in ntlm_negotiate()
1369 sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn); in ntlm_negotiate()
1371 rc = -ENOMEM; in ntlm_negotiate()
1378 rc = -ENOMEM; in ntlm_negotiate()
1382 memcpy(rsp->Buffer, spnego_blob, spnego_blob_len); in ntlm_negotiate()
1383 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); in ntlm_negotiate()
1396 if (conn->use_spnego && conn->mechToken) in user_authblob()
1397 return (struct authenticate_message *)conn->mechToken; in user_authblob()
1399 sz = le16_to_cpu(req->SecurityBufferOffset); in user_authblob()
1400 return (struct authenticate_message *)((char *)&req->hdr.ProtocolId in user_authblob()
1412 if (conn->use_spnego && conn->mechToken) in session_user()
1413 secbuf_len = conn->mechTokenLen; in session_user()
1415 secbuf_len = le16_to_cpu(req->SecurityBufferLength); in session_user()
1421 name_off = le32_to_cpu(authblob->UserName.BufferOffset); in session_user()
1422 name_len = le16_to_cpu(authblob->UserName.Length); in session_user()
1430 conn->local_nls); in session_user()
1446 struct ksmbd_conn *conn = work->conn; in ntlm_authenticate()
1447 struct ksmbd_session *sess = work->sess; in ntlm_authenticate()
1448 struct channel *chann = NULL; in ntlm_authenticate()
1454 if (conn->use_spnego) { in ntlm_authenticate()
1462 return -ENOMEM; in ntlm_authenticate()
1464 memcpy(rsp->Buffer, spnego_blob, spnego_blob_len); in ntlm_authenticate()
1465 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); in ntlm_authenticate()
1472 return -EPERM; in ntlm_authenticate()
1476 prev_id = le64_to_cpu(req->PreviousSessionId); in ntlm_authenticate()
1477 if (prev_id && prev_id != sess->id) in ntlm_authenticate()
1480 if (sess->state == SMB2_SESSION_VALID) { in ntlm_authenticate()
1485 if (conn->binding == false && ksmbd_anonymous_user(user)) { in ntlm_authenticate()
1490 if (!ksmbd_compare_user(sess->user, user)) { in ntlm_authenticate()
1492 return -EPERM; in ntlm_authenticate()
1496 sess->user = user; in ntlm_authenticate()
1499 if (conn->binding == false && user_guest(sess->user)) { in ntlm_authenticate()
1500 rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE; in ntlm_authenticate()
1505 if (conn->use_spnego && conn->mechToken) in ntlm_authenticate()
1506 sz = conn->mechTokenLen; in ntlm_authenticate()
1508 sz = le16_to_cpu(req->SecurityBufferLength); in ntlm_authenticate()
1511 set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD); in ntlm_authenticate()
1513 return -EPERM; in ntlm_authenticate()
1522 if (sess->state == SMB2_SESSION_VALID) { in ntlm_authenticate()
1523 if (conn->binding) in ntlm_authenticate()
1528 if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE && in ntlm_authenticate()
1529 (conn->sign || server_conf.enforced_signing)) || in ntlm_authenticate()
1530 (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) in ntlm_authenticate()
1531 sess->sign = true; in ntlm_authenticate()
1534 !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { in ntlm_authenticate()
1535 rc = conn->ops->generate_encryptionkey(conn, sess); in ntlm_authenticate()
1539 return -EINVAL; in ntlm_authenticate()
1541 sess->enc = true; in ntlm_authenticate()
1543 rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; in ntlm_authenticate()
1548 sess->sign = false; in ntlm_authenticate()
1552 if (conn->dialect >= SMB30_PROT_ID) { in ntlm_authenticate()
1555 chann = kmalloc(sizeof(struct channel), KSMBD_DEFAULT_GFP); in ntlm_authenticate()
1557 return -ENOMEM; in ntlm_authenticate()
1559 chann->conn = conn; in ntlm_authenticate()
1560 xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP); in ntlm_authenticate()
1564 if (conn->ops->generate_signingkey) { in ntlm_authenticate()
1565 rc = conn->ops->generate_signingkey(sess, conn); in ntlm_authenticate()
1568 return -EINVAL; in ntlm_authenticate()
1574 return -ENOENT; in ntlm_authenticate()
1584 struct ksmbd_conn *conn = work->conn; in krb5_authenticate()
1585 struct ksmbd_session *sess = work->sess; in krb5_authenticate()
1587 struct channel *chann = NULL; in krb5_authenticate()
1592 in_blob = (char *)&req->hdr.ProtocolId + in krb5_authenticate()
1593 le16_to_cpu(req->SecurityBufferOffset); in krb5_authenticate()
1594 in_len = le16_to_cpu(req->SecurityBufferLength); in krb5_authenticate()
1595 out_blob = (char *)&rsp->hdr.ProtocolId + in krb5_authenticate()
1596 le16_to_cpu(rsp->SecurityBufferOffset); in krb5_authenticate()
1597 out_len = work->response_sz - in krb5_authenticate()
1598 (le16_to_cpu(rsp->SecurityBufferOffset) + 4); in krb5_authenticate()
1601 prev_sess_id = le64_to_cpu(req->PreviousSessionId); in krb5_authenticate()
1602 if (prev_sess_id && prev_sess_id != sess->id) in krb5_authenticate()
1603 destroy_previous_session(conn, sess->user, prev_sess_id); in krb5_authenticate()
1605 if (sess->state == SMB2_SESSION_VALID) { in krb5_authenticate()
1606 ksmbd_free_user(sess->user); in krb5_authenticate()
1607 sess->user = NULL; in krb5_authenticate()
1614 return -EINVAL; in krb5_authenticate()
1616 rsp->SecurityBufferLength = cpu_to_le16(out_len); in krb5_authenticate()
1618 if ((conn->sign || server_conf.enforced_signing) || in krb5_authenticate()
1619 (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) in krb5_authenticate()
1620 sess->sign = true; in krb5_authenticate()
1623 retval = conn->ops->generate_encryptionkey(conn, sess); in krb5_authenticate()
1627 return -EINVAL; in krb5_authenticate()
1629 sess->enc = true; in krb5_authenticate()
1631 rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; in krb5_authenticate()
1632 sess->sign = false; in krb5_authenticate()
1635 if (conn->dialect >= SMB30_PROT_ID) { in krb5_authenticate()
1638 chann = kmalloc(sizeof(struct channel), KSMBD_DEFAULT_GFP); in krb5_authenticate()
1640 return -ENOMEM; in krb5_authenticate()
1642 chann->conn = conn; in krb5_authenticate()
1643 xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP); in krb5_authenticate()
1647 if (conn->ops->generate_signingkey) { in krb5_authenticate()
1648 retval = conn->ops->generate_signingkey(sess, conn); in krb5_authenticate()
1651 return -EINVAL; in krb5_authenticate()
1657 return -ENOENT; in krb5_authenticate()
1666 return -EOPNOTSUPP; in krb5_authenticate()
1672 struct ksmbd_conn *conn = work->conn; in smb2_sess_setup()
1683 work->send_no_response = 1; in smb2_sess_setup()
1689 rsp->StructureSize = cpu_to_le16(9); in smb2_sess_setup()
1690 rsp->SessionFlags = 0; in smb2_sess_setup()
1691 rsp->SecurityBufferOffset = cpu_to_le16(72); in smb2_sess_setup()
1692 rsp->SecurityBufferLength = 0; in smb2_sess_setup()
1695 if (!req->hdr.SessionId) { in smb2_sess_setup()
1698 rc = -ENOMEM; in smb2_sess_setup()
1701 rsp->hdr.SessionId = cpu_to_le64(sess->id); in smb2_sess_setup()
1706 conn->binding = false; in smb2_sess_setup()
1707 } else if (conn->dialect >= SMB30_PROT_ID && in smb2_sess_setup()
1709 req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) { in smb2_sess_setup()
1710 u64 sess_id = le64_to_cpu(req->hdr.SessionId); in smb2_sess_setup()
1714 rc = -ENOENT; in smb2_sess_setup()
1718 if (conn->dialect != sess->dialect) { in smb2_sess_setup()
1719 rc = -EINVAL; in smb2_sess_setup()
1723 if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) { in smb2_sess_setup()
1724 rc = -EINVAL; in smb2_sess_setup()
1728 if (strncmp(conn->ClientGUID, sess->ClientGUID, in smb2_sess_setup()
1730 rc = -ENOENT; in smb2_sess_setup()
1734 if (sess->state == SMB2_SESSION_IN_PROGRESS) { in smb2_sess_setup()
1735 rc = -EACCES; in smb2_sess_setup()
1739 if (sess->state == SMB2_SESSION_EXPIRED) { in smb2_sess_setup()
1740 rc = -EFAULT; in smb2_sess_setup()
1745 rc = -EFAULT; in smb2_sess_setup()
1752 rc = -EACCES; in smb2_sess_setup()
1756 if (user_guest(sess->user)) { in smb2_sess_setup()
1757 rc = -EOPNOTSUPP; in smb2_sess_setup()
1761 conn->binding = true; in smb2_sess_setup()
1762 } else if ((conn->dialect < SMB30_PROT_ID || in smb2_sess_setup()
1764 (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { in smb2_sess_setup()
1766 rc = -EACCES; in smb2_sess_setup()
1770 le64_to_cpu(req->hdr.SessionId)); in smb2_sess_setup()
1772 rc = -ENOENT; in smb2_sess_setup()
1776 if (sess->state == SMB2_SESSION_EXPIRED) { in smb2_sess_setup()
1777 rc = -EFAULT; in smb2_sess_setup()
1782 rc = -EFAULT; in smb2_sess_setup()
1787 conn->binding = false; in smb2_sess_setup()
1789 work->sess = sess; in smb2_sess_setup()
1791 negblob_off = le16_to_cpu(req->SecurityBufferOffset); in smb2_sess_setup()
1792 negblob_len = le16_to_cpu(req->SecurityBufferLength); in smb2_sess_setup()
1794 rc = -EINVAL; in smb2_sess_setup()
1798 negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId + in smb2_sess_setup()
1802 if (conn->mechToken) { in smb2_sess_setup()
1803 negblob = (struct negotiate_message *)conn->mechToken; in smb2_sess_setup()
1804 negblob_len = conn->mechTokenLen; in smb2_sess_setup()
1809 rc = -EINVAL; in smb2_sess_setup()
1813 if (server_conf.auth_mechs & conn->auth_mechs) { in smb2_sess_setup()
1818 if (conn->preferred_auth_mech & in smb2_sess_setup()
1822 rc = -EINVAL; in smb2_sess_setup()
1828 sess->state = SMB2_SESSION_VALID; in smb2_sess_setup()
1830 kfree(sess->Preauth_HashValue); in smb2_sess_setup()
1831 sess->Preauth_HashValue = NULL; in smb2_sess_setup()
1832 } else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) { in smb2_sess_setup()
1833 if (negblob->MessageType == NtLmNegotiate) { in smb2_sess_setup()
1837 rsp->hdr.Status = in smb2_sess_setup()
1839 } else if (negblob->MessageType == NtLmAuthenticate) { in smb2_sess_setup()
1846 sess->state = SMB2_SESSION_VALID; in smb2_sess_setup()
1848 if (conn->binding) { in smb2_sess_setup()
1852 ksmbd_preauth_session_lookup(conn, sess->id); in smb2_sess_setup()
1854 list_del(&preauth_sess->preauth_entry); in smb2_sess_setup()
1858 kfree(sess->Preauth_HashValue); in smb2_sess_setup()
1859 sess->Preauth_HashValue = NULL; in smb2_sess_setup()
1862 le32_to_cpu(negblob->MessageType)); in smb2_sess_setup()
1863 rc = -EINVAL; in smb2_sess_setup()
1868 rc = -EINVAL; in smb2_sess_setup()
1872 rc = -EINVAL; in smb2_sess_setup()
1876 if (rc == -EINVAL) in smb2_sess_setup()
1877 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_sess_setup()
1878 else if (rc == -ENOENT) in smb2_sess_setup()
1879 rsp->hdr.Status = STATUS_USER_SESSION_DELETED; in smb2_sess_setup()
1880 else if (rc == -EACCES) in smb2_sess_setup()
1881 rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED; in smb2_sess_setup()
1882 else if (rc == -EFAULT) in smb2_sess_setup()
1883 rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED; in smb2_sess_setup()
1884 else if (rc == -ENOMEM) in smb2_sess_setup()
1885 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_sess_setup()
1886 else if (rc == -EOPNOTSUPP) in smb2_sess_setup()
1887 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_sess_setup()
1889 rsp->hdr.Status = STATUS_LOGON_FAILURE; in smb2_sess_setup()
1891 if (conn->use_spnego && conn->mechToken) { in smb2_sess_setup()
1892 kfree(conn->mechToken); in smb2_sess_setup()
1893 conn->mechToken = NULL; in smb2_sess_setup()
1901 rsp->SecurityBufferOffset = 0; in smb2_sess_setup()
1912 if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION) in smb2_sess_setup()
1915 sess->last_active = jiffies; in smb2_sess_setup()
1916 sess->state = SMB2_SESSION_EXPIRED; in smb2_sess_setup()
1918 work->sess = NULL; in smb2_sess_setup()
1929 if (rsp->SecurityBufferLength) in smb2_sess_setup()
1931 le16_to_cpu(rsp->SecurityBufferLength); in smb2_sess_setup()
1936 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_sess_setup()
1944 * smb2_tree_connect() - handler for smb2 tree connect command
1951 struct ksmbd_conn *conn = work->conn; in smb2_tree_connect()
1954 struct ksmbd_session *sess = work->sess; in smb2_tree_connect()
1958 int rc = -EINVAL; in smb2_tree_connect()
1964 treename = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->PathOffset), in smb2_tree_connect()
1965 le16_to_cpu(req->PathLength), true, in smb2_tree_connect()
1966 conn->local_nls); in smb2_tree_connect()
1973 name = ksmbd_extract_sharename(conn->um, treename); in smb2_tree_connect()
1984 rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id); in smb2_tree_connect()
1988 share = status.tree_conn->share_conf; in smb2_tree_connect()
1991 rsp->ShareType = SMB2_SHARE_TYPE_PIPE; in smb2_tree_connect()
1992 rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE | in smb2_tree_connect()
1998 rsp->ShareType = SMB2_SHARE_TYPE_DISK; in smb2_tree_connect()
1999 rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE | in smb2_tree_connect()
2003 rsp->MaximalAccess |= FILE_WRITE_DATA_LE | in smb2_tree_connect()
2012 status.tree_conn->maximal_access = le32_to_cpu(rsp->MaximalAccess); in smb2_tree_connect()
2013 if (conn->posix_ext_supported) in smb2_tree_connect()
2014 status.tree_conn->posix_extensions = true; in smb2_tree_connect()
2016 write_lock(&sess->tree_conns_lock); in smb2_tree_connect()
2017 status.tree_conn->t_state = TREE_CONNECTED; in smb2_tree_connect()
2018 write_unlock(&sess->tree_conns_lock); in smb2_tree_connect()
2019 rsp->StructureSize = cpu_to_le16(16); in smb2_tree_connect()
2024 rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY; in smb2_tree_connect()
2026 rsp->Capabilities = 0; in smb2_tree_connect()
2027 rsp->Reserved = 0; in smb2_tree_connect()
2029 rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING; in smb2_tree_connect()
2042 rsp->hdr.Status = STATUS_SUCCESS; in smb2_tree_connect()
2045 case -ESTALE: in smb2_tree_connect()
2046 case -ENOENT: in smb2_tree_connect()
2048 rsp->hdr.Status = STATUS_BAD_NETWORK_NAME; in smb2_tree_connect()
2050 case -ENOMEM: in smb2_tree_connect()
2052 rsp->hdr.Status = STATUS_NO_MEMORY; in smb2_tree_connect()
2057 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_tree_connect()
2059 case -EINVAL: in smb2_tree_connect()
2060 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_tree_connect()
2063 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_tree_connect()
2073 * smb2_create_open_flags() - convert smb open flags to unix open flags
2145 * smb2_tree_disconnect() - handler for smb tree connect request
2154 struct ksmbd_session *sess = work->sess; in smb2_tree_disconnect()
2155 struct ksmbd_tree_connect *tcon = work->tcon; in smb2_tree_disconnect() local
2162 if (!tcon) { in smb2_tree_disconnect()
2163 ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); in smb2_tree_disconnect()
2165 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_tree_disconnect()
2166 err = -ENOENT; in smb2_tree_disconnect()
2172 write_lock(&sess->tree_conns_lock); in smb2_tree_disconnect()
2173 if (tcon->t_state == TREE_DISCONNECTED) { in smb2_tree_disconnect()
2174 write_unlock(&sess->tree_conns_lock); in smb2_tree_disconnect()
2175 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_tree_disconnect()
2176 err = -ENOENT; in smb2_tree_disconnect()
2180 WARN_ON_ONCE(atomic_dec_and_test(&tcon->refcount)); in smb2_tree_disconnect()
2181 tcon->t_state = TREE_DISCONNECTED; in smb2_tree_disconnect()
2182 write_unlock(&sess->tree_conns_lock); in smb2_tree_disconnect()
2184 err = ksmbd_tree_conn_disconnect(sess, tcon); in smb2_tree_disconnect()
2186 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_tree_disconnect()
2190 work->tcon = NULL; in smb2_tree_disconnect()
2192 rsp->StructureSize = cpu_to_le16(4); in smb2_tree_disconnect()
2196 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_tree_disconnect()
2209 * smb2_session_logoff() - handler for session log off request
2216 struct ksmbd_conn *conn = work->conn; in smb2_session_logoff()
2217 struct ksmbd_session *sess = work->sess; in smb2_session_logoff()
2230 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_session_logoff()
2232 return -ENOENT; in smb2_session_logoff()
2234 sess_id = le64_to_cpu(req->hdr.SessionId); in smb2_session_logoff()
2242 ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); in smb2_session_logoff()
2243 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_session_logoff()
2245 return -ENOENT; in smb2_session_logoff()
2248 down_write(&conn->session_lock); in smb2_session_logoff()
2249 sess->state = SMB2_SESSION_EXPIRED; in smb2_session_logoff()
2250 up_write(&conn->session_lock); in smb2_session_logoff()
2252 if (sess->user) { in smb2_session_logoff()
2253 ksmbd_free_user(sess->user); in smb2_session_logoff()
2254 sess->user = NULL; in smb2_session_logoff()
2258 rsp->StructureSize = cpu_to_le16(4); in smb2_session_logoff()
2261 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_session_logoff()
2269 * create_smb2_pipe() - create IPC pipe
2284 name = smb_strndup_from_utf16(req->Buffer, le16_to_cpu(req->NameLength), in create_smb2_pipe()
2285 1, work->conn->local_nls); in create_smb2_pipe()
2287 rsp->hdr.Status = STATUS_NO_MEMORY; in create_smb2_pipe()
2292 id = ksmbd_session_rpc_open(work->sess, name); in create_smb2_pipe()
2299 rsp->hdr.Status = STATUS_SUCCESS; in create_smb2_pipe()
2300 rsp->StructureSize = cpu_to_le16(89); in create_smb2_pipe()
2301 rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE; in create_smb2_pipe()
2302 rsp->Flags = 0; in create_smb2_pipe()
2303 rsp->CreateAction = cpu_to_le32(FILE_OPENED); in create_smb2_pipe()
2305 rsp->CreationTime = cpu_to_le64(0); in create_smb2_pipe()
2306 rsp->LastAccessTime = cpu_to_le64(0); in create_smb2_pipe()
2307 rsp->ChangeTime = cpu_to_le64(0); in create_smb2_pipe()
2308 rsp->AllocationSize = cpu_to_le64(0); in create_smb2_pipe()
2309 rsp->EndofFile = cpu_to_le64(0); in create_smb2_pipe()
2310 rsp->FileAttributes = FILE_ATTRIBUTE_NORMAL_LE; in create_smb2_pipe()
2311 rsp->Reserved2 = 0; in create_smb2_pipe()
2312 rsp->VolatileFileId = id; in create_smb2_pipe()
2313 rsp->PersistentFileId = 0; in create_smb2_pipe()
2314 rsp->CreateContextsOffset = 0; in create_smb2_pipe()
2315 rsp->CreateContextsLength = 0; in create_smb2_pipe()
2326 case -EINVAL: in create_smb2_pipe()
2327 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in create_smb2_pipe()
2329 case -ENOSPC: in create_smb2_pipe()
2330 case -ENOMEM: in create_smb2_pipe()
2331 rsp->hdr.Status = STATUS_NO_MEMORY; in create_smb2_pipe()
2343 * smb2_set_ea() - handler for setting extended attributes using set
2355 struct mnt_idmap *idmap = mnt_idmap(path->mnt); in smb2_set_ea()
2360 if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + in smb2_set_ea()
2361 le16_to_cpu(eabuf->EaValueLength)) in smb2_set_ea()
2362 return -EINVAL; in smb2_set_ea()
2366 return -ENOMEM; in smb2_set_ea()
2369 if (!eabuf->EaNameLength) in smb2_set_ea()
2374 eabuf->name, eabuf->EaNameLength, in smb2_set_ea()
2375 le16_to_cpu(eabuf->EaValueLength), in smb2_set_ea()
2376 le32_to_cpu(eabuf->NextEntryOffset)); in smb2_set_ea()
2378 if (eabuf->EaNameLength > in smb2_set_ea()
2379 (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) { in smb2_set_ea()
2380 rc = -EINVAL; in smb2_set_ea()
2385 memcpy(&attr_name[XATTR_USER_PREFIX_LEN], eabuf->name, in smb2_set_ea()
2386 eabuf->EaNameLength); in smb2_set_ea()
2387 attr_name[XATTR_USER_PREFIX_LEN + eabuf->EaNameLength] = '\0'; in smb2_set_ea()
2388 value = (char *)&eabuf->name + eabuf->EaNameLength + 1; in smb2_set_ea()
2390 if (!eabuf->EaValueLength) { in smb2_set_ea()
2392 path->dentry, in smb2_set_ea()
2395 eabuf->EaNameLength); in smb2_set_ea()
2416 le16_to_cpu(eabuf->EaValueLength), in smb2_set_ea()
2427 next = le32_to_cpu(eabuf->NextEntryOffset); in smb2_set_ea()
2430 buf_len -= next; in smb2_set_ea()
2433 rc = -EINVAL; in smb2_set_ea()
2437 if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + in smb2_set_ea()
2438 le16_to_cpu(eabuf->EaValueLength)) { in smb2_set_ea()
2439 rc = -EINVAL; in smb2_set_ea()
2452 struct mnt_idmap *idmap = mnt_idmap(path->mnt); in smb2_set_stream_name_xattr()
2464 fp->stream.name = xattr_stream_name; in smb2_set_stream_name_xattr()
2465 fp->stream.size = xattr_stream_size; in smb2_set_stream_name_xattr()
2469 path->dentry, in smb2_set_stream_name_xattr()
2475 if (fp->cdoption == FILE_OPEN_LE) { in smb2_set_stream_name_xattr()
2477 return -EBADF; in smb2_set_stream_name_xattr()
2488 struct mnt_idmap *idmap = mnt_idmap(path->mnt); in smb2_remove_smb_xattrs()
2493 xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list); in smb2_remove_smb_xattrs()
2501 for (name = xattr_list; name - xattr_list < xattr_list_len; in smb2_remove_smb_xattrs()
2530 if (rc == -EOPNOTSUPP) in smb2_create_truncate()
2539 static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *path, in smb2_new_xattrs() argument
2545 if (!test_share_config_flag(tcon->share_conf, in smb2_new_xattrs()
2550 da.attr = le32_to_cpu(fp->f_ci->m_fattr); in smb2_new_xattrs()
2551 da.itime = da.create_time = fp->create_time; in smb2_new_xattrs()
2555 rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da, true); in smb2_new_xattrs()
2560 static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon, in smb2_update_xattrs() argument
2566 fp->f_ci->m_fattr &= ~(FILE_ATTRIBUTE_HIDDEN_LE | FILE_ATTRIBUTE_SYSTEM_LE); in smb2_update_xattrs()
2569 if (!test_share_config_flag(tcon->share_conf, in smb2_update_xattrs()
2573 rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_idmap(path->mnt), in smb2_update_xattrs()
2574 path->dentry, &da); in smb2_update_xattrs()
2576 fp->f_ci->m_fattr = cpu_to_le32(da.attr); in smb2_update_xattrs()
2577 fp->create_time = da.create_time; in smb2_update_xattrs()
2578 fp->itime = da.itime; in smb2_update_xattrs()
2586 struct ksmbd_tree_connect *tcon = work->tcon; in smb2_creat() local
2587 struct ksmbd_share_config *share = tcon->share_conf; in smb2_creat()
2592 return -EBADF; in smb2_creat()
2627 if (!req->CreateContextsOffset) in smb2_create_sd_buffer()
2628 return -ENOENT; in smb2_create_sd_buffer()
2633 return -ENOENT; in smb2_create_sd_buffer()
2640 if (le16_to_cpu(context->DataOffset) + in smb2_create_sd_buffer()
2641 le32_to_cpu(context->DataLength) < in smb2_create_sd_buffer()
2643 return -EINVAL; in smb2_create_sd_buffer()
2644 return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd, in smb2_create_sd_buffer()
2645 le32_to_cpu(sd_buf->ccontext.DataLength), true, false); in smb2_create_sd_buffer()
2655 fattr->cf_uid = vfsuid_into_kuid(vfsuid); in ksmbd_acls_fattr()
2656 fattr->cf_gid = vfsgid_into_kgid(vfsgid); in ksmbd_acls_fattr()
2657 fattr->cf_mode = inode->i_mode; in ksmbd_acls_fattr()
2658 fattr->cf_acls = NULL; in ksmbd_acls_fattr()
2659 fattr->cf_dacls = NULL; in ksmbd_acls_fattr()
2662 fattr->cf_acls = get_inode_acl(inode, ACL_TYPE_ACCESS); in ksmbd_acls_fattr()
2663 if (S_ISDIR(inode->i_mode)) in ksmbd_acls_fattr()
2664 fattr->cf_dacls = get_inode_acl(inode, ACL_TYPE_DEFAULT); in ksmbd_acls_fattr()
2689 struct ksmbd_conn *conn = work->conn; in parse_durable_handle_context()
2696 req_op_level = req->RequestedOplockLevel; in parse_durable_handle_context()
2699 context = smb2_find_context_vals(req, durable_arr[dh_idx - 1], 4); in parse_durable_handle_context()
2712 if (dh_info->type == DURABLE_RECONN || in parse_durable_handle_context()
2713 dh_info->type == DURABLE_REQ_V2) { in parse_durable_handle_context()
2714 err = -EINVAL; in parse_durable_handle_context()
2718 if (le16_to_cpu(context->DataOffset) + in parse_durable_handle_context()
2719 le32_to_cpu(context->DataLength) < in parse_durable_handle_context()
2721 err = -EINVAL; in parse_durable_handle_context()
2726 persistent_id = recon_v2->Fid.PersistentFileId; in parse_durable_handle_context()
2727 dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); in parse_durable_handle_context()
2728 if (!dh_info->fp) { in parse_durable_handle_context()
2730 err = -EBADF; in parse_durable_handle_context()
2734 if (memcmp(dh_info->fp->create_guid, recon_v2->CreateGuid, in parse_durable_handle_context()
2736 err = -EBADF; in parse_durable_handle_context()
2737 ksmbd_put_durable_fd(dh_info->fp); in parse_durable_handle_context()
2741 dh_info->type = dh_idx; in parse_durable_handle_context()
2742 dh_info->reconnected = true; in parse_durable_handle_context()
2744 "reconnect v2 Persistent-id from reconnect = %llu\n", in parse_durable_handle_context()
2752 if (dh_info->type == DURABLE_RECONN_V2 || in parse_durable_handle_context()
2753 dh_info->type == DURABLE_REQ_V2) { in parse_durable_handle_context()
2754 err = -EINVAL; in parse_durable_handle_context()
2758 if (le16_to_cpu(context->DataOffset) + in parse_durable_handle_context()
2759 le32_to_cpu(context->DataLength) < in parse_durable_handle_context()
2761 err = -EINVAL; in parse_durable_handle_context()
2766 persistent_id = recon->Data.Fid.PersistentFileId; in parse_durable_handle_context()
2767 dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); in parse_durable_handle_context()
2768 if (!dh_info->fp) { in parse_durable_handle_context()
2770 err = -EBADF; in parse_durable_handle_context()
2774 dh_info->type = dh_idx; in parse_durable_handle_context()
2775 dh_info->reconnected = true; in parse_durable_handle_context()
2776 ksmbd_debug(SMB, "reconnect Persistent-id from reconnect = %llu\n", in parse_durable_handle_context()
2784 if (dh_info->type == DURABLE_RECONN || in parse_durable_handle_context()
2785 dh_info->type == DURABLE_RECONN_V2) { in parse_durable_handle_context()
2786 err = -EINVAL; in parse_durable_handle_context()
2790 if (le16_to_cpu(context->DataOffset) + in parse_durable_handle_context()
2791 le32_to_cpu(context->DataLength) < in parse_durable_handle_context()
2793 err = -EINVAL; in parse_durable_handle_context()
2800 dh_info->fp = ksmbd_lookup_fd_cguid(durable_v2_blob->CreateGuid); in parse_durable_handle_context()
2801 if (dh_info->fp) { in parse_durable_handle_context()
2802 if (!memcmp(conn->ClientGUID, dh_info->fp->client_guid, in parse_durable_handle_context()
2804 if (!(req->hdr.Flags & SMB2_FLAGS_REPLAY_OPERATION)) { in parse_durable_handle_context()
2805 err = -ENOEXEC; in parse_durable_handle_context()
2809 dh_info->fp->conn = conn; in parse_durable_handle_context()
2810 dh_info->reconnected = true; in parse_durable_handle_context()
2815 if ((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || in parse_durable_handle_context()
2817 dh_info->CreateGuid = in parse_durable_handle_context()
2818 durable_v2_blob->CreateGuid; in parse_durable_handle_context()
2819 dh_info->persistent = in parse_durable_handle_context()
2820 le32_to_cpu(durable_v2_blob->Flags); in parse_durable_handle_context()
2821 dh_info->timeout = in parse_durable_handle_context()
2822 le32_to_cpu(durable_v2_blob->Timeout); in parse_durable_handle_context()
2823 dh_info->type = dh_idx; in parse_durable_handle_context()
2828 if (dh_info->type == DURABLE_RECONN) in parse_durable_handle_context()
2830 if (dh_info->type == DURABLE_RECONN_V2 || in parse_durable_handle_context()
2831 dh_info->type == DURABLE_REQ_V2) { in parse_durable_handle_context()
2832 err = -EINVAL; in parse_durable_handle_context()
2836 if ((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || in parse_durable_handle_context()
2839 dh_info->type = dh_idx; in parse_durable_handle_context()
2849 * smb2_open() - handler for smb file open request
2856 struct ksmbd_conn *conn = work->conn; in smb2_open()
2857 struct ksmbd_session *sess = work->sess; in smb2_open()
2858 struct ksmbd_tree_connect *tcon = work->tcon; in smb2_open() local
2862 struct ksmbd_share_config *share = tcon->share_conf; in smb2_open()
2892 if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off && in smb2_open()
2893 (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)) { in smb2_open()
2895 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_open()
2897 return -EINVAL; in smb2_open()
2905 if (req->NameLength) { in smb2_open()
2906 name = smb2_get_name((char *)req + le16_to_cpu(req->NameOffset), in smb2_open()
2907 le16_to_cpu(req->NameLength), in smb2_open()
2908 work->conn->local_nls); in smb2_open()
2917 if (!test_share_config_flag(work->tcon->share_conf, in smb2_open()
2919 rc = -EBADF; in smb2_open()
2932 rc = -ENOENT; in smb2_open()
2940 rc = -ENOMEM; in smb2_open()
2945 req_op_level = req->RequestedOplockLevel; in smb2_open()
2948 req->CreateContextsOffset) { in smb2_open()
2970 rc = -ENOMEM; in smb2_open()
2978 rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat); in smb2_open()
2988 if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) { in smb2_open()
2990 le32_to_cpu(req->ImpersonationLevel)); in smb2_open()
2991 rc = -EIO; in smb2_open()
2992 rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL; in smb2_open()
2996 if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) { in smb2_open()
2998 le32_to_cpu(req->CreateOptions)); in smb2_open()
2999 rc = -EINVAL; in smb2_open()
3002 if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE && in smb2_open()
3003 req->CreateOptions & FILE_RANDOM_ACCESS_LE) in smb2_open()
3004 req->CreateOptions = ~(FILE_SEQUENTIAL_ONLY_LE); in smb2_open()
3006 if (req->CreateOptions & in smb2_open()
3009 rc = -EOPNOTSUPP; in smb2_open()
3013 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { in smb2_open()
3014 if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) { in smb2_open()
3015 rc = -EINVAL; in smb2_open()
3017 } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) { in smb2_open()
3018 req->CreateOptions = ~(FILE_NO_COMPRESSION_LE); in smb2_open()
3023 if (le32_to_cpu(req->CreateDisposition) > in smb2_open()
3026 le32_to_cpu(req->CreateDisposition)); in smb2_open()
3027 rc = -EINVAL; in smb2_open()
3031 if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) { in smb2_open()
3033 le32_to_cpu(req->DesiredAccess)); in smb2_open()
3034 rc = -EACCES; in smb2_open()
3038 if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) { in smb2_open()
3040 le32_to_cpu(req->FileAttributes)); in smb2_open()
3041 rc = -EINVAL; in smb2_open()
3045 if (req->CreateContextsOffset) { in smb2_open()
3046 /* Parse non-durable handle create contexts */ in smb2_open()
3053 if (le16_to_cpu(context->DataOffset) + in smb2_open()
3054 le32_to_cpu(context->DataLength) < in smb2_open()
3056 rc = -EINVAL; in smb2_open()
3059 if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { in smb2_open()
3060 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_open()
3061 rc = -EACCES; in smb2_open()
3084 rc = -EBADF; in smb2_open()
3088 if (tcon->posix_extensions) { in smb2_open()
3097 if (le16_to_cpu(context->DataOffset) + in smb2_open()
3098 le32_to_cpu(context->DataLength) < in smb2_open()
3099 sizeof(struct create_posix) - 4) { in smb2_open()
3100 rc = -EINVAL; in smb2_open()
3105 posix_mode = le32_to_cpu(posix->Mode); in smb2_open()
3112 rc = -ENOMEM; in smb2_open()
3121 if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) { in smb2_open()
3126 if (req->CreateDisposition == FILE_OVERWRITE_IF_LE || in smb2_open()
3127 req->CreateDisposition == FILE_OPEN_IF_LE) { in smb2_open()
3128 rc = -EACCES; in smb2_open()
3132 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_open()
3135 rc = -EACCES; in smb2_open()
3139 rc = -EACCES; in smb2_open()
3145 if (rc != -ENOENT) in smb2_open()
3153 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { in smb2_open()
3155 rc = -EIO; in smb2_open()
3156 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY; in smb2_open()
3159 if (file_present && S_ISDIR(d_inode(path.dentry)->i_mode) && in smb2_open()
3161 rc = -EIO; in smb2_open()
3162 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY; in smb2_open()
3166 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE && in smb2_open()
3167 req->FileAttributes & FILE_ATTRIBUTE_NORMAL_LE) { in smb2_open()
3168 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY; in smb2_open()
3169 rc = -EIO; in smb2_open()
3176 if (file_present && req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE && in smb2_open()
3177 S_ISDIR(d_inode(path.dentry)->i_mode) && in smb2_open()
3178 !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) { in smb2_open()
3180 name, req->CreateOptions); in smb2_open()
3181 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY; in smb2_open()
3182 rc = -EIO; in smb2_open()
3186 if (file_present && (req->CreateOptions & FILE_DIRECTORY_FILE_LE) && in smb2_open()
3187 !(req->CreateDisposition == FILE_CREATE_LE) && in smb2_open()
3188 !S_ISDIR(d_inode(path.dentry)->i_mode)) { in smb2_open()
3189 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY; in smb2_open()
3190 rc = -EIO; in smb2_open()
3195 req->CreateDisposition == FILE_CREATE_LE) { in smb2_open()
3196 rc = -EEXIST; in smb2_open()
3200 daccess = smb_map_generic_desired_access(req->DesiredAccess); in smb2_open()
3202 if (file_present && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) { in smb2_open()
3204 sess->user->uid); in smb2_open()
3222 req->CreateDisposition, in smb2_open()
3224 req->CreateOptions, in smb2_open()
3225 file_present ? d_inode(path.dentry)->i_mode : 0); in smb2_open()
3227 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_open()
3231 rc = -EACCES; in smb2_open()
3240 req->CreateOptions & FILE_DIRECTORY_FILE_LE); in smb2_open()
3242 if (rc == -ENOENT) { in smb2_open()
3243 rc = -EIO; in smb2_open()
3244 rsp->hdr.Status = STATUS_OBJECT_PATH_NOT_FOUND; in smb2_open()
3252 if (le32_to_cpu(ea_buf->ccontext.DataLength) < in smb2_open()
3254 rc = -EINVAL; in smb2_open()
3258 rc = smb2_set_ea(&ea_buf->ea, in smb2_open()
3259 le32_to_cpu(ea_buf->ccontext.DataLength), in smb2_open()
3261 if (rc == -EOPNOTSUPP) in smb2_open()
3279 (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) { in smb2_open()
3281 d_inode(path.dentry->d_parent), in smb2_open()
3289 rc = ksmbd_query_inode_status(path.dentry->d_parent); in smb2_open()
3291 rc = -EBUSY; in smb2_open()
3309 if ((req->CreateDisposition & FILE_CREATE_MASK_LE) == in smb2_open()
3316 ksmbd_vfs_set_fadvise(filp, req->CreateOptions); in smb2_open()
3318 /* Obtain Volatile-ID */ in smb2_open()
3327 /* Get Persistent-ID */ in smb2_open()
3329 if (!has_file_id(fp->persistent_id)) { in smb2_open()
3330 rc = -ENOMEM; in smb2_open()
3334 fp->cdoption = req->CreateDisposition; in smb2_open()
3335 fp->daccess = daccess; in smb2_open()
3336 fp->saccess = req->ShareAccess; in smb2_open()
3337 fp->coption = req->CreateOptions; in smb2_open()
3346 d_inode(path.dentry->d_parent)); in smb2_open()
3350 if (test_share_config_flag(work->tcon->share_conf, in smb2_open()
3352 rc = smb_inherit_dacl(conn, &path, sess->user->uid, in smb2_open()
3353 sess->user->gid); in smb2_open()
3363 if (test_share_config_flag(work->tcon->share_conf, in smb2_open()
3371 ace_num = fattr.cf_acls->a_count; in smb2_open()
3373 ace_num += fattr.cf_dacls->a_count; in smb2_open()
3425 fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE | in smb2_open()
3432 down_write(&fp->f_ci->m_lock); in smb2_open()
3433 list_add(&fp->node, &fp->f_ci->m_fp_list); in smb2_open()
3434 up_write(&fp->f_ci->m_lock); in smb2_open()
3438 rc = -EBUSY; in smb2_open()
3445 if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC && in smb2_open()
3446 !fp->attrib_only && !stream_name) { in smb2_open()
3451 share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); in smb2_open()
3452 if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || in smb2_open()
3454 !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) { in smb2_open()
3455 if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) { in smb2_open()
3461 if (S_ISDIR(file_inode(filp)->i_mode)) { in smb2_open()
3462 lc->req_state &= ~SMB2_LEASE_WRITE_CACHING_LE; in smb2_open()
3463 lc->is_dir = true; in smb2_open()
3473 req_op_level = smb2_map_lease_to_oplock(lc->req_state); in smb2_open()
3476 name, req_op_level, lc->req_state); in smb2_open()
3477 rc = find_same_lease_key(sess, fp->f_ci, lc); in smb2_open()
3486 fp->persistent_id, fp, in smb2_open()
3487 le32_to_cpu(req->hdr.Id.SyncId.TreeId), in smb2_open()
3493 if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) in smb2_open()
3497 rc = smb2_create_truncate(&fp->filp->f_path); in smb2_open()
3502 if (req->CreateContextsOffset) { in smb2_open()
3514 if (le16_to_cpu(az_req->ccontext.DataOffset) + in smb2_open()
3515 le32_to_cpu(az_req->ccontext.DataLength) < in smb2_open()
3517 rc = -EINVAL; in smb2_open()
3520 alloc_size = le64_to_cpu(az_req->AllocationSize); in smb2_open()
3525 err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0, in smb2_open()
3548 fp->create_time = ksmbd_UnixTimeToNT(stat.btime); in smb2_open()
3550 fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); in smb2_open()
3551 if (req->FileAttributes || fp->f_ci->m_fattr == 0) in smb2_open()
3552 fp->f_ci->m_fattr = in smb2_open()
3553 cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); in smb2_open()
3556 smb2_update_xattrs(tcon, &path, fp); in smb2_open()
3558 smb2_new_xattrs(tcon, &path, fp); in smb2_open()
3560 memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); in smb2_open()
3564 test_share_config_flag(work->tcon->share_conf, in smb2_open()
3566 fp->is_persistent = true; in smb2_open()
3568 fp->is_durable = true; in smb2_open()
3571 memcpy(fp->create_guid, dh_info.CreateGuid, in smb2_open()
3574 fp->durable_timeout = in smb2_open()
3578 fp->durable_timeout = 60; in smb2_open()
3583 rsp->StructureSize = cpu_to_le16(89); in smb2_open()
3585 opinfo = rcu_dereference(fp->f_opinfo); in smb2_open()
3586 rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0; in smb2_open()
3588 rsp->Flags = 0; in smb2_open()
3589 rsp->CreateAction = cpu_to_le32(file_info); in smb2_open()
3590 rsp->CreationTime = cpu_to_le64(fp->create_time); in smb2_open()
3592 rsp->LastAccessTime = cpu_to_le64(time); in smb2_open()
3594 rsp->LastWriteTime = cpu_to_le64(time); in smb2_open()
3596 rsp->ChangeTime = cpu_to_le64(time); in smb2_open()
3597 rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 : in smb2_open()
3599 rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in smb2_open()
3600 rsp->FileAttributes = fp->f_ci->m_fattr; in smb2_open()
3602 rsp->Reserved2 = 0; in smb2_open()
3604 rsp->PersistentFileId = fp->persistent_id; in smb2_open()
3605 rsp->VolatileFileId = fp->volatile_id; in smb2_open()
3607 rsp->CreateContextsOffset = 0; in smb2_open()
3608 rsp->CreateContextsLength = 0; in smb2_open()
3612 if (opinfo && opinfo->is_lease) { in smb2_open()
3616 name, opinfo->o_lease->state); in smb2_open()
3617 rsp->OplockLevel = SMB2_OPLOCK_LEVEL_LEASE; in smb2_open()
3619 lease_ccontext = (struct create_context *)rsp->Buffer; in smb2_open()
3621 create_lease_buf(rsp->Buffer, opinfo->o_lease); in smb2_open()
3622 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3623 conn->vals->create_lease_size); in smb2_open()
3624 iov_len += conn->vals->create_lease_size; in smb2_open()
3625 next_ptr = &lease_ccontext->Next; in smb2_open()
3626 next_off = conn->vals->create_lease_size; in smb2_open()
3636 mxac_ccontext = (struct create_context *)(rsp->Buffer + in smb2_open()
3637 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3639 create_mxac_rsp_buf(rsp->Buffer + in smb2_open()
3640 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3642 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3643 conn->vals->create_mxac_size); in smb2_open()
3644 iov_len += conn->vals->create_mxac_size; in smb2_open()
3647 next_ptr = &mxac_ccontext->Next; in smb2_open()
3648 next_off = conn->vals->create_mxac_size; in smb2_open()
3654 disk_id_ccontext = (struct create_context *)(rsp->Buffer + in smb2_open()
3655 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3657 create_disk_id_rsp_buf(rsp->Buffer + in smb2_open()
3658 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3659 stat.ino, tcon->id); in smb2_open()
3660 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3661 conn->vals->create_disk_id_size); in smb2_open()
3662 iov_len += conn->vals->create_disk_id_size; in smb2_open()
3665 next_ptr = &disk_id_ccontext->Next; in smb2_open()
3666 next_off = conn->vals->create_disk_id_size; in smb2_open()
3672 durable_ccontext = (struct create_context *)(rsp->Buffer + in smb2_open()
3673 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3676 create_durable_rsp_buf(rsp->Buffer + in smb2_open()
3677 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3678 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3679 conn->vals->create_durable_size); in smb2_open()
3680 iov_len += conn->vals->create_durable_size; in smb2_open()
3682 create_durable_v2_rsp_buf(rsp->Buffer + in smb2_open()
3683 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3685 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3686 conn->vals->create_durable_v2_size); in smb2_open()
3687 iov_len += conn->vals->create_durable_v2_size; in smb2_open()
3692 next_ptr = &durable_ccontext->Next; in smb2_open()
3693 next_off = conn->vals->create_durable_size; in smb2_open()
3698 create_posix_rsp_buf(rsp->Buffer + in smb2_open()
3699 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3701 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3702 conn->vals->create_posix_size); in smb2_open()
3703 iov_len += conn->vals->create_posix_size; in smb2_open()
3709 rsp->CreateContextsOffset = in smb2_open()
3722 ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED); in smb2_open()
3726 if (rc == -EINVAL) in smb2_open()
3727 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_open()
3728 else if (rc == -EOPNOTSUPP) in smb2_open()
3729 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_open()
3730 else if (rc == -EACCES || rc == -ESTALE || rc == -EXDEV) in smb2_open()
3731 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_open()
3732 else if (rc == -ENOENT) in smb2_open()
3733 rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID; in smb2_open()
3734 else if (rc == -EPERM) in smb2_open()
3735 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_open()
3736 else if (rc == -EBUSY) in smb2_open()
3737 rsp->hdr.Status = STATUS_DELETE_PENDING; in smb2_open()
3738 else if (rc == -EBADF) in smb2_open()
3739 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND; in smb2_open()
3740 else if (rc == -ENOEXEC) in smb2_open()
3741 rsp->hdr.Status = STATUS_DUPLICATE_OBJECTID; in smb2_open()
3742 else if (rc == -ENXIO) in smb2_open()
3743 rsp->hdr.Status = STATUS_NO_SUCH_DEVICE; in smb2_open()
3744 else if (rc == -EEXIST) in smb2_open()
3745 rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION; in smb2_open()
3746 else if (rc == -EMFILE) in smb2_open()
3747 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_open()
3748 if (!rsp->hdr.Status) in smb2_open()
3749 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_open()
3754 ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status); in smb2_open()
3781 return -EOPNOTSUPP; in readdir_info_level_struct_sz()
3792 ffdinfo = (struct file_full_directory_info *)d_info->rptr; in dentry_name()
3793 d_info->rptr += le32_to_cpu(ffdinfo->NextEntryOffset); in dentry_name()
3794 d_info->name = ffdinfo->FileName; in dentry_name()
3795 d_info->name_len = le32_to_cpu(ffdinfo->FileNameLength); in dentry_name()
3802 fbdinfo = (struct file_both_directory_info *)d_info->rptr; in dentry_name()
3803 d_info->rptr += le32_to_cpu(fbdinfo->NextEntryOffset); in dentry_name()
3804 d_info->name = fbdinfo->FileName; in dentry_name()
3805 d_info->name_len = le32_to_cpu(fbdinfo->FileNameLength); in dentry_name()
3812 fdinfo = (struct file_directory_info *)d_info->rptr; in dentry_name()
3813 d_info->rptr += le32_to_cpu(fdinfo->NextEntryOffset); in dentry_name()
3814 d_info->name = fdinfo->FileName; in dentry_name()
3815 d_info->name_len = le32_to_cpu(fdinfo->FileNameLength); in dentry_name()
3822 fninfo = (struct file_names_info *)d_info->rptr; in dentry_name()
3823 d_info->rptr += le32_to_cpu(fninfo->NextEntryOffset); in dentry_name()
3824 d_info->name = fninfo->FileName; in dentry_name()
3825 d_info->name_len = le32_to_cpu(fninfo->FileNameLength); in dentry_name()
3832 dinfo = (struct file_id_full_dir_info *)d_info->rptr; in dentry_name()
3833 d_info->rptr += le32_to_cpu(dinfo->NextEntryOffset); in dentry_name()
3834 d_info->name = dinfo->FileName; in dentry_name()
3835 d_info->name_len = le32_to_cpu(dinfo->FileNameLength); in dentry_name()
3842 fibdinfo = (struct file_id_both_directory_info *)d_info->rptr; in dentry_name()
3843 d_info->rptr += le32_to_cpu(fibdinfo->NextEntryOffset); in dentry_name()
3844 d_info->name = fibdinfo->FileName; in dentry_name()
3845 d_info->name_len = le32_to_cpu(fibdinfo->FileNameLength); in dentry_name()
3852 posix_info = (struct smb2_posix_info *)d_info->rptr; in dentry_name()
3853 d_info->rptr += le32_to_cpu(posix_info->NextEntryOffset); in dentry_name()
3854 d_info->name = posix_info->name; in dentry_name()
3855 d_info->name_len = le32_to_cpu(posix_info->name_len); in dentry_name()
3859 return -EINVAL; in dentry_name()
3864 * smb2_populate_readdir_entry() - encode directory entry in smb2 response
3887 conn->local_nls, in smb2_populate_readdir_entry()
3890 return -ENOMEM; in smb2_populate_readdir_entry()
3894 rc = -EINVAL; in smb2_populate_readdir_entry()
3900 d_info->last_entry_off_align = next_entry_offset - struct_sz; in smb2_populate_readdir_entry()
3902 if (next_entry_offset > d_info->out_buf_len) { in smb2_populate_readdir_entry()
3903 d_info->out_buf_len = 0; in smb2_populate_readdir_entry()
3904 rc = -ENOSPC; in smb2_populate_readdir_entry()
3908 kstat = d_info->wptr; in smb2_populate_readdir_entry()
3910 kstat = ksmbd_vfs_init_kstat(&d_info->wptr, ksmbd_kstat); in smb2_populate_readdir_entry()
3918 ffdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3919 ffdinfo->EaSize = in smb2_populate_readdir_entry()
3920 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3921 if (ffdinfo->EaSize) in smb2_populate_readdir_entry()
3922 ffdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3923 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3924 ffdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3925 memcpy(ffdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3926 ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3934 fbdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3935 fbdinfo->EaSize = in smb2_populate_readdir_entry()
3936 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3937 if (fbdinfo->EaSize) in smb2_populate_readdir_entry()
3938 fbdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3939 fbdinfo->ShortNameLength = 0; in smb2_populate_readdir_entry()
3940 fbdinfo->Reserved = 0; in smb2_populate_readdir_entry()
3941 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3942 fbdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3943 memcpy(fbdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3944 fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3952 fdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3953 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3954 fdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3955 memcpy(fdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3956 fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3964 fninfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3965 memcpy(fninfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3966 fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3974 dinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3975 dinfo->EaSize = in smb2_populate_readdir_entry()
3976 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3977 if (dinfo->EaSize) in smb2_populate_readdir_entry()
3978 dinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3979 dinfo->Reserved = 0; in smb2_populate_readdir_entry()
3980 dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino); in smb2_populate_readdir_entry()
3981 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3982 dinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3983 memcpy(dinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3984 dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3992 fibdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3993 fibdinfo->EaSize = in smb2_populate_readdir_entry()
3994 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3995 if (fibdinfo->EaSize) in smb2_populate_readdir_entry()
3996 fibdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3997 fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino); in smb2_populate_readdir_entry()
3998 fibdinfo->ShortNameLength = 0; in smb2_populate_readdir_entry()
3999 fibdinfo->Reserved = 0; in smb2_populate_readdir_entry()
4000 fibdinfo->Reserved2 = cpu_to_le16(0); in smb2_populate_readdir_entry()
4001 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
4002 fibdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
4003 memcpy(fibdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
4004 fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
4013 posix_info->Ignored = 0; in smb2_populate_readdir_entry()
4014 posix_info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time); in smb2_populate_readdir_entry()
4015 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime); in smb2_populate_readdir_entry()
4016 posix_info->ChangeTime = cpu_to_le64(time); in smb2_populate_readdir_entry()
4017 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->atime); in smb2_populate_readdir_entry()
4018 posix_info->LastAccessTime = cpu_to_le64(time); in smb2_populate_readdir_entry()
4019 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->mtime); in smb2_populate_readdir_entry()
4020 posix_info->LastWriteTime = cpu_to_le64(time); in smb2_populate_readdir_entry()
4021 posix_info->EndOfFile = cpu_to_le64(ksmbd_kstat->kstat->size); in smb2_populate_readdir_entry()
4022 posix_info->AllocationSize = cpu_to_le64(ksmbd_kstat->kstat->blocks << 9); in smb2_populate_readdir_entry()
4023 posix_info->DeviceId = cpu_to_le32(ksmbd_kstat->kstat->rdev); in smb2_populate_readdir_entry()
4024 posix_info->HardLinks = cpu_to_le32(ksmbd_kstat->kstat->nlink); in smb2_populate_readdir_entry()
4025 posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode & 0777); in smb2_populate_readdir_entry()
4026 switch (ksmbd_kstat->kstat->mode & S_IFMT) { in smb2_populate_readdir_entry()
4028 posix_info->Mode |= cpu_to_le32(POSIX_TYPE_DIR << POSIX_FILETYPE_SHIFT); in smb2_populate_readdir_entry()
4031 posix_info->Mode |= cpu_to_le32(POSIX_TYPE_SYMLINK << POSIX_FILETYPE_SHIFT); in smb2_populate_readdir_entry()
4034 posix_info->Mode |= cpu_to_le32(POSIX_TYPE_CHARDEV << POSIX_FILETYPE_SHIFT); in smb2_populate_readdir_entry()
4037 posix_info->Mode |= cpu_to_le32(POSIX_TYPE_BLKDEV << POSIX_FILETYPE_SHIFT); in smb2_populate_readdir_entry()
4040 posix_info->Mode |= cpu_to_le32(POSIX_TYPE_FIFO << POSIX_FILETYPE_SHIFT); in smb2_populate_readdir_entry()
4043 posix_info->Mode |= cpu_to_le32(POSIX_TYPE_SOCKET << POSIX_FILETYPE_SHIFT); in smb2_populate_readdir_entry()
4046 posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino); in smb2_populate_readdir_entry()
4047 posix_info->DosAttributes = in smb2_populate_readdir_entry()
4048 S_ISDIR(ksmbd_kstat->kstat->mode) ? in smb2_populate_readdir_entry()
4050 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
4051 posix_info->DosAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
4057 id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid), in smb2_populate_readdir_entry()
4058 SIDUNIX_USER, (struct smb_sid *)&posix_info->SidBuffer[0]); in smb2_populate_readdir_entry()
4059 id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid), in smb2_populate_readdir_entry()
4060 SIDUNIX_GROUP, (struct smb_sid *)&posix_info->SidBuffer[16]); in smb2_populate_readdir_entry()
4061 memcpy(posix_info->name, conv_name, conv_len); in smb2_populate_readdir_entry()
4062 posix_info->name_len = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
4063 posix_info->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
4069 d_info->last_entry_offset = d_info->data_count; in smb2_populate_readdir_entry()
4070 d_info->data_count += next_entry_offset; in smb2_populate_readdir_entry()
4071 d_info->out_buf_len -= next_entry_offset; in smb2_populate_readdir_entry()
4072 d_info->wptr += next_entry_offset; in smb2_populate_readdir_entry()
4076 info_level, d_info->out_buf_len, in smb2_populate_readdir_entry()
4077 next_entry_offset, d_info->data_count); in smb2_populate_readdir_entry()
4095 struct dentry *dir = dir_fp->filp->f_path.dentry; in lock_dir()
4102 struct dentry *dir = dir_fp->filp->f_path.dentry; in unlock_dir()
4109 struct mnt_idmap *idmap = file_mnt_idmap(priv->dir_fp->filp); in process_query_dir_entries()
4115 for (i = 0; i < priv->d_info->num_entry; i++) { in process_query_dir_entries()
4118 if (dentry_name(priv->d_info, priv->info_level)) in process_query_dir_entries()
4119 return -EINVAL; in process_query_dir_entries()
4121 lock_dir(priv->dir_fp); in process_query_dir_entries()
4122 dent = lookup_one(idmap, priv->d_info->name, in process_query_dir_entries()
4123 priv->dir_fp->filp->f_path.dentry, in process_query_dir_entries()
4124 priv->d_info->name_len); in process_query_dir_entries()
4125 unlock_dir(priv->dir_fp); in process_query_dir_entries()
4129 priv->d_info->name, in process_query_dir_entries()
4136 priv->d_info->name); in process_query_dir_entries()
4141 if (priv->info_level != FILE_NAMES_INFORMATION) { in process_query_dir_entries()
4142 rc = ksmbd_vfs_fill_dentry_attrs(priv->work, in process_query_dir_entries()
4152 rc = smb2_populate_readdir_entry(priv->work->conn, in process_query_dir_entries()
4153 priv->info_level, in process_query_dir_entries()
4154 priv->d_info, in process_query_dir_entries()
4171 if (struct_sz == -EOPNOTSUPP) in reserve_populate_dentry()
4172 return -EOPNOTSUPP; in reserve_populate_dentry()
4174 conv_len = (d_info->name_len + 1) * 2; in reserve_populate_dentry()
4178 if (next_entry_offset > d_info->out_buf_len) { in reserve_populate_dentry()
4179 d_info->out_buf_len = 0; in reserve_populate_dentry()
4180 return -ENOSPC; in reserve_populate_dentry()
4188 ffdinfo = (struct file_full_directory_info *)d_info->wptr; in reserve_populate_dentry()
4189 memcpy(ffdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4190 ffdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4191 ffdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4192 ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4199 fbdinfo = (struct file_both_directory_info *)d_info->wptr; in reserve_populate_dentry()
4200 memcpy(fbdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4201 fbdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4202 fbdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4203 fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4210 fdinfo = (struct file_directory_info *)d_info->wptr; in reserve_populate_dentry()
4211 memcpy(fdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4212 fdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4213 fdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4214 fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4221 fninfo = (struct file_names_info *)d_info->wptr; in reserve_populate_dentry()
4222 memcpy(fninfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4223 fninfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4224 fninfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4225 fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4232 dinfo = (struct file_id_full_dir_info *)d_info->wptr; in reserve_populate_dentry()
4233 memcpy(dinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4234 dinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4235 dinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4236 dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4243 fibdinfo = (struct file_id_both_directory_info *)d_info->wptr; in reserve_populate_dentry()
4244 memcpy(fibdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4245 fibdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4246 fibdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4247 fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4254 posix_info = (struct smb2_posix_info *)d_info->wptr; in reserve_populate_dentry()
4255 memcpy(posix_info->name, d_info->name, d_info->name_len); in reserve_populate_dentry()
4256 posix_info->name[d_info->name_len] = 0x00; in reserve_populate_dentry()
4257 posix_info->name_len = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4258 posix_info->NextEntryOffset = in reserve_populate_dentry()
4264 d_info->num_entry++; in reserve_populate_dentry()
4265 d_info->out_buf_len -= next_entry_offset; in reserve_populate_dentry()
4266 d_info->wptr += next_entry_offset; in reserve_populate_dentry()
4279 priv = buf->private; in __query_dir()
4280 d_info = priv->d_info; in __query_dir()
4285 d_info->num_scan++; in __query_dir()
4286 if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name)) in __query_dir()
4288 if (!match_pattern(name, namlen, priv->search_pattern)) in __query_dir()
4291 d_info->name = name; in __query_dir()
4292 d_info->name_len = namlen; in __query_dir()
4293 rc = reserve_populate_dentry(d_info, priv->info_level); in __query_dir()
4296 if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) in __query_dir()
4297 d_info->out_buf_len = 0; in __query_dir()
4313 return -EOPNOTSUPP; in verify_info_level()
4323 free_len = (int)(work->response_sz - in smb2_resp_buf_len()
4324 (get_rfc1002_len(work->response_buf) + 4)) - hdr2_len; in smb2_resp_buf_len()
4334 if (out_buf_len > work->conn->vals->max_trans_size) in smb2_calc_max_out_buf_len()
4335 return -EINVAL; in smb2_calc_max_out_buf_len()
4339 return -EINVAL; in smb2_calc_max_out_buf_len()
4346 struct ksmbd_conn *conn = work->conn; in smb2_query_dir()
4349 struct ksmbd_share_config *share = work->tcon->share_conf; in smb2_query_dir()
4363 rsp->hdr.Status = STATUS_NO_MEMORY; in smb2_query_dir()
4365 return -ENOMEM; in smb2_query_dir()
4368 rc = verify_info_level(req->FileInformationClass); in smb2_query_dir()
4370 rc = -EFAULT; in smb2_query_dir()
4374 dir_fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in smb2_query_dir()
4376 rc = -EBADF; in smb2_query_dir()
4380 if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) || in smb2_query_dir()
4381 inode_permission(file_mnt_idmap(dir_fp->filp), in smb2_query_dir()
4382 file_inode(dir_fp->filp), in smb2_query_dir()
4384 pr_err("no right to enumerate directory (%pD)\n", dir_fp->filp); in smb2_query_dir()
4385 rc = -EACCES; in smb2_query_dir()
4389 if (!S_ISDIR(file_inode(dir_fp->filp)->i_mode)) { in smb2_query_dir()
4391 rc = -EINVAL; in smb2_query_dir()
4395 srch_flag = req->Flags; in smb2_query_dir()
4396 srch_ptr = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->FileNameOffset), in smb2_query_dir()
4397 le16_to_cpu(req->FileNameLength), 1, in smb2_query_dir()
4398 conn->local_nls); in smb2_query_dir()
4401 rc = -EINVAL; in smb2_query_dir()
4409 generic_file_llseek(dir_fp->filp, 0, SEEK_SET); in smb2_query_dir()
4413 d_info.wptr = (char *)rsp->Buffer; in smb2_query_dir()
4414 d_info.rptr = (char *)rsp->Buffer; in smb2_query_dir()
4417 le32_to_cpu(req->OutputBufferLength)); in smb2_query_dir()
4419 rc = -EINVAL; in smb2_query_dir()
4428 rc = ksmbd_populate_dot_dotdot_entries(work, req->FileInformationClass, in smb2_query_dir()
4431 if (rc == -ENOSPC) in smb2_query_dir()
4445 query_dir_private.info_level = req->FileInformationClass; in smb2_query_dir()
4446 dir_fp->readdir_data.private = &query_dir_private; in smb2_query_dir()
4447 set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir); in smb2_query_dir()
4450 rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx); in smb2_query_dir()
4460 * req->OutputBufferLength is too small to contain even one entry. in smb2_query_dir()
4465 if (rc > 0 || rc == -ENOSPC) in smb2_query_dir()
4478 rsp->hdr.Status = STATUS_NO_SUCH_FILE; in smb2_query_dir()
4480 dir_fp->dot_dotdot[0] = dir_fp->dot_dotdot[1] = 0; in smb2_query_dir()
4481 rsp->hdr.Status = STATUS_NO_MORE_FILES; in smb2_query_dir()
4483 rsp->StructureSize = cpu_to_le16(9); in smb2_query_dir()
4484 rsp->OutputBufferOffset = cpu_to_le16(0); in smb2_query_dir()
4485 rsp->OutputBufferLength = cpu_to_le32(0); in smb2_query_dir()
4486 rsp->Buffer[0] = 0; in smb2_query_dir()
4495 ((char *)rsp->Buffer + d_info.last_entry_offset)) in smb2_query_dir()
4496 ->NextEntryOffset = 0; in smb2_query_dir()
4498 d_info.data_count -= d_info.last_entry_off_align; in smb2_query_dir()
4500 rsp->StructureSize = cpu_to_le16(9); in smb2_query_dir()
4501 rsp->OutputBufferOffset = cpu_to_le16(72); in smb2_query_dir()
4502 rsp->OutputBufferLength = cpu_to_le32(d_info.data_count); in smb2_query_dir()
4520 if (rc == -EINVAL) in smb2_query_dir()
4521 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_query_dir()
4522 else if (rc == -EACCES) in smb2_query_dir()
4523 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_query_dir()
4524 else if (rc == -ENOENT) in smb2_query_dir()
4525 rsp->hdr.Status = STATUS_NO_SUCH_FILE; in smb2_query_dir()
4526 else if (rc == -EBADF) in smb2_query_dir()
4527 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_query_dir()
4528 else if (rc == -ENOMEM) in smb2_query_dir()
4529 rsp->hdr.Status = STATUS_NO_MEMORY; in smb2_query_dir()
4530 else if (rc == -EFAULT) in smb2_query_dir()
4531 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS; in smb2_query_dir()
4532 else if (rc == -EIO) in smb2_query_dir()
4533 rsp->hdr.Status = STATUS_FILE_CORRUPT_ERROR; in smb2_query_dir()
4534 if (!rsp->hdr.Status) in smb2_query_dir()
4535 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_query_dir()
4544 * buffer_check_err() - helper function to check buffer errors
4555 if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) { in buffer_check_err()
4557 rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH; in buffer_check_err()
4559 return -EINVAL; in buffer_check_err()
4569 sinfo = (struct smb2_file_standard_info *)rsp->Buffer; in get_standard_info_pipe()
4571 sinfo->AllocationSize = cpu_to_le64(4096); in get_standard_info_pipe()
4572 sinfo->EndOfFile = cpu_to_le64(0); in get_standard_info_pipe()
4573 sinfo->NumberOfLinks = cpu_to_le32(1); in get_standard_info_pipe()
4574 sinfo->DeletePending = 1; in get_standard_info_pipe()
4575 sinfo->Directory = 0; in get_standard_info_pipe()
4576 rsp->OutputBufferLength = in get_standard_info_pipe()
4585 file_info = (struct smb2_file_internal_info *)rsp->Buffer; in get_internal_info_pipe()
4588 file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63)); in get_internal_info_pipe()
4589 rsp->OutputBufferLength = in get_internal_info_pipe()
4605 id = req->VolatileFileId; in smb2_get_info_file_pipe()
4607 return -ENOENT; in smb2_get_info_file_pipe()
4610 req->FileInfoClass, req->VolatileFileId); in smb2_get_info_file_pipe()
4612 switch (req->FileInfoClass) { in smb2_get_info_file_pipe()
4615 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_file_pipe()
4620 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_file_pipe()
4625 req->FileInfoClass); in smb2_get_info_file_pipe()
4626 rc = -EOPNOTSUPP; in smb2_get_info_file_pipe()
4632 * smb2_get_ea() - handler for smb2 get extended attribute command
4651 struct mnt_idmap *idmap = file_mnt_idmap(fp->filp); in smb2_get_ea()
4653 if (!(fp->daccess & FILE_READ_EA_LE)) { in smb2_get_ea()
4655 fp->daccess); in smb2_get_ea()
4656 return -EACCES; in smb2_get_ea()
4659 path = &fp->filp->f_path; in smb2_get_ea()
4661 if (req->InputBufferLength) { in smb2_get_ea()
4662 if (le32_to_cpu(req->InputBufferLength) <= in smb2_get_ea()
4664 return -EINVAL; in smb2_get_ea()
4667 le16_to_cpu(req->InputBufferOffset)); in smb2_get_ea()
4670 if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY) in smb2_get_ea()
4673 le32_to_cpu(req->Flags)); in smb2_get_ea()
4678 le32_to_cpu(req->OutputBufferLength)); in smb2_get_ea()
4680 return -EINVAL; in smb2_get_ea()
4682 rc = ksmbd_vfs_listxattr(path->dentry, &xattr_list); in smb2_get_ea()
4684 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_get_ea()
4692 ptr = (char *)rsp->Buffer; in smb2_get_ea()
4716 if (req->InputBufferLength && in smb2_get_ea()
4717 strncmp(&name[XATTR_USER_PREFIX_LEN], ea_req->name, in smb2_get_ea()
4718 ea_req->EaNameLength)) in smb2_get_ea()
4726 name_len -= XATTR_USER_PREFIX_LEN; in smb2_get_ea()
4728 ptr = eainfo->name + name_len + 1; in smb2_get_ea()
4729 buf_free_len -= (offsetof(struct smb2_ea_info, name) + in smb2_get_ea()
4732 value_len = ksmbd_vfs_getxattr(idmap, path->dentry, in smb2_get_ea()
4735 rc = -ENOENT; in smb2_get_ea()
4736 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_get_ea()
4740 buf_free_len -= value_len; in smb2_get_ea()
4750 eainfo->Flags = 0; in smb2_get_ea()
4751 eainfo->EaNameLength = name_len; in smb2_get_ea()
4754 memcpy(eainfo->name, &name[XATTR_USER_PREFIX_LEN], in smb2_get_ea()
4757 memcpy(eainfo->name, name, name_len); in smb2_get_ea()
4759 eainfo->name[name_len] = '\0'; in smb2_get_ea()
4760 eainfo->EaValueLength = cpu_to_le16(value_len); in smb2_get_ea()
4765 alignment_bytes = ((next_offset + 3) & ~3) - next_offset; in smb2_get_ea()
4770 buf_free_len -= alignment_bytes; in smb2_get_ea()
4772 eainfo->NextEntryOffset = cpu_to_le32(next_offset); in smb2_get_ea()
4777 if (req->InputBufferLength) { in smb2_get_ea()
4784 prev_eainfo->NextEntryOffset = 0; in smb2_get_ea()
4788 rsp->hdr.Status = STATUS_NO_EAS_ON_FILE; in smb2_get_ea()
4789 rsp->OutputBufferLength = cpu_to_le32(rsp_data_cnt); in smb2_get_ea()
4800 file_info = (struct smb2_file_access_info *)rsp->Buffer; in get_file_access_info()
4801 file_info->AccessFlags = fp->daccess; in get_file_access_info()
4802 rsp->OutputBufferLength = in get_file_access_info()
4814 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_basic_info()
4816 fp->daccess); in get_file_basic_info()
4817 return -EACCES; in get_file_basic_info()
4820 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_basic_info()
4825 basic_info = (struct smb2_file_basic_info *)rsp->Buffer; in get_file_basic_info()
4826 basic_info->CreationTime = cpu_to_le64(fp->create_time); in get_file_basic_info()
4828 basic_info->LastAccessTime = cpu_to_le64(time); in get_file_basic_info()
4830 basic_info->LastWriteTime = cpu_to_le64(time); in get_file_basic_info()
4832 basic_info->ChangeTime = cpu_to_le64(time); in get_file_basic_info()
4833 basic_info->Attributes = fp->f_ci->m_fattr; in get_file_basic_info()
4834 basic_info->Pad1 = 0; in get_file_basic_info()
4835 rsp->OutputBufferLength = in get_file_basic_info()
4848 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_standard_info()
4853 sinfo = (struct smb2_file_standard_info *)rsp->Buffer; in get_file_standard_info()
4856 sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9); in get_file_standard_info()
4857 sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in get_file_standard_info()
4858 sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending); in get_file_standard_info()
4859 sinfo->DeletePending = delete_pending; in get_file_standard_info()
4860 sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0; in get_file_standard_info()
4861 rsp->OutputBufferLength = in get_file_standard_info()
4872 file_info = (struct smb2_file_alignment_info *)rsp->Buffer; in get_file_alignment_info()
4873 file_info->AlignmentRequirement = 0; in get_file_alignment_info()
4874 rsp->OutputBufferLength = in get_file_alignment_info()
4883 struct ksmbd_conn *conn = work->conn; in get_file_all_info()
4892 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_all_info()
4894 fp->daccess); in get_file_all_info()
4895 return -EACCES; in get_file_all_info()
4898 filename = convert_to_nt_pathname(work->tcon->share_conf, &fp->filp->f_path); in get_file_all_info()
4902 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_all_info()
4909 file_info = (struct smb2_file_all_info *)rsp->Buffer; in get_file_all_info()
4911 file_info->CreationTime = cpu_to_le64(fp->create_time); in get_file_all_info()
4913 file_info->LastAccessTime = cpu_to_le64(time); in get_file_all_info()
4915 file_info->LastWriteTime = cpu_to_le64(time); in get_file_all_info()
4917 file_info->ChangeTime = cpu_to_le64(time); in get_file_all_info()
4918 file_info->Attributes = fp->f_ci->m_fattr; in get_file_all_info()
4919 file_info->Pad1 = 0; in get_file_all_info()
4920 file_info->AllocationSize = in get_file_all_info()
4922 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in get_file_all_info()
4923 file_info->NumberOfLinks = in get_file_all_info()
4924 cpu_to_le32(get_nlink(&stat) - delete_pending); in get_file_all_info()
4925 file_info->DeletePending = delete_pending; in get_file_all_info()
4926 file_info->Directory = S_ISDIR(stat.mode) ? 1 : 0; in get_file_all_info()
4927 file_info->Pad2 = 0; in get_file_all_info()
4928 file_info->IndexNumber = cpu_to_le64(stat.ino); in get_file_all_info()
4929 file_info->EASize = 0; in get_file_all_info()
4930 file_info->AccessFlags = fp->daccess; in get_file_all_info()
4931 file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); in get_file_all_info()
4932 file_info->Mode = fp->coption; in get_file_all_info()
4933 file_info->AlignmentRequirement = 0; in get_file_all_info()
4934 conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename, in get_file_all_info()
4935 PATH_MAX, conn->local_nls, 0); in get_file_all_info()
4937 file_info->FileNameLength = cpu_to_le32(conv_len); in get_file_all_info()
4938 rsp->OutputBufferLength = in get_file_all_info()
4939 cpu_to_le32(sizeof(struct smb2_file_all_info) + conv_len - 1); in get_file_all_info()
4949 struct ksmbd_conn *conn = work->conn; in get_file_alternate_info()
4951 struct dentry *dentry = fp->filp->f_path.dentry; in get_file_alternate_info()
4954 spin_lock(&dentry->d_lock); in get_file_alternate_info()
4955 file_info = (struct smb2_file_alt_name_info *)rsp->Buffer; in get_file_alternate_info()
4957 dentry->d_name.name, in get_file_alternate_info()
4958 file_info->FileName); in get_file_alternate_info()
4959 spin_unlock(&dentry->d_lock); in get_file_alternate_info()
4960 file_info->FileNameLength = cpu_to_le32(conv_len); in get_file_alternate_info()
4961 rsp->OutputBufferLength = in get_file_alternate_info()
4970 struct ksmbd_conn *conn = work->conn; in get_file_stream_info()
4974 const struct path *path = &fp->filp->f_path; in get_file_stream_info()
4981 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_stream_info()
4986 file_info = (struct smb2_file_stream_info *)rsp->Buffer; in get_file_stream_info()
4990 le32_to_cpu(req->OutputBufferLength)); in get_file_stream_info()
4994 xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list); in get_file_stream_info()
5013 stream_name_len = streamlen - (XATTR_USER_PREFIX_LEN + in get_file_stream_info()
5032 file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes]; in get_file_stream_info()
5033 streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName, in get_file_stream_info()
5035 conn->local_nls, 0); in get_file_stream_info()
5038 file_info->StreamNameLength = cpu_to_le32(streamlen); in get_file_stream_info()
5039 file_info->StreamSize = cpu_to_le64(stream_name_len); in get_file_stream_info()
5040 file_info->StreamAllocationSize = cpu_to_le64(stream_name_len); in get_file_stream_info()
5043 buf_free_len -= next; in get_file_stream_info()
5044 file_info->NextEntryOffset = cpu_to_le32(next); in get_file_stream_info()
5051 &rsp->Buffer[nbytes]; in get_file_stream_info()
5052 streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName, in get_file_stream_info()
5053 "::$DATA", 7, conn->local_nls, 0); in get_file_stream_info()
5055 file_info->StreamNameLength = cpu_to_le32(streamlen); in get_file_stream_info()
5056 file_info->StreamSize = cpu_to_le64(stat.size); in get_file_stream_info()
5057 file_info->StreamAllocationSize = cpu_to_le64(stat.blocks << 9); in get_file_stream_info()
5062 file_info->NextEntryOffset = 0; in get_file_stream_info()
5065 rsp->OutputBufferLength = cpu_to_le32(nbytes); in get_file_stream_info()
5077 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_internal_info()
5082 file_info = (struct smb2_file_internal_info *)rsp->Buffer; in get_file_internal_info()
5083 file_info->IndexNumber = cpu_to_le64(stat.ino); in get_file_internal_info()
5084 rsp->OutputBufferLength = in get_file_internal_info()
5098 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_network_open_info()
5100 fp->daccess); in get_file_network_open_info()
5101 return -EACCES; in get_file_network_open_info()
5104 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_network_open_info()
5109 file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer; in get_file_network_open_info()
5111 file_info->CreationTime = cpu_to_le64(fp->create_time); in get_file_network_open_info()
5113 file_info->LastAccessTime = cpu_to_le64(time); in get_file_network_open_info()
5115 file_info->LastWriteTime = cpu_to_le64(time); in get_file_network_open_info()
5117 file_info->ChangeTime = cpu_to_le64(time); in get_file_network_open_info()
5118 file_info->Attributes = fp->f_ci->m_fattr; in get_file_network_open_info()
5119 file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); in get_file_network_open_info()
5120 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in get_file_network_open_info()
5121 file_info->Reserved = cpu_to_le32(0); in get_file_network_open_info()
5122 rsp->OutputBufferLength = in get_file_network_open_info()
5131 file_info = (struct smb2_file_ea_info *)rsp->Buffer; in get_file_ea_info()
5132 file_info->EASize = 0; in get_file_ea_info()
5133 rsp->OutputBufferLength = in get_file_ea_info()
5142 file_info = (struct smb2_file_pos_info *)rsp->Buffer; in get_file_position_info()
5143 file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); in get_file_position_info()
5144 rsp->OutputBufferLength = in get_file_position_info()
5153 file_info = (struct smb2_file_mode_info *)rsp->Buffer; in get_file_mode_info()
5154 file_info->Mode = fp->coption & FILE_MODE_INFO_MASK; in get_file_mode_info()
5155 rsp->OutputBufferLength = in get_file_mode_info()
5166 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_compression_info()
5171 file_info = (struct smb2_file_comp_info *)rsp->Buffer; in get_file_compression_info()
5172 file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9); in get_file_compression_info()
5173 file_info->CompressionFormat = COMPRESSION_FORMAT_NONE; in get_file_compression_info()
5174 file_info->CompressionUnitShift = 0; in get_file_compression_info()
5175 file_info->ChunkShift = 0; in get_file_compression_info()
5176 file_info->ClusterShift = 0; in get_file_compression_info()
5177 memset(&file_info->Reserved[0], 0, 3); in get_file_compression_info()
5179 rsp->OutputBufferLength = in get_file_compression_info()
5190 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_attribute_tag_info()
5192 fp->daccess); in get_file_attribute_tag_info()
5193 return -EACCES; in get_file_attribute_tag_info()
5196 file_info = (struct smb2_file_attr_tag_info *)rsp->Buffer; in get_file_attribute_tag_info()
5197 file_info->FileAttributes = fp->f_ci->m_fattr; in get_file_attribute_tag_info()
5198 file_info->ReparseTag = 0; in get_file_attribute_tag_info()
5199 rsp->OutputBufferLength = in get_file_attribute_tag_info()
5208 struct inode *inode = file_inode(fp->filp); in find_file_posix_info()
5209 struct mnt_idmap *idmap = file_mnt_idmap(fp->filp); in find_file_posix_info()
5217 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in find_file_posix_info()
5222 file_info = (struct smb311_posix_qinfo *)rsp->Buffer; in find_file_posix_info()
5223 file_info->CreationTime = cpu_to_le64(fp->create_time); in find_file_posix_info()
5225 file_info->LastAccessTime = cpu_to_le64(time); in find_file_posix_info()
5227 file_info->LastWriteTime = cpu_to_le64(time); in find_file_posix_info()
5229 file_info->ChangeTime = cpu_to_le64(time); in find_file_posix_info()
5230 file_info->DosAttributes = fp->f_ci->m_fattr; in find_file_posix_info()
5231 file_info->Inode = cpu_to_le64(stat.ino); in find_file_posix_info()
5232 file_info->EndOfFile = cpu_to_le64(stat.size); in find_file_posix_info()
5233 file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); in find_file_posix_info()
5234 file_info->HardLinks = cpu_to_le32(stat.nlink); in find_file_posix_info()
5235 file_info->Mode = cpu_to_le32(stat.mode & 0777); in find_file_posix_info()
5238 file_info->Mode |= cpu_to_le32(POSIX_TYPE_DIR << POSIX_FILETYPE_SHIFT); in find_file_posix_info()
5241 file_info->Mode |= cpu_to_le32(POSIX_TYPE_SYMLINK << POSIX_FILETYPE_SHIFT); in find_file_posix_info()
5244 file_info->Mode |= cpu_to_le32(POSIX_TYPE_CHARDEV << POSIX_FILETYPE_SHIFT); in find_file_posix_info()
5247 file_info->Mode |= cpu_to_le32(POSIX_TYPE_BLKDEV << POSIX_FILETYPE_SHIFT); in find_file_posix_info()
5250 file_info->Mode |= cpu_to_le32(POSIX_TYPE_FIFO << POSIX_FILETYPE_SHIFT); in find_file_posix_info()
5253 file_info->Mode |= cpu_to_le32(POSIX_TYPE_SOCKET << POSIX_FILETYPE_SHIFT); in find_file_posix_info()
5256 file_info->DeviceId = cpu_to_le32(stat.rdev); in find_file_posix_info()
5264 SIDUNIX_USER, (struct smb_sid *)&file_info->Sids[0]); in find_file_posix_info()
5266 SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]); in find_file_posix_info()
5268 rsp->OutputBufferLength = cpu_to_le32(out_buf_len); in find_file_posix_info()
5282 if (test_share_config_flag(work->tcon->share_conf, in smb2_get_info_file()
5285 return smb2_get_info_file_pipe(work->sess, req, rsp, in smb2_get_info_file()
5286 work->response_buf); in smb2_get_info_file()
5289 if (work->next_smb2_rcv_hdr_off) { in smb2_get_info_file()
5290 if (!has_file_id(req->VolatileFileId)) { in smb2_get_info_file()
5292 work->compound_fid); in smb2_get_info_file()
5293 id = work->compound_fid; in smb2_get_info_file()
5294 pid = work->compound_pfid; in smb2_get_info_file()
5299 id = req->VolatileFileId; in smb2_get_info_file()
5300 pid = req->PersistentFileId; in smb2_get_info_file()
5305 return -ENOENT; in smb2_get_info_file()
5307 fileinfoclass = req->FileInfoClass; in smb2_get_info_file()
5311 get_file_access_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5315 rc = get_file_basic_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5319 rc = get_file_standard_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5323 get_file_alignment_info(rsp, work->response_buf); in smb2_get_info_file()
5327 rc = get_file_all_info(work, rsp, fp, work->response_buf); in smb2_get_info_file()
5331 get_file_alternate_info(work, rsp, fp, work->response_buf); in smb2_get_info_file()
5335 rc = get_file_stream_info(work, rsp, fp, work->response_buf); in smb2_get_info_file()
5339 rc = get_file_internal_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5343 rc = get_file_network_open_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5347 get_file_ea_info(rsp, work->response_buf); in smb2_get_info_file()
5351 rc = smb2_get_ea(work, fp, req, rsp, work->response_buf); in smb2_get_info_file()
5355 get_file_position_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5359 get_file_mode_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5363 rc = get_file_compression_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5367 rc = get_file_attribute_tag_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5370 if (!work->tcon->posix_extensions) { in smb2_get_info_file()
5372 rc = -EOPNOTSUPP; in smb2_get_info_file()
5374 rc = find_file_posix_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5380 rc = -EOPNOTSUPP; in smb2_get_info_file()
5383 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_file()
5384 rsp, work->response_buf); in smb2_get_info_file()
5393 struct ksmbd_session *sess = work->sess; in smb2_get_info_filesystem()
5394 struct ksmbd_conn *conn = work->conn; in smb2_get_info_filesystem()
5395 struct ksmbd_share_config *share = work->tcon->share_conf; in smb2_get_info_filesystem()
5401 if (!share->path) in smb2_get_info_filesystem()
5402 return -EIO; in smb2_get_info_filesystem()
5404 rc = kern_path(share->path, LOOKUP_NO_SYMLINKS, &path); in smb2_get_info_filesystem()
5407 return -EIO; in smb2_get_info_filesystem()
5412 pr_err("cannot do stat of path %s\n", share->path); in smb2_get_info_filesystem()
5414 return -EIO; in smb2_get_info_filesystem()
5417 fsinfoclass = req->FileInfoClass; in smb2_get_info_filesystem()
5424 info = (struct filesystem_device_info *)rsp->Buffer; in smb2_get_info_filesystem()
5426 info->DeviceType = cpu_to_le32(FILE_DEVICE_DISK); in smb2_get_info_filesystem()
5427 info->DeviceCharacteristics = in smb2_get_info_filesystem()
5429 if (!test_tree_conn_flag(work->tcon, in smb2_get_info_filesystem()
5431 info->DeviceCharacteristics |= in smb2_get_info_filesystem()
5433 rsp->OutputBufferLength = cpu_to_le32(8); in smb2_get_info_filesystem()
5441 info = (struct filesystem_attribute_info *)rsp->Buffer; in smb2_get_info_filesystem()
5442 info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS | in smb2_get_info_filesystem()
5449 info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps); in smb2_get_info_filesystem()
5451 if (test_share_config_flag(work->tcon->share_conf, in smb2_get_info_filesystem()
5453 info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS); in smb2_get_info_filesystem()
5455 info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen); in smb2_get_info_filesystem()
5456 len = smbConvertToUTF16((__le16 *)info->FileSystemName, in smb2_get_info_filesystem()
5457 "NTFS", PATH_MAX, conn->local_nls, 0); in smb2_get_info_filesystem()
5459 info->FileSystemNameLen = cpu_to_le32(len); in smb2_get_info_filesystem()
5461 rsp->OutputBufferLength = cpu_to_le32(sz); in smb2_get_info_filesystem()
5470 info = (struct filesystem_vol_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5471 info->VolumeCreationTime = 0; in smb2_get_info_filesystem()
5472 serial_crc = crc32_le(serial_crc, share->name, in smb2_get_info_filesystem()
5473 strlen(share->name)); in smb2_get_info_filesystem()
5474 serial_crc = crc32_le(serial_crc, share->path, in smb2_get_info_filesystem()
5475 strlen(share->path)); in smb2_get_info_filesystem()
5479 info->SerialNumber = cpu_to_le32(serial_crc); in smb2_get_info_filesystem()
5480 len = smbConvertToUTF16((__le16 *)info->VolumeLabel, in smb2_get_info_filesystem()
5481 share->name, PATH_MAX, in smb2_get_info_filesystem()
5482 conn->local_nls, 0); in smb2_get_info_filesystem()
5484 info->VolumeLabelSize = cpu_to_le32(len); in smb2_get_info_filesystem()
5485 info->Reserved = 0; in smb2_get_info_filesystem()
5487 rsp->OutputBufferLength = cpu_to_le32(sz); in smb2_get_info_filesystem()
5494 info = (struct filesystem_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5495 info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks); in smb2_get_info_filesystem()
5496 info->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree); in smb2_get_info_filesystem()
5497 info->SectorsPerAllocationUnit = cpu_to_le32(1); in smb2_get_info_filesystem()
5498 info->BytesPerSector = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5499 rsp->OutputBufferLength = cpu_to_le32(24); in smb2_get_info_filesystem()
5506 info = (struct smb2_fs_full_size_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5507 info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks); in smb2_get_info_filesystem()
5508 info->CallerAvailableAllocationUnits = in smb2_get_info_filesystem()
5510 info->ActualAvailableAllocationUnits = in smb2_get_info_filesystem()
5512 info->SectorsPerAllocationUnit = cpu_to_le32(1); in smb2_get_info_filesystem()
5513 info->BytesPerSector = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5514 rsp->OutputBufferLength = cpu_to_le32(32); in smb2_get_info_filesystem()
5521 info = (struct object_id_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5523 if (!user_guest(sess->user)) in smb2_get_info_filesystem()
5524 memcpy(info->objid, user_passkey(sess->user), 16); in smb2_get_info_filesystem()
5526 memset(info->objid, 0, 16); in smb2_get_info_filesystem()
5528 info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC); in smb2_get_info_filesystem()
5529 info->extended_info.version = cpu_to_le32(1); in smb2_get_info_filesystem()
5530 info->extended_info.release = cpu_to_le32(1); in smb2_get_info_filesystem()
5531 info->extended_info.rel_date = 0; in smb2_get_info_filesystem()
5532 memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0")); in smb2_get_info_filesystem()
5533 rsp->OutputBufferLength = cpu_to_le32(64); in smb2_get_info_filesystem()
5540 min_t(unsigned int, path.mnt->mnt_sb->s_blocksize, 4096); in smb2_get_info_filesystem()
5542 info = (struct smb3_fs_ss_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5544 info->LogicalBytesPerSector = cpu_to_le32(sector_size); in smb2_get_info_filesystem()
5545 info->PhysicalBytesPerSectorForAtomicity = in smb2_get_info_filesystem()
5547 info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size); in smb2_get_info_filesystem()
5548 info->FSEffPhysicalBytesPerSectorForAtomicity = in smb2_get_info_filesystem()
5550 info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE | in smb2_get_info_filesystem()
5552 info->ByteOffsetForSectorAlignment = 0; in smb2_get_info_filesystem()
5553 info->ByteOffsetForPartitionAlignment = 0; in smb2_get_info_filesystem()
5554 rsp->OutputBufferLength = cpu_to_le32(28); in smb2_get_info_filesystem()
5567 info = (struct smb2_fs_control_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5568 info->FreeSpaceStartFiltering = 0; in smb2_get_info_filesystem()
5569 info->FreeSpaceThreshold = 0; in smb2_get_info_filesystem()
5570 info->FreeSpaceStopFiltering = 0; in smb2_get_info_filesystem()
5571 info->DefaultQuotaThreshold = cpu_to_le64(SMB2_NO_FID); in smb2_get_info_filesystem()
5572 info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID); in smb2_get_info_filesystem()
5573 info->Padding = 0; in smb2_get_info_filesystem()
5574 rsp->OutputBufferLength = cpu_to_le32(48); in smb2_get_info_filesystem()
5581 if (!work->tcon->posix_extensions) { in smb2_get_info_filesystem()
5583 rc = -EOPNOTSUPP; in smb2_get_info_filesystem()
5585 info = (struct filesystem_posix_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5586 info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5587 info->BlockSize = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5588 info->TotalBlocks = cpu_to_le64(stfs.f_blocks); in smb2_get_info_filesystem()
5589 info->BlocksAvail = cpu_to_le64(stfs.f_bfree); in smb2_get_info_filesystem()
5590 info->UserBlocksAvail = cpu_to_le64(stfs.f_bavail); in smb2_get_info_filesystem()
5591 info->TotalFileNodes = cpu_to_le64(stfs.f_files); in smb2_get_info_filesystem()
5592 info->FreeFileNodes = cpu_to_le64(stfs.f_ffree); in smb2_get_info_filesystem()
5593 rsp->OutputBufferLength = cpu_to_le32(56); in smb2_get_info_filesystem()
5599 return -EOPNOTSUPP; in smb2_get_info_filesystem()
5601 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_filesystem()
5602 rsp, work->response_buf); in smb2_get_info_filesystem()
5613 struct smb_ntsd *pntsd = (struct smb_ntsd *)rsp->Buffer, *ppntsd = NULL; in smb2_get_info_sec()
5618 int addition_info = le32_to_cpu(req->AdditionalInformation); in smb2_get_info_sec()
5627 pntsd->revision = cpu_to_le16(1); in smb2_get_info_sec()
5628 pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PROTECTED); in smb2_get_info_sec()
5629 pntsd->osidoffset = 0; in smb2_get_info_sec()
5630 pntsd->gsidoffset = 0; in smb2_get_info_sec()
5631 pntsd->sacloffset = 0; in smb2_get_info_sec()
5632 pntsd->dacloffset = 0; in smb2_get_info_sec()
5635 rsp->OutputBufferLength = cpu_to_le32(secdesclen); in smb2_get_info_sec()
5640 if (work->next_smb2_rcv_hdr_off) { in smb2_get_info_sec()
5641 if (!has_file_id(req->VolatileFileId)) { in smb2_get_info_sec()
5643 work->compound_fid); in smb2_get_info_sec()
5644 id = work->compound_fid; in smb2_get_info_sec()
5645 pid = work->compound_pfid; in smb2_get_info_sec()
5650 id = req->VolatileFileId; in smb2_get_info_sec()
5651 pid = req->PersistentFileId; in smb2_get_info_sec()
5656 return -ENOENT; in smb2_get_info_sec()
5658 idmap = file_mnt_idmap(fp->filp); in smb2_get_info_sec()
5659 inode = file_inode(fp->filp); in smb2_get_info_sec()
5662 if (test_share_config_flag(work->tcon->share_conf, in smb2_get_info_sec()
5664 ppntsd_size = ksmbd_vfs_get_sd_xattr(work->conn, idmap, in smb2_get_info_sec()
5665 fp->filp->f_path.dentry, in smb2_get_info_sec()
5679 rsp->OutputBufferLength = cpu_to_le32(secdesclen); in smb2_get_info_sec()
5684 * smb2_query_info() - handler for smb2 query info command
5700 rc = -ENOMEM; in smb2_query_info()
5704 switch (req->InfoType) { in smb2_query_info()
5719 req->InfoType); in smb2_query_info()
5720 rc = -EOPNOTSUPP; in smb2_query_info()
5725 rsp->StructureSize = cpu_to_le16(9); in smb2_query_info()
5726 rsp->OutputBufferOffset = cpu_to_le16(72); in smb2_query_info()
5729 le32_to_cpu(rsp->OutputBufferLength)); in smb2_query_info()
5734 if (rc == -EACCES) in smb2_query_info()
5735 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_query_info()
5736 else if (rc == -ENOENT) in smb2_query_info()
5737 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_query_info()
5738 else if (rc == -EIO) in smb2_query_info()
5739 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_query_info()
5740 else if (rc == -ENOMEM) in smb2_query_info()
5741 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_query_info()
5742 else if (rc == -EOPNOTSUPP || rsp->hdr.Status == 0) in smb2_query_info()
5743 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS; in smb2_query_info()
5754 * smb2_close_pipe() - handler for closing IPC pipe
5767 id = req->VolatileFileId; in smb2_close_pipe()
5768 ksmbd_session_rpc_close(work->sess, id); in smb2_close_pipe()
5770 rsp->StructureSize = cpu_to_le16(60); in smb2_close_pipe()
5771 rsp->Flags = 0; in smb2_close_pipe()
5772 rsp->Reserved = 0; in smb2_close_pipe()
5773 rsp->CreationTime = 0; in smb2_close_pipe()
5774 rsp->LastAccessTime = 0; in smb2_close_pipe()
5775 rsp->LastWriteTime = 0; in smb2_close_pipe()
5776 rsp->ChangeTime = 0; in smb2_close_pipe()
5777 rsp->AllocationSize = 0; in smb2_close_pipe()
5778 rsp->EndOfFile = 0; in smb2_close_pipe()
5779 rsp->Attributes = 0; in smb2_close_pipe()
5786 * smb2_close() - handler for smb2 close file command
5797 struct ksmbd_conn *conn = work->conn; in smb2_close()
5806 if (test_share_config_flag(work->tcon->share_conf, in smb2_close()
5812 sess_id = le64_to_cpu(req->hdr.SessionId); in smb2_close()
5813 if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS) in smb2_close()
5814 sess_id = work->compound_sid; in smb2_close()
5816 work->compound_sid = 0; in smb2_close()
5818 work->compound_sid = sess_id; in smb2_close()
5820 rsp->hdr.Status = STATUS_USER_SESSION_DELETED; in smb2_close()
5821 if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS) in smb2_close()
5822 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_close()
5823 err = -EBADF; in smb2_close()
5827 if (work->next_smb2_rcv_hdr_off && in smb2_close()
5828 !has_file_id(req->VolatileFileId)) { in smb2_close()
5829 if (!has_file_id(work->compound_fid)) { in smb2_close()
5832 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_close()
5833 err = -EBADF; in smb2_close()
5838 work->compound_fid, in smb2_close()
5839 work->compound_pfid); in smb2_close()
5840 volatile_id = work->compound_fid; in smb2_close()
5843 work->compound_fid = KSMBD_NO_FID; in smb2_close()
5844 work->compound_pfid = KSMBD_NO_FID; in smb2_close()
5847 volatile_id = req->VolatileFileId; in smb2_close()
5851 rsp->StructureSize = cpu_to_le16(60); in smb2_close()
5852 rsp->Reserved = 0; in smb2_close()
5854 if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) { in smb2_close()
5860 err = -ENOENT; in smb2_close()
5864 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in smb2_close()
5871 rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB; in smb2_close()
5872 rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 : in smb2_close()
5874 rsp->EndOfFile = cpu_to_le64(stat.size); in smb2_close()
5875 rsp->Attributes = fp->f_ci->m_fattr; in smb2_close()
5876 rsp->CreationTime = cpu_to_le64(fp->create_time); in smb2_close()
5878 rsp->LastAccessTime = cpu_to_le64(time); in smb2_close()
5880 rsp->LastWriteTime = cpu_to_le64(time); in smb2_close()
5882 rsp->ChangeTime = cpu_to_le64(time); in smb2_close()
5885 rsp->Flags = 0; in smb2_close()
5886 rsp->AllocationSize = 0; in smb2_close()
5887 rsp->EndOfFile = 0; in smb2_close()
5888 rsp->Attributes = 0; in smb2_close()
5889 rsp->CreationTime = 0; in smb2_close()
5890 rsp->LastAccessTime = 0; in smb2_close()
5891 rsp->LastWriteTime = 0; in smb2_close()
5892 rsp->ChangeTime = 0; in smb2_close()
5902 if (rsp->hdr.Status == 0) in smb2_close()
5903 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_close()
5911 * smb2_echo() - handler for smb2 echo(ping) command
5918 struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf); in smb2_echo()
5922 if (work->next_smb2_rcv_hdr_off) in smb2_echo()
5925 rsp->StructureSize = cpu_to_le16(4); in smb2_echo()
5926 rsp->Reserved = 0; in smb2_echo()
5935 struct ksmbd_share_config *share = fp->tcon->share_conf; in smb2_rename()
5940 new_name = smb2_get_name(file_info->FileName, in smb2_rename()
5941 le32_to_cpu(file_info->FileNameLength), in smb2_rename()
5957 if (len > 0 && new_name[len - 1] != '/') { in smb2_rename()
5959 rc = -ESHARE; in smb2_rename()
5970 rc = ksmbd_vfs_setxattr(file_mnt_idmap(fp->filp), in smb2_rename()
5971 &fp->filp->f_path, in smb2_rename()
5977 rc = -EINVAL; in smb2_rename()
5986 rc = -ENOENT; in smb2_rename()
5991 if (!file_info->ReplaceIfExists) in smb2_rename()
5994 rc = ksmbd_vfs_rename(work, &fp->filp->f_path, new_name, flags); in smb2_rename()
6014 le32_to_cpu(file_info->FileNameLength)) in smb2_create_link()
6015 return -EINVAL; in smb2_create_link()
6020 return -ENOMEM; in smb2_create_link()
6022 link_name = smb2_get_name(file_info->FileName, in smb2_create_link()
6023 le32_to_cpu(file_info->FileNameLength), in smb2_create_link()
6025 if (IS_ERR(link_name) || S_ISDIR(file_inode(filp)->i_mode)) { in smb2_create_link()
6026 rc = -EINVAL; in smb2_create_link()
6033 rc = -EINVAL; in smb2_create_link()
6041 if (rc != -ENOENT) in smb2_create_link()
6046 if (file_info->ReplaceIfExists) { in smb2_create_link()
6050 rc = -EINVAL; in smb2_create_link()
6058 rc = -EEXIST; in smb2_create_link()
6066 rc = -EINVAL; in smb2_create_link()
6087 if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE)) in set_file_basic_info()
6088 return -EACCES; in set_file_basic_info()
6091 filp = fp->filp; in set_file_basic_info()
6095 if (file_info->CreationTime) in set_file_basic_info()
6096 fp->create_time = le64_to_cpu(file_info->CreationTime); in set_file_basic_info()
6098 if (file_info->LastAccessTime) { in set_file_basic_info()
6099 attrs.ia_atime = ksmbd_NTtimeToUnix(file_info->LastAccessTime); in set_file_basic_info()
6103 if (file_info->ChangeTime) in set_file_basic_info()
6105 ksmbd_NTtimeToUnix(file_info->ChangeTime)); in set_file_basic_info()
6107 if (file_info->LastWriteTime) { in set_file_basic_info()
6108 attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime); in set_file_basic_info()
6112 if (file_info->Attributes) { in set_file_basic_info()
6113 if (!S_ISDIR(inode->i_mode) && in set_file_basic_info()
6114 file_info->Attributes & FILE_ATTRIBUTE_DIRECTORY_LE) { in set_file_basic_info()
6116 return -EINVAL; in set_file_basic_info()
6119 if (!(S_ISDIR(inode->i_mode) && file_info->Attributes == FILE_ATTRIBUTE_NORMAL_LE)) in set_file_basic_info()
6120 fp->f_ci->m_fattr = file_info->Attributes | in set_file_basic_info()
6121 (fp->f_ci->m_fattr & FILE_ATTRIBUTE_DIRECTORY_LE); in set_file_basic_info()
6125 (file_info->CreationTime || file_info->Attributes)) { in set_file_basic_info()
6129 da.itime = fp->itime; in set_file_basic_info()
6130 da.create_time = fp->create_time; in set_file_basic_info()
6131 da.attr = le32_to_cpu(fp->f_ci->m_fattr); in set_file_basic_info()
6135 rc = ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da, in set_file_basic_info()
6144 struct dentry *dentry = filp->f_path.dentry; in set_file_basic_info()
6148 return -EACCES; in set_file_basic_info()
6172 if (!(fp->daccess & FILE_WRITE_DATA_LE)) in set_file_allocation_info()
6173 return -EACCES; in set_file_allocation_info()
6175 rc = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in set_file_allocation_info()
6180 alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9; in set_file_allocation_info()
6181 inode = file_inode(fp->filp); in set_file_allocation_info()
6185 rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0, in set_file_allocation_info()
6187 if (rc && rc != -EOPNOTSUPP) { in set_file_allocation_info()
6220 if (!(fp->daccess & FILE_WRITE_DATA_LE)) in set_end_of_file_info()
6221 return -EACCES; in set_end_of_file_info()
6223 newsize = le64_to_cpu(file_eof_info->EndOfFile); in set_end_of_file_info()
6224 inode = file_inode(fp->filp); in set_end_of_file_info()
6233 if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) { in set_end_of_file_info()
6238 if (rc != -EAGAIN) in set_end_of_file_info()
6239 rc = -EBADF; in set_end_of_file_info()
6250 if (!(fp->daccess & FILE_DELETE_LE)) { in set_rename_info()
6251 pr_err("no right to delete : 0x%x\n", fp->daccess); in set_rename_info()
6252 return -EACCES; in set_rename_info()
6256 le32_to_cpu(rename_info->FileNameLength)) in set_rename_info()
6257 return -EINVAL; in set_rename_info()
6259 if (!le32_to_cpu(rename_info->FileNameLength)) in set_rename_info()
6260 return -EINVAL; in set_rename_info()
6262 return smb2_rename(work, fp, rename_info, work->conn->local_nls); in set_rename_info()
6270 if (!(fp->daccess & FILE_DELETE_LE)) { in set_file_disposition_info()
6271 pr_err("no right to delete : 0x%x\n", fp->daccess); in set_file_disposition_info()
6272 return -EACCES; in set_file_disposition_info()
6275 inode = file_inode(fp->filp); in set_file_disposition_info()
6276 if (file_info->DeletePending) { in set_file_disposition_info()
6277 if (S_ISDIR(inode->i_mode) && in set_file_disposition_info()
6278 ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY) in set_file_disposition_info()
6279 return -EBUSY; in set_file_disposition_info()
6294 inode = file_inode(fp->filp); in set_file_position_info()
6295 current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset); in set_file_position_info()
6296 sector_size = inode->i_sb->s_blocksize; in set_file_position_info()
6299 (fp->coption == FILE_NO_INTERMEDIATE_BUFFERING_LE && in set_file_position_info()
6300 current_byte_offset & (sector_size - 1))) { in set_file_position_info()
6303 return -EINVAL; in set_file_position_info()
6306 fp->filp->f_pos = current_byte_offset; in set_file_position_info()
6315 mode = file_info->Mode; in set_file_mode_info()
6319 return -EINVAL; in set_file_mode_info()
6326 ksmbd_vfs_set_fadvise(fp->filp, mode); in set_file_mode_info()
6327 fp->coption = mode; in set_file_mode_info()
6332 * smb2_set_info_file() - handler for smb2 set info command
6345 unsigned int buf_len = le32_to_cpu(req->BufferLength); in smb2_set_info_file()
6346 char *buffer = (char *)req + le16_to_cpu(req->BufferOffset); in smb2_set_info_file()
6348 switch (req->FileInfoClass) { in smb2_set_info_file()
6352 return -EINVAL; in smb2_set_info_file()
6359 return -EINVAL; in smb2_set_info_file()
6367 return -EINVAL; in smb2_set_info_file()
6375 return -EINVAL; in smb2_set_info_file()
6384 return -EINVAL; in smb2_set_info_file()
6386 return smb2_create_link(work, work->tcon->share_conf, in smb2_set_info_file()
6388 buf_len, fp->filp, in smb2_set_info_file()
6389 work->conn->local_nls); in smb2_set_info_file()
6394 return -EINVAL; in smb2_set_info_file()
6401 if (!(fp->daccess & FILE_WRITE_EA_LE)) { in smb2_set_info_file()
6403 fp->daccess); in smb2_set_info_file()
6404 return -EACCES; in smb2_set_info_file()
6408 return -EINVAL; in smb2_set_info_file()
6411 buf_len, &fp->filp->f_path, true); in smb2_set_info_file()
6416 return -EINVAL; in smb2_set_info_file()
6423 return -EINVAL; in smb2_set_info_file()
6429 pr_err("Unimplemented Fileinfoclass :%d\n", req->FileInfoClass); in smb2_set_info_file()
6430 return -EOPNOTSUPP; in smb2_set_info_file()
6438 fp->saccess |= FILE_SHARE_DELETE_LE; in smb2_set_info_sec()
6440 return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd, in smb2_set_info_sec()
6445 * smb2_set_info() - handler for smb2 set info command handler
6460 if (work->next_smb2_rcv_hdr_off) { in smb2_set_info()
6463 if (!has_file_id(req->VolatileFileId)) { in smb2_set_info()
6465 work->compound_fid); in smb2_set_info()
6466 id = work->compound_fid; in smb2_set_info()
6467 pid = work->compound_pfid; in smb2_set_info()
6470 req = smb2_get_msg(work->request_buf); in smb2_set_info()
6471 rsp = smb2_get_msg(work->response_buf); in smb2_set_info()
6474 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_set_info()
6477 rc = -EACCES; in smb2_set_info()
6482 id = req->VolatileFileId; in smb2_set_info()
6483 pid = req->PersistentFileId; in smb2_set_info()
6489 rc = -ENOENT; in smb2_set_info()
6493 switch (req->InfoType) { in smb2_set_info()
6496 rc = smb2_set_info_file(work, fp, req, work->tcon->share_conf); in smb2_set_info()
6501 rc = -ENOMEM; in smb2_set_info()
6505 le32_to_cpu(req->AdditionalInformation), in smb2_set_info()
6506 (char *)req + le16_to_cpu(req->BufferOffset), in smb2_set_info()
6507 le32_to_cpu(req->BufferLength)); in smb2_set_info()
6511 rc = -EOPNOTSUPP; in smb2_set_info()
6517 rsp->StructureSize = cpu_to_le16(2); in smb2_set_info()
6526 if (rc == -EACCES || rc == -EPERM || rc == -EXDEV) in smb2_set_info()
6527 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_set_info()
6528 else if (rc == -EINVAL) in smb2_set_info()
6529 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_set_info()
6530 else if (rc == -ESHARE) in smb2_set_info()
6531 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_set_info()
6532 else if (rc == -ENOENT) in smb2_set_info()
6533 rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID; in smb2_set_info()
6534 else if (rc == -EBUSY || rc == -ENOTEMPTY) in smb2_set_info()
6535 rsp->hdr.Status = STATUS_DIRECTORY_NOT_EMPTY; in smb2_set_info()
6536 else if (rc == -EAGAIN) in smb2_set_info()
6537 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in smb2_set_info()
6538 else if (rc == -EBADF || rc == -ESTALE) in smb2_set_info()
6539 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_set_info()
6540 else if (rc == -EEXIST) in smb2_set_info()
6541 rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION; in smb2_set_info()
6542 else if (rsp->hdr.Status == 0 || rc == -EOPNOTSUPP) in smb2_set_info()
6543 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS; in smb2_set_info()
6551 * smb2_read_pipe() - handler for smb2 read from IPC pipe
6566 id = req->VolatileFileId; in smb2_read_pipe()
6568 rpc_resp = ksmbd_rpc_read(work->sess, id); in smb2_read_pipe()
6572 if (rpc_resp->flags != KSMBD_RPC_OK) { in smb2_read_pipe()
6573 err = -EINVAL; in smb2_read_pipe()
6578 kvmalloc(rpc_resp->payload_sz, KSMBD_DEFAULT_GFP); in smb2_read_pipe()
6580 err = -ENOMEM; in smb2_read_pipe()
6584 memcpy(aux_payload_buf, rpc_resp->payload, rpc_resp->payload_sz); in smb2_read_pipe()
6586 nbytes = rpc_resp->payload_sz; in smb2_read_pipe()
6602 rsp->StructureSize = cpu_to_le16(17); in smb2_read_pipe()
6603 rsp->DataOffset = 80; in smb2_read_pipe()
6604 rsp->Reserved = 0; in smb2_read_pipe()
6605 rsp->DataLength = cpu_to_le32(nbytes); in smb2_read_pipe()
6606 rsp->DataRemaining = 0; in smb2_read_pipe()
6607 rsp->Flags = 0; in smb2_read_pipe()
6611 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_read_pipe()
6619 __le32 Channel, in smb2_set_remote_key_for_rdma() argument
6624 if (work->conn->dialect == SMB30_PROT_ID && in smb2_set_remote_key_for_rdma()
6625 Channel != SMB2_CHANNEL_RDMA_V1) in smb2_set_remote_key_for_rdma()
6626 return -EINVAL; in smb2_set_remote_key_for_rdma()
6638 return -EINVAL; in smb2_set_remote_key_for_rdma()
6640 work->need_invalidate_rkey = in smb2_set_remote_key_for_rdma()
6641 (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE); in smb2_set_remote_key_for_rdma()
6642 if (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) in smb2_set_remote_key_for_rdma()
6643 work->remote_key = le32_to_cpu(desc->token); in smb2_set_remote_key_for_rdma()
6653 err = ksmbd_conn_rdma_write(work->conn, data_buf, length, in smb2_read_rdma_channel()
6655 ((char *)req + le16_to_cpu(req->ReadChannelInfoOffset)), in smb2_read_rdma_channel()
6656 le16_to_cpu(req->ReadChannelInfoLength)); in smb2_read_rdma_channel()
6664 * smb2_read() - handler for smb2 read from file
6671 struct ksmbd_conn *conn = work->conn; in smb2_read()
6680 unsigned int max_read_size = conn->vals->max_read_size; in smb2_read()
6686 if (test_share_config_flag(work->tcon->share_conf, in smb2_read()
6692 if (work->next_smb2_rcv_hdr_off) { in smb2_read()
6695 if (!has_file_id(req->VolatileFileId)) { in smb2_read()
6697 work->compound_fid); in smb2_read()
6698 id = work->compound_fid; in smb2_read()
6699 pid = work->compound_pfid; in smb2_read()
6702 req = smb2_get_msg(work->request_buf); in smb2_read()
6703 rsp = smb2_get_msg(work->response_buf); in smb2_read()
6707 id = req->VolatileFileId; in smb2_read()
6708 pid = req->PersistentFileId; in smb2_read()
6711 if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE || in smb2_read()
6712 req->Channel == SMB2_CHANNEL_RDMA_V1) { in smb2_read()
6718 unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset); in smb2_read()
6721 err = -EINVAL; in smb2_read()
6727 req->Channel, in smb2_read()
6728 req->ReadChannelInfoLength); in smb2_read()
6735 err = -ENOENT; in smb2_read()
6739 if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_READ_ATTRIBUTES_LE))) { in smb2_read()
6740 pr_err("Not permitted to read : 0x%x\n", fp->daccess); in smb2_read()
6741 err = -EACCES; in smb2_read()
6745 offset = le64_to_cpu(req->Offset); in smb2_read()
6747 err = -EINVAL; in smb2_read()
6750 length = le32_to_cpu(req->Length); in smb2_read()
6751 mincount = le32_to_cpu(req->MinimumCount); in smb2_read()
6756 err = -EINVAL; in smb2_read()
6761 fp->filp, offset, length); in smb2_read()
6765 err = -ENOMEM; in smb2_read()
6777 rsp->hdr.Status = STATUS_END_OF_FILE; in smb2_read()
6787 /* write data to the client using rdma channel */ in smb2_read()
6800 rsp->StructureSize = cpu_to_le16(17); in smb2_read()
6801 rsp->DataOffset = 80; in smb2_read()
6802 rsp->Reserved = 0; in smb2_read()
6803 rsp->DataLength = cpu_to_le32(nbytes); in smb2_read()
6804 rsp->DataRemaining = cpu_to_le32(remain_bytes); in smb2_read()
6805 rsp->Flags = 0; in smb2_read()
6818 if (err == -EISDIR) in smb2_read()
6819 rsp->hdr.Status = STATUS_INVALID_DEVICE_REQUEST; in smb2_read()
6820 else if (err == -EAGAIN) in smb2_read()
6821 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in smb2_read()
6822 else if (err == -ENOENT) in smb2_read()
6823 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_read()
6824 else if (err == -EACCES) in smb2_read()
6825 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_read()
6826 else if (err == -ESHARE) in smb2_read()
6827 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_read()
6828 else if (err == -EINVAL) in smb2_read()
6829 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_read()
6831 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_read()
6840 * smb2_write_pipe() - handler for smb2 write on IPC pipe
6857 length = le32_to_cpu(req->Length); in smb2_write_pipe()
6858 id = req->VolatileFileId; in smb2_write_pipe()
6860 if ((u64)le16_to_cpu(req->DataOffset) + length > in smb2_write_pipe()
6861 get_rfc1002_len(work->request_buf)) { in smb2_write_pipe()
6863 le16_to_cpu(req->DataOffset), in smb2_write_pipe()
6864 get_rfc1002_len(work->request_buf)); in smb2_write_pipe()
6865 err = -EINVAL; in smb2_write_pipe()
6869 data_buf = (char *)(((char *)&req->hdr.ProtocolId) + in smb2_write_pipe()
6870 le16_to_cpu(req->DataOffset)); in smb2_write_pipe()
6872 rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length); in smb2_write_pipe()
6874 if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) { in smb2_write_pipe()
6875 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_write_pipe()
6878 return -EOPNOTSUPP; in smb2_write_pipe()
6880 if (rpc_resp->flags != KSMBD_RPC_OK) { in smb2_write_pipe()
6881 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_write_pipe()
6889 rsp->StructureSize = cpu_to_le16(17); in smb2_write_pipe()
6890 rsp->DataOffset = 0; in smb2_write_pipe()
6891 rsp->Reserved = 0; in smb2_write_pipe()
6892 rsp->DataLength = cpu_to_le32(length); in smb2_write_pipe()
6893 rsp->DataRemaining = 0; in smb2_write_pipe()
6894 rsp->Reserved2 = 0; in smb2_write_pipe()
6899 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_write_pipe()
6917 return -ENOMEM; in smb2_write_rdma_channel()
6919 ret = ksmbd_conn_rdma_read(work->conn, data_buf, length, in smb2_write_rdma_channel()
6921 ((char *)req + le16_to_cpu(req->WriteChannelInfoOffset)), in smb2_write_rdma_channel()
6922 le16_to_cpu(req->WriteChannelInfoLength)); in smb2_write_rdma_channel()
6937 * smb2_write() - handler for smb2 write from file
6953 unsigned int max_write_size = work->conn->vals->max_write_size; in smb2_write()
6959 if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) { in smb2_write()
6964 offset = le64_to_cpu(req->Offset); in smb2_write()
6966 return -EINVAL; in smb2_write()
6967 length = le32_to_cpu(req->Length); in smb2_write()
6969 if (req->Channel == SMB2_CHANNEL_RDMA_V1 || in smb2_write()
6970 req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) { in smb2_write()
6973 length = le32_to_cpu(req->RemainingBytes); in smb2_write()
6977 unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset); in smb2_write()
6979 if (req->Length != 0 || req->DataOffset != 0 || in smb2_write()
6981 err = -EINVAL; in smb2_write()
6987 req->Channel, in smb2_write()
6988 req->WriteChannelInfoLength); in smb2_write()
6993 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_write()
6995 err = -EACCES; in smb2_write()
6999 fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in smb2_write()
7001 err = -ENOENT; in smb2_write()
7005 if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_READ_ATTRIBUTES_LE))) { in smb2_write()
7006 pr_err("Not permitted to write : 0x%x\n", fp->daccess); in smb2_write()
7007 err = -EACCES; in smb2_write()
7014 err = -EINVAL; in smb2_write()
7018 ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags)); in smb2_write()
7019 if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH) in smb2_write()
7023 if (le16_to_cpu(req->DataOffset) < in smb2_write()
7025 err = -EINVAL; in smb2_write()
7029 data_buf = (char *)(((char *)&req->hdr.ProtocolId) + in smb2_write()
7030 le16_to_cpu(req->DataOffset)); in smb2_write()
7033 fp->filp, offset, length); in smb2_write()
7039 /* read data from the client using rdma channel, and in smb2_write()
7050 rsp->StructureSize = cpu_to_le16(17); in smb2_write()
7051 rsp->DataOffset = 0; in smb2_write()
7052 rsp->Reserved = 0; in smb2_write()
7053 rsp->DataLength = cpu_to_le32(nbytes); in smb2_write()
7054 rsp->DataRemaining = 0; in smb2_write()
7055 rsp->Reserved2 = 0; in smb2_write()
7063 if (err == -EAGAIN) in smb2_write()
7064 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in smb2_write()
7065 else if (err == -ENOSPC || err == -EFBIG) in smb2_write()
7066 rsp->hdr.Status = STATUS_DISK_FULL; in smb2_write()
7067 else if (err == -ENOENT) in smb2_write()
7068 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_write()
7069 else if (err == -EACCES) in smb2_write()
7070 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_write()
7071 else if (err == -ESHARE) in smb2_write()
7072 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_write()
7073 else if (err == -EINVAL) in smb2_write()
7074 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_write()
7076 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_write()
7084 * smb2_flush() - handler for smb2 flush file - fsync
7097 ksmbd_debug(SMB, "Received smb2 flush request(fid : %llu)\n", req->VolatileFileId); in smb2_flush()
7099 err = ksmbd_vfs_fsync(work, req->VolatileFileId, req->PersistentFileId); in smb2_flush()
7103 rsp->StructureSize = cpu_to_le16(4); in smb2_flush()
7104 rsp->Reserved = 0; in smb2_flush()
7108 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_flush()
7114 * smb2_cancel() - handler for smb2 cancel command
7121 struct ksmbd_conn *conn = work->conn; in smb2_cancel()
7122 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in smb2_cancel()
7127 if (work->next_smb2_rcv_hdr_off) in smb2_cancel()
7131 hdr->MessageId, hdr->Flags); in smb2_cancel()
7133 if (hdr->Flags & SMB2_FLAGS_ASYNC_COMMAND) { in smb2_cancel()
7134 command_list = &conn->async_requests; in smb2_cancel()
7136 spin_lock(&conn->request_lock); in smb2_cancel()
7139 chdr = smb2_get_msg(iter->request_buf); in smb2_cancel()
7141 if (iter->async_id != in smb2_cancel()
7142 le64_to_cpu(hdr->Id.AsyncId)) in smb2_cancel()
7147 le64_to_cpu(hdr->Id.AsyncId), in smb2_cancel()
7148 le16_to_cpu(chdr->Command)); in smb2_cancel()
7149 iter->state = KSMBD_WORK_CANCELLED; in smb2_cancel()
7150 if (iter->cancel_fn) in smb2_cancel()
7151 iter->cancel_fn(iter->cancel_argv); in smb2_cancel()
7154 spin_unlock(&conn->request_lock); in smb2_cancel()
7156 command_list = &conn->requests; in smb2_cancel()
7158 spin_lock(&conn->request_lock); in smb2_cancel()
7160 chdr = smb2_get_msg(iter->request_buf); in smb2_cancel()
7162 if (chdr->MessageId != hdr->MessageId || in smb2_cancel()
7168 le64_to_cpu(hdr->MessageId), in smb2_cancel()
7169 le16_to_cpu(chdr->Command)); in smb2_cancel()
7170 iter->state = KSMBD_WORK_CANCELLED; in smb2_cancel()
7173 spin_unlock(&conn->request_lock); in smb2_cancel()
7177 work->send_no_response = 1; in smb2_cancel()
7191 fl->c.flc_owner = f; in smb_flock_init()
7192 fl->c.flc_pid = current->tgid; in smb_flock_init()
7193 fl->c.flc_file = f; in smb_flock_init()
7194 fl->c.flc_flags = FL_POSIX; in smb_flock_init()
7195 fl->fl_ops = NULL; in smb_flock_init()
7196 fl->fl_lmops = NULL; in smb_flock_init()
7204 int cmd = -EINVAL; in smb2_set_flock_flags()
7211 flock->c.flc_type = F_RDLCK; in smb2_set_flock_flags()
7212 flock->c.flc_flags |= FL_SLEEP; in smb2_set_flock_flags()
7217 flock->c.flc_type = F_WRLCK; in smb2_set_flock_flags()
7218 flock->c.flc_flags |= FL_SLEEP; in smb2_set_flock_flags()
7224 flock->c.flc_type = F_RDLCK; in smb2_set_flock_flags()
7230 flock->c.flc_type = F_WRLCK; in smb2_set_flock_flags()
7234 flock->c.flc_type = F_UNLCK; in smb2_set_flock_flags()
7252 lock->cmd = cmd; in smb2_lock_init()
7253 lock->fl = flock; in smb2_lock_init()
7254 lock->start = flock->fl_start; in smb2_lock_init()
7255 lock->end = flock->fl_end; in smb2_lock_init()
7256 lock->flags = flags; in smb2_lock_init()
7257 if (lock->start == lock->end) in smb2_lock_init()
7258 lock->zero_len = 1; in smb2_lock_init()
7259 INIT_LIST_HEAD(&lock->clist); in smb2_lock_init()
7260 INIT_LIST_HEAD(&lock->flist); in smb2_lock_init()
7261 INIT_LIST_HEAD(&lock->llist); in smb2_lock_init()
7262 list_add_tail(&lock->llist, lock_list); in smb2_lock_init()
7278 return waitqueue_active(&fl->c.flc_wait); in lock_defer_pending()
7282 * smb2_lock() - handler for smb2 file lock command
7298 int err = -EIO, i, rc = 0; in smb2_lock()
7310 fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in smb2_lock()
7312 ksmbd_debug(SMB, "Invalid file id for lock : %llu\n", req->VolatileFileId); in smb2_lock()
7313 err = -ENOENT; in smb2_lock()
7317 filp = fp->filp; in smb2_lock()
7318 lock_count = le16_to_cpu(req->LockCount); in smb2_lock()
7319 lock_ele = req->locks; in smb2_lock()
7323 err = -EINVAL; in smb2_lock()
7338 if (lock_start > U64_MAX - lock_length) { in smb2_lock()
7340 rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE; in smb2_lock()
7346 flock->fl_start = OFFSET_MAX; in smb2_lock()
7348 flock->fl_start = lock_start; in smb2_lock()
7351 if (lock_length > OFFSET_MAX - flock->fl_start) in smb2_lock()
7352 lock_length = OFFSET_MAX - flock->fl_start; in smb2_lock()
7354 flock->fl_end = flock->fl_start + lock_length; in smb2_lock()
7356 if (flock->fl_end < flock->fl_start) { in smb2_lock()
7359 flock->fl_end, flock->fl_start); in smb2_lock()
7360 rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE; in smb2_lock()
7367 if (cmp_lock->fl->fl_start <= flock->fl_start && in smb2_lock()
7368 cmp_lock->fl->fl_end >= flock->fl_end) { in smb2_lock()
7369 if (cmp_lock->fl->c.flc_type != F_UNLCK && in smb2_lock()
7370 flock->c.flc_type != F_UNLCK) { in smb2_lock()
7372 err = -EINVAL; in smb2_lock()
7381 err = -EINVAL; in smb2_lock()
7388 if (smb_lock->cmd < 0) { in smb2_lock()
7389 err = -EINVAL; in smb2_lock()
7393 if (!(smb_lock->flags & SMB2_LOCKFLAG_MASK)) { in smb2_lock()
7394 err = -EINVAL; in smb2_lock()
7399 smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) || in smb2_lock()
7401 !(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK))) { in smb2_lock()
7402 err = -EINVAL; in smb2_lock()
7406 prior_lock = smb_lock->flags; in smb2_lock()
7408 if (!(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) && in smb2_lock()
7409 !(smb_lock->flags & SMB2_LOCKFLAG_FAIL_IMMEDIATELY)) in smb2_lock()
7416 spin_lock(&conn->llist_lock); in smb2_lock()
7417 list_for_each_entry_safe(cmp_lock, tmp2, &conn->lock_list, clist) { in smb2_lock()
7418 if (file_inode(cmp_lock->fl->c.flc_file) != in smb2_lock()
7419 file_inode(smb_lock->fl->c.flc_file)) in smb2_lock()
7422 if (lock_is_unlock(smb_lock->fl)) { in smb2_lock()
7423 if (cmp_lock->fl->c.flc_file == smb_lock->fl->c.flc_file && in smb2_lock()
7424 cmp_lock->start == smb_lock->start && in smb2_lock()
7425 cmp_lock->end == smb_lock->end && in smb2_lock()
7426 !lock_defer_pending(cmp_lock->fl)) { in smb2_lock()
7428 list_del(&cmp_lock->flist); in smb2_lock()
7429 list_del(&cmp_lock->clist); in smb2_lock()
7430 spin_unlock(&conn->llist_lock); in smb2_lock()
7433 locks_free_lock(cmp_lock->fl); in smb2_lock()
7440 if (cmp_lock->fl->c.flc_file == smb_lock->fl->c.flc_file) { in smb2_lock()
7441 if (smb_lock->flags & SMB2_LOCKFLAG_SHARED) in smb2_lock()
7444 if (cmp_lock->flags & SMB2_LOCKFLAG_SHARED) in smb2_lock()
7449 if (cmp_lock->zero_len && !smb_lock->zero_len && in smb2_lock()
7450 cmp_lock->start > smb_lock->start && in smb2_lock()
7451 cmp_lock->start < smb_lock->end) { in smb2_lock()
7452 spin_unlock(&conn->llist_lock); in smb2_lock()
7458 if (smb_lock->zero_len && !cmp_lock->zero_len && in smb2_lock()
7459 smb_lock->start > cmp_lock->start && in smb2_lock()
7460 smb_lock->start < cmp_lock->end) { in smb2_lock()
7461 spin_unlock(&conn->llist_lock); in smb2_lock()
7467 if (((cmp_lock->start <= smb_lock->start && in smb2_lock()
7468 cmp_lock->end > smb_lock->start) || in smb2_lock()
7469 (cmp_lock->start < smb_lock->end && in smb2_lock()
7470 cmp_lock->end >= smb_lock->end)) && in smb2_lock()
7471 !cmp_lock->zero_len && !smb_lock->zero_len) { in smb2_lock()
7472 spin_unlock(&conn->llist_lock); in smb2_lock()
7478 spin_unlock(&conn->llist_lock); in smb2_lock()
7482 if (lock_is_unlock(smb_lock->fl) && nolock) { in smb2_lock()
7484 rsp->hdr.Status = STATUS_RANGE_NOT_LOCKED; in smb2_lock()
7489 flock = smb_lock->fl; in smb2_lock()
7490 list_del(&smb_lock->llist); in smb2_lock()
7492 if (smb_lock->zero_len) { in smb2_lock()
7497 rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL); in smb2_lock()
7499 if (smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) { in smb2_lock()
7502 } else if (rc == -ENOENT) { in smb2_lock()
7503 rsp->hdr.Status = STATUS_NOT_LOCKED; in smb2_lock()
7514 list_add(&smb_lock->llist, &rollback_list); in smb2_lock()
7518 err = -ENOMEM; in smb2_lock()
7528 err = -ENOMEM; in smb2_lock()
7531 spin_lock(&fp->f_lock); in smb2_lock()
7532 list_add(&work->fp_entry, &fp->blocked_works); in smb2_lock()
7533 spin_unlock(&fp->f_lock); in smb2_lock()
7539 spin_lock(&fp->f_lock); in smb2_lock()
7540 list_del(&work->fp_entry); in smb2_lock()
7541 spin_unlock(&fp->f_lock); in smb2_lock()
7543 if (work->state != KSMBD_WORK_ACTIVE) { in smb2_lock()
7544 list_del(&smb_lock->llist); in smb2_lock()
7547 if (work->state == KSMBD_WORK_CANCELLED) { in smb2_lock()
7548 rsp->hdr.Status = in smb2_lock()
7553 work->send_no_response = 1; in smb2_lock()
7557 rsp->hdr.Status = in smb2_lock()
7563 list_del(&smb_lock->llist); in smb2_lock()
7567 list_add(&smb_lock->llist, &rollback_list); in smb2_lock()
7568 spin_lock(&work->conn->llist_lock); in smb2_lock()
7569 list_add_tail(&smb_lock->clist, in smb2_lock()
7570 &work->conn->lock_list); in smb2_lock()
7571 list_add_tail(&smb_lock->flist, in smb2_lock()
7572 &fp->lock_list); in smb2_lock()
7573 spin_unlock(&work->conn->llist_lock); in smb2_lock()
7581 if (atomic_read(&fp->f_ci->op_count) > 1) in smb2_lock()
7584 rsp->StructureSize = cpu_to_le16(4); in smb2_lock()
7586 rsp->hdr.Status = STATUS_SUCCESS; in smb2_lock()
7587 rsp->Reserved = 0; in smb2_lock()
7597 locks_free_lock(smb_lock->fl); in smb2_lock()
7598 list_del(&smb_lock->llist); in smb2_lock()
7606 rlock->c.flc_type = F_UNLCK; in smb2_lock()
7607 rlock->fl_start = smb_lock->start; in smb2_lock()
7608 rlock->fl_end = smb_lock->end; in smb2_lock()
7614 list_del(&smb_lock->llist); in smb2_lock()
7615 spin_lock(&work->conn->llist_lock); in smb2_lock()
7616 if (!list_empty(&smb_lock->flist)) in smb2_lock()
7617 list_del(&smb_lock->flist); in smb2_lock()
7618 list_del(&smb_lock->clist); in smb2_lock()
7619 spin_unlock(&work->conn->llist_lock); in smb2_lock()
7621 locks_free_lock(smb_lock->fl); in smb2_lock()
7628 if (!rsp->hdr.Status) { in smb2_lock()
7629 if (err == -EINVAL) in smb2_lock()
7630 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_lock()
7631 else if (err == -ENOMEM) in smb2_lock()
7632 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_lock()
7633 else if (err == -ENOENT) in smb2_lock()
7634 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_lock()
7636 rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED; in smb2_lock()
7660 ci_rsp = (struct copychunk_ioctl_rsp *)&rsp->Buffer[0]; in fsctl_copychunk()
7662 rsp->VolatileFileId = volatile_id; in fsctl_copychunk()
7663 rsp->PersistentFileId = persistent_id; in fsctl_copychunk()
7664 ci_rsp->ChunksWritten = in fsctl_copychunk()
7666 ci_rsp->ChunkBytesWritten = in fsctl_copychunk()
7668 ci_rsp->TotalBytesWritten = in fsctl_copychunk()
7671 chunk_count = le32_to_cpu(ci_req->ChunkCount); in fsctl_copychunk()
7679 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_copychunk()
7680 return -EINVAL; in fsctl_copychunk()
7683 chunks = &ci_req->Chunks[0]; in fsctl_copychunk()
7693 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_copychunk()
7694 return -EINVAL; in fsctl_copychunk()
7698 le64_to_cpu(ci_req->ResumeKey[0])); in fsctl_copychunk()
7700 ret = -EINVAL; in fsctl_copychunk()
7702 src_fp->persistent_id != le64_to_cpu(ci_req->ResumeKey[1])) { in fsctl_copychunk()
7703 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND; in fsctl_copychunk()
7708 rsp->hdr.Status = STATUS_FILE_CLOSED; in fsctl_copychunk()
7717 !(dst_fp->daccess & (FILE_READ_DATA_LE | FILE_GENERIC_READ_LE))) { in fsctl_copychunk()
7718 rsp->hdr.Status = STATUS_ACCESS_DENIED; in fsctl_copychunk()
7728 if (ret == -EACCES) in fsctl_copychunk()
7729 rsp->hdr.Status = STATUS_ACCESS_DENIED; in fsctl_copychunk()
7730 if (ret == -EAGAIN) in fsctl_copychunk()
7731 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in fsctl_copychunk()
7732 else if (ret == -EBADF) in fsctl_copychunk()
7733 rsp->hdr.Status = STATUS_INVALID_HANDLE; in fsctl_copychunk()
7734 else if (ret == -EFBIG || ret == -ENOSPC) in fsctl_copychunk()
7735 rsp->hdr.Status = STATUS_DISK_FULL; in fsctl_copychunk()
7736 else if (ret == -EINVAL) in fsctl_copychunk()
7737 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_copychunk()
7738 else if (ret == -EISDIR) in fsctl_copychunk()
7739 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY; in fsctl_copychunk()
7740 else if (ret == -E2BIG) in fsctl_copychunk()
7741 rsp->hdr.Status = STATUS_INVALID_VIEW_SIZE; in fsctl_copychunk()
7743 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in fsctl_copychunk()
7746 ci_rsp->ChunksWritten = cpu_to_le32(chunk_count_written); in fsctl_copychunk()
7747 ci_rsp->ChunkBytesWritten = cpu_to_le32(chunk_size_written); in fsctl_copychunk()
7748 ci_rsp->TotalBytesWritten = cpu_to_le32(total_size_written); in fsctl_copychunk()
7763 if (ifa->ifa_flags & IFA_F_SECONDARY) in idev_ipv4_address()
7766 addr = ifa->ifa_address; in idev_ipv4_address()
7788 if (netdev->type == ARPHRD_LOOPBACK) in fsctl_query_iface_info_ioctl()
7791 if (!ksmbd_find_netdev_name_iface_list(netdev->name)) in fsctl_query_iface_info_ioctl()
7801 return -ENOSPC; in fsctl_query_iface_info_ioctl()
7805 &rsp->Buffer[nbytes]; in fsctl_query_iface_info_ioctl()
7806 nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex); in fsctl_query_iface_info_ioctl()
7808 nii_rsp->Capability = 0; in fsctl_query_iface_info_ioctl()
7809 if (netdev->real_num_tx_queues > 1) in fsctl_query_iface_info_ioctl()
7810 nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE); in fsctl_query_iface_info_ioctl()
7812 nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE); in fsctl_query_iface_info_ioctl()
7814 nii_rsp->Next = cpu_to_le32(152); in fsctl_query_iface_info_ioctl()
7815 nii_rsp->Reserved = 0; in fsctl_query_iface_info_ioctl()
7817 if (netdev->ethtool_ops->get_link_ksettings) { in fsctl_query_iface_info_ioctl()
7820 netdev->ethtool_ops->get_link_ksettings(netdev, &cmd); in fsctl_query_iface_info_ioctl()
7823 ksmbd_debug(SMB, "%s %s\n", netdev->name, in fsctl_query_iface_info_ioctl()
7829 nii_rsp->LinkSpeed = cpu_to_le64(speed); in fsctl_query_iface_info_ioctl()
7832 nii_rsp->SockAddr_Storage; in fsctl_query_iface_info_ioctl()
7838 sockaddr_storage->Family = cpu_to_le16(INTERNETWORK); in fsctl_query_iface_info_ioctl()
7839 sockaddr_storage->addr4.Port = 0; in fsctl_query_iface_info_ioctl()
7844 sockaddr_storage->addr4.IPv4address = in fsctl_query_iface_info_ioctl()
7852 __u8 *ipv6_addr = sockaddr_storage->addr6.IPv6address; in fsctl_query_iface_info_ioctl()
7854 sockaddr_storage->Family = cpu_to_le16(INTERNETWORKV6); in fsctl_query_iface_info_ioctl()
7855 sockaddr_storage->addr6.Port = 0; in fsctl_query_iface_info_ioctl()
7856 sockaddr_storage->addr6.FlowInfo = 0; in fsctl_query_iface_info_ioctl()
7862 list_for_each_entry(ifa, &idev6->addr_list, if_list) { in fsctl_query_iface_info_ioctl()
7863 if (ifa->flags & (IFA_F_TENTATIVE | in fsctl_query_iface_info_ioctl()
7866 memcpy(ipv6_addr, ifa->addr.s6_addr, 16); in fsctl_query_iface_info_ioctl()
7869 sockaddr_storage->addr6.ScopeId = 0; in fsctl_query_iface_info_ioctl()
7877 nii_rsp->Next = 0; in fsctl_query_iface_info_ioctl()
7879 rsp->PersistentFileId = SMB2_NO_FID; in fsctl_query_iface_info_ioctl()
7880 rsp->VolatileFileId = SMB2_NO_FID; in fsctl_query_iface_info_ioctl()
7893 le16_to_cpu(neg_req->DialectCount) * sizeof(__le16)) in fsctl_validate_negotiate_info()
7894 return -EINVAL; in fsctl_validate_negotiate_info()
7896 dialect = ksmbd_lookup_dialect_by_id(neg_req->Dialects, in fsctl_validate_negotiate_info()
7897 neg_req->DialectCount); in fsctl_validate_negotiate_info()
7898 if (dialect == BAD_PROT_ID || dialect != conn->dialect) { in fsctl_validate_negotiate_info()
7899 ret = -EINVAL; in fsctl_validate_negotiate_info()
7903 if (strncmp(neg_req->Guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE)) { in fsctl_validate_negotiate_info()
7904 ret = -EINVAL; in fsctl_validate_negotiate_info()
7908 if (le16_to_cpu(neg_req->SecurityMode) != conn->cli_sec_mode) { in fsctl_validate_negotiate_info()
7909 ret = -EINVAL; in fsctl_validate_negotiate_info()
7913 if (le32_to_cpu(neg_req->Capabilities) != conn->cli_cap) { in fsctl_validate_negotiate_info()
7914 ret = -EINVAL; in fsctl_validate_negotiate_info()
7918 neg_rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); in fsctl_validate_negotiate_info()
7919 memset(neg_rsp->Guid, 0, SMB2_CLIENT_GUID_SIZE); in fsctl_validate_negotiate_info()
7920 neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode); in fsctl_validate_negotiate_info()
7921 neg_rsp->Dialect = cpu_to_le16(conn->dialect); in fsctl_validate_negotiate_info()
7937 return -EINVAL; in fsctl_query_allocated_ranges()
7939 start = le64_to_cpu(qar_req->file_offset); in fsctl_query_allocated_ranges()
7940 length = le64_to_cpu(qar_req->length); in fsctl_query_allocated_ranges()
7943 return -EINVAL; in fsctl_query_allocated_ranges()
7947 return -ENOENT; in fsctl_query_allocated_ranges()
7951 if (ret && ret != -E2BIG) in fsctl_query_allocated_ranges()
7964 char *data_buf = (char *)req + le32_to_cpu(req->InputOffset); in fsctl_pipe_transceive()
7967 rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf, in fsctl_pipe_transceive()
7968 le32_to_cpu(req->InputCount)); in fsctl_pipe_transceive()
7970 if (rpc_resp->flags == KSMBD_RPC_SOME_NOT_MAPPED) { in fsctl_pipe_transceive()
7975 rsp->hdr.Status = STATUS_SOME_NOT_MAPPED; in fsctl_pipe_transceive()
7976 } else if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) { in fsctl_pipe_transceive()
7977 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in fsctl_pipe_transceive()
7979 } else if (rpc_resp->flags != KSMBD_RPC_OK) { in fsctl_pipe_transceive()
7980 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_pipe_transceive()
7984 nbytes = rpc_resp->payload_sz; in fsctl_pipe_transceive()
7985 if (rpc_resp->payload_sz > out_buf_len) { in fsctl_pipe_transceive()
7986 rsp->hdr.Status = STATUS_BUFFER_OVERFLOW; in fsctl_pipe_transceive()
7990 if (!rpc_resp->payload_sz) { in fsctl_pipe_transceive()
7991 rsp->hdr.Status = in fsctl_pipe_transceive()
7996 memcpy((char *)rsp->Buffer, rpc_resp->payload, nbytes); in fsctl_pipe_transceive()
8013 return -ENOENT; in fsctl_set_sparse()
8014 idmap = file_mnt_idmap(fp->filp); in fsctl_set_sparse()
8016 old_fattr = fp->f_ci->m_fattr; in fsctl_set_sparse()
8017 if (sparse->SetSparse) in fsctl_set_sparse()
8018 fp->f_ci->m_fattr |= FILE_ATTRIBUTE_SPARSE_FILE_LE; in fsctl_set_sparse()
8020 fp->f_ci->m_fattr &= ~FILE_ATTRIBUTE_SPARSE_FILE_LE; in fsctl_set_sparse()
8022 if (fp->f_ci->m_fattr != old_fattr && in fsctl_set_sparse()
8023 test_share_config_flag(work->tcon->share_conf, in fsctl_set_sparse()
8028 fp->filp->f_path.dentry, &da); in fsctl_set_sparse()
8032 da.attr = le32_to_cpu(fp->f_ci->m_fattr); in fsctl_set_sparse()
8034 &fp->filp->f_path, in fsctl_set_sparse()
8037 fp->f_ci->m_fattr = old_fattr; in fsctl_set_sparse()
8051 fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in fsctl_request_resume_key()
8053 return -ENOENT; in fsctl_request_resume_key()
8056 key_rsp->ResumeKey[0] = req->VolatileFileId; in fsctl_request_resume_key()
8057 key_rsp->ResumeKey[1] = req->PersistentFileId; in fsctl_request_resume_key()
8064 * smb2_ioctl() - handler for smb2 ioctl command
8075 struct ksmbd_conn *conn = work->conn; in smb2_ioctl()
8081 if (work->next_smb2_rcv_hdr_off) { in smb2_ioctl()
8084 if (!has_file_id(req->VolatileFileId)) { in smb2_ioctl()
8086 work->compound_fid); in smb2_ioctl()
8087 id = work->compound_fid; in smb2_ioctl()
8090 req = smb2_get_msg(work->request_buf); in smb2_ioctl()
8091 rsp = smb2_get_msg(work->response_buf); in smb2_ioctl()
8095 id = req->VolatileFileId; in smb2_ioctl()
8097 if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) { in smb2_ioctl()
8098 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_ioctl()
8102 buffer = (char *)req + le32_to_cpu(req->InputOffset); in smb2_ioctl()
8104 cnt_code = le32_to_cpu(req->CtlCode); in smb2_ioctl()
8106 le32_to_cpu(req->MaxOutputResponse)); in smb2_ioctl()
8108 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_ioctl()
8112 in_buf_len = le32_to_cpu(req->InputCount); in smb2_ioctl()
8118 rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED; in smb2_ioctl()
8126 &rsp->Buffer[0]; in smb2_ioctl()
8132 memset(obj_buf->ObjectId, 0x0, 16); in smb2_ioctl()
8133 memset(obj_buf->BirthVolumeId, 0x0, 16); in smb2_ioctl()
8134 memset(obj_buf->BirthObjectId, 0x0, 16); in smb2_ioctl()
8135 memset(obj_buf->DomainId, 0x0, 16); in smb2_ioctl()
8144 if (conn->dialect < SMB30_PROT_ID) { in smb2_ioctl()
8145 ret = -EOPNOTSUPP; in smb2_ioctl()
8151 ret = -EINVAL; in smb2_ioctl()
8156 ret = -EINVAL; in smb2_ioctl()
8162 (struct validate_negotiate_info_rsp *)&rsp->Buffer[0], in smb2_ioctl()
8168 rsp->PersistentFileId = SMB2_NO_FID; in smb2_ioctl()
8169 rsp->VolatileFileId = SMB2_NO_FID; in smb2_ioctl()
8179 ret = -EINVAL; in smb2_ioctl()
8184 (struct resume_key_ioctl_rsp *)&rsp->Buffer[0]); in smb2_ioctl()
8187 rsp->PersistentFileId = req->PersistentFileId; in smb2_ioctl()
8188 rsp->VolatileFileId = req->VolatileFileId; in smb2_ioctl()
8193 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_ioctl()
8196 ret = -EACCES; in smb2_ioctl()
8201 ret = -EINVAL; in smb2_ioctl()
8206 ret = -EINVAL; in smb2_ioctl()
8211 rsp->VolatileFileId = req->VolatileFileId; in smb2_ioctl()
8212 rsp->PersistentFileId = req->PersistentFileId; in smb2_ioctl()
8215 le32_to_cpu(req->CtlCode), in smb2_ioctl()
8216 le32_to_cpu(req->InputCount), in smb2_ioctl()
8217 req->VolatileFileId, in smb2_ioctl()
8218 req->PersistentFileId, in smb2_ioctl()
8223 ret = -EINVAL; in smb2_ioctl()
8237 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_ioctl()
8240 ret = -EACCES; in smb2_ioctl()
8245 ret = -EINVAL; in smb2_ioctl()
8252 off = le64_to_cpu(zero_data->FileOffset); in smb2_ioctl()
8253 bfz = le64_to_cpu(zero_data->BeyondFinalZero); in smb2_ioctl()
8255 ret = -EINVAL; in smb2_ioctl()
8259 len = bfz - off; in smb2_ioctl()
8263 ret = -ENOENT; in smb2_ioctl()
8276 ret = -EINVAL; in smb2_ioctl()
8282 (struct file_allocated_range_buffer *)&rsp->Buffer[0], in smb2_ioctl()
8285 if (ret == -E2BIG) { in smb2_ioctl()
8286 rsp->hdr.Status = STATUS_BUFFER_OVERFLOW; in smb2_ioctl()
8299 reparse_ptr = (struct reparse_data_buffer *)&rsp->Buffer[0]; in smb2_ioctl()
8303 ret = -ENOENT; in smb2_ioctl()
8307 reparse_ptr->ReparseTag = in smb2_ioctl()
8308 smb2_get_reparse_tag_special_file(file_inode(fp->filp)->i_mode); in smb2_ioctl()
8309 reparse_ptr->ReparseDataLength = 0; in smb2_ioctl()
8321 ret = -EINVAL; in smb2_ioctl()
8327 fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle, in smb2_ioctl()
8328 dup_ext->PersistentFileHandle); in smb2_ioctl()
8331 ret = -ENOENT; in smb2_ioctl()
8338 ret = -ENOENT; in smb2_ioctl()
8342 src_off = le64_to_cpu(dup_ext->SourceFileOffset); in smb2_ioctl()
8343 dst_off = le64_to_cpu(dup_ext->TargetFileOffset); in smb2_ioctl()
8344 length = le64_to_cpu(dup_ext->ByteCount); in smb2_ioctl()
8348 * beneficial when re-exporting nfs/smb mount, but note that in smb2_ioctl()
8354 cloned = vfs_clone_file_range(fp_in->filp, src_off, in smb2_ioctl()
8355 fp_out->filp, dst_off, length, 0); in smb2_ioctl()
8356 if (cloned == -EXDEV || cloned == -EOPNOTSUPP) { in smb2_ioctl()
8357 ret = -EOPNOTSUPP; in smb2_ioctl()
8360 cloned = vfs_copy_file_range(fp_in->filp, src_off, in smb2_ioctl()
8361 fp_out->filp, dst_off, in smb2_ioctl()
8367 ret = -EINVAL; in smb2_ioctl()
8381 ret = -EOPNOTSUPP; in smb2_ioctl()
8385 rsp->CtlCode = cpu_to_le32(cnt_code); in smb2_ioctl()
8386 rsp->InputCount = cpu_to_le32(0); in smb2_ioctl()
8387 rsp->InputOffset = cpu_to_le32(112); in smb2_ioctl()
8388 rsp->OutputOffset = cpu_to_le32(112); in smb2_ioctl()
8389 rsp->OutputCount = cpu_to_le32(nbytes); in smb2_ioctl()
8390 rsp->StructureSize = cpu_to_le16(49); in smb2_ioctl()
8391 rsp->Reserved = cpu_to_le16(0); in smb2_ioctl()
8392 rsp->Flags = cpu_to_le32(0); in smb2_ioctl()
8393 rsp->Reserved2 = cpu_to_le32(0); in smb2_ioctl()
8399 if (ret == -EACCES) in smb2_ioctl()
8400 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_ioctl()
8401 else if (ret == -ENOENT) in smb2_ioctl()
8402 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND; in smb2_ioctl()
8403 else if (ret == -EOPNOTSUPP) in smb2_ioctl()
8404 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_ioctl()
8405 else if (ret == -ENOSPC) in smb2_ioctl()
8406 rsp->hdr.Status = STATUS_BUFFER_TOO_SMALL; in smb2_ioctl()
8407 else if (ret < 0 || rsp->hdr.Status == 0) in smb2_ioctl()
8408 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_ioctl()
8414 * smb20_oplock_break_ack() - handler for smb2.0 oplock break command
8433 volatile_id = req->VolatileFid; in smb20_oplock_break_ack()
8434 persistent_id = req->PersistentFid; in smb20_oplock_break_ack()
8435 req_oplevel = req->OplockLevel; in smb20_oplock_break_ack()
8441 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb20_oplock_break_ack()
8449 rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL; in smb20_oplock_break_ack()
8455 if (opinfo->level == SMB2_OPLOCK_LEVEL_NONE) { in smb20_oplock_break_ack()
8456 rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL; in smb20_oplock_break_ack()
8460 if (opinfo->op_state == OPLOCK_STATE_NONE) { in smb20_oplock_break_ack()
8461 ksmbd_debug(SMB, "unexpected oplock state 0x%x\n", opinfo->op_state); in smb20_oplock_break_ack()
8462 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb20_oplock_break_ack()
8466 if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE || in smb20_oplock_break_ack()
8467 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) && in smb20_oplock_break_ack()
8472 } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II && in smb20_oplock_break_ack()
8479 if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE || in smb20_oplock_break_ack()
8480 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) && in smb20_oplock_break_ack()
8483 } else if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE || in smb20_oplock_break_ack()
8484 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) && in smb20_oplock_break_ack()
8487 } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II && in smb20_oplock_break_ack()
8511 pr_err("unknown oplock change 0x%x -> 0x%x\n", in smb20_oplock_break_ack()
8512 opinfo->level, rsp_oplevel); in smb20_oplock_break_ack()
8516 rsp->hdr.Status = err; in smb20_oplock_break_ack()
8520 opinfo->op_state = OPLOCK_STATE_NONE; in smb20_oplock_break_ack()
8521 wake_up_interruptible_all(&opinfo->oplock_q); in smb20_oplock_break_ack()
8525 rsp->StructureSize = cpu_to_le16(24); in smb20_oplock_break_ack()
8526 rsp->OplockLevel = rsp_oplevel; in smb20_oplock_break_ack()
8527 rsp->Reserved = 0; in smb20_oplock_break_ack()
8528 rsp->Reserved2 = 0; in smb20_oplock_break_ack()
8529 rsp->VolatileFid = volatile_id; in smb20_oplock_break_ack()
8530 rsp->PersistentFid = persistent_id; in smb20_oplock_break_ack()
8536 opinfo->op_state = OPLOCK_STATE_NONE; in smb20_oplock_break_ack()
8537 wake_up_interruptible_all(&opinfo->oplock_q); in smb20_oplock_break_ack()
8546 if ((lease->new_state == in check_lease_state()
8549 lease->new_state = req_state; in check_lease_state()
8553 if (lease->new_state == req_state) in check_lease_state()
8560 * smb21_lease_break_ack() - handler for smb2.1 lease break command
8567 struct ksmbd_conn *conn = work->conn; in smb21_lease_break_ack()
8580 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8581 opinfo = lookup_lease_in_table(conn, req->LeaseKey); in smb21_lease_break_ack()
8585 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb21_lease_break_ack()
8588 lease = opinfo->o_lease; in smb21_lease_break_ack()
8590 if (opinfo->op_state == OPLOCK_STATE_NONE) { in smb21_lease_break_ack()
8592 opinfo->op_state); in smb21_lease_break_ack()
8593 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb21_lease_break_ack()
8597 if (check_lease_state(lease, req->LeaseState)) { in smb21_lease_break_ack()
8598 rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED; in smb21_lease_break_ack()
8601 req->LeaseState, lease->new_state); in smb21_lease_break_ack()
8605 if (!atomic_read(&opinfo->breaking_cnt)) { in smb21_lease_break_ack()
8606 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb21_lease_break_ack()
8611 if (req->LeaseState & in smb21_lease_break_ack()
8614 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) in smb21_lease_break_ack()
8618 ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n", in smb21_lease_break_ack()
8619 le32_to_cpu(lease->state), in smb21_lease_break_ack()
8620 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8621 } else if (lease->state == SMB2_LEASE_READ_CACHING_LE && in smb21_lease_break_ack()
8622 req->LeaseState != SMB2_LEASE_NONE_LE) { in smb21_lease_break_ack()
8625 ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n", in smb21_lease_break_ack()
8626 le32_to_cpu(lease->state), in smb21_lease_break_ack()
8627 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8631 if (req->LeaseState == SMB2_LEASE_NONE_LE) { in smb21_lease_break_ack()
8632 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) in smb21_lease_break_ack()
8636 } else if (req->LeaseState & SMB2_LEASE_READ_CACHING_LE) { in smb21_lease_break_ack()
8637 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) in smb21_lease_break_ack()
8660 ksmbd_debug(OPLOCK, "unknown lease change 0x%x -> 0x%x\n", in smb21_lease_break_ack()
8661 le32_to_cpu(lease->state), in smb21_lease_break_ack()
8662 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8666 rsp->hdr.Status = err; in smb21_lease_break_ack()
8670 lease_state = lease->state; in smb21_lease_break_ack()
8671 opinfo->op_state = OPLOCK_STATE_NONE; in smb21_lease_break_ack()
8672 wake_up_interruptible_all(&opinfo->oplock_q); in smb21_lease_break_ack()
8673 atomic_dec(&opinfo->breaking_cnt); in smb21_lease_break_ack()
8674 wake_up_interruptible_all(&opinfo->oplock_brk); in smb21_lease_break_ack()
8677 rsp->StructureSize = cpu_to_le16(36); in smb21_lease_break_ack()
8678 rsp->Reserved = 0; in smb21_lease_break_ack()
8679 rsp->Flags = 0; in smb21_lease_break_ack()
8680 memcpy(rsp->LeaseKey, req->LeaseKey, 16); in smb21_lease_break_ack()
8681 rsp->LeaseState = lease_state; in smb21_lease_break_ack()
8682 rsp->LeaseDuration = 0; in smb21_lease_break_ack()
8688 wake_up_interruptible_all(&opinfo->oplock_q); in smb21_lease_break_ack()
8689 atomic_dec(&opinfo->breaking_cnt); in smb21_lease_break_ack()
8690 wake_up_interruptible_all(&opinfo->oplock_brk); in smb21_lease_break_ack()
8697 * smb2_oplock_break() - dispatcher for smb2.0 and 2.1 oplock/lease break
8711 switch (le16_to_cpu(req->StructureSize)) { in smb2_oplock_break()
8720 le16_to_cpu(req->StructureSize)); in smb2_oplock_break()
8721 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_oplock_break()
8729 * smb2_notify() - handler for smb2 notify request
8743 if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) { in smb2_notify()
8744 rsp->hdr.Status = STATUS_INTERNAL_ERROR; in smb2_notify()
8750 rsp->hdr.Status = STATUS_NOT_IMPLEMENTED; in smb2_notify()
8755 * smb2_is_sign_req() - handler for checking packet signing status
8763 struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf); in smb2_is_sign_req()
8765 if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) && in smb2_is_sign_req()
8775 * smb2_check_sign_req() - handler for req packet sign processing
8788 hdr = smb2_get_msg(work->request_buf); in smb2_check_sign_req()
8789 if (work->next_smb2_rcv_hdr_off) in smb2_check_sign_req()
8792 if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off) in smb2_check_sign_req()
8793 len = get_rfc1002_len(work->request_buf); in smb2_check_sign_req()
8794 else if (hdr->NextCommand) in smb2_check_sign_req()
8795 len = le32_to_cpu(hdr->NextCommand); in smb2_check_sign_req()
8797 len = get_rfc1002_len(work->request_buf) - in smb2_check_sign_req()
8798 work->next_smb2_rcv_hdr_off; in smb2_check_sign_req()
8800 memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE); in smb2_check_sign_req()
8801 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb2_check_sign_req()
8803 iov[0].iov_base = (char *)&hdr->ProtocolId; in smb2_check_sign_req()
8806 if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1, in smb2_check_sign_req()
8819 * smb2_set_sign_rsp() - handler for rsp packet sign processing
8831 hdr->Flags |= SMB2_FLAGS_SIGNED; in smb2_set_sign_rsp()
8832 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb2_set_sign_rsp()
8834 if (hdr->Command == SMB2_READ) { in smb2_set_sign_rsp()
8835 iov = &work->iov[work->iov_idx - 1]; in smb2_set_sign_rsp()
8838 iov = &work->iov[work->iov_idx]; in smb2_set_sign_rsp()
8841 if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec, in smb2_set_sign_rsp()
8843 memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE); in smb2_set_sign_rsp()
8847 * smb3_check_sign_req() - handler for req packet sign processing
8854 struct ksmbd_conn *conn = work->conn; in smb3_check_sign_req()
8857 struct channel *chann; in smb3_check_sign_req()
8863 hdr = smb2_get_msg(work->request_buf); in smb3_check_sign_req()
8864 if (work->next_smb2_rcv_hdr_off) in smb3_check_sign_req()
8867 if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off) in smb3_check_sign_req()
8868 len = get_rfc1002_len(work->request_buf); in smb3_check_sign_req()
8869 else if (hdr->NextCommand) in smb3_check_sign_req()
8870 len = le32_to_cpu(hdr->NextCommand); in smb3_check_sign_req()
8872 len = get_rfc1002_len(work->request_buf) - in smb3_check_sign_req()
8873 work->next_smb2_rcv_hdr_off; in smb3_check_sign_req()
8875 if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { in smb3_check_sign_req()
8876 signing_key = work->sess->smb3signingkey; in smb3_check_sign_req()
8878 chann = lookup_chann_list(work->sess, conn); in smb3_check_sign_req()
8882 signing_key = chann->smb3signingkey; in smb3_check_sign_req()
8890 memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE); in smb3_check_sign_req()
8891 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb3_check_sign_req()
8892 iov[0].iov_base = (char *)&hdr->ProtocolId; in smb3_check_sign_req()
8907 * smb3_set_sign_rsp() - handler for rsp packet sign processing
8913 struct ksmbd_conn *conn = work->conn; in smb3_set_sign_rsp()
8915 struct channel *chann; in smb3_set_sign_rsp()
8923 if (conn->binding == false && in smb3_set_sign_rsp()
8924 le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { in smb3_set_sign_rsp()
8925 signing_key = work->sess->smb3signingkey; in smb3_set_sign_rsp()
8927 chann = lookup_chann_list(work->sess, work->conn); in smb3_set_sign_rsp()
8931 signing_key = chann->smb3signingkey; in smb3_set_sign_rsp()
8937 hdr->Flags |= SMB2_FLAGS_SIGNED; in smb3_set_sign_rsp()
8938 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb3_set_sign_rsp()
8940 if (hdr->Command == SMB2_READ) { in smb3_set_sign_rsp()
8941 iov = &work->iov[work->iov_idx - 1]; in smb3_set_sign_rsp()
8944 iov = &work->iov[work->iov_idx]; in smb3_set_sign_rsp()
8949 memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE); in smb3_set_sign_rsp()
8953 * smb3_preauth_hash_rsp() - handler for computing preauth hash on response
8959 struct ksmbd_conn *conn = work->conn; in smb3_preauth_hash_rsp()
8960 struct ksmbd_session *sess = work->sess; in smb3_preauth_hash_rsp()
8963 if (conn->dialect != SMB311_PROT_ID) in smb3_preauth_hash_rsp()
8968 if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE && in smb3_preauth_hash_rsp()
8969 conn->preauth_info) in smb3_preauth_hash_rsp()
8970 ksmbd_gen_preauth_integrity_hash(conn, work->response_buf, in smb3_preauth_hash_rsp()
8971 conn->preauth_info->Preauth_HashValue); in smb3_preauth_hash_rsp()
8973 if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) { in smb3_preauth_hash_rsp()
8976 if (conn->binding) { in smb3_preauth_hash_rsp()
8979 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id); in smb3_preauth_hash_rsp()
8982 hash_value = preauth_sess->Preauth_HashValue; in smb3_preauth_hash_rsp()
8984 hash_value = sess->Preauth_HashValue; in smb3_preauth_hash_rsp()
8988 ksmbd_gen_preauth_integrity_hash(conn, work->response_buf, in smb3_preauth_hash_rsp()
9000 tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; in fill_transform_hdr()
9001 tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len); in fill_transform_hdr()
9002 tr_hdr->Flags = cpu_to_le16(TRANSFORM_FLAG_ENCRYPTED); in fill_transform_hdr()
9005 get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE); in fill_transform_hdr()
9007 get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE); in fill_transform_hdr()
9008 memcpy(&tr_hdr->SessionId, &hdr->SessionId, 8); in fill_transform_hdr()
9015 struct kvec *iov = work->iov; in smb3_encrypt_resp()
9016 int rc = -ENOMEM; in smb3_encrypt_resp()
9024 fill_transform_hdr(tr_buf, work->response_buf, work->conn->cipher_type); in smb3_encrypt_resp()
9028 work->tr_buf = tr_buf; in smb3_encrypt_resp()
9030 return ksmbd_crypt_message(work, iov, work->iov_idx + 1, 1); in smb3_encrypt_resp()
9037 return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM; in smb3_is_transform_hdr()
9043 char *buf = work->request_buf; in smb3_decrypt_req()
9046 int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr); in smb3_decrypt_req()
9054 return -ECONNABORTED; in smb3_decrypt_req()
9057 if (buf_data_size < le32_to_cpu(tr_hdr->OriginalMessageSize)) { in smb3_decrypt_req()
9059 return -ECONNABORTED; in smb3_decrypt_req()
9062 sess = ksmbd_session_lookup_all(work->conn, le64_to_cpu(tr_hdr->SessionId)); in smb3_decrypt_req()
9065 le64_to_cpu(tr_hdr->SessionId)); in smb3_decrypt_req()
9066 return -ECONNABORTED; in smb3_decrypt_req()
9086 struct ksmbd_conn *conn = work->conn; in smb3_11_final_sess_setup_resp()
9087 struct ksmbd_session *sess = work->sess; in smb3_11_final_sess_setup_resp()
9088 struct smb2_hdr *rsp = smb2_get_msg(work->response_buf); in smb3_11_final_sess_setup_resp()
9090 if (conn->dialect < SMB30_PROT_ID) in smb3_11_final_sess_setup_resp()
9093 if (work->next_smb2_rcv_hdr_off) in smb3_11_final_sess_setup_resp()
9096 if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && in smb3_11_final_sess_setup_resp()
9097 sess->user && !user_guest(sess->user) && in smb3_11_final_sess_setup_resp()
9098 rsp->Status == STATUS_SUCCESS) in smb3_11_final_sess_setup_resp()