Lines Matching +full:tcon +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0-or-later
44 if (work->next_smb2_rcv_hdr_off) { in __wbuf()
48 *req = smb2_get_msg(work->request_buf); in __wbuf()
49 *rsp = smb2_get_msg(work->response_buf); in __wbuf()
56 * check_session_id() - check for valid session id in smb header
66 if (id == 0 || id == -1) in check_session_id()
76 struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn) in lookup_chann_list()
78 return xa_load(&sess->ksmbd_chann_list, (long)conn); in lookup_chann_list()
82 * smb2_get_ksmbd_tcon() - get tree connection information using a tree id.
91 unsigned int cmd = le16_to_cpu(req_hdr->Command); in smb2_get_ksmbd_tcon()
101 if (xa_empty(&work->sess->tree_conns)) { in smb2_get_ksmbd_tcon()
103 return -ENOENT; in smb2_get_ksmbd_tcon()
106 tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId); in smb2_get_ksmbd_tcon()
110 * Just validate tree id in header with work->tcon->id. in smb2_get_ksmbd_tcon()
112 if (work->next_smb2_rcv_hdr_off) { in smb2_get_ksmbd_tcon()
113 if (!work->tcon) { in smb2_get_ksmbd_tcon()
114 pr_err("The first operation in the compound does not have tcon\n"); in smb2_get_ksmbd_tcon()
115 return -EINVAL; in smb2_get_ksmbd_tcon()
117 if (tree_id != UINT_MAX && work->tcon->id != tree_id) { in smb2_get_ksmbd_tcon()
119 tree_id, work->tcon->id); in smb2_get_ksmbd_tcon()
120 return -EINVAL; in smb2_get_ksmbd_tcon()
125 work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id); in smb2_get_ksmbd_tcon()
126 if (!work->tcon) { in smb2_get_ksmbd_tcon()
128 return -ENOENT; in smb2_get_ksmbd_tcon()
135 * smb2_set_err_rsp() - set error response code on smb response
142 if (work->next_smb2_rcv_hdr_off) in smb2_set_err_rsp()
145 err_rsp = smb2_get_msg(work->response_buf); in smb2_set_err_rsp()
147 if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) { in smb2_set_err_rsp()
150 err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE; in smb2_set_err_rsp()
151 err_rsp->ErrorContextCount = 0; in smb2_set_err_rsp()
152 err_rsp->Reserved = 0; in smb2_set_err_rsp()
153 err_rsp->ByteCount = 0; in smb2_set_err_rsp()
154 err_rsp->ErrorData[0] = 0; in smb2_set_err_rsp()
159 work->send_no_response = 1; in smb2_set_err_rsp()
164 * is_smb2_neg_cmd() - is it smb2 negotiation command
171 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in is_smb2_neg_cmd()
174 if (hdr->ProtocolId != SMB2_PROTO_NUMBER) in is_smb2_neg_cmd()
178 if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) in is_smb2_neg_cmd()
181 if (hdr->Command != SMB2_NEGOTIATE) in is_smb2_neg_cmd()
188 * is_smb2_rsp() - is it smb2 response
195 struct smb2_hdr *hdr = smb2_get_msg(work->response_buf); in is_smb2_rsp()
198 if (hdr->ProtocolId != SMB2_PROTO_NUMBER) in is_smb2_rsp()
202 if (!(hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)) in is_smb2_rsp()
209 * get_smb2_cmd_val() - get smb command code from smb header
218 if (work->next_smb2_rcv_hdr_off) in get_smb2_cmd_val()
221 rcv_hdr = smb2_get_msg(work->request_buf); in get_smb2_cmd_val()
222 return le16_to_cpu(rcv_hdr->Command); in get_smb2_cmd_val()
226 * set_smb2_rsp_status() - set error response code on smb2 header
234 rsp_hdr = smb2_get_msg(work->response_buf); in set_smb2_rsp_status()
235 rsp_hdr->Status = err; in set_smb2_rsp_status()
237 work->iov_idx = 0; in set_smb2_rsp_status()
238 work->iov_cnt = 0; in set_smb2_rsp_status()
239 work->next_smb2_rcv_hdr_off = 0; in set_smb2_rsp_status()
244 * init_smb2_neg_rsp() - initialize smb2 response for negotiate command
248 * dialect auto-negotiation.
254 struct ksmbd_conn *conn = work->conn; in init_smb2_neg_rsp()
257 rsp_hdr = smb2_get_msg(work->response_buf); in init_smb2_neg_rsp()
259 rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER; in init_smb2_neg_rsp()
260 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; in init_smb2_neg_rsp()
261 rsp_hdr->CreditRequest = cpu_to_le16(2); in init_smb2_neg_rsp()
262 rsp_hdr->Command = SMB2_NEGOTIATE; in init_smb2_neg_rsp()
263 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR); in init_smb2_neg_rsp()
264 rsp_hdr->NextCommand = 0; in init_smb2_neg_rsp()
265 rsp_hdr->MessageId = 0; in init_smb2_neg_rsp()
266 rsp_hdr->Id.SyncId.ProcessId = 0; in init_smb2_neg_rsp()
267 rsp_hdr->Id.SyncId.TreeId = 0; in init_smb2_neg_rsp()
268 rsp_hdr->SessionId = 0; in init_smb2_neg_rsp()
269 memset(rsp_hdr->Signature, 0, 16); in init_smb2_neg_rsp()
271 rsp = smb2_get_msg(work->response_buf); in init_smb2_neg_rsp()
275 rsp->StructureSize = cpu_to_le16(65); in init_smb2_neg_rsp()
276 ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect); in init_smb2_neg_rsp()
277 rsp->DialectRevision = cpu_to_le16(conn->dialect); in init_smb2_neg_rsp()
278 /* Not setting conn guid rsp->ServerGUID, as it in init_smb2_neg_rsp()
281 rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); in init_smb2_neg_rsp()
283 rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size); in init_smb2_neg_rsp()
284 rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size); in init_smb2_neg_rsp()
285 rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size); in init_smb2_neg_rsp()
287 rsp->SystemTime = cpu_to_le64(ksmbd_systime()); in init_smb2_neg_rsp()
288 rsp->ServerStartTime = 0; in init_smb2_neg_rsp()
290 rsp->SecurityBufferOffset = cpu_to_le16(128); in init_smb2_neg_rsp()
291 rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH); in init_smb2_neg_rsp()
292 ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) + in init_smb2_neg_rsp()
293 le16_to_cpu(rsp->SecurityBufferOffset)); in init_smb2_neg_rsp()
294 rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE; in init_smb2_neg_rsp()
296 rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE; in init_smb2_neg_rsp()
301 conn->use_spnego = true; in init_smb2_neg_rsp()
308 * smb2_set_rsp_credits() - set number of credits in response buffer
315 struct ksmbd_conn *conn = work->conn; in smb2_set_rsp_credits()
319 if (work->send_no_response) in smb2_set_rsp_credits()
322 hdr->CreditCharge = req_hdr->CreditCharge; in smb2_set_rsp_credits()
324 if (conn->total_credits > conn->vals->max_credits) { in smb2_set_rsp_credits()
325 hdr->CreditRequest = 0; in smb2_set_rsp_credits()
326 pr_err("Total credits overflow: %d\n", conn->total_credits); in smb2_set_rsp_credits()
327 return -EINVAL; in smb2_set_rsp_credits()
331 le16_to_cpu(req_hdr->CreditCharge), 1); in smb2_set_rsp_credits()
332 if (credit_charge > conn->total_credits) { in smb2_set_rsp_credits()
334 credit_charge, conn->total_credits); in smb2_set_rsp_credits()
335 return -EINVAL; in smb2_set_rsp_credits()
338 conn->total_credits -= credit_charge; in smb2_set_rsp_credits()
339 conn->outstanding_credits -= credit_charge; in smb2_set_rsp_credits()
341 le16_to_cpu(req_hdr->CreditRequest), 1); in smb2_set_rsp_credits()
349 if (hdr->Command == SMB2_NEGOTIATE) in smb2_set_rsp_credits()
352 aux_max = conn->vals->max_credits - conn->total_credits; in smb2_set_rsp_credits()
355 conn->total_credits += credits_granted; in smb2_set_rsp_credits()
356 work->credits_granted += credits_granted; in smb2_set_rsp_credits()
358 if (!req_hdr->NextCommand) { in smb2_set_rsp_credits()
360 hdr->CreditRequest = cpu_to_le16(work->credits_granted); in smb2_set_rsp_credits()
365 conn->total_credits); in smb2_set_rsp_credits()
370 * init_chained_smb2_rsp() - initialize smb2 chained response
382 /* Len of this response = updated RFC len - offset of previous cmd in init_chained_smb2_rsp()
389 if (req->Command == SMB2_CREATE && rsp->Status == STATUS_SUCCESS) { in init_chained_smb2_rsp()
390 work->compound_fid = ((struct smb2_create_rsp *)rsp)->VolatileFileId; in init_chained_smb2_rsp()
391 work->compound_pfid = ((struct smb2_create_rsp *)rsp)->PersistentFileId; in init_chained_smb2_rsp()
392 work->compound_sid = le64_to_cpu(rsp->SessionId); in init_chained_smb2_rsp()
395 len = get_rfc1002_len(work->response_buf) - work->next_smb2_rsp_hdr_off; in init_chained_smb2_rsp()
396 next_hdr_offset = le32_to_cpu(req->NextCommand); in init_chained_smb2_rsp()
399 work->iov[work->iov_idx].iov_len += (new_len - len); in init_chained_smb2_rsp()
400 inc_rfc1001_len(work->response_buf, new_len - len); in init_chained_smb2_rsp()
401 rsp->NextCommand = cpu_to_le32(new_len); in init_chained_smb2_rsp()
403 work->next_smb2_rcv_hdr_off += next_hdr_offset; in init_chained_smb2_rsp()
404 work->curr_smb2_rsp_hdr_off = work->next_smb2_rsp_hdr_off; in init_chained_smb2_rsp()
405 work->next_smb2_rsp_hdr_off += new_len; in init_chained_smb2_rsp()
408 new_len, work->next_smb2_rcv_hdr_off, in init_chained_smb2_rsp()
409 work->next_smb2_rsp_hdr_off); in init_chained_smb2_rsp()
414 if (!(rcv_hdr->Flags & SMB2_FLAGS_RELATED_OPERATIONS)) { in init_chained_smb2_rsp()
416 work->compound_fid = KSMBD_NO_FID; in init_chained_smb2_rsp()
417 work->compound_pfid = KSMBD_NO_FID; in init_chained_smb2_rsp()
420 rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER; in init_chained_smb2_rsp()
421 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; in init_chained_smb2_rsp()
422 rsp_hdr->Command = rcv_hdr->Command; in init_chained_smb2_rsp()
427 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR | in init_chained_smb2_rsp()
429 rsp_hdr->NextCommand = 0; in init_chained_smb2_rsp()
430 rsp_hdr->MessageId = rcv_hdr->MessageId; in init_chained_smb2_rsp()
431 rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId; in init_chained_smb2_rsp()
432 rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId; in init_chained_smb2_rsp()
433 rsp_hdr->SessionId = rcv_hdr->SessionId; in init_chained_smb2_rsp()
434 memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16); in init_chained_smb2_rsp()
438 * is_chained_smb2_message() - check for chained command
445 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in is_chained_smb2_message()
448 if (hdr->ProtocolId != SMB2_PROTO_NUMBER) in is_chained_smb2_message()
452 next_cmd = le32_to_cpu(hdr->NextCommand); in is_chained_smb2_message()
454 if ((u64)work->next_smb2_rcv_hdr_off + next_cmd + in is_chained_smb2_message()
456 get_rfc1002_len(work->request_buf)) { in is_chained_smb2_message()
462 if ((u64)get_rfc1002_len(work->response_buf) + MAX_CIFS_SMALL_BUFFER_SIZE > in is_chained_smb2_message()
463 work->response_sz) { in is_chained_smb2_message()
471 } else if (work->next_smb2_rcv_hdr_off) { in is_chained_smb2_message()
476 len = ALIGN(get_rfc1002_len(work->response_buf), 8); in is_chained_smb2_message()
477 len = len - get_rfc1002_len(work->response_buf); in is_chained_smb2_message()
480 work->iov[work->iov_idx].iov_len += len; in is_chained_smb2_message()
481 inc_rfc1001_len(work->response_buf, len); in is_chained_smb2_message()
483 work->curr_smb2_rsp_hdr_off = work->next_smb2_rsp_hdr_off; in is_chained_smb2_message()
489 * init_smb2_rsp_hdr() - initialize smb2 response
496 struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf); in init_smb2_rsp_hdr()
497 struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf); in init_smb2_rsp_hdr()
500 rsp_hdr->ProtocolId = rcv_hdr->ProtocolId; in init_smb2_rsp_hdr()
501 rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE; in init_smb2_rsp_hdr()
502 rsp_hdr->Command = rcv_hdr->Command; in init_smb2_rsp_hdr()
507 rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR); in init_smb2_rsp_hdr()
508 rsp_hdr->NextCommand = 0; in init_smb2_rsp_hdr()
509 rsp_hdr->MessageId = rcv_hdr->MessageId; in init_smb2_rsp_hdr()
510 rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId; in init_smb2_rsp_hdr()
511 rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId; in init_smb2_rsp_hdr()
512 rsp_hdr->SessionId = rcv_hdr->SessionId; in init_smb2_rsp_hdr()
513 memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16); in init_smb2_rsp_hdr()
519 * smb2_allocate_rsp_buf() - allocate smb2 response buffer
526 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in smb2_allocate_rsp_buf()
528 size_t large_sz = small_sz + work->conn->vals->max_trans_size; in smb2_allocate_rsp_buf()
530 int cmd = le16_to_cpu(hdr->Command); in smb2_allocate_rsp_buf()
538 if (get_rfc1002_len(work->request_buf) < in smb2_allocate_rsp_buf()
540 return -EINVAL; in smb2_allocate_rsp_buf()
542 req = smb2_get_msg(work->request_buf); in smb2_allocate_rsp_buf()
543 if ((req->InfoType == SMB2_O_INFO_FILE && in smb2_allocate_rsp_buf()
544 (req->FileInfoClass == FILE_FULL_EA_INFORMATION || in smb2_allocate_rsp_buf()
545 req->FileInfoClass == FILE_ALL_INFORMATION)) || in smb2_allocate_rsp_buf()
546 req->InfoType == SMB2_O_INFO_SECURITY) in smb2_allocate_rsp_buf()
551 if (le32_to_cpu(hdr->NextCommand) > 0) in smb2_allocate_rsp_buf()
554 work->response_buf = kvzalloc(sz, GFP_KERNEL); in smb2_allocate_rsp_buf()
555 if (!work->response_buf) in smb2_allocate_rsp_buf()
556 return -ENOMEM; in smb2_allocate_rsp_buf()
558 work->response_sz = sz; in smb2_allocate_rsp_buf()
563 * smb2_check_user_session() - check for valid session for a user
571 struct ksmbd_conn *conn = work->conn; in smb2_check_user_session()
572 unsigned int cmd = le16_to_cpu(req_hdr->Command); in smb2_check_user_session()
585 return -EIO; in smb2_check_user_session()
587 sess_id = le64_to_cpu(req_hdr->SessionId); in smb2_check_user_session()
591 * Just validate session id in header with work->sess->id. in smb2_check_user_session()
593 if (work->next_smb2_rcv_hdr_off) { in smb2_check_user_session()
594 if (!work->sess) { in smb2_check_user_session()
596 return -EINVAL; in smb2_check_user_session()
598 if (sess_id != ULLONG_MAX && work->sess->id != sess_id) { in smb2_check_user_session()
600 sess_id, work->sess->id); in smb2_check_user_session()
601 return -EINVAL; in smb2_check_user_session()
607 work->sess = ksmbd_session_lookup_all(conn, sess_id); in smb2_check_user_session()
608 if (work->sess) { in smb2_check_user_session()
609 ksmbd_user_session_get(work->sess); in smb2_check_user_session()
613 return -ENOENT; in smb2_check_user_session()
617 * smb2_get_name() - get filename string from on the wire smb format
638 return ERR_PTR(-EINVAL); in smb2_get_name()
648 struct ksmbd_conn *conn = work->conn; in setup_async_work()
651 id = ksmbd_acquire_async_msg_id(&conn->async_ida); in setup_async_work()
656 work->asynchronous = true; in setup_async_work()
657 work->async_id = id; in setup_async_work()
661 work->async_id); in setup_async_work()
663 work->cancel_fn = fn; in setup_async_work()
664 work->cancel_argv = arg; in setup_async_work()
666 if (list_empty(&work->async_request_entry)) { in setup_async_work()
667 spin_lock(&conn->request_lock); in setup_async_work()
668 list_add_tail(&work->async_request_entry, &conn->async_requests); in setup_async_work()
669 spin_unlock(&conn->request_lock); in setup_async_work()
677 struct ksmbd_conn *conn = work->conn; in release_async_work()
679 spin_lock(&conn->request_lock); in release_async_work()
680 list_del_init(&work->async_request_entry); in release_async_work()
681 spin_unlock(&conn->request_lock); in release_async_work()
683 work->asynchronous = 0; in release_async_work()
684 work->cancel_fn = NULL; in release_async_work()
685 kfree(work->cancel_argv); in release_async_work()
686 work->cancel_argv = NULL; in release_async_work()
687 if (work->async_id) { in release_async_work()
688 ksmbd_release_id(&conn->async_ida, work->async_id); in release_async_work()
689 work->async_id = 0; in release_async_work()
704 in_work->conn = work->conn; in smb2_send_interim_resp()
705 memcpy(smb2_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work), in smb2_send_interim_resp()
708 rsp_hdr = smb2_get_msg(in_work->response_buf); in smb2_send_interim_resp()
709 rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND; in smb2_send_interim_resp()
710 rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id); in smb2_send_interim_resp()
712 rsp_hdr->Status = status; in smb2_send_interim_resp()
738 * smb2_get_dos_mode() - get file mode in dos format from unix mode
748 if (S_ISDIR(stat->mode)) { in smb2_get_dos_mode()
754 if (S_ISREG(stat->mode) && (server_conf.share_fake_fscaps & in smb2_get_dos_mode()
758 if (smb2_get_reparse_tag_special_file(stat->mode)) in smb2_get_dos_mode()
768 pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES; in build_preauth_ctxt()
769 pneg_ctxt->DataLength = cpu_to_le16(38); in build_preauth_ctxt()
770 pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1); in build_preauth_ctxt()
771 pneg_ctxt->Reserved = cpu_to_le32(0); in build_preauth_ctxt()
772 pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE); in build_preauth_ctxt()
773 get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE); in build_preauth_ctxt()
774 pneg_ctxt->HashAlgorithms = hash_id; in build_preauth_ctxt()
780 pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES; in build_encrypt_ctxt()
781 pneg_ctxt->DataLength = cpu_to_le16(4); in build_encrypt_ctxt()
782 pneg_ctxt->Reserved = cpu_to_le32(0); in build_encrypt_ctxt()
783 pneg_ctxt->CipherCount = cpu_to_le16(1); in build_encrypt_ctxt()
784 pneg_ctxt->Ciphers[0] = cipher_type; in build_encrypt_ctxt()
790 pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES; in build_sign_cap_ctxt()
791 pneg_ctxt->DataLength = in build_sign_cap_ctxt()
793 - sizeof(struct smb2_neg_context)); in build_sign_cap_ctxt()
794 pneg_ctxt->Reserved = cpu_to_le32(0); in build_sign_cap_ctxt()
795 pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(1); in build_sign_cap_ctxt()
796 pneg_ctxt->SigningAlgorithms[0] = sign_algo; in build_sign_cap_ctxt()
801 pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE; in build_posix_ctxt()
802 pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN); in build_posix_ctxt()
804 pneg_ctxt->Name[0] = 0x93; in build_posix_ctxt()
805 pneg_ctxt->Name[1] = 0xAD; in build_posix_ctxt()
806 pneg_ctxt->Name[2] = 0x25; in build_posix_ctxt()
807 pneg_ctxt->Name[3] = 0x50; in build_posix_ctxt()
808 pneg_ctxt->Name[4] = 0x9C; in build_posix_ctxt()
809 pneg_ctxt->Name[5] = 0xB4; in build_posix_ctxt()
810 pneg_ctxt->Name[6] = 0x11; in build_posix_ctxt()
811 pneg_ctxt->Name[7] = 0xE7; in build_posix_ctxt()
812 pneg_ctxt->Name[8] = 0xB4; in build_posix_ctxt()
813 pneg_ctxt->Name[9] = 0x23; in build_posix_ctxt()
814 pneg_ctxt->Name[10] = 0x83; in build_posix_ctxt()
815 pneg_ctxt->Name[11] = 0xDE; in build_posix_ctxt()
816 pneg_ctxt->Name[12] = 0x96; in build_posix_ctxt()
817 pneg_ctxt->Name[13] = 0x8B; in build_posix_ctxt()
818 pneg_ctxt->Name[14] = 0xCD; in build_posix_ctxt()
819 pneg_ctxt->Name[15] = 0x7C; in build_posix_ctxt()
826 le32_to_cpu(rsp->NegotiateContextOffset); in assemble_neg_contexts()
833 conn->preauth_info->Preauth_HashId); in assemble_neg_contexts()
836 if (conn->cipher_type) { in assemble_neg_contexts()
843 conn->cipher_type); in assemble_neg_contexts()
849 WARN_ON(conn->compress_algorithm != SMB3_COMPRESS_NONE); in assemble_neg_contexts()
851 if (conn->posix_ext_supported) { in assemble_neg_contexts()
861 if (conn->signing_negotiated) { in assemble_neg_contexts()
867 conn->signing_algorithm); in assemble_neg_contexts()
872 rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt); in assemble_neg_contexts()
888 if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512) in decode_preauth_ctxt()
891 conn->preauth_info->Preauth_HashId = SMB2_PREAUTH_INTEGRITY_SHA512; in decode_preauth_ctxt()
907 conn->cipher_type = 0; in decode_encrypt_ctxt()
909 cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount); in decode_encrypt_ctxt()
922 if (pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_GCM || in decode_encrypt_ctxt()
923 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_CCM || in decode_encrypt_ctxt()
924 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_CCM || in decode_encrypt_ctxt()
925 pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_GCM) { in decode_encrypt_ctxt()
927 pneg_ctxt->Ciphers[i]); in decode_encrypt_ctxt()
928 conn->cipher_type = pneg_ctxt->Ciphers[i]; in decode_encrypt_ctxt()
935 * smb3_encryption_negotiated() - checks if server and client agreed on enabling encryption
942 if (!conn->ops->generate_encryptionkey) in smb3_encryption_negotiated()
949 return (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) || in smb3_encryption_negotiated()
950 conn->cipher_type; in smb3_encryption_negotiated()
956 conn->compress_algorithm = SMB3_COMPRESS_NONE; in decode_compress_ctxt()
971 conn->signing_negotiated = false; in decode_sign_cap_ctxt()
972 sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount); in decode_sign_cap_ctxt()
982 if (pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_HMAC_SHA256_LE || in decode_sign_cap_ctxt()
983 pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_AES_CMAC_LE) { in decode_sign_cap_ctxt()
985 pneg_ctxt->SigningAlgorithms[i]); in decode_sign_cap_ctxt()
986 conn->signing_negotiated = true; in decode_sign_cap_ctxt()
987 conn->signing_algorithm = in decode_sign_cap_ctxt()
988 pneg_ctxt->SigningAlgorithms[i]; in decode_sign_cap_ctxt()
1001 unsigned int offset = le32_to_cpu(req->NegotiateContextOffset); in deassemble_neg_contexts()
1002 unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount); in deassemble_neg_contexts()
1011 len_of_ctxts = len_of_smb - offset; in deassemble_neg_contexts()
1020 clen = le16_to_cpu(pctx->DataLength); in deassemble_neg_contexts()
1026 if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) { in deassemble_neg_contexts()
1029 if (conn->preauth_info->Preauth_HashId) in deassemble_neg_contexts()
1037 } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) { in deassemble_neg_contexts()
1040 if (conn->cipher_type) in deassemble_neg_contexts()
1046 } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) { in deassemble_neg_contexts()
1049 if (conn->compress_algorithm) in deassemble_neg_contexts()
1054 } else if (pctx->ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) { in deassemble_neg_contexts()
1057 } else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) { in deassemble_neg_contexts()
1060 conn->posix_ext_supported = true; in deassemble_neg_contexts()
1061 } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) { in deassemble_neg_contexts()
1072 len_of_ctxts -= offset; in deassemble_neg_contexts()
1078 * smb2_handle_negotiate() - handler for smb2 negotiate command
1085 struct ksmbd_conn *conn = work->conn; in smb2_handle_negotiate()
1086 struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf); in smb2_handle_negotiate()
1087 struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf); in smb2_handle_negotiate()
1093 conn->need_neg = false; in smb2_handle_negotiate()
1095 pr_err("conn->tcp_status is already in CifsGood State\n"); in smb2_handle_negotiate()
1096 work->send_no_response = 1; in smb2_handle_negotiate()
1100 smb2_buf_len = get_rfc1002_len(work->request_buf); in smb2_handle_negotiate()
1103 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1104 rc = -EINVAL; in smb2_handle_negotiate()
1108 if (req->DialectCount == 0) { in smb2_handle_negotiate()
1110 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1111 rc = -EINVAL; in smb2_handle_negotiate()
1115 if (conn->dialect == SMB311_PROT_ID) { in smb2_handle_negotiate()
1116 unsigned int nego_ctxt_off = le32_to_cpu(req->NegotiateContextOffset); in smb2_handle_negotiate()
1119 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1120 rc = -EINVAL; in smb2_handle_negotiate()
1125 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1126 rc = -EINVAL; in smb2_handle_negotiate()
1130 if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > in smb2_handle_negotiate()
1132 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1133 rc = -EINVAL; in smb2_handle_negotiate()
1137 if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > in smb2_handle_negotiate()
1139 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1140 rc = -EINVAL; in smb2_handle_negotiate()
1145 conn->cli_cap = le32_to_cpu(req->Capabilities); in smb2_handle_negotiate()
1146 switch (conn->dialect) { in smb2_handle_negotiate()
1148 conn->preauth_info = in smb2_handle_negotiate()
1151 if (!conn->preauth_info) { in smb2_handle_negotiate()
1152 rc = -ENOMEM; in smb2_handle_negotiate()
1153 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1158 get_rfc1002_len(work->request_buf)); in smb2_handle_negotiate()
1162 rsp->hdr.Status = status; in smb2_handle_negotiate()
1163 rc = -EINVAL; in smb2_handle_negotiate()
1164 kfree(conn->preauth_info); in smb2_handle_negotiate()
1165 conn->preauth_info = NULL; in smb2_handle_negotiate()
1171 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_handle_negotiate()
1172 kfree(conn->preauth_info); in smb2_handle_negotiate()
1173 conn->preauth_info = NULL; in smb2_handle_negotiate()
1178 work->request_buf, in smb2_handle_negotiate()
1179 conn->preauth_info->Preauth_HashValue); in smb2_handle_negotiate()
1180 rsp->NegotiateContextOffset = in smb2_handle_negotiate()
1197 conn->dialect); in smb2_handle_negotiate()
1198 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_handle_negotiate()
1199 rc = -EINVAL; in smb2_handle_negotiate()
1202 rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); in smb2_handle_negotiate()
1205 conn->connection_type = conn->dialect; in smb2_handle_negotiate()
1207 rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size); in smb2_handle_negotiate()
1208 rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size); in smb2_handle_negotiate()
1209 rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size); in smb2_handle_negotiate()
1211 memcpy(conn->ClientGUID, req->ClientGUID, in smb2_handle_negotiate()
1213 conn->cli_sec_mode = le16_to_cpu(req->SecurityMode); in smb2_handle_negotiate()
1215 rsp->StructureSize = cpu_to_le16(65); in smb2_handle_negotiate()
1216 rsp->DialectRevision = cpu_to_le16(conn->dialect); in smb2_handle_negotiate()
1217 /* Not setting conn guid rsp->ServerGUID, as it in smb2_handle_negotiate()
1220 memset(rsp->ServerGUID, 0, SMB2_CLIENT_GUID_SIZE); in smb2_handle_negotiate()
1222 rsp->SystemTime = cpu_to_le64(ksmbd_systime()); in smb2_handle_negotiate()
1223 rsp->ServerStartTime = 0; in smb2_handle_negotiate()
1225 le32_to_cpu(rsp->NegotiateContextOffset), in smb2_handle_negotiate()
1226 le16_to_cpu(rsp->NegotiateContextCount)); in smb2_handle_negotiate()
1228 rsp->SecurityBufferOffset = cpu_to_le16(128); in smb2_handle_negotiate()
1229 rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH); in smb2_handle_negotiate()
1230 ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) + in smb2_handle_negotiate()
1231 le16_to_cpu(rsp->SecurityBufferOffset)); in smb2_handle_negotiate()
1233 rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE; in smb2_handle_negotiate()
1234 conn->use_spnego = true; in smb2_handle_negotiate()
1238 req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED_LE) in smb2_handle_negotiate()
1239 conn->sign = true; in smb2_handle_negotiate()
1242 rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE; in smb2_handle_negotiate()
1243 conn->sign = true; in smb2_handle_negotiate()
1246 conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode); in smb2_handle_negotiate()
1251 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_handle_negotiate()
1265 if (sess->Preauth_HashValue) in alloc_preauth_hash()
1268 sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue, in alloc_preauth_hash()
1270 if (!sess->Preauth_HashValue) in alloc_preauth_hash()
1271 return -ENOMEM; in alloc_preauth_hash()
1278 struct ksmbd_conn *conn = work->conn; in generate_preauth_hash()
1279 struct ksmbd_session *sess = work->sess; in generate_preauth_hash()
1282 if (conn->dialect != SMB311_PROT_ID) in generate_preauth_hash()
1285 if (conn->binding) { in generate_preauth_hash()
1288 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id); in generate_preauth_hash()
1290 preauth_sess = ksmbd_preauth_session_alloc(conn, sess->id); in generate_preauth_hash()
1292 return -ENOMEM; in generate_preauth_hash()
1295 preauth_hash = preauth_sess->Preauth_HashValue; in generate_preauth_hash()
1297 if (!sess->Preauth_HashValue) in generate_preauth_hash()
1299 return -ENOMEM; in generate_preauth_hash()
1300 preauth_hash = sess->Preauth_HashValue; in generate_preauth_hash()
1303 ksmbd_gen_preauth_integrity_hash(conn, work->request_buf, preauth_hash); in generate_preauth_hash()
1311 if (!conn->use_spnego) in decode_negotiation_token()
1312 return -EINVAL; in decode_negotiation_token()
1316 conn->auth_mechs |= KSMBD_AUTH_NTLMSSP; in decode_negotiation_token()
1317 conn->preferred_auth_mech = KSMBD_AUTH_NTLMSSP; in decode_negotiation_token()
1318 conn->use_spnego = false; in decode_negotiation_token()
1335 rc = ksmbd_decode_ntlmssp_neg_blob(negblob, negblob_len, work->conn); in ntlm_negotiate()
1339 sz = le16_to_cpu(rsp->SecurityBufferOffset); in ntlm_negotiate()
1340 chgblob = (struct challenge_message *)rsp->Buffer; in ntlm_negotiate()
1343 if (!work->conn->use_spnego) { in ntlm_negotiate()
1344 sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn); in ntlm_negotiate()
1346 return -ENOMEM; in ntlm_negotiate()
1348 rsp->SecurityBufferLength = cpu_to_le16(sz); in ntlm_negotiate()
1357 return -ENOMEM; in ntlm_negotiate()
1360 sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn); in ntlm_negotiate()
1362 rc = -ENOMEM; in ntlm_negotiate()
1369 rc = -ENOMEM; in ntlm_negotiate()
1373 memcpy(rsp->Buffer, spnego_blob, spnego_blob_len); in ntlm_negotiate()
1374 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); in ntlm_negotiate()
1387 if (conn->use_spnego && conn->mechToken) in user_authblob()
1388 return (struct authenticate_message *)conn->mechToken; in user_authblob()
1390 sz = le16_to_cpu(req->SecurityBufferOffset); in user_authblob()
1391 return (struct authenticate_message *)((char *)&req->hdr.ProtocolId in user_authblob()
1403 if (conn->use_spnego && conn->mechToken) in session_user()
1404 secbuf_len = conn->mechTokenLen; in session_user()
1406 secbuf_len = le16_to_cpu(req->SecurityBufferLength); in session_user()
1412 name_off = le32_to_cpu(authblob->UserName.BufferOffset); in session_user()
1413 name_len = le16_to_cpu(authblob->UserName.Length); in session_user()
1421 conn->local_nls); in session_user()
1437 struct ksmbd_conn *conn = work->conn; in ntlm_authenticate()
1438 struct ksmbd_session *sess = work->sess; in ntlm_authenticate()
1439 struct channel *chann = NULL; in ntlm_authenticate()
1445 if (conn->use_spnego) { in ntlm_authenticate()
1453 return -ENOMEM; in ntlm_authenticate()
1455 memcpy(rsp->Buffer, spnego_blob, spnego_blob_len); in ntlm_authenticate()
1456 rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); in ntlm_authenticate()
1463 return -EPERM; in ntlm_authenticate()
1467 prev_id = le64_to_cpu(req->PreviousSessionId); in ntlm_authenticate()
1468 if (prev_id && prev_id != sess->id) in ntlm_authenticate()
1471 if (sess->state == SMB2_SESSION_VALID) { in ntlm_authenticate()
1476 if (conn->binding == false && ksmbd_anonymous_user(user)) { in ntlm_authenticate()
1481 if (!ksmbd_compare_user(sess->user, user)) { in ntlm_authenticate()
1483 return -EPERM; in ntlm_authenticate()
1487 sess->user = user; in ntlm_authenticate()
1490 if (conn->binding == false && user_guest(sess->user)) { in ntlm_authenticate()
1491 rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE; in ntlm_authenticate()
1496 if (conn->use_spnego && conn->mechToken) in ntlm_authenticate()
1497 sz = conn->mechTokenLen; in ntlm_authenticate()
1499 sz = le16_to_cpu(req->SecurityBufferLength); in ntlm_authenticate()
1502 set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD); in ntlm_authenticate()
1504 return -EPERM; in ntlm_authenticate()
1513 if (sess->state == SMB2_SESSION_VALID) { in ntlm_authenticate()
1514 if (conn->binding) in ntlm_authenticate()
1519 if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE && in ntlm_authenticate()
1520 (conn->sign || server_conf.enforced_signing)) || in ntlm_authenticate()
1521 (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) in ntlm_authenticate()
1522 sess->sign = true; in ntlm_authenticate()
1525 !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { in ntlm_authenticate()
1526 rc = conn->ops->generate_encryptionkey(conn, sess); in ntlm_authenticate()
1530 return -EINVAL; in ntlm_authenticate()
1532 sess->enc = true; in ntlm_authenticate()
1534 rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; in ntlm_authenticate()
1539 sess->sign = false; in ntlm_authenticate()
1543 if (conn->dialect >= SMB30_PROT_ID) { in ntlm_authenticate()
1546 chann = kmalloc(sizeof(struct channel), GFP_KERNEL); in ntlm_authenticate()
1548 return -ENOMEM; in ntlm_authenticate()
1550 chann->conn = conn; in ntlm_authenticate()
1551 xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL); in ntlm_authenticate()
1555 if (conn->ops->generate_signingkey) { in ntlm_authenticate()
1556 rc = conn->ops->generate_signingkey(sess, conn); in ntlm_authenticate()
1559 return -EINVAL; in ntlm_authenticate()
1565 return -ENOENT; in ntlm_authenticate()
1575 struct ksmbd_conn *conn = work->conn; in krb5_authenticate()
1576 struct ksmbd_session *sess = work->sess; in krb5_authenticate()
1578 struct channel *chann = NULL; in krb5_authenticate()
1583 in_blob = (char *)&req->hdr.ProtocolId + in krb5_authenticate()
1584 le16_to_cpu(req->SecurityBufferOffset); in krb5_authenticate()
1585 in_len = le16_to_cpu(req->SecurityBufferLength); in krb5_authenticate()
1586 out_blob = (char *)&rsp->hdr.ProtocolId + in krb5_authenticate()
1587 le16_to_cpu(rsp->SecurityBufferOffset); in krb5_authenticate()
1588 out_len = work->response_sz - in krb5_authenticate()
1589 (le16_to_cpu(rsp->SecurityBufferOffset) + 4); in krb5_authenticate()
1592 prev_sess_id = le64_to_cpu(req->PreviousSessionId); in krb5_authenticate()
1593 if (prev_sess_id && prev_sess_id != sess->id) in krb5_authenticate()
1594 destroy_previous_session(conn, sess->user, prev_sess_id); in krb5_authenticate()
1596 if (sess->state == SMB2_SESSION_VALID) in krb5_authenticate()
1597 ksmbd_free_user(sess->user); in krb5_authenticate()
1603 return -EINVAL; in krb5_authenticate()
1605 rsp->SecurityBufferLength = cpu_to_le16(out_len); in krb5_authenticate()
1607 if ((conn->sign || server_conf.enforced_signing) || in krb5_authenticate()
1608 (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) in krb5_authenticate()
1609 sess->sign = true; in krb5_authenticate()
1612 retval = conn->ops->generate_encryptionkey(conn, sess); in krb5_authenticate()
1616 return -EINVAL; in krb5_authenticate()
1618 sess->enc = true; in krb5_authenticate()
1620 rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; in krb5_authenticate()
1621 sess->sign = false; in krb5_authenticate()
1624 if (conn->dialect >= SMB30_PROT_ID) { in krb5_authenticate()
1627 chann = kmalloc(sizeof(struct channel), GFP_KERNEL); in krb5_authenticate()
1629 return -ENOMEM; in krb5_authenticate()
1631 chann->conn = conn; in krb5_authenticate()
1632 xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL); in krb5_authenticate()
1636 if (conn->ops->generate_signingkey) { in krb5_authenticate()
1637 retval = conn->ops->generate_signingkey(sess, conn); in krb5_authenticate()
1640 return -EINVAL; in krb5_authenticate()
1646 return -ENOENT; in krb5_authenticate()
1655 return -EOPNOTSUPP; in krb5_authenticate()
1661 struct ksmbd_conn *conn = work->conn; in smb2_sess_setup()
1673 rsp->StructureSize = cpu_to_le16(9); in smb2_sess_setup()
1674 rsp->SessionFlags = 0; in smb2_sess_setup()
1675 rsp->SecurityBufferOffset = cpu_to_le16(72); in smb2_sess_setup()
1676 rsp->SecurityBufferLength = 0; in smb2_sess_setup()
1679 if (!req->hdr.SessionId) { in smb2_sess_setup()
1682 rc = -ENOMEM; in smb2_sess_setup()
1685 rsp->hdr.SessionId = cpu_to_le64(sess->id); in smb2_sess_setup()
1690 conn->binding = false; in smb2_sess_setup()
1691 } else if (conn->dialect >= SMB30_PROT_ID && in smb2_sess_setup()
1693 req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) { in smb2_sess_setup()
1694 u64 sess_id = le64_to_cpu(req->hdr.SessionId); in smb2_sess_setup()
1698 rc = -ENOENT; in smb2_sess_setup()
1702 if (conn->dialect != sess->dialect) { in smb2_sess_setup()
1703 rc = -EINVAL; in smb2_sess_setup()
1707 if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) { in smb2_sess_setup()
1708 rc = -EINVAL; in smb2_sess_setup()
1712 if (strncmp(conn->ClientGUID, sess->ClientGUID, in smb2_sess_setup()
1714 rc = -ENOENT; in smb2_sess_setup()
1718 if (sess->state == SMB2_SESSION_IN_PROGRESS) { in smb2_sess_setup()
1719 rc = -EACCES; in smb2_sess_setup()
1723 if (sess->state == SMB2_SESSION_EXPIRED) { in smb2_sess_setup()
1724 rc = -EFAULT; in smb2_sess_setup()
1729 rc = -EFAULT; in smb2_sess_setup()
1735 rc = -EACCES; in smb2_sess_setup()
1739 if (user_guest(sess->user)) { in smb2_sess_setup()
1740 rc = -EOPNOTSUPP; in smb2_sess_setup()
1744 conn->binding = true; in smb2_sess_setup()
1746 } else if ((conn->dialect < SMB30_PROT_ID || in smb2_sess_setup()
1748 (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { in smb2_sess_setup()
1750 rc = -EACCES; in smb2_sess_setup()
1754 le64_to_cpu(req->hdr.SessionId)); in smb2_sess_setup()
1756 rc = -ENOENT; in smb2_sess_setup()
1760 if (sess->state == SMB2_SESSION_EXPIRED) { in smb2_sess_setup()
1761 rc = -EFAULT; in smb2_sess_setup()
1766 rc = -EFAULT; in smb2_sess_setup()
1771 conn->binding = false; in smb2_sess_setup()
1774 work->sess = sess; in smb2_sess_setup()
1776 negblob_off = le16_to_cpu(req->SecurityBufferOffset); in smb2_sess_setup()
1777 negblob_len = le16_to_cpu(req->SecurityBufferLength); in smb2_sess_setup()
1779 rc = -EINVAL; in smb2_sess_setup()
1783 negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId + in smb2_sess_setup()
1787 if (conn->mechToken) { in smb2_sess_setup()
1788 negblob = (struct negotiate_message *)conn->mechToken; in smb2_sess_setup()
1789 negblob_len = conn->mechTokenLen; in smb2_sess_setup()
1794 rc = -EINVAL; in smb2_sess_setup()
1798 if (server_conf.auth_mechs & conn->auth_mechs) { in smb2_sess_setup()
1803 if (conn->preferred_auth_mech & in smb2_sess_setup()
1807 rc = -EINVAL; in smb2_sess_setup()
1813 sess->state = SMB2_SESSION_VALID; in smb2_sess_setup()
1815 kfree(sess->Preauth_HashValue); in smb2_sess_setup()
1816 sess->Preauth_HashValue = NULL; in smb2_sess_setup()
1817 } else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) { in smb2_sess_setup()
1818 if (negblob->MessageType == NtLmNegotiate) { in smb2_sess_setup()
1822 rsp->hdr.Status = in smb2_sess_setup()
1824 } else if (negblob->MessageType == NtLmAuthenticate) { in smb2_sess_setup()
1831 sess->state = SMB2_SESSION_VALID; in smb2_sess_setup()
1833 if (conn->binding) { in smb2_sess_setup()
1837 ksmbd_preauth_session_lookup(conn, sess->id); in smb2_sess_setup()
1839 list_del(&preauth_sess->preauth_entry); in smb2_sess_setup()
1843 kfree(sess->Preauth_HashValue); in smb2_sess_setup()
1844 sess->Preauth_HashValue = NULL; in smb2_sess_setup()
1847 le32_to_cpu(negblob->MessageType)); in smb2_sess_setup()
1848 rc = -EINVAL; in smb2_sess_setup()
1853 rc = -EINVAL; in smb2_sess_setup()
1857 rc = -EINVAL; in smb2_sess_setup()
1861 if (rc == -EINVAL) in smb2_sess_setup()
1862 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_sess_setup()
1863 else if (rc == -ENOENT) in smb2_sess_setup()
1864 rsp->hdr.Status = STATUS_USER_SESSION_DELETED; in smb2_sess_setup()
1865 else if (rc == -EACCES) in smb2_sess_setup()
1866 rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED; in smb2_sess_setup()
1867 else if (rc == -EFAULT) in smb2_sess_setup()
1868 rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED; in smb2_sess_setup()
1869 else if (rc == -ENOMEM) in smb2_sess_setup()
1870 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_sess_setup()
1871 else if (rc == -EOPNOTSUPP) in smb2_sess_setup()
1872 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_sess_setup()
1874 rsp->hdr.Status = STATUS_LOGON_FAILURE; in smb2_sess_setup()
1876 if (conn->use_spnego && conn->mechToken) { in smb2_sess_setup()
1877 kfree(conn->mechToken); in smb2_sess_setup()
1878 conn->mechToken = NULL; in smb2_sess_setup()
1886 rsp->SecurityBufferOffset = 0; in smb2_sess_setup()
1897 if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION) in smb2_sess_setup()
1900 sess->last_active = jiffies; in smb2_sess_setup()
1901 sess->state = SMB2_SESSION_EXPIRED; in smb2_sess_setup()
1912 if (rsp->SecurityBufferLength) in smb2_sess_setup()
1914 le16_to_cpu(rsp->SecurityBufferLength); in smb2_sess_setup()
1919 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_sess_setup()
1927 * smb2_tree_connect() - handler for smb2 tree connect command
1934 struct ksmbd_conn *conn = work->conn; in smb2_tree_connect()
1937 struct ksmbd_session *sess = work->sess; in smb2_tree_connect()
1941 int rc = -EINVAL; in smb2_tree_connect()
1945 treename = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->PathOffset), in smb2_tree_connect()
1946 le16_to_cpu(req->PathLength), true, in smb2_tree_connect()
1947 conn->local_nls); in smb2_tree_connect()
1954 name = ksmbd_extract_sharename(conn->um, treename); in smb2_tree_connect()
1965 rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id); in smb2_tree_connect()
1969 share = status.tree_conn->share_conf; in smb2_tree_connect()
1972 rsp->ShareType = SMB2_SHARE_TYPE_PIPE; in smb2_tree_connect()
1973 rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE | in smb2_tree_connect()
1979 rsp->ShareType = SMB2_SHARE_TYPE_DISK; in smb2_tree_connect()
1980 rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE | in smb2_tree_connect()
1984 rsp->MaximalAccess |= FILE_WRITE_DATA_LE | in smb2_tree_connect()
1993 status.tree_conn->maximal_access = le32_to_cpu(rsp->MaximalAccess); in smb2_tree_connect()
1994 if (conn->posix_ext_supported) in smb2_tree_connect()
1995 status.tree_conn->posix_extensions = true; in smb2_tree_connect()
1997 write_lock(&sess->tree_conns_lock); in smb2_tree_connect()
1998 status.tree_conn->t_state = TREE_CONNECTED; in smb2_tree_connect()
1999 write_unlock(&sess->tree_conns_lock); in smb2_tree_connect()
2000 rsp->StructureSize = cpu_to_le16(16); in smb2_tree_connect()
2005 rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY; in smb2_tree_connect()
2007 rsp->Capabilities = 0; in smb2_tree_connect()
2008 rsp->Reserved = 0; in smb2_tree_connect()
2010 rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING; in smb2_tree_connect()
2023 rsp->hdr.Status = STATUS_SUCCESS; in smb2_tree_connect()
2026 case -ESTALE: in smb2_tree_connect()
2027 case -ENOENT: in smb2_tree_connect()
2029 rsp->hdr.Status = STATUS_BAD_NETWORK_NAME; in smb2_tree_connect()
2031 case -ENOMEM: in smb2_tree_connect()
2033 rsp->hdr.Status = STATUS_NO_MEMORY; in smb2_tree_connect()
2038 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_tree_connect()
2040 case -EINVAL: in smb2_tree_connect()
2041 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_tree_connect()
2044 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_tree_connect()
2054 * smb2_create_open_flags() - convert smb open flags to unix open flags
2126 * smb2_tree_disconnect() - handler for smb tree connect request
2135 struct ksmbd_session *sess = work->sess; in smb2_tree_disconnect()
2136 struct ksmbd_tree_connect *tcon = work->tcon; in smb2_tree_disconnect() local
2143 if (!tcon) { in smb2_tree_disconnect()
2144 ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); in smb2_tree_disconnect()
2146 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_tree_disconnect()
2147 err = -ENOENT; in smb2_tree_disconnect()
2153 write_lock(&sess->tree_conns_lock); in smb2_tree_disconnect()
2154 if (tcon->t_state == TREE_DISCONNECTED) { in smb2_tree_disconnect()
2155 write_unlock(&sess->tree_conns_lock); in smb2_tree_disconnect()
2156 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_tree_disconnect()
2157 err = -ENOENT; in smb2_tree_disconnect()
2161 WARN_ON_ONCE(atomic_dec_and_test(&tcon->refcount)); in smb2_tree_disconnect()
2162 tcon->t_state = TREE_DISCONNECTED; in smb2_tree_disconnect()
2163 write_unlock(&sess->tree_conns_lock); in smb2_tree_disconnect()
2165 err = ksmbd_tree_conn_disconnect(sess, tcon); in smb2_tree_disconnect()
2167 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_tree_disconnect()
2171 work->tcon = NULL; in smb2_tree_disconnect()
2173 rsp->StructureSize = cpu_to_le16(4); in smb2_tree_disconnect()
2177 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_tree_disconnect()
2190 * smb2_session_logoff() - handler for session log off request
2197 struct ksmbd_conn *conn = work->conn; in smb2_session_logoff()
2211 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_session_logoff()
2213 return -ENOENT; in smb2_session_logoff()
2215 sess_id = le64_to_cpu(req->hdr.SessionId); in smb2_session_logoff()
2223 * Re-lookup session to validate if session is deleted in smb2_session_logoff()
2228 ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); in smb2_session_logoff()
2229 rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; in smb2_session_logoff()
2231 return -ENOENT; in smb2_session_logoff()
2234 ksmbd_destroy_file_table(&sess->file_table); in smb2_session_logoff()
2235 down_write(&conn->session_lock); in smb2_session_logoff()
2236 sess->state = SMB2_SESSION_EXPIRED; in smb2_session_logoff()
2237 up_write(&conn->session_lock); in smb2_session_logoff()
2239 ksmbd_free_user(sess->user); in smb2_session_logoff()
2240 sess->user = NULL; in smb2_session_logoff()
2243 rsp->StructureSize = cpu_to_le16(4); in smb2_session_logoff()
2246 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_session_logoff()
2254 * create_smb2_pipe() - create IPC pipe
2269 name = smb_strndup_from_utf16(req->Buffer, le16_to_cpu(req->NameLength), in create_smb2_pipe()
2270 1, work->conn->local_nls); in create_smb2_pipe()
2272 rsp->hdr.Status = STATUS_NO_MEMORY; in create_smb2_pipe()
2277 id = ksmbd_session_rpc_open(work->sess, name); in create_smb2_pipe()
2284 rsp->hdr.Status = STATUS_SUCCESS; in create_smb2_pipe()
2285 rsp->StructureSize = cpu_to_le16(89); in create_smb2_pipe()
2286 rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE; in create_smb2_pipe()
2287 rsp->Flags = 0; in create_smb2_pipe()
2288 rsp->CreateAction = cpu_to_le32(FILE_OPENED); in create_smb2_pipe()
2290 rsp->CreationTime = cpu_to_le64(0); in create_smb2_pipe()
2291 rsp->LastAccessTime = cpu_to_le64(0); in create_smb2_pipe()
2292 rsp->ChangeTime = cpu_to_le64(0); in create_smb2_pipe()
2293 rsp->AllocationSize = cpu_to_le64(0); in create_smb2_pipe()
2294 rsp->EndofFile = cpu_to_le64(0); in create_smb2_pipe()
2295 rsp->FileAttributes = FILE_ATTRIBUTE_NORMAL_LE; in create_smb2_pipe()
2296 rsp->Reserved2 = 0; in create_smb2_pipe()
2297 rsp->VolatileFileId = id; in create_smb2_pipe()
2298 rsp->PersistentFileId = 0; in create_smb2_pipe()
2299 rsp->CreateContextsOffset = 0; in create_smb2_pipe()
2300 rsp->CreateContextsLength = 0; in create_smb2_pipe()
2311 case -EINVAL: in create_smb2_pipe()
2312 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in create_smb2_pipe()
2314 case -ENOSPC: in create_smb2_pipe()
2315 case -ENOMEM: in create_smb2_pipe()
2316 rsp->hdr.Status = STATUS_NO_MEMORY; in create_smb2_pipe()
2328 * smb2_set_ea() - handler for setting extended attributes using set
2340 struct mnt_idmap *idmap = mnt_idmap(path->mnt); in smb2_set_ea()
2345 if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + in smb2_set_ea()
2346 le16_to_cpu(eabuf->EaValueLength)) in smb2_set_ea()
2347 return -EINVAL; in smb2_set_ea()
2351 return -ENOMEM; in smb2_set_ea()
2354 if (!eabuf->EaNameLength) in smb2_set_ea()
2359 eabuf->name, eabuf->EaNameLength, in smb2_set_ea()
2360 le16_to_cpu(eabuf->EaValueLength), in smb2_set_ea()
2361 le32_to_cpu(eabuf->NextEntryOffset)); in smb2_set_ea()
2363 if (eabuf->EaNameLength > in smb2_set_ea()
2364 (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) { in smb2_set_ea()
2365 rc = -EINVAL; in smb2_set_ea()
2370 memcpy(&attr_name[XATTR_USER_PREFIX_LEN], eabuf->name, in smb2_set_ea()
2371 eabuf->EaNameLength); in smb2_set_ea()
2372 attr_name[XATTR_USER_PREFIX_LEN + eabuf->EaNameLength] = '\0'; in smb2_set_ea()
2373 value = (char *)&eabuf->name + eabuf->EaNameLength + 1; in smb2_set_ea()
2375 if (!eabuf->EaValueLength) { in smb2_set_ea()
2377 path->dentry, in smb2_set_ea()
2380 eabuf->EaNameLength); in smb2_set_ea()
2401 le16_to_cpu(eabuf->EaValueLength), in smb2_set_ea()
2412 next = le32_to_cpu(eabuf->NextEntryOffset); in smb2_set_ea()
2415 buf_len -= next; in smb2_set_ea()
2418 rc = -EINVAL; in smb2_set_ea()
2422 if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + in smb2_set_ea()
2423 le16_to_cpu(eabuf->EaValueLength)) { in smb2_set_ea()
2424 rc = -EINVAL; in smb2_set_ea()
2437 struct mnt_idmap *idmap = mnt_idmap(path->mnt); in smb2_set_stream_name_xattr()
2449 fp->stream.name = xattr_stream_name; in smb2_set_stream_name_xattr()
2450 fp->stream.size = xattr_stream_size; in smb2_set_stream_name_xattr()
2454 path->dentry, in smb2_set_stream_name_xattr()
2460 if (fp->cdoption == FILE_OPEN_LE) { in smb2_set_stream_name_xattr()
2462 return -EBADF; in smb2_set_stream_name_xattr()
2473 struct mnt_idmap *idmap = mnt_idmap(path->mnt); in smb2_remove_smb_xattrs()
2478 xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list); in smb2_remove_smb_xattrs()
2486 for (name = xattr_list; name - xattr_list < xattr_list_len; in smb2_remove_smb_xattrs()
2515 if (rc == -EOPNOTSUPP) in smb2_create_truncate()
2524 static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *path, in smb2_new_xattrs() argument
2530 if (!test_share_config_flag(tcon->share_conf, in smb2_new_xattrs()
2535 da.attr = le32_to_cpu(fp->f_ci->m_fattr); in smb2_new_xattrs()
2536 da.itime = da.create_time = fp->create_time; in smb2_new_xattrs()
2540 rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da, true); in smb2_new_xattrs()
2545 static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon, in smb2_update_xattrs() argument
2551 fp->f_ci->m_fattr &= ~(FILE_ATTRIBUTE_HIDDEN_LE | FILE_ATTRIBUTE_SYSTEM_LE); in smb2_update_xattrs()
2554 if (!test_share_config_flag(tcon->share_conf, in smb2_update_xattrs()
2558 rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_idmap(path->mnt), in smb2_update_xattrs()
2559 path->dentry, &da); in smb2_update_xattrs()
2561 fp->f_ci->m_fattr = cpu_to_le32(da.attr); in smb2_update_xattrs()
2562 fp->create_time = da.create_time; in smb2_update_xattrs()
2563 fp->itime = da.itime; in smb2_update_xattrs()
2571 struct ksmbd_tree_connect *tcon = work->tcon; in smb2_creat() local
2572 struct ksmbd_share_config *share = tcon->share_conf; in smb2_creat()
2577 return -EBADF; in smb2_creat()
2612 if (!req->CreateContextsOffset) in smb2_create_sd_buffer()
2613 return -ENOENT; in smb2_create_sd_buffer()
2618 return -ENOENT; in smb2_create_sd_buffer()
2625 if (le16_to_cpu(context->DataOffset) + in smb2_create_sd_buffer()
2626 le32_to_cpu(context->DataLength) < in smb2_create_sd_buffer()
2628 return -EINVAL; in smb2_create_sd_buffer()
2629 return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd, in smb2_create_sd_buffer()
2630 le32_to_cpu(sd_buf->ccontext.DataLength), true, false); in smb2_create_sd_buffer()
2640 fattr->cf_uid = vfsuid_into_kuid(vfsuid); in ksmbd_acls_fattr()
2641 fattr->cf_gid = vfsgid_into_kgid(vfsgid); in ksmbd_acls_fattr()
2642 fattr->cf_mode = inode->i_mode; in ksmbd_acls_fattr()
2643 fattr->cf_acls = NULL; in ksmbd_acls_fattr()
2644 fattr->cf_dacls = NULL; in ksmbd_acls_fattr()
2647 fattr->cf_acls = get_inode_acl(inode, ACL_TYPE_ACCESS); in ksmbd_acls_fattr()
2648 if (S_ISDIR(inode->i_mode)) in ksmbd_acls_fattr()
2649 fattr->cf_dacls = get_inode_acl(inode, ACL_TYPE_DEFAULT); in ksmbd_acls_fattr()
2674 struct ksmbd_conn *conn = work->conn; in parse_durable_handle_context()
2681 req_op_level = req->RequestedOplockLevel; in parse_durable_handle_context()
2684 context = smb2_find_context_vals(req, durable_arr[dh_idx - 1], 4); in parse_durable_handle_context()
2697 if (dh_info->type == DURABLE_RECONN || in parse_durable_handle_context()
2698 dh_info->type == DURABLE_REQ_V2) { in parse_durable_handle_context()
2699 err = -EINVAL; in parse_durable_handle_context()
2704 persistent_id = recon_v2->Fid.PersistentFileId; in parse_durable_handle_context()
2705 dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); in parse_durable_handle_context()
2706 if (!dh_info->fp) { in parse_durable_handle_context()
2708 err = -EBADF; in parse_durable_handle_context()
2712 if (memcmp(dh_info->fp->create_guid, recon_v2->CreateGuid, in parse_durable_handle_context()
2714 err = -EBADF; in parse_durable_handle_context()
2715 ksmbd_put_durable_fd(dh_info->fp); in parse_durable_handle_context()
2719 dh_info->type = dh_idx; in parse_durable_handle_context()
2720 dh_info->reconnected = true; in parse_durable_handle_context()
2722 "reconnect v2 Persistent-id from reconnect = %llu\n", in parse_durable_handle_context()
2730 if (dh_info->type == DURABLE_RECONN_V2 || in parse_durable_handle_context()
2731 dh_info->type == DURABLE_REQ_V2) { in parse_durable_handle_context()
2732 err = -EINVAL; in parse_durable_handle_context()
2737 persistent_id = recon->Data.Fid.PersistentFileId; in parse_durable_handle_context()
2738 dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); in parse_durable_handle_context()
2739 if (!dh_info->fp) { in parse_durable_handle_context()
2741 err = -EBADF; in parse_durable_handle_context()
2745 dh_info->type = dh_idx; in parse_durable_handle_context()
2746 dh_info->reconnected = true; in parse_durable_handle_context()
2747 ksmbd_debug(SMB, "reconnect Persistent-id from reconnect = %llu\n", in parse_durable_handle_context()
2755 if (dh_info->type == DURABLE_RECONN || in parse_durable_handle_context()
2756 dh_info->type == DURABLE_RECONN_V2) { in parse_durable_handle_context()
2757 err = -EINVAL; in parse_durable_handle_context()
2764 dh_info->fp = ksmbd_lookup_fd_cguid(durable_v2_blob->CreateGuid); in parse_durable_handle_context()
2765 if (dh_info->fp) { in parse_durable_handle_context()
2766 if (!memcmp(conn->ClientGUID, dh_info->fp->client_guid, in parse_durable_handle_context()
2768 if (!(req->hdr.Flags & SMB2_FLAGS_REPLAY_OPERATION)) { in parse_durable_handle_context()
2769 err = -ENOEXEC; in parse_durable_handle_context()
2773 dh_info->fp->conn = conn; in parse_durable_handle_context()
2774 dh_info->reconnected = true; in parse_durable_handle_context()
2779 if ((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || in parse_durable_handle_context()
2781 dh_info->CreateGuid = in parse_durable_handle_context()
2782 durable_v2_blob->CreateGuid; in parse_durable_handle_context()
2783 dh_info->persistent = in parse_durable_handle_context()
2784 le32_to_cpu(durable_v2_blob->Flags); in parse_durable_handle_context()
2785 dh_info->timeout = in parse_durable_handle_context()
2786 le32_to_cpu(durable_v2_blob->Timeout); in parse_durable_handle_context()
2787 dh_info->type = dh_idx; in parse_durable_handle_context()
2792 if (dh_info->type == DURABLE_RECONN) in parse_durable_handle_context()
2794 if (dh_info->type == DURABLE_RECONN_V2 || in parse_durable_handle_context()
2795 dh_info->type == DURABLE_REQ_V2) { in parse_durable_handle_context()
2796 err = -EINVAL; in parse_durable_handle_context()
2800 if ((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || in parse_durable_handle_context()
2803 dh_info->type = dh_idx; in parse_durable_handle_context()
2813 * smb2_open() - handler for smb file open request
2820 struct ksmbd_conn *conn = work->conn; in smb2_open()
2821 struct ksmbd_session *sess = work->sess; in smb2_open()
2822 struct ksmbd_tree_connect *tcon = work->tcon; in smb2_open() local
2826 struct ksmbd_share_config *share = tcon->share_conf; in smb2_open()
2854 if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off && in smb2_open()
2855 (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)) { in smb2_open()
2857 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_open()
2859 return -EINVAL; in smb2_open()
2867 if (req->NameLength) { in smb2_open()
2868 name = smb2_get_name((char *)req + le16_to_cpu(req->NameOffset), in smb2_open()
2869 le16_to_cpu(req->NameLength), in smb2_open()
2870 work->conn->local_nls); in smb2_open()
2879 if (!test_share_config_flag(work->tcon->share_conf, in smb2_open()
2881 rc = -EBADF; in smb2_open()
2894 rc = -ENOENT; in smb2_open()
2902 rc = -ENOMEM; in smb2_open()
2907 req_op_level = req->RequestedOplockLevel; in smb2_open()
2910 req->CreateContextsOffset) { in smb2_open()
2932 rc = -ENOMEM; in smb2_open()
2940 rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat); in smb2_open()
2950 if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) { in smb2_open()
2952 le32_to_cpu(req->ImpersonationLevel)); in smb2_open()
2953 rc = -EIO; in smb2_open()
2954 rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL; in smb2_open()
2958 if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) { in smb2_open()
2960 le32_to_cpu(req->CreateOptions)); in smb2_open()
2961 rc = -EINVAL; in smb2_open()
2964 if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE && in smb2_open()
2965 req->CreateOptions & FILE_RANDOM_ACCESS_LE) in smb2_open()
2966 req->CreateOptions = ~(FILE_SEQUENTIAL_ONLY_LE); in smb2_open()
2968 if (req->CreateOptions & in smb2_open()
2971 rc = -EOPNOTSUPP; in smb2_open()
2975 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { in smb2_open()
2976 if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) { in smb2_open()
2977 rc = -EINVAL; in smb2_open()
2979 } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) { in smb2_open()
2980 req->CreateOptions = ~(FILE_NO_COMPRESSION_LE); in smb2_open()
2985 if (le32_to_cpu(req->CreateDisposition) > in smb2_open()
2988 le32_to_cpu(req->CreateDisposition)); in smb2_open()
2989 rc = -EINVAL; in smb2_open()
2993 if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) { in smb2_open()
2995 le32_to_cpu(req->DesiredAccess)); in smb2_open()
2996 rc = -EACCES; in smb2_open()
3000 if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) { in smb2_open()
3002 le32_to_cpu(req->FileAttributes)); in smb2_open()
3003 rc = -EINVAL; in smb2_open()
3007 if (req->CreateContextsOffset) { in smb2_open()
3008 /* Parse non-durable handle create contexts */ in smb2_open()
3015 if (le16_to_cpu(context->DataOffset) + in smb2_open()
3016 le32_to_cpu(context->DataLength) < in smb2_open()
3018 rc = -EINVAL; in smb2_open()
3021 if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { in smb2_open()
3022 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_open()
3023 rc = -EACCES; in smb2_open()
3046 rc = -EBADF; in smb2_open()
3050 if (tcon->posix_extensions) { in smb2_open()
3059 if (le16_to_cpu(context->DataOffset) + in smb2_open()
3060 le32_to_cpu(context->DataLength) < in smb2_open()
3061 sizeof(struct create_posix) - 4) { in smb2_open()
3062 rc = -EINVAL; in smb2_open()
3067 posix_mode = le32_to_cpu(posix->Mode); in smb2_open()
3074 rc = -ENOMEM; in smb2_open()
3083 if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) { in smb2_open()
3088 if (req->CreateDisposition == FILE_OVERWRITE_IF_LE || in smb2_open()
3089 req->CreateDisposition == FILE_OPEN_IF_LE) { in smb2_open()
3090 rc = -EACCES; in smb2_open()
3094 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_open()
3097 rc = -EACCES; in smb2_open()
3101 rc = -EACCES; in smb2_open()
3107 if (rc != -ENOENT) in smb2_open()
3115 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { in smb2_open()
3117 rc = -EIO; in smb2_open()
3118 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY; in smb2_open()
3121 if (file_present && S_ISDIR(d_inode(path.dentry)->i_mode) && in smb2_open()
3123 rc = -EIO; in smb2_open()
3124 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY; in smb2_open()
3128 if (req->CreateOptions & FILE_DIRECTORY_FILE_LE && in smb2_open()
3129 req->FileAttributes & FILE_ATTRIBUTE_NORMAL_LE) { in smb2_open()
3130 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY; in smb2_open()
3131 rc = -EIO; in smb2_open()
3138 if (file_present && req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE && in smb2_open()
3139 S_ISDIR(d_inode(path.dentry)->i_mode) && in smb2_open()
3140 !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) { in smb2_open()
3142 name, req->CreateOptions); in smb2_open()
3143 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY; in smb2_open()
3144 rc = -EIO; in smb2_open()
3148 if (file_present && (req->CreateOptions & FILE_DIRECTORY_FILE_LE) && in smb2_open()
3149 !(req->CreateDisposition == FILE_CREATE_LE) && in smb2_open()
3150 !S_ISDIR(d_inode(path.dentry)->i_mode)) { in smb2_open()
3151 rsp->hdr.Status = STATUS_NOT_A_DIRECTORY; in smb2_open()
3152 rc = -EIO; in smb2_open()
3157 req->CreateDisposition == FILE_CREATE_LE) { in smb2_open()
3158 rc = -EEXIST; in smb2_open()
3162 daccess = smb_map_generic_desired_access(req->DesiredAccess); in smb2_open()
3164 if (file_present && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) { in smb2_open()
3166 sess->user->uid); in smb2_open()
3184 req->CreateDisposition, in smb2_open()
3186 req->CreateOptions, in smb2_open()
3187 file_present ? d_inode(path.dentry)->i_mode : 0); in smb2_open()
3189 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_open()
3193 rc = -EACCES; in smb2_open()
3202 req->CreateOptions & FILE_DIRECTORY_FILE_LE); in smb2_open()
3204 if (rc == -ENOENT) { in smb2_open()
3205 rc = -EIO; in smb2_open()
3206 rsp->hdr.Status = STATUS_OBJECT_PATH_NOT_FOUND; in smb2_open()
3214 if (le32_to_cpu(ea_buf->ccontext.DataLength) < in smb2_open()
3216 rc = -EINVAL; in smb2_open()
3220 rc = smb2_set_ea(&ea_buf->ea, in smb2_open()
3221 le32_to_cpu(ea_buf->ccontext.DataLength), in smb2_open()
3223 if (rc == -EOPNOTSUPP) in smb2_open()
3241 (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) { in smb2_open()
3243 d_inode(path.dentry->d_parent), in smb2_open()
3251 rc = ksmbd_query_inode_status(path.dentry->d_parent); in smb2_open()
3253 rc = -EBUSY; in smb2_open()
3271 if ((req->CreateDisposition & FILE_CREATE_MASK_LE) == in smb2_open()
3278 ksmbd_vfs_set_fadvise(filp, req->CreateOptions); in smb2_open()
3280 /* Obtain Volatile-ID */ in smb2_open()
3289 /* Get Persistent-ID */ in smb2_open()
3291 if (!has_file_id(fp->persistent_id)) { in smb2_open()
3292 rc = -ENOMEM; in smb2_open()
3296 fp->cdoption = req->CreateDisposition; in smb2_open()
3297 fp->daccess = daccess; in smb2_open()
3298 fp->saccess = req->ShareAccess; in smb2_open()
3299 fp->coption = req->CreateOptions; in smb2_open()
3308 d_inode(path.dentry->d_parent)); in smb2_open()
3312 if (test_share_config_flag(work->tcon->share_conf, in smb2_open()
3314 rc = smb_inherit_dacl(conn, &path, sess->user->uid, in smb2_open()
3315 sess->user->gid); in smb2_open()
3325 if (test_share_config_flag(work->tcon->share_conf, in smb2_open()
3333 ace_num = fattr.cf_acls->a_count; in smb2_open()
3335 ace_num += fattr.cf_dacls->a_count; in smb2_open()
3387 fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE | in smb2_open()
3394 down_write(&fp->f_ci->m_lock); in smb2_open()
3395 list_add(&fp->node, &fp->f_ci->m_fp_list); in smb2_open()
3396 up_write(&fp->f_ci->m_lock); in smb2_open()
3400 rc = -EBUSY; in smb2_open()
3407 if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC && in smb2_open()
3408 !fp->attrib_only && !stream_name) { in smb2_open()
3413 share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); in smb2_open()
3414 if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || in smb2_open()
3416 !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) { in smb2_open()
3417 if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) { in smb2_open()
3423 if (S_ISDIR(file_inode(filp)->i_mode)) { in smb2_open()
3424 lc->req_state &= ~SMB2_LEASE_WRITE_CACHING_LE; in smb2_open()
3425 lc->is_dir = true; in smb2_open()
3435 req_op_level = smb2_map_lease_to_oplock(lc->req_state); in smb2_open()
3438 name, req_op_level, lc->req_state); in smb2_open()
3439 rc = find_same_lease_key(sess, fp->f_ci, lc); in smb2_open()
3448 fp->persistent_id, fp, in smb2_open()
3449 le32_to_cpu(req->hdr.Id.SyncId.TreeId), in smb2_open()
3455 if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) in smb2_open()
3459 rc = smb2_create_truncate(&fp->filp->f_path); in smb2_open()
3464 if (req->CreateContextsOffset) { in smb2_open()
3476 if (le16_to_cpu(az_req->ccontext.DataOffset) + in smb2_open()
3477 le32_to_cpu(az_req->ccontext.DataLength) < in smb2_open()
3479 rc = -EINVAL; in smb2_open()
3482 alloc_size = le64_to_cpu(az_req->AllocationSize); in smb2_open()
3487 err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0, in smb2_open()
3510 fp->create_time = ksmbd_UnixTimeToNT(stat.btime); in smb2_open()
3512 fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); in smb2_open()
3513 if (req->FileAttributes || fp->f_ci->m_fattr == 0) in smb2_open()
3514 fp->f_ci->m_fattr = in smb2_open()
3515 cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); in smb2_open()
3518 smb2_update_xattrs(tcon, &path, fp); in smb2_open()
3520 smb2_new_xattrs(tcon, &path, fp); in smb2_open()
3522 memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); in smb2_open()
3526 test_share_config_flag(work->tcon->share_conf, in smb2_open()
3528 fp->is_persistent = true; in smb2_open()
3530 fp->is_durable = true; in smb2_open()
3533 memcpy(fp->create_guid, dh_info.CreateGuid, in smb2_open()
3536 fp->durable_timeout = in smb2_open()
3540 fp->durable_timeout = 60; in smb2_open()
3545 rsp->StructureSize = cpu_to_le16(89); in smb2_open()
3547 opinfo = rcu_dereference(fp->f_opinfo); in smb2_open()
3548 rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0; in smb2_open()
3550 rsp->Flags = 0; in smb2_open()
3551 rsp->CreateAction = cpu_to_le32(file_info); in smb2_open()
3552 rsp->CreationTime = cpu_to_le64(fp->create_time); in smb2_open()
3554 rsp->LastAccessTime = cpu_to_le64(time); in smb2_open()
3556 rsp->LastWriteTime = cpu_to_le64(time); in smb2_open()
3558 rsp->ChangeTime = cpu_to_le64(time); in smb2_open()
3559 rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 : in smb2_open()
3561 rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in smb2_open()
3562 rsp->FileAttributes = fp->f_ci->m_fattr; in smb2_open()
3564 rsp->Reserved2 = 0; in smb2_open()
3566 rsp->PersistentFileId = fp->persistent_id; in smb2_open()
3567 rsp->VolatileFileId = fp->volatile_id; in smb2_open()
3569 rsp->CreateContextsOffset = 0; in smb2_open()
3570 rsp->CreateContextsLength = 0; in smb2_open()
3574 if (opinfo && opinfo->is_lease) { in smb2_open()
3578 name, opinfo->o_lease->state); in smb2_open()
3579 rsp->OplockLevel = SMB2_OPLOCK_LEVEL_LEASE; in smb2_open()
3581 lease_ccontext = (struct create_context *)rsp->Buffer; in smb2_open()
3583 create_lease_buf(rsp->Buffer, opinfo->o_lease); in smb2_open()
3584 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3585 conn->vals->create_lease_size); in smb2_open()
3586 iov_len += conn->vals->create_lease_size; in smb2_open()
3587 next_ptr = &lease_ccontext->Next; in smb2_open()
3588 next_off = conn->vals->create_lease_size; in smb2_open()
3598 mxac_ccontext = (struct create_context *)(rsp->Buffer + in smb2_open()
3599 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3601 create_mxac_rsp_buf(rsp->Buffer + in smb2_open()
3602 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3604 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3605 conn->vals->create_mxac_size); in smb2_open()
3606 iov_len += conn->vals->create_mxac_size; in smb2_open()
3609 next_ptr = &mxac_ccontext->Next; in smb2_open()
3610 next_off = conn->vals->create_mxac_size; in smb2_open()
3616 disk_id_ccontext = (struct create_context *)(rsp->Buffer + in smb2_open()
3617 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3619 create_disk_id_rsp_buf(rsp->Buffer + in smb2_open()
3620 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3621 stat.ino, tcon->id); in smb2_open()
3622 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3623 conn->vals->create_disk_id_size); in smb2_open()
3624 iov_len += conn->vals->create_disk_id_size; in smb2_open()
3627 next_ptr = &disk_id_ccontext->Next; in smb2_open()
3628 next_off = conn->vals->create_disk_id_size; in smb2_open()
3634 durable_ccontext = (struct create_context *)(rsp->Buffer + in smb2_open()
3635 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3638 create_durable_rsp_buf(rsp->Buffer + in smb2_open()
3639 le32_to_cpu(rsp->CreateContextsLength)); in smb2_open()
3640 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3641 conn->vals->create_durable_size); in smb2_open()
3642 iov_len += conn->vals->create_durable_size; in smb2_open()
3644 create_durable_v2_rsp_buf(rsp->Buffer + in smb2_open()
3645 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3647 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3648 conn->vals->create_durable_v2_size); in smb2_open()
3649 iov_len += conn->vals->create_durable_v2_size; in smb2_open()
3654 next_ptr = &durable_ccontext->Next; in smb2_open()
3655 next_off = conn->vals->create_durable_size; in smb2_open()
3660 create_posix_rsp_buf(rsp->Buffer + in smb2_open()
3661 le32_to_cpu(rsp->CreateContextsLength), in smb2_open()
3663 le32_add_cpu(&rsp->CreateContextsLength, in smb2_open()
3664 conn->vals->create_posix_size); in smb2_open()
3665 iov_len += conn->vals->create_posix_size; in smb2_open()
3671 rsp->CreateContextsOffset = in smb2_open()
3684 ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED); in smb2_open()
3688 if (rc == -EINVAL) in smb2_open()
3689 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_open()
3690 else if (rc == -EOPNOTSUPP) in smb2_open()
3691 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_open()
3692 else if (rc == -EACCES || rc == -ESTALE || rc == -EXDEV) in smb2_open()
3693 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_open()
3694 else if (rc == -ENOENT) in smb2_open()
3695 rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID; in smb2_open()
3696 else if (rc == -EPERM) in smb2_open()
3697 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_open()
3698 else if (rc == -EBUSY) in smb2_open()
3699 rsp->hdr.Status = STATUS_DELETE_PENDING; in smb2_open()
3700 else if (rc == -EBADF) in smb2_open()
3701 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND; in smb2_open()
3702 else if (rc == -ENOEXEC) in smb2_open()
3703 rsp->hdr.Status = STATUS_DUPLICATE_OBJECTID; in smb2_open()
3704 else if (rc == -ENXIO) in smb2_open()
3705 rsp->hdr.Status = STATUS_NO_SUCH_DEVICE; in smb2_open()
3706 else if (rc == -EEXIST) in smb2_open()
3707 rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION; in smb2_open()
3708 else if (rc == -EMFILE) in smb2_open()
3709 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_open()
3710 if (!rsp->hdr.Status) in smb2_open()
3711 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_open()
3716 ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status); in smb2_open()
3743 return -EOPNOTSUPP; in readdir_info_level_struct_sz()
3754 ffdinfo = (struct file_full_directory_info *)d_info->rptr; in dentry_name()
3755 d_info->rptr += le32_to_cpu(ffdinfo->NextEntryOffset); in dentry_name()
3756 d_info->name = ffdinfo->FileName; in dentry_name()
3757 d_info->name_len = le32_to_cpu(ffdinfo->FileNameLength); in dentry_name()
3764 fbdinfo = (struct file_both_directory_info *)d_info->rptr; in dentry_name()
3765 d_info->rptr += le32_to_cpu(fbdinfo->NextEntryOffset); in dentry_name()
3766 d_info->name = fbdinfo->FileName; in dentry_name()
3767 d_info->name_len = le32_to_cpu(fbdinfo->FileNameLength); in dentry_name()
3774 fdinfo = (struct file_directory_info *)d_info->rptr; in dentry_name()
3775 d_info->rptr += le32_to_cpu(fdinfo->NextEntryOffset); in dentry_name()
3776 d_info->name = fdinfo->FileName; in dentry_name()
3777 d_info->name_len = le32_to_cpu(fdinfo->FileNameLength); in dentry_name()
3784 fninfo = (struct file_names_info *)d_info->rptr; in dentry_name()
3785 d_info->rptr += le32_to_cpu(fninfo->NextEntryOffset); in dentry_name()
3786 d_info->name = fninfo->FileName; in dentry_name()
3787 d_info->name_len = le32_to_cpu(fninfo->FileNameLength); in dentry_name()
3794 dinfo = (struct file_id_full_dir_info *)d_info->rptr; in dentry_name()
3795 d_info->rptr += le32_to_cpu(dinfo->NextEntryOffset); in dentry_name()
3796 d_info->name = dinfo->FileName; in dentry_name()
3797 d_info->name_len = le32_to_cpu(dinfo->FileNameLength); in dentry_name()
3804 fibdinfo = (struct file_id_both_directory_info *)d_info->rptr; in dentry_name()
3805 d_info->rptr += le32_to_cpu(fibdinfo->NextEntryOffset); in dentry_name()
3806 d_info->name = fibdinfo->FileName; in dentry_name()
3807 d_info->name_len = le32_to_cpu(fibdinfo->FileNameLength); in dentry_name()
3814 posix_info = (struct smb2_posix_info *)d_info->rptr; in dentry_name()
3815 d_info->rptr += le32_to_cpu(posix_info->NextEntryOffset); in dentry_name()
3816 d_info->name = posix_info->name; in dentry_name()
3817 d_info->name_len = le32_to_cpu(posix_info->name_len); in dentry_name()
3821 return -EINVAL; in dentry_name()
3826 * smb2_populate_readdir_entry() - encode directory entry in smb2 response
3849 conn->local_nls, in smb2_populate_readdir_entry()
3852 return -ENOMEM; in smb2_populate_readdir_entry()
3856 rc = -EINVAL; in smb2_populate_readdir_entry()
3862 d_info->last_entry_off_align = next_entry_offset - struct_sz; in smb2_populate_readdir_entry()
3864 if (next_entry_offset > d_info->out_buf_len) { in smb2_populate_readdir_entry()
3865 d_info->out_buf_len = 0; in smb2_populate_readdir_entry()
3866 rc = -ENOSPC; in smb2_populate_readdir_entry()
3870 kstat = d_info->wptr; in smb2_populate_readdir_entry()
3872 kstat = ksmbd_vfs_init_kstat(&d_info->wptr, ksmbd_kstat); in smb2_populate_readdir_entry()
3880 ffdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3881 ffdinfo->EaSize = in smb2_populate_readdir_entry()
3882 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3883 if (ffdinfo->EaSize) in smb2_populate_readdir_entry()
3884 ffdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3885 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3886 ffdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3887 memcpy(ffdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3888 ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3896 fbdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3897 fbdinfo->EaSize = in smb2_populate_readdir_entry()
3898 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3899 if (fbdinfo->EaSize) in smb2_populate_readdir_entry()
3900 fbdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3901 fbdinfo->ShortNameLength = 0; in smb2_populate_readdir_entry()
3902 fbdinfo->Reserved = 0; in smb2_populate_readdir_entry()
3903 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3904 fbdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3905 memcpy(fbdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3906 fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3914 fdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3915 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3916 fdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3917 memcpy(fdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3918 fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3926 fninfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3927 memcpy(fninfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3928 fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3936 dinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3937 dinfo->EaSize = in smb2_populate_readdir_entry()
3938 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3939 if (dinfo->EaSize) in smb2_populate_readdir_entry()
3940 dinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3941 dinfo->Reserved = 0; in smb2_populate_readdir_entry()
3942 dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino); in smb2_populate_readdir_entry()
3943 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3944 dinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3945 memcpy(dinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3946 dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3954 fibdinfo->FileNameLength = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
3955 fibdinfo->EaSize = in smb2_populate_readdir_entry()
3956 smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); in smb2_populate_readdir_entry()
3957 if (fibdinfo->EaSize) in smb2_populate_readdir_entry()
3958 fibdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE; in smb2_populate_readdir_entry()
3959 fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino); in smb2_populate_readdir_entry()
3960 fibdinfo->ShortNameLength = 0; in smb2_populate_readdir_entry()
3961 fibdinfo->Reserved = 0; in smb2_populate_readdir_entry()
3962 fibdinfo->Reserved2 = cpu_to_le16(0); in smb2_populate_readdir_entry()
3963 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3964 fibdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3965 memcpy(fibdinfo->FileName, conv_name, conv_len); in smb2_populate_readdir_entry()
3966 fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
3975 posix_info->Ignored = 0; in smb2_populate_readdir_entry()
3976 posix_info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time); in smb2_populate_readdir_entry()
3977 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime); in smb2_populate_readdir_entry()
3978 posix_info->ChangeTime = cpu_to_le64(time); in smb2_populate_readdir_entry()
3979 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->atime); in smb2_populate_readdir_entry()
3980 posix_info->LastAccessTime = cpu_to_le64(time); in smb2_populate_readdir_entry()
3981 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->mtime); in smb2_populate_readdir_entry()
3982 posix_info->LastWriteTime = cpu_to_le64(time); in smb2_populate_readdir_entry()
3983 posix_info->EndOfFile = cpu_to_le64(ksmbd_kstat->kstat->size); in smb2_populate_readdir_entry()
3984 posix_info->AllocationSize = cpu_to_le64(ksmbd_kstat->kstat->blocks << 9); in smb2_populate_readdir_entry()
3985 posix_info->DeviceId = cpu_to_le32(ksmbd_kstat->kstat->rdev); in smb2_populate_readdir_entry()
3986 posix_info->HardLinks = cpu_to_le32(ksmbd_kstat->kstat->nlink); in smb2_populate_readdir_entry()
3987 posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode & 0777); in smb2_populate_readdir_entry()
3988 posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino); in smb2_populate_readdir_entry()
3989 posix_info->DosAttributes = in smb2_populate_readdir_entry()
3990 S_ISDIR(ksmbd_kstat->kstat->mode) ? in smb2_populate_readdir_entry()
3992 if (d_info->hide_dot_file && d_info->name[0] == '.') in smb2_populate_readdir_entry()
3993 posix_info->DosAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; in smb2_populate_readdir_entry()
3999 id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid), in smb2_populate_readdir_entry()
4000 SIDUNIX_USER, (struct smb_sid *)&posix_info->SidBuffer[0]); in smb2_populate_readdir_entry()
4001 id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid), in smb2_populate_readdir_entry()
4002 SIDUNIX_GROUP, (struct smb_sid *)&posix_info->SidBuffer[16]); in smb2_populate_readdir_entry()
4003 memcpy(posix_info->name, conv_name, conv_len); in smb2_populate_readdir_entry()
4004 posix_info->name_len = cpu_to_le32(conv_len); in smb2_populate_readdir_entry()
4005 posix_info->NextEntryOffset = cpu_to_le32(next_entry_offset); in smb2_populate_readdir_entry()
4011 d_info->last_entry_offset = d_info->data_count; in smb2_populate_readdir_entry()
4012 d_info->data_count += next_entry_offset; in smb2_populate_readdir_entry()
4013 d_info->out_buf_len -= next_entry_offset; in smb2_populate_readdir_entry()
4014 d_info->wptr += next_entry_offset; in smb2_populate_readdir_entry()
4018 info_level, d_info->out_buf_len, in smb2_populate_readdir_entry()
4019 next_entry_offset, d_info->data_count); in smb2_populate_readdir_entry()
4037 struct dentry *dir = dir_fp->filp->f_path.dentry; in lock_dir()
4044 struct dentry *dir = dir_fp->filp->f_path.dentry; in unlock_dir()
4051 struct mnt_idmap *idmap = file_mnt_idmap(priv->dir_fp->filp); in process_query_dir_entries()
4057 for (i = 0; i < priv->d_info->num_entry; i++) { in process_query_dir_entries()
4060 if (dentry_name(priv->d_info, priv->info_level)) in process_query_dir_entries()
4061 return -EINVAL; in process_query_dir_entries()
4063 lock_dir(priv->dir_fp); in process_query_dir_entries()
4064 dent = lookup_one(idmap, priv->d_info->name, in process_query_dir_entries()
4065 priv->dir_fp->filp->f_path.dentry, in process_query_dir_entries()
4066 priv->d_info->name_len); in process_query_dir_entries()
4067 unlock_dir(priv->dir_fp); in process_query_dir_entries()
4071 priv->d_info->name, in process_query_dir_entries()
4078 priv->d_info->name); in process_query_dir_entries()
4083 if (priv->info_level != FILE_NAMES_INFORMATION) { in process_query_dir_entries()
4084 rc = ksmbd_vfs_fill_dentry_attrs(priv->work, in process_query_dir_entries()
4094 rc = smb2_populate_readdir_entry(priv->work->conn, in process_query_dir_entries()
4095 priv->info_level, in process_query_dir_entries()
4096 priv->d_info, in process_query_dir_entries()
4113 if (struct_sz == -EOPNOTSUPP) in reserve_populate_dentry()
4114 return -EOPNOTSUPP; in reserve_populate_dentry()
4116 conv_len = (d_info->name_len + 1) * 2; in reserve_populate_dentry()
4120 if (next_entry_offset > d_info->out_buf_len) { in reserve_populate_dentry()
4121 d_info->out_buf_len = 0; in reserve_populate_dentry()
4122 return -ENOSPC; in reserve_populate_dentry()
4130 ffdinfo = (struct file_full_directory_info *)d_info->wptr; in reserve_populate_dentry()
4131 memcpy(ffdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4132 ffdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4133 ffdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4134 ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4141 fbdinfo = (struct file_both_directory_info *)d_info->wptr; in reserve_populate_dentry()
4142 memcpy(fbdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4143 fbdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4144 fbdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4145 fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4152 fdinfo = (struct file_directory_info *)d_info->wptr; in reserve_populate_dentry()
4153 memcpy(fdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4154 fdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4155 fdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4156 fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4163 fninfo = (struct file_names_info *)d_info->wptr; in reserve_populate_dentry()
4164 memcpy(fninfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4165 fninfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4166 fninfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4167 fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4174 dinfo = (struct file_id_full_dir_info *)d_info->wptr; in reserve_populate_dentry()
4175 memcpy(dinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4176 dinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4177 dinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4178 dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4185 fibdinfo = (struct file_id_both_directory_info *)d_info->wptr; in reserve_populate_dentry()
4186 memcpy(fibdinfo->FileName, d_info->name, d_info->name_len); in reserve_populate_dentry()
4187 fibdinfo->FileName[d_info->name_len] = 0x00; in reserve_populate_dentry()
4188 fibdinfo->FileNameLength = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4189 fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset); in reserve_populate_dentry()
4196 posix_info = (struct smb2_posix_info *)d_info->wptr; in reserve_populate_dentry()
4197 memcpy(posix_info->name, d_info->name, d_info->name_len); in reserve_populate_dentry()
4198 posix_info->name[d_info->name_len] = 0x00; in reserve_populate_dentry()
4199 posix_info->name_len = cpu_to_le32(d_info->name_len); in reserve_populate_dentry()
4200 posix_info->NextEntryOffset = in reserve_populate_dentry()
4206 d_info->num_entry++; in reserve_populate_dentry()
4207 d_info->out_buf_len -= next_entry_offset; in reserve_populate_dentry()
4208 d_info->wptr += next_entry_offset; in reserve_populate_dentry()
4221 priv = buf->private; in __query_dir()
4222 d_info = priv->d_info; in __query_dir()
4227 if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name)) in __query_dir()
4229 if (!match_pattern(name, namlen, priv->search_pattern)) in __query_dir()
4232 d_info->name = name; in __query_dir()
4233 d_info->name_len = namlen; in __query_dir()
4234 rc = reserve_populate_dentry(d_info, priv->info_level); in __query_dir()
4237 if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) in __query_dir()
4238 d_info->out_buf_len = 0; in __query_dir()
4254 return -EOPNOTSUPP; in verify_info_level()
4264 free_len = (int)(work->response_sz - in smb2_resp_buf_len()
4265 (get_rfc1002_len(work->response_buf) + 4)) - hdr2_len; in smb2_resp_buf_len()
4275 if (out_buf_len > work->conn->vals->max_trans_size) in smb2_calc_max_out_buf_len()
4276 return -EINVAL; in smb2_calc_max_out_buf_len()
4280 return -EINVAL; in smb2_calc_max_out_buf_len()
4287 struct ksmbd_conn *conn = work->conn; in smb2_query_dir()
4290 struct ksmbd_share_config *share = work->tcon->share_conf; in smb2_query_dir()
4302 rsp->hdr.Status = STATUS_NO_MEMORY; in smb2_query_dir()
4304 return -ENOMEM; in smb2_query_dir()
4307 rc = verify_info_level(req->FileInformationClass); in smb2_query_dir()
4309 rc = -EFAULT; in smb2_query_dir()
4313 dir_fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in smb2_query_dir()
4315 rc = -EBADF; in smb2_query_dir()
4319 if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) || in smb2_query_dir()
4320 inode_permission(file_mnt_idmap(dir_fp->filp), in smb2_query_dir()
4321 file_inode(dir_fp->filp), in smb2_query_dir()
4323 pr_err("no right to enumerate directory (%pD)\n", dir_fp->filp); in smb2_query_dir()
4324 rc = -EACCES; in smb2_query_dir()
4328 if (!S_ISDIR(file_inode(dir_fp->filp)->i_mode)) { in smb2_query_dir()
4330 rc = -EINVAL; in smb2_query_dir()
4334 srch_flag = req->Flags; in smb2_query_dir()
4335 srch_ptr = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->FileNameOffset), in smb2_query_dir()
4336 le16_to_cpu(req->FileNameLength), 1, in smb2_query_dir()
4337 conn->local_nls); in smb2_query_dir()
4340 rc = -EINVAL; in smb2_query_dir()
4348 generic_file_llseek(dir_fp->filp, 0, SEEK_SET); in smb2_query_dir()
4352 d_info.wptr = (char *)rsp->Buffer; in smb2_query_dir()
4353 d_info.rptr = (char *)rsp->Buffer; in smb2_query_dir()
4356 le32_to_cpu(req->OutputBufferLength)); in smb2_query_dir()
4358 rc = -EINVAL; in smb2_query_dir()
4367 rc = ksmbd_populate_dot_dotdot_entries(work, req->FileInformationClass, in smb2_query_dir()
4370 if (rc == -ENOSPC) in smb2_query_dir()
4384 query_dir_private.info_level = req->FileInformationClass; in smb2_query_dir()
4385 dir_fp->readdir_data.private = &query_dir_private; in smb2_query_dir()
4386 set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir); in smb2_query_dir()
4388 rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx); in smb2_query_dir()
4390 * req->OutputBufferLength is too small to contain even one entry. in smb2_query_dir()
4395 if (rc > 0 || rc == -ENOSPC) in smb2_query_dir()
4408 rsp->hdr.Status = STATUS_NO_SUCH_FILE; in smb2_query_dir()
4410 dir_fp->dot_dotdot[0] = dir_fp->dot_dotdot[1] = 0; in smb2_query_dir()
4411 rsp->hdr.Status = STATUS_NO_MORE_FILES; in smb2_query_dir()
4413 rsp->StructureSize = cpu_to_le16(9); in smb2_query_dir()
4414 rsp->OutputBufferOffset = cpu_to_le16(0); in smb2_query_dir()
4415 rsp->OutputBufferLength = cpu_to_le32(0); in smb2_query_dir()
4416 rsp->Buffer[0] = 0; in smb2_query_dir()
4425 ((char *)rsp->Buffer + d_info.last_entry_offset)) in smb2_query_dir()
4426 ->NextEntryOffset = 0; in smb2_query_dir()
4428 d_info.data_count -= d_info.last_entry_off_align; in smb2_query_dir()
4430 rsp->StructureSize = cpu_to_le16(9); in smb2_query_dir()
4431 rsp->OutputBufferOffset = cpu_to_le16(72); in smb2_query_dir()
4432 rsp->OutputBufferLength = cpu_to_le32(d_info.data_count); in smb2_query_dir()
4450 if (rc == -EINVAL) in smb2_query_dir()
4451 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_query_dir()
4452 else if (rc == -EACCES) in smb2_query_dir()
4453 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_query_dir()
4454 else if (rc == -ENOENT) in smb2_query_dir()
4455 rsp->hdr.Status = STATUS_NO_SUCH_FILE; in smb2_query_dir()
4456 else if (rc == -EBADF) in smb2_query_dir()
4457 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_query_dir()
4458 else if (rc == -ENOMEM) in smb2_query_dir()
4459 rsp->hdr.Status = STATUS_NO_MEMORY; in smb2_query_dir()
4460 else if (rc == -EFAULT) in smb2_query_dir()
4461 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS; in smb2_query_dir()
4462 else if (rc == -EIO) in smb2_query_dir()
4463 rsp->hdr.Status = STATUS_FILE_CORRUPT_ERROR; in smb2_query_dir()
4464 if (!rsp->hdr.Status) in smb2_query_dir()
4465 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_query_dir()
4474 * buffer_check_err() - helper function to check buffer errors
4485 if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) { in buffer_check_err()
4487 rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH; in buffer_check_err()
4489 return -EINVAL; in buffer_check_err()
4499 sinfo = (struct smb2_file_standard_info *)rsp->Buffer; in get_standard_info_pipe()
4501 sinfo->AllocationSize = cpu_to_le64(4096); in get_standard_info_pipe()
4502 sinfo->EndOfFile = cpu_to_le64(0); in get_standard_info_pipe()
4503 sinfo->NumberOfLinks = cpu_to_le32(1); in get_standard_info_pipe()
4504 sinfo->DeletePending = 1; in get_standard_info_pipe()
4505 sinfo->Directory = 0; in get_standard_info_pipe()
4506 rsp->OutputBufferLength = in get_standard_info_pipe()
4515 file_info = (struct smb2_file_internal_info *)rsp->Buffer; in get_internal_info_pipe()
4518 file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63)); in get_internal_info_pipe()
4519 rsp->OutputBufferLength = in get_internal_info_pipe()
4535 id = req->VolatileFileId; in smb2_get_info_file_pipe()
4537 return -ENOENT; in smb2_get_info_file_pipe()
4540 req->FileInfoClass, req->VolatileFileId); in smb2_get_info_file_pipe()
4542 switch (req->FileInfoClass) { in smb2_get_info_file_pipe()
4545 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_file_pipe()
4550 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_file_pipe()
4555 req->FileInfoClass); in smb2_get_info_file_pipe()
4556 rc = -EOPNOTSUPP; in smb2_get_info_file_pipe()
4562 * smb2_get_ea() - handler for smb2 get extended attribute command
4581 struct mnt_idmap *idmap = file_mnt_idmap(fp->filp); in smb2_get_ea()
4583 if (!(fp->daccess & FILE_READ_EA_LE)) { in smb2_get_ea()
4585 fp->daccess); in smb2_get_ea()
4586 return -EACCES; in smb2_get_ea()
4589 path = &fp->filp->f_path; in smb2_get_ea()
4591 if (req->InputBufferLength) { in smb2_get_ea()
4592 if (le32_to_cpu(req->InputBufferLength) <= in smb2_get_ea()
4594 return -EINVAL; in smb2_get_ea()
4597 le16_to_cpu(req->InputBufferOffset)); in smb2_get_ea()
4600 if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY) in smb2_get_ea()
4603 le32_to_cpu(req->Flags)); in smb2_get_ea()
4608 le32_to_cpu(req->OutputBufferLength)); in smb2_get_ea()
4610 return -EINVAL; in smb2_get_ea()
4612 rc = ksmbd_vfs_listxattr(path->dentry, &xattr_list); in smb2_get_ea()
4614 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_get_ea()
4622 ptr = (char *)rsp->Buffer; in smb2_get_ea()
4646 if (req->InputBufferLength && in smb2_get_ea()
4647 strncmp(&name[XATTR_USER_PREFIX_LEN], ea_req->name, in smb2_get_ea()
4648 ea_req->EaNameLength)) in smb2_get_ea()
4656 name_len -= XATTR_USER_PREFIX_LEN; in smb2_get_ea()
4658 ptr = eainfo->name + name_len + 1; in smb2_get_ea()
4659 buf_free_len -= (offsetof(struct smb2_ea_info, name) + in smb2_get_ea()
4662 value_len = ksmbd_vfs_getxattr(idmap, path->dentry, in smb2_get_ea()
4665 rc = -ENOENT; in smb2_get_ea()
4666 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_get_ea()
4670 buf_free_len -= value_len; in smb2_get_ea()
4680 eainfo->Flags = 0; in smb2_get_ea()
4681 eainfo->EaNameLength = name_len; in smb2_get_ea()
4684 memcpy(eainfo->name, &name[XATTR_USER_PREFIX_LEN], in smb2_get_ea()
4687 memcpy(eainfo->name, name, name_len); in smb2_get_ea()
4689 eainfo->name[name_len] = '\0'; in smb2_get_ea()
4690 eainfo->EaValueLength = cpu_to_le16(value_len); in smb2_get_ea()
4695 alignment_bytes = ((next_offset + 3) & ~3) - next_offset; in smb2_get_ea()
4700 buf_free_len -= alignment_bytes; in smb2_get_ea()
4702 eainfo->NextEntryOffset = cpu_to_le32(next_offset); in smb2_get_ea()
4707 if (req->InputBufferLength) { in smb2_get_ea()
4714 prev_eainfo->NextEntryOffset = 0; in smb2_get_ea()
4718 rsp->hdr.Status = STATUS_NO_EAS_ON_FILE; in smb2_get_ea()
4719 rsp->OutputBufferLength = cpu_to_le32(rsp_data_cnt); in smb2_get_ea()
4730 file_info = (struct smb2_file_access_info *)rsp->Buffer; in get_file_access_info()
4731 file_info->AccessFlags = fp->daccess; in get_file_access_info()
4732 rsp->OutputBufferLength = in get_file_access_info()
4744 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_basic_info()
4746 fp->daccess); in get_file_basic_info()
4747 return -EACCES; in get_file_basic_info()
4750 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_basic_info()
4755 basic_info = (struct smb2_file_basic_info *)rsp->Buffer; in get_file_basic_info()
4756 basic_info->CreationTime = cpu_to_le64(fp->create_time); in get_file_basic_info()
4758 basic_info->LastAccessTime = cpu_to_le64(time); in get_file_basic_info()
4760 basic_info->LastWriteTime = cpu_to_le64(time); in get_file_basic_info()
4762 basic_info->ChangeTime = cpu_to_le64(time); in get_file_basic_info()
4763 basic_info->Attributes = fp->f_ci->m_fattr; in get_file_basic_info()
4764 basic_info->Pad1 = 0; in get_file_basic_info()
4765 rsp->OutputBufferLength = in get_file_basic_info()
4778 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_standard_info()
4783 sinfo = (struct smb2_file_standard_info *)rsp->Buffer; in get_file_standard_info()
4786 sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9); in get_file_standard_info()
4787 sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in get_file_standard_info()
4788 sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending); in get_file_standard_info()
4789 sinfo->DeletePending = delete_pending; in get_file_standard_info()
4790 sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0; in get_file_standard_info()
4791 rsp->OutputBufferLength = in get_file_standard_info()
4802 file_info = (struct smb2_file_alignment_info *)rsp->Buffer; in get_file_alignment_info()
4803 file_info->AlignmentRequirement = 0; in get_file_alignment_info()
4804 rsp->OutputBufferLength = in get_file_alignment_info()
4813 struct ksmbd_conn *conn = work->conn; in get_file_all_info()
4822 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_all_info()
4824 fp->daccess); in get_file_all_info()
4825 return -EACCES; in get_file_all_info()
4828 filename = convert_to_nt_pathname(work->tcon->share_conf, &fp->filp->f_path); in get_file_all_info()
4832 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_all_info()
4839 file_info = (struct smb2_file_all_info *)rsp->Buffer; in get_file_all_info()
4841 file_info->CreationTime = cpu_to_le64(fp->create_time); in get_file_all_info()
4843 file_info->LastAccessTime = cpu_to_le64(time); in get_file_all_info()
4845 file_info->LastWriteTime = cpu_to_le64(time); in get_file_all_info()
4847 file_info->ChangeTime = cpu_to_le64(time); in get_file_all_info()
4848 file_info->Attributes = fp->f_ci->m_fattr; in get_file_all_info()
4849 file_info->Pad1 = 0; in get_file_all_info()
4850 file_info->AllocationSize = in get_file_all_info()
4852 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in get_file_all_info()
4853 file_info->NumberOfLinks = in get_file_all_info()
4854 cpu_to_le32(get_nlink(&stat) - delete_pending); in get_file_all_info()
4855 file_info->DeletePending = delete_pending; in get_file_all_info()
4856 file_info->Directory = S_ISDIR(stat.mode) ? 1 : 0; in get_file_all_info()
4857 file_info->Pad2 = 0; in get_file_all_info()
4858 file_info->IndexNumber = cpu_to_le64(stat.ino); in get_file_all_info()
4859 file_info->EASize = 0; in get_file_all_info()
4860 file_info->AccessFlags = fp->daccess; in get_file_all_info()
4861 file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); in get_file_all_info()
4862 file_info->Mode = fp->coption; in get_file_all_info()
4863 file_info->AlignmentRequirement = 0; in get_file_all_info()
4864 conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename, in get_file_all_info()
4865 PATH_MAX, conn->local_nls, 0); in get_file_all_info()
4867 file_info->FileNameLength = cpu_to_le32(conv_len); in get_file_all_info()
4868 rsp->OutputBufferLength = in get_file_all_info()
4869 cpu_to_le32(sizeof(struct smb2_file_all_info) + conv_len - 1); in get_file_all_info()
4879 struct ksmbd_conn *conn = work->conn; in get_file_alternate_info()
4881 struct dentry *dentry = fp->filp->f_path.dentry; in get_file_alternate_info()
4884 spin_lock(&dentry->d_lock); in get_file_alternate_info()
4885 file_info = (struct smb2_file_alt_name_info *)rsp->Buffer; in get_file_alternate_info()
4887 dentry->d_name.name, in get_file_alternate_info()
4888 file_info->FileName); in get_file_alternate_info()
4889 spin_unlock(&dentry->d_lock); in get_file_alternate_info()
4890 file_info->FileNameLength = cpu_to_le32(conv_len); in get_file_alternate_info()
4891 rsp->OutputBufferLength = in get_file_alternate_info()
4900 struct ksmbd_conn *conn = work->conn; in get_file_stream_info()
4904 const struct path *path = &fp->filp->f_path; in get_file_stream_info()
4911 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_stream_info()
4916 file_info = (struct smb2_file_stream_info *)rsp->Buffer; in get_file_stream_info()
4920 le32_to_cpu(req->OutputBufferLength)); in get_file_stream_info()
4924 xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list); in get_file_stream_info()
4943 stream_name_len = streamlen - (XATTR_USER_PREFIX_LEN + in get_file_stream_info()
4962 file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes]; in get_file_stream_info()
4963 streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName, in get_file_stream_info()
4965 conn->local_nls, 0); in get_file_stream_info()
4968 file_info->StreamNameLength = cpu_to_le32(streamlen); in get_file_stream_info()
4969 file_info->StreamSize = cpu_to_le64(stream_name_len); in get_file_stream_info()
4970 file_info->StreamAllocationSize = cpu_to_le64(stream_name_len); in get_file_stream_info()
4973 buf_free_len -= next; in get_file_stream_info()
4974 file_info->NextEntryOffset = cpu_to_le32(next); in get_file_stream_info()
4981 &rsp->Buffer[nbytes]; in get_file_stream_info()
4982 streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName, in get_file_stream_info()
4983 "::$DATA", 7, conn->local_nls, 0); in get_file_stream_info()
4985 file_info->StreamNameLength = cpu_to_le32(streamlen); in get_file_stream_info()
4986 file_info->StreamSize = cpu_to_le64(stat.size); in get_file_stream_info()
4987 file_info->StreamAllocationSize = cpu_to_le64(stat.blocks << 9); in get_file_stream_info()
4992 file_info->NextEntryOffset = 0; in get_file_stream_info()
4995 rsp->OutputBufferLength = cpu_to_le32(nbytes); in get_file_stream_info()
5007 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_internal_info()
5012 file_info = (struct smb2_file_internal_info *)rsp->Buffer; in get_file_internal_info()
5013 file_info->IndexNumber = cpu_to_le64(stat.ino); in get_file_internal_info()
5014 rsp->OutputBufferLength = in get_file_internal_info()
5028 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_network_open_info()
5030 fp->daccess); in get_file_network_open_info()
5031 return -EACCES; in get_file_network_open_info()
5034 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_network_open_info()
5039 file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer; in get_file_network_open_info()
5041 file_info->CreationTime = cpu_to_le64(fp->create_time); in get_file_network_open_info()
5043 file_info->LastAccessTime = cpu_to_le64(time); in get_file_network_open_info()
5045 file_info->LastWriteTime = cpu_to_le64(time); in get_file_network_open_info()
5047 file_info->ChangeTime = cpu_to_le64(time); in get_file_network_open_info()
5048 file_info->Attributes = fp->f_ci->m_fattr; in get_file_network_open_info()
5049 file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); in get_file_network_open_info()
5050 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); in get_file_network_open_info()
5051 file_info->Reserved = cpu_to_le32(0); in get_file_network_open_info()
5052 rsp->OutputBufferLength = in get_file_network_open_info()
5061 file_info = (struct smb2_file_ea_info *)rsp->Buffer; in get_file_ea_info()
5062 file_info->EASize = 0; in get_file_ea_info()
5063 rsp->OutputBufferLength = in get_file_ea_info()
5072 file_info = (struct smb2_file_pos_info *)rsp->Buffer; in get_file_position_info()
5073 file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); in get_file_position_info()
5074 rsp->OutputBufferLength = in get_file_position_info()
5083 file_info = (struct smb2_file_mode_info *)rsp->Buffer; in get_file_mode_info()
5084 file_info->Mode = fp->coption & FILE_MODE_INFO_MASK; in get_file_mode_info()
5085 rsp->OutputBufferLength = in get_file_mode_info()
5096 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in get_file_compression_info()
5101 file_info = (struct smb2_file_comp_info *)rsp->Buffer; in get_file_compression_info()
5102 file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9); in get_file_compression_info()
5103 file_info->CompressionFormat = COMPRESSION_FORMAT_NONE; in get_file_compression_info()
5104 file_info->CompressionUnitShift = 0; in get_file_compression_info()
5105 file_info->ChunkShift = 0; in get_file_compression_info()
5106 file_info->ClusterShift = 0; in get_file_compression_info()
5107 memset(&file_info->Reserved[0], 0, 3); in get_file_compression_info()
5109 rsp->OutputBufferLength = in get_file_compression_info()
5120 if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { in get_file_attribute_tag_info()
5122 fp->daccess); in get_file_attribute_tag_info()
5123 return -EACCES; in get_file_attribute_tag_info()
5126 file_info = (struct smb2_file_attr_tag_info *)rsp->Buffer; in get_file_attribute_tag_info()
5127 file_info->FileAttributes = fp->f_ci->m_fattr; in get_file_attribute_tag_info()
5128 file_info->ReparseTag = 0; in get_file_attribute_tag_info()
5129 rsp->OutputBufferLength = in get_file_attribute_tag_info()
5138 struct inode *inode = file_inode(fp->filp); in find_file_posix_info()
5139 struct mnt_idmap *idmap = file_mnt_idmap(fp->filp); in find_file_posix_info()
5147 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in find_file_posix_info()
5152 file_info = (struct smb311_posix_qinfo *)rsp->Buffer; in find_file_posix_info()
5153 file_info->CreationTime = cpu_to_le64(fp->create_time); in find_file_posix_info()
5155 file_info->LastAccessTime = cpu_to_le64(time); in find_file_posix_info()
5157 file_info->LastWriteTime = cpu_to_le64(time); in find_file_posix_info()
5159 file_info->ChangeTime = cpu_to_le64(time); in find_file_posix_info()
5160 file_info->DosAttributes = fp->f_ci->m_fattr; in find_file_posix_info()
5161 file_info->Inode = cpu_to_le64(stat.ino); in find_file_posix_info()
5162 file_info->EndOfFile = cpu_to_le64(stat.size); in find_file_posix_info()
5163 file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); in find_file_posix_info()
5164 file_info->HardLinks = cpu_to_le32(stat.nlink); in find_file_posix_info()
5165 file_info->Mode = cpu_to_le32(stat.mode & 0777); in find_file_posix_info()
5166 file_info->DeviceId = cpu_to_le32(stat.rdev); in find_file_posix_info()
5174 SIDUNIX_USER, (struct smb_sid *)&file_info->Sids[0]); in find_file_posix_info()
5176 SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]); in find_file_posix_info()
5178 rsp->OutputBufferLength = cpu_to_le32(out_buf_len); in find_file_posix_info()
5192 if (test_share_config_flag(work->tcon->share_conf, in smb2_get_info_file()
5195 return smb2_get_info_file_pipe(work->sess, req, rsp, in smb2_get_info_file()
5196 work->response_buf); in smb2_get_info_file()
5199 if (work->next_smb2_rcv_hdr_off) { in smb2_get_info_file()
5200 if (!has_file_id(req->VolatileFileId)) { in smb2_get_info_file()
5202 work->compound_fid); in smb2_get_info_file()
5203 id = work->compound_fid; in smb2_get_info_file()
5204 pid = work->compound_pfid; in smb2_get_info_file()
5209 id = req->VolatileFileId; in smb2_get_info_file()
5210 pid = req->PersistentFileId; in smb2_get_info_file()
5215 return -ENOENT; in smb2_get_info_file()
5217 fileinfoclass = req->FileInfoClass; in smb2_get_info_file()
5221 get_file_access_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5225 rc = get_file_basic_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5229 rc = get_file_standard_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5233 get_file_alignment_info(rsp, work->response_buf); in smb2_get_info_file()
5237 rc = get_file_all_info(work, rsp, fp, work->response_buf); in smb2_get_info_file()
5241 get_file_alternate_info(work, rsp, fp, work->response_buf); in smb2_get_info_file()
5245 rc = get_file_stream_info(work, rsp, fp, work->response_buf); in smb2_get_info_file()
5249 rc = get_file_internal_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5253 rc = get_file_network_open_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5257 get_file_ea_info(rsp, work->response_buf); in smb2_get_info_file()
5261 rc = smb2_get_ea(work, fp, req, rsp, work->response_buf); in smb2_get_info_file()
5265 get_file_position_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5269 get_file_mode_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5273 rc = get_file_compression_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5277 rc = get_file_attribute_tag_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5280 if (!work->tcon->posix_extensions) { in smb2_get_info_file()
5282 rc = -EOPNOTSUPP; in smb2_get_info_file()
5284 rc = find_file_posix_info(rsp, fp, work->response_buf); in smb2_get_info_file()
5290 rc = -EOPNOTSUPP; in smb2_get_info_file()
5293 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_file()
5294 rsp, work->response_buf); in smb2_get_info_file()
5303 struct ksmbd_session *sess = work->sess; in smb2_get_info_filesystem()
5304 struct ksmbd_conn *conn = work->conn; in smb2_get_info_filesystem()
5305 struct ksmbd_share_config *share = work->tcon->share_conf; in smb2_get_info_filesystem()
5311 if (!share->path) in smb2_get_info_filesystem()
5312 return -EIO; in smb2_get_info_filesystem()
5314 rc = kern_path(share->path, LOOKUP_NO_SYMLINKS, &path); in smb2_get_info_filesystem()
5317 return -EIO; in smb2_get_info_filesystem()
5322 pr_err("cannot do stat of path %s\n", share->path); in smb2_get_info_filesystem()
5324 return -EIO; in smb2_get_info_filesystem()
5327 fsinfoclass = req->FileInfoClass; in smb2_get_info_filesystem()
5334 info = (struct filesystem_device_info *)rsp->Buffer; in smb2_get_info_filesystem()
5336 info->DeviceType = cpu_to_le32(FILE_DEVICE_DISK); in smb2_get_info_filesystem()
5337 info->DeviceCharacteristics = in smb2_get_info_filesystem()
5339 if (!test_tree_conn_flag(work->tcon, in smb2_get_info_filesystem()
5341 info->DeviceCharacteristics |= in smb2_get_info_filesystem()
5343 rsp->OutputBufferLength = cpu_to_le32(8); in smb2_get_info_filesystem()
5351 info = (struct filesystem_attribute_info *)rsp->Buffer; in smb2_get_info_filesystem()
5352 info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS | in smb2_get_info_filesystem()
5359 info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps); in smb2_get_info_filesystem()
5361 if (test_share_config_flag(work->tcon->share_conf, in smb2_get_info_filesystem()
5363 info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS); in smb2_get_info_filesystem()
5365 info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen); in smb2_get_info_filesystem()
5366 len = smbConvertToUTF16((__le16 *)info->FileSystemName, in smb2_get_info_filesystem()
5367 "NTFS", PATH_MAX, conn->local_nls, 0); in smb2_get_info_filesystem()
5369 info->FileSystemNameLen = cpu_to_le32(len); in smb2_get_info_filesystem()
5371 rsp->OutputBufferLength = cpu_to_le32(sz); in smb2_get_info_filesystem()
5380 info = (struct filesystem_vol_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5381 info->VolumeCreationTime = 0; in smb2_get_info_filesystem()
5382 serial_crc = crc32_le(serial_crc, share->name, in smb2_get_info_filesystem()
5383 strlen(share->name)); in smb2_get_info_filesystem()
5384 serial_crc = crc32_le(serial_crc, share->path, in smb2_get_info_filesystem()
5385 strlen(share->path)); in smb2_get_info_filesystem()
5389 info->SerialNumber = cpu_to_le32(serial_crc); in smb2_get_info_filesystem()
5390 len = smbConvertToUTF16((__le16 *)info->VolumeLabel, in smb2_get_info_filesystem()
5391 share->name, PATH_MAX, in smb2_get_info_filesystem()
5392 conn->local_nls, 0); in smb2_get_info_filesystem()
5394 info->VolumeLabelSize = cpu_to_le32(len); in smb2_get_info_filesystem()
5395 info->Reserved = 0; in smb2_get_info_filesystem()
5397 rsp->OutputBufferLength = cpu_to_le32(sz); in smb2_get_info_filesystem()
5404 info = (struct filesystem_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5405 info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks); in smb2_get_info_filesystem()
5406 info->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree); in smb2_get_info_filesystem()
5407 info->SectorsPerAllocationUnit = cpu_to_le32(1); in smb2_get_info_filesystem()
5408 info->BytesPerSector = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5409 rsp->OutputBufferLength = cpu_to_le32(24); in smb2_get_info_filesystem()
5416 info = (struct smb2_fs_full_size_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5417 info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks); in smb2_get_info_filesystem()
5418 info->CallerAvailableAllocationUnits = in smb2_get_info_filesystem()
5420 info->ActualAvailableAllocationUnits = in smb2_get_info_filesystem()
5422 info->SectorsPerAllocationUnit = cpu_to_le32(1); in smb2_get_info_filesystem()
5423 info->BytesPerSector = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5424 rsp->OutputBufferLength = cpu_to_le32(32); in smb2_get_info_filesystem()
5431 info = (struct object_id_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5433 if (!user_guest(sess->user)) in smb2_get_info_filesystem()
5434 memcpy(info->objid, user_passkey(sess->user), 16); in smb2_get_info_filesystem()
5436 memset(info->objid, 0, 16); in smb2_get_info_filesystem()
5438 info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC); in smb2_get_info_filesystem()
5439 info->extended_info.version = cpu_to_le32(1); in smb2_get_info_filesystem()
5440 info->extended_info.release = cpu_to_le32(1); in smb2_get_info_filesystem()
5441 info->extended_info.rel_date = 0; in smb2_get_info_filesystem()
5442 memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0")); in smb2_get_info_filesystem()
5443 rsp->OutputBufferLength = cpu_to_le32(64); in smb2_get_info_filesystem()
5450 min_t(unsigned int, path.mnt->mnt_sb->s_blocksize, 4096); in smb2_get_info_filesystem()
5452 info = (struct smb3_fs_ss_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5454 info->LogicalBytesPerSector = cpu_to_le32(sector_size); in smb2_get_info_filesystem()
5455 info->PhysicalBytesPerSectorForAtomicity = in smb2_get_info_filesystem()
5457 info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size); in smb2_get_info_filesystem()
5458 info->FSEffPhysicalBytesPerSectorForAtomicity = in smb2_get_info_filesystem()
5460 info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE | in smb2_get_info_filesystem()
5462 info->ByteOffsetForSectorAlignment = 0; in smb2_get_info_filesystem()
5463 info->ByteOffsetForPartitionAlignment = 0; in smb2_get_info_filesystem()
5464 rsp->OutputBufferLength = cpu_to_le32(28); in smb2_get_info_filesystem()
5477 info = (struct smb2_fs_control_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5478 info->FreeSpaceStartFiltering = 0; in smb2_get_info_filesystem()
5479 info->FreeSpaceThreshold = 0; in smb2_get_info_filesystem()
5480 info->FreeSpaceStopFiltering = 0; in smb2_get_info_filesystem()
5481 info->DefaultQuotaThreshold = cpu_to_le64(SMB2_NO_FID); in smb2_get_info_filesystem()
5482 info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID); in smb2_get_info_filesystem()
5483 info->Padding = 0; in smb2_get_info_filesystem()
5484 rsp->OutputBufferLength = cpu_to_le32(48); in smb2_get_info_filesystem()
5491 if (!work->tcon->posix_extensions) { in smb2_get_info_filesystem()
5493 rc = -EOPNOTSUPP; in smb2_get_info_filesystem()
5495 info = (struct filesystem_posix_info *)(rsp->Buffer); in smb2_get_info_filesystem()
5496 info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5497 info->BlockSize = cpu_to_le32(stfs.f_bsize); in smb2_get_info_filesystem()
5498 info->TotalBlocks = cpu_to_le64(stfs.f_blocks); in smb2_get_info_filesystem()
5499 info->BlocksAvail = cpu_to_le64(stfs.f_bfree); in smb2_get_info_filesystem()
5500 info->UserBlocksAvail = cpu_to_le64(stfs.f_bavail); in smb2_get_info_filesystem()
5501 info->TotalFileNodes = cpu_to_le64(stfs.f_files); in smb2_get_info_filesystem()
5502 info->FreeFileNodes = cpu_to_le64(stfs.f_ffree); in smb2_get_info_filesystem()
5503 rsp->OutputBufferLength = cpu_to_le32(56); in smb2_get_info_filesystem()
5509 return -EOPNOTSUPP; in smb2_get_info_filesystem()
5511 rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength), in smb2_get_info_filesystem()
5512 rsp, work->response_buf); in smb2_get_info_filesystem()
5523 struct smb_ntsd *pntsd = (struct smb_ntsd *)rsp->Buffer, *ppntsd = NULL; in smb2_get_info_sec()
5528 int addition_info = le32_to_cpu(req->AdditionalInformation); in smb2_get_info_sec()
5537 pntsd->revision = cpu_to_le16(1); in smb2_get_info_sec()
5538 pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PROTECTED); in smb2_get_info_sec()
5539 pntsd->osidoffset = 0; in smb2_get_info_sec()
5540 pntsd->gsidoffset = 0; in smb2_get_info_sec()
5541 pntsd->sacloffset = 0; in smb2_get_info_sec()
5542 pntsd->dacloffset = 0; in smb2_get_info_sec()
5545 rsp->OutputBufferLength = cpu_to_le32(secdesclen); in smb2_get_info_sec()
5550 if (work->next_smb2_rcv_hdr_off) { in smb2_get_info_sec()
5551 if (!has_file_id(req->VolatileFileId)) { in smb2_get_info_sec()
5553 work->compound_fid); in smb2_get_info_sec()
5554 id = work->compound_fid; in smb2_get_info_sec()
5555 pid = work->compound_pfid; in smb2_get_info_sec()
5560 id = req->VolatileFileId; in smb2_get_info_sec()
5561 pid = req->PersistentFileId; in smb2_get_info_sec()
5566 return -ENOENT; in smb2_get_info_sec()
5568 idmap = file_mnt_idmap(fp->filp); in smb2_get_info_sec()
5569 inode = file_inode(fp->filp); in smb2_get_info_sec()
5572 if (test_share_config_flag(work->tcon->share_conf, in smb2_get_info_sec()
5574 ppntsd_size = ksmbd_vfs_get_sd_xattr(work->conn, idmap, in smb2_get_info_sec()
5575 fp->filp->f_path.dentry, in smb2_get_info_sec()
5589 rsp->OutputBufferLength = cpu_to_le32(secdesclen); in smb2_get_info_sec()
5594 * smb2_query_info() - handler for smb2 query info command
5610 rc = -ENOMEM; in smb2_query_info()
5614 switch (req->InfoType) { in smb2_query_info()
5629 req->InfoType); in smb2_query_info()
5630 rc = -EOPNOTSUPP; in smb2_query_info()
5635 rsp->StructureSize = cpu_to_le16(9); in smb2_query_info()
5636 rsp->OutputBufferOffset = cpu_to_le16(72); in smb2_query_info()
5639 le32_to_cpu(rsp->OutputBufferLength)); in smb2_query_info()
5644 if (rc == -EACCES) in smb2_query_info()
5645 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_query_info()
5646 else if (rc == -ENOENT) in smb2_query_info()
5647 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_query_info()
5648 else if (rc == -EIO) in smb2_query_info()
5649 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_query_info()
5650 else if (rc == -ENOMEM) in smb2_query_info()
5651 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_query_info()
5652 else if (rc == -EOPNOTSUPP || rsp->hdr.Status == 0) in smb2_query_info()
5653 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS; in smb2_query_info()
5664 * smb2_close_pipe() - handler for closing IPC pipe
5677 id = req->VolatileFileId; in smb2_close_pipe()
5678 ksmbd_session_rpc_close(work->sess, id); in smb2_close_pipe()
5680 rsp->StructureSize = cpu_to_le16(60); in smb2_close_pipe()
5681 rsp->Flags = 0; in smb2_close_pipe()
5682 rsp->Reserved = 0; in smb2_close_pipe()
5683 rsp->CreationTime = 0; in smb2_close_pipe()
5684 rsp->LastAccessTime = 0; in smb2_close_pipe()
5685 rsp->LastWriteTime = 0; in smb2_close_pipe()
5686 rsp->ChangeTime = 0; in smb2_close_pipe()
5687 rsp->AllocationSize = 0; in smb2_close_pipe()
5688 rsp->EndOfFile = 0; in smb2_close_pipe()
5689 rsp->Attributes = 0; in smb2_close_pipe()
5696 * smb2_close() - handler for smb2 close file command
5707 struct ksmbd_conn *conn = work->conn; in smb2_close()
5714 if (test_share_config_flag(work->tcon->share_conf, in smb2_close()
5720 sess_id = le64_to_cpu(req->hdr.SessionId); in smb2_close()
5721 if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS) in smb2_close()
5722 sess_id = work->compound_sid; in smb2_close()
5724 work->compound_sid = 0; in smb2_close()
5726 work->compound_sid = sess_id; in smb2_close()
5728 rsp->hdr.Status = STATUS_USER_SESSION_DELETED; in smb2_close()
5729 if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS) in smb2_close()
5730 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_close()
5731 err = -EBADF; in smb2_close()
5735 if (work->next_smb2_rcv_hdr_off && in smb2_close()
5736 !has_file_id(req->VolatileFileId)) { in smb2_close()
5737 if (!has_file_id(work->compound_fid)) { in smb2_close()
5740 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_close()
5741 err = -EBADF; in smb2_close()
5746 work->compound_fid, in smb2_close()
5747 work->compound_pfid); in smb2_close()
5748 volatile_id = work->compound_fid; in smb2_close()
5751 work->compound_fid = KSMBD_NO_FID; in smb2_close()
5752 work->compound_pfid = KSMBD_NO_FID; in smb2_close()
5755 volatile_id = req->VolatileFileId; in smb2_close()
5759 rsp->StructureSize = cpu_to_le16(60); in smb2_close()
5760 rsp->Reserved = 0; in smb2_close()
5762 if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) { in smb2_close()
5768 err = -ENOENT; in smb2_close()
5772 ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in smb2_close()
5779 rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB; in smb2_close()
5780 rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 : in smb2_close()
5782 rsp->EndOfFile = cpu_to_le64(stat.size); in smb2_close()
5783 rsp->Attributes = fp->f_ci->m_fattr; in smb2_close()
5784 rsp->CreationTime = cpu_to_le64(fp->create_time); in smb2_close()
5786 rsp->LastAccessTime = cpu_to_le64(time); in smb2_close()
5788 rsp->LastWriteTime = cpu_to_le64(time); in smb2_close()
5790 rsp->ChangeTime = cpu_to_le64(time); in smb2_close()
5793 rsp->Flags = 0; in smb2_close()
5794 rsp->AllocationSize = 0; in smb2_close()
5795 rsp->EndOfFile = 0; in smb2_close()
5796 rsp->Attributes = 0; in smb2_close()
5797 rsp->CreationTime = 0; in smb2_close()
5798 rsp->LastAccessTime = 0; in smb2_close()
5799 rsp->LastWriteTime = 0; in smb2_close()
5800 rsp->ChangeTime = 0; in smb2_close()
5810 if (rsp->hdr.Status == 0) in smb2_close()
5811 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_close()
5819 * smb2_echo() - handler for smb2 echo(ping) command
5826 struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf); in smb2_echo()
5828 if (work->next_smb2_rcv_hdr_off) in smb2_echo()
5831 rsp->StructureSize = cpu_to_le16(4); in smb2_echo()
5832 rsp->Reserved = 0; in smb2_echo()
5841 struct ksmbd_share_config *share = fp->tcon->share_conf; in smb2_rename()
5846 new_name = smb2_get_name(file_info->FileName, in smb2_rename()
5847 le32_to_cpu(file_info->FileNameLength), in smb2_rename()
5863 if (len > 0 && new_name[len - 1] != '/') { in smb2_rename()
5865 rc = -ESHARE; in smb2_rename()
5876 rc = ksmbd_vfs_setxattr(file_mnt_idmap(fp->filp), in smb2_rename()
5877 &fp->filp->f_path, in smb2_rename()
5883 rc = -EINVAL; in smb2_rename()
5892 rc = -ENOENT; in smb2_rename()
5897 if (!file_info->ReplaceIfExists) in smb2_rename()
5900 rc = ksmbd_vfs_rename(work, &fp->filp->f_path, new_name, flags); in smb2_rename()
5920 le32_to_cpu(file_info->FileNameLength)) in smb2_create_link()
5921 return -EINVAL; in smb2_create_link()
5926 return -ENOMEM; in smb2_create_link()
5928 link_name = smb2_get_name(file_info->FileName, in smb2_create_link()
5929 le32_to_cpu(file_info->FileNameLength), in smb2_create_link()
5931 if (IS_ERR(link_name) || S_ISDIR(file_inode(filp)->i_mode)) { in smb2_create_link()
5932 rc = -EINVAL; in smb2_create_link()
5939 rc = -EINVAL; in smb2_create_link()
5947 if (rc != -ENOENT) in smb2_create_link()
5952 if (file_info->ReplaceIfExists) { in smb2_create_link()
5956 rc = -EINVAL; in smb2_create_link()
5964 rc = -EEXIST; in smb2_create_link()
5972 rc = -EINVAL; in smb2_create_link()
5993 if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE)) in set_file_basic_info()
5994 return -EACCES; in set_file_basic_info()
5997 filp = fp->filp; in set_file_basic_info()
6001 if (file_info->CreationTime) in set_file_basic_info()
6002 fp->create_time = le64_to_cpu(file_info->CreationTime); in set_file_basic_info()
6004 if (file_info->LastAccessTime) { in set_file_basic_info()
6005 attrs.ia_atime = ksmbd_NTtimeToUnix(file_info->LastAccessTime); in set_file_basic_info()
6010 if (file_info->ChangeTime) in set_file_basic_info()
6011 attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime); in set_file_basic_info()
6015 if (file_info->LastWriteTime) { in set_file_basic_info()
6016 attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime); in set_file_basic_info()
6020 if (file_info->Attributes) { in set_file_basic_info()
6021 if (!S_ISDIR(inode->i_mode) && in set_file_basic_info()
6022 file_info->Attributes & FILE_ATTRIBUTE_DIRECTORY_LE) { in set_file_basic_info()
6024 return -EINVAL; in set_file_basic_info()
6027 if (!(S_ISDIR(inode->i_mode) && file_info->Attributes == FILE_ATTRIBUTE_NORMAL_LE)) in set_file_basic_info()
6028 fp->f_ci->m_fattr = file_info->Attributes | in set_file_basic_info()
6029 (fp->f_ci->m_fattr & FILE_ATTRIBUTE_DIRECTORY_LE); in set_file_basic_info()
6033 (file_info->CreationTime || file_info->Attributes)) { in set_file_basic_info()
6037 da.itime = fp->itime; in set_file_basic_info()
6038 da.create_time = fp->create_time; in set_file_basic_info()
6039 da.attr = le32_to_cpu(fp->f_ci->m_fattr); in set_file_basic_info()
6043 rc = ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da, in set_file_basic_info()
6052 struct dentry *dentry = filp->f_path.dentry; in set_file_basic_info()
6056 return -EACCES; in set_file_basic_info()
6082 if (!(fp->daccess & FILE_WRITE_DATA_LE)) in set_file_allocation_info()
6083 return -EACCES; in set_file_allocation_info()
6085 rc = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, in set_file_allocation_info()
6090 alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9; in set_file_allocation_info()
6091 inode = file_inode(fp->filp); in set_file_allocation_info()
6095 rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0, in set_file_allocation_info()
6097 if (rc && rc != -EOPNOTSUPP) { in set_file_allocation_info()
6130 if (!(fp->daccess & FILE_WRITE_DATA_LE)) in set_end_of_file_info()
6131 return -EACCES; in set_end_of_file_info()
6133 newsize = le64_to_cpu(file_eof_info->EndOfFile); in set_end_of_file_info()
6134 inode = file_inode(fp->filp); in set_end_of_file_info()
6143 if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) { in set_end_of_file_info()
6148 if (rc != -EAGAIN) in set_end_of_file_info()
6149 rc = -EBADF; in set_end_of_file_info()
6160 if (!(fp->daccess & FILE_DELETE_LE)) { in set_rename_info()
6161 pr_err("no right to delete : 0x%x\n", fp->daccess); in set_rename_info()
6162 return -EACCES; in set_rename_info()
6166 le32_to_cpu(rename_info->FileNameLength)) in set_rename_info()
6167 return -EINVAL; in set_rename_info()
6169 if (!le32_to_cpu(rename_info->FileNameLength)) in set_rename_info()
6170 return -EINVAL; in set_rename_info()
6172 return smb2_rename(work, fp, rename_info, work->conn->local_nls); in set_rename_info()
6180 if (!(fp->daccess & FILE_DELETE_LE)) { in set_file_disposition_info()
6181 pr_err("no right to delete : 0x%x\n", fp->daccess); in set_file_disposition_info()
6182 return -EACCES; in set_file_disposition_info()
6185 inode = file_inode(fp->filp); in set_file_disposition_info()
6186 if (file_info->DeletePending) { in set_file_disposition_info()
6187 if (S_ISDIR(inode->i_mode) && in set_file_disposition_info()
6188 ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY) in set_file_disposition_info()
6189 return -EBUSY; in set_file_disposition_info()
6204 inode = file_inode(fp->filp); in set_file_position_info()
6205 current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset); in set_file_position_info()
6206 sector_size = inode->i_sb->s_blocksize; in set_file_position_info()
6209 (fp->coption == FILE_NO_INTERMEDIATE_BUFFERING_LE && in set_file_position_info()
6210 current_byte_offset & (sector_size - 1))) { in set_file_position_info()
6213 return -EINVAL; in set_file_position_info()
6216 fp->filp->f_pos = current_byte_offset; in set_file_position_info()
6225 mode = file_info->Mode; in set_file_mode_info()
6229 return -EINVAL; in set_file_mode_info()
6236 ksmbd_vfs_set_fadvise(fp->filp, mode); in set_file_mode_info()
6237 fp->coption = mode; in set_file_mode_info()
6242 * smb2_set_info_file() - handler for smb2 set info command
6255 unsigned int buf_len = le32_to_cpu(req->BufferLength); in smb2_set_info_file()
6256 char *buffer = (char *)req + le16_to_cpu(req->BufferOffset); in smb2_set_info_file()
6258 switch (req->FileInfoClass) { in smb2_set_info_file()
6262 return -EINVAL; in smb2_set_info_file()
6269 return -EINVAL; in smb2_set_info_file()
6277 return -EINVAL; in smb2_set_info_file()
6285 return -EINVAL; in smb2_set_info_file()
6294 return -EINVAL; in smb2_set_info_file()
6296 return smb2_create_link(work, work->tcon->share_conf, in smb2_set_info_file()
6298 buf_len, fp->filp, in smb2_set_info_file()
6299 work->conn->local_nls); in smb2_set_info_file()
6304 return -EINVAL; in smb2_set_info_file()
6311 if (!(fp->daccess & FILE_WRITE_EA_LE)) { in smb2_set_info_file()
6313 fp->daccess); in smb2_set_info_file()
6314 return -EACCES; in smb2_set_info_file()
6318 return -EINVAL; in smb2_set_info_file()
6321 buf_len, &fp->filp->f_path, true); in smb2_set_info_file()
6326 return -EINVAL; in smb2_set_info_file()
6333 return -EINVAL; in smb2_set_info_file()
6339 pr_err("Unimplemented Fileinfoclass :%d\n", req->FileInfoClass); in smb2_set_info_file()
6340 return -EOPNOTSUPP; in smb2_set_info_file()
6348 fp->saccess |= FILE_SHARE_DELETE_LE; in smb2_set_info_sec()
6350 return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd, in smb2_set_info_sec()
6355 * smb2_set_info() - handler for smb2 set info command handler
6370 if (work->next_smb2_rcv_hdr_off) { in smb2_set_info()
6373 if (!has_file_id(req->VolatileFileId)) { in smb2_set_info()
6375 work->compound_fid); in smb2_set_info()
6376 id = work->compound_fid; in smb2_set_info()
6377 pid = work->compound_pfid; in smb2_set_info()
6380 req = smb2_get_msg(work->request_buf); in smb2_set_info()
6381 rsp = smb2_get_msg(work->response_buf); in smb2_set_info()
6384 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_set_info()
6387 rc = -EACCES; in smb2_set_info()
6392 id = req->VolatileFileId; in smb2_set_info()
6393 pid = req->PersistentFileId; in smb2_set_info()
6399 rc = -ENOENT; in smb2_set_info()
6403 switch (req->InfoType) { in smb2_set_info()
6406 rc = smb2_set_info_file(work, fp, req, work->tcon->share_conf); in smb2_set_info()
6411 rc = -ENOMEM; in smb2_set_info()
6415 le32_to_cpu(req->AdditionalInformation), in smb2_set_info()
6416 (char *)req + le16_to_cpu(req->BufferOffset), in smb2_set_info()
6417 le32_to_cpu(req->BufferLength)); in smb2_set_info()
6421 rc = -EOPNOTSUPP; in smb2_set_info()
6427 rsp->StructureSize = cpu_to_le16(2); in smb2_set_info()
6436 if (rc == -EACCES || rc == -EPERM || rc == -EXDEV) in smb2_set_info()
6437 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_set_info()
6438 else if (rc == -EINVAL) in smb2_set_info()
6439 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_set_info()
6440 else if (rc == -ESHARE) in smb2_set_info()
6441 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_set_info()
6442 else if (rc == -ENOENT) in smb2_set_info()
6443 rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID; in smb2_set_info()
6444 else if (rc == -EBUSY || rc == -ENOTEMPTY) in smb2_set_info()
6445 rsp->hdr.Status = STATUS_DIRECTORY_NOT_EMPTY; in smb2_set_info()
6446 else if (rc == -EAGAIN) in smb2_set_info()
6447 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in smb2_set_info()
6448 else if (rc == -EBADF || rc == -ESTALE) in smb2_set_info()
6449 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_set_info()
6450 else if (rc == -EEXIST) in smb2_set_info()
6451 rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION; in smb2_set_info()
6452 else if (rsp->hdr.Status == 0 || rc == -EOPNOTSUPP) in smb2_set_info()
6453 rsp->hdr.Status = STATUS_INVALID_INFO_CLASS; in smb2_set_info()
6461 * smb2_read_pipe() - handler for smb2 read from IPC pipe
6476 id = req->VolatileFileId; in smb2_read_pipe()
6478 rpc_resp = ksmbd_rpc_read(work->sess, id); in smb2_read_pipe()
6482 if (rpc_resp->flags != KSMBD_RPC_OK) { in smb2_read_pipe()
6483 err = -EINVAL; in smb2_read_pipe()
6488 kvmalloc(rpc_resp->payload_sz, GFP_KERNEL); in smb2_read_pipe()
6490 err = -ENOMEM; in smb2_read_pipe()
6494 memcpy(aux_payload_buf, rpc_resp->payload, rpc_resp->payload_sz); in smb2_read_pipe()
6496 nbytes = rpc_resp->payload_sz; in smb2_read_pipe()
6512 rsp->StructureSize = cpu_to_le16(17); in smb2_read_pipe()
6513 rsp->DataOffset = 80; in smb2_read_pipe()
6514 rsp->Reserved = 0; in smb2_read_pipe()
6515 rsp->DataLength = cpu_to_le32(nbytes); in smb2_read_pipe()
6516 rsp->DataRemaining = 0; in smb2_read_pipe()
6517 rsp->Flags = 0; in smb2_read_pipe()
6521 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in smb2_read_pipe()
6529 __le32 Channel, in smb2_set_remote_key_for_rdma() argument
6534 if (work->conn->dialect == SMB30_PROT_ID && in smb2_set_remote_key_for_rdma()
6535 Channel != SMB2_CHANNEL_RDMA_V1) in smb2_set_remote_key_for_rdma()
6536 return -EINVAL; in smb2_set_remote_key_for_rdma()
6548 return -EINVAL; in smb2_set_remote_key_for_rdma()
6550 work->need_invalidate_rkey = in smb2_set_remote_key_for_rdma()
6551 (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE); in smb2_set_remote_key_for_rdma()
6552 if (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) in smb2_set_remote_key_for_rdma()
6553 work->remote_key = le32_to_cpu(desc->token); in smb2_set_remote_key_for_rdma()
6563 err = ksmbd_conn_rdma_write(work->conn, data_buf, length, in smb2_read_rdma_channel()
6565 ((char *)req + le16_to_cpu(req->ReadChannelInfoOffset)), in smb2_read_rdma_channel()
6566 le16_to_cpu(req->ReadChannelInfoLength)); in smb2_read_rdma_channel()
6574 * smb2_read() - handler for smb2 read from file
6581 struct ksmbd_conn *conn = work->conn; in smb2_read()
6590 unsigned int max_read_size = conn->vals->max_read_size; in smb2_read()
6594 if (test_share_config_flag(work->tcon->share_conf, in smb2_read()
6600 if (work->next_smb2_rcv_hdr_off) { in smb2_read()
6603 if (!has_file_id(req->VolatileFileId)) { in smb2_read()
6605 work->compound_fid); in smb2_read()
6606 id = work->compound_fid; in smb2_read()
6607 pid = work->compound_pfid; in smb2_read()
6610 req = smb2_get_msg(work->request_buf); in smb2_read()
6611 rsp = smb2_get_msg(work->response_buf); in smb2_read()
6615 id = req->VolatileFileId; in smb2_read()
6616 pid = req->PersistentFileId; in smb2_read()
6619 if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE || in smb2_read()
6620 req->Channel == SMB2_CHANNEL_RDMA_V1) { in smb2_read()
6626 unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset); in smb2_read()
6629 err = -EINVAL; in smb2_read()
6635 req->Channel, in smb2_read()
6636 req->ReadChannelInfoLength); in smb2_read()
6643 err = -ENOENT; in smb2_read()
6647 if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_READ_ATTRIBUTES_LE))) { in smb2_read()
6648 pr_err("Not permitted to read : 0x%x\n", fp->daccess); in smb2_read()
6649 err = -EACCES; in smb2_read()
6653 offset = le64_to_cpu(req->Offset); in smb2_read()
6654 length = le32_to_cpu(req->Length); in smb2_read()
6655 mincount = le32_to_cpu(req->MinimumCount); in smb2_read()
6660 err = -EINVAL; in smb2_read()
6665 fp->filp, offset, length); in smb2_read()
6669 err = -ENOMEM; in smb2_read()
6681 rsp->hdr.Status = STATUS_END_OF_FILE; in smb2_read()
6691 /* write data to the client using rdma channel */ in smb2_read()
6704 rsp->StructureSize = cpu_to_le16(17); in smb2_read()
6705 rsp->DataOffset = 80; in smb2_read()
6706 rsp->Reserved = 0; in smb2_read()
6707 rsp->DataLength = cpu_to_le32(nbytes); in smb2_read()
6708 rsp->DataRemaining = cpu_to_le32(remain_bytes); in smb2_read()
6709 rsp->Flags = 0; in smb2_read()
6722 if (err == -EISDIR) in smb2_read()
6723 rsp->hdr.Status = STATUS_INVALID_DEVICE_REQUEST; in smb2_read()
6724 else if (err == -EAGAIN) in smb2_read()
6725 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in smb2_read()
6726 else if (err == -ENOENT) in smb2_read()
6727 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_read()
6728 else if (err == -EACCES) in smb2_read()
6729 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_read()
6730 else if (err == -ESHARE) in smb2_read()
6731 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_read()
6732 else if (err == -EINVAL) in smb2_read()
6733 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_read()
6735 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_read()
6744 * smb2_write_pipe() - handler for smb2 write on IPC pipe
6761 length = le32_to_cpu(req->Length); in smb2_write_pipe()
6762 id = req->VolatileFileId; in smb2_write_pipe()
6764 if ((u64)le16_to_cpu(req->DataOffset) + length > in smb2_write_pipe()
6765 get_rfc1002_len(work->request_buf)) { in smb2_write_pipe()
6767 le16_to_cpu(req->DataOffset), in smb2_write_pipe()
6768 get_rfc1002_len(work->request_buf)); in smb2_write_pipe()
6769 err = -EINVAL; in smb2_write_pipe()
6773 data_buf = (char *)(((char *)&req->hdr.ProtocolId) + in smb2_write_pipe()
6774 le16_to_cpu(req->DataOffset)); in smb2_write_pipe()
6776 rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length); in smb2_write_pipe()
6778 if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) { in smb2_write_pipe()
6779 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_write_pipe()
6782 return -EOPNOTSUPP; in smb2_write_pipe()
6784 if (rpc_resp->flags != KSMBD_RPC_OK) { in smb2_write_pipe()
6785 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_write_pipe()
6793 rsp->StructureSize = cpu_to_le16(17); in smb2_write_pipe()
6794 rsp->DataOffset = 0; in smb2_write_pipe()
6795 rsp->Reserved = 0; in smb2_write_pipe()
6796 rsp->DataLength = cpu_to_le32(length); in smb2_write_pipe()
6797 rsp->DataRemaining = 0; in smb2_write_pipe()
6798 rsp->Reserved2 = 0; in smb2_write_pipe()
6803 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_write_pipe()
6821 return -ENOMEM; in smb2_write_rdma_channel()
6823 ret = ksmbd_conn_rdma_read(work->conn, data_buf, length, in smb2_write_rdma_channel()
6825 ((char *)req + le16_to_cpu(req->WriteChannelInfoOffset)), in smb2_write_rdma_channel()
6826 le16_to_cpu(req->WriteChannelInfoLength)); in smb2_write_rdma_channel()
6841 * smb2_write() - handler for smb2 write from file
6857 unsigned int max_write_size = work->conn->vals->max_write_size; in smb2_write()
6861 if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) { in smb2_write()
6866 offset = le64_to_cpu(req->Offset); in smb2_write()
6867 length = le32_to_cpu(req->Length); in smb2_write()
6869 if (req->Channel == SMB2_CHANNEL_RDMA_V1 || in smb2_write()
6870 req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) { in smb2_write()
6873 length = le32_to_cpu(req->RemainingBytes); in smb2_write()
6877 unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset); in smb2_write()
6879 if (req->Length != 0 || req->DataOffset != 0 || in smb2_write()
6881 err = -EINVAL; in smb2_write()
6887 req->Channel, in smb2_write()
6888 req->WriteChannelInfoLength); in smb2_write()
6893 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_write()
6895 err = -EACCES; in smb2_write()
6899 fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in smb2_write()
6901 err = -ENOENT; in smb2_write()
6905 if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_READ_ATTRIBUTES_LE))) { in smb2_write()
6906 pr_err("Not permitted to write : 0x%x\n", fp->daccess); in smb2_write()
6907 err = -EACCES; in smb2_write()
6914 err = -EINVAL; in smb2_write()
6918 ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags)); in smb2_write()
6919 if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH) in smb2_write()
6923 if (le16_to_cpu(req->DataOffset) < in smb2_write()
6925 err = -EINVAL; in smb2_write()
6929 data_buf = (char *)(((char *)&req->hdr.ProtocolId) + in smb2_write()
6930 le16_to_cpu(req->DataOffset)); in smb2_write()
6933 fp->filp, offset, length); in smb2_write()
6939 /* read data from the client using rdma channel, and in smb2_write()
6950 rsp->StructureSize = cpu_to_le16(17); in smb2_write()
6951 rsp->DataOffset = 0; in smb2_write()
6952 rsp->Reserved = 0; in smb2_write()
6953 rsp->DataLength = cpu_to_le32(nbytes); in smb2_write()
6954 rsp->DataRemaining = 0; in smb2_write()
6955 rsp->Reserved2 = 0; in smb2_write()
6963 if (err == -EAGAIN) in smb2_write()
6964 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in smb2_write()
6965 else if (err == -ENOSPC || err == -EFBIG) in smb2_write()
6966 rsp->hdr.Status = STATUS_DISK_FULL; in smb2_write()
6967 else if (err == -ENOENT) in smb2_write()
6968 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_write()
6969 else if (err == -EACCES) in smb2_write()
6970 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_write()
6971 else if (err == -ESHARE) in smb2_write()
6972 rsp->hdr.Status = STATUS_SHARING_VIOLATION; in smb2_write()
6973 else if (err == -EINVAL) in smb2_write()
6974 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_write()
6976 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_write()
6984 * smb2_flush() - handler for smb2 flush file - fsync
6997 ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n", req->VolatileFileId); in smb2_flush()
6999 err = ksmbd_vfs_fsync(work, req->VolatileFileId, req->PersistentFileId); in smb2_flush()
7003 rsp->StructureSize = cpu_to_le16(4); in smb2_flush()
7004 rsp->Reserved = 0; in smb2_flush()
7008 rsp->hdr.Status = STATUS_INVALID_HANDLE; in smb2_flush()
7014 * smb2_cancel() - handler for smb2 cancel command
7021 struct ksmbd_conn *conn = work->conn; in smb2_cancel()
7022 struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); in smb2_cancel()
7027 if (work->next_smb2_rcv_hdr_off) in smb2_cancel()
7031 hdr->MessageId, hdr->Flags); in smb2_cancel()
7033 if (hdr->Flags & SMB2_FLAGS_ASYNC_COMMAND) { in smb2_cancel()
7034 command_list = &conn->async_requests; in smb2_cancel()
7036 spin_lock(&conn->request_lock); in smb2_cancel()
7039 chdr = smb2_get_msg(iter->request_buf); in smb2_cancel()
7041 if (iter->async_id != in smb2_cancel()
7042 le64_to_cpu(hdr->Id.AsyncId)) in smb2_cancel()
7047 le64_to_cpu(hdr->Id.AsyncId), in smb2_cancel()
7048 le16_to_cpu(chdr->Command)); in smb2_cancel()
7049 iter->state = KSMBD_WORK_CANCELLED; in smb2_cancel()
7050 if (iter->cancel_fn) in smb2_cancel()
7051 iter->cancel_fn(iter->cancel_argv); in smb2_cancel()
7054 spin_unlock(&conn->request_lock); in smb2_cancel()
7056 command_list = &conn->requests; in smb2_cancel()
7058 spin_lock(&conn->request_lock); in smb2_cancel()
7060 chdr = smb2_get_msg(iter->request_buf); in smb2_cancel()
7062 if (chdr->MessageId != hdr->MessageId || in smb2_cancel()
7068 le64_to_cpu(hdr->MessageId), in smb2_cancel()
7069 le16_to_cpu(chdr->Command)); in smb2_cancel()
7070 iter->state = KSMBD_WORK_CANCELLED; in smb2_cancel()
7073 spin_unlock(&conn->request_lock); in smb2_cancel()
7077 work->send_no_response = 1; in smb2_cancel()
7091 fl->c.flc_owner = f; in smb_flock_init()
7092 fl->c.flc_pid = current->tgid; in smb_flock_init()
7093 fl->c.flc_file = f; in smb_flock_init()
7094 fl->c.flc_flags = FL_POSIX; in smb_flock_init()
7095 fl->fl_ops = NULL; in smb_flock_init()
7096 fl->fl_lmops = NULL; in smb_flock_init()
7104 int cmd = -EINVAL; in smb2_set_flock_flags()
7111 flock->c.flc_type = F_RDLCK; in smb2_set_flock_flags()
7112 flock->c.flc_flags |= FL_SLEEP; in smb2_set_flock_flags()
7117 flock->c.flc_type = F_WRLCK; in smb2_set_flock_flags()
7118 flock->c.flc_flags |= FL_SLEEP; in smb2_set_flock_flags()
7124 flock->c.flc_type = F_RDLCK; in smb2_set_flock_flags()
7130 flock->c.flc_type = F_WRLCK; in smb2_set_flock_flags()
7134 flock->c.flc_type = F_UNLCK; in smb2_set_flock_flags()
7152 lock->cmd = cmd; in smb2_lock_init()
7153 lock->fl = flock; in smb2_lock_init()
7154 lock->start = flock->fl_start; in smb2_lock_init()
7155 lock->end = flock->fl_end; in smb2_lock_init()
7156 lock->flags = flags; in smb2_lock_init()
7157 if (lock->start == lock->end) in smb2_lock_init()
7158 lock->zero_len = 1; in smb2_lock_init()
7159 INIT_LIST_HEAD(&lock->clist); in smb2_lock_init()
7160 INIT_LIST_HEAD(&lock->flist); in smb2_lock_init()
7161 INIT_LIST_HEAD(&lock->llist); in smb2_lock_init()
7162 list_add_tail(&lock->llist, lock_list); in smb2_lock_init()
7178 return waitqueue_active(&fl->c.flc_wait); in lock_defer_pending()
7182 * smb2_lock() - handler for smb2 file lock command
7198 int err = -EIO, i, rc = 0; in smb2_lock()
7210 fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in smb2_lock()
7212 ksmbd_debug(SMB, "Invalid file id for lock : %llu\n", req->VolatileFileId); in smb2_lock()
7213 err = -ENOENT; in smb2_lock()
7217 filp = fp->filp; in smb2_lock()
7218 lock_count = le16_to_cpu(req->LockCount); in smb2_lock()
7219 lock_ele = req->locks; in smb2_lock()
7223 err = -EINVAL; in smb2_lock()
7238 if (lock_start > U64_MAX - lock_length) { in smb2_lock()
7240 rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE; in smb2_lock()
7246 flock->fl_start = OFFSET_MAX; in smb2_lock()
7248 flock->fl_start = lock_start; in smb2_lock()
7251 if (lock_length > OFFSET_MAX - flock->fl_start) in smb2_lock()
7252 lock_length = OFFSET_MAX - flock->fl_start; in smb2_lock()
7254 flock->fl_end = flock->fl_start + lock_length; in smb2_lock()
7256 if (flock->fl_end < flock->fl_start) { in smb2_lock()
7259 flock->fl_end, flock->fl_start); in smb2_lock()
7260 rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE; in smb2_lock()
7267 if (cmp_lock->fl->fl_start <= flock->fl_start && in smb2_lock()
7268 cmp_lock->fl->fl_end >= flock->fl_end) { in smb2_lock()
7269 if (cmp_lock->fl->c.flc_type != F_UNLCK && in smb2_lock()
7270 flock->c.flc_type != F_UNLCK) { in smb2_lock()
7272 err = -EINVAL; in smb2_lock()
7281 err = -EINVAL; in smb2_lock()
7288 if (smb_lock->cmd < 0) { in smb2_lock()
7289 err = -EINVAL; in smb2_lock()
7293 if (!(smb_lock->flags & SMB2_LOCKFLAG_MASK)) { in smb2_lock()
7294 err = -EINVAL; in smb2_lock()
7299 smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) || in smb2_lock()
7301 !(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK))) { in smb2_lock()
7302 err = -EINVAL; in smb2_lock()
7306 prior_lock = smb_lock->flags; in smb2_lock()
7308 if (!(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) && in smb2_lock()
7309 !(smb_lock->flags & SMB2_LOCKFLAG_FAIL_IMMEDIATELY)) in smb2_lock()
7316 spin_lock(&conn->llist_lock); in smb2_lock()
7317 list_for_each_entry_safe(cmp_lock, tmp2, &conn->lock_list, clist) { in smb2_lock()
7318 if (file_inode(cmp_lock->fl->c.flc_file) != in smb2_lock()
7319 file_inode(smb_lock->fl->c.flc_file)) in smb2_lock()
7322 if (lock_is_unlock(smb_lock->fl)) { in smb2_lock()
7323 if (cmp_lock->fl->c.flc_file == smb_lock->fl->c.flc_file && in smb2_lock()
7324 cmp_lock->start == smb_lock->start && in smb2_lock()
7325 cmp_lock->end == smb_lock->end && in smb2_lock()
7326 !lock_defer_pending(cmp_lock->fl)) { in smb2_lock()
7328 list_del(&cmp_lock->flist); in smb2_lock()
7329 list_del(&cmp_lock->clist); in smb2_lock()
7330 spin_unlock(&conn->llist_lock); in smb2_lock()
7333 locks_free_lock(cmp_lock->fl); in smb2_lock()
7340 if (cmp_lock->fl->c.flc_file == smb_lock->fl->c.flc_file) { in smb2_lock()
7341 if (smb_lock->flags & SMB2_LOCKFLAG_SHARED) in smb2_lock()
7344 if (cmp_lock->flags & SMB2_LOCKFLAG_SHARED) in smb2_lock()
7349 if (cmp_lock->zero_len && !smb_lock->zero_len && in smb2_lock()
7350 cmp_lock->start > smb_lock->start && in smb2_lock()
7351 cmp_lock->start < smb_lock->end) { in smb2_lock()
7352 spin_unlock(&conn->llist_lock); in smb2_lock()
7358 if (smb_lock->zero_len && !cmp_lock->zero_len && in smb2_lock()
7359 smb_lock->start > cmp_lock->start && in smb2_lock()
7360 smb_lock->start < cmp_lock->end) { in smb2_lock()
7361 spin_unlock(&conn->llist_lock); in smb2_lock()
7367 if (((cmp_lock->start <= smb_lock->start && in smb2_lock()
7368 cmp_lock->end > smb_lock->start) || in smb2_lock()
7369 (cmp_lock->start < smb_lock->end && in smb2_lock()
7370 cmp_lock->end >= smb_lock->end)) && in smb2_lock()
7371 !cmp_lock->zero_len && !smb_lock->zero_len) { in smb2_lock()
7372 spin_unlock(&conn->llist_lock); in smb2_lock()
7378 spin_unlock(&conn->llist_lock); in smb2_lock()
7382 if (lock_is_unlock(smb_lock->fl) && nolock) { in smb2_lock()
7384 rsp->hdr.Status = STATUS_RANGE_NOT_LOCKED; in smb2_lock()
7389 if (smb_lock->zero_len) { in smb2_lock()
7394 flock = smb_lock->fl; in smb2_lock()
7395 list_del(&smb_lock->llist); in smb2_lock()
7397 rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL); in smb2_lock()
7402 } else if (rc == -ENOENT) { in smb2_lock()
7403 rsp->hdr.Status = STATUS_NOT_LOCKED; in smb2_lock()
7414 list_add(&smb_lock->llist, &rollback_list); in smb2_lock()
7418 err = -ENOMEM; in smb2_lock()
7428 err = -ENOMEM; in smb2_lock()
7431 spin_lock(&fp->f_lock); in smb2_lock()
7432 list_add(&work->fp_entry, &fp->blocked_works); in smb2_lock()
7433 spin_unlock(&fp->f_lock); in smb2_lock()
7439 spin_lock(&fp->f_lock); in smb2_lock()
7440 list_del(&work->fp_entry); in smb2_lock()
7441 spin_unlock(&fp->f_lock); in smb2_lock()
7443 if (work->state != KSMBD_WORK_ACTIVE) { in smb2_lock()
7444 list_del(&smb_lock->llist); in smb2_lock()
7447 if (work->state == KSMBD_WORK_CANCELLED) { in smb2_lock()
7448 rsp->hdr.Status = in smb2_lock()
7453 work->send_no_response = 1; in smb2_lock()
7457 rsp->hdr.Status = in smb2_lock()
7463 list_del(&smb_lock->llist); in smb2_lock()
7467 list_add(&smb_lock->llist, &rollback_list); in smb2_lock()
7468 spin_lock(&work->conn->llist_lock); in smb2_lock()
7469 list_add_tail(&smb_lock->clist, in smb2_lock()
7470 &work->conn->lock_list); in smb2_lock()
7471 list_add_tail(&smb_lock->flist, in smb2_lock()
7472 &fp->lock_list); in smb2_lock()
7473 spin_unlock(&work->conn->llist_lock); in smb2_lock()
7481 if (atomic_read(&fp->f_ci->op_count) > 1) in smb2_lock()
7484 rsp->StructureSize = cpu_to_le16(4); in smb2_lock()
7486 rsp->hdr.Status = STATUS_SUCCESS; in smb2_lock()
7487 rsp->Reserved = 0; in smb2_lock()
7497 locks_free_lock(smb_lock->fl); in smb2_lock()
7498 list_del(&smb_lock->llist); in smb2_lock()
7506 rlock->c.flc_type = F_UNLCK; in smb2_lock()
7507 rlock->fl_start = smb_lock->start; in smb2_lock()
7508 rlock->fl_end = smb_lock->end; in smb2_lock()
7514 list_del(&smb_lock->llist); in smb2_lock()
7515 spin_lock(&work->conn->llist_lock); in smb2_lock()
7516 if (!list_empty(&smb_lock->flist)) in smb2_lock()
7517 list_del(&smb_lock->flist); in smb2_lock()
7518 list_del(&smb_lock->clist); in smb2_lock()
7519 spin_unlock(&work->conn->llist_lock); in smb2_lock()
7521 locks_free_lock(smb_lock->fl); in smb2_lock()
7528 if (!rsp->hdr.Status) { in smb2_lock()
7529 if (err == -EINVAL) in smb2_lock()
7530 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_lock()
7531 else if (err == -ENOMEM) in smb2_lock()
7532 rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; in smb2_lock()
7533 else if (err == -ENOENT) in smb2_lock()
7534 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb2_lock()
7536 rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED; in smb2_lock()
7560 ci_rsp = (struct copychunk_ioctl_rsp *)&rsp->Buffer[0]; in fsctl_copychunk()
7562 rsp->VolatileFileId = volatile_id; in fsctl_copychunk()
7563 rsp->PersistentFileId = persistent_id; in fsctl_copychunk()
7564 ci_rsp->ChunksWritten = in fsctl_copychunk()
7566 ci_rsp->ChunkBytesWritten = in fsctl_copychunk()
7568 ci_rsp->TotalBytesWritten = in fsctl_copychunk()
7571 chunk_count = le32_to_cpu(ci_req->ChunkCount); in fsctl_copychunk()
7579 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_copychunk()
7580 return -EINVAL; in fsctl_copychunk()
7583 chunks = &ci_req->Chunks[0]; in fsctl_copychunk()
7593 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_copychunk()
7594 return -EINVAL; in fsctl_copychunk()
7598 le64_to_cpu(ci_req->ResumeKey[0])); in fsctl_copychunk()
7600 ret = -EINVAL; in fsctl_copychunk()
7602 src_fp->persistent_id != le64_to_cpu(ci_req->ResumeKey[1])) { in fsctl_copychunk()
7603 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND; in fsctl_copychunk()
7608 rsp->hdr.Status = STATUS_FILE_CLOSED; in fsctl_copychunk()
7617 !(dst_fp->daccess & (FILE_READ_DATA_LE | FILE_GENERIC_READ_LE))) { in fsctl_copychunk()
7618 rsp->hdr.Status = STATUS_ACCESS_DENIED; in fsctl_copychunk()
7628 if (ret == -EACCES) in fsctl_copychunk()
7629 rsp->hdr.Status = STATUS_ACCESS_DENIED; in fsctl_copychunk()
7630 if (ret == -EAGAIN) in fsctl_copychunk()
7631 rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT; in fsctl_copychunk()
7632 else if (ret == -EBADF) in fsctl_copychunk()
7633 rsp->hdr.Status = STATUS_INVALID_HANDLE; in fsctl_copychunk()
7634 else if (ret == -EFBIG || ret == -ENOSPC) in fsctl_copychunk()
7635 rsp->hdr.Status = STATUS_DISK_FULL; in fsctl_copychunk()
7636 else if (ret == -EINVAL) in fsctl_copychunk()
7637 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_copychunk()
7638 else if (ret == -EISDIR) in fsctl_copychunk()
7639 rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY; in fsctl_copychunk()
7640 else if (ret == -E2BIG) in fsctl_copychunk()
7641 rsp->hdr.Status = STATUS_INVALID_VIEW_SIZE; in fsctl_copychunk()
7643 rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; in fsctl_copychunk()
7646 ci_rsp->ChunksWritten = cpu_to_le32(chunk_count_written); in fsctl_copychunk()
7647 ci_rsp->ChunkBytesWritten = cpu_to_le32(chunk_size_written); in fsctl_copychunk()
7648 ci_rsp->TotalBytesWritten = cpu_to_le32(total_size_written); in fsctl_copychunk()
7663 if (ifa->ifa_flags & IFA_F_SECONDARY) in idev_ipv4_address()
7666 addr = ifa->ifa_address; in idev_ipv4_address()
7688 if (netdev->type == ARPHRD_LOOPBACK) in fsctl_query_iface_info_ioctl()
7698 return -ENOSPC; in fsctl_query_iface_info_ioctl()
7702 &rsp->Buffer[nbytes]; in fsctl_query_iface_info_ioctl()
7703 nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex); in fsctl_query_iface_info_ioctl()
7705 nii_rsp->Capability = 0; in fsctl_query_iface_info_ioctl()
7706 if (netdev->real_num_tx_queues > 1) in fsctl_query_iface_info_ioctl()
7707 nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE); in fsctl_query_iface_info_ioctl()
7709 nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE); in fsctl_query_iface_info_ioctl()
7711 nii_rsp->Next = cpu_to_le32(152); in fsctl_query_iface_info_ioctl()
7712 nii_rsp->Reserved = 0; in fsctl_query_iface_info_ioctl()
7714 if (netdev->ethtool_ops->get_link_ksettings) { in fsctl_query_iface_info_ioctl()
7717 netdev->ethtool_ops->get_link_ksettings(netdev, &cmd); in fsctl_query_iface_info_ioctl()
7720 ksmbd_debug(SMB, "%s %s\n", netdev->name, in fsctl_query_iface_info_ioctl()
7726 nii_rsp->LinkSpeed = cpu_to_le64(speed); in fsctl_query_iface_info_ioctl()
7729 nii_rsp->SockAddr_Storage; in fsctl_query_iface_info_ioctl()
7735 sockaddr_storage->Family = cpu_to_le16(INTERNETWORK); in fsctl_query_iface_info_ioctl()
7736 sockaddr_storage->addr4.Port = 0; in fsctl_query_iface_info_ioctl()
7741 sockaddr_storage->addr4.IPv4address = in fsctl_query_iface_info_ioctl()
7749 __u8 *ipv6_addr = sockaddr_storage->addr6.IPv6address; in fsctl_query_iface_info_ioctl()
7751 sockaddr_storage->Family = cpu_to_le16(INTERNETWORKV6); in fsctl_query_iface_info_ioctl()
7752 sockaddr_storage->addr6.Port = 0; in fsctl_query_iface_info_ioctl()
7753 sockaddr_storage->addr6.FlowInfo = 0; in fsctl_query_iface_info_ioctl()
7759 list_for_each_entry(ifa, &idev6->addr_list, if_list) { in fsctl_query_iface_info_ioctl()
7760 if (ifa->flags & (IFA_F_TENTATIVE | in fsctl_query_iface_info_ioctl()
7763 memcpy(ipv6_addr, ifa->addr.s6_addr, 16); in fsctl_query_iface_info_ioctl()
7766 sockaddr_storage->addr6.ScopeId = 0; in fsctl_query_iface_info_ioctl()
7774 nii_rsp->Next = 0; in fsctl_query_iface_info_ioctl()
7776 rsp->PersistentFileId = SMB2_NO_FID; in fsctl_query_iface_info_ioctl()
7777 rsp->VolatileFileId = SMB2_NO_FID; in fsctl_query_iface_info_ioctl()
7790 le16_to_cpu(neg_req->DialectCount) * sizeof(__le16)) in fsctl_validate_negotiate_info()
7791 return -EINVAL; in fsctl_validate_negotiate_info()
7793 dialect = ksmbd_lookup_dialect_by_id(neg_req->Dialects, in fsctl_validate_negotiate_info()
7794 neg_req->DialectCount); in fsctl_validate_negotiate_info()
7795 if (dialect == BAD_PROT_ID || dialect != conn->dialect) { in fsctl_validate_negotiate_info()
7796 ret = -EINVAL; in fsctl_validate_negotiate_info()
7800 if (strncmp(neg_req->Guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE)) { in fsctl_validate_negotiate_info()
7801 ret = -EINVAL; in fsctl_validate_negotiate_info()
7805 if (le16_to_cpu(neg_req->SecurityMode) != conn->cli_sec_mode) { in fsctl_validate_negotiate_info()
7806 ret = -EINVAL; in fsctl_validate_negotiate_info()
7810 if (le32_to_cpu(neg_req->Capabilities) != conn->cli_cap) { in fsctl_validate_negotiate_info()
7811 ret = -EINVAL; in fsctl_validate_negotiate_info()
7815 neg_rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); in fsctl_validate_negotiate_info()
7816 memset(neg_rsp->Guid, 0, SMB2_CLIENT_GUID_SIZE); in fsctl_validate_negotiate_info()
7817 neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode); in fsctl_validate_negotiate_info()
7818 neg_rsp->Dialect = cpu_to_le16(conn->dialect); in fsctl_validate_negotiate_info()
7834 return -EINVAL; in fsctl_query_allocated_ranges()
7836 start = le64_to_cpu(qar_req->file_offset); in fsctl_query_allocated_ranges()
7837 length = le64_to_cpu(qar_req->length); in fsctl_query_allocated_ranges()
7840 return -EINVAL; in fsctl_query_allocated_ranges()
7844 return -ENOENT; in fsctl_query_allocated_ranges()
7848 if (ret && ret != -E2BIG) in fsctl_query_allocated_ranges()
7861 char *data_buf = (char *)req + le32_to_cpu(req->InputOffset); in fsctl_pipe_transceive()
7864 rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf, in fsctl_pipe_transceive()
7865 le32_to_cpu(req->InputCount)); in fsctl_pipe_transceive()
7867 if (rpc_resp->flags == KSMBD_RPC_SOME_NOT_MAPPED) { in fsctl_pipe_transceive()
7872 rsp->hdr.Status = STATUS_SOME_NOT_MAPPED; in fsctl_pipe_transceive()
7873 } else if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) { in fsctl_pipe_transceive()
7874 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in fsctl_pipe_transceive()
7876 } else if (rpc_resp->flags != KSMBD_RPC_OK) { in fsctl_pipe_transceive()
7877 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in fsctl_pipe_transceive()
7881 nbytes = rpc_resp->payload_sz; in fsctl_pipe_transceive()
7882 if (rpc_resp->payload_sz > out_buf_len) { in fsctl_pipe_transceive()
7883 rsp->hdr.Status = STATUS_BUFFER_OVERFLOW; in fsctl_pipe_transceive()
7887 if (!rpc_resp->payload_sz) { in fsctl_pipe_transceive()
7888 rsp->hdr.Status = in fsctl_pipe_transceive()
7893 memcpy((char *)rsp->Buffer, rpc_resp->payload, nbytes); in fsctl_pipe_transceive()
7910 return -ENOENT; in fsctl_set_sparse()
7911 idmap = file_mnt_idmap(fp->filp); in fsctl_set_sparse()
7913 old_fattr = fp->f_ci->m_fattr; in fsctl_set_sparse()
7914 if (sparse->SetSparse) in fsctl_set_sparse()
7915 fp->f_ci->m_fattr |= FILE_ATTRIBUTE_SPARSE_FILE_LE; in fsctl_set_sparse()
7917 fp->f_ci->m_fattr &= ~FILE_ATTRIBUTE_SPARSE_FILE_LE; in fsctl_set_sparse()
7919 if (fp->f_ci->m_fattr != old_fattr && in fsctl_set_sparse()
7920 test_share_config_flag(work->tcon->share_conf, in fsctl_set_sparse()
7925 fp->filp->f_path.dentry, &da); in fsctl_set_sparse()
7929 da.attr = le32_to_cpu(fp->f_ci->m_fattr); in fsctl_set_sparse()
7931 &fp->filp->f_path, in fsctl_set_sparse()
7934 fp->f_ci->m_fattr = old_fattr; in fsctl_set_sparse()
7948 fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId); in fsctl_request_resume_key()
7950 return -ENOENT; in fsctl_request_resume_key()
7953 key_rsp->ResumeKey[0] = req->VolatileFileId; in fsctl_request_resume_key()
7954 key_rsp->ResumeKey[1] = req->PersistentFileId; in fsctl_request_resume_key()
7961 * smb2_ioctl() - handler for smb2 ioctl command
7972 struct ksmbd_conn *conn = work->conn; in smb2_ioctl()
7976 if (work->next_smb2_rcv_hdr_off) { in smb2_ioctl()
7979 if (!has_file_id(req->VolatileFileId)) { in smb2_ioctl()
7981 work->compound_fid); in smb2_ioctl()
7982 id = work->compound_fid; in smb2_ioctl()
7985 req = smb2_get_msg(work->request_buf); in smb2_ioctl()
7986 rsp = smb2_get_msg(work->response_buf); in smb2_ioctl()
7990 id = req->VolatileFileId; in smb2_ioctl()
7992 if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) { in smb2_ioctl()
7993 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_ioctl()
7997 buffer = (char *)req + le32_to_cpu(req->InputOffset); in smb2_ioctl()
7999 cnt_code = le32_to_cpu(req->CtlCode); in smb2_ioctl()
8001 le32_to_cpu(req->MaxOutputResponse)); in smb2_ioctl()
8003 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_ioctl()
8007 in_buf_len = le32_to_cpu(req->InputCount); in smb2_ioctl()
8013 rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED; in smb2_ioctl()
8021 &rsp->Buffer[0]; in smb2_ioctl()
8027 memset(obj_buf->ObjectId, 0x0, 16); in smb2_ioctl()
8028 memset(obj_buf->BirthVolumeId, 0x0, 16); in smb2_ioctl()
8029 memset(obj_buf->BirthObjectId, 0x0, 16); in smb2_ioctl()
8030 memset(obj_buf->DomainId, 0x0, 16); in smb2_ioctl()
8039 if (conn->dialect < SMB30_PROT_ID) { in smb2_ioctl()
8040 ret = -EOPNOTSUPP; in smb2_ioctl()
8046 ret = -EINVAL; in smb2_ioctl()
8051 ret = -EINVAL; in smb2_ioctl()
8057 (struct validate_negotiate_info_rsp *)&rsp->Buffer[0], in smb2_ioctl()
8063 rsp->PersistentFileId = SMB2_NO_FID; in smb2_ioctl()
8064 rsp->VolatileFileId = SMB2_NO_FID; in smb2_ioctl()
8074 ret = -EINVAL; in smb2_ioctl()
8079 (struct resume_key_ioctl_rsp *)&rsp->Buffer[0]); in smb2_ioctl()
8082 rsp->PersistentFileId = req->PersistentFileId; in smb2_ioctl()
8083 rsp->VolatileFileId = req->VolatileFileId; in smb2_ioctl()
8088 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_ioctl()
8091 ret = -EACCES; in smb2_ioctl()
8096 ret = -EINVAL; in smb2_ioctl()
8101 ret = -EINVAL; in smb2_ioctl()
8106 rsp->VolatileFileId = req->VolatileFileId; in smb2_ioctl()
8107 rsp->PersistentFileId = req->PersistentFileId; in smb2_ioctl()
8110 le32_to_cpu(req->CtlCode), in smb2_ioctl()
8111 le32_to_cpu(req->InputCount), in smb2_ioctl()
8112 req->VolatileFileId, in smb2_ioctl()
8113 req->PersistentFileId, in smb2_ioctl()
8118 ret = -EINVAL; in smb2_ioctl()
8132 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { in smb2_ioctl()
8135 ret = -EACCES; in smb2_ioctl()
8140 ret = -EINVAL; in smb2_ioctl()
8147 off = le64_to_cpu(zero_data->FileOffset); in smb2_ioctl()
8148 bfz = le64_to_cpu(zero_data->BeyondFinalZero); in smb2_ioctl()
8150 ret = -EINVAL; in smb2_ioctl()
8154 len = bfz - off; in smb2_ioctl()
8158 ret = -ENOENT; in smb2_ioctl()
8171 ret = -EINVAL; in smb2_ioctl()
8177 (struct file_allocated_range_buffer *)&rsp->Buffer[0], in smb2_ioctl()
8180 if (ret == -E2BIG) { in smb2_ioctl()
8181 rsp->hdr.Status = STATUS_BUFFER_OVERFLOW; in smb2_ioctl()
8194 reparse_ptr = (struct reparse_data_buffer *)&rsp->Buffer[0]; in smb2_ioctl()
8198 ret = -ENOENT; in smb2_ioctl()
8202 reparse_ptr->ReparseTag = in smb2_ioctl()
8203 smb2_get_reparse_tag_special_file(file_inode(fp->filp)->i_mode); in smb2_ioctl()
8204 reparse_ptr->ReparseDataLength = 0; in smb2_ioctl()
8216 ret = -EINVAL; in smb2_ioctl()
8222 fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle, in smb2_ioctl()
8223 dup_ext->PersistentFileHandle); in smb2_ioctl()
8226 ret = -ENOENT; in smb2_ioctl()
8233 ret = -ENOENT; in smb2_ioctl()
8237 src_off = le64_to_cpu(dup_ext->SourceFileOffset); in smb2_ioctl()
8238 dst_off = le64_to_cpu(dup_ext->TargetFileOffset); in smb2_ioctl()
8239 length = le64_to_cpu(dup_ext->ByteCount); in smb2_ioctl()
8243 * beneficial when re-exporting nfs/smb mount, but note that in smb2_ioctl()
8249 cloned = vfs_clone_file_range(fp_in->filp, src_off, in smb2_ioctl()
8250 fp_out->filp, dst_off, length, 0); in smb2_ioctl()
8251 if (cloned == -EXDEV || cloned == -EOPNOTSUPP) { in smb2_ioctl()
8252 ret = -EOPNOTSUPP; in smb2_ioctl()
8255 cloned = vfs_copy_file_range(fp_in->filp, src_off, in smb2_ioctl()
8256 fp_out->filp, dst_off, in smb2_ioctl()
8262 ret = -EINVAL; in smb2_ioctl()
8276 ret = -EOPNOTSUPP; in smb2_ioctl()
8280 rsp->CtlCode = cpu_to_le32(cnt_code); in smb2_ioctl()
8281 rsp->InputCount = cpu_to_le32(0); in smb2_ioctl()
8282 rsp->InputOffset = cpu_to_le32(112); in smb2_ioctl()
8283 rsp->OutputOffset = cpu_to_le32(112); in smb2_ioctl()
8284 rsp->OutputCount = cpu_to_le32(nbytes); in smb2_ioctl()
8285 rsp->StructureSize = cpu_to_le16(49); in smb2_ioctl()
8286 rsp->Reserved = cpu_to_le16(0); in smb2_ioctl()
8287 rsp->Flags = cpu_to_le32(0); in smb2_ioctl()
8288 rsp->Reserved2 = cpu_to_le32(0); in smb2_ioctl()
8294 if (ret == -EACCES) in smb2_ioctl()
8295 rsp->hdr.Status = STATUS_ACCESS_DENIED; in smb2_ioctl()
8296 else if (ret == -ENOENT) in smb2_ioctl()
8297 rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND; in smb2_ioctl()
8298 else if (ret == -EOPNOTSUPP) in smb2_ioctl()
8299 rsp->hdr.Status = STATUS_NOT_SUPPORTED; in smb2_ioctl()
8300 else if (ret == -ENOSPC) in smb2_ioctl()
8301 rsp->hdr.Status = STATUS_BUFFER_TOO_SMALL; in smb2_ioctl()
8302 else if (ret < 0 || rsp->hdr.Status == 0) in smb2_ioctl()
8303 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_ioctl()
8309 * smb20_oplock_break_ack() - handler for smb2.0 oplock break command
8328 volatile_id = req->VolatileFid; in smb20_oplock_break_ack()
8329 persistent_id = req->PersistentFid; in smb20_oplock_break_ack()
8330 req_oplevel = req->OplockLevel; in smb20_oplock_break_ack()
8336 rsp->hdr.Status = STATUS_FILE_CLOSED; in smb20_oplock_break_ack()
8344 rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL; in smb20_oplock_break_ack()
8350 if (opinfo->level == SMB2_OPLOCK_LEVEL_NONE) { in smb20_oplock_break_ack()
8351 rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL; in smb20_oplock_break_ack()
8355 if (opinfo->op_state == OPLOCK_STATE_NONE) { in smb20_oplock_break_ack()
8356 ksmbd_debug(SMB, "unexpected oplock state 0x%x\n", opinfo->op_state); in smb20_oplock_break_ack()
8357 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb20_oplock_break_ack()
8361 if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE || in smb20_oplock_break_ack()
8362 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) && in smb20_oplock_break_ack()
8367 } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II && in smb20_oplock_break_ack()
8374 if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE || in smb20_oplock_break_ack()
8375 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) && in smb20_oplock_break_ack()
8378 } else if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE || in smb20_oplock_break_ack()
8379 opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) && in smb20_oplock_break_ack()
8382 } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II && in smb20_oplock_break_ack()
8406 pr_err("unknown oplock change 0x%x -> 0x%x\n", in smb20_oplock_break_ack()
8407 opinfo->level, rsp_oplevel); in smb20_oplock_break_ack()
8411 rsp->hdr.Status = err; in smb20_oplock_break_ack()
8415 opinfo->op_state = OPLOCK_STATE_NONE; in smb20_oplock_break_ack()
8416 wake_up_interruptible_all(&opinfo->oplock_q); in smb20_oplock_break_ack()
8420 rsp->StructureSize = cpu_to_le16(24); in smb20_oplock_break_ack()
8421 rsp->OplockLevel = rsp_oplevel; in smb20_oplock_break_ack()
8422 rsp->Reserved = 0; in smb20_oplock_break_ack()
8423 rsp->Reserved2 = 0; in smb20_oplock_break_ack()
8424 rsp->VolatileFid = volatile_id; in smb20_oplock_break_ack()
8425 rsp->PersistentFid = persistent_id; in smb20_oplock_break_ack()
8431 opinfo->op_state = OPLOCK_STATE_NONE; in smb20_oplock_break_ack()
8432 wake_up_interruptible_all(&opinfo->oplock_q); in smb20_oplock_break_ack()
8441 if ((lease->new_state == in check_lease_state()
8444 lease->new_state = req_state; in check_lease_state()
8448 if (lease->new_state == req_state) in check_lease_state()
8455 * smb21_lease_break_ack() - handler for smb2.1 lease break command
8462 struct ksmbd_conn *conn = work->conn; in smb21_lease_break_ack()
8475 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8476 opinfo = lookup_lease_in_table(conn, req->LeaseKey); in smb21_lease_break_ack()
8480 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb21_lease_break_ack()
8483 lease = opinfo->o_lease; in smb21_lease_break_ack()
8485 if (opinfo->op_state == OPLOCK_STATE_NONE) { in smb21_lease_break_ack()
8487 opinfo->op_state); in smb21_lease_break_ack()
8488 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb21_lease_break_ack()
8492 if (check_lease_state(lease, req->LeaseState)) { in smb21_lease_break_ack()
8493 rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED; in smb21_lease_break_ack()
8496 req->LeaseState, lease->new_state); in smb21_lease_break_ack()
8500 if (!atomic_read(&opinfo->breaking_cnt)) { in smb21_lease_break_ack()
8501 rsp->hdr.Status = STATUS_UNSUCCESSFUL; in smb21_lease_break_ack()
8506 if (req->LeaseState & in smb21_lease_break_ack()
8509 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) in smb21_lease_break_ack()
8513 ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n", in smb21_lease_break_ack()
8514 le32_to_cpu(lease->state), in smb21_lease_break_ack()
8515 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8516 } else if (lease->state == SMB2_LEASE_READ_CACHING_LE && in smb21_lease_break_ack()
8517 req->LeaseState != SMB2_LEASE_NONE_LE) { in smb21_lease_break_ack()
8520 ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n", in smb21_lease_break_ack()
8521 le32_to_cpu(lease->state), in smb21_lease_break_ack()
8522 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8526 if (req->LeaseState == SMB2_LEASE_NONE_LE) { in smb21_lease_break_ack()
8527 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) in smb21_lease_break_ack()
8531 } else if (req->LeaseState & SMB2_LEASE_READ_CACHING_LE) { in smb21_lease_break_ack()
8532 if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) in smb21_lease_break_ack()
8555 ksmbd_debug(OPLOCK, "unknown lease change 0x%x -> 0x%x\n", in smb21_lease_break_ack()
8556 le32_to_cpu(lease->state), in smb21_lease_break_ack()
8557 le32_to_cpu(req->LeaseState)); in smb21_lease_break_ack()
8561 rsp->hdr.Status = err; in smb21_lease_break_ack()
8565 lease_state = lease->state; in smb21_lease_break_ack()
8566 opinfo->op_state = OPLOCK_STATE_NONE; in smb21_lease_break_ack()
8567 wake_up_interruptible_all(&opinfo->oplock_q); in smb21_lease_break_ack()
8568 atomic_dec(&opinfo->breaking_cnt); in smb21_lease_break_ack()
8569 wake_up_interruptible_all(&opinfo->oplock_brk); in smb21_lease_break_ack()
8572 rsp->StructureSize = cpu_to_le16(36); in smb21_lease_break_ack()
8573 rsp->Reserved = 0; in smb21_lease_break_ack()
8574 rsp->Flags = 0; in smb21_lease_break_ack()
8575 memcpy(rsp->LeaseKey, req->LeaseKey, 16); in smb21_lease_break_ack()
8576 rsp->LeaseState = lease_state; in smb21_lease_break_ack()
8577 rsp->LeaseDuration = 0; in smb21_lease_break_ack()
8583 wake_up_interruptible_all(&opinfo->oplock_q); in smb21_lease_break_ack()
8584 atomic_dec(&opinfo->breaking_cnt); in smb21_lease_break_ack()
8585 wake_up_interruptible_all(&opinfo->oplock_brk); in smb21_lease_break_ack()
8592 * smb2_oplock_break() - dispatcher for smb2.0 and 2.1 oplock/lease break
8604 switch (le16_to_cpu(req->StructureSize)) { in smb2_oplock_break()
8613 le16_to_cpu(req->StructureSize)); in smb2_oplock_break()
8614 rsp->hdr.Status = STATUS_INVALID_PARAMETER; in smb2_oplock_break()
8622 * smb2_notify() - handler for smb2 notify request
8634 if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) { in smb2_notify()
8635 rsp->hdr.Status = STATUS_INTERNAL_ERROR; in smb2_notify()
8641 rsp->hdr.Status = STATUS_NOT_IMPLEMENTED; in smb2_notify()
8646 * smb2_is_sign_req() - handler for checking packet signing status
8654 struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf); in smb2_is_sign_req()
8656 if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) && in smb2_is_sign_req()
8666 * smb2_check_sign_req() - handler for req packet sign processing
8679 hdr = smb2_get_msg(work->request_buf); in smb2_check_sign_req()
8680 if (work->next_smb2_rcv_hdr_off) in smb2_check_sign_req()
8683 if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off) in smb2_check_sign_req()
8684 len = get_rfc1002_len(work->request_buf); in smb2_check_sign_req()
8685 else if (hdr->NextCommand) in smb2_check_sign_req()
8686 len = le32_to_cpu(hdr->NextCommand); in smb2_check_sign_req()
8688 len = get_rfc1002_len(work->request_buf) - in smb2_check_sign_req()
8689 work->next_smb2_rcv_hdr_off; in smb2_check_sign_req()
8691 memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE); in smb2_check_sign_req()
8692 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb2_check_sign_req()
8694 iov[0].iov_base = (char *)&hdr->ProtocolId; in smb2_check_sign_req()
8697 if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1, in smb2_check_sign_req()
8710 * smb2_set_sign_rsp() - handler for rsp packet sign processing
8722 hdr->Flags |= SMB2_FLAGS_SIGNED; in smb2_set_sign_rsp()
8723 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb2_set_sign_rsp()
8725 if (hdr->Command == SMB2_READ) { in smb2_set_sign_rsp()
8726 iov = &work->iov[work->iov_idx - 1]; in smb2_set_sign_rsp()
8729 iov = &work->iov[work->iov_idx]; in smb2_set_sign_rsp()
8732 if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec, in smb2_set_sign_rsp()
8734 memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE); in smb2_set_sign_rsp()
8738 * smb3_check_sign_req() - handler for req packet sign processing
8745 struct ksmbd_conn *conn = work->conn; in smb3_check_sign_req()
8748 struct channel *chann; in smb3_check_sign_req()
8754 hdr = smb2_get_msg(work->request_buf); in smb3_check_sign_req()
8755 if (work->next_smb2_rcv_hdr_off) in smb3_check_sign_req()
8758 if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off) in smb3_check_sign_req()
8759 len = get_rfc1002_len(work->request_buf); in smb3_check_sign_req()
8760 else if (hdr->NextCommand) in smb3_check_sign_req()
8761 len = le32_to_cpu(hdr->NextCommand); in smb3_check_sign_req()
8763 len = get_rfc1002_len(work->request_buf) - in smb3_check_sign_req()
8764 work->next_smb2_rcv_hdr_off; in smb3_check_sign_req()
8766 if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { in smb3_check_sign_req()
8767 signing_key = work->sess->smb3signingkey; in smb3_check_sign_req()
8769 chann = lookup_chann_list(work->sess, conn); in smb3_check_sign_req()
8773 signing_key = chann->smb3signingkey; in smb3_check_sign_req()
8781 memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE); in smb3_check_sign_req()
8782 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb3_check_sign_req()
8783 iov[0].iov_base = (char *)&hdr->ProtocolId; in smb3_check_sign_req()
8798 * smb3_set_sign_rsp() - handler for rsp packet sign processing
8804 struct ksmbd_conn *conn = work->conn; in smb3_set_sign_rsp()
8806 struct channel *chann; in smb3_set_sign_rsp()
8814 if (conn->binding == false && in smb3_set_sign_rsp()
8815 le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { in smb3_set_sign_rsp()
8816 signing_key = work->sess->smb3signingkey; in smb3_set_sign_rsp()
8818 chann = lookup_chann_list(work->sess, work->conn); in smb3_set_sign_rsp()
8822 signing_key = chann->smb3signingkey; in smb3_set_sign_rsp()
8828 hdr->Flags |= SMB2_FLAGS_SIGNED; in smb3_set_sign_rsp()
8829 memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); in smb3_set_sign_rsp()
8831 if (hdr->Command == SMB2_READ) { in smb3_set_sign_rsp()
8832 iov = &work->iov[work->iov_idx - 1]; in smb3_set_sign_rsp()
8835 iov = &work->iov[work->iov_idx]; in smb3_set_sign_rsp()
8840 memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE); in smb3_set_sign_rsp()
8844 * smb3_preauth_hash_rsp() - handler for computing preauth hash on response
8850 struct ksmbd_conn *conn = work->conn; in smb3_preauth_hash_rsp()
8851 struct ksmbd_session *sess = work->sess; in smb3_preauth_hash_rsp()
8854 if (conn->dialect != SMB311_PROT_ID) in smb3_preauth_hash_rsp()
8859 if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE && in smb3_preauth_hash_rsp()
8860 conn->preauth_info) in smb3_preauth_hash_rsp()
8861 ksmbd_gen_preauth_integrity_hash(conn, work->response_buf, in smb3_preauth_hash_rsp()
8862 conn->preauth_info->Preauth_HashValue); in smb3_preauth_hash_rsp()
8864 if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) { in smb3_preauth_hash_rsp()
8867 if (conn->binding) { in smb3_preauth_hash_rsp()
8870 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id); in smb3_preauth_hash_rsp()
8873 hash_value = preauth_sess->Preauth_HashValue; in smb3_preauth_hash_rsp()
8875 hash_value = sess->Preauth_HashValue; in smb3_preauth_hash_rsp()
8879 ksmbd_gen_preauth_integrity_hash(conn, work->response_buf, in smb3_preauth_hash_rsp()
8891 tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; in fill_transform_hdr()
8892 tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len); in fill_transform_hdr()
8893 tr_hdr->Flags = cpu_to_le16(TRANSFORM_FLAG_ENCRYPTED); in fill_transform_hdr()
8896 get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE); in fill_transform_hdr()
8898 get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE); in fill_transform_hdr()
8899 memcpy(&tr_hdr->SessionId, &hdr->SessionId, 8); in fill_transform_hdr()
8906 struct kvec *iov = work->iov; in smb3_encrypt_resp()
8907 int rc = -ENOMEM; in smb3_encrypt_resp()
8915 fill_transform_hdr(tr_buf, work->response_buf, work->conn->cipher_type); in smb3_encrypt_resp()
8919 work->tr_buf = tr_buf; in smb3_encrypt_resp()
8921 return ksmbd_crypt_message(work, iov, work->iov_idx + 1, 1); in smb3_encrypt_resp()
8928 return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM; in smb3_is_transform_hdr()
8934 char *buf = work->request_buf; in smb3_decrypt_req()
8937 int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr); in smb3_decrypt_req()
8945 return -ECONNABORTED; in smb3_decrypt_req()
8948 if (buf_data_size < le32_to_cpu(tr_hdr->OriginalMessageSize)) { in smb3_decrypt_req()
8950 return -ECONNABORTED; in smb3_decrypt_req()
8953 sess = ksmbd_session_lookup_all(work->conn, le64_to_cpu(tr_hdr->SessionId)); in smb3_decrypt_req()
8956 le64_to_cpu(tr_hdr->SessionId)); in smb3_decrypt_req()
8957 return -ECONNABORTED; in smb3_decrypt_req()
8976 struct ksmbd_conn *conn = work->conn; in smb3_11_final_sess_setup_resp()
8977 struct ksmbd_session *sess = work->sess; in smb3_11_final_sess_setup_resp()
8978 struct smb2_hdr *rsp = smb2_get_msg(work->response_buf); in smb3_11_final_sess_setup_resp()
8980 if (conn->dialect < SMB30_PROT_ID) in smb3_11_final_sess_setup_resp()
8983 if (work->next_smb2_rcv_hdr_off) in smb3_11_final_sess_setup_resp()
8986 if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && in smb3_11_final_sess_setup_resp()
8987 sess->user && !user_guest(sess->user) && in smb3_11_final_sess_setup_resp()
8988 rsp->Status == STATUS_SUCCESS) in smb3_11_final_sess_setup_resp()