11 ksmbd server fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmWfZIYACgkQiiy9cAdy T1Gijgv+MH40buaJETR2FjRxzUiC92FFafGcX+fh5dLM22Sxb9AW+cNzOf/CSqNE 0AKpdhh+MVq0xiYwaXrrGGUfpUOZ3fwTHNJjpCt5o34b8U6IrHIah96noCRhDwQm pE1Loi5TyWYRYsCjajau+tIi9+lgROkJ9eM34bx2dkkDw5ng4MQAygqJDwDM1n+i N/O3vRqG3ZUrK5h7v9kVBdFZlkiiVm8cjNH86prfecnT6TTa/6QZoNd9kQAyvGe2 hWhW4J70y+H3JHcaBeGp11wcLcyBeFwBdqeo+os5EUPN/BbWaXuUqktBKvfnHIWA ucwrAMNVVK82JhudlkIGuYVgEOrLDrZsWjIJmDajFtJuO3Yo9VLkeZKcMRhPj45H kodPbCfPxNXg/y2fn1P3nCyiRSHHFb0QFEvK5JZV0Zwv5yPeziA/5e+6lu6OWNW7 VYQb2ZdOzuNW6aXHXnPRQQDSbVFsgD5dVxqYA9cugvtKAslUb9Q6z4kNkCFbYq/F xJ0VH0K5 =UhAE -----END PGP SIGNATURE----- Merge tag '6.8-rc-smb-server-fixes' of git://git.samba.org/ksmbd Pull smb server updates from Steve French: - memory allocation fix - three lease fixes, including important rename fix - read only share fix - thread freeze fix - three cleanup fixes (two kernel doc related) - locking fix in setting EAs - packet header validation fix * tag '6.8-rc-smb-server-fixes' of git://git.samba.org/ksmbd: ksmbd: Add missing set_freezable() for freezable kthread ksmbd: free ppace array on error in parse_dacl ksmbd: send lease break notification on FILE_RENAME_INFORMATION ksmbd: don't allow O_TRUNC open on read-only share ksmbd: vfs: fix all kernel-doc warnings ksmbd: auth: fix most kernel-doc warnings ksmbd: Remove usage of the deprecated ida_simple_xx() API ksmbd: don't increment epoch if current state and request state are same ksmbd: fix potential circular locking issue in smb2_set_ea() ksmbd: set v2 lease version on lease upgrade ksmbd: validate the zero field of packet header
This commit is contained in:
commit
6a31658aa1
@ -208,10 +208,12 @@ out:
|
||||
|
||||
/**
|
||||
* ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
|
||||
* @sess: session of connection
|
||||
* @conn: connection
|
||||
* @sess: session of connection
|
||||
* @ntlmv2: NTLMv2 challenge response
|
||||
* @blen: NTLMv2 blob length
|
||||
* @domain_name: domain name
|
||||
* @cryptkey: session crypto key
|
||||
*
|
||||
* Return: 0 on success, error number on error
|
||||
*/
|
||||
@ -294,7 +296,8 @@ out:
|
||||
* ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
|
||||
* authenticate blob
|
||||
* @authblob: authenticate blob source pointer
|
||||
* @usr: user details
|
||||
* @blob_len: length of the @authblob message
|
||||
* @conn: connection
|
||||
* @sess: session of connection
|
||||
*
|
||||
* Return: 0 on success, error number on error
|
||||
@ -376,8 +379,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
|
||||
* ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
|
||||
* negotiate blob
|
||||
* @negblob: negotiate blob source pointer
|
||||
* @rsp: response header pointer to be updated
|
||||
* @sess: session of connection
|
||||
* @blob_len: length of the @authblob message
|
||||
* @conn: connection
|
||||
*
|
||||
*/
|
||||
int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
|
||||
@ -403,8 +406,7 @@ int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
|
||||
* ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
|
||||
* challenge blob
|
||||
* @chgblob: challenge blob source pointer to initialize
|
||||
* @rsp: response header pointer to be updated
|
||||
* @sess: session of connection
|
||||
* @conn: connection
|
||||
*
|
||||
*/
|
||||
unsigned int
|
||||
|
@ -284,6 +284,7 @@ int ksmbd_conn_handler_loop(void *p)
|
||||
goto out;
|
||||
|
||||
conn->last_active = jiffies;
|
||||
set_freezable();
|
||||
while (ksmbd_conn_alive(conn)) {
|
||||
if (try_to_freeze())
|
||||
continue;
|
||||
|
@ -5,42 +5,33 @@
|
||||
|
||||
#include "ksmbd_ida.h"
|
||||
|
||||
static inline int __acquire_id(struct ida *ida, int from, int to)
|
||||
{
|
||||
return ida_simple_get(ida, from, to, GFP_KERNEL);
|
||||
}
|
||||
|
||||
int ksmbd_acquire_smb2_tid(struct ida *ida)
|
||||
{
|
||||
int id;
|
||||
|
||||
id = __acquire_id(ida, 1, 0xFFFFFFFF);
|
||||
|
||||
return id;
|
||||
return ida_alloc_range(ida, 1, 0xFFFFFFFE, GFP_KERNEL);
|
||||
}
|
||||
|
||||
int ksmbd_acquire_smb2_uid(struct ida *ida)
|
||||
{
|
||||
int id;
|
||||
|
||||
id = __acquire_id(ida, 1, 0);
|
||||
id = ida_alloc_min(ida, 1, GFP_KERNEL);
|
||||
if (id == 0xFFFE)
|
||||
id = __acquire_id(ida, 1, 0);
|
||||
id = ida_alloc_min(ida, 1, GFP_KERNEL);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
int ksmbd_acquire_async_msg_id(struct ida *ida)
|
||||
{
|
||||
return __acquire_id(ida, 1, 0);
|
||||
return ida_alloc_min(ida, 1, GFP_KERNEL);
|
||||
}
|
||||
|
||||
int ksmbd_acquire_id(struct ida *ida)
|
||||
{
|
||||
return __acquire_id(ida, 0, 0);
|
||||
return ida_alloc(ida, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void ksmbd_release_id(struct ida *ida, int id)
|
||||
{
|
||||
ida_simple_remove(ida, id);
|
||||
ida_free(ida, id);
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
|
||||
lease->is_dir = lctx->is_dir;
|
||||
memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);
|
||||
lease->version = lctx->version;
|
||||
lease->epoch = le16_to_cpu(lctx->epoch);
|
||||
lease->epoch = le16_to_cpu(lctx->epoch) + 1;
|
||||
INIT_LIST_HEAD(&opinfo->lease_entry);
|
||||
opinfo->o_lease = lease;
|
||||
|
||||
@ -546,6 +546,7 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
|
||||
atomic_read(&ci->sop_count)) == 1) {
|
||||
if (lease->state != SMB2_LEASE_NONE_LE &&
|
||||
lease->state == (lctx->req_state & lease->state)) {
|
||||
lease->epoch++;
|
||||
lease->state |= lctx->req_state;
|
||||
if (lctx->req_state &
|
||||
SMB2_LEASE_WRITE_CACHING_LE)
|
||||
@ -556,13 +557,17 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
|
||||
atomic_read(&ci->sop_count)) > 1) {
|
||||
if (lctx->req_state ==
|
||||
(SMB2_LEASE_READ_CACHING_LE |
|
||||
SMB2_LEASE_HANDLE_CACHING_LE))
|
||||
SMB2_LEASE_HANDLE_CACHING_LE)) {
|
||||
lease->epoch++;
|
||||
lease->state = lctx->req_state;
|
||||
}
|
||||
}
|
||||
|
||||
if (lctx->req_state && lease->state ==
|
||||
SMB2_LEASE_NONE_LE)
|
||||
SMB2_LEASE_NONE_LE) {
|
||||
lease->epoch++;
|
||||
lease_none_upgrade(opinfo, lctx->req_state);
|
||||
}
|
||||
}
|
||||
read_lock(&ci->m_lock);
|
||||
}
|
||||
@ -1035,7 +1040,8 @@ static void copy_lease(struct oplock_info *op1, struct oplock_info *op2)
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
lease2->duration = lease1->duration;
|
||||
lease2->flags = lease1->flags;
|
||||
lease2->epoch = lease1->epoch++;
|
||||
lease2->epoch = lease1->epoch;
|
||||
lease2->version = lease1->version;
|
||||
}
|
||||
|
||||
static int add_lease_global_list(struct oplock_info *opinfo)
|
||||
@ -1447,7 +1453,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
|
||||
memcpy(buf->lcontext.LeaseKey, lease->lease_key,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
buf->lcontext.LeaseFlags = lease->flags;
|
||||
buf->lcontext.Epoch = cpu_to_le16(++lease->epoch);
|
||||
buf->lcontext.Epoch = cpu_to_le16(lease->epoch);
|
||||
buf->lcontext.LeaseState = lease->state;
|
||||
memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
|
@ -2311,11 +2311,12 @@ out:
|
||||
* @eabuf: set info command buffer
|
||||
* @buf_len: set info command buffer length
|
||||
* @path: dentry path for get ea
|
||||
* @get_write: get write access to a mount
|
||||
*
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
|
||||
const struct path *path)
|
||||
const struct path *path, bool get_write)
|
||||
{
|
||||
struct mnt_idmap *idmap = mnt_idmap(path->mnt);
|
||||
char *attr_name = NULL, *value;
|
||||
@ -2971,7 +2972,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
&may_flags);
|
||||
|
||||
if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
|
||||
if (open_flags & O_CREAT) {
|
||||
if (open_flags & (O_CREAT | O_TRUNC)) {
|
||||
ksmbd_debug(SMB,
|
||||
"User does not have write permission\n");
|
||||
rc = -EACCES;
|
||||
@ -3003,7 +3004,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
|
||||
rc = smb2_set_ea(&ea_buf->ea,
|
||||
le32_to_cpu(ea_buf->ccontext.DataLength),
|
||||
&path);
|
||||
&path, false);
|
||||
if (rc == -EOPNOTSUPP)
|
||||
rc = 0;
|
||||
else if (rc)
|
||||
@ -5568,6 +5569,7 @@ static int smb2_rename(struct ksmbd_work *work,
|
||||
if (!file_info->ReplaceIfExists)
|
||||
flags = RENAME_NOREPLACE;
|
||||
|
||||
smb_break_all_levII_oplock(work, fp, 0);
|
||||
rc = ksmbd_vfs_rename(work, &fp->filp->f_path, new_name, flags);
|
||||
out:
|
||||
kfree(new_name);
|
||||
@ -5943,12 +5945,6 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
}
|
||||
case FILE_RENAME_INFORMATION:
|
||||
{
|
||||
if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
|
||||
ksmbd_debug(SMB,
|
||||
"User does not have write permission\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (buf_len < sizeof(struct smb2_file_rename_info))
|
||||
return -EINVAL;
|
||||
|
||||
@ -5968,12 +5964,6 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
}
|
||||
case FILE_DISPOSITION_INFORMATION:
|
||||
{
|
||||
if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
|
||||
ksmbd_debug(SMB,
|
||||
"User does not have write permission\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (buf_len < sizeof(struct smb2_file_disposition_info))
|
||||
return -EINVAL;
|
||||
|
||||
@ -5992,7 +5982,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
return -EINVAL;
|
||||
|
||||
return smb2_set_ea((struct smb2_ea_info *)req->Buffer,
|
||||
buf_len, &fp->filp->f_path);
|
||||
buf_len, &fp->filp->f_path, true);
|
||||
}
|
||||
case FILE_POSITION_INFORMATION:
|
||||
{
|
||||
@ -6035,7 +6025,7 @@ int smb2_set_info(struct ksmbd_work *work)
|
||||
{
|
||||
struct smb2_set_info_req *req;
|
||||
struct smb2_set_info_rsp *rsp;
|
||||
struct ksmbd_file *fp;
|
||||
struct ksmbd_file *fp = NULL;
|
||||
int rc = 0;
|
||||
unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
|
||||
|
||||
@ -6055,6 +6045,13 @@ int smb2_set_info(struct ksmbd_work *work)
|
||||
rsp = smb2_get_msg(work->response_buf);
|
||||
}
|
||||
|
||||
if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
|
||||
ksmbd_debug(SMB, "User does not have write permission\n");
|
||||
pr_err("User does not have write permission\n");
|
||||
rc = -EACCES;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (!has_file_id(id)) {
|
||||
id = req->VolatileFileId;
|
||||
pid = req->PersistentFileId;
|
||||
|
@ -158,8 +158,12 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work)
|
||||
*/
|
||||
bool ksmbd_smb_request(struct ksmbd_conn *conn)
|
||||
{
|
||||
__le32 *proto = (__le32 *)smb2_get_msg(conn->request_buf);
|
||||
__le32 *proto;
|
||||
|
||||
if (conn->request_buf[0] != 0)
|
||||
return false;
|
||||
|
||||
proto = (__le32 *)smb2_get_msg(conn->request_buf);
|
||||
if (*proto == SMB2_COMPRESSION_TRANSFORM_ID) {
|
||||
pr_err_ratelimited("smb2 compression not support yet");
|
||||
return false;
|
||||
|
@ -401,10 +401,6 @@ static void parse_dacl(struct mnt_idmap *idmap,
|
||||
if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
|
||||
return;
|
||||
|
||||
ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL);
|
||||
if (!ppace)
|
||||
return;
|
||||
|
||||
ret = init_acl_state(&acl_state, num_aces);
|
||||
if (ret)
|
||||
return;
|
||||
@ -414,6 +410,13 @@ static void parse_dacl(struct mnt_idmap *idmap,
|
||||
return;
|
||||
}
|
||||
|
||||
ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL);
|
||||
if (!ppace) {
|
||||
free_acl_state(&default_acl_state);
|
||||
free_acl_state(&acl_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* reset rwx permissions for user/group/other.
|
||||
* Also, if num_aces is 0 i.e. DACL has no ACEs,
|
||||
|
@ -49,6 +49,10 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
|
||||
|
||||
/**
|
||||
* ksmbd_vfs_lock_parent() - lock parent dentry if it is stable
|
||||
* @parent: parent dentry
|
||||
* @child: child dentry
|
||||
*
|
||||
* Returns: %0 on success, %-ENOENT if the parent dentry is not stable
|
||||
*/
|
||||
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
|
||||
{
|
||||
@ -360,7 +364,7 @@ out:
|
||||
/**
|
||||
* ksmbd_vfs_read() - vfs helper for smb file read
|
||||
* @work: smb work
|
||||
* @fid: file id of open file
|
||||
* @fp: ksmbd file pointer
|
||||
* @count: read byte count
|
||||
* @pos: file pos
|
||||
* @rbuf: read data buffer
|
||||
@ -474,7 +478,7 @@ out:
|
||||
/**
|
||||
* ksmbd_vfs_write() - vfs helper for smb file write
|
||||
* @work: work
|
||||
* @fid: file id of open file
|
||||
* @fp: ksmbd file pointer
|
||||
* @buf: buf containing data for writing
|
||||
* @count: read byte count
|
||||
* @pos: file pos
|
||||
@ -545,10 +549,8 @@ out:
|
||||
|
||||
/**
|
||||
* ksmbd_vfs_getattr() - vfs helper for smb getattr
|
||||
* @work: work
|
||||
* @fid: file id of open file
|
||||
* @attrs: inode attributes
|
||||
*
|
||||
* @path: path of dentry
|
||||
* @stat: pointer to returned kernel stat structure
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat)
|
||||
@ -565,6 +567,7 @@ int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat)
|
||||
* ksmbd_vfs_fsync() - vfs helper for smb fsync
|
||||
* @work: work
|
||||
* @fid: file id of open file
|
||||
* @p_id: persistent file id
|
||||
*
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
@ -587,7 +590,8 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
|
||||
|
||||
/**
|
||||
* ksmbd_vfs_remove_file() - vfs helper for smb rmdir or unlink
|
||||
* @name: directory or file name that is relative to share
|
||||
* @work: work
|
||||
* @path: path of dentry
|
||||
*
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
@ -623,6 +627,7 @@ out_err:
|
||||
|
||||
/**
|
||||
* ksmbd_vfs_link() - vfs helper for creating smb hardlink
|
||||
* @work: work
|
||||
* @oldname: source file name
|
||||
* @newname: hardlink name that is relative to share
|
||||
*
|
||||
@ -800,7 +805,7 @@ revert_fsids:
|
||||
/**
|
||||
* ksmbd_vfs_truncate() - vfs helper for smb file truncate
|
||||
* @work: work
|
||||
* @fid: file id of old file
|
||||
* @fp: ksmbd file pointer
|
||||
* @size: truncate to given size
|
||||
*
|
||||
* Return: 0 on success, otherwise error
|
||||
@ -843,7 +848,6 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work,
|
||||
* ksmbd_vfs_listxattr() - vfs helper for smb list extended attributes
|
||||
* @dentry: dentry of file for listing xattrs
|
||||
* @list: destination buffer
|
||||
* @size: destination buffer length
|
||||
*
|
||||
* Return: xattr list length on success, otherwise error
|
||||
*/
|
||||
@ -952,7 +956,7 @@ int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
|
||||
/**
|
||||
* ksmbd_vfs_set_fadvise() - convert smb IO caching options to linux options
|
||||
* @filp: file pointer for IO
|
||||
* @options: smb IO options
|
||||
* @option: smb IO options
|
||||
*/
|
||||
void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option)
|
||||
{
|
||||
@ -1164,6 +1168,7 @@ static bool __caseless_lookup(struct dir_context *ctx, const char *name,
|
||||
* @dir: path info
|
||||
* @name: filename to lookup
|
||||
* @namelen: filename length
|
||||
* @um: &struct unicode_map to use
|
||||
*
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
@ -1194,6 +1199,7 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
|
||||
|
||||
/**
|
||||
* ksmbd_vfs_kern_path_locked() - lookup a file and get path info
|
||||
* @work: work
|
||||
* @name: file path that is relative to share
|
||||
* @flags: lookup flags
|
||||
* @parent_path: if lookup succeed, return parent_path info
|
||||
@ -1641,6 +1647,8 @@ int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap,
|
||||
* ksmbd_vfs_init_kstat() - convert unix stat information to smb stat format
|
||||
* @p: destination buffer
|
||||
* @ksmbd_kstat: ksmbd kstat wrapper
|
||||
*
|
||||
* Returns: pointer to the converted &struct file_directory_info
|
||||
*/
|
||||
void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user