diff options
Diffstat (limited to 'fs/smb/server/smb2pdu.c')
-rw-r--r-- | fs/smb/server/smb2pdu.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index e6bdc1b20727..599118aed205 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -605,8 +605,10 @@ int smb2_check_user_session(struct ksmbd_work *work) /* Check for validity of user session */ work->sess = ksmbd_session_lookup_all(conn, sess_id); - if (work->sess) + if (work->sess) { + ksmbd_user_session_get(work->sess); return 1; + } ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id); return -ENOENT; } @@ -1335,8 +1337,7 @@ static int ntlm_negotiate(struct ksmbd_work *work, return rc; sz = le16_to_cpu(rsp->SecurityBufferOffset); - chgblob = - (struct challenge_message *)((char *)&rsp->hdr.ProtocolId + sz); + chgblob = (struct challenge_message *)rsp->Buffer; memset(chgblob, 0, sizeof(struct challenge_message)); if (!work->conn->use_spnego) { @@ -1369,9 +1370,7 @@ static int ntlm_negotiate(struct ksmbd_work *work, goto out; } - sz = le16_to_cpu(rsp->SecurityBufferOffset); - unsafe_memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len, - /* alloc is larger than blob, see smb2_allocate_rsp_buf() */); + memcpy(rsp->Buffer, spnego_blob, spnego_blob_len); rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); out: @@ -1453,10 +1452,7 @@ static int ntlm_authenticate(struct ksmbd_work *work, if (rc) return -ENOMEM; - sz = le16_to_cpu(rsp->SecurityBufferOffset); - unsafe_memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, - spnego_blob_len, - /* alloc is larger than blob, see smb2_allocate_rsp_buf() */); + memcpy(rsp->Buffer, spnego_blob, spnego_blob_len); rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len); kfree(spnego_blob); } @@ -1746,6 +1742,7 @@ int smb2_sess_setup(struct ksmbd_work *work) } conn->binding = true; + ksmbd_user_session_get(sess); } else if ((conn->dialect < SMB30_PROT_ID || server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) && (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { @@ -1772,6 +1769,7 @@ int smb2_sess_setup(struct ksmbd_work *work) } conn->binding = false; + ksmbd_user_session_get(sess); } work->sess = sess; @@ -2058,18 +2056,20 @@ out_err1: * @access: file access flags * @disposition: file disposition flags * @may_flags: set with MAY_ flags - * @is_dir: is creating open flags for directory + * @coptions: file creation options + * @mode: file mode * * Return: file open flags */ static int smb2_create_open_flags(bool file_present, __le32 access, __le32 disposition, int *may_flags, - bool is_dir) + __le32 coptions, + umode_t mode) { int oflags = O_NONBLOCK | O_LARGEFILE; - if (is_dir) { + if (coptions & FILE_DIRECTORY_FILE_LE || S_ISDIR(mode)) { access &= ~FILE_WRITE_DESIRE_ACCESS_LE; ksmbd_debug(SMB, "Discard write access to a directory\n"); } @@ -2086,7 +2086,7 @@ static int smb2_create_open_flags(bool file_present, __le32 access, *may_flags = MAY_OPEN | MAY_READ; } - if (access == FILE_READ_ATTRIBUTES_LE) + if (access == FILE_READ_ATTRIBUTES_LE || S_ISBLK(mode) || S_ISCHR(mode)) oflags |= O_PATH; if (file_present) { @@ -2232,7 +2232,9 @@ int smb2_session_logoff(struct ksmbd_work *work) } ksmbd_destroy_file_table(&sess->file_table); + down_write(&conn->session_lock); sess->state = SMB2_SESSION_EXPIRED; + up_write(&conn->session_lock); ksmbd_free_user(sess->user); sess->user = NULL; @@ -3181,8 +3183,8 @@ int smb2_open(struct ksmbd_work *work) open_flags = smb2_create_open_flags(file_present, daccess, req->CreateDisposition, &may_flags, - req->CreateOptions & FILE_DIRECTORY_FILE_LE || - (file_present && S_ISDIR(d_inode(path.dentry)->i_mode))); + req->CreateOptions, + file_present ? d_inode(path.dentry)->i_mode : 0); if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { if (open_flags & (O_CREAT | O_TRUNC)) { @@ -3531,8 +3533,9 @@ int smb2_open(struct ksmbd_work *work) memcpy(fp->create_guid, dh_info.CreateGuid, SMB2_CREATE_GUID_SIZE); if (dh_info.timeout) - fp->durable_timeout = min(dh_info.timeout, - DURABLE_HANDLE_MAX_TIMEOUT); + fp->durable_timeout = + min_t(unsigned int, dh_info.timeout, + DURABLE_HANDLE_MAX_TIMEOUT); else fp->durable_timeout = 60; } @@ -4586,7 +4589,7 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp, path = &fp->filp->f_path; /* single EA entry is requested with given user.* name */ if (req->InputBufferLength) { - if (le32_to_cpu(req->InputBufferLength) < + if (le32_to_cpu(req->InputBufferLength) <= sizeof(struct smb2_ea_info_req)) return -EINVAL; @@ -4886,7 +4889,7 @@ static void get_file_alternate_info(struct ksmbd_work *work, spin_unlock(&dentry->d_lock); file_info->FileNameLength = cpu_to_le32(conv_len); rsp->OutputBufferLength = - cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len); + cpu_to_le32(struct_size(file_info, FileName, conv_len)); } static int get_file_stream_info(struct ksmbd_work *work, @@ -7565,7 +7568,6 @@ static int fsctl_copychunk(struct ksmbd_work *work, ci_rsp->TotalBytesWritten = cpu_to_le32(ksmbd_server_side_copy_max_total_size()); - chunks = (struct srv_copychunk *)&ci_req->Chunks[0]; chunk_count = le32_to_cpu(ci_req->ChunkCount); if (chunk_count == 0) goto out; @@ -7573,12 +7575,12 @@ static int fsctl_copychunk(struct ksmbd_work *work, /* verify the SRV_COPYCHUNK_COPY packet */ if (chunk_count > ksmbd_server_side_copy_max_chunk_count() || - input_count < offsetof(struct copychunk_ioctl_req, Chunks) + - chunk_count * sizeof(struct srv_copychunk)) { + input_count < struct_size(ci_req, Chunks, chunk_count)) { rsp->hdr.Status = STATUS_INVALID_PARAMETER; return -EINVAL; } + chunks = &ci_req->Chunks[0]; for (i = 0; i < chunk_count; i++) { if (le32_to_cpu(chunks[i].Length) == 0 || le32_to_cpu(chunks[i].Length) > ksmbd_server_side_copy_max_chunk_size()) @@ -8090,7 +8092,7 @@ int smb2_ioctl(struct ksmbd_work *work) goto out; } - if (in_buf_len < sizeof(struct copychunk_ioctl_req)) { + if (in_buf_len <= sizeof(struct copychunk_ioctl_req)) { ret = -EINVAL; goto out; } |