Commit 71b1543c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '6.9-rc5-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:
 "Five ksmbd server fixes, most also for stable:

   - rename fix

   - two fixes for potential out of bounds

   - fix for connections from MacOS (padding in close response)

   - fix for when to enable persistent handles"

* tag '6.9-rc5-ksmbd-fixes' of git://git.samba.org/ksmbd:
  ksmbd: add continuous availability share parameter
  ksmbd: common: use struct_group_attr instead of struct_group for network_open_info
  ksmbd: clear RENAME_NOREPLACE before calling vfs_rename
  ksmbd: validate request buffer size in smb2_allocate_rsp_buf()
  ksmbd: fix slab-out-of-bounds in smb2_allocate_rsp_buf
parents a2c63a3f e9d8c2f9
...@@ -711,7 +711,7 @@ struct smb2_close_rsp { ...@@ -711,7 +711,7 @@ struct smb2_close_rsp {
__le16 StructureSize; /* 60 */ __le16 StructureSize; /* 60 */
__le16 Flags; __le16 Flags;
__le32 Reserved; __le32 Reserved;
struct_group(network_open_info, struct_group_attr(network_open_info, __packed,
__le64 CreationTime; __le64 CreationTime;
__le64 LastAccessTime; __le64 LastAccessTime;
__le64 LastWriteTime; __le64 LastWriteTime;
......
...@@ -340,23 +340,24 @@ enum KSMBD_TREE_CONN_STATUS { ...@@ -340,23 +340,24 @@ enum KSMBD_TREE_CONN_STATUS {
/* /*
* Share config flags. * Share config flags.
*/ */
#define KSMBD_SHARE_FLAG_INVALID (0) #define KSMBD_SHARE_FLAG_INVALID (0)
#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0) #define KSMBD_SHARE_FLAG_AVAILABLE BIT(0)
#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1) #define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1)
#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2) #define KSMBD_SHARE_FLAG_WRITEABLE BIT(2)
#define KSMBD_SHARE_FLAG_READONLY BIT(3) #define KSMBD_SHARE_FLAG_READONLY BIT(3)
#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4) #define KSMBD_SHARE_FLAG_GUEST_OK BIT(4)
#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5) #define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5)
#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6) #define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6)
#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7) #define KSMBD_SHARE_FLAG_OPLOCKS BIT(7)
#define KSMBD_SHARE_FLAG_PIPE BIT(8) #define KSMBD_SHARE_FLAG_PIPE BIT(8)
#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9) #define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9)
#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10) #define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10)
#define KSMBD_SHARE_FLAG_STREAMS BIT(11) #define KSMBD_SHARE_FLAG_STREAMS BIT(11)
#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12) #define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12)
#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13) #define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13)
#define KSMBD_SHARE_FLAG_UPDATE BIT(14) #define KSMBD_SHARE_FLAG_UPDATE BIT(14)
#define KSMBD_SHARE_FLAG_CROSSMNT BIT(15) #define KSMBD_SHARE_FLAG_CROSSMNT BIT(15)
#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY BIT(16)
/* /*
* Tree connect request flags. * Tree connect request flags.
......
...@@ -167,20 +167,17 @@ static void __handle_ksmbd_work(struct ksmbd_work *work, ...@@ -167,20 +167,17 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
int rc; int rc;
bool is_chained = false; bool is_chained = false;
if (conn->ops->allocate_rsp_buf(work))
return;
if (conn->ops->is_transform_hdr && if (conn->ops->is_transform_hdr &&
conn->ops->is_transform_hdr(work->request_buf)) { conn->ops->is_transform_hdr(work->request_buf)) {
rc = conn->ops->decrypt_req(work); rc = conn->ops->decrypt_req(work);
if (rc < 0) { if (rc < 0)
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR); return;
goto send;
}
work->encrypted = true; work->encrypted = true;
} }
if (conn->ops->allocate_rsp_buf(work))
return;
rc = conn->ops->init_rsp_hdr(work); rc = conn->ops->init_rsp_hdr(work);
if (rc) { if (rc) {
/* either uid or tid is not correct */ /* either uid or tid is not correct */
......
...@@ -535,6 +535,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work) ...@@ -535,6 +535,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
if (cmd == SMB2_QUERY_INFO_HE) { if (cmd == SMB2_QUERY_INFO_HE) {
struct smb2_query_info_req *req; struct smb2_query_info_req *req;
if (get_rfc1002_len(work->request_buf) <
offsetof(struct smb2_query_info_req, OutputBufferLength))
return -EINVAL;
req = smb2_get_msg(work->request_buf); req = smb2_get_msg(work->request_buf);
if ((req->InfoType == SMB2_O_INFO_FILE && if ((req->InfoType == SMB2_O_INFO_FILE &&
(req->FileInfoClass == FILE_FULL_EA_INFORMATION || (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
...@@ -1984,7 +1988,12 @@ int smb2_tree_connect(struct ksmbd_work *work) ...@@ -1984,7 +1988,12 @@ int smb2_tree_connect(struct ksmbd_work *work)
write_unlock(&sess->tree_conns_lock); write_unlock(&sess->tree_conns_lock);
rsp->StructureSize = cpu_to_le16(16); rsp->StructureSize = cpu_to_le16(16);
out_err1: out_err1:
rsp->Capabilities = 0; if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE &&
test_share_config_flag(share,
KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
else
rsp->Capabilities = 0;
rsp->Reserved = 0; rsp->Reserved = 0;
/* default manual caching */ /* default manual caching */
rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING; rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
...@@ -3498,7 +3507,9 @@ int smb2_open(struct ksmbd_work *work) ...@@ -3498,7 +3507,9 @@ int smb2_open(struct ksmbd_work *work)
memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
if (dh_info.type == DURABLE_REQ_V2 || dh_info.type == DURABLE_REQ) { if (dh_info.type == DURABLE_REQ_V2 || dh_info.type == DURABLE_REQ) {
if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent) if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent &&
test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
fp->is_persistent = true; fp->is_persistent = true;
else else
fp->is_durable = true; fp->is_durable = true;
......
...@@ -754,10 +754,15 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path, ...@@ -754,10 +754,15 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
goto out4; goto out4;
} }
/*
* explicitly handle file overwrite case, for compatibility with
* filesystems that may not support rename flags (e.g: fuse)
*/
if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) { if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) {
err = -EEXIST; err = -EEXIST;
goto out4; goto out4;
} }
flags &= ~(RENAME_NOREPLACE);
if (old_child == trap) { if (old_child == trap) {
err = -EINVAL; err = -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment