* [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y
@ 2023-12-18 15:32 Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 001/154] ksmbd: use ksmbd_req_buf_next() in ksmbd_verify_smb_message() Namjae Jeon
` (154 more replies)
0 siblings, 155 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon
This patchset backport ksmbd patches between 5.16 and 6.7-rc5 kernel.
Bug fixes and CVE patches were not applied well due to clean-up and new
feautre patches. To facilitate backport, This patch-set included
clean-up patches and new feature patches of ksmbd for stable 5.15
kernel.
--
2.25.1
^ permalink raw reply [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 001/154] ksmbd: use ksmbd_req_buf_next() in ksmbd_verify_smb_message()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 002/154] ksmdb: use cmd helper variable in smb2_get_ksmbd_tcon() Namjae Jeon
` (153 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Ralph Boehme, Namjae Jeon, Steve French
From: Ralph Boehme <slow@samba.org>
[ Upstream commit a088ac859f8124d491f02a19d080fc5ee4dbd202 ]
Use ksmbd_req_buf_next() in ksmbd_verify_smb_message().
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Ralph Boehme <slow@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb_common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index af583e426621..44dbc73d0d1c 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -134,7 +134,7 @@ int ksmbd_lookup_protocol_idx(char *str)
*/
int ksmbd_verify_smb_message(struct ksmbd_work *work)
{
- struct smb2_hdr *smb2_hdr = work->request_buf + work->next_smb2_rcv_hdr_off;
+ struct smb2_hdr *smb2_hdr = ksmbd_req_buf_next(work);
struct smb_hdr *hdr;
if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 002/154] ksmdb: use cmd helper variable in smb2_get_ksmbd_tcon()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 001/154] ksmbd: use ksmbd_req_buf_next() in ksmbd_verify_smb_message() Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 003/154] ksmbd: Remove redundant 'flush_workqueue()' calls Namjae Jeon
` (152 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Ralph Boehme, Tom Talpey, Ronnie Sahlberg, Hyunchul Lee,
Namjae Jeon, Steve French
From: Ralph Boehme <slow@samba.org>
[ Upstream commit 341b16014bf871115f0883e831372c4b76389d03 ]
Use cmd helper variable in smb2_get_ksmbd_tcon().
Cc: Tom Talpey <tom@talpey.com>
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: Steve French <smfrench@gmail.com>
Cc: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Ralph Boehme <slow@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/ksmbd/smb2pdu.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 656c627d1bdf..d41ff22d07f2 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -95,11 +95,12 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn
int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
{
struct smb2_hdr *req_hdr = work->request_buf;
+ unsigned int cmd = le16_to_cpu(req_hdr->Command);
int tree_id;
- if (work->conn->ops->get_cmd_val(work) == SMB2_TREE_CONNECT_HE ||
- work->conn->ops->get_cmd_val(work) == SMB2_CANCEL_HE ||
- work->conn->ops->get_cmd_val(work) == SMB2_LOGOFF_HE) {
+ if (cmd == SMB2_TREE_CONNECT_HE ||
+ cmd == SMB2_CANCEL_HE ||
+ cmd == SMB2_LOGOFF_HE) {
ksmbd_debug(SMB, "skip to check tree connect request\n");
return 0;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 003/154] ksmbd: Remove redundant 'flush_workqueue()' calls
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 001/154] ksmbd: use ksmbd_req_buf_next() in ksmbd_verify_smb_message() Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 002/154] ksmdb: use cmd helper variable in smb2_get_ksmbd_tcon() Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 17:56 ` Christophe JAILLET
2023-12-18 15:32 ` [PATCH 5.15.y 004/154] ksmbd: remove md4 leftovers Namjae Jeon
` (151 subsequent siblings)
154 siblings, 1 reply; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Christophe JAILLET, Namjae Jeon, Steve French
From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
[ Upstream commit e8d585b2f68c0b10c966ee55146de043429085a3 ]
'destroy_workqueue()' already drains the queue before destroying it, so
there is no need to flush it explicitly.
Remove the redundant 'flush_workqueue()' calls.
This was generated with coccinelle:
@@
expression E;
@@
- flush_workqueue(E);
destroy_workqueue(E);
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_work.c | 1 -
fs/ksmbd/transport_rdma.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
index fd58eb4809f6..14b9caebf7a4 100644
--- a/fs/ksmbd/ksmbd_work.c
+++ b/fs/ksmbd/ksmbd_work.c
@@ -69,7 +69,6 @@ int ksmbd_workqueue_init(void)
void ksmbd_workqueue_destroy(void)
{
- flush_workqueue(ksmbd_wq);
destroy_workqueue(ksmbd_wq);
ksmbd_wq = NULL;
}
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 9ca29cdb7898..86446742f4ad 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -2049,7 +2049,6 @@ int ksmbd_rdma_destroy(void)
smb_direct_listener.cm_id = NULL;
if (smb_direct_wq) {
- flush_workqueue(smb_direct_wq);
destroy_workqueue(smb_direct_wq);
smb_direct_wq = NULL;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 004/154] ksmbd: remove md4 leftovers
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (2 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 003/154] ksmbd: Remove redundant 'flush_workqueue()' calls Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 005/154] ksmbd: remove smb2_buf_length in smb2_hdr Namjae Jeon
` (150 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Hyunchul Lee, Steve French
[ Upstream commit 561a1cf57535154f094f31167a9170197caae686 ]
As NTLM authentication is removed, md4 is no longer used.
ksmbd remove md4 leftovers, i.e. select CRYPTO_MD4, MODULE_SOFTDEP md4.
Acked-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/Kconfig | 1 -
fs/ksmbd/server.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/fs/ksmbd/Kconfig b/fs/ksmbd/Kconfig
index 6af339cfdc04..e1fe17747ed6 100644
--- a/fs/ksmbd/Kconfig
+++ b/fs/ksmbd/Kconfig
@@ -6,7 +6,6 @@ config SMB_SERVER
select NLS
select NLS_UTF8
select CRYPTO
- select CRYPTO_MD4
select CRYPTO_MD5
select CRYPTO_HMAC
select CRYPTO_ECB
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index eb45d56b3577..bca0fbf3c67c 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -628,7 +628,6 @@ MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: ecb");
MODULE_SOFTDEP("pre: hmac");
-MODULE_SOFTDEP("pre: md4");
MODULE_SOFTDEP("pre: md5");
MODULE_SOFTDEP("pre: nls");
MODULE_SOFTDEP("pre: aes");
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 005/154] ksmbd: remove smb2_buf_length in smb2_hdr
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (3 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 004/154] ksmbd: remove md4 leftovers Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 006/154] ksmbd: remove smb2_buf_length in smb2_transform_hdr Namjae Jeon
` (149 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Ronnie Sahlberg, Steve French
[ Upstream commit cb4517201b8acdb5fd5314494aaf86c267f22345 ]
To move smb2_hdr to smbfs_common, This patch remove smb2_buf_length
variable in smb2_hdr. Also, declare smb2_get_msg function to get smb2
request/response from ->request/response_buf.
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 4 +-
fs/ksmbd/connection.c | 9 +-
fs/ksmbd/ksmbd_work.h | 4 +-
fs/ksmbd/oplock.c | 24 +--
fs/ksmbd/smb2pdu.c | 435 +++++++++++++++++++-------------------
fs/ksmbd/smb2pdu.h | 20 +-
fs/ksmbd/smb_common.c | 11 +-
fs/ksmbd/smb_common.h | 6 -
fs/ksmbd/transport_rdma.c | 2 +-
9 files changed, 256 insertions(+), 259 deletions(-)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index 59d205946746..3258a3176c06 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -884,9 +884,9 @@ int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
__u8 *pi_hash)
{
int rc;
- struct smb2_hdr *rcv_hdr = (struct smb2_hdr *)buf;
+ struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
- int msg_size = be32_to_cpu(rcv_hdr->smb2_buf_length);
+ int msg_size = get_rfc1002_len(buf);
struct ksmbd_crypto_ctx *ctx = NULL;
if (conn->preauth_info->Preauth_HashId !=
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index cab274b77727..e4af77581c2f 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -160,14 +160,13 @@ void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
int ksmbd_conn_write(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb_hdr *rsp_hdr = work->response_buf;
size_t len = 0;
int sent;
struct kvec iov[3];
int iov_idx = 0;
ksmbd_conn_try_dequeue_request(work);
- if (!rsp_hdr) {
+ if (!work->response_buf) {
pr_err("NULL response header\n");
return -EINVAL;
}
@@ -179,7 +178,7 @@ int ksmbd_conn_write(struct ksmbd_work *work)
}
if (work->aux_payload_sz) {
- iov[iov_idx] = (struct kvec) { rsp_hdr, work->resp_hdr_sz };
+ iov[iov_idx] = (struct kvec) { work->response_buf, work->resp_hdr_sz };
len += iov[iov_idx++].iov_len;
iov[iov_idx] = (struct kvec) { work->aux_payload_buf, work->aux_payload_sz };
len += iov[iov_idx++].iov_len;
@@ -187,8 +186,8 @@ int ksmbd_conn_write(struct ksmbd_work *work)
if (work->tr_buf)
iov[iov_idx].iov_len = work->resp_hdr_sz;
else
- iov[iov_idx].iov_len = get_rfc1002_len(rsp_hdr) + 4;
- iov[iov_idx].iov_base = rsp_hdr;
+ iov[iov_idx].iov_len = get_rfc1002_len(work->response_buf) + 4;
+ iov[iov_idx].iov_base = work->response_buf;
len += iov[iov_idx++].iov_len;
}
diff --git a/fs/ksmbd/ksmbd_work.h b/fs/ksmbd/ksmbd_work.h
index f7156bc50049..5ece58e40c97 100644
--- a/fs/ksmbd/ksmbd_work.h
+++ b/fs/ksmbd/ksmbd_work.h
@@ -92,7 +92,7 @@ struct ksmbd_work {
*/
static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
{
- return work->response_buf + work->next_smb2_rsp_hdr_off;
+ return work->response_buf + work->next_smb2_rsp_hdr_off + 4;
}
/**
@@ -101,7 +101,7 @@ static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
*/
static inline void *ksmbd_req_buf_next(struct ksmbd_work *work)
{
- return work->request_buf + work->next_smb2_rcv_hdr_off;
+ return work->request_buf + work->next_smb2_rcv_hdr_off + 4;
}
struct ksmbd_work *ksmbd_alloc_work_struct(void);
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index 9722e5237799..e57b2aa71815 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -630,10 +630,10 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
return;
}
- rsp_hdr = work->response_buf;
+ rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->smb2_buf_length =
- cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
@@ -646,7 +646,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
- rsp = work->response_buf;
+ rsp = smb2_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(24);
if (!br_info->open_trunc &&
@@ -660,7 +660,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp->PersistentFid = cpu_to_le64(fp->persistent_id);
rsp->VolatileFid = cpu_to_le64(fp->volatile_id);
- inc_rfc1001_len(rsp, 24);
+ inc_rfc1001_len(work->response_buf, 24);
ksmbd_debug(OPLOCK,
"sending oplock break v_id %llu p_id = %llu lock level = %d\n",
@@ -737,10 +737,10 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
return;
}
- rsp_hdr = work->response_buf;
+ rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->smb2_buf_length =
- cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
@@ -753,7 +753,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
- rsp = work->response_buf;
+ rsp = smb2_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(44);
rsp->Epoch = br_info->epoch;
rsp->Flags = 0;
@@ -769,7 +769,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp->AccessMaskHint = 0;
rsp->ShareMaskHint = 0;
- inc_rfc1001_len(rsp, 44);
+ inc_rfc1001_len(work->response_buf, 44);
ksmbd_conn_write(work);
ksmbd_free_work_struct(work);
@@ -1399,7 +1399,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
if (!lreq)
return NULL;
- data_offset = (char *)req + 4 + le32_to_cpu(req->CreateContextsOffset);
+ data_offset = (char *)req + le32_to_cpu(req->CreateContextsOffset);
cc = (struct create_context *)data_offset;
do {
cc = (struct create_context *)((char *)cc + next);
@@ -1464,7 +1464,7 @@ struct create_context *smb2_find_context_vals(void *open_req, const char *tag, i
* CreateContextsOffset and CreateContextsLength are guaranteed to
* be valid because of ksmbd_smb2_check_message().
*/
- cc = (struct create_context *)((char *)req + 4 +
+ cc = (struct create_context *)((char *)req +
le32_to_cpu(req->CreateContextsOffset));
remain_len = le32_to_cpu(req->CreateContextsLength);
do {
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d41ff22d07f2..2f04b90c8c2b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -45,8 +45,8 @@ static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
*req = ksmbd_req_buf_next(work);
*rsp = ksmbd_resp_buf_next(work);
} else {
- *req = work->request_buf;
- *rsp = work->response_buf;
+ *req = smb2_get_msg(work->request_buf);
+ *rsp = smb2_get_msg(work->response_buf);
}
}
@@ -94,7 +94,7 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn
*/
int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
{
- struct smb2_hdr *req_hdr = work->request_buf;
+ struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
unsigned int cmd = le16_to_cpu(req_hdr->Command);
int tree_id;
@@ -149,7 +149,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off)
err_rsp = ksmbd_resp_buf_next(work);
else
- err_rsp = work->response_buf;
+ err_rsp = smb2_get_msg(work->response_buf);
if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE;
@@ -169,7 +169,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
*/
bool is_smb2_neg_cmd(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = work->request_buf;
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
/* is it SMB2 header ? */
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -193,7 +193,7 @@ bool is_smb2_neg_cmd(struct ksmbd_work *work)
*/
bool is_smb2_rsp(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = work->response_buf;
+ struct smb2_hdr *hdr = smb2_get_msg(work->response_buf);
/* is it SMB2 header ? */
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -219,7 +219,7 @@ u16 get_smb2_cmd_val(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off)
rcv_hdr = ksmbd_req_buf_next(work);
else
- rcv_hdr = work->request_buf;
+ rcv_hdr = smb2_get_msg(work->request_buf);
return le16_to_cpu(rcv_hdr->Command);
}
@@ -235,7 +235,7 @@ void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
if (work->next_smb2_rcv_hdr_off)
rsp_hdr = ksmbd_resp_buf_next(work);
else
- rsp_hdr = work->response_buf;
+ rsp_hdr = smb2_get_msg(work->response_buf);
rsp_hdr->Status = err;
smb2_set_err_rsp(work);
}
@@ -256,13 +256,11 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
if (conn->need_neg == false)
return -EINVAL;
- rsp_hdr = work->response_buf;
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
+ rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
-
- rsp_hdr->smb2_buf_length =
- cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
-
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(2);
@@ -275,7 +273,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
- rsp = work->response_buf;
+ rsp = smb2_get_msg(work->response_buf);
WARN_ON(ksmbd_conn_good(work));
@@ -296,12 +294,12 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp->SecurityBufferOffset = cpu_to_le16(128);
rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
- ksmbd_copy_gss_neg_header(((char *)(&rsp->hdr) +
- sizeof(rsp->hdr.smb2_buf_length)) +
+ ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
le16_to_cpu(rsp->SecurityBufferOffset));
- inc_rfc1001_len(rsp, sizeof(struct smb2_negotiate_rsp) -
- sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
- AUTH_GSS_LENGTH);
+ inc_rfc1001_len(work->response_buf,
+ sizeof(struct smb2_negotiate_rsp) -
+ sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
+ AUTH_GSS_LENGTH);
rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY)
rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
@@ -407,8 +405,8 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
next_hdr_offset = le32_to_cpu(req->NextCommand);
new_len = ALIGN(len, 8);
- inc_rfc1001_len(work->response_buf, ((sizeof(struct smb2_hdr) - 4)
- + new_len - len));
+ inc_rfc1001_len(work->response_buf,
+ sizeof(struct smb2_hdr) + new_len - len);
rsp->NextCommand = cpu_to_le32(new_len);
work->next_smb2_rcv_hdr_off += next_hdr_offset;
@@ -426,7 +424,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
work->compound_fid = KSMBD_NO_FID;
work->compound_pfid = KSMBD_NO_FID;
}
- memset((char *)rsp_hdr + 4, 0, sizeof(struct smb2_hdr) + 2);
+ memset((char *)rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->Command = rcv_hdr->Command;
@@ -452,7 +450,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
*/
bool is_chained_smb2_message(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = work->request_buf;
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
unsigned int len, next_cmd;
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -503,13 +501,13 @@ bool is_chained_smb2_message(struct ksmbd_work *work)
*/
int init_smb2_rsp_hdr(struct ksmbd_work *work)
{
- struct smb2_hdr *rsp_hdr = work->response_buf;
- struct smb2_hdr *rcv_hdr = work->request_buf;
+ struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf);
+ struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf);
struct ksmbd_conn *conn = work->conn;
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->smb2_buf_length =
- cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->Command = rcv_hdr->Command;
@@ -542,7 +540,7 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
*/
int smb2_allocate_rsp_buf(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = work->request_buf;
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
size_t large_sz = small_sz + work->conn->vals->max_trans_size;
size_t sz = small_sz;
@@ -554,7 +552,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
if (cmd == SMB2_QUERY_INFO_HE) {
struct smb2_query_info_req *req;
- req = work->request_buf;
+ req = smb2_get_msg(work->request_buf);
if ((req->InfoType == SMB2_O_INFO_FILE &&
(req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
req->FileInfoClass == FILE_ALL_INFORMATION)) ||
@@ -582,7 +580,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
*/
int smb2_check_user_session(struct ksmbd_work *work)
{
- struct smb2_hdr *req_hdr = work->request_buf;
+ struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
struct ksmbd_conn *conn = work->conn;
unsigned int cmd = conn->ops->get_cmd_val(work);
unsigned long long sess_id;
@@ -683,7 +681,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
struct ksmbd_conn *conn = work->conn;
int id;
- rsp_hdr = work->response_buf;
+ rsp_hdr = smb2_get_msg(work->response_buf);
rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
id = ksmbd_acquire_async_msg_id(&conn->async_ida);
@@ -715,7 +713,7 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
{
struct smb2_hdr *rsp_hdr;
- rsp_hdr = work->response_buf;
+ rsp_hdr = smb2_get_msg(work->response_buf);
smb2_set_err_rsp(work);
rsp_hdr->Status = status;
@@ -843,11 +841,11 @@ static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
}
static void assemble_neg_contexts(struct ksmbd_conn *conn,
- struct smb2_negotiate_rsp *rsp)
+ struct smb2_negotiate_rsp *rsp,
+ void *smb2_buf_len)
{
- /* +4 is to account for the RFC1001 len field */
char *pneg_ctxt = (char *)rsp +
- le32_to_cpu(rsp->NegotiateContextOffset) + 4;
+ le32_to_cpu(rsp->NegotiateContextOffset);
int neg_ctxt_cnt = 1;
int ctxt_size;
@@ -856,7 +854,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt,
conn->preauth_info->Preauth_HashId);
rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
- inc_rfc1001_len(rsp, AUTH_GSS_PADDING);
+ inc_rfc1001_len(smb2_buf_len, AUTH_GSS_PADDING);
ctxt_size = sizeof(struct smb2_preauth_neg_context);
/* Round to 8 byte boundary */
pneg_ctxt += round_up(sizeof(struct smb2_preauth_neg_context), 8);
@@ -910,7 +908,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
ctxt_size += sizeof(struct smb2_signing_capabilities) + 2;
}
- inc_rfc1001_len(rsp, ctxt_size);
+ inc_rfc1001_len(smb2_buf_len, ctxt_size);
}
static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
@@ -1012,14 +1010,14 @@ static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
}
static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
- struct smb2_negotiate_req *req)
+ struct smb2_negotiate_req *req,
+ int len_of_smb)
{
/* +4 is to account for the RFC1001 len field */
- struct smb2_neg_context *pctx = (struct smb2_neg_context *)((char *)req + 4);
+ struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
int i = 0, len_of_ctxts;
int offset = le32_to_cpu(req->NegotiateContextOffset);
int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
- int len_of_smb = be32_to_cpu(req->hdr.smb2_buf_length);
__le32 status = STATUS_INVALID_PARAMETER;
ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
@@ -1104,8 +1102,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
int smb2_handle_negotiate(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_negotiate_req *req = work->request_buf;
- struct smb2_negotiate_rsp *rsp = work->response_buf;
+ struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf);
int rc = 0;
unsigned int smb2_buf_len, smb2_neg_size;
__le32 status;
@@ -1119,7 +1117,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
}
smb2_buf_len = get_rfc1002_len(work->request_buf);
- smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects) - 4;
+ smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
if (smb2_neg_size > smb2_buf_len) {
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
rc = -EINVAL;
@@ -1175,7 +1173,8 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
goto err_out;
}
- status = deassemble_neg_contexts(conn, req);
+ status = deassemble_neg_contexts(conn, req,
+ get_rfc1002_len(work->request_buf));
if (status != STATUS_SUCCESS) {
pr_err("deassemble_neg_contexts error(0x%x)\n",
status);
@@ -1199,7 +1198,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
conn->preauth_info->Preauth_HashValue);
rsp->NegotiateContextOffset =
cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
- assemble_neg_contexts(conn, rsp);
+ assemble_neg_contexts(conn, rsp, work->response_buf);
break;
case SMB302_PROT_ID:
init_smb3_02_server(conn);
@@ -1247,10 +1246,9 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
rsp->SecurityBufferOffset = cpu_to_le16(128);
rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
- ksmbd_copy_gss_neg_header(((char *)(&rsp->hdr) +
- sizeof(rsp->hdr.smb2_buf_length)) +
- le16_to_cpu(rsp->SecurityBufferOffset));
- inc_rfc1001_len(rsp, sizeof(struct smb2_negotiate_rsp) -
+ ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
+ le16_to_cpu(rsp->SecurityBufferOffset));
+ inc_rfc1001_len(work->response_buf, sizeof(struct smb2_negotiate_rsp) -
sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
AUTH_GSS_LENGTH);
rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
@@ -1342,7 +1340,7 @@ static int ntlm_negotiate(struct ksmbd_work *work,
struct negotiate_message *negblob,
size_t negblob_len)
{
- struct smb2_sess_setup_rsp *rsp = work->response_buf;
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct challenge_message *chgblob;
unsigned char *spnego_blob = NULL;
u16 spnego_blob_len;
@@ -1449,8 +1447,8 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
static int ntlm_authenticate(struct ksmbd_work *work)
{
- struct smb2_sess_setup_req *req = work->request_buf;
- struct smb2_sess_setup_rsp *rsp = work->response_buf;
+ struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
struct channel *chann = NULL;
@@ -1473,7 +1471,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
kfree(spnego_blob);
- inc_rfc1001_len(rsp, spnego_blob_len - 1);
+ inc_rfc1001_len(work->response_buf, spnego_blob_len - 1);
}
user = session_user(conn, req);
@@ -1590,8 +1588,8 @@ static int ntlm_authenticate(struct ksmbd_work *work)
#ifdef CONFIG_SMB_SERVER_KERBEROS5
static int krb5_authenticate(struct ksmbd_work *work)
{
- struct smb2_sess_setup_req *req = work->request_buf;
- struct smb2_sess_setup_rsp *rsp = work->response_buf;
+ struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
char *in_blob, *out_blob;
@@ -1606,8 +1604,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
out_blob = (char *)&rsp->hdr.ProtocolId +
le16_to_cpu(rsp->SecurityBufferOffset);
out_len = work->response_sz -
- offsetof(struct smb2_hdr, smb2_buf_length) -
- le16_to_cpu(rsp->SecurityBufferOffset);
+ (le16_to_cpu(rsp->SecurityBufferOffset) + 4);
/* Check previous session */
prev_sess_id = le64_to_cpu(req->PreviousSessionId);
@@ -1624,7 +1621,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
return -EINVAL;
}
rsp->SecurityBufferLength = cpu_to_le16(out_len);
- inc_rfc1001_len(rsp, out_len - 1);
+ inc_rfc1001_len(work->response_buf, out_len - 1);
if ((conn->sign || server_conf.enforced_signing) ||
(req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
@@ -1683,8 +1680,8 @@ static int krb5_authenticate(struct ksmbd_work *work)
int smb2_sess_setup(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_sess_setup_req *req = work->request_buf;
- struct smb2_sess_setup_rsp *rsp = work->response_buf;
+ struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess;
struct negotiate_message *negblob;
unsigned int negblob_len, negblob_off;
@@ -1696,7 +1693,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
rsp->SessionFlags = 0;
rsp->SecurityBufferOffset = cpu_to_le16(72);
rsp->SecurityBufferLength = 0;
- inc_rfc1001_len(rsp, 9);
+ inc_rfc1001_len(work->response_buf, 9);
if (!req->hdr.SessionId) {
sess = ksmbd_smb2_session_create();
@@ -1777,7 +1774,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
negblob_off = le16_to_cpu(req->SecurityBufferOffset);
negblob_len = le16_to_cpu(req->SecurityBufferLength);
- if (negblob_off < (offsetof(struct smb2_sess_setup_req, Buffer) - 4) ||
+ if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) ||
negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) {
rc = -EINVAL;
goto out_err;
@@ -1819,7 +1816,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
* Note: here total size -1 is done as an
* adjustment for 0 size blob
*/
- inc_rfc1001_len(rsp, le16_to_cpu(rsp->SecurityBufferLength) - 1);
+ inc_rfc1001_len(work->response_buf,
+ le16_to_cpu(rsp->SecurityBufferLength) - 1);
} else if (negblob->MessageType == NtLmAuthenticate) {
rc = ntlm_authenticate(work);
@@ -1915,8 +1913,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
int smb2_tree_connect(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_tree_connect_req *req = work->request_buf;
- struct smb2_tree_connect_rsp *rsp = work->response_buf;
+ struct smb2_tree_connect_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_tree_connect_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess = work->sess;
char *treename = NULL, *name = NULL;
struct ksmbd_tree_conn_status status;
@@ -1981,7 +1979,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
rsp->Reserved = 0;
/* default manual caching */
rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
- inc_rfc1001_len(rsp, 16);
+ inc_rfc1001_len(work->response_buf, 16);
if (!IS_ERR(treename))
kfree(treename);
@@ -2087,17 +2085,18 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
*/
int smb2_tree_disconnect(struct ksmbd_work *work)
{
- struct smb2_tree_disconnect_rsp *rsp = work->response_buf;
+ struct smb2_tree_disconnect_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess = work->sess;
struct ksmbd_tree_connect *tcon = work->tcon;
rsp->StructureSize = cpu_to_le16(4);
- inc_rfc1001_len(rsp, 4);
+ inc_rfc1001_len(work->response_buf, 4);
ksmbd_debug(SMB, "request\n");
if (!tcon) {
- struct smb2_tree_disconnect_req *req = work->request_buf;
+ struct smb2_tree_disconnect_req *req =
+ smb2_get_msg(work->request_buf);
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -2120,11 +2119,11 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_logoff_rsp *rsp = work->response_buf;
+ struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess = work->sess;
rsp->StructureSize = cpu_to_le16(4);
- inc_rfc1001_len(rsp, 4);
+ inc_rfc1001_len(work->response_buf, 4);
ksmbd_debug(SMB, "request\n");
@@ -2134,7 +2133,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_conn_wait_idle(conn);
if (ksmbd_tree_conn_session_logoff(sess)) {
- struct smb2_logoff_req *req = work->request_buf;
+ struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -2161,8 +2160,8 @@ int smb2_session_logoff(struct ksmbd_work *work)
*/
static noinline int create_smb2_pipe(struct ksmbd_work *work)
{
- struct smb2_create_rsp *rsp = work->response_buf;
- struct smb2_create_req *req = work->request_buf;
+ struct smb2_create_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_create_req *req = smb2_get_msg(work->request_buf);
int id;
int err;
char *name;
@@ -2200,7 +2199,7 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
- inc_rfc1001_len(rsp, 88); /* StructureSize - 1*/
+ inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
kfree(name);
return 0;
@@ -2556,7 +2555,7 @@ int smb2_open(struct ksmbd_work *work)
struct ksmbd_session *sess = work->sess;
struct ksmbd_tree_connect *tcon = work->tcon;
struct smb2_create_req *req;
- struct smb2_create_rsp *rsp, *rsp_org;
+ struct smb2_create_rsp *rsp;
struct path path;
struct ksmbd_share_config *share = tcon->share_conf;
struct ksmbd_file *fp = NULL;
@@ -2582,7 +2581,6 @@ int smb2_open(struct ksmbd_work *work)
umode_t posix_mode = 0;
__le32 daccess, maximal_access = 0;
- rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off &&
@@ -3240,7 +3238,7 @@ int smb2_open(struct ksmbd_work *work)
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
- inc_rfc1001_len(rsp_org, 88); /* StructureSize - 1*/
+ inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
/* If lease is request send lease context response */
if (opinfo && opinfo->is_lease) {
@@ -3255,7 +3253,8 @@ int smb2_open(struct ksmbd_work *work)
create_lease_buf(rsp->Buffer, opinfo->o_lease);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_lease_size);
- inc_rfc1001_len(rsp_org, conn->vals->create_lease_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_lease_size);
next_ptr = &lease_ccontext->Next;
next_off = conn->vals->create_lease_size;
}
@@ -3275,7 +3274,8 @@ int smb2_open(struct ksmbd_work *work)
le32_to_cpu(maximal_access));
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_mxac_size);
- inc_rfc1001_len(rsp_org, conn->vals->create_mxac_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_mxac_size);
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
next_ptr = &mxac_ccontext->Next;
@@ -3293,7 +3293,8 @@ int smb2_open(struct ksmbd_work *work)
stat.ino, tcon->id);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_disk_id_size);
- inc_rfc1001_len(rsp_org, conn->vals->create_disk_id_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_disk_id_size);
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
next_ptr = &disk_id_ccontext->Next;
@@ -3307,15 +3308,15 @@ int smb2_open(struct ksmbd_work *work)
fp);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_posix_size);
- inc_rfc1001_len(rsp_org, conn->vals->create_posix_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_posix_size);
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
}
if (contxt_cnt > 0) {
rsp->CreateContextsOffset =
- cpu_to_le32(offsetof(struct smb2_create_rsp, Buffer)
- - 4);
+ cpu_to_le32(offsetof(struct smb2_create_rsp, Buffer));
}
err_out:
@@ -3918,7 +3919,7 @@ int smb2_query_dir(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_query_directory_req *req;
- struct smb2_query_directory_rsp *rsp, *rsp_org;
+ struct smb2_query_directory_rsp *rsp;
struct ksmbd_share_config *share = work->tcon->share_conf;
struct ksmbd_file *dir_fp = NULL;
struct ksmbd_dir_info d_info;
@@ -3928,7 +3929,6 @@ int smb2_query_dir(struct ksmbd_work *work)
int buffer_sz;
struct smb2_query_dir_private query_dir_private = {NULL, };
- rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (ksmbd_override_fsids(work)) {
@@ -4052,7 +4052,7 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->OutputBufferOffset = cpu_to_le16(0);
rsp->OutputBufferLength = cpu_to_le32(0);
rsp->Buffer[0] = 0;
- inc_rfc1001_len(rsp_org, 9);
+ inc_rfc1001_len(work->response_buf, 9);
} else {
no_buf_len:
((struct file_directory_info *)
@@ -4064,7 +4064,7 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72);
rsp->OutputBufferLength = cpu_to_le32(d_info.data_count);
- inc_rfc1001_len(rsp_org, 8 + d_info.data_count);
+ inc_rfc1001_len(work->response_buf, 8 + d_info.data_count);
}
kfree(srch_ptr);
@@ -4109,26 +4109,28 @@ int smb2_query_dir(struct ksmbd_work *work)
* Return: 0 on success, otherwise error
*/
static int buffer_check_err(int reqOutputBufferLength,
- struct smb2_query_info_rsp *rsp, int infoclass_size)
+ struct smb2_query_info_rsp *rsp,
+ void *rsp_org, int infoclass_size)
{
if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) {
if (reqOutputBufferLength < infoclass_size) {
pr_err("Invalid Buffer Size Requested\n");
rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
- rsp->hdr.smb2_buf_length = cpu_to_be32(sizeof(struct smb2_hdr) - 4);
+ *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr));
return -EINVAL;
}
ksmbd_debug(SMB, "Buffer Overflow\n");
rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
- rsp->hdr.smb2_buf_length = cpu_to_be32(sizeof(struct smb2_hdr) - 4 +
+ *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr) +
reqOutputBufferLength);
rsp->OutputBufferLength = cpu_to_le32(reqOutputBufferLength);
}
return 0;
}
-static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp)
+static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp,
+ void *rsp_org)
{
struct smb2_file_standard_info *sinfo;
@@ -4141,10 +4143,11 @@ static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp)
sinfo->Directory = 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_standard_info));
- inc_rfc1001_len(rsp, sizeof(struct smb2_file_standard_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_standard_info));
}
-static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num)
+static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
+ void *rsp_org)
{
struct smb2_file_internal_info *file_info;
@@ -4154,12 +4157,13 @@ static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num)
file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63));
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_internal_info));
- inc_rfc1001_len(rsp, sizeof(struct smb2_file_internal_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
}
static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp)
+ struct smb2_query_info_rsp *rsp,
+ void *rsp_org)
{
u64 id;
int rc;
@@ -4177,14 +4181,16 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
switch (req->FileInfoClass) {
case FILE_STANDARD_INFORMATION:
- get_standard_info_pipe(rsp);
+ get_standard_info_pipe(rsp, rsp_org);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, FILE_STANDARD_INFORMATION_SIZE);
+ rsp, rsp_org,
+ FILE_STANDARD_INFORMATION_SIZE);
break;
case FILE_INTERNAL_INFORMATION:
- get_internal_info_pipe(rsp, id);
+ get_internal_info_pipe(rsp, id, rsp_org);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, FILE_INTERNAL_INFORMATION_SIZE);
+ rsp, rsp_org,
+ FILE_INTERNAL_INFORMATION_SIZE);
break;
default:
ksmbd_debug(SMB, "smb2_info_file_pipe for %u not supported\n",
@@ -4785,7 +4791,7 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
static int smb2_get_info_file(struct ksmbd_work *work,
struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp, void *rsp_org)
+ struct smb2_query_info_rsp *rsp)
{
struct ksmbd_file *fp;
int fileinfoclass = 0;
@@ -4796,7 +4802,8 @@ static int smb2_get_info_file(struct ksmbd_work *work,
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_PIPE)) {
/* smb2 info file called for pipe */
- return smb2_get_info_file_pipe(work->sess, req, rsp);
+ return smb2_get_info_file_pipe(work->sess, req, rsp,
+ work->response_buf);
}
if (work->next_smb2_rcv_hdr_off) {
@@ -4821,77 +4828,77 @@ static int smb2_get_info_file(struct ksmbd_work *work,
switch (fileinfoclass) {
case FILE_ACCESS_INFORMATION:
- get_file_access_info(rsp, fp, rsp_org);
+ get_file_access_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_ACCESS_INFORMATION_SIZE;
break;
case FILE_BASIC_INFORMATION:
- rc = get_file_basic_info(rsp, fp, rsp_org);
+ rc = get_file_basic_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_BASIC_INFORMATION_SIZE;
break;
case FILE_STANDARD_INFORMATION:
- get_file_standard_info(rsp, fp, rsp_org);
+ get_file_standard_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_STANDARD_INFORMATION_SIZE;
break;
case FILE_ALIGNMENT_INFORMATION:
- get_file_alignment_info(rsp, rsp_org);
+ get_file_alignment_info(rsp, work->response_buf);
file_infoclass_size = FILE_ALIGNMENT_INFORMATION_SIZE;
break;
case FILE_ALL_INFORMATION:
- rc = get_file_all_info(work, rsp, fp, rsp_org);
+ rc = get_file_all_info(work, rsp, fp, work->response_buf);
file_infoclass_size = FILE_ALL_INFORMATION_SIZE;
break;
case FILE_ALTERNATE_NAME_INFORMATION:
- get_file_alternate_info(work, rsp, fp, rsp_org);
+ get_file_alternate_info(work, rsp, fp, work->response_buf);
file_infoclass_size = FILE_ALTERNATE_NAME_INFORMATION_SIZE;
break;
case FILE_STREAM_INFORMATION:
- get_file_stream_info(work, rsp, fp, rsp_org);
+ get_file_stream_info(work, rsp, fp, work->response_buf);
file_infoclass_size = FILE_STREAM_INFORMATION_SIZE;
break;
case FILE_INTERNAL_INFORMATION:
- get_file_internal_info(rsp, fp, rsp_org);
+ get_file_internal_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_INTERNAL_INFORMATION_SIZE;
break;
case FILE_NETWORK_OPEN_INFORMATION:
- rc = get_file_network_open_info(rsp, fp, rsp_org);
+ rc = get_file_network_open_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_NETWORK_OPEN_INFORMATION_SIZE;
break;
case FILE_EA_INFORMATION:
- get_file_ea_info(rsp, rsp_org);
+ get_file_ea_info(rsp, work->response_buf);
file_infoclass_size = FILE_EA_INFORMATION_SIZE;
break;
case FILE_FULL_EA_INFORMATION:
- rc = smb2_get_ea(work, fp, req, rsp, rsp_org);
+ rc = smb2_get_ea(work, fp, req, rsp, work->response_buf);
file_infoclass_size = FILE_FULL_EA_INFORMATION_SIZE;
break;
case FILE_POSITION_INFORMATION:
- get_file_position_info(rsp, fp, rsp_org);
+ get_file_position_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_POSITION_INFORMATION_SIZE;
break;
case FILE_MODE_INFORMATION:
- get_file_mode_info(rsp, fp, rsp_org);
+ get_file_mode_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_MODE_INFORMATION_SIZE;
break;
case FILE_COMPRESSION_INFORMATION:
- get_file_compression_info(rsp, fp, rsp_org);
+ get_file_compression_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_COMPRESSION_INFORMATION_SIZE;
break;
case FILE_ATTRIBUTE_TAG_INFORMATION:
- rc = get_file_attribute_tag_info(rsp, fp, rsp_org);
+ rc = get_file_attribute_tag_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_ATTRIBUTE_TAG_INFORMATION_SIZE;
break;
case SMB_FIND_FILE_POSIX_INFO:
@@ -4899,7 +4906,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
rc = -EOPNOTSUPP;
} else {
- rc = find_file_posix_info(rsp, fp, rsp_org);
+ rc = find_file_posix_info(rsp, fp, work->response_buf);
file_infoclass_size = sizeof(struct smb311_posix_qinfo);
}
break;
@@ -4910,7 +4917,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
}
if (!rc)
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp,
+ rsp, work->response_buf,
file_infoclass_size);
ksmbd_fd_put(work, fp);
return rc;
@@ -4918,7 +4925,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
static int smb2_get_info_filesystem(struct ksmbd_work *work,
struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp, void *rsp_org)
+ struct smb2_query_info_rsp *rsp)
{
struct ksmbd_session *sess = work->sess;
struct ksmbd_conn *conn = work->conn;
@@ -4957,7 +4964,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->DeviceType = cpu_to_le32(stfs.f_type);
info->DeviceCharacteristics = cpu_to_le32(0x00000020);
rsp->OutputBufferLength = cpu_to_le32(8);
- inc_rfc1001_len(rsp_org, 8);
+ inc_rfc1001_len(work->response_buf, 8);
fs_infoclass_size = FS_DEVICE_INFORMATION_SIZE;
break;
}
@@ -4987,7 +4994,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->FileSystemNameLen = cpu_to_le32(len);
sz = sizeof(struct filesystem_attribute_info) - 2 + len;
rsp->OutputBufferLength = cpu_to_le32(sz);
- inc_rfc1001_len(rsp_org, sz);
+ inc_rfc1001_len(work->response_buf, sz);
fs_infoclass_size = FS_ATTRIBUTE_INFORMATION_SIZE;
break;
}
@@ -5015,7 +5022,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->Reserved = 0;
sz = sizeof(struct filesystem_vol_info) - 2 + len;
rsp->OutputBufferLength = cpu_to_le32(sz);
- inc_rfc1001_len(rsp_org, sz);
+ inc_rfc1001_len(work->response_buf, sz);
fs_infoclass_size = FS_VOLUME_INFORMATION_SIZE;
break;
}
@@ -5029,7 +5036,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(24);
- inc_rfc1001_len(rsp_org, 24);
+ inc_rfc1001_len(work->response_buf, 24);
fs_infoclass_size = FS_SIZE_INFORMATION_SIZE;
break;
}
@@ -5046,7 +5053,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(32);
- inc_rfc1001_len(rsp_org, 32);
+ inc_rfc1001_len(work->response_buf, 32);
fs_infoclass_size = FS_FULL_SIZE_INFORMATION_SIZE;
break;
}
@@ -5067,7 +5074,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->extended_info.rel_date = 0;
memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0"));
rsp->OutputBufferLength = cpu_to_le32(64);
- inc_rfc1001_len(rsp_org, 64);
+ inc_rfc1001_len(work->response_buf, 64);
fs_infoclass_size = FS_OBJECT_ID_INFORMATION_SIZE;
break;
}
@@ -5090,7 +5097,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->ByteOffsetForSectorAlignment = 0;
info->ByteOffsetForPartitionAlignment = 0;
rsp->OutputBufferLength = cpu_to_le32(28);
- inc_rfc1001_len(rsp_org, 28);
+ inc_rfc1001_len(work->response_buf, 28);
fs_infoclass_size = FS_SECTOR_SIZE_INFORMATION_SIZE;
break;
}
@@ -5112,7 +5119,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID);
info->Padding = 0;
rsp->OutputBufferLength = cpu_to_le32(48);
- inc_rfc1001_len(rsp_org, 48);
+ inc_rfc1001_len(work->response_buf, 48);
fs_infoclass_size = FS_CONTROL_INFORMATION_SIZE;
break;
}
@@ -5133,7 +5140,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->TotalFileNodes = cpu_to_le64(stfs.f_files);
info->FreeFileNodes = cpu_to_le64(stfs.f_ffree);
rsp->OutputBufferLength = cpu_to_le32(56);
- inc_rfc1001_len(rsp_org, 56);
+ inc_rfc1001_len(work->response_buf, 56);
fs_infoclass_size = FS_POSIX_INFORMATION_SIZE;
}
break;
@@ -5143,7 +5150,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
return -EOPNOTSUPP;
}
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp,
+ rsp, work->response_buf,
fs_infoclass_size);
path_put(&path);
return rc;
@@ -5151,7 +5158,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
static int smb2_get_info_sec(struct ksmbd_work *work,
struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp, void *rsp_org)
+ struct smb2_query_info_rsp *rsp)
{
struct ksmbd_file *fp;
struct user_namespace *user_ns;
@@ -5178,7 +5185,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
secdesclen = sizeof(struct smb_ntsd);
rsp->OutputBufferLength = cpu_to_le32(secdesclen);
- inc_rfc1001_len(rsp_org, secdesclen);
+ inc_rfc1001_len(work->response_buf, secdesclen);
return 0;
}
@@ -5223,7 +5230,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
return rc;
rsp->OutputBufferLength = cpu_to_le32(secdesclen);
- inc_rfc1001_len(rsp_org, secdesclen);
+ inc_rfc1001_len(work->response_buf, secdesclen);
return 0;
}
@@ -5236,10 +5243,9 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
int smb2_query_info(struct ksmbd_work *work)
{
struct smb2_query_info_req *req;
- struct smb2_query_info_rsp *rsp, *rsp_org;
+ struct smb2_query_info_rsp *rsp;
int rc = 0;
- rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
ksmbd_debug(SMB, "GOT query info request\n");
@@ -5247,15 +5253,15 @@ int smb2_query_info(struct ksmbd_work *work)
switch (req->InfoType) {
case SMB2_O_INFO_FILE:
ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
- rc = smb2_get_info_file(work, req, rsp, (void *)rsp_org);
+ rc = smb2_get_info_file(work, req, rsp);
break;
case SMB2_O_INFO_FILESYSTEM:
ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILESYSTEM\n");
- rc = smb2_get_info_filesystem(work, req, rsp, (void *)rsp_org);
+ rc = smb2_get_info_filesystem(work, req, rsp);
break;
case SMB2_O_INFO_SECURITY:
ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
- rc = smb2_get_info_sec(work, req, rsp, (void *)rsp_org);
+ rc = smb2_get_info_sec(work, req, rsp);
break;
default:
ksmbd_debug(SMB, "InfoType %d not supported yet\n",
@@ -5280,7 +5286,7 @@ int smb2_query_info(struct ksmbd_work *work)
}
rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72);
- inc_rfc1001_len(rsp_org, 8);
+ inc_rfc1001_len(work->response_buf, 8);
return 0;
}
@@ -5293,8 +5299,8 @@ int smb2_query_info(struct ksmbd_work *work)
static noinline int smb2_close_pipe(struct ksmbd_work *work)
{
u64 id;
- struct smb2_close_req *req = work->request_buf;
- struct smb2_close_rsp *rsp = work->response_buf;
+ struct smb2_close_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_close_rsp *rsp = smb2_get_msg(work->response_buf);
id = le64_to_cpu(req->VolatileFileId);
ksmbd_session_rpc_close(work->sess, id);
@@ -5309,7 +5315,7 @@ static noinline int smb2_close_pipe(struct ksmbd_work *work)
rsp->AllocationSize = 0;
rsp->EndOfFile = 0;
rsp->Attributes = 0;
- inc_rfc1001_len(rsp, 60);
+ inc_rfc1001_len(work->response_buf, 60);
return 0;
}
@@ -5325,14 +5331,12 @@ int smb2_close(struct ksmbd_work *work)
u64 sess_id;
struct smb2_close_req *req;
struct smb2_close_rsp *rsp;
- struct smb2_close_rsp *rsp_org;
struct ksmbd_conn *conn = work->conn;
struct ksmbd_file *fp;
struct inode *inode;
u64 time;
int err = 0;
- rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (test_share_config_flag(work->tcon->share_conf,
@@ -5422,7 +5426,7 @@ int smb2_close(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_FILE_CLOSED;
smb2_set_err_rsp(work);
} else {
- inc_rfc1001_len(rsp_org, 60);
+ inc_rfc1001_len(work->response_buf, 60);
}
return 0;
@@ -5436,11 +5440,11 @@ int smb2_close(struct ksmbd_work *work)
*/
int smb2_echo(struct ksmbd_work *work)
{
- struct smb2_echo_rsp *rsp = work->response_buf;
+ struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(4);
rsp->Reserved = 0;
- inc_rfc1001_len(rsp, 4);
+ inc_rfc1001_len(work->response_buf, 4);
return 0;
}
@@ -6061,14 +6065,13 @@ static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
int smb2_set_info(struct ksmbd_work *work)
{
struct smb2_set_info_req *req;
- struct smb2_set_info_rsp *rsp, *rsp_org;
+ struct smb2_set_info_rsp *rsp;
struct ksmbd_file *fp;
int rc = 0;
unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
ksmbd_debug(SMB, "Received set info request\n");
- rsp_org = work->response_buf;
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work);
@@ -6079,8 +6082,8 @@ int smb2_set_info(struct ksmbd_work *work)
pid = work->compound_pfid;
}
} else {
- req = work->request_buf;
- rsp = work->response_buf;
+ req = smb2_get_msg(work->request_buf);
+ rsp = smb2_get_msg(work->response_buf);
}
if (!has_file_id(id)) {
@@ -6120,7 +6123,7 @@ int smb2_set_info(struct ksmbd_work *work)
goto err_out;
rsp->StructureSize = cpu_to_le16(2);
- inc_rfc1001_len(rsp_org, 2);
+ inc_rfc1001_len(work->response_buf, 2);
ksmbd_fd_put(work, fp);
return 0;
@@ -6160,12 +6163,12 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
int nbytes = 0, err;
u64 id;
struct ksmbd_rpc_command *rpc_resp;
- struct smb2_read_req *req = work->request_buf;
- struct smb2_read_rsp *rsp = work->response_buf;
+ struct smb2_read_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_read_rsp *rsp = smb2_get_msg(work->response_buf);
id = le64_to_cpu(req->VolatileFileId);
- inc_rfc1001_len(rsp, 16);
+ inc_rfc1001_len(work->response_buf, 16);
rpc_resp = ksmbd_rpc_read(work->sess, id);
if (rpc_resp) {
if (rpc_resp->flags != KSMBD_RPC_OK) {
@@ -6184,7 +6187,7 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
rpc_resp->payload_sz);
nbytes = rpc_resp->payload_sz;
- work->resp_hdr_sz = get_rfc1002_len(rsp) + 4;
+ work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
work->aux_payload_sz = nbytes;
kvfree(rpc_resp);
}
@@ -6195,7 +6198,7 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
- inc_rfc1001_len(rsp, nbytes);
+ inc_rfc1001_len(work->response_buf, nbytes);
return 0;
out:
@@ -6245,14 +6248,13 @@ int smb2_read(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_read_req *req;
- struct smb2_read_rsp *rsp, *rsp_org;
+ struct smb2_read_rsp *rsp;
struct ksmbd_file *fp = NULL;
loff_t offset;
size_t length, mincount;
ssize_t nbytes = 0, remain_bytes = 0;
int err = 0;
- rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (work->next_smb2_rcv_hdr_off) {
work->send_no_response = 1;
@@ -6339,10 +6341,10 @@ int smb2_read(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = cpu_to_le32(remain_bytes);
rsp->Reserved2 = 0;
- inc_rfc1001_len(rsp_org, 16);
- work->resp_hdr_sz = get_rfc1002_len(rsp_org) + 4;
+ inc_rfc1001_len(work->response_buf, 16);
+ work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
work->aux_payload_sz = nbytes;
- inc_rfc1001_len(rsp_org, nbytes);
+ inc_rfc1001_len(work->response_buf, nbytes);
ksmbd_fd_put(work, fp);
return 0;
@@ -6377,8 +6379,8 @@ int smb2_read(struct ksmbd_work *work)
*/
static noinline int smb2_write_pipe(struct ksmbd_work *work)
{
- struct smb2_write_req *req = work->request_buf;
- struct smb2_write_rsp *rsp = work->response_buf;
+ struct smb2_write_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_write_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_rpc_command *rpc_resp;
u64 id = 0;
int err = 0, ret = 0;
@@ -6389,13 +6391,14 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
id = le64_to_cpu(req->VolatileFileId);
if (le16_to_cpu(req->DataOffset) ==
- (offsetof(struct smb2_write_req, Buffer) - 4)) {
+ offsetof(struct smb2_write_req, Buffer)) {
data_buf = (char *)&req->Buffer[0];
} else {
- if ((u64)le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(req)) {
+ if ((u64)le16_to_cpu(req->DataOffset) + length >
+ get_rfc1002_len(work->request_buf)) {
pr_err("invalid write data offset %u, smb_len %u\n",
le16_to_cpu(req->DataOffset),
- get_rfc1002_len(req));
+ get_rfc1002_len(work->request_buf));
err = -EINVAL;
goto out;
}
@@ -6427,7 +6430,7 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(length);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
- inc_rfc1001_len(rsp, 16);
+ inc_rfc1001_len(work->response_buf, 16);
return 0;
out:
if (err) {
@@ -6495,7 +6498,7 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
int smb2_write(struct ksmbd_work *work)
{
struct smb2_write_req *req;
- struct smb2_write_rsp *rsp, *rsp_org;
+ struct smb2_write_rsp *rsp;
struct ksmbd_file *fp = NULL;
loff_t offset;
size_t length;
@@ -6504,7 +6507,6 @@ int smb2_write(struct ksmbd_work *work)
bool writethrough = false;
int err = 0;
- rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) {
@@ -6547,7 +6549,7 @@ int smb2_write(struct ksmbd_work *work)
if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
if (le16_to_cpu(req->DataOffset) ==
- (offsetof(struct smb2_write_req, Buffer) - 4)) {
+ offsetof(struct smb2_write_req, Buffer)) {
data_buf = (char *)&req->Buffer[0];
} else {
if (le16_to_cpu(req->DataOffset) <
@@ -6589,7 +6591,7 @@ int smb2_write(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
- inc_rfc1001_len(rsp_org, 16);
+ inc_rfc1001_len(work->response_buf, 16);
ksmbd_fd_put(work, fp);
return 0;
@@ -6623,10 +6625,9 @@ int smb2_write(struct ksmbd_work *work)
int smb2_flush(struct ksmbd_work *work)
{
struct smb2_flush_req *req;
- struct smb2_flush_rsp *rsp, *rsp_org;
+ struct smb2_flush_rsp *rsp;
int err;
- rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n",
@@ -6640,7 +6641,7 @@ int smb2_flush(struct ksmbd_work *work)
rsp->StructureSize = cpu_to_le16(4);
rsp->Reserved = 0;
- inc_rfc1001_len(rsp_org, 4);
+ inc_rfc1001_len(work->response_buf, 4);
return 0;
out:
@@ -6661,7 +6662,7 @@ int smb2_flush(struct ksmbd_work *work)
int smb2_cancel(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_hdr *hdr = work->request_buf;
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
struct smb2_hdr *chdr;
struct ksmbd_work *cancel_work = NULL;
int canceled = 0;
@@ -6676,7 +6677,7 @@ int smb2_cancel(struct ksmbd_work *work)
spin_lock(&conn->request_lock);
list_for_each_entry(cancel_work, command_list,
async_request_entry) {
- chdr = cancel_work->request_buf;
+ chdr = smb2_get_msg(cancel_work->request_buf);
if (cancel_work->async_id !=
le64_to_cpu(hdr->Id.AsyncId))
@@ -6695,7 +6696,7 @@ int smb2_cancel(struct ksmbd_work *work)
spin_lock(&conn->request_lock);
list_for_each_entry(cancel_work, command_list, request_entry) {
- chdr = cancel_work->request_buf;
+ chdr = smb2_get_msg(cancel_work->request_buf);
if (chdr->MessageId != hdr->MessageId ||
cancel_work == work)
@@ -6830,8 +6831,8 @@ static inline bool lock_defer_pending(struct file_lock *fl)
*/
int smb2_lock(struct ksmbd_work *work)
{
- struct smb2_lock_req *req = work->request_buf;
- struct smb2_lock_rsp *rsp = work->response_buf;
+ struct smb2_lock_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_lock_rsp *rsp = smb2_get_msg(work->response_buf);
struct smb2_lock_element *lock_ele;
struct ksmbd_file *fp = NULL;
struct file_lock *flock = NULL;
@@ -7138,7 +7139,7 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_debug(SMB, "successful in taking lock\n");
rsp->hdr.Status = STATUS_SUCCESS;
rsp->Reserved = 0;
- inc_rfc1001_len(rsp, 4);
+ inc_rfc1001_len(work->response_buf, 4);
ksmbd_fd_put(work, fp);
return 0;
@@ -7616,13 +7617,12 @@ static int fsctl_request_resume_key(struct ksmbd_work *work,
int smb2_ioctl(struct ksmbd_work *work)
{
struct smb2_ioctl_req *req;
- struct smb2_ioctl_rsp *rsp, *rsp_org;
+ struct smb2_ioctl_rsp *rsp;
unsigned int cnt_code, nbytes = 0, out_buf_len, in_buf_len;
u64 id = KSMBD_NO_FID;
struct ksmbd_conn *conn = work->conn;
int ret = 0;
- rsp_org = work->response_buf;
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work);
@@ -7632,8 +7632,8 @@ int smb2_ioctl(struct ksmbd_work *work)
id = work->compound_fid;
}
} else {
- req = work->request_buf;
- rsp = work->response_buf;
+ req = smb2_get_msg(work->request_buf);
+ rsp = smb2_get_msg(work->response_buf);
}
if (!has_file_id(id))
@@ -7935,7 +7935,7 @@ int smb2_ioctl(struct ksmbd_work *work)
rsp->Reserved = cpu_to_le16(0);
rsp->Flags = cpu_to_le32(0);
rsp->Reserved2 = cpu_to_le32(0);
- inc_rfc1001_len(rsp_org, 48 + nbytes);
+ inc_rfc1001_len(work->response_buf, 48 + nbytes);
return 0;
@@ -7962,8 +7962,8 @@ int smb2_ioctl(struct ksmbd_work *work)
*/
static void smb20_oplock_break_ack(struct ksmbd_work *work)
{
- struct smb2_oplock_break *req = work->request_buf;
- struct smb2_oplock_break *rsp = work->response_buf;
+ struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
+ struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_file *fp;
struct oplock_info *opinfo = NULL;
__le32 err = 0;
@@ -8070,7 +8070,7 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
rsp->Reserved2 = 0;
rsp->VolatileFid = cpu_to_le64(volatile_id);
rsp->PersistentFid = cpu_to_le64(persistent_id);
- inc_rfc1001_len(rsp, 24);
+ inc_rfc1001_len(work->response_buf, 24);
return;
err_out:
@@ -8106,8 +8106,8 @@ static int check_lease_state(struct lease *lease, __le32 req_state)
static void smb21_lease_break_ack(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_lease_ack *req = work->request_buf;
- struct smb2_lease_ack *rsp = work->response_buf;
+ struct smb2_lease_ack *req = smb2_get_msg(work->request_buf);
+ struct smb2_lease_ack *rsp = smb2_get_msg(work->response_buf);
struct oplock_info *opinfo;
__le32 err = 0;
int ret = 0;
@@ -8219,7 +8219,7 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
memcpy(rsp->LeaseKey, req->LeaseKey, 16);
rsp->LeaseState = lease_state;
rsp->LeaseDuration = 0;
- inc_rfc1001_len(rsp, 36);
+ inc_rfc1001_len(work->response_buf, 36);
return;
err_out:
@@ -8240,8 +8240,8 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
*/
int smb2_oplock_break(struct ksmbd_work *work)
{
- struct smb2_oplock_break *req = work->request_buf;
- struct smb2_oplock_break *rsp = work->response_buf;
+ struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
+ struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
switch (le16_to_cpu(req->StructureSize)) {
case OP_BREAK_STRUCT_SIZE_20:
@@ -8293,7 +8293,7 @@ int smb2_notify(struct ksmbd_work *work)
*/
bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
{
- struct smb2_hdr *rcv_hdr2 = work->request_buf;
+ struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf);
if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) &&
command != SMB2_NEGOTIATE_HE &&
@@ -8312,22 +8312,22 @@ bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
*/
int smb2_check_sign_req(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr, *hdr_org;
+ struct smb2_hdr *hdr;
char signature_req[SMB2_SIGNATURE_SIZE];
char signature[SMB2_HMACSHA256_SIZE];
struct kvec iov[1];
size_t len;
- hdr_org = hdr = work->request_buf;
+ hdr = smb2_get_msg(work->request_buf);
if (work->next_smb2_rcv_hdr_off)
hdr = ksmbd_req_buf_next(work);
if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
- len = be32_to_cpu(hdr_org->smb2_buf_length);
+ len = get_rfc1002_len(work->request_buf);
else if (hdr->NextCommand)
len = le32_to_cpu(hdr->NextCommand);
else
- len = be32_to_cpu(hdr_org->smb2_buf_length) -
+ len = get_rfc1002_len(work->request_buf) -
work->next_smb2_rcv_hdr_off;
memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
@@ -8355,25 +8355,26 @@ int smb2_check_sign_req(struct ksmbd_work *work)
*/
void smb2_set_sign_rsp(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr, *hdr_org;
+ struct smb2_hdr *hdr;
struct smb2_hdr *req_hdr;
char signature[SMB2_HMACSHA256_SIZE];
struct kvec iov[2];
size_t len;
int n_vec = 1;
- hdr_org = hdr = work->response_buf;
+ hdr = smb2_get_msg(work->response_buf);
if (work->next_smb2_rsp_hdr_off)
hdr = ksmbd_resp_buf_next(work);
req_hdr = ksmbd_req_buf_next(work);
if (!work->next_smb2_rsp_hdr_off) {
- len = get_rfc1002_len(hdr_org);
+ len = get_rfc1002_len(work->response_buf);
if (req_hdr->NextCommand)
len = ALIGN(len, 8);
} else {
- len = get_rfc1002_len(hdr_org) - work->next_smb2_rsp_hdr_off;
+ len = get_rfc1002_len(work->response_buf) -
+ work->next_smb2_rsp_hdr_off;
len = ALIGN(len, 8);
}
@@ -8409,23 +8410,23 @@ int smb3_check_sign_req(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
char *signing_key;
- struct smb2_hdr *hdr, *hdr_org;
+ struct smb2_hdr *hdr;
struct channel *chann;
char signature_req[SMB2_SIGNATURE_SIZE];
char signature[SMB2_CMACAES_SIZE];
struct kvec iov[1];
size_t len;
- hdr_org = hdr = work->request_buf;
+ hdr = smb2_get_msg(work->request_buf);
if (work->next_smb2_rcv_hdr_off)
hdr = ksmbd_req_buf_next(work);
if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
- len = be32_to_cpu(hdr_org->smb2_buf_length);
+ len = get_rfc1002_len(work->request_buf);
else if (hdr->NextCommand)
len = le32_to_cpu(hdr->NextCommand);
else
- len = be32_to_cpu(hdr_org->smb2_buf_length) -
+ len = get_rfc1002_len(work->request_buf) -
work->next_smb2_rcv_hdr_off;
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
@@ -8470,8 +8471,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
void smb3_set_sign_rsp(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_hdr *req_hdr;
- struct smb2_hdr *hdr, *hdr_org;
+ struct smb2_hdr *req_hdr, *hdr;
struct channel *chann;
char signature[SMB2_CMACAES_SIZE];
struct kvec iov[2];
@@ -8479,18 +8479,19 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
size_t len;
char *signing_key;
- hdr_org = hdr = work->response_buf;
+ hdr = smb2_get_msg(work->response_buf);
if (work->next_smb2_rsp_hdr_off)
hdr = ksmbd_resp_buf_next(work);
req_hdr = ksmbd_req_buf_next(work);
if (!work->next_smb2_rsp_hdr_off) {
- len = get_rfc1002_len(hdr_org);
+ len = get_rfc1002_len(work->response_buf);
if (req_hdr->NextCommand)
len = ALIGN(len, 8);
} else {
- len = get_rfc1002_len(hdr_org) - work->next_smb2_rsp_hdr_off;
+ len = get_rfc1002_len(work->response_buf) -
+ work->next_smb2_rsp_hdr_off;
len = ALIGN(len, 8);
}
@@ -8547,7 +8548,7 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE &&
conn->preauth_info)
- ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
+ ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
conn->preauth_info->Preauth_HashValue);
if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) {
@@ -8565,7 +8566,7 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
if (!hash_value)
return;
}
- ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
+ ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
hash_value);
}
}
@@ -8647,7 +8648,6 @@ int smb3_decrypt_req(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess;
char *buf = work->request_buf;
- struct smb2_hdr *hdr;
unsigned int pdu_length = get_rfc1002_len(buf);
struct kvec iov[2];
int buf_data_size = pdu_length + 4 -
@@ -8683,8 +8683,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
return rc;
memmove(buf + 4, iov[1].iov_base, buf_data_size);
- hdr = (struct smb2_hdr *)buf;
- hdr->smb2_buf_length = cpu_to_be32(buf_data_size);
+ *(__be32 *)buf = cpu_to_be32(buf_data_size);
return rc;
}
@@ -8693,7 +8692,7 @@ bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
- struct smb2_hdr *rsp = work->response_buf;
+ struct smb2_hdr *rsp = smb2_get_msg(work->response_buf);
if (conn->dialect < SMB30_PROT_ID)
return false;
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index fa1cd556ab7a..ebbdb6476c11 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -131,11 +131,6 @@
cpu_to_le16(__SMB2_HEADER_STRUCTURE_SIZE)
struct smb2_hdr {
- __be32 smb2_buf_length; /* big endian on wire */
- /*
- * length is only two or three bytes - with
- * one or two byte type preceding it that MBZ
- */
__le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */
__le16 StructureSize; /* 64 */
__le16 CreditCharge; /* MBZ */
@@ -254,14 +249,14 @@ struct preauth_integrity_info {
__u8 Preauth_HashValue[PREAUTH_HASHVALUE_SIZE];
};
-/* offset is sizeof smb2_negotiate_rsp - 4 but rounded up to 8 bytes. */
+/* offset is sizeof smb2_negotiate_rsp but rounded up to 8 bytes. */
#ifdef CONFIG_SMB_SERVER_KERBEROS5
-/* sizeof(struct smb2_negotiate_rsp) - 4 =
+/* sizeof(struct smb2_negotiate_rsp) =
* header(64) + response(64) + GSS_LENGTH(96) + GSS_PADDING(0)
*/
#define OFFSET_OF_NEG_CONTEXT 0xe0
#else
-/* sizeof(struct smb2_negotiate_rsp) - 4 =
+/* sizeof(struct smb2_negotiate_rsp) =
* header(64) + response(64) + GSS_LENGTH(74) + GSS_PADDING(6)
*/
#define OFFSET_OF_NEG_CONTEXT 0xd0
@@ -1707,4 +1702,13 @@ int smb2_ioctl(struct ksmbd_work *work);
int smb2_oplock_break(struct ksmbd_work *work);
int smb2_notify(struct ksmbd_work *ksmbd_work);
+/*
+ * Get the body of the smb2 message excluding the 4 byte rfc1002 headers
+ * from request/response buffer.
+ */
+static inline void *smb2_get_msg(void *buf)
+{
+ return buf + 4;
+}
+
#endif /* _SMB2PDU_H */
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index 44dbc73d0d1c..4341d52c12f3 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -243,14 +243,14 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
static int ksmbd_negotiate_smb_dialect(void *buf)
{
int smb_buf_length = get_rfc1002_len(buf);
- __le32 proto = ((struct smb2_hdr *)buf)->ProtocolId;
+ __le32 proto = ((struct smb2_hdr *)smb2_get_msg(buf))->ProtocolId;
if (proto == SMB2_PROTO_NUMBER) {
struct smb2_negotiate_req *req;
int smb2_neg_size =
- offsetof(struct smb2_negotiate_req, Dialects) - 4;
+ offsetof(struct smb2_negotiate_req, Dialects);
- req = (struct smb2_negotiate_req *)buf;
+ req = (struct smb2_negotiate_req *)smb2_get_msg(buf);
if (smb2_neg_size > smb_buf_length)
goto err_out;
@@ -469,11 +469,12 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
struct ksmbd_conn *conn = work->conn;
int ret;
- conn->dialect = ksmbd_negotiate_smb_dialect(work->request_buf);
+ conn->dialect =
+ ksmbd_negotiate_smb_dialect(work->request_buf);
ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
if (command == SMB2_NEGOTIATE_HE) {
- struct smb2_hdr *smb2_hdr = work->request_buf;
+ struct smb2_hdr *smb2_hdr = smb2_get_msg(work->request_buf);
if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
index 48cbaa032140..ceb3cacaef1b 100644
--- a/fs/ksmbd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -464,12 +464,6 @@ struct smb_version_cmds {
int (*proc)(struct ksmbd_work *swork);
};
-static inline size_t
-smb2_hdr_size_no_buflen(struct smb_version_values *vals)
-{
- return vals->header_size - 4;
-}
-
int ksmbd_min_protocol(void);
int ksmbd_max_protocol(void);
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 86446742f4ad..9975ebc6fe63 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -490,7 +490,7 @@ static int smb_direct_check_recvmsg(struct smb_direct_recvmsg *recvmsg)
struct smb_direct_data_transfer *req =
(struct smb_direct_data_transfer *)recvmsg->packet;
struct smb2_hdr *hdr = (struct smb2_hdr *)(recvmsg->packet
- + le32_to_cpu(req->data_offset) - 4);
+ + le32_to_cpu(req->data_offset));
ksmbd_debug(RDMA,
"CreditGranted: %u, CreditRequested: %u, DataLength: %u, RemainingDataLength: %u, SMB: %x, Command: %u\n",
le16_to_cpu(req->credits_granted),
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 006/154] ksmbd: remove smb2_buf_length in smb2_transform_hdr
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (4 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 005/154] ksmbd: remove smb2_buf_length in smb2_hdr Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 007/154] ksmbd: change LeaseKey data type to u8 array Namjae Jeon
` (148 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Ronnie Sahlberg, Steve French
[ Upstream commit 2dd9129f7dec1de369e4447a54ea2edf695f765b ]
To move smb2_transform_hdr to smbfs_common, This patch remove
smb2_buf_length variable in smb2_transform_hdr.
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 7 +++----
fs/ksmbd/connection.c | 2 +-
fs/ksmbd/smb2pdu.c | 37 +++++++++++++++++--------------------
fs/ksmbd/smb2pdu.h | 5 -----
4 files changed, 21 insertions(+), 30 deletions(-)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index 3258a3176c06..33cb94ed6f66 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -994,7 +994,7 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
u8 *sign)
{
struct scatterlist *sg;
- unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
+ unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
if (!nvec)
@@ -1058,9 +1058,8 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
unsigned int nvec, int enc)
{
- struct smb2_transform_hdr *tr_hdr =
- (struct smb2_transform_hdr *)iov[0].iov_base;
- unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
+ struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
+ unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int rc;
struct scatterlist *sg;
u8 sign[SMB2_SIGNATURE_SIZE] = {};
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index e4af77581c2f..ddf447e9b8bf 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -173,7 +173,7 @@ int ksmbd_conn_write(struct ksmbd_work *work)
if (work->tr_buf) {
iov[iov_idx] = (struct kvec) { work->tr_buf,
- sizeof(struct smb2_transform_hdr) };
+ sizeof(struct smb2_transform_hdr) + 4 };
len += iov[iov_idx++].iov_len;
}
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 2f04b90c8c2b..e693595b9cf3 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -8571,13 +8571,13 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
}
}
-static void fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, char *old_buf,
- __le16 cipher_type)
+static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
{
- struct smb2_hdr *hdr = (struct smb2_hdr *)old_buf;
+ struct smb2_transform_hdr *tr_hdr = tr_buf + 4;
+ struct smb2_hdr *hdr = smb2_get_msg(old_buf);
unsigned int orig_len = get_rfc1002_len(old_buf);
- memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
+ memset(tr_buf, 0, sizeof(struct smb2_transform_hdr) + 4);
tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
tr_hdr->Flags = cpu_to_le16(0x01);
@@ -8587,14 +8587,13 @@ static void fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, char *old_buf,
else
get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
memcpy(&tr_hdr->SessionId, &hdr->SessionId, 8);
- inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - 4);
- inc_rfc1001_len(tr_hdr, orig_len);
+ inc_rfc1001_len(tr_buf, sizeof(struct smb2_transform_hdr));
+ inc_rfc1001_len(tr_buf, orig_len);
}
int smb3_encrypt_resp(struct ksmbd_work *work)
{
char *buf = work->response_buf;
- struct smb2_transform_hdr *tr_hdr;
struct kvec iov[3];
int rc = -ENOMEM;
int buf_size = 0, rq_nvec = 2 + (work->aux_payload_sz ? 1 : 0);
@@ -8602,15 +8601,15 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
if (ARRAY_SIZE(iov) < rq_nvec)
return -ENOMEM;
- tr_hdr = kzalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
- if (!tr_hdr)
+ work->tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, GFP_KERNEL);
+ if (!work->tr_buf)
return rc;
/* fill transform header */
- fill_transform_hdr(tr_hdr, buf, work->conn->cipher_type);
+ fill_transform_hdr(work->tr_buf, buf, work->conn->cipher_type);
- iov[0].iov_base = tr_hdr;
- iov[0].iov_len = sizeof(struct smb2_transform_hdr);
+ iov[0].iov_base = work->tr_buf;
+ iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
buf_size += iov[0].iov_len - 4;
iov[1].iov_base = buf + 4;
@@ -8630,15 +8629,14 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
return rc;
memmove(buf, iov[1].iov_base, iov[1].iov_len);
- tr_hdr->smb2_buf_length = cpu_to_be32(buf_size);
- work->tr_buf = tr_hdr;
+ *(__be32 *)work->tr_buf = cpu_to_be32(buf_size);
return rc;
}
bool smb3_is_transform_hdr(void *buf)
{
- struct smb2_transform_hdr *trhdr = buf;
+ struct smb2_transform_hdr *trhdr = smb2_get_msg(buf);
return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
}
@@ -8650,9 +8648,8 @@ int smb3_decrypt_req(struct ksmbd_work *work)
char *buf = work->request_buf;
unsigned int pdu_length = get_rfc1002_len(buf);
struct kvec iov[2];
- int buf_data_size = pdu_length + 4 -
- sizeof(struct smb2_transform_hdr);
- struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
+ int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr);
+ struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
int rc = 0;
if (pdu_length < sizeof(struct smb2_transform_hdr) ||
@@ -8675,8 +8672,8 @@ int smb3_decrypt_req(struct ksmbd_work *work)
}
iov[0].iov_base = buf;
- iov[0].iov_len = sizeof(struct smb2_transform_hdr);
- iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
+ iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
+ iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr) + 4;
iov[1].iov_len = buf_data_size;
rc = ksmbd_crypt_message(conn, iov, 2, 0);
if (rc)
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index ebbdb6476c11..2175ab5fb557 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -160,11 +160,6 @@ struct smb2_pdu {
#define SMB3_AES_GCM_NONCE 12
struct smb2_transform_hdr {
- __be32 smb2_buf_length; /* big endian on wire */
- /*
- * length is only two or three bytes - with
- * one or two byte type preceding it that MBZ
- */
__le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */
__u8 Signature[16];
__u8 Nonce[16];
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 007/154] ksmbd: change LeaseKey data type to u8 array
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (5 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 006/154] ksmbd: remove smb2_buf_length in smb2_transform_hdr Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 008/154] ksmbd: use oid registry functions to decode OIDs Namjae Jeon
` (147 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 2734b692f7b8167b93498dcd698067623d4267ca ]
cifs define LeaseKey as u8 array in structure. To move lease structure
to smbfs_common, ksmbd change LeaseKey data type to u8 array.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/oplock.c | 24 +++++++++---------------
fs/ksmbd/oplock.h | 2 --
fs/ksmbd/smb2pdu.h | 11 +++++------
3 files changed, 14 insertions(+), 23 deletions(-)
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index e57b2aa71815..e1d854609195 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -1336,19 +1336,16 @@ __u8 smb2_map_lease_to_oplock(__le32 lease_state)
*/
void create_lease_buf(u8 *rbuf, struct lease *lease)
{
- char *LeaseKey = (char *)&lease->lease_key;
-
if (lease->version == 2) {
struct create_lease_v2 *buf = (struct create_lease_v2 *)rbuf;
- char *ParentLeaseKey = (char *)&lease->parent_lease_key;
memset(buf, 0, sizeof(struct create_lease_v2));
- buf->lcontext.LeaseKeyLow = *((__le64 *)LeaseKey);
- buf->lcontext.LeaseKeyHigh = *((__le64 *)(LeaseKey + 8));
+ memcpy(buf->lcontext.LeaseKey, lease->lease_key,
+ SMB2_LEASE_KEY_SIZE);
buf->lcontext.LeaseFlags = lease->flags;
buf->lcontext.LeaseState = lease->state;
- buf->lcontext.ParentLeaseKeyLow = *((__le64 *)ParentLeaseKey);
- buf->lcontext.ParentLeaseKeyHigh = *((__le64 *)(ParentLeaseKey + 8));
+ memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
+ SMB2_LEASE_KEY_SIZE);
buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_lease_v2, lcontext));
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
@@ -1363,8 +1360,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
struct create_lease *buf = (struct create_lease *)rbuf;
memset(buf, 0, sizeof(struct create_lease));
- buf->lcontext.LeaseKeyLow = *((__le64 *)LeaseKey);
- buf->lcontext.LeaseKeyHigh = *((__le64 *)(LeaseKey + 8));
+ memcpy(buf->lcontext.LeaseKey, lease->lease_key, SMB2_LEASE_KEY_SIZE);
buf->lcontext.LeaseFlags = lease->flags;
buf->lcontext.LeaseState = lease->state;
buf->ccontext.DataOffset = cpu_to_le16(offsetof
@@ -1417,19 +1413,17 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
- *((__le64 *)lreq->lease_key) = lc->lcontext.LeaseKeyLow;
- *((__le64 *)(lreq->lease_key + 8)) = lc->lcontext.LeaseKeyHigh;
+ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
lreq->req_state = lc->lcontext.LeaseState;
lreq->flags = lc->lcontext.LeaseFlags;
lreq->duration = lc->lcontext.LeaseDuration;
- *((__le64 *)lreq->parent_lease_key) = lc->lcontext.ParentLeaseKeyLow;
- *((__le64 *)(lreq->parent_lease_key + 8)) = lc->lcontext.ParentLeaseKeyHigh;
+ memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
+ SMB2_LEASE_KEY_SIZE);
lreq->version = 2;
} else {
struct create_lease *lc = (struct create_lease *)cc;
- *((__le64 *)lreq->lease_key) = lc->lcontext.LeaseKeyLow;
- *((__le64 *)(lreq->lease_key + 8)) = lc->lcontext.LeaseKeyHigh;
+ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
lreq->req_state = lc->lcontext.LeaseState;
lreq->flags = lc->lcontext.LeaseFlags;
lreq->duration = lc->lcontext.LeaseDuration;
diff --git a/fs/ksmbd/oplock.h b/fs/ksmbd/oplock.h
index 2c4f4a0512b7..e1ba363b412a 100644
--- a/fs/ksmbd/oplock.h
+++ b/fs/ksmbd/oplock.h
@@ -28,8 +28,6 @@
#define OPLOCK_WRITE_TO_NONE 0x04
#define OPLOCK_READ_TO_NONE 0x08
-#define SMB2_LEASE_KEY_SIZE 16
-
struct lease_ctx_info {
__u8 lease_key[SMB2_LEASE_KEY_SIZE];
__le32 req_state;
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index 2175ab5fb557..3ae27ccfc20d 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -734,22 +734,21 @@ struct create_posix_rsp {
#define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE cpu_to_le32(0x02)
+#define SMB2_LEASE_KEY_SIZE 16
+
struct lease_context {
- __le64 LeaseKeyLow;
- __le64 LeaseKeyHigh;
+ __u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
__le32 LeaseState;
__le32 LeaseFlags;
__le64 LeaseDuration;
} __packed;
struct lease_context_v2 {
- __le64 LeaseKeyLow;
- __le64 LeaseKeyHigh;
+ __u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
__le32 LeaseState;
__le32 LeaseFlags;
__le64 LeaseDuration;
- __le64 ParentLeaseKeyLow;
- __le64 ParentLeaseKeyHigh;
+ __u8 ParentLeaseKey[SMB2_LEASE_KEY_SIZE];
__le16 Epoch;
__le16 Reserved;
} __packed;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 008/154] ksmbd: use oid registry functions to decode OIDs
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (6 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 007/154] ksmbd: change LeaseKey data type to u8 array Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 009/154] ksmbd: Remove unused parameter from smb2_get_name() Namjae Jeon
` (146 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 294277410cf3b46bee2b8282ab754e52975c0a70 ]
Use look_up_OID to decode OIDs rather than
implementing functions.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/asn1.c | 142 +++++++-----------------------------------------
1 file changed, 19 insertions(+), 123 deletions(-)
diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c
index b014f4638610..c03eba090368 100644
--- a/fs/ksmbd/asn1.c
+++ b/fs/ksmbd/asn1.c
@@ -21,101 +21,11 @@
#include "ksmbd_spnego_negtokeninit.asn1.h"
#include "ksmbd_spnego_negtokentarg.asn1.h"
-#define SPNEGO_OID_LEN 7
#define NTLMSSP_OID_LEN 10
-#define KRB5_OID_LEN 7
-#define KRB5U2U_OID_LEN 8
-#define MSKRB5_OID_LEN 7
-static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
-static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
-static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
-static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 };
-static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
static char NTLMSSP_OID_STR[NTLMSSP_OID_LEN] = { 0x2b, 0x06, 0x01, 0x04, 0x01,
0x82, 0x37, 0x02, 0x02, 0x0a };
-static bool
-asn1_subid_decode(const unsigned char **begin, const unsigned char *end,
- unsigned long *subid)
-{
- const unsigned char *ptr = *begin;
- unsigned char ch;
-
- *subid = 0;
-
- do {
- if (ptr >= end)
- return false;
-
- ch = *ptr++;
- *subid <<= 7;
- *subid |= ch & 0x7F;
- } while ((ch & 0x80) == 0x80);
-
- *begin = ptr;
- return true;
-}
-
-static bool asn1_oid_decode(const unsigned char *value, size_t vlen,
- unsigned long **oid, size_t *oidlen)
-{
- const unsigned char *iptr = value, *end = value + vlen;
- unsigned long *optr;
- unsigned long subid;
-
- vlen += 1;
- if (vlen < 2 || vlen > UINT_MAX / sizeof(unsigned long))
- goto fail_nullify;
-
- *oid = kmalloc(vlen * sizeof(unsigned long), GFP_KERNEL);
- if (!*oid)
- return false;
-
- optr = *oid;
-
- if (!asn1_subid_decode(&iptr, end, &subid))
- goto fail;
-
- if (subid < 40) {
- optr[0] = 0;
- optr[1] = subid;
- } else if (subid < 80) {
- optr[0] = 1;
- optr[1] = subid - 40;
- } else {
- optr[0] = 2;
- optr[1] = subid - 80;
- }
-
- *oidlen = 2;
- optr += 2;
-
- while (iptr < end) {
- if (++(*oidlen) > vlen)
- goto fail;
-
- if (!asn1_subid_decode(&iptr, end, optr++))
- goto fail;
- }
- return true;
-
-fail:
- kfree(*oid);
-fail_nullify:
- *oid = NULL;
- return false;
-}
-
-static bool oid_eq(unsigned long *oid1, unsigned int oid1len,
- unsigned long *oid2, unsigned int oid2len)
-{
- if (oid1len != oid2len)
- return false;
-
- return memcmp(oid1, oid2, oid1len) == 0;
-}
-
int
ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
struct ksmbd_conn *conn)
@@ -252,26 +162,18 @@ int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
int ksmbd_gssapi_this_mech(void *context, size_t hdrlen, unsigned char tag,
const void *value, size_t vlen)
{
- unsigned long *oid;
- size_t oidlen;
- int err = 0;
-
- if (!asn1_oid_decode(value, vlen, &oid, &oidlen)) {
- err = -EBADMSG;
- goto out;
- }
+ enum OID oid;
- if (!oid_eq(oid, oidlen, SPNEGO_OID, SPNEGO_OID_LEN))
- err = -EBADMSG;
- kfree(oid);
-out:
- if (err) {
+ oid = look_up_OID(value, vlen);
+ if (oid != OID_spnego) {
char buf[50];
sprint_oid(value, vlen, buf, sizeof(buf));
ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
+ return -EBADMSG;
}
- return err;
+
+ return 0;
}
int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
@@ -279,37 +181,31 @@ int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
size_t vlen)
{
struct ksmbd_conn *conn = context;
- unsigned long *oid;
- size_t oidlen;
+ enum OID oid;
int mech_type;
- char buf[50];
- if (!asn1_oid_decode(value, vlen, &oid, &oidlen))
- goto fail;
-
- if (oid_eq(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN))
+ oid = look_up_OID(value, vlen);
+ if (oid == OID_ntlmssp) {
mech_type = KSMBD_AUTH_NTLMSSP;
- else if (oid_eq(oid, oidlen, MSKRB5_OID, MSKRB5_OID_LEN))
+ } else if (oid == OID_mskrb5) {
mech_type = KSMBD_AUTH_MSKRB5;
- else if (oid_eq(oid, oidlen, KRB5_OID, KRB5_OID_LEN))
+ } else if (oid == OID_krb5) {
mech_type = KSMBD_AUTH_KRB5;
- else if (oid_eq(oid, oidlen, KRB5U2U_OID, KRB5U2U_OID_LEN))
+ } else if (oid == OID_krb5u2u) {
mech_type = KSMBD_AUTH_KRB5U2U;
- else
- goto fail;
+ } else {
+ char buf[50];
+
+ sprint_oid(value, vlen, buf, sizeof(buf));
+ ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
+ return -EBADMSG;
+ }
conn->auth_mechs |= mech_type;
if (conn->preferred_auth_mech == 0)
conn->preferred_auth_mech = mech_type;
- kfree(oid);
return 0;
-
-fail:
- kfree(oid);
- sprint_oid(value, vlen, buf, sizeof(buf));
- ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
- return -EBADMSG;
}
int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 009/154] ksmbd: Remove unused parameter from smb2_get_name()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (7 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 008/154] ksmbd: use oid registry functions to decode OIDs Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 010/154] ksmbd: Remove unused fields from ksmbd_file struct definition Namjae Jeon
` (145 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Marios Makassikis, Namjae Jeon, Steve French
From: Marios Makassikis <mmakassikis@freebox.fr>
[ Upstream commit 80917f17e3f99027661a45262c310139e53a9faa ]
The 'share' parameter is no longer used by smb2_get_name() since
commit 265fd1991c1d ("ksmbd: use LOOKUP_BENEATH to prevent the out of
share access").
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index e693595b9cf3..bf537080b2e0 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -651,7 +651,6 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
/**
* smb2_get_name() - get filename string from on the wire smb format
- * @share: ksmbd_share_config pointer
* @src: source buffer
* @maxlen: maxlen of source string
* @nls_table: nls_table pointer
@@ -659,8 +658,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
* Return: matching converted filename on success, otherwise error ptr
*/
static char *
-smb2_get_name(struct ksmbd_share_config *share, const char *src,
- const int maxlen, struct nls_table *local_nls)
+smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)
{
char *name;
@@ -2604,8 +2602,7 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
- name = smb2_get_name(share,
- req->Buffer,
+ name = smb2_get_name(req->Buffer,
le16_to_cpu(req->NameLength),
work->conn->local_nls);
if (IS_ERR(name)) {
@@ -5481,8 +5478,7 @@ static int smb2_rename(struct ksmbd_work *work,
goto out;
}
- new_name = smb2_get_name(share,
- file_info->FileName,
+ new_name = smb2_get_name(file_info->FileName,
le32_to_cpu(file_info->FileNameLength),
local_nls);
if (IS_ERR(new_name)) {
@@ -5593,8 +5589,7 @@ static int smb2_create_link(struct ksmbd_work *work,
if (!pathname)
return -ENOMEM;
- link_name = smb2_get_name(share,
- file_info->FileName,
+ link_name = smb2_get_name(file_info->FileName,
le32_to_cpu(file_info->FileNameLength),
local_nls);
if (IS_ERR(link_name) || S_ISDIR(file_inode(filp)->i_mode)) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 010/154] ksmbd: Remove unused fields from ksmbd_file struct definition
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (8 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 009/154] ksmbd: Remove unused parameter from smb2_get_name() Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 011/154] ksmbd: set both ipv4 and ipv6 in FSCTL_QUERY_NETWORK_INTERFACE_INFO Namjae Jeon
` (144 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Marios Makassikis, Namjae Jeon, Steve French
From: Marios Makassikis <mmakassikis@freebox.fr>
[ Upstream commit 305f8bda15ebbe4004681286a5c67d0dc296c771 ]
These fields are remnants of the not upstreamed SMB1 code.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs_cache.h | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/fs/ksmbd/vfs_cache.h b/fs/ksmbd/vfs_cache.h
index 448576fbe4b7..36239ce31afd 100644
--- a/fs/ksmbd/vfs_cache.h
+++ b/fs/ksmbd/vfs_cache.h
@@ -96,16 +96,6 @@ struct ksmbd_file {
int durable_timeout;
- /* for SMB1 */
- int pid;
-
- /* conflict lock fail count for SMB1 */
- unsigned int cflock_cnt;
- /* last lock failure start offset for SMB1 */
- unsigned long long llock_fstart;
-
- int dirent_offset;
-
/* if ls is happening on directory, below is valid*/
struct ksmbd_readdir_data readdir_data;
int dot_dotdot[2];
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 011/154] ksmbd: set both ipv4 and ipv6 in FSCTL_QUERY_NETWORK_INTERFACE_INFO
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (9 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 010/154] ksmbd: Remove unused fields from ksmbd_file struct definition Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 012/154] ksmbd: Fix buffer_check_err() kernel-doc comment Namjae Jeon
` (143 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit a58b45a4dbfd0bf2ebb157789da4d8e6368afb1b ]
Set ipv4 and ipv6 address in FSCTL_QUERY_NETWORK_INTERFACE_INFO.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index bf537080b2e0..cf883f9575bc 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -7327,15 +7327,10 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
struct sockaddr_storage_rsp *sockaddr_storage;
unsigned int flags;
unsigned long long speed;
- struct sockaddr_in6 *csin6 = (struct sockaddr_in6 *)&conn->peer_addr;
rtnl_lock();
for_each_netdev(&init_net, netdev) {
- if (out_buf_len <
- nbytes + sizeof(struct network_interface_info_ioctl_rsp)) {
- rtnl_unlock();
- return -ENOSPC;
- }
+ bool ipv4_set = false;
if (netdev->type == ARPHRD_LOOPBACK)
continue;
@@ -7343,6 +7338,12 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
flags = dev_get_flags(netdev);
if (!(flags & IFF_RUNNING))
continue;
+ipv6_retry:
+ if (out_buf_len <
+ nbytes + sizeof(struct network_interface_info_ioctl_rsp)) {
+ rtnl_unlock();
+ return -ENOSPC;
+ }
nii_rsp = (struct network_interface_info_ioctl_rsp *)
&rsp->Buffer[nbytes];
@@ -7375,8 +7376,7 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
nii_rsp->SockAddr_Storage;
memset(sockaddr_storage, 0, 128);
- if (conn->peer_addr.ss_family == PF_INET ||
- ipv6_addr_v4mapped(&csin6->sin6_addr)) {
+ if (!ipv4_set) {
struct in_device *idev;
sockaddr_storage->Family = cpu_to_le16(INTERNETWORK);
@@ -7387,6 +7387,9 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
continue;
sockaddr_storage->addr4.IPv4address =
idev_ipv4_address(idev);
+ nbytes += sizeof(struct network_interface_info_ioctl_rsp);
+ ipv4_set = true;
+ goto ipv6_retry;
} else {
struct inet6_dev *idev6;
struct inet6_ifaddr *ifa;
@@ -7408,9 +7411,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
break;
}
sockaddr_storage->addr6.ScopeId = 0;
+ nbytes += sizeof(struct network_interface_info_ioctl_rsp);
}
-
- nbytes += sizeof(struct network_interface_info_ioctl_rsp);
}
rtnl_unlock();
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 012/154] ksmbd: Fix buffer_check_err() kernel-doc comment
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (10 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 011/154] ksmbd: set both ipv4 and ipv6 in FSCTL_QUERY_NETWORK_INTERFACE_INFO Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 013/154] ksmbd: Fix smb2_set_info_file() " Namjae Jeon
` (142 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Yang Li, Abaci Robot, Namjae Jeon, Steve French
From: Yang Li <yang.lee@linux.alibaba.com>
[ Upstream commit e230d013378489bcd4b5589ca1d2a5b91ff8d098 ]
Add the description of @rsp_org in buffer_check_err() kernel-doc comment
to remove a warning found by running scripts/kernel-doc, which is caused
by using 'make W=1'.
fs/ksmbd/smb2pdu.c:4028: warning: Function parameter or member 'rsp_org'
not described in 'buffer_check_err'
Reported-by: Abaci Robot <abaci@linux.alibaba.com>
Fixes: cb4517201b8a ("ksmbd: remove smb2_buf_length in smb2_hdr")
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index cf883f9575bc..0edb0a96766d 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -4101,6 +4101,7 @@ int smb2_query_dir(struct ksmbd_work *work)
* buffer_check_err() - helper function to check buffer errors
* @reqOutputBufferLength: max buffer length expected in command response
* @rsp: query info response buffer contains output buffer length
+ * @rsp_org: base response buffer pointer in case of chained response
* @infoclass_size: query info class response buffer size
*
* Return: 0 on success, otherwise error
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 013/154] ksmbd: Fix smb2_set_info_file() kernel-doc comment
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (11 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 012/154] ksmbd: Fix buffer_check_err() kernel-doc comment Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 014/154] ksmbd: Delete an invalid argument description in smb2_populate_readdir_entry() Namjae Jeon
` (141 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Yang Li, Abaci Robot, Namjae Jeon, Steve French
From: Yang Li <yang.lee@linux.alibaba.com>
[ Upstream commit 4bfd9eed15e163969156e976c62db5ef423e5b0f ]
Fix argument list that the kdoc format and script verified in
smb2_set_info_file().
The warnings were found by running scripts/kernel-doc, which is
caused by using 'make W=1'.
fs/ksmbd/smb2pdu.c:5862: warning: Function parameter or member 'req' not
described in 'smb2_set_info_file'
fs/ksmbd/smb2pdu.c:5862: warning: Excess function parameter 'info_class'
description in 'smb2_set_info_file'
Reported-by: Abaci Robot <abaci@linux.alibaba.com>
Fixes: 9496e268e3af ("ksmbd: add request buffer validation in smb2_set_info")
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 0edb0a96766d..3118ef0aae50 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -5932,7 +5932,7 @@ static int set_file_mode_info(struct ksmbd_file *fp,
* smb2_set_info_file() - handler for smb2 set info command
* @work: smb work containing set info command buffer
* @fp: ksmbd_file pointer
- * @info_class: smb2 set info class
+ * @req: request buffer pointer
* @share: ksmbd_share_config pointer
*
* Return: 0 on success, otherwise error
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 014/154] ksmbd: Delete an invalid argument description in smb2_populate_readdir_entry()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (12 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 013/154] ksmbd: Fix smb2_set_info_file() " Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 015/154] ksmbd: Fix smb2_get_name() kernel-doc comment Namjae Jeon
` (140 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Yang Li, Abaci Robot, Namjae Jeon, Steve French
From: Yang Li <yang.lee@linux.alibaba.com>
[ Upstream commit f5c381392948dcae19f854b9586b806654f08a11 ]
A warning is reported because an invalid argument description, it is found
by running scripts/kernel-doc, which is caused by using 'make W=1'.
fs/ksmbd/smb2pdu.c:3406: warning: Excess function parameter 'user_ns'
description in 'smb2_populate_readdir_entry'
Reported-by: Abaci Robot <abaci@linux.alibaba.com>
Fixes: 475d6f98804c ("ksmbd: fix translation in smb2_populate_readdir_entry()")
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 3118ef0aae50..5980b625a0f9 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3466,7 +3466,6 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
* @conn: connection instance
* @info_level: smb information level
* @d_info: structure included variables for query dir
- * @user_ns: user namespace
* @ksmbd_kstat: ksmbd wrapper of dirent stat information
*
* if directory has many entries, find first can't read it fully.
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 015/154] ksmbd: Fix smb2_get_name() kernel-doc comment
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (13 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 014/154] ksmbd: Delete an invalid argument description in smb2_populate_readdir_entry() Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 016/154] ksmbd: register ksmbd ib client with ib_register_client() Namjae Jeon
` (139 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Yang Li, Abaci Robot, Namjae Jeon, Steve French
From: Yang Li <yang.lee@linux.alibaba.com>
[ Upstream commit d4eeb82674acadf789277b577986e8e7d3faf695 ]
Remove some warnings found by running scripts/kernel-doc,
which is caused by using 'make W=1'.
fs/ksmbd/smb2pdu.c:623: warning: Function parameter or member
'local_nls' not described in 'smb2_get_name'
fs/ksmbd/smb2pdu.c:623: warning: Excess function parameter 'nls_table'
description in 'smb2_get_name'
Reported-by: Abaci Robot <abaci@linux.alibaba.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 5980b625a0f9..7b7b620d2d66 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -653,7 +653,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
* smb2_get_name() - get filename string from on the wire smb format
* @src: source buffer
* @maxlen: maxlen of source string
- * @nls_table: nls_table pointer
+ * @local_nls: nls_table pointer
*
* Return: matching converted filename on success, otherwise error ptr
*/
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 016/154] ksmbd: register ksmbd ib client with ib_register_client()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (14 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 015/154] ksmbd: Fix smb2_get_name() kernel-doc comment Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 017/154] ksmbd: set 445 port to smbdirect port by default Namjae Jeon
` (138 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 31928a001bed0d9642711d2eba520fc46d41c376 ]
Register ksmbd ib client with ib_register_client() to find the rdma capable
network adapter. If ops.get_netdev(Chelsio NICs) is NULL, ksmbd will find
it using ib_device_get_by_netdev in old way.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 107 ++++++++++++++++++++++++++++++++++----
fs/ksmbd/transport_rdma.h | 2 +-
2 files changed, 98 insertions(+), 11 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 9975ebc6fe63..3bcca8e5a6c8 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -79,6 +79,14 @@ static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
static int smb_direct_max_outstanding_rw_ops = 8;
+static LIST_HEAD(smb_direct_device_list);
+static DEFINE_RWLOCK(smb_direct_device_lock);
+
+struct smb_direct_device {
+ struct ib_device *ib_dev;
+ struct list_head list;
+};
+
static struct smb_direct_listener {
struct rdma_cm_id *cm_id;
} smb_direct_listener;
@@ -2013,12 +2021,61 @@ static int smb_direct_listen(int port)
return ret;
}
+static int smb_direct_ib_client_add(struct ib_device *ib_dev)
+{
+ struct smb_direct_device *smb_dev;
+
+ if (!ib_dev->ops.get_netdev ||
+ !rdma_frwr_is_supported(&ib_dev->attrs))
+ return 0;
+
+ smb_dev = kzalloc(sizeof(*smb_dev), GFP_KERNEL);
+ if (!smb_dev)
+ return -ENOMEM;
+ smb_dev->ib_dev = ib_dev;
+
+ write_lock(&smb_direct_device_lock);
+ list_add(&smb_dev->list, &smb_direct_device_list);
+ write_unlock(&smb_direct_device_lock);
+
+ ksmbd_debug(RDMA, "ib device added: name %s\n", ib_dev->name);
+ return 0;
+}
+
+static void smb_direct_ib_client_remove(struct ib_device *ib_dev,
+ void *client_data)
+{
+ struct smb_direct_device *smb_dev, *tmp;
+
+ write_lock(&smb_direct_device_lock);
+ list_for_each_entry_safe(smb_dev, tmp, &smb_direct_device_list, list) {
+ if (smb_dev->ib_dev == ib_dev) {
+ list_del(&smb_dev->list);
+ kfree(smb_dev);
+ break;
+ }
+ }
+ write_unlock(&smb_direct_device_lock);
+}
+
+static struct ib_client smb_direct_ib_client = {
+ .name = "ksmbd_smb_direct_ib",
+ .add = smb_direct_ib_client_add,
+ .remove = smb_direct_ib_client_remove,
+};
+
int ksmbd_rdma_init(void)
{
int ret;
smb_direct_listener.cm_id = NULL;
+ ret = ib_register_client(&smb_direct_ib_client);
+ if (ret) {
+ pr_err("failed to ib_register_client\n");
+ return ret;
+ }
+
/* When a client is running out of send credits, the credits are
* granted by the server's sending a packet using this queue.
* This avoids the situation that a clients cannot send packets
@@ -2042,30 +2099,60 @@ int ksmbd_rdma_init(void)
return 0;
}
-int ksmbd_rdma_destroy(void)
+void ksmbd_rdma_destroy(void)
{
- if (smb_direct_listener.cm_id)
- rdma_destroy_id(smb_direct_listener.cm_id);
+ if (!smb_direct_listener.cm_id)
+ return;
+
+ ib_unregister_client(&smb_direct_ib_client);
+ rdma_destroy_id(smb_direct_listener.cm_id);
+
smb_direct_listener.cm_id = NULL;
if (smb_direct_wq) {
destroy_workqueue(smb_direct_wq);
smb_direct_wq = NULL;
}
- return 0;
}
bool ksmbd_rdma_capable_netdev(struct net_device *netdev)
{
- struct ib_device *ibdev;
+ struct smb_direct_device *smb_dev;
+ int i;
bool rdma_capable = false;
- ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN);
- if (ibdev) {
- if (rdma_frwr_is_supported(&ibdev->attrs))
- rdma_capable = true;
- ib_device_put(ibdev);
+ read_lock(&smb_direct_device_lock);
+ list_for_each_entry(smb_dev, &smb_direct_device_list, list) {
+ for (i = 0; i < smb_dev->ib_dev->phys_port_cnt; i++) {
+ struct net_device *ndev;
+
+ ndev = smb_dev->ib_dev->ops.get_netdev(smb_dev->ib_dev,
+ i + 1);
+ if (!ndev)
+ continue;
+
+ if (ndev == netdev) {
+ dev_put(ndev);
+ rdma_capable = true;
+ goto out;
+ }
+ dev_put(ndev);
+ }
+ }
+out:
+ read_unlock(&smb_direct_device_lock);
+
+ if (rdma_capable == false) {
+ struct ib_device *ibdev;
+
+ ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN);
+ if (ibdev) {
+ if (rdma_frwr_is_supported(&ibdev->attrs))
+ rdma_capable = true;
+ ib_device_put(ibdev);
+ }
}
+
return rdma_capable;
}
diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
index 04a7a37685c3..3e6c4be3d560 100644
--- a/fs/ksmbd/transport_rdma.h
+++ b/fs/ksmbd/transport_rdma.h
@@ -56,7 +56,7 @@ struct smb_direct_data_transfer {
#ifdef CONFIG_SMB_SERVER_SMBDIRECT
int ksmbd_rdma_init(void);
-int ksmbd_rdma_destroy(void);
+void ksmbd_rdma_destroy(void);
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
void init_smbd_max_io_size(unsigned int sz);
#else
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 017/154] ksmbd: set 445 port to smbdirect port by default
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (15 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 016/154] ksmbd: register ksmbd ib client with ib_register_client() Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 018/154] ksmbd: smbd: call rdma_accept() under CM handler Namjae Jeon
` (137 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit cb097b3dd5ece9596a0a0b7e33893c02a9bde8c6 ]
When SMB Direct is used with iWARP, Windows use 5445 port for smb direct
port, 445 port for SMB. This patch check ib_device using ib_client to
know if NICs type is iWARP or Infiniband.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 15 ++++++++++++---
fs/ksmbd/transport_rdma.h | 2 --
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 3bcca8e5a6c8..9d12ef4024e2 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -34,7 +34,8 @@
#include "smbstatus.h"
#include "transport_rdma.h"
-#define SMB_DIRECT_PORT 5445
+#define SMB_DIRECT_PORT_IWARP 5445
+#define SMB_DIRECT_PORT_INFINIBAND 445
#define SMB_DIRECT_VERSION_LE cpu_to_le16(0x0100)
@@ -60,6 +61,10 @@
* as defined in [MS-SMBD] 3.1.1.1
* Those may change after a SMB_DIRECT negotiation
*/
+
+/* Set 445 port to SMB Direct port by default */
+static int smb_direct_port = SMB_DIRECT_PORT_INFINIBAND;
+
/* The local peer's maximum number of credits to grant to the peer */
static int smb_direct_receive_credit_max = 255;
@@ -1948,7 +1953,7 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
KSMBD_TRANS(t)->conn, "ksmbd:r%u",
- SMB_DIRECT_PORT);
+ smb_direct_port);
if (IS_ERR(KSMBD_TRANS(t)->handler)) {
int ret = PTR_ERR(KSMBD_TRANS(t)->handler);
@@ -2025,6 +2030,10 @@ static int smb_direct_ib_client_add(struct ib_device *ib_dev)
{
struct smb_direct_device *smb_dev;
+ /* Set 5445 port if device type is iWARP(No IB) */
+ if (ib_dev->node_type != RDMA_NODE_IB_CA)
+ smb_direct_port = SMB_DIRECT_PORT_IWARP;
+
if (!ib_dev->ops.get_netdev ||
!rdma_frwr_is_supported(&ib_dev->attrs))
return 0;
@@ -2086,7 +2095,7 @@ int ksmbd_rdma_init(void)
if (!smb_direct_wq)
return -ENOMEM;
- ret = smb_direct_listen(SMB_DIRECT_PORT);
+ ret = smb_direct_listen(smb_direct_port);
if (ret) {
destroy_workqueue(smb_direct_wq);
smb_direct_wq = NULL;
diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
index 3e6c4be3d560..e7b4e6790fab 100644
--- a/fs/ksmbd/transport_rdma.h
+++ b/fs/ksmbd/transport_rdma.h
@@ -7,8 +7,6 @@
#ifndef __KSMBD_TRANSPORT_RDMA_H__
#define __KSMBD_TRANSPORT_RDMA_H__
-#define SMB_DIRECT_PORT 5445
-
#define SMBD_DEFAULT_IOSIZE (8 * 1024 * 1024)
#define SMBD_MIN_IOSIZE (512 * 1024)
#define SMBD_MAX_IOSIZE (16 * 1024 * 1024)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 018/154] ksmbd: smbd: call rdma_accept() under CM handler
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (16 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 017/154] ksmbd: set 445 port to smbdirect port by default Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 019/154] ksmbd: smbd: create MR pool Namjae Jeon
` (136 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 99b7650ac51847e81b4d5139824e321e6cb76130 ]
if CONFIG_LOCKDEP is enabled, the following
kernel warning message is generated because
rdma_accept() checks whehter the handler_mutex
is held by lockdep_assert_held. CM(Connection
Manager) holds the mutex before CM handler
callback is called.
[ 63.211405 ] WARNING: CPU: 1 PID: 345 at drivers/infiniband/core/cma.c:4405 rdma_accept+0x17a/0x350
[ 63.212080 ] RIP: 0010:rdma_accept+0x17a/0x350
...
[ 63.214036 ] Call Trace:
[ 63.214098 ] <TASK>
[ 63.214185 ] smb_direct_accept_client+0xb4/0x170 [ksmbd]
[ 63.214412 ] smb_direct_prepare+0x322/0x8c0 [ksmbd]
[ 63.214555 ] ? rcu_read_lock_sched_held+0x3a/0x70
[ 63.214700 ] ksmbd_conn_handler_loop+0x63/0x270 [ksmbd]
[ 63.214826 ] ? ksmbd_conn_alive+0x80/0x80 [ksmbd]
[ 63.214952 ] kthread+0x171/0x1a0
[ 63.215039 ] ? set_kthread_struct+0x40/0x40
[ 63.215128 ] ret_from_fork+0x22/0x30
To avoid this, move creating a queue pair and accepting
a client from transport_ops->prepare() to
smb_direct_handle_connect_request().
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 102 ++++++++++++++++++++++----------------
1 file changed, 59 insertions(+), 43 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 9d12ef4024e2..ba2d3d286017 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -574,6 +574,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
}
t->negotiation_requested = true;
t->full_packet_received = true;
+ enqueue_reassembly(t, recvmsg, 0);
wake_up_interruptible(&t->wait_status);
break;
case SMB_DIRECT_MSG_DATA_TRANSFER: {
@@ -1600,19 +1601,13 @@ static int smb_direct_accept_client(struct smb_direct_transport *t)
pr_err("error at rdma_accept: %d\n", ret);
return ret;
}
-
- wait_event_interruptible(t->wait_status,
- t->status != SMB_DIRECT_CS_NEW);
- if (t->status != SMB_DIRECT_CS_CONNECTED)
- return -ENOTCONN;
return 0;
}
-static int smb_direct_negotiate(struct smb_direct_transport *t)
+static int smb_direct_prepare_negotiation(struct smb_direct_transport *t)
{
int ret;
struct smb_direct_recvmsg *recvmsg;
- struct smb_direct_negotiate_req *req;
recvmsg = get_free_recvmsg(t);
if (!recvmsg)
@@ -1622,44 +1617,20 @@ static int smb_direct_negotiate(struct smb_direct_transport *t)
ret = smb_direct_post_recv(t, recvmsg);
if (ret) {
pr_err("Can't post recv: %d\n", ret);
- goto out;
+ goto out_err;
}
t->negotiation_requested = false;
ret = smb_direct_accept_client(t);
if (ret) {
pr_err("Can't accept client\n");
- goto out;
+ goto out_err;
}
smb_direct_post_recv_credits(&t->post_recv_credits_work.work);
-
- ksmbd_debug(RDMA, "Waiting for SMB_DIRECT negotiate request\n");
- ret = wait_event_interruptible_timeout(t->wait_status,
- t->negotiation_requested ||
- t->status == SMB_DIRECT_CS_DISCONNECTED,
- SMB_DIRECT_NEGOTIATE_TIMEOUT * HZ);
- if (ret <= 0 || t->status == SMB_DIRECT_CS_DISCONNECTED) {
- ret = ret < 0 ? ret : -ETIMEDOUT;
- goto out;
- }
-
- ret = smb_direct_check_recvmsg(recvmsg);
- if (ret == -ECONNABORTED)
- goto out;
-
- req = (struct smb_direct_negotiate_req *)recvmsg->packet;
- t->max_recv_size = min_t(int, t->max_recv_size,
- le32_to_cpu(req->preferred_send_size));
- t->max_send_size = min_t(int, t->max_send_size,
- le32_to_cpu(req->max_receive_size));
- t->max_fragmented_send_size =
- le32_to_cpu(req->max_fragmented_size);
-
- ret = smb_direct_send_negotiate_response(t, ret);
-out:
- if (recvmsg)
- put_recvmsg(t, recvmsg);
+ return 0;
+out_err:
+ put_recvmsg(t, recvmsg);
return ret;
}
@@ -1896,6 +1867,47 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
static int smb_direct_prepare(struct ksmbd_transport *t)
{
struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+ struct smb_direct_recvmsg *recvmsg;
+ struct smb_direct_negotiate_req *req;
+ int ret;
+
+ ksmbd_debug(RDMA, "Waiting for SMB_DIRECT negotiate request\n");
+ ret = wait_event_interruptible_timeout(st->wait_status,
+ st->negotiation_requested ||
+ st->status == SMB_DIRECT_CS_DISCONNECTED,
+ SMB_DIRECT_NEGOTIATE_TIMEOUT * HZ);
+ if (ret <= 0 || st->status == SMB_DIRECT_CS_DISCONNECTED)
+ return ret < 0 ? ret : -ETIMEDOUT;
+
+ recvmsg = get_first_reassembly(st);
+ if (!recvmsg)
+ return -ECONNABORTED;
+
+ ret = smb_direct_check_recvmsg(recvmsg);
+ if (ret == -ECONNABORTED)
+ goto out;
+
+ req = (struct smb_direct_negotiate_req *)recvmsg->packet;
+ st->max_recv_size = min_t(int, st->max_recv_size,
+ le32_to_cpu(req->preferred_send_size));
+ st->max_send_size = min_t(int, st->max_send_size,
+ le32_to_cpu(req->max_receive_size));
+ st->max_fragmented_send_size =
+ le32_to_cpu(req->max_fragmented_size);
+
+ ret = smb_direct_send_negotiate_response(st, ret);
+out:
+ spin_lock_irq(&st->reassembly_queue_lock);
+ st->reassembly_queue_length--;
+ list_del(&recvmsg->list);
+ spin_unlock_irq(&st->reassembly_queue_lock);
+ put_recvmsg(st, recvmsg);
+
+ return ret;
+}
+
+static int smb_direct_connect(struct smb_direct_transport *st)
+{
int ret;
struct ib_qp_cap qp_cap;
@@ -1917,13 +1929,11 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
return ret;
}
- ret = smb_direct_negotiate(st);
+ ret = smb_direct_prepare_negotiation(st);
if (ret) {
pr_err("Can't negotiate: %d\n", ret);
return ret;
}
-
- st->status = SMB_DIRECT_CS_CONNECTED;
return 0;
}
@@ -1939,6 +1949,7 @@ static bool rdma_frwr_is_supported(struct ib_device_attr *attrs)
static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
{
struct smb_direct_transport *t;
+ int ret;
if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) {
ksmbd_debug(RDMA,
@@ -1951,18 +1962,23 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
if (!t)
return -ENOMEM;
+ ret = smb_direct_connect(t);
+ if (ret)
+ goto out_err;
+
KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
KSMBD_TRANS(t)->conn, "ksmbd:r%u",
smb_direct_port);
if (IS_ERR(KSMBD_TRANS(t)->handler)) {
- int ret = PTR_ERR(KSMBD_TRANS(t)->handler);
-
+ ret = PTR_ERR(KSMBD_TRANS(t)->handler);
pr_err("Can't start thread\n");
- free_transport(t);
- return ret;
+ goto out_err;
}
return 0;
+out_err:
+ free_transport(t);
+ return ret;
}
static int smb_direct_listen_handler(struct rdma_cm_id *cm_id,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 019/154] ksmbd: smbd: create MR pool
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (17 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 018/154] ksmbd: smbd: call rdma_accept() under CM handler Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 020/154] ksmbd: smbd: change the default maximum read/write, receive size Namjae Jeon
` (135 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit c9f189271cff85d5d735e25dfa4bc95952ec12d8 ]
Create a memory region pool because rdma_rw_ctx_init()
uses memory registration if memory registration yields
better performance than using multiple SGE entries.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index ba2d3d286017..5901c4a2ece1 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -434,6 +434,7 @@ static void free_transport(struct smb_direct_transport *t)
if (t->qp) {
ib_drain_qp(t->qp);
+ ib_mr_pool_destroy(t->qp, &t->qp->rdma_mrs);
ib_destroy_qp(t->qp);
}
@@ -1714,7 +1715,9 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
cap->max_send_sge = SMB_DIRECT_MAX_SEND_SGES;
cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES;
cap->max_inline_data = 0;
- cap->max_rdma_ctxs = 0;
+ cap->max_rdma_ctxs =
+ rdma_rw_mr_factor(device, t->cm_id->port_num, max_pages) *
+ smb_direct_max_outstanding_rw_ops;
return 0;
}
@@ -1796,6 +1799,7 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
{
int ret;
struct ib_qp_init_attr qp_attr;
+ int pages_per_rw;
t->pd = ib_alloc_pd(t->cm_id->device, 0);
if (IS_ERR(t->pd)) {
@@ -1843,6 +1847,23 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
t->qp = t->cm_id->qp;
t->cm_id->event_handler = smb_direct_cm_handler;
+ pages_per_rw = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1;
+ if (pages_per_rw > t->cm_id->device->attrs.max_sgl_rd) {
+ int pages_per_mr, mr_count;
+
+ pages_per_mr = min_t(int, pages_per_rw,
+ t->cm_id->device->attrs.max_fast_reg_page_list_len);
+ mr_count = DIV_ROUND_UP(pages_per_rw, pages_per_mr) *
+ atomic_read(&t->rw_avail_ops);
+ ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs, mr_count,
+ IB_MR_TYPE_MEM_REG, pages_per_mr, 0);
+ if (ret) {
+ pr_err("failed to init mr pool count %d pages %d\n",
+ mr_count, pages_per_mr);
+ goto err;
+ }
+ }
+
return 0;
err:
if (t->qp) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 020/154] ksmbd: smbd: change the default maximum read/write, receive size
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (18 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 019/154] ksmbd: smbd: create MR pool Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 021/154] ksmbd: add smb-direct shutdown Namjae Jeon
` (134 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 4d02c4fdc0e256b493f9a3b604c7ff18f0019f17 ]
Due to restriction that cannot handle multiple
buffer descriptor structures, decrease the maximum
read/write size for Windows clients.
And set the maximum fragmented receive size
in consideration of the receive queue size.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 5901c4a2ece1..7e85c2767cd0 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1914,7 +1914,9 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
st->max_send_size = min_t(int, st->max_send_size,
le32_to_cpu(req->max_receive_size));
st->max_fragmented_send_size =
- le32_to_cpu(req->max_fragmented_size);
+ le32_to_cpu(req->max_fragmented_size);
+ st->max_fragmented_recv_size =
+ (st->recv_credit_max * st->max_recv_size) / 2;
ret = smb_direct_send_negotiate_response(st, ret);
out:
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 021/154] ksmbd: add smb-direct shutdown
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (19 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 020/154] ksmbd: smbd: change the default maximum read/write, receive size Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 022/154] ksmbd: smbd: fix missing client's memory region invalidation Namjae Jeon
` (133 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Yufan Chen, Steve French
[ Upstream commit 136dff3a6b71dc16c30b35cc390feb0bfc32ed50 ]
When killing ksmbd server after connecting rdma, ksmbd threads does not
terminate properly because the rdma connection is still alive.
This patch add shutdown operation to disconnect rdma connection while
ksmbd threads terminate.
Signed-off-by: Yufan Chen <wiz.chen@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 9 ++++++++-
fs/ksmbd/connection.h | 1 +
fs/ksmbd/transport_rdma.c | 10 ++++++++++
3 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index ddf447e9b8bf..6e3416d9c65e 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -399,17 +399,24 @@ int ksmbd_conn_transport_init(void)
static void stop_sessions(void)
{
struct ksmbd_conn *conn;
+ struct ksmbd_transport *t;
again:
read_lock(&conn_list_lock);
list_for_each_entry(conn, &conn_list, conns_list) {
struct task_struct *task;
- task = conn->transport->handler;
+ t = conn->transport;
+ task = t->handler;
if (task)
ksmbd_debug(CONN, "Stop session handler %s/%d\n",
task->comm, task_pid_nr(task));
conn->status = KSMBD_SESS_EXITING;
+ if (t->ops->shutdown) {
+ read_unlock(&conn_list_lock);
+ t->ops->shutdown(t);
+ read_lock(&conn_list_lock);
+ }
}
read_unlock(&conn_list_lock);
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index 89eb41bbd160..fd243cdddb22 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -110,6 +110,7 @@ struct ksmbd_conn_ops {
struct ksmbd_transport_ops {
int (*prepare)(struct ksmbd_transport *t);
void (*disconnect)(struct ksmbd_transport *t);
+ void (*shutdown)(struct ksmbd_transport *t);
int (*read)(struct ksmbd_transport *t, char *buf,
unsigned int size, int max_retries);
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 7e85c2767cd0..c723e0552d77 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1459,6 +1459,15 @@ static void smb_direct_disconnect(struct ksmbd_transport *t)
free_transport(st);
}
+static void smb_direct_shutdown(struct ksmbd_transport *t)
+{
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+
+ ksmbd_debug(RDMA, "smb-direct shutdown cm_id=%p\n", st->cm_id);
+
+ smb_direct_disconnect_rdma_work(&st->disconnect_work);
+}
+
static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event)
{
@@ -2207,6 +2216,7 @@ bool ksmbd_rdma_capable_netdev(struct net_device *netdev)
static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
.prepare = smb_direct_prepare,
.disconnect = smb_direct_disconnect,
+ .shutdown = smb_direct_shutdown,
.writev = smb_direct_writev,
.read = smb_direct_read,
.rdma_read = smb_direct_rdma_read,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 022/154] ksmbd: smbd: fix missing client's memory region invalidation
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (20 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 021/154] ksmbd: add smb-direct shutdown Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 023/154] ksmbd: smbd: validate buffer descriptor structures Namjae Jeon
` (132 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 2fd5dcb1c8ef96c9f0fa8bda53ca480524b80ae7 ]
if the Channel of a SMB2 WRITE request is
SMB2_CHANNEL_RDMA_V1_INVALIDTE, a client
does not invalidate its memory regions but
ksmbd must do it by sending a SMB2 WRITE response
with IB_WR_SEND_WITH_INV.
But if errors occur while processing a SMB2
READ/WRITE request, ksmbd sends a response
with IB_WR_SEND. So a client could use memory
regions already in use.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 71 +++++++++++++++++++++++++++++-----------------
1 file changed, 45 insertions(+), 26 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 7b7b620d2d66..51198d3b4bb6 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6203,25 +6203,33 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
return err;
}
-static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work,
- struct smb2_read_req *req, void *data_buf,
- size_t length)
+static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
+ struct smb2_buffer_desc_v1 *desc,
+ __le32 Channel,
+ __le16 ChannelInfoOffset,
+ __le16 ChannelInfoLength)
{
- struct smb2_buffer_desc_v1 *desc =
- (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
- int err;
-
if (work->conn->dialect == SMB30_PROT_ID &&
- req->Channel != SMB2_CHANNEL_RDMA_V1)
+ Channel != SMB2_CHANNEL_RDMA_V1)
return -EINVAL;
- if (req->ReadChannelInfoOffset == 0 ||
- le16_to_cpu(req->ReadChannelInfoLength) < sizeof(*desc))
+ if (ChannelInfoOffset == 0 ||
+ le16_to_cpu(ChannelInfoLength) < sizeof(*desc))
return -EINVAL;
work->need_invalidate_rkey =
- (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
+ (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
work->remote_key = le32_to_cpu(desc->token);
+ return 0;
+}
+
+static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work,
+ struct smb2_read_req *req, void *data_buf,
+ size_t length)
+{
+ struct smb2_buffer_desc_v1 *desc =
+ (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
+ int err;
err = ksmbd_conn_rdma_write(work->conn, data_buf, length,
le32_to_cpu(desc->token),
@@ -6263,6 +6271,18 @@ int smb2_read(struct ksmbd_work *work)
return smb2_read_pipe(work);
}
+ if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
+ req->Channel == SMB2_CHANNEL_RDMA_V1) {
+ err = smb2_set_remote_key_for_rdma(work,
+ (struct smb2_buffer_desc_v1 *)
+ &req->Buffer[0],
+ req->Channel,
+ req->ReadChannelInfoOffset,
+ req->ReadChannelInfoLength);
+ if (err)
+ goto out;
+ }
+
fp = ksmbd_lookup_fd_slow(work, le64_to_cpu(req->VolatileFileId),
le64_to_cpu(req->PersistentFileId));
if (!fp) {
@@ -6448,21 +6468,6 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
desc = (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
- if (work->conn->dialect == SMB30_PROT_ID &&
- req->Channel != SMB2_CHANNEL_RDMA_V1)
- return -EINVAL;
-
- if (req->Length != 0 || req->DataOffset != 0)
- return -EINVAL;
-
- if (req->WriteChannelInfoOffset == 0 ||
- le16_to_cpu(req->WriteChannelInfoLength) < sizeof(*desc))
- return -EINVAL;
-
- work->need_invalidate_rkey =
- (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
- work->remote_key = le32_to_cpu(desc->token);
-
data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
if (!data_buf)
return -ENOMEM;
@@ -6509,6 +6514,20 @@ int smb2_write(struct ksmbd_work *work)
return smb2_write_pipe(work);
}
+ if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
+ req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
+ if (req->Length != 0 || req->DataOffset != 0)
+ return -EINVAL;
+ err = smb2_set_remote_key_for_rdma(work,
+ (struct smb2_buffer_desc_v1 *)
+ &req->Buffer[0],
+ req->Channel,
+ req->WriteChannelInfoOffset,
+ req->WriteChannelInfoLength);
+ if (err)
+ goto out;
+ }
+
if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
ksmbd_debug(SMB, "User does not have write permission\n");
err = -EACCES;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 023/154] ksmbd: smbd: validate buffer descriptor structures
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (21 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 022/154] ksmbd: smbd: fix missing client's memory region invalidation Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 024/154] ksmbd: add support for key exchange Namjae Jeon
` (131 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 6d896d3b44cf64ab9b2483697e222098e7b72f70 ]
Check ChannelInfoOffset and ChannelInfoLength
to validate buffer descriptor structures.
And add a debug log to print the structures'
content.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 51198d3b4bb6..99ae8f3f3d92 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6209,13 +6209,26 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
__le16 ChannelInfoOffset,
__le16 ChannelInfoLength)
{
+ unsigned int i, ch_count;
+
if (work->conn->dialect == SMB30_PROT_ID &&
Channel != SMB2_CHANNEL_RDMA_V1)
return -EINVAL;
- if (ChannelInfoOffset == 0 ||
- le16_to_cpu(ChannelInfoLength) < sizeof(*desc))
+ ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc);
+ if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) {
+ for (i = 0; i < ch_count; i++) {
+ pr_info("RDMA r/w request %#x: token %#x, length %#x\n",
+ i,
+ le32_to_cpu(desc[i].token),
+ le32_to_cpu(desc[i].length));
+ }
+ }
+ if (ch_count != 1) {
+ ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n",
+ ch_count);
return -EINVAL;
+ }
work->need_invalidate_rkey =
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
@@ -6273,9 +6286,15 @@ int smb2_read(struct ksmbd_work *work)
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
+ unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
+
+ if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
+ err = -EINVAL;
+ goto out;
+ }
err = smb2_set_remote_key_for_rdma(work,
(struct smb2_buffer_desc_v1 *)
- &req->Buffer[0],
+ ((char *)req + ch_offset),
req->Channel,
req->ReadChannelInfoOffset,
req->ReadChannelInfoLength);
@@ -6516,11 +6535,16 @@ int smb2_write(struct ksmbd_work *work)
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
- if (req->Length != 0 || req->DataOffset != 0)
- return -EINVAL;
+ unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
+
+ if (req->Length != 0 || req->DataOffset != 0 ||
+ ch_offset < offsetof(struct smb2_write_req, Buffer)) {
+ err = -EINVAL;
+ goto out;
+ }
err = smb2_set_remote_key_for_rdma(work,
(struct smb2_buffer_desc_v1 *)
- &req->Buffer[0],
+ ((char *)req + ch_offset),
req->Channel,
req->WriteChannelInfoOffset,
req->WriteChannelInfoLength);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 024/154] ksmbd: add support for key exchange
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (22 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 023/154] ksmbd: smbd: validate buffer descriptor structures Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 025/154] ksmbd: use netif_is_bridge_port Namjae Jeon
` (130 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit f9929ef6a2a55f03aac61248c6a3a987b8546f2a ]
When mounting cifs client, can see the following warning message.
CIFS: decode_ntlmssp_challenge: authentication has been weakened as server
does not support key exchange
To remove this warning message, Add support for key exchange feature to
ksmbd. This patch decrypts 16-byte ciphertext value sent by the client
using RC4 with session key. The decrypted value is the recovered secondary
key that will use instead of the session key for signing and sealing.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index 33cb94ed6f66..2048e0546116 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -29,6 +29,7 @@
#include "mgmt/user_config.h"
#include "crypto_ctx.h"
#include "transport_ipc.h"
+#include "../smbfs_common/arc4.h"
/*
* Fixed format data defining GSS header and fixed string
@@ -342,6 +343,29 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
nt_len - CIFS_ENCPWD_SIZE,
domain_name, conn->ntlmssp.cryptkey);
kfree(domain_name);
+
+ /* The recovered secondary session key */
+ if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) {
+ struct arc4_ctx *ctx_arc4;
+ unsigned int sess_key_off, sess_key_len;
+
+ sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset);
+ sess_key_len = le16_to_cpu(authblob->SessionKey.Length);
+
+ if (blob_len < (u64)sess_key_off + sess_key_len)
+ return -EINVAL;
+
+ ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
+ if (!ctx_arc4)
+ return -ENOMEM;
+
+ cifs_arc4_setkey(ctx_arc4, sess->sess_key,
+ SMB2_NTLMV2_SESSKEY_SIZE);
+ cifs_arc4_crypt(ctx_arc4, sess->sess_key,
+ (char *)authblob + sess_key_off, sess_key_len);
+ kfree_sensitive(ctx_arc4);
+ }
+
return ret;
}
@@ -414,6 +438,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
(cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
+ if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
+ flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
+
chgblob->NegotiateFlags = cpu_to_le32(flags);
len = strlen(ksmbd_netbios_name());
name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 025/154] ksmbd: use netif_is_bridge_port
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (23 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 024/154] ksmbd: add support for key exchange Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 026/154] ksmbd: store fids as opaque u64 integers Namjae Jeon
` (129 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Tobias Klauser, Namjae Jeon, Steve French
From: Tobias Klauser <tklauser@distanz.ch>
[ Upstream commit 1b699bf3a8786f7d41eebd9f6ba673185fa5b6bd ]
Use netif_is_bridge_port defined in <linux/netdevice.h> instead of
open-coding it.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_tcp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
index d1d7954368a5..4995f74fb21c 100644
--- a/fs/ksmbd/transport_tcp.c
+++ b/fs/ksmbd/transport_tcp.c
@@ -505,7 +505,7 @@ static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
switch (event) {
case NETDEV_UP:
- if (netdev->priv_flags & IFF_BRIDGE_PORT)
+ if (netif_is_bridge_port(netdev))
return NOTIFY_OK;
list_for_each_entry(iface, &iface_list, entry) {
@@ -614,7 +614,7 @@ int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz)
rtnl_lock();
for_each_netdev(&init_net, netdev) {
- if (netdev->priv_flags & IFF_BRIDGE_PORT)
+ if (netif_is_bridge_port(netdev))
continue;
if (!alloc_iface(kstrdup(netdev->name, GFP_KERNEL)))
return -ENOMEM;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 026/154] ksmbd: store fids as opaque u64 integers
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (24 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 025/154] ksmbd: use netif_is_bridge_port Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 027/154] ksmbd: shorten experimental warning on loading the module Namjae Jeon
` (128 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Paulo Alcantara (SUSE), Tom Talpey, Namjae Jeon,
Steve French
From: "Paulo Alcantara (SUSE)" <pc@cjr.nz>
[ Upstream commit 2d004c6cae567e33ab2e197757181c72a322451f ]
There is no need to store the fids as le64 integers as they are opaque
to the client and only used for equality.
Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Tom Talpey <tom@talpey.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 94 +++++++++++++++++++---------------------------
fs/ksmbd/smb2pdu.h | 34 ++++++++---------
2 files changed, 56 insertions(+), 72 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 99ae8f3f3d92..2b32e90742e0 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -392,12 +392,8 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
* command in the compound request
*/
if (req->Command == SMB2_CREATE && rsp->Status == STATUS_SUCCESS) {
- work->compound_fid =
- le64_to_cpu(((struct smb2_create_rsp *)rsp)->
- VolatileFileId);
- work->compound_pfid =
- le64_to_cpu(((struct smb2_create_rsp *)rsp)->
- PersistentFileId);
+ work->compound_fid = ((struct smb2_create_rsp *)rsp)->VolatileFileId;
+ work->compound_pfid = ((struct smb2_create_rsp *)rsp)->PersistentFileId;
work->compound_sid = le64_to_cpu(rsp->SessionId);
}
@@ -2192,7 +2188,7 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
rsp->EndofFile = cpu_to_le64(0);
rsp->FileAttributes = ATTR_NORMAL_LE;
rsp->Reserved2 = 0;
- rsp->VolatileFileId = cpu_to_le64(id);
+ rsp->VolatileFileId = id;
rsp->PersistentFileId = 0;
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
@@ -3230,8 +3226,8 @@ int smb2_open(struct ksmbd_work *work)
rsp->Reserved2 = 0;
- rsp->PersistentFileId = cpu_to_le64(fp->persistent_id);
- rsp->VolatileFileId = cpu_to_le64(fp->volatile_id);
+ rsp->PersistentFileId = fp->persistent_id;
+ rsp->VolatileFileId = fp->volatile_id;
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
@@ -3939,9 +3935,7 @@ int smb2_query_dir(struct ksmbd_work *work)
goto err_out2;
}
- dir_fp = ksmbd_lookup_fd_slow(work,
- le64_to_cpu(req->VolatileFileId),
- le64_to_cpu(req->PersistentFileId));
+ dir_fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
if (!dir_fp) {
rc = -EBADF;
goto err_out2;
@@ -4169,12 +4163,12 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
* Windows can sometime send query file info request on
* pipe without opening it, checking error condition here
*/
- id = le64_to_cpu(req->VolatileFileId);
+ id = req->VolatileFileId;
if (!ksmbd_session_rpc_method(sess, id))
return -ENOENT;
ksmbd_debug(SMB, "FileInfoClass %u, FileId 0x%llx\n",
- req->FileInfoClass, le64_to_cpu(req->VolatileFileId));
+ req->FileInfoClass, req->VolatileFileId);
switch (req->FileInfoClass) {
case FILE_STANDARD_INFORMATION:
@@ -4804,7 +4798,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
}
if (work->next_smb2_rcv_hdr_off) {
- if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
+ if (!has_file_id(req->VolatileFileId)) {
ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid);
id = work->compound_fid;
@@ -4813,8 +4807,8 @@ static int smb2_get_info_file(struct ksmbd_work *work,
}
if (!has_file_id(id)) {
- id = le64_to_cpu(req->VolatileFileId);
- pid = le64_to_cpu(req->PersistentFileId);
+ id = req->VolatileFileId;
+ pid = req->PersistentFileId;
}
fp = ksmbd_lookup_fd_slow(work, id, pid);
@@ -5188,7 +5182,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
}
if (work->next_smb2_rcv_hdr_off) {
- if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
+ if (!has_file_id(req->VolatileFileId)) {
ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid);
id = work->compound_fid;
@@ -5197,8 +5191,8 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
}
if (!has_file_id(id)) {
- id = le64_to_cpu(req->VolatileFileId);
- pid = le64_to_cpu(req->PersistentFileId);
+ id = req->VolatileFileId;
+ pid = req->PersistentFileId;
}
fp = ksmbd_lookup_fd_slow(work, id, pid);
@@ -5299,7 +5293,7 @@ static noinline int smb2_close_pipe(struct ksmbd_work *work)
struct smb2_close_req *req = smb2_get_msg(work->request_buf);
struct smb2_close_rsp *rsp = smb2_get_msg(work->response_buf);
- id = le64_to_cpu(req->VolatileFileId);
+ id = req->VolatileFileId;
ksmbd_session_rpc_close(work->sess, id);
rsp->StructureSize = cpu_to_le16(60);
@@ -5358,7 +5352,7 @@ int smb2_close(struct ksmbd_work *work)
}
if (work->next_smb2_rcv_hdr_off &&
- !has_file_id(le64_to_cpu(req->VolatileFileId))) {
+ !has_file_id(req->VolatileFileId)) {
if (!has_file_id(work->compound_fid)) {
/* file already closed, return FILE_CLOSED */
ksmbd_debug(SMB, "file already closed\n");
@@ -5377,7 +5371,7 @@ int smb2_close(struct ksmbd_work *work)
work->compound_pfid = KSMBD_NO_FID;
}
} else {
- volatile_id = le64_to_cpu(req->VolatileFileId);
+ volatile_id = req->VolatileFileId;
}
ksmbd_debug(SMB, "volatile_id = %llu\n", volatile_id);
@@ -6070,7 +6064,7 @@ int smb2_set_info(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work);
- if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
+ if (!has_file_id(req->VolatileFileId)) {
ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid);
id = work->compound_fid;
@@ -6082,8 +6076,8 @@ int smb2_set_info(struct ksmbd_work *work)
}
if (!has_file_id(id)) {
- id = le64_to_cpu(req->VolatileFileId);
- pid = le64_to_cpu(req->PersistentFileId);
+ id = req->VolatileFileId;
+ pid = req->PersistentFileId;
}
fp = ksmbd_lookup_fd_slow(work, id, pid);
@@ -6161,7 +6155,7 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
struct smb2_read_req *req = smb2_get_msg(work->request_buf);
struct smb2_read_rsp *rsp = smb2_get_msg(work->response_buf);
- id = le64_to_cpu(req->VolatileFileId);
+ id = req->VolatileFileId;
inc_rfc1001_len(work->response_buf, 16);
rpc_resp = ksmbd_rpc_read(work->sess, id);
@@ -6302,8 +6296,7 @@ int smb2_read(struct ksmbd_work *work)
goto out;
}
- fp = ksmbd_lookup_fd_slow(work, le64_to_cpu(req->VolatileFileId),
- le64_to_cpu(req->PersistentFileId));
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
if (!fp) {
err = -ENOENT;
goto out;
@@ -6422,7 +6415,7 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
size_t length;
length = le32_to_cpu(req->Length);
- id = le64_to_cpu(req->VolatileFileId);
+ id = req->VolatileFileId;
if (le16_to_cpu(req->DataOffset) ==
offsetof(struct smb2_write_req, Buffer)) {
@@ -6558,8 +6551,7 @@ int smb2_write(struct ksmbd_work *work)
goto out;
}
- fp = ksmbd_lookup_fd_slow(work, le64_to_cpu(req->VolatileFileId),
- le64_to_cpu(req->PersistentFileId));
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
if (!fp) {
err = -ENOENT;
goto out;
@@ -6668,12 +6660,9 @@ int smb2_flush(struct ksmbd_work *work)
WORK_BUFFERS(work, req, rsp);
- ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n",
- le64_to_cpu(req->VolatileFileId));
+ ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n", req->VolatileFileId);
- err = ksmbd_vfs_fsync(work,
- le64_to_cpu(req->VolatileFileId),
- le64_to_cpu(req->PersistentFileId));
+ err = ksmbd_vfs_fsync(work, req->VolatileFileId, req->PersistentFileId);
if (err)
goto out;
@@ -6888,12 +6877,9 @@ int smb2_lock(struct ksmbd_work *work)
int prior_lock = 0;
ksmbd_debug(SMB, "Received lock request\n");
- fp = ksmbd_lookup_fd_slow(work,
- le64_to_cpu(req->VolatileFileId),
- le64_to_cpu(req->PersistentFileId));
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
if (!fp) {
- ksmbd_debug(SMB, "Invalid file id for lock : %llu\n",
- le64_to_cpu(req->VolatileFileId));
+ ksmbd_debug(SMB, "Invalid file id for lock : %llu\n", req->VolatileFileId);
err = -ENOENT;
goto out2;
}
@@ -7248,8 +7234,8 @@ static int fsctl_copychunk(struct ksmbd_work *work,
ci_rsp = (struct copychunk_ioctl_rsp *)&rsp->Buffer[0];
- rsp->VolatileFileId = cpu_to_le64(volatile_id);
- rsp->PersistentFileId = cpu_to_le64(persistent_id);
+ rsp->VolatileFileId = volatile_id;
+ rsp->PersistentFileId = persistent_id;
ci_rsp->ChunksWritten =
cpu_to_le32(ksmbd_server_side_copy_max_chunk_count());
ci_rsp->ChunkBytesWritten =
@@ -7463,8 +7449,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
if (nii_rsp)
nii_rsp->Next = 0;
- rsp->PersistentFileId = cpu_to_le64(SMB2_NO_FID);
- rsp->VolatileFileId = cpu_to_le64(SMB2_NO_FID);
+ rsp->PersistentFileId = SMB2_NO_FID;
+ rsp->VolatileFileId = SMB2_NO_FID;
return nbytes;
}
@@ -7634,9 +7620,7 @@ static int fsctl_request_resume_key(struct ksmbd_work *work,
{
struct ksmbd_file *fp;
- fp = ksmbd_lookup_fd_slow(work,
- le64_to_cpu(req->VolatileFileId),
- le64_to_cpu(req->PersistentFileId));
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
if (!fp)
return -ENOENT;
@@ -7666,7 +7650,7 @@ int smb2_ioctl(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work);
- if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
+ if (!has_file_id(req->VolatileFileId)) {
ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid);
id = work->compound_fid;
@@ -7677,7 +7661,7 @@ int smb2_ioctl(struct ksmbd_work *work)
}
if (!has_file_id(id))
- id = le64_to_cpu(req->VolatileFileId);
+ id = req->VolatileFileId;
if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) {
rsp->hdr.Status = STATUS_NOT_SUPPORTED;
@@ -7748,8 +7732,8 @@ int smb2_ioctl(struct ksmbd_work *work)
goto out;
nbytes = sizeof(struct validate_negotiate_info_rsp);
- rsp->PersistentFileId = cpu_to_le64(SMB2_NO_FID);
- rsp->VolatileFileId = cpu_to_le64(SMB2_NO_FID);
+ rsp->PersistentFileId = SMB2_NO_FID;
+ rsp->VolatileFileId = SMB2_NO_FID;
break;
case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
ret = fsctl_query_iface_info_ioctl(conn, rsp, out_buf_len);
@@ -7797,8 +7781,8 @@ int smb2_ioctl(struct ksmbd_work *work)
(struct copychunk_ioctl_req *)&req->Buffer[0],
le32_to_cpu(req->CntCode),
le32_to_cpu(req->InputCount),
- le64_to_cpu(req->VolatileFileId),
- le64_to_cpu(req->PersistentFileId),
+ req->VolatileFileId,
+ req->PersistentFileId,
rsp);
break;
case FSCTL_SET_SPARSE:
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index 3ae27ccfc20d..10776df5baa7 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -634,8 +634,8 @@ struct create_durable_reconn_req {
union {
__u8 Reserved[16];
struct {
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
} Fid;
} Data;
} __packed;
@@ -644,8 +644,8 @@ struct create_durable_reconn_v2_req {
struct create_context ccontext;
__u8 Name[8];
struct {
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
} Fid;
__u8 CreateGuid[16];
__le32 Flags;
@@ -889,8 +889,8 @@ struct smb2_ioctl_req {
__le16 StructureSize; /* Must be 57 */
__le16 Reserved; /* offset from start of SMB2 header to write data */
__le32 CntCode;
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
__le32 InputOffset; /* Reserved MBZ */
__le32 InputCount;
__le32 MaxInputResponse;
@@ -907,8 +907,8 @@ struct smb2_ioctl_rsp {
__le16 StructureSize; /* Must be 49 */
__le16 Reserved; /* offset from start of SMB2 header to write data */
__le32 CntCode;
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
__le32 InputOffset; /* Reserved MBZ */
__le32 InputCount;
__le32 OutputOffset;
@@ -977,7 +977,7 @@ struct file_object_buf_type1_ioctl_rsp {
} __packed;
struct resume_key_ioctl_rsp {
- __le64 ResumeKey[3];
+ __u64 ResumeKey[3];
__le32 ContextLength;
__u8 Context[4]; /* ignored, Windows sets to 4 bytes of zero */
} __packed;
@@ -1089,8 +1089,8 @@ struct smb2_lock_req {
__le16 StructureSize; /* Must be 48 */
__le16 LockCount;
__le32 Reserved;
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
/* Followed by at least one */
struct smb2_lock_element locks[1];
} __packed;
@@ -1125,8 +1125,8 @@ struct smb2_query_directory_req {
__u8 FileInformationClass;
__u8 Flags;
__le32 FileIndex;
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
__le16 FileNameOffset;
__le16 FileNameLength;
__le32 OutputBufferLength;
@@ -1172,8 +1172,8 @@ struct smb2_query_info_req {
__le32 InputBufferLength;
__le32 AdditionalInformation;
__le32 Flags;
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
__u8 Buffer[1];
} __packed;
@@ -1194,8 +1194,8 @@ struct smb2_set_info_req {
__le16 BufferOffset;
__u16 Reserved;
__le32 AdditionalInformation;
- __le64 PersistentFileId;
- __le64 VolatileFileId;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
__u8 Buffer[1];
} __packed;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 027/154] ksmbd: shorten experimental warning on loading the module
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (25 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 026/154] ksmbd: store fids as opaque u64 integers Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 028/154] ksmbd: Remove a redundant zeroing of memory Namjae Jeon
` (127 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Steve French, Namjae Jeon
From: Steve French <stfrench@microsoft.com>
[ Upstream commit adc32821409aef8d7f6d868c20a96f4901f48705 ]
ksmbd is continuing to improve. Shorten the warning message
logged the first time it is loaded to:
"The ksmbd server is experimental"
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/server.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index bca0fbf3c67c..049d68831ccd 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -590,7 +590,7 @@ static int __init ksmbd_server_init(void)
if (ret)
goto err_crypto_destroy;
- pr_warn_once("The ksmbd server is experimental, use at your own risk.\n");
+ pr_warn_once("The ksmbd server is experimental\n");
return 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 028/154] ksmbd: Remove a redundant zeroing of memory
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (26 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 027/154] ksmbd: shorten experimental warning on loading the module Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 029/154] ksmbd: replace usage of found with dedicated list iterator variable Namjae Jeon
` (126 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Christophe JAILLET, Hyunchul Lee, Namjae Jeon,
Steve French
From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
[ Upstream commit 56b401fb0c506120f25c1b4feeb96d9117efe171 ]
fill_transform_hdr() has only one caller that already clears tr_buf (it is
kzalloc'ed).
So there is no need to clear it another time here.
Remove the superfluous memset() and add a comment to remind that the caller
must clear the buffer.
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Acked-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 2b32e90742e0..a5fc7b7fd590 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -8601,7 +8601,7 @@ static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
struct smb2_hdr *hdr = smb2_get_msg(old_buf);
unsigned int orig_len = get_rfc1002_len(old_buf);
- memset(tr_buf, 0, sizeof(struct smb2_transform_hdr) + 4);
+ /* tr_buf must be cleared by the caller */
tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
tr_hdr->Flags = cpu_to_le16(0x01);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 029/154] ksmbd: replace usage of found with dedicated list iterator variable
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (27 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 028/154] ksmbd: Remove a redundant zeroing of memory Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 030/154] smb3: fix ksmbd bigendian bug in oplock break, and move its struct to smbfs_common Namjae Jeon
` (125 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Jakob Koschel, Hyunchul Lee, Namjae Jeon, Steve French
From: Jakob Koschel <jakobkoschel@gmail.com>
[ Upstream commit edf5f0548fbb77e20b898460dc25281b0f4d974d ]
To move the list iterator variable into the list_for_each_entry_*()
macro in the future it should be avoided to use the list iterator
variable after the loop body.
To *never* use the list iterator variable after the loop it was
concluded to use a separate iterator variable instead of a
found boolean [1].
This removes the need to use a found variable and simply checking if
the variable was set, can determine if the break/goto was hit.
Link: https://lore.kernel.org/all/CAHk-=wgRr_D8CB-D9Kg-c=EHreAsk5SqXPwr9Y7k9sA6cWXJ6w@mail.gmail.com/
Signed-off-by: Jakob Koschel <jakobkoschel@gmail.com>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index a5fc7b7fd590..2dc67809a2c7 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6691,8 +6691,7 @@ int smb2_cancel(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
struct smb2_hdr *chdr;
- struct ksmbd_work *cancel_work = NULL;
- int canceled = 0;
+ struct ksmbd_work *cancel_work = NULL, *iter;
struct list_head *command_list;
ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
@@ -6702,11 +6701,11 @@ int smb2_cancel(struct ksmbd_work *work)
command_list = &conn->async_requests;
spin_lock(&conn->request_lock);
- list_for_each_entry(cancel_work, command_list,
+ list_for_each_entry(iter, command_list,
async_request_entry) {
- chdr = smb2_get_msg(cancel_work->request_buf);
+ chdr = smb2_get_msg(iter->request_buf);
- if (cancel_work->async_id !=
+ if (iter->async_id !=
le64_to_cpu(hdr->Id.AsyncId))
continue;
@@ -6714,7 +6713,7 @@ int smb2_cancel(struct ksmbd_work *work)
"smb2 with AsyncId %llu cancelled command = 0x%x\n",
le64_to_cpu(hdr->Id.AsyncId),
le16_to_cpu(chdr->Command));
- canceled = 1;
+ cancel_work = iter;
break;
}
spin_unlock(&conn->request_lock);
@@ -6722,24 +6721,24 @@ int smb2_cancel(struct ksmbd_work *work)
command_list = &conn->requests;
spin_lock(&conn->request_lock);
- list_for_each_entry(cancel_work, command_list, request_entry) {
- chdr = smb2_get_msg(cancel_work->request_buf);
+ list_for_each_entry(iter, command_list, request_entry) {
+ chdr = smb2_get_msg(iter->request_buf);
if (chdr->MessageId != hdr->MessageId ||
- cancel_work == work)
+ iter == work)
continue;
ksmbd_debug(SMB,
"smb2 with mid %llu cancelled command = 0x%x\n",
le64_to_cpu(hdr->MessageId),
le16_to_cpu(chdr->Command));
- canceled = 1;
+ cancel_work = iter;
break;
}
spin_unlock(&conn->request_lock);
}
- if (canceled) {
+ if (cancel_work) {
cancel_work->state = KSMBD_WORK_CANCELLED;
if (cancel_work->cancel_fn)
cancel_work->cancel_fn(cancel_work->cancel_argv);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 030/154] smb3: fix ksmbd bigendian bug in oplock break, and move its struct to smbfs_common
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (28 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 029/154] ksmbd: replace usage of found with dedicated list iterator variable Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 031/154] ksmbd: remove filename in ksmbd_file Namjae Jeon
` (124 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Steve French, Paulo Alcantara, Namjae Jeon
From: Steve French <stfrench@microsoft.com>
[ Upstream commit c7803b05f74bc3941b127f3155671e1944f632ae ]
Fix an endian bug in ksmbd for one remaining use of
Persistent/VolatileFid that unnecessarily converted it (it is an
opaque endian field that does not need to be and should not
be converted) in oplock_break for ksmbd, and move the definitions
for the oplock and lease break protocol requests and responses
to fs/smbfs_common/smb2pdu.h
Also move a few more definitions for various protocol requests
that were duplicated (in fs/cifs/smb2pdu.h and fs/ksmbd/smb2pdu.h)
into fs/smbfs_common/smb2pdu.h including:
- various ioctls and reparse structures
- validate negotiate request and response structs
- duplicate extents structs
Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/oplock.c | 4 ++--
fs/ksmbd/smb2pdu.c | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index e1d854609195..2e52ebc209d2 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -657,8 +657,8 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;
rsp->Reserved = 0;
rsp->Reserved2 = 0;
- rsp->PersistentFid = cpu_to_le64(fp->persistent_id);
- rsp->VolatileFid = cpu_to_le64(fp->volatile_id);
+ rsp->PersistentFid = fp->persistent_id;
+ rsp->VolatileFid = fp->volatile_id;
inc_rfc1001_len(work->response_buf, 24);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 2dc67809a2c7..6b4132ea1956 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -7995,8 +7995,8 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
char req_oplevel = 0, rsp_oplevel = 0;
unsigned int oplock_change_type;
- volatile_id = le64_to_cpu(req->VolatileFid);
- persistent_id = le64_to_cpu(req->PersistentFid);
+ volatile_id = req->VolatileFid;
+ persistent_id = req->PersistentFid;
req_oplevel = req->OplockLevel;
ksmbd_debug(OPLOCK, "v_id %llu, p_id %llu request oplock level %d\n",
volatile_id, persistent_id, req_oplevel);
@@ -8091,8 +8091,8 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
rsp->OplockLevel = rsp_oplevel;
rsp->Reserved = 0;
rsp->Reserved2 = 0;
- rsp->VolatileFid = cpu_to_le64(volatile_id);
- rsp->PersistentFid = cpu_to_le64(persistent_id);
+ rsp->VolatileFid = volatile_id;
+ rsp->PersistentFid = persistent_id;
inc_rfc1001_len(work->response_buf, 24);
return;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 031/154] ksmbd: remove filename in ksmbd_file
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (29 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 030/154] smb3: fix ksmbd bigendian bug in oplock break, and move its struct to smbfs_common Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 032/154] ksmbd: validate length in smb2_write() Namjae Jeon
` (123 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Hyunchul Lee, Steve French
[ Upstream commit 50f500b7f6335404b18bbffa93e3a905a08d061a ]
If the filename is change by underlying rename the server, fp->filename
and real filename can be different. This patch remove the uses of
fp->filename in ksmbd and replace it with d_path().
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/misc.c | 40 +++++++++++++++++++++++++++++++---------
fs/ksmbd/misc.h | 3 ++-
fs/ksmbd/oplock.c | 30 ------------------------------
fs/ksmbd/oplock.h | 2 --
fs/ksmbd/smb2pdu.c | 21 +++++++--------------
fs/ksmbd/vfs.c | 6 ++----
fs/ksmbd/vfs_cache.c | 1 -
fs/ksmbd/vfs_cache.h | 1 -
8 files changed, 42 insertions(+), 62 deletions(-)
diff --git a/fs/ksmbd/misc.c b/fs/ksmbd/misc.c
index 60e7ac62c917..1e2076a53bed 100644
--- a/fs/ksmbd/misc.c
+++ b/fs/ksmbd/misc.c
@@ -158,19 +158,41 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
* Return : windows path string or error
*/
-char *convert_to_nt_pathname(char *filename)
+char *convert_to_nt_pathname(struct ksmbd_share_config *share,
+ struct path *path)
{
- char *ab_pathname;
+ char *pathname, *ab_pathname, *nt_pathname;
+ int share_path_len = share->path_sz;
- if (strlen(filename) == 0)
- filename = "\\";
+ pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!pathname)
+ return ERR_PTR(-EACCES);
- ab_pathname = kstrdup(filename, GFP_KERNEL);
- if (!ab_pathname)
- return NULL;
+ ab_pathname = d_path(path, pathname, PATH_MAX);
+ if (IS_ERR(ab_pathname)) {
+ nt_pathname = ERR_PTR(-EACCES);
+ goto free_pathname;
+ }
+
+ if (strncmp(ab_pathname, share->path, share_path_len)) {
+ nt_pathname = ERR_PTR(-EACCES);
+ goto free_pathname;
+ }
+
+ nt_pathname = kzalloc(strlen(&ab_pathname[share_path_len]) + 2, GFP_KERNEL);
+ if (!nt_pathname) {
+ nt_pathname = ERR_PTR(-ENOMEM);
+ goto free_pathname;
+ }
+ if (ab_pathname[share_path_len] == '\0')
+ strcpy(nt_pathname, "/");
+ strcat(nt_pathname, &ab_pathname[share_path_len]);
+
+ ksmbd_conv_path_to_windows(nt_pathname);
- ksmbd_conv_path_to_windows(ab_pathname);
- return ab_pathname;
+free_pathname:
+ kfree(pathname);
+ return nt_pathname;
}
int get_nlink(struct kstat *st)
diff --git a/fs/ksmbd/misc.h b/fs/ksmbd/misc.h
index 253366bd0951..aae2a252945f 100644
--- a/fs/ksmbd/misc.h
+++ b/fs/ksmbd/misc.h
@@ -14,7 +14,8 @@ struct ksmbd_file;
int match_pattern(const char *str, size_t len, const char *pattern);
int ksmbd_validate_filename(char *filename);
int parse_stream_name(char *filename, char **stream_name, int *s_type);
-char *convert_to_nt_pathname(char *filename);
+char *convert_to_nt_pathname(struct ksmbd_share_config *share,
+ struct path *path);
int get_nlink(struct kstat *st);
void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(char *path);
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index 2e52ebc209d2..ae5fc4b2c133 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -1696,33 +1696,3 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
read_unlock(&lease_list_lock);
return ret_op;
}
-
-int smb2_check_durable_oplock(struct ksmbd_file *fp,
- struct lease_ctx_info *lctx, char *name)
-{
- struct oplock_info *opinfo = opinfo_get(fp);
- int ret = 0;
-
- if (opinfo && opinfo->is_lease) {
- if (!lctx) {
- pr_err("open does not include lease\n");
- ret = -EBADF;
- goto out;
- }
- if (memcmp(opinfo->o_lease->lease_key, lctx->lease_key,
- SMB2_LEASE_KEY_SIZE)) {
- pr_err("invalid lease key\n");
- ret = -EBADF;
- goto out;
- }
- if (name && strcmp(fp->filename, name)) {
- pr_err("invalid name reconnect %s\n", name);
- ret = -EINVAL;
- goto out;
- }
- }
-out:
- if (opinfo)
- opinfo_put(opinfo);
- return ret;
-}
diff --git a/fs/ksmbd/oplock.h b/fs/ksmbd/oplock.h
index e1ba363b412a..4b0fe6da7694 100644
--- a/fs/ksmbd/oplock.h
+++ b/fs/ksmbd/oplock.h
@@ -124,6 +124,4 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
struct lease_ctx_info *lctx);
void destroy_lease_table(struct ksmbd_conn *conn);
-int smb2_check_durable_oplock(struct ksmbd_file *fp,
- struct lease_ctx_info *lctx, char *name);
#endif /* __KSMBD_OPLOCK_H */
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 6b4132ea1956..a1bcb822c95d 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2988,7 +2988,6 @@ int smb2_open(struct ksmbd_work *work)
goto err_out;
}
- fp->filename = name;
fp->cdoption = req->CreateDisposition;
fp->daccess = daccess;
fp->saccess = req->ShareAccess;
@@ -3343,14 +3342,13 @@ int smb2_open(struct ksmbd_work *work)
if (!rsp->hdr.Status)
rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
- if (!fp || !fp->filename)
- kfree(name);
if (fp)
ksmbd_fd_put(work, fp);
smb2_set_err_rsp(work);
ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
}
+ kfree(name);
kfree(lc);
return 0;
@@ -3969,8 +3967,6 @@ int smb2_query_dir(struct ksmbd_work *work)
ksmbd_debug(SMB, "Search pattern is %s\n", srch_ptr);
}
- ksmbd_debug(SMB, "Directory name is %s\n", dir_fp->filename);
-
if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) {
ksmbd_debug(SMB, "Restart directory scan\n");
generic_file_llseek(dir_fp->filp, 0, SEEK_SET);
@@ -4456,9 +4452,9 @@ static int get_file_all_info(struct ksmbd_work *work,
return -EACCES;
}
- filename = convert_to_nt_pathname(fp->filename);
- if (!filename)
- return -ENOMEM;
+ filename = convert_to_nt_pathname(work->tcon->share_conf, &fp->filp->f_path);
+ if (IS_ERR(filename))
+ return PTR_ERR(filename);
inode = file_inode(fp->filp);
generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
@@ -5761,8 +5757,7 @@ static int set_file_allocation_info(struct ksmbd_work *work,
size = i_size_read(inode);
rc = ksmbd_vfs_truncate(work, fp, alloc_blks * 512);
if (rc) {
- pr_err("truncate failed! filename : %s, err %d\n",
- fp->filename, rc);
+ pr_err("truncate failed!, err %d\n", rc);
return rc;
}
if (size < alloc_blks * 512)
@@ -5792,12 +5787,10 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
* truncated range.
*/
if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
- ksmbd_debug(SMB, "filename : %s truncated to newsize %lld\n",
- fp->filename, newsize);
+ ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize);
rc = ksmbd_vfs_truncate(work, fp, newsize);
if (rc) {
- ksmbd_debug(SMB, "truncate failed! filename : %s err %d\n",
- fp->filename, rc);
+ ksmbd_debug(SMB, "truncate failed!, err %d\n", rc);
if (rc != -EAGAIN)
rc = -EBADF;
return rc;
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index f76acd83c294..0092e6911b14 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -397,8 +397,7 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
nbytes = kernel_read(filp, rbuf, count, pos);
if (nbytes < 0) {
- pr_err("smb read failed for (%s), err = %zd\n",
- fp->filename, nbytes);
+ pr_err("smb read failed, err = %zd\n", nbytes);
return nbytes;
}
@@ -873,8 +872,7 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work,
err = vfs_truncate(&filp->f_path, size);
if (err)
- pr_err("truncate failed for filename : %s err %d\n",
- fp->filename, err);
+ pr_err("truncate failed, err %d\n", err);
return err;
}
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index b67ce2d52cee..52ae9937d6a1 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -328,7 +328,6 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
kfree(smb_lock);
}
- kfree(fp->filename);
if (ksmbd_stream_fd(fp))
kfree(fp->stream.name);
kmem_cache_free(filp_cache, fp);
diff --git a/fs/ksmbd/vfs_cache.h b/fs/ksmbd/vfs_cache.h
index 36239ce31afd..fcb13413fa8d 100644
--- a/fs/ksmbd/vfs_cache.h
+++ b/fs/ksmbd/vfs_cache.h
@@ -62,7 +62,6 @@ struct ksmbd_inode {
struct ksmbd_file {
struct file *filp;
- char *filename;
u64 persistent_id;
u64 volatile_id;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 032/154] ksmbd: validate length in smb2_write()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (30 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 031/154] ksmbd: remove filename in ksmbd_file Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 033/154] ksmbd: smbd: change prototypes of RDMA read/write related functions Namjae Jeon
` (122 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Marios Makassikis, Steve French
[ Upstream commit 158a66b245739e15858de42c0ba60fcf3de9b8e6 ]
The SMB2 Write packet contains data that is to be written
to a file or to a pipe. Depending on the client, there may
be padding between the header and the data field.
Currently, the length is validated only in the case padding
is present.
Since the DataOffset field always points to the beginning
of the data, there is no need to have a special case for
padding. By removing this, the length is validated in both
cases.
Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/ksmbd/smb2pdu.c | 42 ++++++++++++++++--------------------------
1 file changed, 16 insertions(+), 26 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index a1bcb822c95d..134a725332a0 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6410,23 +6410,18 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
length = le32_to_cpu(req->Length);
id = req->VolatileFileId;
- if (le16_to_cpu(req->DataOffset) ==
- offsetof(struct smb2_write_req, Buffer)) {
- data_buf = (char *)&req->Buffer[0];
- } else {
- if ((u64)le16_to_cpu(req->DataOffset) + length >
- get_rfc1002_len(work->request_buf)) {
- pr_err("invalid write data offset %u, smb_len %u\n",
- le16_to_cpu(req->DataOffset),
- get_rfc1002_len(work->request_buf));
- err = -EINVAL;
- goto out;
- }
-
- data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
- le16_to_cpu(req->DataOffset));
+ if ((u64)le16_to_cpu(req->DataOffset) + length >
+ get_rfc1002_len(work->request_buf)) {
+ pr_err("invalid write data offset %u, smb_len %u\n",
+ le16_to_cpu(req->DataOffset),
+ get_rfc1002_len(work->request_buf));
+ err = -EINVAL;
+ goto out;
}
+ data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
+ le16_to_cpu(req->DataOffset));
+
rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length);
if (rpc_resp) {
if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
@@ -6571,20 +6566,15 @@ int smb2_write(struct ksmbd_work *work)
if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
- if (le16_to_cpu(req->DataOffset) ==
+ if (le16_to_cpu(req->DataOffset) <
offsetof(struct smb2_write_req, Buffer)) {
- data_buf = (char *)&req->Buffer[0];
- } else {
- if (le16_to_cpu(req->DataOffset) <
- offsetof(struct smb2_write_req, Buffer)) {
- err = -EINVAL;
- goto out;
- }
-
- data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
- le16_to_cpu(req->DataOffset));
+ err = -EINVAL;
+ goto out;
}
+ data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
+ le16_to_cpu(req->DataOffset));
+
ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
writethrough = true;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 033/154] ksmbd: smbd: change prototypes of RDMA read/write related functions
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (31 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 032/154] ksmbd: validate length in smb2_write() Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 034/154] ksmbd: smbd: introduce read/write credits for RDMA read/write Namjae Jeon
` (121 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 1807abcf8778bcbbf584fe54da9ccbe9029c49bb ]
Change the prototypes of RDMA read/write
operations to accept a pointer and length
of buffer descriptors.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 20 ++++++++++----------
fs/ksmbd/connection.h | 27 ++++++++++++++++-----------
fs/ksmbd/smb2pdu.c | 23 ++++++++---------------
fs/ksmbd/transport_rdma.c | 30 +++++++++++++++++-------------
4 files changed, 51 insertions(+), 49 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 6e3416d9c65e..192646b8920e 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -206,31 +206,31 @@ int ksmbd_conn_write(struct ksmbd_work *work)
return 0;
}
-int ksmbd_conn_rdma_read(struct ksmbd_conn *conn, void *buf,
- unsigned int buflen, u32 remote_key, u64 remote_offset,
- u32 remote_len)
+int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
{
int ret = -EINVAL;
if (conn->transport->ops->rdma_read)
ret = conn->transport->ops->rdma_read(conn->transport,
buf, buflen,
- remote_key, remote_offset,
- remote_len);
+ desc, desc_len);
return ret;
}
-int ksmbd_conn_rdma_write(struct ksmbd_conn *conn, void *buf,
- unsigned int buflen, u32 remote_key,
- u64 remote_offset, u32 remote_len)
+int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
{
int ret = -EINVAL;
if (conn->transport->ops->rdma_write)
ret = conn->transport->ops->rdma_write(conn->transport,
buf, buflen,
- remote_key, remote_offset,
- remote_len);
+ desc, desc_len);
return ret;
}
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index fd243cdddb22..e0a25cddbb29 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -116,11 +116,14 @@ struct ksmbd_transport_ops {
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
int size, bool need_invalidate_rkey,
unsigned int remote_key);
- int (*rdma_read)(struct ksmbd_transport *t, void *buf, unsigned int len,
- u32 remote_key, u64 remote_offset, u32 remote_len);
- int (*rdma_write)(struct ksmbd_transport *t, void *buf,
- unsigned int len, u32 remote_key, u64 remote_offset,
- u32 remote_len);
+ int (*rdma_read)(struct ksmbd_transport *t,
+ void *buf, unsigned int len,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
+ int (*rdma_write)(struct ksmbd_transport *t,
+ void *buf, unsigned int len,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
};
struct ksmbd_transport {
@@ -142,12 +145,14 @@ struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn);
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
int ksmbd_conn_write(struct ksmbd_work *work);
-int ksmbd_conn_rdma_read(struct ksmbd_conn *conn, void *buf,
- unsigned int buflen, u32 remote_key, u64 remote_offset,
- u32 remote_len);
-int ksmbd_conn_rdma_write(struct ksmbd_conn *conn, void *buf,
- unsigned int buflen, u32 remote_key, u64 remote_offset,
- u32 remote_len);
+int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
+int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 134a725332a0..d26af17f383c 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6193,7 +6193,6 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
struct smb2_buffer_desc_v1 *desc,
__le32 Channel,
- __le16 ChannelInfoOffset,
__le16 ChannelInfoLength)
{
unsigned int i, ch_count;
@@ -6219,7 +6218,8 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
work->need_invalidate_rkey =
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
- work->remote_key = le32_to_cpu(desc->token);
+ if (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE)
+ work->remote_key = le32_to_cpu(desc->token);
return 0;
}
@@ -6227,14 +6227,12 @@ static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work,
struct smb2_read_req *req, void *data_buf,
size_t length)
{
- struct smb2_buffer_desc_v1 *desc =
- (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
int err;
err = ksmbd_conn_rdma_write(work->conn, data_buf, length,
- le32_to_cpu(desc->token),
- le64_to_cpu(desc->offset),
- le32_to_cpu(desc->length));
+ (struct smb2_buffer_desc_v1 *)
+ ((char *)req + le16_to_cpu(req->ReadChannelInfoOffset)),
+ le16_to_cpu(req->ReadChannelInfoLength));
if (err)
return err;
@@ -6283,7 +6281,6 @@ int smb2_read(struct ksmbd_work *work)
(struct smb2_buffer_desc_v1 *)
((char *)req + ch_offset),
req->Channel,
- req->ReadChannelInfoOffset,
req->ReadChannelInfoLength);
if (err)
goto out;
@@ -6461,21 +6458,18 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
struct ksmbd_file *fp,
loff_t offset, size_t length, bool sync)
{
- struct smb2_buffer_desc_v1 *desc;
char *data_buf;
int ret;
ssize_t nbytes;
- desc = (struct smb2_buffer_desc_v1 *)&req->Buffer[0];
-
data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
if (!data_buf)
return -ENOMEM;
ret = ksmbd_conn_rdma_read(work->conn, data_buf, length,
- le32_to_cpu(desc->token),
- le64_to_cpu(desc->offset),
- le32_to_cpu(desc->length));
+ (struct smb2_buffer_desc_v1 *)
+ ((char *)req + le16_to_cpu(req->WriteChannelInfoOffset)),
+ le16_to_cpu(req->WriteChannelInfoLength));
if (ret < 0) {
kvfree(data_buf);
return ret;
@@ -6527,7 +6521,6 @@ int smb2_write(struct ksmbd_work *work)
(struct smb2_buffer_desc_v1 *)
((char *)req + ch_offset),
req->Channel,
- req->WriteChannelInfoOffset,
req->WriteChannelInfoLength);
if (err)
goto out;
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index c723e0552d77..991eefe7fe1f 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1357,14 +1357,18 @@ static void write_done(struct ib_cq *cq, struct ib_wc *wc)
read_write_done(cq, wc, DMA_TO_DEVICE);
}
-static int smb_direct_rdma_xmit(struct smb_direct_transport *t, void *buf,
- int buf_len, u32 remote_key, u64 remote_offset,
- u32 remote_len, bool is_read)
+static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
+ void *buf, int buf_len,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len,
+ bool is_read)
{
struct smb_direct_rdma_rw_msg *msg;
int ret;
DECLARE_COMPLETION_ONSTACK(completion);
struct ib_send_wr *first_wr = NULL;
+ u32 remote_key = le32_to_cpu(desc[0].token);
+ u64 remote_offset = le64_to_cpu(desc[0].offset);
ret = wait_for_credits(t, &t->wait_rw_avail_ops, &t->rw_avail_ops);
if (ret < 0)
@@ -1429,22 +1433,22 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t, void *buf,
return ret;
}
-static int smb_direct_rdma_write(struct ksmbd_transport *t, void *buf,
- unsigned int buflen, u32 remote_key,
- u64 remote_offset, u32 remote_len)
+static int smb_direct_rdma_write(struct ksmbd_transport *t,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
{
return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
- remote_key, remote_offset,
- remote_len, false);
+ desc, desc_len, false);
}
-static int smb_direct_rdma_read(struct ksmbd_transport *t, void *buf,
- unsigned int buflen, u32 remote_key,
- u64 remote_offset, u32 remote_len)
+static int smb_direct_rdma_read(struct ksmbd_transport *t,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
{
return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
- remote_key, remote_offset,
- remote_len, true);
+ desc, desc_len, true);
}
static void smb_direct_disconnect(struct ksmbd_transport *t)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 034/154] ksmbd: smbd: introduce read/write credits for RDMA read/write
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (32 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 033/154] ksmbd: smbd: change prototypes of RDMA read/write related functions Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 035/154] ksmbd: smbd: simplify tracking pending packets Namjae Jeon
` (120 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit ddbdc861e37c168cf2fb8a7b7477f5d18b4daf76 ]
SMB2_READ/SMB2_WRITE request has to be granted the number
of rw credits, the pages the request wants to transfer
/ the maximum pages which can be registered with one
MR to read and write a file.
And allocate enough RDMA resources for the maximum
number of rw credits allowed by ksmbd.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 118 ++++++++++++++++++++++----------------
1 file changed, 70 insertions(+), 48 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 991eefe7fe1f..411ea62712f1 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -82,8 +82,6 @@ static int smb_direct_max_receive_size = 8192;
static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
-static int smb_direct_max_outstanding_rw_ops = 8;
-
static LIST_HEAD(smb_direct_device_list);
static DEFINE_RWLOCK(smb_direct_device_lock);
@@ -147,10 +145,12 @@ struct smb_direct_transport {
atomic_t send_credits;
spinlock_t lock_new_recv_credits;
int new_recv_credits;
- atomic_t rw_avail_ops;
+ int max_rw_credits;
+ int pages_per_rw_credit;
+ atomic_t rw_credits;
wait_queue_head_t wait_send_credits;
- wait_queue_head_t wait_rw_avail_ops;
+ wait_queue_head_t wait_rw_credits;
mempool_t *sendmsg_mempool;
struct kmem_cache *sendmsg_cache;
@@ -383,7 +383,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
t->reassembly_queue_length = 0;
init_waitqueue_head(&t->wait_reassembly_queue);
init_waitqueue_head(&t->wait_send_credits);
- init_waitqueue_head(&t->wait_rw_avail_ops);
+ init_waitqueue_head(&t->wait_rw_credits);
spin_lock_init(&t->receive_credit_lock);
spin_lock_init(&t->recvmsg_queue_lock);
@@ -989,18 +989,19 @@ static int smb_direct_flush_send_list(struct smb_direct_transport *t,
}
static int wait_for_credits(struct smb_direct_transport *t,
- wait_queue_head_t *waitq, atomic_t *credits)
+ wait_queue_head_t *waitq, atomic_t *total_credits,
+ int needed)
{
int ret;
do {
- if (atomic_dec_return(credits) >= 0)
+ if (atomic_sub_return(needed, total_credits) >= 0)
return 0;
- atomic_inc(credits);
+ atomic_add(needed, total_credits);
ret = wait_event_interruptible(*waitq,
- atomic_read(credits) > 0 ||
- t->status != SMB_DIRECT_CS_CONNECTED);
+ atomic_read(total_credits) >= needed ||
+ t->status != SMB_DIRECT_CS_CONNECTED);
if (t->status != SMB_DIRECT_CS_CONNECTED)
return -ENOTCONN;
@@ -1021,7 +1022,19 @@ static int wait_for_send_credits(struct smb_direct_transport *t,
return ret;
}
- return wait_for_credits(t, &t->wait_send_credits, &t->send_credits);
+ return wait_for_credits(t, &t->wait_send_credits, &t->send_credits, 1);
+}
+
+static int wait_for_rw_credits(struct smb_direct_transport *t, int credits)
+{
+ return wait_for_credits(t, &t->wait_rw_credits, &t->rw_credits, credits);
+}
+
+static int calc_rw_credits(struct smb_direct_transport *t,
+ char *buf, unsigned int len)
+{
+ return DIV_ROUND_UP(get_buf_page_count(buf, len),
+ t->pages_per_rw_credit);
}
static int smb_direct_create_header(struct smb_direct_transport *t,
@@ -1337,8 +1350,8 @@ static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
smb_direct_disconnect_rdma_connection(t);
}
- if (atomic_inc_return(&t->rw_avail_ops) > 0)
- wake_up(&t->wait_rw_avail_ops);
+ if (atomic_inc_return(&t->rw_credits) > 0)
+ wake_up(&t->wait_rw_credits);
rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
msg->sg_list, msg->sgt.nents, dir);
@@ -1369,8 +1382,10 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
struct ib_send_wr *first_wr = NULL;
u32 remote_key = le32_to_cpu(desc[0].token);
u64 remote_offset = le64_to_cpu(desc[0].offset);
+ int credits_needed;
- ret = wait_for_credits(t, &t->wait_rw_avail_ops, &t->rw_avail_ops);
+ credits_needed = calc_rw_credits(t, buf, buf_len);
+ ret = wait_for_rw_credits(t, credits_needed);
if (ret < 0)
return ret;
@@ -1378,7 +1393,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
msg = kmalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
if (!msg) {
- atomic_inc(&t->rw_avail_ops);
+ atomic_add(credits_needed, &t->rw_credits);
return -ENOMEM;
}
@@ -1387,7 +1402,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
get_buf_page_count(buf, buf_len),
msg->sg_list, SG_CHUNK_SIZE);
if (ret) {
- atomic_inc(&t->rw_avail_ops);
+ atomic_add(credits_needed, &t->rw_credits);
kfree(msg);
return -ENOMEM;
}
@@ -1423,7 +1438,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
return 0;
err:
- atomic_inc(&t->rw_avail_ops);
+ atomic_add(credits_needed, &t->rw_credits);
if (first_wr)
rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
msg->sg_list, msg->sgt.nents,
@@ -1648,11 +1663,19 @@ static int smb_direct_prepare_negotiation(struct smb_direct_transport *t)
return ret;
}
+static unsigned int smb_direct_get_max_fr_pages(struct smb_direct_transport *t)
+{
+ return min_t(unsigned int,
+ t->cm_id->device->attrs.max_fast_reg_page_list_len,
+ 256);
+}
+
static int smb_direct_init_params(struct smb_direct_transport *t,
struct ib_qp_cap *cap)
{
struct ib_device *device = t->cm_id->device;
- int max_send_sges, max_pages, max_rw_wrs, max_send_wrs;
+ int max_send_sges, max_rw_wrs, max_send_wrs;
+ unsigned int max_sge_per_wr, wrs_per_credit;
/* need 2 more sge. because a SMB_DIRECT header will be mapped,
* and maybe a send buffer could be not page aligned.
@@ -1664,25 +1687,31 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
return -EINVAL;
}
- /*
- * allow smb_direct_max_outstanding_rw_ops of in-flight RDMA
- * read/writes. HCA guarantees at least max_send_sge of sges for
- * a RDMA read/write work request, and if memory registration is used,
- * we need reg_mr, local_inv wrs for each read/write.
+ /* Calculate the number of work requests for RDMA R/W.
+ * The maximum number of pages which can be registered
+ * with one Memory region can be transferred with one
+ * R/W credit. And at least 4 work requests for each credit
+ * are needed for MR registration, RDMA R/W, local & remote
+ * MR invalidation.
*/
t->max_rdma_rw_size = smb_direct_max_read_write_size;
- max_pages = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1;
- max_rw_wrs = DIV_ROUND_UP(max_pages, SMB_DIRECT_MAX_SEND_SGES);
- max_rw_wrs += rdma_rw_mr_factor(device, t->cm_id->port_num,
- max_pages) * 2;
- max_rw_wrs *= smb_direct_max_outstanding_rw_ops;
+ t->pages_per_rw_credit = smb_direct_get_max_fr_pages(t);
+ t->max_rw_credits = DIV_ROUND_UP(t->max_rdma_rw_size,
+ (t->pages_per_rw_credit - 1) *
+ PAGE_SIZE);
+
+ max_sge_per_wr = min_t(unsigned int, device->attrs.max_send_sge,
+ device->attrs.max_sge_rd);
+ wrs_per_credit = max_t(unsigned int, 4,
+ DIV_ROUND_UP(t->pages_per_rw_credit,
+ max_sge_per_wr) + 1);
+ max_rw_wrs = t->max_rw_credits * wrs_per_credit;
max_send_wrs = smb_direct_send_credit_target + max_rw_wrs;
if (max_send_wrs > device->attrs.max_cqe ||
max_send_wrs > device->attrs.max_qp_wr) {
- pr_err("consider lowering send_credit_target = %d, or max_outstanding_rw_ops = %d\n",
- smb_direct_send_credit_target,
- smb_direct_max_outstanding_rw_ops);
+ pr_err("consider lowering send_credit_target = %d\n",
+ smb_direct_send_credit_target);
pr_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
device->attrs.max_cqe, device->attrs.max_qp_wr);
return -EINVAL;
@@ -1717,7 +1746,7 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
t->send_credit_target = smb_direct_send_credit_target;
atomic_set(&t->send_credits, 0);
- atomic_set(&t->rw_avail_ops, smb_direct_max_outstanding_rw_ops);
+ atomic_set(&t->rw_credits, t->max_rw_credits);
t->max_send_size = smb_direct_max_send_size;
t->max_recv_size = smb_direct_max_receive_size;
@@ -1725,12 +1754,10 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
cap->max_send_wr = max_send_wrs;
cap->max_recv_wr = t->recv_credit_max;
- cap->max_send_sge = SMB_DIRECT_MAX_SEND_SGES;
+ cap->max_send_sge = max_sge_per_wr;
cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES;
cap->max_inline_data = 0;
- cap->max_rdma_ctxs =
- rdma_rw_mr_factor(device, t->cm_id->port_num, max_pages) *
- smb_direct_max_outstanding_rw_ops;
+ cap->max_rdma_ctxs = t->max_rw_credits;
return 0;
}
@@ -1823,7 +1850,8 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
}
t->send_cq = ib_alloc_cq(t->cm_id->device, t,
- t->send_credit_target, 0, IB_POLL_WORKQUEUE);
+ smb_direct_send_credit_target + cap->max_rdma_ctxs,
+ 0, IB_POLL_WORKQUEUE);
if (IS_ERR(t->send_cq)) {
pr_err("Can't create RDMA send CQ\n");
ret = PTR_ERR(t->send_cq);
@@ -1832,8 +1860,7 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
}
t->recv_cq = ib_alloc_cq(t->cm_id->device, t,
- cap->max_send_wr + cap->max_rdma_ctxs,
- 0, IB_POLL_WORKQUEUE);
+ t->recv_credit_max, 0, IB_POLL_WORKQUEUE);
if (IS_ERR(t->recv_cq)) {
pr_err("Can't create RDMA recv CQ\n");
ret = PTR_ERR(t->recv_cq);
@@ -1862,17 +1889,12 @@ static int smb_direct_create_qpair(struct smb_direct_transport *t,
pages_per_rw = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1;
if (pages_per_rw > t->cm_id->device->attrs.max_sgl_rd) {
- int pages_per_mr, mr_count;
-
- pages_per_mr = min_t(int, pages_per_rw,
- t->cm_id->device->attrs.max_fast_reg_page_list_len);
- mr_count = DIV_ROUND_UP(pages_per_rw, pages_per_mr) *
- atomic_read(&t->rw_avail_ops);
- ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs, mr_count,
- IB_MR_TYPE_MEM_REG, pages_per_mr, 0);
+ ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs,
+ t->max_rw_credits, IB_MR_TYPE_MEM_REG,
+ t->pages_per_rw_credit, 0);
if (ret) {
pr_err("failed to init mr pool count %d pages %d\n",
- mr_count, pages_per_mr);
+ t->max_rw_credits, t->pages_per_rw_credit);
goto err;
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 035/154] ksmbd: smbd: simplify tracking pending packets
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (33 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 034/154] ksmbd: smbd: introduce read/write credits for RDMA read/write Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 036/154] ksmbd: smbd: change the return value of get_sg_list Namjae Jeon
` (119 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 11659a8ddbd9c4c1ab6f3b8f52837178ef121b20 ]
Because we don't have to tracking pending packets
by dividing these into packets with payload and
packets without payload, merge the tracking code.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 34 +++++++---------------------------
1 file changed, 7 insertions(+), 27 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 411ea62712f1..02271ebf418a 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -157,8 +157,6 @@ struct smb_direct_transport {
mempool_t *recvmsg_mempool;
struct kmem_cache *recvmsg_cache;
- wait_queue_head_t wait_send_payload_pending;
- atomic_t send_payload_pending;
wait_queue_head_t wait_send_pending;
atomic_t send_pending;
@@ -392,8 +390,6 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
spin_lock_init(&t->empty_recvmsg_queue_lock);
INIT_LIST_HEAD(&t->empty_recvmsg_queue);
- init_waitqueue_head(&t->wait_send_payload_pending);
- atomic_set(&t->send_payload_pending, 0);
init_waitqueue_head(&t->wait_send_pending);
atomic_set(&t->send_pending, 0);
@@ -423,8 +419,6 @@ static void free_transport(struct smb_direct_transport *t)
wake_up_interruptible(&t->wait_send_credits);
ksmbd_debug(RDMA, "wait for all send posted to IB to finish\n");
- wait_event(t->wait_send_payload_pending,
- atomic_read(&t->send_payload_pending) == 0);
wait_event(t->wait_send_pending,
atomic_read(&t->send_pending) == 0);
@@ -879,13 +873,8 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
smb_direct_disconnect_rdma_connection(t);
}
- if (sendmsg->num_sge > 1) {
- if (atomic_dec_and_test(&t->send_payload_pending))
- wake_up(&t->wait_send_payload_pending);
- } else {
- if (atomic_dec_and_test(&t->send_pending))
- wake_up(&t->wait_send_pending);
- }
+ if (atomic_dec_and_test(&t->send_pending))
+ wake_up(&t->wait_send_pending);
/* iterate and free the list of messages in reverse. the list's head
* is invalid.
@@ -917,21 +906,12 @@ static int smb_direct_post_send(struct smb_direct_transport *t,
{
int ret;
- if (wr->num_sge > 1)
- atomic_inc(&t->send_payload_pending);
- else
- atomic_inc(&t->send_pending);
-
+ atomic_inc(&t->send_pending);
ret = ib_post_send(t->qp, wr, NULL);
if (ret) {
pr_err("failed to post send: %d\n", ret);
- if (wr->num_sge > 1) {
- if (atomic_dec_and_test(&t->send_payload_pending))
- wake_up(&t->wait_send_payload_pending);
- } else {
- if (atomic_dec_and_test(&t->send_pending))
- wake_up(&t->wait_send_pending);
- }
+ if (atomic_dec_and_test(&t->send_pending))
+ wake_up(&t->wait_send_pending);
smb_direct_disconnect_rdma_connection(t);
}
return ret;
@@ -1332,8 +1312,8 @@ static int smb_direct_writev(struct ksmbd_transport *t,
* that means all the I/Os have been out and we are good to return
*/
- wait_event(st->wait_send_payload_pending,
- atomic_read(&st->send_payload_pending) == 0);
+ wait_event(st->wait_send_pending,
+ atomic_read(&st->send_pending) == 0);
return ret;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 036/154] ksmbd: smbd: change the return value of get_sg_list
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (34 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 035/154] ksmbd: smbd: simplify tracking pending packets Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 037/154] ksmbd: smbd: handle multiple Buffer descriptors Namjae Jeon
` (118 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 4e3edd0092704b25626a0fe60a974f6f382ff93d ]
Make get_sg_list return EINVAL if there aren't
mapped scatterlists.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 02271ebf418a..ca853433e4b4 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1085,7 +1085,7 @@ static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nen
int offset, len;
int i = 0;
- if (nentries < get_buf_page_count(buf, size))
+ if (size <= 0 || nentries < get_buf_page_count(buf, size))
return -EINVAL;
offset = offset_in_page(buf);
@@ -1117,7 +1117,7 @@ static int get_mapped_sg_list(struct ib_device *device, void *buf, int size,
int npages;
npages = get_sg_list(buf, size, sg_list, nentries);
- if (npages <= 0)
+ if (npages < 0)
return -EINVAL;
return ib_dma_map_sg(device, sg_list, npages, dir);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 037/154] ksmbd: smbd: handle multiple Buffer descriptors
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (35 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 036/154] ksmbd: smbd: change the return value of get_sg_list Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 038/154] ksmbd: fix wrong smbd max read/write size check Namjae Jeon
` (117 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit ee1b0558965909872775183dc237cdf9f8eddaba ]
Make ksmbd handle multiple buffer descriptors
when reading and writing files using SMB direct:
Post the work requests of rdma_rw_ctx for
RDMA read/write in smb_direct_rdma_xmit(), and
the work request for the READ/WRITE response
with a remote invalidation in smb_direct_writev().
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 5 +-
fs/ksmbd/transport_rdma.c | 164 ++++++++++++++++++++++++--------------
2 files changed, 107 insertions(+), 62 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d26af17f383c..dd0ced5d191f 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6210,11 +6210,8 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
le32_to_cpu(desc[i].length));
}
}
- if (ch_count != 1) {
- ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n",
- ch_count);
+ if (!ch_count)
return -EINVAL;
- }
work->need_invalidate_rkey =
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index ca853433e4b4..95c5c2f749e1 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -206,7 +206,9 @@ struct smb_direct_recvmsg {
struct smb_direct_rdma_rw_msg {
struct smb_direct_transport *t;
struct ib_cqe cqe;
+ int status;
struct completion *completion;
+ struct list_head list;
struct rdma_rw_ctx rw_ctx;
struct sg_table sgt;
struct scatterlist sg_list[0];
@@ -1317,6 +1319,16 @@ static int smb_direct_writev(struct ksmbd_transport *t,
return ret;
}
+static void smb_direct_free_rdma_rw_msg(struct smb_direct_transport *t,
+ struct smb_direct_rdma_rw_msg *msg,
+ enum dma_data_direction dir)
+{
+ rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
+ msg->sgt.sgl, msg->sgt.nents, dir);
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+ kfree(msg);
+}
+
static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
enum dma_data_direction dir)
{
@@ -1325,19 +1337,14 @@ static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
struct smb_direct_transport *t = msg->t;
if (wc->status != IB_WC_SUCCESS) {
+ msg->status = -EIO;
pr_err("read/write error. opcode = %d, status = %s(%d)\n",
wc->opcode, ib_wc_status_msg(wc->status), wc->status);
- smb_direct_disconnect_rdma_connection(t);
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smb_direct_disconnect_rdma_connection(t);
}
- if (atomic_inc_return(&t->rw_credits) > 0)
- wake_up(&t->wait_rw_credits);
-
- rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
- msg->sg_list, msg->sgt.nents, dir);
- sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
complete(msg->completion);
- kfree(msg);
}
static void read_done(struct ib_cq *cq, struct ib_wc *wc)
@@ -1356,75 +1363,116 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
unsigned int desc_len,
bool is_read)
{
- struct smb_direct_rdma_rw_msg *msg;
- int ret;
+ struct smb_direct_rdma_rw_msg *msg, *next_msg;
+ int i, ret;
DECLARE_COMPLETION_ONSTACK(completion);
- struct ib_send_wr *first_wr = NULL;
- u32 remote_key = le32_to_cpu(desc[0].token);
- u64 remote_offset = le64_to_cpu(desc[0].offset);
+ struct ib_send_wr *first_wr;
+ LIST_HEAD(msg_list);
+ char *desc_buf;
int credits_needed;
+ unsigned int desc_buf_len;
+ size_t total_length = 0;
+
+ if (t->status != SMB_DIRECT_CS_CONNECTED)
+ return -ENOTCONN;
+
+ /* calculate needed credits */
+ credits_needed = 0;
+ desc_buf = buf;
+ for (i = 0; i < desc_len / sizeof(*desc); i++) {
+ desc_buf_len = le32_to_cpu(desc[i].length);
+
+ credits_needed += calc_rw_credits(t, desc_buf, desc_buf_len);
+ desc_buf += desc_buf_len;
+ total_length += desc_buf_len;
+ if (desc_buf_len == 0 || total_length > buf_len ||
+ total_length > t->max_rdma_rw_size)
+ return -EINVAL;
+ }
+
+ ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n",
+ is_read ? "read" : "write", buf_len, credits_needed);
- credits_needed = calc_rw_credits(t, buf, buf_len);
ret = wait_for_rw_credits(t, credits_needed);
if (ret < 0)
return ret;
- /* TODO: mempool */
- msg = kmalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
- sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
- if (!msg) {
- atomic_add(credits_needed, &t->rw_credits);
- return -ENOMEM;
- }
+ /* build rdma_rw_ctx for each descriptor */
+ desc_buf = buf;
+ for (i = 0; i < desc_len / sizeof(*desc); i++) {
+ msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
+ sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
+ if (!msg) {
+ ret = -ENOMEM;
+ goto out;
+ }
- msg->sgt.sgl = &msg->sg_list[0];
- ret = sg_alloc_table_chained(&msg->sgt,
- get_buf_page_count(buf, buf_len),
- msg->sg_list, SG_CHUNK_SIZE);
- if (ret) {
- atomic_add(credits_needed, &t->rw_credits);
- kfree(msg);
- return -ENOMEM;
- }
+ desc_buf_len = le32_to_cpu(desc[i].length);
- ret = get_sg_list(buf, buf_len, msg->sgt.sgl, msg->sgt.orig_nents);
- if (ret <= 0) {
- pr_err("failed to get pages\n");
- goto err;
- }
+ msg->t = t;
+ msg->cqe.done = is_read ? read_done : write_done;
+ msg->completion = &completion;
- ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port,
- msg->sg_list, get_buf_page_count(buf, buf_len),
- 0, remote_offset, remote_key,
- is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
- if (ret < 0) {
- pr_err("failed to init rdma_rw_ctx: %d\n", ret);
- goto err;
+ msg->sgt.sgl = &msg->sg_list[0];
+ ret = sg_alloc_table_chained(&msg->sgt,
+ get_buf_page_count(desc_buf, desc_buf_len),
+ msg->sg_list, SG_CHUNK_SIZE);
+ if (ret) {
+ kfree(msg);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = get_sg_list(desc_buf, desc_buf_len,
+ msg->sgt.sgl, msg->sgt.orig_nents);
+ if (ret < 0) {
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+ kfree(msg);
+ goto out;
+ }
+
+ ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port,
+ msg->sgt.sgl,
+ get_buf_page_count(desc_buf, desc_buf_len),
+ 0,
+ le64_to_cpu(desc[i].offset),
+ le32_to_cpu(desc[i].token),
+ is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ if (ret < 0) {
+ pr_err("failed to init rdma_rw_ctx: %d\n", ret);
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+ kfree(msg);
+ goto out;
+ }
+
+ list_add_tail(&msg->list, &msg_list);
+ desc_buf += desc_buf_len;
}
- msg->t = t;
- msg->cqe.done = is_read ? read_done : write_done;
- msg->completion = &completion;
- first_wr = rdma_rw_ctx_wrs(&msg->rw_ctx, t->qp, t->qp->port,
- &msg->cqe, NULL);
+ /* concatenate work requests of rdma_rw_ctxs */
+ first_wr = NULL;
+ list_for_each_entry_reverse(msg, &msg_list, list) {
+ first_wr = rdma_rw_ctx_wrs(&msg->rw_ctx, t->qp, t->qp->port,
+ &msg->cqe, first_wr);
+ }
ret = ib_post_send(t->qp, first_wr, NULL);
if (ret) {
- pr_err("failed to post send wr: %d\n", ret);
- goto err;
+ pr_err("failed to post send wr for RDMA R/W: %d\n", ret);
+ goto out;
}
+ msg = list_last_entry(&msg_list, struct smb_direct_rdma_rw_msg, list);
wait_for_completion(&completion);
- return 0;
-
-err:
+ ret = msg->status;
+out:
+ list_for_each_entry_safe(msg, next_msg, &msg_list, list) {
+ list_del(&msg->list);
+ smb_direct_free_rdma_rw_msg(t, msg,
+ is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
atomic_add(credits_needed, &t->rw_credits);
- if (first_wr)
- rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
- msg->sg_list, msg->sgt.nents,
- is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
- sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
- kfree(msg);
+ wake_up(&t->wait_rw_credits);
return ret;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 038/154] ksmbd: fix wrong smbd max read/write size check
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (36 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 037/154] ksmbd: smbd: handle multiple Buffer descriptors Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 039/154] ksmbd: Fix some kernel-doc comments Namjae Jeon
` (116 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Hyunchul Lee, Steve French
[ Upstream commit 7a84399e1ce3f5f2fbec3e7dd93459ba25badc2f ]
smb-direct max read/write size can be different with smb2 max read/write
size. So smb2_read() can return error by wrong max read/write size check.
This patch use smb_direct_max_read_write_size for this check in
smb-direct read/write().
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 39 +++++++++++++++++++++++++--------------
fs/ksmbd/transport_rdma.c | 5 +++++
fs/ksmbd/transport_rdma.h | 2 ++
3 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index dd0ced5d191f..85afa551b11b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6252,6 +6252,8 @@ int smb2_read(struct ksmbd_work *work)
size_t length, mincount;
ssize_t nbytes = 0, remain_bytes = 0;
int err = 0;
+ bool is_rdma_channel = false;
+ unsigned int max_read_size = conn->vals->max_read_size;
WORK_BUFFERS(work, req, rsp);
if (work->next_smb2_rcv_hdr_off) {
@@ -6268,6 +6270,11 @@ int smb2_read(struct ksmbd_work *work)
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
+ is_rdma_channel = true;
+ max_read_size = get_smbd_max_read_write_size();
+ }
+
+ if (is_rdma_channel == true) {
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
@@ -6299,9 +6306,9 @@ int smb2_read(struct ksmbd_work *work)
length = le32_to_cpu(req->Length);
mincount = le32_to_cpu(req->MinimumCount);
- if (length > conn->vals->max_read_size) {
+ if (length > max_read_size) {
ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
- conn->vals->max_read_size);
+ max_read_size);
err = -EINVAL;
goto out;
}
@@ -6333,8 +6340,7 @@ int smb2_read(struct ksmbd_work *work)
ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
nbytes, offset, mincount);
- if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
- req->Channel == SMB2_CHANNEL_RDMA_V1) {
+ if (is_rdma_channel == true) {
/* write data to the client using rdma channel */
remain_bytes = smb2_read_rdma_channel(work, req,
work->aux_payload_buf,
@@ -6495,8 +6501,9 @@ int smb2_write(struct ksmbd_work *work)
size_t length;
ssize_t nbytes;
char *data_buf;
- bool writethrough = false;
+ bool writethrough = false, is_rdma_channel = false;
int err = 0;
+ unsigned int max_write_size = work->conn->vals->max_write_size;
WORK_BUFFERS(work, req, rsp);
@@ -6505,8 +6512,17 @@ int smb2_write(struct ksmbd_work *work)
return smb2_write_pipe(work);
}
+ offset = le64_to_cpu(req->Offset);
+ length = le32_to_cpu(req->Length);
+
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
+ is_rdma_channel = true;
+ max_write_size = get_smbd_max_read_write_size();
+ length = le32_to_cpu(req->RemainingBytes);
+ }
+
+ if (is_rdma_channel == true) {
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
if (req->Length != 0 || req->DataOffset != 0 ||
@@ -6541,12 +6557,9 @@ int smb2_write(struct ksmbd_work *work)
goto out;
}
- offset = le64_to_cpu(req->Offset);
- length = le32_to_cpu(req->Length);
-
- if (length > work->conn->vals->max_write_size) {
+ if (length > max_write_size) {
ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
- work->conn->vals->max_write_size);
+ max_write_size);
err = -EINVAL;
goto out;
}
@@ -6554,8 +6567,7 @@ int smb2_write(struct ksmbd_work *work)
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
writethrough = true;
- if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
- req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
+ if (is_rdma_channel == false) {
if (le16_to_cpu(req->DataOffset) <
offsetof(struct smb2_write_req, Buffer)) {
err = -EINVAL;
@@ -6579,8 +6591,7 @@ int smb2_write(struct ksmbd_work *work)
/* read data from the client using rdma channel, and
* write the data.
*/
- nbytes = smb2_write_rdma_channel(work, req, fp, offset,
- le32_to_cpu(req->RemainingBytes),
+ nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
writethrough);
if (nbytes < 0) {
err = (int)nbytes;
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 95c5c2f749e1..f36c7626af0c 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -220,6 +220,11 @@ void init_smbd_max_io_size(unsigned int sz)
smb_direct_max_read_write_size = sz;
}
+unsigned int get_smbd_max_read_write_size(void)
+{
+ return smb_direct_max_read_write_size;
+}
+
static inline int get_buf_page_count(void *buf, int size)
{
return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
index e7b4e6790fab..77aee4e5c9dc 100644
--- a/fs/ksmbd/transport_rdma.h
+++ b/fs/ksmbd/transport_rdma.h
@@ -57,11 +57,13 @@ int ksmbd_rdma_init(void);
void ksmbd_rdma_destroy(void);
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
void init_smbd_max_io_size(unsigned int sz);
+unsigned int get_smbd_max_read_write_size(void);
#else
static inline int ksmbd_rdma_init(void) { return 0; }
static inline int ksmbd_rdma_destroy(void) { return 0; }
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
static inline void init_smbd_max_io_size(unsigned int sz) { }
+static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
#endif
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 039/154] ksmbd: Fix some kernel-doc comments
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (37 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 038/154] ksmbd: fix wrong smbd max read/write size check Namjae Jeon
@ 2023-12-18 15:32 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 040/154] ksmbd: smbd: fix connection dropped issue Namjae Jeon
` (115 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:32 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Yang Li, Abaci Robot, Namjae Jeon, Steve French
From: Yang Li <yang.lee@linux.alibaba.com>
[ Upstream commit 7820c6ee029548290b318e522eb2578516d05393 ]
Remove some warnings found by running scripts/kernel-doc,
which is caused by using 'make W=1'.
fs/ksmbd/misc.c:30: warning: Function parameter or member 'str' not
described in 'match_pattern'
fs/ksmbd/misc.c:30: warning: Excess function parameter 'string'
description in 'match_pattern'
fs/ksmbd/misc.c:163: warning: Function parameter or member 'share' not
described in 'convert_to_nt_pathname'
fs/ksmbd/misc.c:163: warning: Function parameter or member 'path' not
described in 'convert_to_nt_pathname'
fs/ksmbd/misc.c:163: warning: Excess function parameter 'filename'
description in 'convert_to_nt_pathname'
fs/ksmbd/misc.c:163: warning: Excess function parameter 'sharepath'
description in 'convert_to_nt_pathname'
fs/ksmbd/misc.c:259: warning: Function parameter or member 'share' not
described in 'convert_to_unix_name'
fs/ksmbd/misc.c:259: warning: Function parameter or member 'name' not
described in 'convert_to_unix_name'
fs/ksmbd/misc.c:259: warning: Excess function parameter 'path'
description in 'convert_to_unix_name'
fs/ksmbd/misc.c:259: warning: Excess function parameter 'tid'
description in 'convert_to_unix_name'
Reported-by: Abaci Robot <abaci@linux.alibaba.com>
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/misc.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/misc.c b/fs/ksmbd/misc.c
index 1e2076a53bed..df991107ad2c 100644
--- a/fs/ksmbd/misc.c
+++ b/fs/ksmbd/misc.c
@@ -20,7 +20,7 @@
* wildcard '*' and '?'
* TODO : implement consideration about DOS_DOT, DOS_QM and DOS_STAR
*
- * @string: string to compare with a pattern
+ * @str: string to compare with a pattern
* @len: string length
* @pattern: pattern string which might include wildcard '*' and '?'
*
@@ -152,8 +152,8 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
/**
* convert_to_nt_pathname() - extract and return windows path string
* whose share directory prefix was removed from file path
- * @filename : unix filename
- * @sharepath: share path string
+ * @share: ksmbd_share_config pointer
+ * @path: path to report
*
* Return : windows path string or error
*/
@@ -250,8 +250,8 @@ char *ksmbd_extract_sharename(char *treename)
/**
* convert_to_unix_name() - convert windows name to unix format
- * @path: name to be converted
- * @tid: tree id of mathing share
+ * @share: ksmbd_share_config pointer
+ * @name: file name that is relative to share
*
* Return: converted name on success, otherwise NULL
*/
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 040/154] ksmbd: smbd: fix connection dropped issue
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (38 preceding siblings ...)
2023-12-18 15:32 ` [PATCH 5.15.y 039/154] ksmbd: Fix some kernel-doc comments Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 041/154] ksmbd: smbd: relax the count of sges required Namjae Jeon
` (114 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Hyunchul Lee, Yufan Chen, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 5366afc4065075a4456941fbd51c33604d631ee5 ]
When there are bursty connection requests,
RDMA connection event handler is deferred and
Negotiation requests are received even if
connection status is NEW.
To handle it, set the status to CONNECTED
if Negotiation requests are received.
Reported-by: Yufan Chen <wiz.chen@gmail.com>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Tested-by: Yufan Chen <wiz.chen@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index f36c7626af0c..6c127fabdc56 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -576,6 +576,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
}
t->negotiation_requested = true;
t->full_packet_received = true;
+ t->status = SMB_DIRECT_CS_CONNECTED;
enqueue_reassembly(t, recvmsg, 0);
wake_up_interruptible(&t->wait_status);
break;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 041/154] ksmbd: smbd: relax the count of sges required
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (39 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 040/154] ksmbd: smbd: fix connection dropped issue Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 042/154] ksmbd: smbd: Remove useless license text when SPDX-License-Identifier is already used Namjae Jeon
` (113 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Hyunchul Lee, Namjae Jeon, Tom Talpey, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 621433b7e25d6d42e5f75bd8c4a62d6c7251511b ]
Remove the condition that the count of sges
must be greater than or equal to
SMB_DIRECT_MAX_SEND_SGES(8).
Because ksmbd needs sges only for SMB direct
header, SMB2 transform header, SMB2 response,
and optional payload.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Tom Talpey <tom@talpey.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 6c127fabdc56..ab12ec537015 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1711,11 +1711,11 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
int max_send_sges, max_rw_wrs, max_send_wrs;
unsigned int max_sge_per_wr, wrs_per_credit;
- /* need 2 more sge. because a SMB_DIRECT header will be mapped,
- * and maybe a send buffer could be not page aligned.
+ /* need 3 more sge. because a SMB_DIRECT header, SMB2 header,
+ * SMB2 response could be mapped.
*/
t->max_send_size = smb_direct_max_send_size;
- max_send_sges = DIV_ROUND_UP(t->max_send_size, PAGE_SIZE) + 2;
+ max_send_sges = DIV_ROUND_UP(t->max_send_size, PAGE_SIZE) + 3;
if (max_send_sges > SMB_DIRECT_MAX_SEND_SGES) {
pr_err("max_send_size %d is too large\n", t->max_send_size);
return -EINVAL;
@@ -1736,6 +1736,8 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
max_sge_per_wr = min_t(unsigned int, device->attrs.max_send_sge,
device->attrs.max_sge_rd);
+ max_sge_per_wr = max_t(unsigned int, max_sge_per_wr,
+ max_send_sges);
wrs_per_credit = max_t(unsigned int, 4,
DIV_ROUND_UP(t->pages_per_rw_credit,
max_sge_per_wr) + 1);
@@ -1760,11 +1762,6 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
return -EINVAL;
}
- if (device->attrs.max_send_sge < SMB_DIRECT_MAX_SEND_SGES) {
- pr_err("warning: device max_send_sge = %d too small\n",
- device->attrs.max_send_sge);
- return -EINVAL;
- }
if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) {
pr_err("warning: device max_recv_sge = %d too small\n",
device->attrs.max_recv_sge);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 042/154] ksmbd: smbd: Remove useless license text when SPDX-License-Identifier is already used
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (40 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 041/154] ksmbd: smbd: relax the count of sges required Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 043/154] ksmbd: remove duplicate flag set in smb2_write Namjae Jeon
` (112 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Christophe JAILLET, Namjae Jeon, Steve French
From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
[ Upstream commit 06ee1c0aebd5dfdf6bf237165b22415f64f38b7c ]
An SPDX-License-Identifier is already in place. There is no need to
duplicate part of the corresponding license.
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index ab12ec537015..7bac4b09c844 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -5,16 +5,6 @@
*
* Author(s): Long Li <longli@microsoft.com>,
* Hyunchul Lee <hyc.lee@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
*/
#define SUBMOD_NAME "smb_direct"
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 043/154] ksmbd: remove duplicate flag set in smb2_write
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (41 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 042/154] ksmbd: smbd: Remove useless license text when SPDX-License-Identifier is already used Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 044/154] ksmbd: remove unused ksmbd_share_configs_cleanup function Namjae Jeon
` (111 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit 745bbc0995c25917dfafb645b8efb29813ef9e0b ]
The writethrough flag is set again if is_rdma_channel is false.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 85afa551b11b..1c674a7b2b39 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6564,6 +6564,7 @@ int smb2_write(struct ksmbd_work *work)
goto out;
}
+ ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
writethrough = true;
@@ -6577,10 +6578,6 @@ int smb2_write(struct ksmbd_work *work)
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
le16_to_cpu(req->DataOffset));
- ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
- if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
- writethrough = true;
-
ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
fp->filp->f_path.dentry, offset, length);
err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 044/154] ksmbd: remove unused ksmbd_share_configs_cleanup function
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (42 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 043/154] ksmbd: remove duplicate flag set in smb2_write Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 045/154] ksmbd: use wait_event instead of schedule_timeout() Namjae Jeon
` (110 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 1c90b54718fdea4f89e7e0c2415803f33f6d0b00 ]
remove unused ksmbd_share_configs_cleanup function.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/share_config.c | 14 --------------
fs/ksmbd/mgmt/share_config.h | 2 --
2 files changed, 16 deletions(-)
diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
index cb72d30f5b71..70655af93b44 100644
--- a/fs/ksmbd/mgmt/share_config.c
+++ b/fs/ksmbd/mgmt/share_config.c
@@ -222,17 +222,3 @@ bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
}
return false;
}
-
-void ksmbd_share_configs_cleanup(void)
-{
- struct ksmbd_share_config *share;
- struct hlist_node *tmp;
- int i;
-
- down_write(&shares_table_lock);
- hash_for_each_safe(shares_table, i, tmp, share, hlist) {
- hash_del(&share->hlist);
- kill_share(share);
- }
- up_write(&shares_table_lock);
-}
diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h
index 953befc94e84..28bf3511763f 100644
--- a/fs/ksmbd/mgmt/share_config.h
+++ b/fs/ksmbd/mgmt/share_config.h
@@ -76,6 +76,4 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
struct ksmbd_share_config *ksmbd_share_config_get(char *name);
bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
const char *filename);
-void ksmbd_share_configs_cleanup(void);
-
#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 045/154] ksmbd: use wait_event instead of schedule_timeout()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (43 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 044/154] ksmbd: remove unused ksmbd_share_configs_cleanup function Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 046/154] ksmbd: request update to stale share config Namjae Jeon
` (109 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Hyunchul Lee, Steve French
[ Upstream commit a14c573870a664386adc10526a6c2648ea56dae1 ]
ksmbd threads eating masses of cputime when connection is disconnected.
If connection is disconnected, ksmbd thread waits for pending requests
to be processed using schedule_timeout. schedule_timeout() incorrectly
is used, and it is more efficient to use wait_event/wake_up than to check
r_count every time with timeout.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 6 +++---
fs/ksmbd/connection.h | 1 +
fs/ksmbd/oplock.c | 35 ++++++++++++++++++++++-------------
fs/ksmbd/server.c | 8 +++++++-
4 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 192646b8920e..be1f8ffa4a78 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -66,6 +66,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
conn->outstanding_credits = 0;
init_waitqueue_head(&conn->req_running_q);
+ init_waitqueue_head(&conn->r_count_q);
INIT_LIST_HEAD(&conn->conns_list);
INIT_LIST_HEAD(&conn->requests);
INIT_LIST_HEAD(&conn->async_requests);
@@ -165,7 +166,6 @@ int ksmbd_conn_write(struct ksmbd_work *work)
struct kvec iov[3];
int iov_idx = 0;
- ksmbd_conn_try_dequeue_request(work);
if (!work->response_buf) {
pr_err("NULL response header\n");
return -EINVAL;
@@ -358,8 +358,8 @@ int ksmbd_conn_handler_loop(void *p)
out:
/* Wait till all reference dropped to the Server object*/
- while (atomic_read(&conn->r_count) > 0)
- schedule_timeout(HZ);
+ wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
+
unload_nls(conn->local_nls);
if (default_conn_ops.terminate_fn)
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index e0a25cddbb29..a8c367c481e8 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -58,6 +58,7 @@ struct ksmbd_conn {
unsigned int outstanding_credits;
spinlock_t credits_lock;
wait_queue_head_t req_running_q;
+ wait_queue_head_t r_count_q;
/* Lock to protect requests list*/
spinlock_t request_lock;
struct list_head requests;
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index ae5fc4b2c133..b527f451d7a4 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -616,18 +616,13 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
struct ksmbd_file *fp;
fp = ksmbd_lookup_durable_fd(br_info->fid);
- if (!fp) {
- atomic_dec(&conn->r_count);
- ksmbd_free_work_struct(work);
- return;
- }
+ if (!fp)
+ goto out;
if (allocate_oplock_break_buf(work)) {
pr_err("smb2_allocate_rsp_buf failed! ");
- atomic_dec(&conn->r_count);
ksmbd_fd_put(work, fp);
- ksmbd_free_work_struct(work);
- return;
+ goto out;
}
rsp_hdr = smb2_get_msg(work->response_buf);
@@ -668,8 +663,16 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
ksmbd_fd_put(work, fp);
ksmbd_conn_write(work);
+
+out:
ksmbd_free_work_struct(work);
- atomic_dec(&conn->r_count);
+ /*
+ * Checking waitqueue to dropping pending requests on
+ * disconnection. waitqueue_active is safe because it
+ * uses atomic operation for condition.
+ */
+ if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+ wake_up(&conn->r_count_q);
}
/**
@@ -732,9 +735,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
if (allocate_oplock_break_buf(work)) {
ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");
- ksmbd_free_work_struct(work);
- atomic_dec(&conn->r_count);
- return;
+ goto out;
}
rsp_hdr = smb2_get_msg(work->response_buf);
@@ -772,8 +773,16 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
inc_rfc1001_len(work->response_buf, 44);
ksmbd_conn_write(work);
+
+out:
ksmbd_free_work_struct(work);
- atomic_dec(&conn->r_count);
+ /*
+ * Checking waitqueue to dropping pending requests on
+ * disconnection. waitqueue_active is safe because it
+ * uses atomic operation for condition.
+ */
+ if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+ wake_up(&conn->r_count_q);
}
/**
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index 049d68831ccd..1d5e46d71070 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -266,7 +266,13 @@ static void handle_ksmbd_work(struct work_struct *wk)
ksmbd_conn_try_dequeue_request(work);
ksmbd_free_work_struct(work);
- atomic_dec(&conn->r_count);
+ /*
+ * Checking waitqueue to dropping pending requests on
+ * disconnection. waitqueue_active is safe because it
+ * uses atomic operation for condition.
+ */
+ if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+ wake_up(&conn->r_count_q);
}
/**
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 046/154] ksmbd: request update to stale share config
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (44 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 045/154] ksmbd: use wait_event instead of schedule_timeout() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 047/154] ksmbd: remove unnecessary generic_fillattr in smb2_open Namjae Jeon
` (108 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Atte Heikkilä, Namjae Jeon, Steve French
From: Atte Heikkilä <atteh.mailbox@gmail.com>
[ Upstream commit 4963d74f8a6cc0eafd71d9ffc13e3a11ff1dd160 ]
ksmbd_share_config_get() retrieves the cached share config as long
as there is at least one connection to the share. This is an issue when
the user space utilities are used to update share configs. In that case
there is a need to inform ksmbd that it should not use the cached share
config for a new connection to the share. With these changes the tree
connection flag KSMBD_TREE_CONN_FLAG_UPDATE indicates this. When this
flag is set, ksmbd removes the share config from the shares hash table
meaning that ksmbd_share_config_get() ends up requesting a share config
from user space.
Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_netlink.h | 2 ++
fs/ksmbd/mgmt/share_config.c | 6 +++++-
fs/ksmbd/mgmt/share_config.h | 1 +
fs/ksmbd/mgmt/tree_connect.c | 14 ++++++++++++++
fs/ksmbd/smb2pdu.c | 1 +
5 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
index fae859d59c79..17ad22808ee3 100644
--- a/fs/ksmbd/ksmbd_netlink.h
+++ b/fs/ksmbd/ksmbd_netlink.h
@@ -350,6 +350,7 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_SHARE_FLAG_STREAMS BIT(11)
#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12)
#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13)
+#define KSMBD_SHARE_FLAG_UPDATE BIT(14)
/*
* Tree connect request flags.
@@ -365,6 +366,7 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_TREE_CONN_FLAG_READ_ONLY BIT(1)
#define KSMBD_TREE_CONN_FLAG_WRITABLE BIT(2)
#define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT BIT(3)
+#define KSMBD_TREE_CONN_FLAG_UPDATE BIT(4)
/*
* RPC over IPC.
diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
index 70655af93b44..c9bca1c2c834 100644
--- a/fs/ksmbd/mgmt/share_config.c
+++ b/fs/ksmbd/mgmt/share_config.c
@@ -51,12 +51,16 @@ static void kill_share(struct ksmbd_share_config *share)
kfree(share);
}
-void __ksmbd_share_config_put(struct ksmbd_share_config *share)
+void ksmbd_share_config_del(struct ksmbd_share_config *share)
{
down_write(&shares_table_lock);
hash_del(&share->hlist);
up_write(&shares_table_lock);
+}
+void __ksmbd_share_config_put(struct ksmbd_share_config *share)
+{
+ ksmbd_share_config_del(share);
kill_share(share);
}
diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h
index 28bf3511763f..902f2cb1963a 100644
--- a/fs/ksmbd/mgmt/share_config.h
+++ b/fs/ksmbd/mgmt/share_config.h
@@ -64,6 +64,7 @@ static inline int test_share_config_flag(struct ksmbd_share_config *share,
return share->flags & flag;
}
+void ksmbd_share_config_del(struct ksmbd_share_config *share);
void __ksmbd_share_config_put(struct ksmbd_share_config *share);
static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index dd262daa2c4a..97ab7987df6e 100644
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -57,6 +57,20 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
goto out_error;
tree_conn->flags = resp->connection_flags;
+ if (test_tree_conn_flag(tree_conn, KSMBD_TREE_CONN_FLAG_UPDATE)) {
+ struct ksmbd_share_config *new_sc;
+
+ ksmbd_share_config_del(sc);
+ new_sc = ksmbd_share_config_get(share_name);
+ if (!new_sc) {
+ pr_err("Failed to update stale share config\n");
+ status.ret = -ESTALE;
+ goto out_error;
+ }
+ ksmbd_share_config_put(sc);
+ sc = new_sc;
+ }
+
tree_conn->user = sess->user;
tree_conn->share_conf = sc;
status.tree_conn = tree_conn;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 1c674a7b2b39..d87a051da11c 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1985,6 +1985,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_SUCCESS;
rc = 0;
break;
+ case -ESTALE:
case -ENOENT:
case KSMBD_TREE_CONN_STATUS_NO_SHARE:
rsp->hdr.Status = STATUS_BAD_NETWORK_NAME;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 047/154] ksmbd: remove unnecessary generic_fillattr in smb2_open
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (45 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 046/154] ksmbd: request update to stale share config Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 048/154] ksmbd: don't open-code file_path() Namjae Jeon
` (107 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hyunchul Lee, Namjae Jeon, Steve French
From: Hyunchul Lee <hyc.lee@gmail.com>
[ Upstream commit c90b31eaf9e77269d3803ed9223a2e0168b519ac ]
Remove unnecessary generic_fillattr to fix wrong
AllocationSize of SMB2_CREATE response, And
Move the call of ksmbd_vfs_getattr above the place
where stat is needed because of truncate.
This patch fixes wrong AllocationSize of SMB2_CREATE
response. Because ext4 updates inode->i_blocks only
when disk space is allocated, generic_fillattr does
not set stat.blocks properly for delayed allocation.
But ext4 returns the blocks that include the delayed
allocation blocks when getattr is called.
The issue can be reproduced with commands below:
touch ${FILENAME}
xfs_io -c "pwrite -S 0xAB 0 40k" ${FILENAME}
xfs_io -c "stat" ${FILENAME}
40KB are written, but the count of blocks is 8.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d87a051da11c..f74f2ffa0f07 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3095,12 +3095,6 @@ int smb2_open(struct ksmbd_work *work)
list_add(&fp->node, &fp->f_ci->m_fp_list);
write_unlock(&fp->f_ci->m_lock);
- rc = ksmbd_vfs_getattr(&path, &stat);
- if (rc) {
- generic_fillattr(user_ns, d_inode(path.dentry), &stat);
- rc = 0;
- }
-
/* Check delete pending among previous fp before oplock break */
if (ksmbd_inode_pending_delete(fp)) {
rc = -EBUSY;
@@ -3187,6 +3181,10 @@ int smb2_open(struct ksmbd_work *work)
}
}
+ rc = ksmbd_vfs_getattr(&path, &stat);
+ if (rc)
+ goto err_out;
+
if (stat.result_mask & STATX_BTIME)
fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
else
@@ -3202,9 +3200,6 @@ int smb2_open(struct ksmbd_work *work)
memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
- generic_fillattr(user_ns, file_inode(fp->filp),
- &stat);
-
rsp->StructureSize = cpu_to_le16(89);
rcu_read_lock();
opinfo = rcu_dereference(fp->f_opinfo);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 048/154] ksmbd: don't open-code file_path()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (46 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 047/154] ksmbd: remove unnecessary generic_fillattr in smb2_open Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 049/154] ksmbd: don't open-code %pD Namjae Jeon
` (106 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Al Viro, Namjae Jeon, Steve French
From: Al Viro <viro@zeniv.linux.org.uk>
[ Upstream commit 2f5930c1d7936b74eb820c5b157011994c707a74 ]
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index f74f2ffa0f07..5ca491e73c6d 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -5449,7 +5449,7 @@ static int smb2_rename(struct ksmbd_work *work,
if (!pathname)
return -ENOMEM;
- abs_oldname = d_path(&fp->filp->f_path, pathname, PATH_MAX);
+ abs_oldname = file_path(fp->filp, pathname, PATH_MAX);
if (IS_ERR(abs_oldname)) {
rc = -EINVAL;
goto out;
@@ -5584,7 +5584,7 @@ static int smb2_create_link(struct ksmbd_work *work,
}
ksmbd_debug(SMB, "link name is %s\n", link_name);
- target_name = d_path(&filp->f_path, pathname, PATH_MAX);
+ target_name = file_path(filp, pathname, PATH_MAX);
if (IS_ERR(target_name)) {
rc = -EINVAL;
goto out;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 049/154] ksmbd: don't open-code %pD
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (47 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 048/154] ksmbd: don't open-code file_path() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 050/154] ksmbd: constify struct path Namjae Jeon
` (105 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Al Viro, Namjae Jeon, Steve French
From: Al Viro <viro@zeniv.linux.org.uk>
[ Upstream commit 369c1634cc7ae8645a5cba4c7eb874755c2a6a07 ]
a bunch of places used %pd with file->f_path.dentry; shorter (and saner)
way to spell that is %pD with file...
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 11 +++++------
fs/ksmbd/vfs.c | 14 ++++++--------
2 files changed, 11 insertions(+), 14 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 5ca491e73c6d..61811c10ec93 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3939,8 +3939,7 @@ int smb2_query_dir(struct ksmbd_work *work)
inode_permission(file_mnt_user_ns(dir_fp->filp),
file_inode(dir_fp->filp),
MAY_READ | MAY_EXEC)) {
- pr_err("no right to enumerate directory (%pd)\n",
- dir_fp->filp->f_path.dentry);
+ pr_err("no right to enumerate directory (%pD)\n", dir_fp->filp);
rc = -EACCES;
goto err_out2;
}
@@ -6309,8 +6308,8 @@ int smb2_read(struct ksmbd_work *work)
goto out;
}
- ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
- fp->filp->f_path.dentry, offset, length);
+ ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
+ fp->filp, offset, length);
work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
if (!work->aux_payload_buf) {
@@ -6574,8 +6573,8 @@ int smb2_write(struct ksmbd_work *work)
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
le16_to_cpu(req->DataOffset));
- ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
- fp->filp->f_path.dentry, offset, length);
+ ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
+ fp->filp, offset, length);
err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
writethrough, &nbytes);
if (err < 0)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 0092e6911b14..8c542581f62a 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -376,8 +376,7 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
if (work->conn->connection_type) {
if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
- pr_err("no right to read(%pd)\n",
- fp->filp->f_path.dentry);
+ pr_err("no right to read(%pD)\n", fp->filp);
return -EACCES;
}
}
@@ -486,8 +485,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
if (work->conn->connection_type) {
if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
- pr_err("no right to write(%pd)\n",
- fp->filp->f_path.dentry);
+ pr_err("no right to write(%pD)\n", fp->filp);
err = -EACCES;
goto out;
}
@@ -526,8 +524,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
if (sync) {
err = vfs_fsync_range(filp, offset, offset + *written, 0);
if (err < 0)
- pr_err("fsync failed for filename = %pd, err = %d\n",
- fp->filp->f_path.dentry, err);
+ pr_err("fsync failed for filename = %pD, err = %d\n",
+ fp->filp, err);
}
out:
@@ -1742,11 +1740,11 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
*total_size_written = 0;
if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
- pr_err("no right to read(%pd)\n", src_fp->filp->f_path.dentry);
+ pr_err("no right to read(%pD)\n", src_fp->filp);
return -EACCES;
}
if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
- pr_err("no right to write(%pd)\n", dst_fp->filp->f_path.dentry);
+ pr_err("no right to write(%pD)\n", dst_fp->filp);
return -EACCES;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 050/154] ksmbd: constify struct path
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (48 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 049/154] ksmbd: don't open-code %pD Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 051/154] ksmbd: remove generic_fillattr use in smb2_open() Namjae Jeon
` (104 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Al Viro, Namjae Jeon, Steve French
From: Al Viro <viro@zeniv.linux.org.uk>
[ Upstream commit c22180a5e2a9e1426fab01d9e54011ec531b1b52 ]
... in particular, there should never be a non-const pointers to
any file->f_path.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/misc.c | 2 +-
fs/ksmbd/misc.h | 2 +-
fs/ksmbd/smb2pdu.c | 18 +++++++++---------
fs/ksmbd/smbacl.c | 6 +++---
fs/ksmbd/smbacl.h | 6 +++---
fs/ksmbd/vfs.c | 4 ++--
fs/ksmbd/vfs.h | 2 +-
7 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/fs/ksmbd/misc.c b/fs/ksmbd/misc.c
index df991107ad2c..364a0a463dfc 100644
--- a/fs/ksmbd/misc.c
+++ b/fs/ksmbd/misc.c
@@ -159,7 +159,7 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
*/
char *convert_to_nt_pathname(struct ksmbd_share_config *share,
- struct path *path)
+ const struct path *path)
{
char *pathname, *ab_pathname, *nt_pathname;
int share_path_len = share->path_sz;
diff --git a/fs/ksmbd/misc.h b/fs/ksmbd/misc.h
index aae2a252945f..5a0ae2f8e5e7 100644
--- a/fs/ksmbd/misc.h
+++ b/fs/ksmbd/misc.h
@@ -15,7 +15,7 @@ int match_pattern(const char *str, size_t len, const char *pattern);
int ksmbd_validate_filename(char *filename);
int parse_stream_name(char *filename, char **stream_name, int *s_type);
char *convert_to_nt_pathname(struct ksmbd_share_config *share,
- struct path *path);
+ const struct path *path);
int get_nlink(struct kstat *st);
void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(char *path);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 61811c10ec93..8f929807f4c8 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2226,7 +2226,7 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
* Return: 0 on success, otherwise error
*/
static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
- struct path *path)
+ const struct path *path)
{
struct user_namespace *user_ns = mnt_user_ns(path->mnt);
char *attr_name = NULL, *value;
@@ -2320,7 +2320,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
return rc;
}
-static noinline int smb2_set_stream_name_xattr(struct path *path,
+static noinline int smb2_set_stream_name_xattr(const struct path *path,
struct ksmbd_file *fp,
char *stream_name, int s_type)
{
@@ -2359,7 +2359,7 @@ static noinline int smb2_set_stream_name_xattr(struct path *path,
return 0;
}
-static int smb2_remove_smb_xattrs(struct path *path)
+static int smb2_remove_smb_xattrs(const struct path *path)
{
struct user_namespace *user_ns = mnt_user_ns(path->mnt);
char *name, *xattr_list = NULL;
@@ -2393,7 +2393,7 @@ static int smb2_remove_smb_xattrs(struct path *path)
return err;
}
-static int smb2_create_truncate(struct path *path)
+static int smb2_create_truncate(const struct path *path)
{
int rc = vfs_truncate(path, 0);
@@ -2412,7 +2412,7 @@ static int smb2_create_truncate(struct path *path)
return rc;
}
-static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, struct path *path,
+static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *path,
struct ksmbd_file *fp)
{
struct xattr_dos_attrib da = {0};
@@ -2435,7 +2435,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, struct path *path,
}
static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
- struct path *path, struct ksmbd_file *fp)
+ const struct path *path, struct ksmbd_file *fp)
{
struct xattr_dos_attrib da;
int rc;
@@ -2495,7 +2495,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
static int smb2_create_sd_buffer(struct ksmbd_work *work,
struct smb2_create_req *req,
- struct path *path)
+ const struct path *path)
{
struct create_context *context;
struct create_sd_buf_req *sd_buf;
@@ -4201,7 +4201,7 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
int rc, name_len, value_len, xattr_list_len, idx;
ssize_t buf_free_len, alignment_bytes, next_offset, rsp_data_cnt = 0;
struct smb2_ea_info_req *ea_req = NULL;
- struct path *path;
+ const struct path *path;
struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
if (!(fp->daccess & FILE_READ_EA_LE)) {
@@ -4523,7 +4523,7 @@ static void get_file_stream_info(struct ksmbd_work *work,
struct smb2_file_stream_info *file_info;
char *stream_name, *xattr_list = NULL, *stream_buf;
struct kstat stat;
- struct path *path = &fp->filp->f_path;
+ const struct path *path = &fp->filp->f_path;
ssize_t xattr_list_len;
int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
int buf_free_len;
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index 83f805248a81..253e8133520a 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -991,7 +991,7 @@ static void smb_set_ace(struct smb_ace *ace, const struct smb_sid *sid, u8 type,
}
int smb_inherit_dacl(struct ksmbd_conn *conn,
- struct path *path,
+ const struct path *path,
unsigned int uid, unsigned int gid)
{
const struct smb_sid *psid, *creator = NULL;
@@ -1208,7 +1208,7 @@ bool smb_inherit_flags(int flags, bool is_dir)
return false;
}
-int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
+int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
__le32 *pdaccess, int uid)
{
struct user_namespace *user_ns = mnt_user_ns(path->mnt);
@@ -1375,7 +1375,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
}
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
- struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
+ const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
bool type_check)
{
int rc;
diff --git a/fs/ksmbd/smbacl.h b/fs/ksmbd/smbacl.h
index fcb2c83f2992..f06abf247445 100644
--- a/fs/ksmbd/smbacl.h
+++ b/fs/ksmbd/smbacl.h
@@ -201,12 +201,12 @@ void posix_state_to_acl(struct posix_acl_state *state,
struct posix_acl_entry *pace);
int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid);
bool smb_inherit_flags(int flags, bool is_dir);
-int smb_inherit_dacl(struct ksmbd_conn *conn, struct path *path,
+int smb_inherit_dacl(struct ksmbd_conn *conn, const struct path *path,
unsigned int uid, unsigned int gid);
-int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
+int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
__le32 *pdaccess, int uid);
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
- struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
+ const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
bool type_check);
void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
void ksmbd_init_domain(u32 *sub_auth);
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 8c542581f62a..284aa87f3e5c 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -540,7 +540,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
*
* Return: 0 on success, otherwise error
*/
-int ksmbd_vfs_getattr(struct path *path, struct kstat *stat)
+int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat)
{
int err;
@@ -1165,7 +1165,7 @@ static int __caseless_lookup(struct dir_context *ctx, const char *name,
*
* Return: 0 on success, otherwise error
*/
-static int ksmbd_vfs_lookup_in_dir(struct path *dir, char *name, size_t namelen)
+static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name, size_t namelen)
{
int ret;
struct file *dfilp;
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index 432c94773177..7dd054f86850 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -124,7 +124,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id);
int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name);
int ksmbd_vfs_link(struct ksmbd_work *work,
const char *oldname, const char *newname);
-int ksmbd_vfs_getattr(struct path *path, struct kstat *stat);
+int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat);
int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
char *newname);
int ksmbd_vfs_truncate(struct ksmbd_work *work,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 051/154] ksmbd: remove generic_fillattr use in smb2_open()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (49 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 050/154] ksmbd: constify struct path Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 052/154] ksmbd: casefold utf-8 share names and fix ascii lowercase conversion Namjae Jeon
` (103 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Hyunchul Lee, Steve French
[ Upstream commit 823d0d3e2b05791ba8cbab22574b947c21f89c18 ]
Removed the use of unneeded generic_fillattr() in smb2_open().
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 8f929807f4c8..4a68cf9624f7 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2809,7 +2809,6 @@ int smb2_open(struct ksmbd_work *work)
} else {
file_present = true;
user_ns = mnt_user_ns(path.mnt);
- generic_fillattr(user_ns, d_inode(path.dentry), &stat);
}
if (stream_name) {
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
@@ -2818,7 +2817,8 @@ int smb2_open(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
}
} else {
- if (S_ISDIR(stat.mode) && s_type == DATA_STREAM) {
+ if (file_present && S_ISDIR(d_inode(path.dentry)->i_mode) &&
+ s_type == DATA_STREAM) {
rc = -EIO;
rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
}
@@ -2835,7 +2835,8 @@ int smb2_open(struct ksmbd_work *work)
}
if (file_present && req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE &&
- S_ISDIR(stat.mode) && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
+ S_ISDIR(d_inode(path.dentry)->i_mode) &&
+ !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
ksmbd_debug(SMB, "open() argument is a directory: %s, %x\n",
name, req->CreateOptions);
rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
@@ -2845,7 +2846,7 @@ int smb2_open(struct ksmbd_work *work)
if (file_present && (req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
!(req->CreateDisposition == FILE_CREATE_LE) &&
- !S_ISDIR(stat.mode)) {
+ !S_ISDIR(d_inode(path.dentry)->i_mode)) {
rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
rc = -EIO;
goto err_out;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 052/154] ksmbd: casefold utf-8 share names and fix ascii lowercase conversion
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (50 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 051/154] ksmbd: remove generic_fillattr use in smb2_open() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 053/154] ksmbd: change security id to the one samba used for posix extension Namjae Jeon
` (102 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Atte Heikkilä, Namjae Jeon, Steve French
From: Atte Heikkilä <atteh.mailbox@gmail.com>
[ Upstream commit 16b5f54e30c1ddec36bdf946a299b3254aace477 ]
strtolower() corrupts all UTF-8 share names that have a byte in the C0
(À ISO8859-1) to DE (Þ ISO8859-1) range, since the non-ASCII part of
ISO8859-1 is incompatible with UTF-8. Prevent this by checking that a
byte is in the ASCII range with isascii(), before the conversion to
lowercase with tolower(). Properly handle case-insensitivity of UTF-8
share names by casefolding them, but fallback to ASCII lowercase
conversion on failure or if CONFIG_UNICODE is not set. Refactor to move
the share name casefolding immediately after the share name extraction.
Also, make the associated constness corrections.
Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 8 +++++++
fs/ksmbd/connection.h | 1 +
fs/ksmbd/mgmt/share_config.c | 18 ++++-----------
fs/ksmbd/mgmt/share_config.h | 2 +-
fs/ksmbd/mgmt/tree_connect.c | 2 +-
fs/ksmbd/mgmt/tree_connect.h | 2 +-
fs/ksmbd/misc.c | 44 +++++++++++++++++++++++++++++-------
fs/ksmbd/misc.h | 2 +-
fs/ksmbd/smb2pdu.c | 2 +-
fs/ksmbd/unicode.h | 3 ++-
10 files changed, 56 insertions(+), 28 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index be1f8ffa4a78..14326323da79 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -60,6 +60,12 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
conn->local_nls = load_nls("utf8");
if (!conn->local_nls)
conn->local_nls = load_nls_default();
+ if (IS_ENABLED(CONFIG_UNICODE))
+ conn->um = utf8_load("12.1.0");
+ else
+ conn->um = ERR_PTR(-EOPNOTSUPP);
+ if (IS_ERR(conn->um))
+ conn->um = NULL;
atomic_set(&conn->req_running, 0);
atomic_set(&conn->r_count, 0);
conn->total_credits = 1;
@@ -361,6 +367,8 @@ int ksmbd_conn_handler_loop(void *p)
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
+ if (IS_ENABLED(CONFIG_UNICODE))
+ utf8_unload(conn->um);
unload_nls(conn->local_nls);
if (default_conn_ops.terminate_fn)
default_conn_ops.terminate_fn(conn);
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index a8c367c481e8..8c99fdbd701f 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -46,6 +46,7 @@ struct ksmbd_conn {
char *request_buf;
struct ksmbd_transport *transport;
struct nls_table *local_nls;
+ struct unicode_map *um;
struct list_head conns_list;
/* smb session 1 per user */
struct xarray sessions;
diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
index c9bca1c2c834..5d039704c23c 100644
--- a/fs/ksmbd/mgmt/share_config.c
+++ b/fs/ksmbd/mgmt/share_config.c
@@ -26,7 +26,7 @@ struct ksmbd_veto_pattern {
struct list_head list;
};
-static unsigned int share_name_hash(char *name)
+static unsigned int share_name_hash(const char *name)
{
return jhash(name, strlen(name), 0);
}
@@ -72,7 +72,7 @@ __get_share_config(struct ksmbd_share_config *share)
return share;
}
-static struct ksmbd_share_config *__share_lookup(char *name)
+static struct ksmbd_share_config *__share_lookup(const char *name)
{
struct ksmbd_share_config *share;
unsigned int key = share_name_hash(name);
@@ -119,7 +119,7 @@ static int parse_veto_list(struct ksmbd_share_config *share,
return 0;
}
-static struct ksmbd_share_config *share_config_request(char *name)
+static struct ksmbd_share_config *share_config_request(const char *name)
{
struct ksmbd_share_config_response *resp;
struct ksmbd_share_config *share = NULL;
@@ -190,20 +190,10 @@ static struct ksmbd_share_config *share_config_request(char *name)
return share;
}
-static void strtolower(char *share_name)
-{
- while (*share_name) {
- *share_name = tolower(*share_name);
- share_name++;
- }
-}
-
-struct ksmbd_share_config *ksmbd_share_config_get(char *name)
+struct ksmbd_share_config *ksmbd_share_config_get(const char *name)
{
struct ksmbd_share_config *share;
- strtolower(name);
-
down_read(&shares_table_lock);
share = __share_lookup(name);
if (share)
diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h
index 902f2cb1963a..7f7e89ecfe61 100644
--- a/fs/ksmbd/mgmt/share_config.h
+++ b/fs/ksmbd/mgmt/share_config.h
@@ -74,7 +74,7 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
__ksmbd_share_config_put(share);
}
-struct ksmbd_share_config *ksmbd_share_config_get(char *name);
+struct ksmbd_share_config *ksmbd_share_config_get(const char *name);
bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
const char *filename);
#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index 97ab7987df6e..867c0286b901 100644
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -17,7 +17,7 @@
struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- char *share_name)
+ const char *share_name)
{
struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
struct ksmbd_tree_connect_response *resp = NULL;
diff --git a/fs/ksmbd/mgmt/tree_connect.h b/fs/ksmbd/mgmt/tree_connect.h
index 71e50271dccf..0f97ddc1e39c 100644
--- a/fs/ksmbd/mgmt/tree_connect.h
+++ b/fs/ksmbd/mgmt/tree_connect.h
@@ -42,7 +42,7 @@ struct ksmbd_session;
struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- char *share_name);
+ const char *share_name);
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *tree_conn);
diff --git a/fs/ksmbd/misc.c b/fs/ksmbd/misc.c
index 364a0a463dfc..28459b1efaa8 100644
--- a/fs/ksmbd/misc.c
+++ b/fs/ksmbd/misc.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/xattr.h>
#include <linux/fs.h>
+#include <linux/unicode.h>
#include "misc.h"
#include "smb_common.h"
@@ -226,26 +227,53 @@ void ksmbd_conv_path_to_windows(char *path)
strreplace(path, '/', '\\');
}
+static char *casefold_sharename(struct unicode_map *um, const char *name)
+{
+ char *cf_name;
+ int cf_len;
+
+ cf_name = kzalloc(KSMBD_REQ_MAX_SHARE_NAME, GFP_KERNEL);
+ if (!cf_name)
+ return ERR_PTR(-ENOMEM);
+
+ if (IS_ENABLED(CONFIG_UNICODE) && um) {
+ const struct qstr q_name = {.name = name, .len = strlen(name)};
+
+ cf_len = utf8_casefold(um, &q_name, cf_name,
+ KSMBD_REQ_MAX_SHARE_NAME);
+ if (cf_len < 0)
+ goto out_ascii;
+
+ return cf_name;
+ }
+
+out_ascii:
+ cf_len = strscpy(cf_name, name, KSMBD_REQ_MAX_SHARE_NAME);
+ if (cf_len < 0) {
+ kfree(cf_name);
+ return ERR_PTR(-E2BIG);
+ }
+
+ for (; *cf_name; ++cf_name)
+ *cf_name = isascii(*cf_name) ? tolower(*cf_name) : *cf_name;
+ return cf_name - cf_len;
+}
+
/**
* ksmbd_extract_sharename() - get share name from tree connect request
* @treename: buffer containing tree name and share name
*
* Return: share name on success, otherwise error
*/
-char *ksmbd_extract_sharename(char *treename)
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
{
- char *name = treename;
- char *dst;
- char *pos = strrchr(name, '\\');
+ const char *name = treename, *pos = strrchr(name, '\\');
if (pos)
name = (pos + 1);
/* caller has to free the memory */
- dst = kstrdup(name, GFP_KERNEL);
- if (!dst)
- return ERR_PTR(-ENOMEM);
- return dst;
+ return casefold_sharename(um, name);
}
/**
diff --git a/fs/ksmbd/misc.h b/fs/ksmbd/misc.h
index 5a0ae2f8e5e7..cc72f4e6baf2 100644
--- a/fs/ksmbd/misc.h
+++ b/fs/ksmbd/misc.h
@@ -20,7 +20,7 @@ int get_nlink(struct kstat *st);
void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(char *path);
void ksmbd_conv_path_to_windows(char *path);
-char *ksmbd_extract_sharename(char *treename);
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
#define KSMBD_DIR_INFO_ALIGNMENT 8
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 4a68cf9624f7..9aad3d7e0c95 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1924,7 +1924,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
goto out_err1;
}
- name = ksmbd_extract_sharename(treename);
+ name = ksmbd_extract_sharename(conn->um, treename);
if (IS_ERR(name)) {
status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
goto out_err1;
diff --git a/fs/ksmbd/unicode.h b/fs/ksmbd/unicode.h
index 5593024230ae..076f6034a789 100644
--- a/fs/ksmbd/unicode.h
+++ b/fs/ksmbd/unicode.h
@@ -24,6 +24,7 @@
#include <asm/byteorder.h>
#include <linux/types.h>
#include <linux/nls.h>
+#include <linux/unicode.h>
#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
@@ -69,7 +70,7 @@ char *smb_strndup_from_utf16(const char *src, const int maxlen,
const struct nls_table *codepage);
int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
const struct nls_table *cp, int mapchars);
-char *ksmbd_extract_sharename(char *treename);
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
#endif
/*
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 053/154] ksmbd: change security id to the one samba used for posix extension
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (51 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 052/154] ksmbd: casefold utf-8 share names and fix ascii lowercase conversion Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 054/154] ksmbd: set file permission mode to match Samba server posix extension behavior Namjae Jeon
` (101 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 5609bdd9ffdccd83f9003511b1801584b703baa5 ]
Samba set SIDOWNER and SIDUNIX_GROUP in create posix context and
set SIDUNIX_USER/GROUP in other sids for posix extension.
This patch change security id to the one samba used.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/oplock.c | 17 ++++++++++++++---
fs/ksmbd/smb2pdu.c | 9 +++++++--
fs/ksmbd/smb2pdu.h | 6 ++++--
3 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index b527f451d7a4..c2a19328f01d 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -1615,7 +1615,11 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
memset(buf, 0, sizeof(struct create_posix_rsp));
buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_posix_rsp, nlink));
- buf->ccontext.DataLength = cpu_to_le32(52);
+ /*
+ * DataLength = nlink(4) + reparse_tag(4) + mode(4) +
+ * domain sid(28) + unix group sid(16).
+ */
+ buf->ccontext.DataLength = cpu_to_le32(56);
buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_posix_rsp, Name));
buf->ccontext.NameLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
@@ -1640,12 +1644,19 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
buf->nlink = cpu_to_le32(inode->i_nlink);
buf->reparse_tag = cpu_to_le32(fp->volatile_id);
buf->mode = cpu_to_le32(inode->i_mode);
+ /*
+ * SidBuffer(44) contain two sids(Domain sid(28), UNIX group sid(16)).
+ * Domain sid(28) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 4(num_subauth)) + RID(4).
+ * UNIX group id(16) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 1(num_subauth)) + RID(4).
+ */
id_to_sid(from_kuid_munged(&init_user_ns,
i_uid_into_mnt(user_ns, inode)),
- SIDNFS_USER, (struct smb_sid *)&buf->SidBuffer[0]);
+ SIDOWNER, (struct smb_sid *)&buf->SidBuffer[0]);
id_to_sid(from_kgid_munged(&init_user_ns,
i_gid_into_mnt(user_ns, inode)),
- SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]);
+ SIDUNIX_GROUP, (struct smb_sid *)&buf->SidBuffer[28]);
}
/*
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 9aad3d7e0c95..e78b36d74baa 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3619,10 +3619,15 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE;
if (d_info->hide_dot_file && d_info->name[0] == '.')
posix_info->DosAttributes |= ATTR_HIDDEN_LE;
+ /*
+ * SidBuffer(32) contain two sids(Domain sid(16), UNIX group sid(16)).
+ * UNIX sid(16) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 1(num_subauth)) + RID(4).
+ */
id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid),
- SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
+ SIDUNIX_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid),
- SIDNFS_GROUP, (struct smb_sid *)&posix_info->SidBuffer[20]);
+ SIDUNIX_GROUP, (struct smb_sid *)&posix_info->SidBuffer[16]);
memcpy(posix_info->name, conv_name, conv_len);
posix_info->name_len = cpu_to_le32(conv_len);
posix_info->NextEntryOffset = cpu_to_le32(next_entry_offset);
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index 10776df5baa7..fe391b8afa9c 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -724,7 +724,8 @@ struct create_posix_rsp {
__le32 nlink;
__le32 reparse_tag;
__le32 mode;
- u8 SidBuffer[40];
+ /* SidBuffer contain two sids(Domain sid(28), UNIX group sid(16)) */
+ u8 SidBuffer[44];
} __packed;
#define SMB2_LEASE_NONE_LE cpu_to_le32(0x00)
@@ -1617,7 +1618,8 @@ struct smb2_posix_info {
__le32 HardLinks;
__le32 ReparseTag;
__le32 Mode;
- u8 SidBuffer[40];
+ /* SidBuffer contain two sids (UNIX user sid(16), UNIX group sid(16)) */
+ u8 SidBuffer[32];
__le32 name_len;
u8 name[1];
/*
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 054/154] ksmbd: set file permission mode to match Samba server posix extension behavior
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (52 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 053/154] ksmbd: change security id to the one samba used for posix extension Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 055/154] ksmbd: fill sids in SMB_FIND_FILE_POSIX_INFO response Namjae Jeon
` (100 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit f6c2b201da7588f7f7688ddc99b7bb000609129c ]
Set file permission mode to match Samba server posix extension behavior.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/oplock.c | 2 +-
fs/ksmbd/smb2pdu.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index c2a19328f01d..919c598a9d66 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -1643,7 +1643,7 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
buf->nlink = cpu_to_le32(inode->i_nlink);
buf->reparse_tag = cpu_to_le32(fp->volatile_id);
- buf->mode = cpu_to_le32(inode->i_mode);
+ buf->mode = cpu_to_le32(inode->i_mode & 0777);
/*
* SidBuffer(44) contain two sids(Domain sid(28), UNIX group sid(16)).
* Domain sid(28) = revision(1) + num_subauth(1) + authority(6) +
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index e78b36d74baa..9e9ba815ffa3 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3613,7 +3613,7 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
posix_info->AllocationSize = cpu_to_le64(ksmbd_kstat->kstat->blocks << 9);
posix_info->DeviceId = cpu_to_le32(ksmbd_kstat->kstat->rdev);
posix_info->HardLinks = cpu_to_le32(ksmbd_kstat->kstat->nlink);
- posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode);
+ posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode & 0777);
posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino);
posix_info->DosAttributes =
S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE;
@@ -4769,7 +4769,7 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
file_info->EndOfFile = cpu_to_le64(inode->i_size);
file_info->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
file_info->HardLinks = cpu_to_le32(inode->i_nlink);
- file_info->Mode = cpu_to_le32(inode->i_mode);
+ file_info->Mode = cpu_to_le32(inode->i_mode & 0777);
file_info->DeviceId = cpu_to_le32(inode->i_rdev);
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb311_posix_qinfo));
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 055/154] ksmbd: fill sids in SMB_FIND_FILE_POSIX_INFO response
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (53 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 054/154] ksmbd: set file permission mode to match Samba server posix extension behavior Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 056/154] ksmbd: fix encryption failure issue for session logoff response Namjae Jeon
` (99 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit d5919f2a1459083bd0aaede7fc44e945290e44df ]
This patch fill missing sids in SMB_FIND_FILE_POSIX_INFO response.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 9e9ba815ffa3..85678fcabe3c 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -4754,7 +4754,9 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
{
struct smb311_posix_qinfo *file_info;
struct inode *inode = file_inode(fp->filp);
+ struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
u64 time;
+ int out_buf_len = sizeof(struct smb311_posix_qinfo) + 32;
file_info = (struct smb311_posix_qinfo *)rsp->Buffer;
file_info->CreationTime = cpu_to_le64(fp->create_time);
@@ -4771,10 +4773,24 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
file_info->HardLinks = cpu_to_le32(inode->i_nlink);
file_info->Mode = cpu_to_le32(inode->i_mode & 0777);
file_info->DeviceId = cpu_to_le32(inode->i_rdev);
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb311_posix_qinfo));
- inc_rfc1001_len(rsp_org, sizeof(struct smb311_posix_qinfo));
- return 0;
+
+ /*
+ * Sids(32) contain two sids(Domain sid(16), UNIX group sid(16)).
+ * UNIX sid(16) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 1(num_subauth)) + RID(4).
+ */
+ id_to_sid(from_kuid_munged(&init_user_ns,
+ i_uid_into_mnt(user_ns, inode)),
+ SIDUNIX_USER,
+ (struct smb_sid *)&file_info->Sids[0]);
+ id_to_sid(from_kgid_munged(&init_user_ns,
+ i_gid_into_mnt(user_ns, inode)),
+ SIDUNIX_GROUP,
+ (struct smb_sid *)&file_info->Sids[16]);
+
+ rsp->OutputBufferLength = cpu_to_le32(out_buf_len);
+ inc_rfc1001_len(rsp_org, out_buf_len);
+ return out_buf_len;
}
static int smb2_get_info_file(struct ksmbd_work *work,
@@ -4894,8 +4910,8 @@ static int smb2_get_info_file(struct ksmbd_work *work,
pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
rc = -EOPNOTSUPP;
} else {
- rc = find_file_posix_info(rsp, fp, work->response_buf);
- file_infoclass_size = sizeof(struct smb311_posix_qinfo);
+ file_infoclass_size = find_file_posix_info(rsp, fp,
+ work->response_buf);
}
break;
default:
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 056/154] ksmbd: fix encryption failure issue for session logoff response
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (54 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 055/154] ksmbd: fill sids in SMB_FIND_FILE_POSIX_INFO response Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 057/154] ksmbd: set NTLMSSP_NEGOTIATE_SEAL flag to challenge blob Namjae Jeon
` (98 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit af705ef2b0ded0d8f54c238fdf3c17a1d47ad924 ]
If client send encrypted session logoff request on seal mount,
Encryption for that response fails.
ksmbd: Could not get encryption key
CIFS: VFS: cifs_put_smb_ses: Session Logoff failure rc=-512
Session lookup fails in ksmbd_get_encryption_key() because sess->state is
set to SMB2_SESSION_EXPIRED in session logoff. There is no need to do
session lookup again to encrypt the response. This patch change to use
ksmbd_session in ksmbd_work.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 12 ++++++++----
fs/ksmbd/auth.h | 3 ++-
fs/ksmbd/smb2pdu.c | 7 +++----
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index 2048e0546116..45f0e9a75e63 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -988,13 +988,16 @@ int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
return rc;
}
-static int ksmbd_get_encryption_key(struct ksmbd_conn *conn, __u64 ses_id,
+static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
int enc, u8 *key)
{
struct ksmbd_session *sess;
u8 *ses_enc_key;
- sess = ksmbd_session_lookup_all(conn, ses_id);
+ if (enc)
+ sess = work->sess;
+ else
+ sess = ksmbd_session_lookup_all(work->conn, ses_id);
if (!sess)
return -EINVAL;
@@ -1082,9 +1085,10 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
return sg;
}
-int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
+int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
unsigned int nvec, int enc)
{
+ struct ksmbd_conn *conn = work->conn;
struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int rc;
@@ -1098,7 +1102,7 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
struct ksmbd_crypto_ctx *ctx;
- rc = ksmbd_get_encryption_key(conn,
+ rc = ksmbd_get_encryption_key(work,
le64_to_cpu(tr_hdr->SessionId),
enc,
key);
diff --git a/fs/ksmbd/auth.h b/fs/ksmbd/auth.h
index 25b772653de0..362b6159a6cf 100644
--- a/fs/ksmbd/auth.h
+++ b/fs/ksmbd/auth.h
@@ -33,9 +33,10 @@
struct ksmbd_session;
struct ksmbd_conn;
+struct ksmbd_work;
struct kvec;
-int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
+int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
unsigned int nvec, int enc);
void ksmbd_copy_gss_neg_header(void *buf);
int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 85678fcabe3c..933f806f14dc 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -8645,7 +8645,7 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
buf_size += iov[1].iov_len;
work->resp_hdr_sz = iov[1].iov_len;
- rc = ksmbd_crypt_message(work->conn, iov, rq_nvec, 1);
+ rc = ksmbd_crypt_message(work, iov, rq_nvec, 1);
if (rc)
return rc;
@@ -8664,7 +8664,6 @@ bool smb3_is_transform_hdr(void *buf)
int smb3_decrypt_req(struct ksmbd_work *work)
{
- struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess;
char *buf = work->request_buf;
unsigned int pdu_length = get_rfc1002_len(buf);
@@ -8685,7 +8684,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
return -ECONNABORTED;
}
- sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId));
+ sess = ksmbd_session_lookup_all(work->conn, le64_to_cpu(tr_hdr->SessionId));
if (!sess) {
pr_err("invalid session id(%llx) in transform header\n",
le64_to_cpu(tr_hdr->SessionId));
@@ -8696,7 +8695,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr) + 4;
iov[1].iov_len = buf_data_size;
- rc = ksmbd_crypt_message(conn, iov, 2, 0);
+ rc = ksmbd_crypt_message(work, iov, 2, 0);
if (rc)
return rc;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 057/154] ksmbd: set NTLMSSP_NEGOTIATE_SEAL flag to challenge blob
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (55 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 056/154] ksmbd: fix encryption failure issue for session logoff response Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 058/154] ksmbd: decrease the number of SMB3 smbdirect server SGEs Namjae Jeon
` (97 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 5bedae90b369ca1a7660b9af39591ed19009b495 ]
If NTLMSSP_NEGOTIATE_SEAL flags is set in negotiate blob from client,
Set NTLMSSP_NEGOTIATE_SEAL flag to challenge blob.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 3 +++
fs/ksmbd/smb2pdu.c | 2 +-
fs/ksmbd/smb2pdu.h | 1 +
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index 45f0e9a75e63..bad4c3af9540 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -428,6 +428,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
NTLMSSP_NEGOTIATE_56);
}
+ if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn))
+ flags |= NTLMSSP_NEGOTIATE_SEAL;
+
if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 933f806f14dc..8151f7782329 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -956,7 +956,7 @@ static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
*
* Return: true if connection should be encrypted, else false
*/
-static bool smb3_encryption_negotiated(struct ksmbd_conn *conn)
+bool smb3_encryption_negotiated(struct ksmbd_conn *conn)
{
if (!conn->ops->generate_encryptionkey)
return false;
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index fe391b8afa9c..e20d4d707f1b 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -1672,6 +1672,7 @@ int smb3_decrypt_req(struct ksmbd_work *work);
int smb3_encrypt_resp(struct ksmbd_work *work);
bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work);
int smb2_set_rsp_credits(struct ksmbd_work *work);
+bool smb3_encryption_negotiated(struct ksmbd_conn *conn);
/* smb2 misc functions */
int ksmbd_smb2_check_message(struct ksmbd_work *work);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 058/154] ksmbd: decrease the number of SMB3 smbdirect server SGEs
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (56 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 057/154] ksmbd: set NTLMSSP_NEGOTIATE_SEAL flag to challenge blob Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 059/154] ksmbd: reduce server smbdirect max send/receive segment sizes Namjae Jeon
` (96 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Tom Talpey, Namjae Jeon, Steve French
From: Tom Talpey <tom@talpey.com>
[ Upstream commit 2b4eeeaa90617c5e37da7c804c422b4e833b87b2 ]
The server-side SMBDirect layer requires no more than 6 send SGEs
The previous default of 8 causes ksmbd to fail on the SoftiWARP
(siw) provider, and possibly others. Additionally, large numbers
of SGEs reduces performance significantly on adapter implementations.
Signed-off-by: Tom Talpey <tom@talpey.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 7bac4b09c844..ef4891b54447 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -32,7 +32,7 @@
/* SMB_DIRECT negotiation timeout in seconds */
#define SMB_DIRECT_NEGOTIATE_TIMEOUT 120
-#define SMB_DIRECT_MAX_SEND_SGES 8
+#define SMB_DIRECT_MAX_SEND_SGES 6
#define SMB_DIRECT_MAX_RECV_SGES 1
/*
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 059/154] ksmbd: reduce server smbdirect max send/receive segment sizes
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (57 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 058/154] ksmbd: decrease the number of SMB3 smbdirect server SGEs Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 060/154] ksmbd: hide socket error message when ipv6 config is disable Namjae Jeon
` (95 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Tom Talpey, Namjae Jeon, Steve French
From: Tom Talpey <tom@talpey.com>
[ Upstream commit 78af146e109bef5b3c411964141c6f8adbccd3b0 ]
Reduce ksmbd smbdirect max segment send and receive size to 1364
to match protocol norms. Larger buffers are unnecessary and add
significant memory overhead.
Signed-off-by: Tom Talpey <tom@talpey.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index ef4891b54447..652391aee733 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -62,13 +62,13 @@ static int smb_direct_receive_credit_max = 255;
static int smb_direct_send_credit_target = 255;
/* The maximum single message size can be sent to remote peer */
-static int smb_direct_max_send_size = 8192;
+static int smb_direct_max_send_size = 1364;
/* The maximum fragmented upper-layer payload receive size supported */
static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
/* The maximum single-message size which can be received */
-static int smb_direct_max_receive_size = 8192;
+static int smb_direct_max_receive_size = 1364;
static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 060/154] ksmbd: hide socket error message when ipv6 config is disable
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (58 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 059/154] ksmbd: reduce server smbdirect max send/receive segment sizes Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 061/154] ksmbd: make utf-8 file name comparison work in __caseless_lookup() Namjae Jeon
` (94 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Tom Talpey, Steve French
[ Upstream commit 5876e99611a91dfb2fb1f7af9d1ae5c017c8331c ]
When ipv6 config is disable(CONFIG_IPV6 is not set), ksmbd fallback to
create ipv4 socket. User reported that this error message lead to
misunderstood some issue. Users have requested not to print this error
message that occurs even though there is no problem.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Acked-by: Tom Talpey <tom@talpey.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_tcp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
index 4995f74fb21c..20e85e2701f2 100644
--- a/fs/ksmbd/transport_tcp.c
+++ b/fs/ksmbd/transport_tcp.c
@@ -428,7 +428,8 @@ static int create_socket(struct interface *iface)
ret = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &ksmbd_socket);
if (ret) {
- pr_err("Can't create socket for ipv6, try ipv4: %d\n", ret);
+ if (ret != -EAFNOSUPPORT)
+ pr_err("Can't create socket for ipv6, fallback to ipv4: %d\n", ret);
ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP,
&ksmbd_socket);
if (ret) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 061/154] ksmbd: make utf-8 file name comparison work in __caseless_lookup()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (59 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 060/154] ksmbd: hide socket error message when ipv6 config is disable Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 062/154] ksmbd: call ib_drain_qp when disconnected Namjae Jeon
` (93 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Atte Heikkilä, Namjae Jeon, Steve French
From: Atte Heikkilä <atteh.mailbox@gmail.com>
[ Upstream commit dbab80e2071ad8c702e50dab43326608a127d27b ]
Case-insensitive file name lookups with __caseless_lookup() use
strncasecmp() for file name comparison. strncasecmp() assumes an
ISO8859-1-compatible encoding, which is not the case here as UTF-8
is always used. As such, use of strncasecmp() here produces correct
results only if both strings use characters in the ASCII range only.
Fix this by using utf8_strncasecmp() if CONFIG_UNICODE is set. On
failure or if CONFIG_UNICODE is not set, fallback to strncasecmp().
Also, as we are adding an include for `linux/unicode.h', include it
in `fs/ksmbd/connection.h' as well since it should be explicit there.
Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.h | 1 +
fs/ksmbd/vfs.c | 20 +++++++++++++++++---
fs/ksmbd/vfs.h | 2 ++
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index 8c99fdbd701f..0e3a848defaf 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -14,6 +14,7 @@
#include <net/request_sock.h>
#include <linux/kthread.h>
#include <linux/nls.h>
+#include <linux/unicode.h>
#include "smb_common.h"
#include "ksmbd_work.h"
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 284aa87f3e5c..d7814397764c 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -1144,12 +1144,23 @@ static int __caseless_lookup(struct dir_context *ctx, const char *name,
unsigned int d_type)
{
struct ksmbd_readdir_data *buf;
+ int cmp = -EINVAL;
buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
if (buf->used != namlen)
return 0;
- if (!strncasecmp((char *)buf->private, name, namlen)) {
+ if (IS_ENABLED(CONFIG_UNICODE) && buf->um) {
+ const struct qstr q_buf = {.name = buf->private,
+ .len = buf->used};
+ const struct qstr q_name = {.name = name,
+ .len = namlen};
+
+ cmp = utf8_strncasecmp(buf->um, &q_buf, &q_name);
+ }
+ if (cmp < 0)
+ cmp = strncasecmp((char *)buf->private, name, namlen);
+ if (!cmp) {
memcpy((char *)buf->private, name, namlen);
buf->dirent_count = 1;
return -EEXIST;
@@ -1165,7 +1176,8 @@ static int __caseless_lookup(struct dir_context *ctx, const char *name,
*
* Return: 0 on success, otherwise error
*/
-static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name, size_t namelen)
+static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
+ size_t namelen, struct unicode_map *um)
{
int ret;
struct file *dfilp;
@@ -1175,6 +1187,7 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name, size_t na
.private = name,
.used = namelen,
.dirent_count = 0,
+ .um = um,
};
dfilp = dentry_open(dir, flags, current_cred());
@@ -1237,7 +1250,8 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
break;
err = ksmbd_vfs_lookup_in_dir(&parent, filename,
- filename_len);
+ filename_len,
+ work->conn->um);
path_put(&parent);
if (err)
goto out;
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index 7dd054f86850..1f0cbd520f12 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -12,6 +12,7 @@
#include <linux/namei.h>
#include <uapi/linux/xattr.h>
#include <linux/posix_acl.h>
+#include <linux/unicode.h>
#include "smbacl.h"
#include "xattr.h"
@@ -99,6 +100,7 @@ struct ksmbd_readdir_data {
unsigned int used;
unsigned int dirent_count;
unsigned int file_attr;
+ struct unicode_map *um;
};
/* ksmbd kstat wrapper to get valid create time when reading dir entry */
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 062/154] ksmbd: call ib_drain_qp when disconnected
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (60 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 061/154] ksmbd: make utf-8 file name comparison work in __caseless_lookup() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 063/154] ksmbd: validate share name from share config response Namjae Jeon
` (92 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Namjae Jeon, Hyunchul Lee, Tom Talpey, Steve French
[ Upstream commit 141fa9824c0fc11d44b2d5bb1266a33e95fa67fd ]
When disconnected, call ib_drain_qp to cancel all pending work requests
and prevent ksmbd_conn_handler_loop from waiting for a long time
for those work requests to compelete.
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Tom Talpey <tom@talpey.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 652391aee733..68077150ad2f 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1527,6 +1527,8 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
}
case RDMA_CM_EVENT_DEVICE_REMOVAL:
case RDMA_CM_EVENT_DISCONNECTED: {
+ ib_drain_qp(t->qp);
+
t->status = SMB_DIRECT_CS_DISCONNECTED;
wake_up_interruptible(&t->wait_status);
wake_up_interruptible(&t->wait_reassembly_queue);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 063/154] ksmbd: validate share name from share config response
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (61 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 062/154] ksmbd: call ib_drain_qp when disconnected Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 064/154] ksmbd: replace one-element arrays with flexible-array members Namjae Jeon
` (91 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Atte Heikkilä, Tom Talpey, Namjae Jeon,
Steve French
From: Atte Heikkilä <atteh.mailbox@gmail.com>
[ Upstream commit f5ba1cdaf5eb380e148183bda06d4844b457d095 ]
Share config response may contain the share name without casefolding as
it is known to the user space daemon. When it is present, casefold and
compare it to the share name the share config request was made with. If
they differ, we have a share config which is incompatible with the way
share config caching is done. This is the case when CONFIG_UNICODE is
not set, the share name contains non-ASCII characters, and those non-
ASCII characters do not match those in the share name known to user
space. In other words, when CONFIG_UNICODE is not set, UTF-8 share
names now work but are only case-insensitive in the ASCII range.
Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com>
Acked-by: Tom Talpey <tom@talpey.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_netlink.h | 3 ++-
fs/ksmbd/mgmt/share_config.c | 22 +++++++++++++++++++---
fs/ksmbd/mgmt/share_config.h | 4 +++-
fs/ksmbd/mgmt/tree_connect.c | 4 ++--
fs/ksmbd/misc.c | 4 ++--
fs/ksmbd/misc.h | 1 +
6 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
index 17ad22808ee3..dd760c78af7b 100644
--- a/fs/ksmbd/ksmbd_netlink.h
+++ b/fs/ksmbd/ksmbd_netlink.h
@@ -164,7 +164,8 @@ struct ksmbd_share_config_response {
__u16 force_directory_mode;
__u16 force_uid;
__u16 force_gid;
- __u32 reserved[128]; /* Reserved room */
+ __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME];
+ __u32 reserved[112]; /* Reserved room */
__u32 veto_list_sz;
__s8 ____payload[];
};
diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
index 5d039704c23c..328a412259dc 100644
--- a/fs/ksmbd/mgmt/share_config.c
+++ b/fs/ksmbd/mgmt/share_config.c
@@ -16,6 +16,7 @@
#include "user_config.h"
#include "user_session.h"
#include "../transport_ipc.h"
+#include "../misc.h"
#define SHARE_HASH_BITS 3
static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
@@ -119,7 +120,8 @@ static int parse_veto_list(struct ksmbd_share_config *share,
return 0;
}
-static struct ksmbd_share_config *share_config_request(const char *name)
+static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
+ const char *name)
{
struct ksmbd_share_config_response *resp;
struct ksmbd_share_config *share = NULL;
@@ -133,6 +135,19 @@ static struct ksmbd_share_config *share_config_request(const char *name)
if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
goto out;
+ if (*resp->share_name) {
+ char *cf_resp_name;
+ bool equal;
+
+ cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);
+ if (IS_ERR(cf_resp_name))
+ goto out;
+ equal = !strcmp(cf_resp_name, name);
+ kfree(cf_resp_name);
+ if (!equal)
+ goto out;
+ }
+
share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
if (!share)
goto out;
@@ -190,7 +205,8 @@ static struct ksmbd_share_config *share_config_request(const char *name)
return share;
}
-struct ksmbd_share_config *ksmbd_share_config_get(const char *name)
+struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+ const char *name)
{
struct ksmbd_share_config *share;
@@ -202,7 +218,7 @@ struct ksmbd_share_config *ksmbd_share_config_get(const char *name)
if (share)
return share;
- return share_config_request(name);
+ return share_config_request(um, name);
}
bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h
index 7f7e89ecfe61..3fd338293942 100644
--- a/fs/ksmbd/mgmt/share_config.h
+++ b/fs/ksmbd/mgmt/share_config.h
@@ -9,6 +9,7 @@
#include <linux/workqueue.h>
#include <linux/hashtable.h>
#include <linux/path.h>
+#include <linux/unicode.h>
struct ksmbd_share_config {
char *name;
@@ -74,7 +75,8 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
__ksmbd_share_config_put(share);
}
-struct ksmbd_share_config *ksmbd_share_config_get(const char *name);
+struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+ const char *name);
bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
const char *filename);
#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index 867c0286b901..8ce17b3fb8da 100644
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -26,7 +26,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct sockaddr *peer_addr;
int ret;
- sc = ksmbd_share_config_get(share_name);
+ sc = ksmbd_share_config_get(conn->um, share_name);
if (!sc)
return status;
@@ -61,7 +61,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct ksmbd_share_config *new_sc;
ksmbd_share_config_del(sc);
- new_sc = ksmbd_share_config_get(share_name);
+ new_sc = ksmbd_share_config_get(conn->um, share_name);
if (!new_sc) {
pr_err("Failed to update stale share config\n");
status.ret = -ESTALE;
diff --git a/fs/ksmbd/misc.c b/fs/ksmbd/misc.c
index 28459b1efaa8..9e8afaa686e3 100644
--- a/fs/ksmbd/misc.c
+++ b/fs/ksmbd/misc.c
@@ -227,7 +227,7 @@ void ksmbd_conv_path_to_windows(char *path)
strreplace(path, '/', '\\');
}
-static char *casefold_sharename(struct unicode_map *um, const char *name)
+char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name)
{
char *cf_name;
int cf_len;
@@ -273,7 +273,7 @@ char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
name = (pos + 1);
/* caller has to free the memory */
- return casefold_sharename(um, name);
+ return ksmbd_casefold_sharename(um, name);
}
/**
diff --git a/fs/ksmbd/misc.h b/fs/ksmbd/misc.h
index cc72f4e6baf2..1facfcd21200 100644
--- a/fs/ksmbd/misc.h
+++ b/fs/ksmbd/misc.h
@@ -20,6 +20,7 @@ int get_nlink(struct kstat *st);
void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(char *path);
void ksmbd_conv_path_to_windows(char *path);
+char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name);
char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 064/154] ksmbd: replace one-element arrays with flexible-array members
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (62 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 063/154] ksmbd: validate share name from share config response Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 065/154] ksmbd: set SMB2_SESSION_FLAG_ENCRYPT_DATA when enforcing data encryption for this share Namjae Jeon
` (90 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Gustavo A. R. Silva, Sergey Senozhatsky, Namjae Jeon,
Kees Cook
From: "Gustavo A. R. Silva" <gustavoars@kernel.org>
[ Upstream commit d272e01fa0a2f15c5c331a37cd99c6875c7b7186 ]
One-element arrays are deprecated, and we are replacing them with flexible
array members instead. So, replace one-element arrays with flexible-array
members in multiple structs in fs/ksmbd/smb_common.h and one in
fs/ksmbd/smb2pdu.h.
Important to mention is that doing a build before/after this patch results
in no binary output differences.
This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines
on memcpy() and help us make progress towards globally enabling
-fstrict-flex-arrays=3 [1].
Link: https://github.com/KSPP/linux/issues/242
Link: https://github.com/KSPP/linux/issues/79
Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/Y3OxronfaPYv9qGP@work
---
fs/ksmbd/smb2pdu.c | 4 ++--
fs/ksmbd/smb2pdu.h | 2 +-
fs/ksmbd/smb_common.h | 12 ++++++------
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 8151f7782329..5868dcbb8062 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3486,7 +3486,7 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
goto free_conv_name;
}
- struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len;
+ struct_sz = readdir_info_level_struct_sz(info_level) + conv_len;
next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
d_info->last_entry_off_align = next_entry_offset - struct_sz;
@@ -3737,7 +3737,7 @@ static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
return -EOPNOTSUPP;
conv_len = (d_info->name_len + 1) * 2;
- next_entry_offset = ALIGN(struct_sz - 1 + conv_len,
+ next_entry_offset = ALIGN(struct_sz + conv_len,
KSMBD_DIR_INFO_ALIGNMENT);
if (next_entry_offset > d_info->out_buf_len) {
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index e20d4d707f1b..77d226fee060 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -1621,7 +1621,7 @@ struct smb2_posix_info {
/* SidBuffer contain two sids (UNIX user sid(16), UNIX group sid(16)) */
u8 SidBuffer[32];
__le32 name_len;
- u8 name[1];
+ u8 name[];
/*
* var sized owner SID
* var sized group SID
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
index ceb3cacaef1b..1ea1f746fa42 100644
--- a/fs/ksmbd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -310,14 +310,14 @@ struct file_directory_info {
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
- char FileName[1];
+ char FileName[];
} __packed; /* level 0x101 FF resp data */
struct file_names_info {
__le32 NextEntryOffset;
__u32 FileIndex;
__le32 FileNameLength;
- char FileName[1];
+ char FileName[];
} __packed; /* level 0xc FF resp data */
struct file_full_directory_info {
@@ -332,7 +332,7 @@ struct file_full_directory_info {
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize;
- char FileName[1];
+ char FileName[];
} __packed; /* level 0x102 FF resp */
struct file_both_directory_info {
@@ -350,7 +350,7 @@ struct file_both_directory_info {
__u8 ShortNameLength;
__u8 Reserved;
__u8 ShortName[24];
- char FileName[1];
+ char FileName[];
} __packed; /* level 0x104 FFrsp data */
struct file_id_both_directory_info {
@@ -370,7 +370,7 @@ struct file_id_both_directory_info {
__u8 ShortName[24];
__le16 Reserved2;
__le64 UniqueId;
- char FileName[1];
+ char FileName[];
} __packed;
struct file_id_full_dir_info {
@@ -387,7 +387,7 @@ struct file_id_full_dir_info {
__le32 EaSize; /* EA size */
__le32 Reserved;
__le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
- char FileName[1];
+ char FileName[];
} __packed; /* level 0x105 FF rsp data */
struct smb_version_values {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 065/154] ksmbd: set SMB2_SESSION_FLAG_ENCRYPT_DATA when enforcing data encryption for this share
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (63 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 064/154] ksmbd: replace one-element arrays with flexible-array members Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 066/154] ksmbd: use F_SETLK when unlocking a file Namjae Jeon
` (89 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 37ba7b005a7a4454046bd8659c7a9c5330552396 ]
Currently, SMB2_SESSION_FLAG_ENCRYPT_DATA is always set session setup
response. Since this forces data encryption from the client, there is a
problem that data is always encrypted regardless of the use of the cifs
seal mount option. SMB2_SESSION_FLAG_ENCRYPT_DATA should be set according
to KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION flags, and in case of
KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF, encryption mode is turned off for
all connections.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_netlink.h | 1 +
fs/ksmbd/smb2ops.c | 10 ++++++++--
fs/ksmbd/smb2pdu.c | 8 +++++---
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
index dd760c78af7b..fb9626383f86 100644
--- a/fs/ksmbd/ksmbd_netlink.h
+++ b/fs/ksmbd/ksmbd_netlink.h
@@ -74,6 +74,7 @@ struct ksmbd_heartbeat {
#define KSMBD_GLOBAL_FLAG_SMB2_LEASES BIT(0)
#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(1)
#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(2)
+#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF BIT(3)
/*
* IPC request for ksmbd server startup
diff --git a/fs/ksmbd/smb2ops.c b/fs/ksmbd/smb2ops.c
index f0a5b704f301..9138e1c29b22 100644
--- a/fs/ksmbd/smb2ops.c
+++ b/fs/ksmbd/smb2ops.c
@@ -248,8 +248,9 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
- conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
+ (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
+ conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
@@ -272,6 +273,11 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
+ (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
+ conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 5868dcbb8062..a40c737ae280 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -934,7 +934,7 @@ static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
return;
}
- if (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION))
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF)
return;
for (i = 0; i < cph_cnt; i++) {
@@ -1538,7 +1538,8 @@ static int ntlm_authenticate(struct ksmbd_work *work)
return -EINVAL;
}
sess->enc = true;
- rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
+ rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
/*
* signing is disable if encryption is enable
* on this session
@@ -1629,7 +1630,8 @@ static int krb5_authenticate(struct ksmbd_work *work)
return -EINVAL;
}
sess->enc = true;
- rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
+ rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
sess->sign = false;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 066/154] ksmbd: use F_SETLK when unlocking a file
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (64 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 065/154] ksmbd: set SMB2_SESSION_FLAG_ENCRYPT_DATA when enforcing data encryption for this share Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 067/154] ksmbd: Fix resource leak in smb2_lock() Namjae Jeon
` (88 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Jeff Layton, David Howells, Namjae Jeon, Steve French
From: Jeff Layton <jlayton@kernel.org>
[ Upstream commit 7ecbe92696bb7fe32c80b6cf64736a0d157717a9 ]
ksmbd seems to be trying to use a cmd value of 0 when unlocking a file.
That activity requires a type of F_UNLCK with a cmd of F_SETLK. For
local POSIX locking, it doesn't matter much since vfs_lock_file ignores
@cmd, but filesystems that define their own ->lock operation expect to
see it set sanely.
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: David Howells <dhowells@redhat.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index a40c737ae280..08d416beb88e 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6803,7 +6803,7 @@ static int smb2_set_flock_flags(struct file_lock *flock, int flags)
case SMB2_LOCKFLAG_UNLOCK:
ksmbd_debug(SMB, "received unlock request\n");
flock->fl_type = F_UNLCK;
- cmd = 0;
+ cmd = F_SETLK;
break;
}
@@ -7181,7 +7181,7 @@ int smb2_lock(struct ksmbd_work *work)
rlock->fl_start = smb_lock->start;
rlock->fl_end = smb_lock->end;
- rc = vfs_lock_file(filp, 0, rlock, NULL);
+ rc = vfs_lock_file(filp, F_SETLK, rlock, NULL);
if (rc)
pr_err("rollback unlock fail : %d\n", rc);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 067/154] ksmbd: Fix resource leak in smb2_lock()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (65 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 066/154] ksmbd: use F_SETLK when unlocking a file Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 068/154] ksmbd: Convert to use sysfs_emit()/sysfs_emit_at() APIs Namjae Jeon
` (87 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Marios Makassikis, Namjae Jeon, Steve French
From: Marios Makassikis <mmakassikis@freebox.fr>
[ Upstream commit 01f6c61bae3d658058ee6322af77acea26a5ee3a ]
"flock" is leaked if an error happens before smb2_lock_init(), as the
lock is not added to the lock_list to be cleaned up.
Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 08d416beb88e..c29c22490f8d 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6907,6 +6907,7 @@ int smb2_lock(struct ksmbd_work *work)
if (lock_start > U64_MAX - lock_length) {
pr_err("Invalid lock range requested\n");
rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
+ locks_free_lock(flock);
goto out;
}
@@ -6926,6 +6927,7 @@ int smb2_lock(struct ksmbd_work *work)
"the end offset(%llx) is smaller than the start offset(%llx)\n",
flock->fl_end, flock->fl_start);
rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
+ locks_free_lock(flock);
goto out;
}
@@ -6937,6 +6939,7 @@ int smb2_lock(struct ksmbd_work *work)
flock->fl_type != F_UNLCK) {
pr_err("conflict two locks in one request\n");
err = -EINVAL;
+ locks_free_lock(flock);
goto out;
}
}
@@ -6945,6 +6948,7 @@ int smb2_lock(struct ksmbd_work *work)
smb_lock = smb2_lock_init(flock, cmd, flags, &lock_list);
if (!smb_lock) {
err = -EINVAL;
+ locks_free_lock(flock);
goto out;
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 068/154] ksmbd: Convert to use sysfs_emit()/sysfs_emit_at() APIs
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (66 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 067/154] ksmbd: Fix resource leak in smb2_lock() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 069/154] ksmbd: send proper error response in smb2_tree_connect() Namjae Jeon
` (86 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, ye xingchen, Sergey Senozhatsky, Namjae Jeon,
Steve French
From: ye xingchen <ye.xingchen@zte.com.cn>
[ Upstream commit 72ee45fd46d0d3578c4e6046f66fae3218543ce3 ]
Follow the advice of the Documentation/filesystems/sysfs.rst and show()
should only use sysfs_emit() or sysfs_emit_at() when formatting the
value to be returned to user space.
Signed-off-by: ye xingchen <ye.xingchen@zte.com.cn>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/server.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index 1d5e46d71070..b9f11ef91ee4 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -439,11 +439,9 @@ static ssize_t stats_show(struct class *class, struct class_attribute *attr,
"reset",
"shutdown"
};
-
- ssize_t sz = scnprintf(buf, PAGE_SIZE, "%d %s %d %lu\n", stats_version,
- state[server_conf.state], server_conf.tcp_port,
- server_conf.ipc_last_active / HZ);
- return sz;
+ return sysfs_emit(buf, "%d %s %d %lu\n", stats_version,
+ state[server_conf.state], server_conf.tcp_port,
+ server_conf.ipc_last_active / HZ);
}
static ssize_t kill_server_store(struct class *class,
@@ -475,19 +473,13 @@ static ssize_t debug_show(struct class *class, struct class_attribute *attr,
for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
if ((ksmbd_debug_types >> i) & 1) {
- pos = scnprintf(buf + sz,
- PAGE_SIZE - sz,
- "[%s] ",
- debug_type_strings[i]);
+ pos = sysfs_emit_at(buf, sz, "[%s] ", debug_type_strings[i]);
} else {
- pos = scnprintf(buf + sz,
- PAGE_SIZE - sz,
- "%s ",
- debug_type_strings[i]);
+ pos = sysfs_emit_at(buf, sz, "%s ", debug_type_strings[i]);
}
sz += pos;
}
- sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
+ sz += sysfs_emit_at(buf, sz, "\n");
return sz;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 069/154] ksmbd: send proper error response in smb2_tree_connect()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (67 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 068/154] ksmbd: Convert to use sysfs_emit()/sysfs_emit_at() APIs Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 070/154] ksmbd: Implements sess->ksmbd_chann_list as xarray Namjae Jeon
` (85 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Marios Makassikis, Namjae Jeon, Steve French
From: Marios Makassikis <mmakassikis@freebox.fr>
[ Upstream commit cdfb2fef522d0c3f9cf293db51de88e9b3d46846 ]
Currently, smb2_tree_connect doesn't send an error response packet on
error.
This causes libsmb2 to skip the specific error code and fail with the
following:
smb2_service failed with : Failed to parse fixed part of command
payload. Unexpected size of Error reply. Expected 9, got 8
Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index c29c22490f8d..14619b074bc3 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1969,13 +1969,13 @@ int smb2_tree_connect(struct ksmbd_work *work)
if (conn->posix_ext_supported)
status.tree_conn->posix_extensions = true;
-out_err1:
rsp->StructureSize = cpu_to_le16(16);
+ inc_rfc1001_len(work->response_buf, 16);
+out_err1:
rsp->Capabilities = 0;
rsp->Reserved = 0;
/* default manual caching */
rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
- inc_rfc1001_len(work->response_buf, 16);
if (!IS_ERR(treename))
kfree(treename);
@@ -2008,6 +2008,9 @@ int smb2_tree_connect(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_ACCESS_DENIED;
}
+ if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
+ smb2_set_err_rsp(work);
+
return rc;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 070/154] ksmbd: Implements sess->ksmbd_chann_list as xarray
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (68 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 069/154] ksmbd: send proper error response in smb2_tree_connect() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 071/154] ksmbd: Implements sess->rpc_handle_list " Namjae Jeon
` (84 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Dawei Li, Namjae Jeon, Steve French
From: Dawei Li <set_pte_at@outlook.com>
[ Upstream commit 1d9c4172110e645b383ff13eee759728d74f1a5d ]
For some ops on channel:
1. lookup_chann_list(), possibly on high frequency.
2. ksmbd_chann_del().
Connection is used as indexing key to lookup channel, in that case,
linear search based on list may suffer a bit for performance.
Implements sess->ksmbd_chann_list as xarray.
Signed-off-by: Dawei Li <set_pte_at@outlook.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/user_session.c | 61 ++++++++++++++----------------------
fs/ksmbd/mgmt/user_session.h | 4 +--
fs/ksmbd/smb2pdu.c | 34 +++-----------------
3 files changed, 30 insertions(+), 69 deletions(-)
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index 92b1603b5abe..a2b128dedcfc 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -30,15 +30,15 @@ struct ksmbd_session_rpc {
static void free_channel_list(struct ksmbd_session *sess)
{
- struct channel *chann, *tmp;
+ struct channel *chann;
+ unsigned long index;
- write_lock(&sess->chann_lock);
- list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
- chann_list) {
- list_del(&chann->chann_list);
+ xa_for_each(&sess->ksmbd_chann_list, index, chann) {
+ xa_erase(&sess->ksmbd_chann_list, index);
kfree(chann);
}
- write_unlock(&sess->chann_lock);
+
+ xa_destroy(&sess->ksmbd_chann_list);
}
static void __session_rpc_close(struct ksmbd_session *sess,
@@ -190,21 +190,15 @@ int ksmbd_session_register(struct ksmbd_conn *conn,
static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
{
- struct channel *chann, *tmp;
-
- write_lock(&sess->chann_lock);
- list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
- chann_list) {
- if (chann->conn == conn) {
- list_del(&chann->chann_list);
- kfree(chann);
- write_unlock(&sess->chann_lock);
- return 0;
- }
- }
- write_unlock(&sess->chann_lock);
+ struct channel *chann;
+
+ chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
+ if (!chann)
+ return -ENOENT;
- return -ENOENT;
+ kfree(chann);
+
+ return 0;
}
void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
@@ -234,7 +228,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
return;
sess_destroy:
- if (list_empty(&sess->ksmbd_chann_list)) {
+ if (xa_empty(&sess->ksmbd_chann_list)) {
xa_erase(&conn->sessions, sess->id);
ksmbd_session_destroy(sess);
}
@@ -320,6 +314,9 @@ static struct ksmbd_session *__session_create(int protocol)
struct ksmbd_session *sess;
int ret;
+ if (protocol != CIFDS_SESSION_FLAG_SMB2)
+ return NULL;
+
sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL);
if (!sess)
return NULL;
@@ -329,30 +326,20 @@ static struct ksmbd_session *__session_create(int protocol)
set_session_flag(sess, protocol);
xa_init(&sess->tree_conns);
- INIT_LIST_HEAD(&sess->ksmbd_chann_list);
+ xa_init(&sess->ksmbd_chann_list);
INIT_LIST_HEAD(&sess->rpc_handle_list);
sess->sequence_number = 1;
- rwlock_init(&sess->chann_lock);
-
- switch (protocol) {
- case CIFDS_SESSION_FLAG_SMB2:
- ret = __init_smb2_session(sess);
- break;
- default:
- ret = -EINVAL;
- break;
- }
+ ret = __init_smb2_session(sess);
if (ret)
goto error;
ida_init(&sess->tree_conn_ida);
- if (protocol == CIFDS_SESSION_FLAG_SMB2) {
- down_write(&sessions_table_lock);
- hash_add(sessions_table, &sess->hlist, sess->id);
- up_write(&sessions_table_lock);
- }
+ down_write(&sessions_table_lock);
+ hash_add(sessions_table, &sess->hlist, sess->id);
+ up_write(&sessions_table_lock);
+
return sess;
error:
diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h
index 8934b8ee275b..44a3c67b2bd9 100644
--- a/fs/ksmbd/mgmt/user_session.h
+++ b/fs/ksmbd/mgmt/user_session.h
@@ -21,7 +21,6 @@ struct ksmbd_file_table;
struct channel {
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
struct ksmbd_conn *conn;
- struct list_head chann_list;
};
struct preauth_session {
@@ -50,8 +49,7 @@ struct ksmbd_session {
char sess_key[CIFS_KEY_SIZE];
struct hlist_node hlist;
- rwlock_t chann_lock;
- struct list_head ksmbd_chann_list;
+ struct xarray ksmbd_chann_list;
struct xarray tree_conns;
struct ida tree_conn_ida;
struct list_head rpc_handle_list;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 14619b074bc3..8c0872074d1b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -75,14 +75,7 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn)
{
- struct channel *chann;
-
- list_for_each_entry(chann, &sess->ksmbd_chann_list, chann_list) {
- if (chann->conn == conn)
- return chann;
- }
-
- return NULL;
+ return xa_load(&sess->ksmbd_chann_list, (long)conn);
}
/**
@@ -626,6 +619,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id);
struct ksmbd_user *prev_user;
struct channel *chann;
+ long index;
if (!prev_sess)
return;
@@ -639,10 +633,8 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
return;
prev_sess->state = SMB2_SESSION_EXPIRED;
- write_lock(&prev_sess->chann_lock);
- list_for_each_entry(chann, &prev_sess->ksmbd_chann_list, chann_list)
+ xa_for_each(&prev_sess->ksmbd_chann_list, index, chann)
chann->conn->status = KSMBD_SESS_EXITING;
- write_unlock(&prev_sess->chann_lock);
}
/**
@@ -1549,19 +1541,14 @@ static int ntlm_authenticate(struct ksmbd_work *work)
binding_session:
if (conn->dialect >= SMB30_PROT_ID) {
- read_lock(&sess->chann_lock);
chann = lookup_chann_list(sess, conn);
- read_unlock(&sess->chann_lock);
if (!chann) {
chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
if (!chann)
return -ENOMEM;
chann->conn = conn;
- INIT_LIST_HEAD(&chann->chann_list);
- write_lock(&sess->chann_lock);
- list_add(&chann->chann_list, &sess->ksmbd_chann_list);
- write_unlock(&sess->chann_lock);
+ xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
}
}
@@ -1636,19 +1623,14 @@ static int krb5_authenticate(struct ksmbd_work *work)
}
if (conn->dialect >= SMB30_PROT_ID) {
- read_lock(&sess->chann_lock);
chann = lookup_chann_list(sess, conn);
- read_unlock(&sess->chann_lock);
if (!chann) {
chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
if (!chann)
return -ENOMEM;
chann->conn = conn;
- INIT_LIST_HEAD(&chann->chann_list);
- write_lock(&sess->chann_lock);
- list_add(&chann->chann_list, &sess->ksmbd_chann_list);
- write_unlock(&sess->chann_lock);
+ xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
}
}
@@ -8462,14 +8444,11 @@ int smb3_check_sign_req(struct ksmbd_work *work)
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
signing_key = work->sess->smb3signingkey;
} else {
- read_lock(&work->sess->chann_lock);
chann = lookup_chann_list(work->sess, conn);
if (!chann) {
- read_unlock(&work->sess->chann_lock);
return 0;
}
signing_key = chann->smb3signingkey;
- read_unlock(&work->sess->chann_lock);
}
if (!signing_key) {
@@ -8529,14 +8508,11 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
signing_key = work->sess->smb3signingkey;
} else {
- read_lock(&work->sess->chann_lock);
chann = lookup_chann_list(work->sess, work->conn);
if (!chann) {
- read_unlock(&work->sess->chann_lock);
return;
}
signing_key = chann->smb3signingkey;
- read_unlock(&work->sess->chann_lock);
}
if (!signing_key)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 071/154] ksmbd: Implements sess->rpc_handle_list as xarray
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (69 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 070/154] ksmbd: Implements sess->ksmbd_chann_list as xarray Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 072/154] ksmbd: fix typo, syncronous->synchronous Namjae Jeon
` (83 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Dawei Li, Namjae Jeon, Steve French
From: Dawei Li <set_pte_at@outlook.com>
[ Upstream commit b685757c7b08d5073046fb379be965fd6c06aafc ]
For some ops on rpc handle:
1. ksmbd_session_rpc_method(), possibly on high frequency.
2. ksmbd_session_rpc_close().
id is used as indexing key to lookup channel, in that case,
linear search based on list may suffer a bit for performance.
Implements sess->rpc_handle_list as xarray.
Signed-off-by: Dawei Li <set_pte_at@outlook.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/user_session.c | 37 ++++++++++++++----------------------
fs/ksmbd/mgmt/user_session.h | 2 +-
2 files changed, 15 insertions(+), 24 deletions(-)
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index a2b128dedcfc..1ca2aae4c299 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -25,7 +25,6 @@ static DECLARE_RWSEM(sessions_table_lock);
struct ksmbd_session_rpc {
int id;
unsigned int method;
- struct list_head list;
};
static void free_channel_list(struct ksmbd_session *sess)
@@ -58,15 +57,14 @@ static void __session_rpc_close(struct ksmbd_session *sess,
static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
{
struct ksmbd_session_rpc *entry;
+ long index;
- while (!list_empty(&sess->rpc_handle_list)) {
- entry = list_entry(sess->rpc_handle_list.next,
- struct ksmbd_session_rpc,
- list);
-
- list_del(&entry->list);
+ xa_for_each(&sess->rpc_handle_list, index, entry) {
+ xa_erase(&sess->rpc_handle_list, index);
__session_rpc_close(sess, entry);
}
+
+ xa_destroy(&sess->rpc_handle_list);
}
static int __rpc_method(char *rpc_name)
@@ -102,13 +100,13 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL);
if (!entry)
- return -EINVAL;
+ return -ENOMEM;
- list_add(&entry->list, &sess->rpc_handle_list);
entry->method = method;
entry->id = ksmbd_ipc_id_alloc();
if (entry->id < 0)
goto free_entry;
+ xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL);
resp = ksmbd_rpc_open(sess, entry->id);
if (!resp)
@@ -117,9 +115,9 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
kvfree(resp);
return entry->id;
free_id:
+ xa_erase(&sess->rpc_handle_list, entry->id);
ksmbd_rpc_id_free(entry->id);
free_entry:
- list_del(&entry->list);
kfree(entry);
return -EINVAL;
}
@@ -128,24 +126,17 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
{
struct ksmbd_session_rpc *entry;
- list_for_each_entry(entry, &sess->rpc_handle_list, list) {
- if (entry->id == id) {
- list_del(&entry->list);
- __session_rpc_close(sess, entry);
- break;
- }
- }
+ entry = xa_erase(&sess->rpc_handle_list, id);
+ if (entry)
+ __session_rpc_close(sess, entry);
}
int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
{
struct ksmbd_session_rpc *entry;
- list_for_each_entry(entry, &sess->rpc_handle_list, list) {
- if (entry->id == id)
- return entry->method;
- }
- return 0;
+ entry = xa_load(&sess->rpc_handle_list, id);
+ return entry ? entry->method : 0;
}
void ksmbd_session_destroy(struct ksmbd_session *sess)
@@ -327,7 +318,7 @@ static struct ksmbd_session *__session_create(int protocol)
set_session_flag(sess, protocol);
xa_init(&sess->tree_conns);
xa_init(&sess->ksmbd_chann_list);
- INIT_LIST_HEAD(&sess->rpc_handle_list);
+ xa_init(&sess->rpc_handle_list);
sess->sequence_number = 1;
ret = __init_smb2_session(sess);
diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h
index 44a3c67b2bd9..b6a9e7a6aae4 100644
--- a/fs/ksmbd/mgmt/user_session.h
+++ b/fs/ksmbd/mgmt/user_session.h
@@ -52,7 +52,7 @@ struct ksmbd_session {
struct xarray ksmbd_chann_list;
struct xarray tree_conns;
struct ida tree_conn_ida;
- struct list_head rpc_handle_list;
+ struct xarray rpc_handle_list;
__u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
__u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 072/154] ksmbd: fix typo, syncronous->synchronous
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (70 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 071/154] ksmbd: Implements sess->rpc_handle_list " Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 073/154] ksmbd: Remove duplicated codes Namjae Jeon
` (82 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Dawei Li, Namjae Jeon, Sergey Senozhatsky, Steve French
From: Dawei Li <set_pte_at@outlook.com>
[ Upstream commit f8d6e7442aa716a233c7eba99dec628f8885e00b ]
syncronous->synchronous
Signed-off-by: Dawei Li <set_pte_at@outlook.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 4 ++--
fs/ksmbd/ksmbd_work.h | 2 +-
fs/ksmbd/smb2pdu.c | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 14326323da79..9ed669d58742 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -114,7 +114,7 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
requests_queue = &conn->requests;
- work->syncronous = true;
+ work->synchronous = true;
}
if (requests_queue) {
@@ -139,7 +139,7 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
spin_lock(&conn->request_lock);
if (!work->multiRsp) {
list_del_init(&work->request_entry);
- if (work->syncronous == false)
+ if (!work->synchronous)
list_del_init(&work->async_request_entry);
ret = 0;
}
diff --git a/fs/ksmbd/ksmbd_work.h b/fs/ksmbd/ksmbd_work.h
index 5ece58e40c97..3234f2cf6327 100644
--- a/fs/ksmbd/ksmbd_work.h
+++ b/fs/ksmbd/ksmbd_work.h
@@ -68,7 +68,7 @@ struct ksmbd_work {
/* Request is encrypted */
bool encrypted:1;
/* Is this SYNC or ASYNC ksmbd_work */
- bool syncronous:1;
+ bool synchronous:1;
bool need_invalidate_rkey:1;
unsigned int remote_key;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 8c0872074d1b..294de8d5e19c 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -512,7 +512,7 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
rsp_hdr->SessionId = rcv_hdr->SessionId;
memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
- work->syncronous = true;
+ work->synchronous = true;
if (work->async_id) {
ksmbd_release_id(&conn->async_ida, work->async_id);
work->async_id = 0;
@@ -675,7 +675,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
pr_err("Failed to alloc async message id\n");
return id;
}
- work->syncronous = false;
+ work->synchronous = false;
work->async_id = id;
rsp_hdr->Id.AsyncId = cpu_to_le64(id);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 073/154] ksmbd: Remove duplicated codes
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (71 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 072/154] ksmbd: fix typo, syncronous->synchronous Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 074/154] ksmbd: update Kconfig to note Kerberos support and fix indentation Namjae Jeon
` (81 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Dawei Li, Namjae Jeon, Steve French
From: Dawei Li <set_pte_at@outlook.com>
[ Upstream commit 7010357004096e54c884813e702d71147dc081f8 ]
ksmbd_neg_token_init_mech_token() and ksmbd_neg_token_targ_resp_token()
share same implementation, unify them.
Signed-off-by: Dawei Li <set_pte_at@outlook.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/asn1.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c
index c03eba090368..cc6384f79675 100644
--- a/fs/ksmbd/asn1.c
+++ b/fs/ksmbd/asn1.c
@@ -208,9 +208,9 @@ int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
return 0;
}
-int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
- unsigned char tag, const void *value,
- size_t vlen)
+static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
+ unsigned char tag, const void *value,
+ size_t vlen)
{
struct ksmbd_conn *conn = context;
@@ -223,17 +223,16 @@ int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
return 0;
}
-int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
+int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
unsigned char tag, const void *value,
size_t vlen)
{
- struct ksmbd_conn *conn = context;
-
- conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
- if (!conn->mechToken)
- return -ENOMEM;
+ return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
+}
- memcpy(conn->mechToken, value, vlen);
- conn->mechToken[vlen] = '\0';
- return 0;
+int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
+ unsigned char tag, const void *value,
+ size_t vlen)
+{
+ return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 074/154] ksmbd: update Kconfig to note Kerberos support and fix indentation
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (72 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 073/154] ksmbd: Remove duplicated codes Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 075/154] ksmbd: Fix spelling mistake "excceed" -> "exceeded" Namjae Jeon
` (80 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Steve French, Namjae Jeon, David Howells
From: Steve French <stfrench@microsoft.com>
[ Upstream commit d280a958f8b2b62610c280ecdf35d780e7922620 ]
Fix indentation of server config options, and also since
support for very old, less secure, NTLM authentication was removed
(and quite a while ago), remove the mention of that in Kconfig, but
do note Kerberos (not just NTLMv2) which are supported and much
more secure.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/Kconfig | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/Kconfig b/fs/ksmbd/Kconfig
index e1fe17747ed6..7055cb5d2880 100644
--- a/fs/ksmbd/Kconfig
+++ b/fs/ksmbd/Kconfig
@@ -33,14 +33,16 @@ config SMB_SERVER
in ksmbd-tools, available from
https://github.com/cifsd-team/ksmbd-tools.
More detail about how to run the ksmbd kernel server is
- available via README file
+ available via the README file
(https://github.com/cifsd-team/ksmbd-tools/blob/master/README).
ksmbd kernel server includes support for auto-negotiation,
Secure negotiate, Pre-authentication integrity, oplock/lease,
compound requests, multi-credit, packet signing, RDMA(smbdirect),
smb3 encryption, copy-offload, secure per-user session
- establishment via NTLM or NTLMv2.
+ establishment via Kerberos or NTLMv2.
+
+if SMB_SERVER
config SMB_SERVER_SMBDIRECT
bool "Support for SMB Direct protocol"
@@ -54,6 +56,8 @@ config SMB_SERVER_SMBDIRECT
SMB Direct allows transferring SMB packets over RDMA. If unsure,
say N.
+endif
+
config SMB_SERVER_CHECK_CAP_NET_ADMIN
bool "Enable check network administration capability"
depends on SMB_SERVER
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 075/154] ksmbd: Fix spelling mistake "excceed" -> "exceeded"
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (73 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 074/154] ksmbd: update Kconfig to note Kerberos support and fix indentation Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 076/154] ksmbd: Fix parameter name and comment mismatch Namjae Jeon
` (79 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Colin Ian King, Namjae Jeon, Steve French
From: Colin Ian King <colin.i.king@gmail.com>
[ Upstream commit 7a17c61ee3b2683c40090179c273f4701fca9677 ]
There is a spelling mistake in an error message. Fix it.
Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 9ed669d58742..ccb978f48e41 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -312,7 +312,7 @@ int ksmbd_conn_handler_loop(void *p)
max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
if (pdu_size > max_allowed_pdu_size) {
- pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n",
+ pr_err_ratelimited("PDU length(%u) exceeded maximum allowed pdu size(%u) on connection(%d)\n",
pdu_size, max_allowed_pdu_size,
conn->status);
break;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 076/154] ksmbd: Fix parameter name and comment mismatch
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (74 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 075/154] ksmbd: Fix spelling mistake "excceed" -> "exceeded" Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 077/154] ksmbd: fix possible memory leak in smb2_lock() Namjae Jeon
` (78 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Jiapeng Chong, Abaci Robot, Namjae Jeon,
Sergey Senozhatsky, Steve French
From: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
[ Upstream commit 63f09a9986eb58578ed6ad0e27a6e2c54e49f797 ]
fs/ksmbd/vfs.c:965: warning: Function parameter or member 'attr_value' not described in 'ksmbd_vfs_setxattr'.
Reported-by: Abaci Robot <abaci@linux.alibaba.com>
Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=3946
Signed-off-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index d7814397764c..90f657f3b48f 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -950,9 +950,9 @@ ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
* ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
* @user_ns: user namespace
* @dentry: dentry to set XATTR at
- * @name: xattr name for setxattr
- * @value: xattr value to set
- * @size: size of xattr value
+ * @attr_name: xattr name for setxattr
+ * @attr_value: xattr value to set
+ * @attr_size: size of xattr value
* @flags: destination buffer length
*
* Return: 0 on success, otherwise error
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 077/154] ksmbd: fix possible memory leak in smb2_lock()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (75 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 076/154] ksmbd: Fix parameter name and comment mismatch Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 078/154] ksmbd: fix wrong signingkey creation when encryption is AES256 Namjae Jeon
` (77 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Hangyu Hua, Namjae Jeon, Steve French
From: Hangyu Hua <hbh25y@gmail.com>
[ Upstream commit d3ca9f7aeba793d74361d88a8800b2f205c9236b ]
argv needs to be free when setup_async_work fails or when the current
process is woken up.
Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 28 +++++++++++++---------------
fs/ksmbd/vfs_cache.c | 5 ++---
2 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 294de8d5e19c..f7b9480e2268 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6676,7 +6676,7 @@ int smb2_cancel(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
struct smb2_hdr *chdr;
- struct ksmbd_work *cancel_work = NULL, *iter;
+ struct ksmbd_work *iter;
struct list_head *command_list;
ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
@@ -6698,7 +6698,9 @@ int smb2_cancel(struct ksmbd_work *work)
"smb2 with AsyncId %llu cancelled command = 0x%x\n",
le64_to_cpu(hdr->Id.AsyncId),
le16_to_cpu(chdr->Command));
- cancel_work = iter;
+ iter->state = KSMBD_WORK_CANCELLED;
+ if (iter->cancel_fn)
+ iter->cancel_fn(iter->cancel_argv);
break;
}
spin_unlock(&conn->request_lock);
@@ -6717,18 +6719,12 @@ int smb2_cancel(struct ksmbd_work *work)
"smb2 with mid %llu cancelled command = 0x%x\n",
le64_to_cpu(hdr->MessageId),
le16_to_cpu(chdr->Command));
- cancel_work = iter;
+ iter->state = KSMBD_WORK_CANCELLED;
break;
}
spin_unlock(&conn->request_lock);
}
- if (cancel_work) {
- cancel_work->state = KSMBD_WORK_CANCELLED;
- if (cancel_work->cancel_fn)
- cancel_work->cancel_fn(cancel_work->cancel_argv);
- }
-
/* For SMB2_CANCEL command itself send no response*/
work->send_no_response = 1;
return 0;
@@ -7093,6 +7089,14 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_vfs_posix_lock_wait(flock);
+ spin_lock(&work->conn->request_lock);
+ spin_lock(&fp->f_lock);
+ list_del(&work->fp_entry);
+ work->cancel_fn = NULL;
+ kfree(argv);
+ spin_unlock(&fp->f_lock);
+ spin_unlock(&work->conn->request_lock);
+
if (work->state != KSMBD_WORK_ACTIVE) {
list_del(&smb_lock->llist);
spin_lock(&work->conn->llist_lock);
@@ -7101,9 +7105,6 @@ int smb2_lock(struct ksmbd_work *work)
locks_free_lock(flock);
if (work->state == KSMBD_WORK_CANCELLED) {
- spin_lock(&fp->f_lock);
- list_del(&work->fp_entry);
- spin_unlock(&fp->f_lock);
rsp->hdr.Status =
STATUS_CANCELLED;
kfree(smb_lock);
@@ -7125,9 +7126,6 @@ int smb2_lock(struct ksmbd_work *work)
list_del(&smb_lock->clist);
spin_unlock(&work->conn->llist_lock);
- spin_lock(&fp->f_lock);
- list_del(&work->fp_entry);
- spin_unlock(&fp->f_lock);
goto retry;
} else if (!rc) {
spin_lock(&work->conn->llist_lock);
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index 52ae9937d6a1..6ec6c129465d 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -364,12 +364,11 @@ static void __put_fd_final(struct ksmbd_work *work, struct ksmbd_file *fp)
static void set_close_state_blocked_works(struct ksmbd_file *fp)
{
- struct ksmbd_work *cancel_work, *ctmp;
+ struct ksmbd_work *cancel_work;
spin_lock(&fp->f_lock);
- list_for_each_entry_safe(cancel_work, ctmp, &fp->blocked_works,
+ list_for_each_entry(cancel_work, &fp->blocked_works,
fp_entry) {
- list_del(&cancel_work->fp_entry);
cancel_work->state = KSMBD_WORK_CLOSED;
cancel_work->cancel_fn(cancel_work->cancel_argv);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 078/154] ksmbd: fix wrong signingkey creation when encryption is AES256
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (76 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 077/154] ksmbd: fix possible memory leak in smb2_lock() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 079/154] ksmbd: remove unused is_char_allowed function Namjae Jeon
` (76 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Miao Lihua, Steve French
[ Upstream commit 7a891d4b62d62566323676cb0e922ded4f37afe1 ]
MacOS and Win11 support AES256 encrytion and it is included in the cipher
array of encryption context. Especially on macOS, The most preferred
cipher is AES256. Connecting to ksmbd fails on newer MacOS clients that
support AES256 encryption. MacOS send disconnect request after receiving
final session setup response from ksmbd. Because final session setup is
signed with signing key was generated incorrectly.
For signging key, 'L' value should be initialized to 128 if key size is
16bytes.
Cc: stable@vger.kernel.org
Reported-by: Miao Lihua <441884205@qq.com>
Tested-by: Miao Lihua <441884205@qq.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index bad4c3af9540..df8fb076f6f1 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -730,8 +730,9 @@ static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
goto smb3signkey_ret;
}
- if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+ if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
+ (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
+ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
else
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 079/154] ksmbd: remove unused is_char_allowed function
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (77 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 078/154] ksmbd: fix wrong signingkey creation when encryption is AES256 Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 080/154] ksmbd: delete asynchronous work from list Namjae Jeon
` (75 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Tom Rix, Sergey Senozhatsky, Namjae Jeon, Steve French
From: Tom Rix <trix@redhat.com>
[ Upstream commit 2824861773eb512b37547516d81ef78108032cb2 ]
clang with W=1 reports
fs/ksmbd/unicode.c:122:19: error: unused function
'is_char_allowed' [-Werror,-Wunused-function]
static inline int is_char_allowed(char *ch)
^
This function is not used so remove it.
Signed-off-by: Tom Rix <trix@redhat.com>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/unicode.c | 18 ------------------
1 file changed, 18 deletions(-)
diff --git a/fs/ksmbd/unicode.c b/fs/ksmbd/unicode.c
index a0db699ddafd..9ae676906ed3 100644
--- a/fs/ksmbd/unicode.c
+++ b/fs/ksmbd/unicode.c
@@ -113,24 +113,6 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
goto out;
}
-/*
- * is_char_allowed() - check for valid character
- * @ch: input character to be checked
- *
- * Return: 1 if char is allowed, otherwise 0
- */
-static inline int is_char_allowed(char *ch)
-{
- /* check for control chars, wildcards etc. */
- if (!(*ch & 0x80) &&
- (*ch <= 0x1f ||
- *ch == '?' || *ch == '"' || *ch == '<' ||
- *ch == '>' || *ch == '|'))
- return 0;
-
- return 1;
-}
-
/*
* smb_from_utf16() - convert utf16le string to local charset
* @to: destination buffer
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 080/154] ksmbd: delete asynchronous work from list
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (78 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 079/154] ksmbd: remove unused is_char_allowed function Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 081/154] ksmbd: fix slab-out-of-bounds in init_smb2_rsp_hdr Namjae Jeon
` (74 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 3a9b557f44ea8f216aab515a7db20e23f0eb51b9 ]
When smb2_lock request is canceled by smb2_cancel or smb2_close(),
ksmbd is missing deleting async_request_entry async_requests list.
Because calling init_smb2_rsp_hdr() in smb2_lock() mark ->synchronous
as true and then it will not be deleted in
ksmbd_conn_try_dequeue_request(). This patch add release_async_work() to
release the ones allocated for async work.
Cc: stable@vger.kernel.org
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 12 +++++-------
fs/ksmbd/ksmbd_work.h | 2 +-
fs/ksmbd/smb2pdu.c | 33 +++++++++++++++++++++------------
fs/ksmbd/smb2pdu.h | 1 +
4 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index ccb978f48e41..54888f2819e6 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -112,10 +112,8 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
struct list_head *requests_queue = NULL;
- if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
+ if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE)
requests_queue = &conn->requests;
- work->synchronous = true;
- }
if (requests_queue) {
atomic_inc(&conn->req_running);
@@ -136,14 +134,14 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
if (!work->multiRsp)
atomic_dec(&conn->req_running);
- spin_lock(&conn->request_lock);
if (!work->multiRsp) {
+ spin_lock(&conn->request_lock);
list_del_init(&work->request_entry);
- if (!work->synchronous)
- list_del_init(&work->async_request_entry);
+ spin_unlock(&conn->request_lock);
+ if (work->asynchronous)
+ release_async_work(work);
ret = 0;
}
- spin_unlock(&conn->request_lock);
wake_up_all(&conn->req_running_q);
return ret;
diff --git a/fs/ksmbd/ksmbd_work.h b/fs/ksmbd/ksmbd_work.h
index 3234f2cf6327..f8ae6144c0ae 100644
--- a/fs/ksmbd/ksmbd_work.h
+++ b/fs/ksmbd/ksmbd_work.h
@@ -68,7 +68,7 @@ struct ksmbd_work {
/* Request is encrypted */
bool encrypted:1;
/* Is this SYNC or ASYNC ksmbd_work */
- bool synchronous:1;
+ bool asynchronous:1;
bool need_invalidate_rkey:1;
unsigned int remote_key;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index f7b9480e2268..ef68a3d8c9d5 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -512,12 +512,6 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
rsp_hdr->SessionId = rcv_hdr->SessionId;
memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
- work->synchronous = true;
- if (work->async_id) {
- ksmbd_release_id(&conn->async_ida, work->async_id);
- work->async_id = 0;
- }
-
return 0;
}
@@ -675,7 +669,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
pr_err("Failed to alloc async message id\n");
return id;
}
- work->synchronous = false;
+ work->asynchronous = true;
work->async_id = id;
rsp_hdr->Id.AsyncId = cpu_to_le64(id);
@@ -695,6 +689,24 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
return 0;
}
+void release_async_work(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+
+ spin_lock(&conn->request_lock);
+ list_del_init(&work->async_request_entry);
+ spin_unlock(&conn->request_lock);
+
+ work->asynchronous = 0;
+ work->cancel_fn = NULL;
+ kfree(work->cancel_argv);
+ work->cancel_argv = NULL;
+ if (work->async_id) {
+ ksmbd_release_id(&conn->async_ida, work->async_id);
+ work->async_id = 0;
+ }
+}
+
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
{
struct smb2_hdr *rsp_hdr;
@@ -7089,13 +7101,9 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_vfs_posix_lock_wait(flock);
- spin_lock(&work->conn->request_lock);
spin_lock(&fp->f_lock);
list_del(&work->fp_entry);
- work->cancel_fn = NULL;
- kfree(argv);
spin_unlock(&fp->f_lock);
- spin_unlock(&work->conn->request_lock);
if (work->state != KSMBD_WORK_ACTIVE) {
list_del(&smb_lock->llist);
@@ -7113,6 +7121,7 @@ int smb2_lock(struct ksmbd_work *work)
work->send_no_response = 1;
goto out;
}
+
init_smb2_rsp_hdr(work);
smb2_set_err_rsp(work);
rsp->hdr.Status =
@@ -7125,7 +7134,7 @@ int smb2_lock(struct ksmbd_work *work)
spin_lock(&work->conn->llist_lock);
list_del(&smb_lock->clist);
spin_unlock(&work->conn->llist_lock);
-
+ release_async_work(work);
goto retry;
} else if (!rc) {
spin_lock(&work->conn->llist_lock);
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index 77d226fee060..9cde1f8e8428 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -1663,6 +1663,7 @@ int find_matching_smb2_dialect(int start_index, __le16 *cli_dialects,
struct file_lock *smb_flock_init(struct file *f);
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
void **arg);
+void release_async_work(struct ksmbd_work *work);
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
struct channel *lookup_chann_list(struct ksmbd_session *sess,
struct ksmbd_conn *conn);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 081/154] ksmbd: fix slab-out-of-bounds in init_smb2_rsp_hdr
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (79 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 080/154] ksmbd: delete asynchronous work from list Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 082/154] ksmbd: avoid out of bounds access in decode_preauth_ctxt() Namjae Jeon
` (73 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit dc8289f912387c3bcfbc5d2db29c8947fa207c11 ]
When smb1 mount fails, KASAN detect slab-out-of-bounds in
init_smb2_rsp_hdr like the following one.
For smb1 negotiate(56bytes) , init_smb2_rsp_hdr() for smb2 is called.
The issue occurs while handling smb1 negotiate as smb2 server operations.
Add smb server operations for smb1 (get_cmd_val, init_rsp_hdr,
allocate_rsp_buf, check_user_session) to handle smb1 negotiate so that
smb2 server operation does not handle it.
[ 411.400423] CIFS: VFS: Use of the less secure dialect vers=1.0 is
not recommended unless required for access to very old servers
[ 411.400452] CIFS: Attempting to mount \\192.168.45.139\homes
[ 411.479312] ksmbd: init_smb2_rsp_hdr : 492
[ 411.479323] ==================================================================
[ 411.479327] BUG: KASAN: slab-out-of-bounds in
init_smb2_rsp_hdr+0x1e2/0x1f4 [ksmbd]
[ 411.479369] Read of size 16 at addr ffff888488ed0734 by task kworker/14:1/199
[ 411.479379] CPU: 14 PID: 199 Comm: kworker/14:1 Tainted: G
OE 6.1.21 #3
[ 411.479386] Hardware name: ASUSTeK COMPUTER INC. Z10PA-D8
Series/Z10PA-D8 Series, BIOS 3801 08/23/2019
[ 411.479390] Workqueue: ksmbd-io handle_ksmbd_work [ksmbd]
[ 411.479425] Call Trace:
[ 411.479428] <TASK>
[ 411.479432] dump_stack_lvl+0x49/0x63
[ 411.479444] print_report+0x171/0x4a8
[ 411.479452] ? kasan_complete_mode_report_info+0x3c/0x200
[ 411.479463] ? init_smb2_rsp_hdr+0x1e2/0x1f4 [ksmbd]
[ 411.479497] kasan_report+0xb4/0x130
[ 411.479503] ? init_smb2_rsp_hdr+0x1e2/0x1f4 [ksmbd]
[ 411.479537] kasan_check_range+0x149/0x1e0
[ 411.479543] memcpy+0x24/0x70
[ 411.479550] init_smb2_rsp_hdr+0x1e2/0x1f4 [ksmbd]
[ 411.479585] handle_ksmbd_work+0x109/0x760 [ksmbd]
[ 411.479616] ? _raw_spin_unlock_irqrestore+0x50/0x50
[ 411.479624] ? smb3_encrypt_resp+0x340/0x340 [ksmbd]
[ 411.479656] process_one_work+0x49c/0x790
[ 411.479667] worker_thread+0x2b1/0x6e0
[ 411.479674] ? process_one_work+0x790/0x790
[ 411.479680] kthread+0x177/0x1b0
[ 411.479686] ? kthread_complete_and_exit+0x30/0x30
[ 411.479692] ret_from_fork+0x22/0x30
[ 411.479702] </TASK>
Fixes: 39b291b86b59 ("ksmbd: return unsupported error on smb1 mount")
Cc: stable@vger.kernel.org
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/server.c | 5 +-
fs/ksmbd/smb2pdu.c | 3 -
fs/ksmbd/smb_common.c | 138 +++++++++++++++++++++++++++++++++---------
fs/ksmbd/smb_common.h | 2 +-
4 files changed, 111 insertions(+), 37 deletions(-)
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index b9f11ef91ee4..586f948976c8 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -296,10 +296,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
work->request_buf = conn->request_buf;
conn->request_buf = NULL;
- if (ksmbd_init_smb_server(work)) {
- ksmbd_free_work_struct(work);
- return -EINVAL;
- }
+ ksmbd_init_smb_server(work);
ksmbd_conn_enqueue_request(work);
atomic_inc(&conn->r_count);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index ef68a3d8c9d5..92fa2090ac54 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -246,9 +246,6 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
struct smb2_negotiate_rsp *rsp;
struct ksmbd_conn *conn = work->conn;
- if (conn->need_neg == false)
- return -EINVAL;
-
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index 4341d52c12f3..1c69811610dc 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -283,20 +283,121 @@ static int ksmbd_negotiate_smb_dialect(void *buf)
return BAD_PROT_ID;
}
-int ksmbd_init_smb_server(struct ksmbd_work *work)
+#define SMB_COM_NEGOTIATE_EX 0x0
+
+/**
+ * get_smb1_cmd_val() - get smb command value from smb header
+ * @work: smb work containing smb header
+ *
+ * Return: smb command value
+ */
+static u16 get_smb1_cmd_val(struct ksmbd_work *work)
{
- struct ksmbd_conn *conn = work->conn;
+ return SMB_COM_NEGOTIATE_EX;
+}
- if (conn->need_neg == false)
+/**
+ * init_smb1_rsp_hdr() - initialize smb negotiate response header
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+static int init_smb1_rsp_hdr(struct ksmbd_work *work)
+{
+ struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
+ struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
+
+ /*
+ * Remove 4 byte direct TCP header.
+ */
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(sizeof(struct smb_hdr) - 4);
+
+ rsp_hdr->Command = SMB_COM_NEGOTIATE;
+ *(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
+ rsp_hdr->Flags = SMBFLG_RESPONSE;
+ rsp_hdr->Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
+ SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
+ rsp_hdr->Pid = rcv_hdr->Pid;
+ rsp_hdr->Mid = rcv_hdr->Mid;
+ return 0;
+}
+
+/**
+ * smb1_check_user_session() - check for valid session for a user
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb1_check_user_session(struct ksmbd_work *work)
+{
+ unsigned int cmd = work->conn->ops->get_cmd_val(work);
+
+ if (cmd == SMB_COM_NEGOTIATE_EX)
return 0;
- init_smb3_11_server(conn);
+ return -EINVAL;
+}
+
+/**
+ * smb1_allocate_rsp_buf() - allocate response buffer for a command
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -ENOMEM
+ */
+static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
+{
+ work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
+ GFP_KERNEL | __GFP_ZERO);
+ work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+
+ if (!work->response_buf) {
+ pr_err("Failed to allocate %u bytes buffer\n",
+ MAX_CIFS_SMALL_BUFFER_SIZE);
+ return -ENOMEM;
+ }
- if (conn->ops->get_cmd_val(work) != SMB_COM_NEGOTIATE)
- conn->need_neg = false;
return 0;
}
+static struct smb_version_ops smb1_server_ops = {
+ .get_cmd_val = get_smb1_cmd_val,
+ .init_rsp_hdr = init_smb1_rsp_hdr,
+ .allocate_rsp_buf = smb1_allocate_rsp_buf,
+ .check_user_session = smb1_check_user_session,
+};
+
+static int smb1_negotiate(struct ksmbd_work *work)
+{
+ return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
+}
+
+static struct smb_version_cmds smb1_server_cmds[1] = {
+ [SMB_COM_NEGOTIATE_EX] = { .proc = smb1_negotiate, },
+};
+
+static void init_smb1_server(struct ksmbd_conn *conn)
+{
+ conn->ops = &smb1_server_ops;
+ conn->cmds = smb1_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+}
+
+void ksmbd_init_smb_server(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ __le32 proto;
+
+ if (conn->need_neg == false)
+ return;
+
+ proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+ if (proto == SMB1_PROTO_NUMBER)
+ init_smb1_server(conn);
+ else
+ init_smb3_11_server(conn);
+}
+
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
struct ksmbd_file *dir,
struct ksmbd_dir_info *d_info,
@@ -444,20 +545,10 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
- /*
- * Remove 4 byte direct TCP header, add 2 byte bcc and
- * 2 byte DialectIndex.
- */
- *(__be32 *)work->response_buf =
- cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2 + 2);
+ /* Add 2 byte bcc and 2 byte DialectIndex. */
+ inc_rfc1001_len(work->response_buf, 4);
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
- neg_rsp->hdr.Command = SMB_COM_NEGOTIATE;
- *(__le32 *)neg_rsp->hdr.Protocol = SMB1_PROTO_NUMBER;
- neg_rsp->hdr.Flags = SMBFLG_RESPONSE;
- neg_rsp->hdr.Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
- SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
-
neg_rsp->hdr.WordCount = 1;
neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
neg_rsp->ByteCount = 0;
@@ -473,24 +564,13 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
ksmbd_negotiate_smb_dialect(work->request_buf);
ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
- if (command == SMB2_NEGOTIATE_HE) {
- struct smb2_hdr *smb2_hdr = smb2_get_msg(work->request_buf);
-
- if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
- ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
- command = SMB_COM_NEGOTIATE;
- }
- }
-
if (command == SMB2_NEGOTIATE_HE) {
ret = smb2_handle_negotiate(work);
- init_smb2_neg_rsp(work);
return ret;
}
if (command == SMB_COM_NEGOTIATE) {
if (__smb2_negotiate(conn)) {
- conn->need_neg = true;
init_smb3_11_server(conn);
init_smb2_neg_rsp(work);
ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
index 1ea1f746fa42..e4a1eb6f8da3 100644
--- a/fs/ksmbd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -474,7 +474,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
-int ksmbd_init_smb_server(struct ksmbd_work *work);
+void ksmbd_init_smb_server(struct ksmbd_work *work);
struct ksmbd_kstat;
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 082/154] ksmbd: avoid out of bounds access in decode_preauth_ctxt()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (80 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 081/154] ksmbd: fix slab-out-of-bounds in init_smb2_rsp_hdr Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 083/154] ksmbd: set NegotiateContextCount once instead of every inc Namjae Jeon
` (72 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, David Disseldorp, Namjae Jeon, Steve French
From: David Disseldorp <ddiss@suse.de>
[ Upstream commit e7067a446264a7514fa1cfaa4052cdb6803bc6a2 ]
Confirm that the accessed pneg_ctxt->HashAlgorithms address sits within
the SMB request boundary; deassemble_neg_contexts() only checks that the
eight byte smb2_neg_context header + (client controlled) DataLength are
within the packet boundary, which is insufficient.
Checking for sizeof(struct smb2_preauth_neg_context) is overkill given
that the type currently assumes SMB311_SALT_SIZE bytes of trailing Salt.
Signed-off-by: David Disseldorp <ddiss@suse.de>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 92fa2090ac54..472aa5fa0d10 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -907,17 +907,21 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
}
static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
- struct smb2_preauth_neg_context *pneg_ctxt)
+ struct smb2_preauth_neg_context *pneg_ctxt,
+ int len_of_ctxts)
{
- __le32 err = STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP;
+ /*
+ * sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
+ * which may not be present. Only check for used HashAlgorithms[1].
+ */
+ if (len_of_ctxts < 6)
+ return STATUS_INVALID_PARAMETER;
- if (pneg_ctxt->HashAlgorithms == SMB2_PREAUTH_INTEGRITY_SHA512) {
- conn->preauth_info->Preauth_HashId =
- SMB2_PREAUTH_INTEGRITY_SHA512;
- err = STATUS_SUCCESS;
- }
+ if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
+ return STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP;
- return err;
+ conn->preauth_info->Preauth_HashId = SMB2_PREAUTH_INTEGRITY_SHA512;
+ return STATUS_SUCCESS;
}
static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
@@ -1045,7 +1049,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
break;
status = decode_preauth_ctxt(conn,
- (struct smb2_preauth_neg_context *)pctx);
+ (struct smb2_preauth_neg_context *)pctx,
+ len_of_ctxts);
if (status != STATUS_SUCCESS)
break;
} else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 083/154] ksmbd: set NegotiateContextCount once instead of every inc
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (81 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 082/154] ksmbd: avoid out of bounds access in decode_preauth_ctxt() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 084/154] ksmbd: avoid duplicate negotiate ctx offset increments Namjae Jeon
` (71 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, David Disseldorp, Namjae Jeon, Steve French
From: David Disseldorp <ddiss@suse.de>
[ Upstream commit 34e8ccf9ce24b6b2e275bbe35cd392e18fbbd369 ]
There are no early returns, so marshalling the incremented
NegotiateContextCount with every context is unnecessary.
Signed-off-by: David Disseldorp <ddiss@suse.de>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 472aa5fa0d10..d8985fe42ac6 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -848,7 +848,6 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
"assemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt,
conn->preauth_info->Preauth_HashId);
- rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
inc_rfc1001_len(smb2_buf_len, AUTH_GSS_PADDING);
ctxt_size = sizeof(struct smb2_preauth_neg_context);
/* Round to 8 byte boundary */
@@ -860,7 +859,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
"assemble SMB2_ENCRYPTION_CAPABILITIES context\n");
build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt,
conn->cipher_type);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_encryption_neg_context) + 2;
/* Round to 8 byte boundary */
pneg_ctxt +=
@@ -875,7 +874,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
/* Temporarily set to SMB3_COMPRESS_NONE */
build_compression_ctxt((struct smb2_compression_ctx *)pneg_ctxt,
conn->compress_algorithm);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_compression_ctx) + 2;
/* Round to 8 byte boundary */
pneg_ctxt += round_up(sizeof(struct smb2_compression_ctx) + 2,
@@ -887,7 +886,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
ksmbd_debug(SMB,
"assemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_posix_neg_context);
/* Round to 8 byte boundary */
pneg_ctxt += round_up(sizeof(struct smb2_posix_neg_context), 8);
@@ -899,10 +898,11 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
"assemble SMB2_SIGNING_CAPABILITIES context\n");
build_sign_cap_ctxt((struct smb2_signing_capabilities *)pneg_ctxt,
conn->signing_algorithm);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_signing_capabilities) + 2;
}
+ rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
inc_rfc1001_len(smb2_buf_len, ctxt_size);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 084/154] ksmbd: avoid duplicate negotiate ctx offset increments
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (82 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 083/154] ksmbd: set NegotiateContextCount once instead of every inc Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 085/154] ksmbd: remove unused compression negotiate ctx packing Namjae Jeon
` (70 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, David Disseldorp, Namjae Jeon, Steve French
From: David Disseldorp <ddiss@suse.de>
[ Upstream commit a12a07a85aff72e19520328f78b1c64d2281a1ec ]
Both pneg_ctxt and ctxt_size change in unison, with each adding the
length of the previously added context, rounded up to an eight byte
boundary.
Drop pneg_ctxt increments and instead use the ctxt_size offset when
passing output pointers to per-context helper functions. This slightly
simplifies offset tracking and shaves off a few text bytes.
Before (x86-64 gcc 7.5):
text data bss dec hex filename
213234 8677 672 222583 36577 ksmbd.ko
After:
text data bss dec hex filename
213218 8677 672 222567 36567 ksmbd.ko
Signed-off-by: David Disseldorp <ddiss@suse.de>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 26 ++++++++++----------------
1 file changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d8985fe42ac6..06c184927d66 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -839,7 +839,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
struct smb2_negotiate_rsp *rsp,
void *smb2_buf_len)
{
- char *pneg_ctxt = (char *)rsp +
+ char * const pneg_ctxt = (char *)rsp +
le32_to_cpu(rsp->NegotiateContextOffset);
int neg_ctxt_cnt = 1;
int ctxt_size;
@@ -850,21 +850,17 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
conn->preauth_info->Preauth_HashId);
inc_rfc1001_len(smb2_buf_len, AUTH_GSS_PADDING);
ctxt_size = sizeof(struct smb2_preauth_neg_context);
- /* Round to 8 byte boundary */
- pneg_ctxt += round_up(sizeof(struct smb2_preauth_neg_context), 8);
if (conn->cipher_type) {
+ /* Round to 8 byte boundary */
ctxt_size = round_up(ctxt_size, 8);
ksmbd_debug(SMB,
"assemble SMB2_ENCRYPTION_CAPABILITIES context\n");
- build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt,
+ build_encrypt_ctxt((struct smb2_encryption_neg_context *)
+ (pneg_ctxt + ctxt_size),
conn->cipher_type);
neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_encryption_neg_context) + 2;
- /* Round to 8 byte boundary */
- pneg_ctxt +=
- round_up(sizeof(struct smb2_encryption_neg_context) + 2,
- 8);
}
if (conn->compress_algorithm) {
@@ -872,31 +868,29 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
ksmbd_debug(SMB,
"assemble SMB2_COMPRESSION_CAPABILITIES context\n");
/* Temporarily set to SMB3_COMPRESS_NONE */
- build_compression_ctxt((struct smb2_compression_ctx *)pneg_ctxt,
+ build_compression_ctxt((struct smb2_compression_ctx *)
+ (pneg_ctxt + ctxt_size),
conn->compress_algorithm);
neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_compression_ctx) + 2;
- /* Round to 8 byte boundary */
- pneg_ctxt += round_up(sizeof(struct smb2_compression_ctx) + 2,
- 8);
}
if (conn->posix_ext_supported) {
ctxt_size = round_up(ctxt_size, 8);
ksmbd_debug(SMB,
"assemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
- build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
+ build_posix_ctxt((struct smb2_posix_neg_context *)
+ (pneg_ctxt + ctxt_size));
neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_posix_neg_context);
- /* Round to 8 byte boundary */
- pneg_ctxt += round_up(sizeof(struct smb2_posix_neg_context), 8);
}
if (conn->signing_negotiated) {
ctxt_size = round_up(ctxt_size, 8);
ksmbd_debug(SMB,
"assemble SMB2_SIGNING_CAPABILITIES context\n");
- build_sign_cap_ctxt((struct smb2_signing_capabilities *)pneg_ctxt,
+ build_sign_cap_ctxt((struct smb2_signing_capabilities *)
+ (pneg_ctxt + ctxt_size),
conn->signing_algorithm);
neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_signing_capabilities) + 2;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 085/154] ksmbd: remove unused compression negotiate ctx packing
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (83 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 084/154] ksmbd: avoid duplicate negotiate ctx offset increments Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 086/154] fs: introduce lock_rename_child() helper Namjae Jeon
` (69 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, David Disseldorp, Namjae Jeon, Steve French
From: David Disseldorp <ddiss@suse.de>
[ Upstream commit af36c51e0e111de4e908328d49cba49de758f66e ]
build_compression_ctxt() is currently unreachable due to
conn.compress_algorithm remaining zero (SMB3_COMPRESS_NONE).
It appears to have been broken in a couple of subtle ways over the
years:
- prior to d6c9ad23b421 ("ksmbd: use the common definitions for
NEGOTIATE_PROTOCOL") smb2_compression_ctx.DataLength was set to 8,
which didn't account for the single CompressionAlgorithms flexible
array member.
- post d6c9ad23b421 smb2_compression_capabilities_context
CompressionAlgorithms is a three member array, while
CompressionAlgorithmCount is set to indicate only one member.
assemble_neg_contexts() ctxt_size is also incorrectly incremented by
sizeof(struct smb2_compression_capabilities_context) + 2, which
assumes one flexible array member.
Signed-off-by: David Disseldorp <ddiss@suse.de>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 27 ++-------------------------
1 file changed, 2 insertions(+), 25 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 06c184927d66..37cb9375eb62 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -787,19 +787,6 @@ static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt,
pneg_ctxt->Ciphers[0] = cipher_type;
}
-static void build_compression_ctxt(struct smb2_compression_ctx *pneg_ctxt,
- __le16 comp_algo)
-{
- pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
- pneg_ctxt->DataLength =
- cpu_to_le16(sizeof(struct smb2_compression_ctx)
- - sizeof(struct smb2_neg_context));
- pneg_ctxt->Reserved = cpu_to_le32(0);
- pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(1);
- pneg_ctxt->Reserved1 = cpu_to_le32(0);
- pneg_ctxt->CompressionAlgorithms[0] = comp_algo;
-}
-
static void build_sign_cap_ctxt(struct smb2_signing_capabilities *pneg_ctxt,
__le16 sign_algo)
{
@@ -862,18 +849,8 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
neg_ctxt_cnt++;
ctxt_size += sizeof(struct smb2_encryption_neg_context) + 2;
}
-
- if (conn->compress_algorithm) {
- ctxt_size = round_up(ctxt_size, 8);
- ksmbd_debug(SMB,
- "assemble SMB2_COMPRESSION_CAPABILITIES context\n");
- /* Temporarily set to SMB3_COMPRESS_NONE */
- build_compression_ctxt((struct smb2_compression_ctx *)
- (pneg_ctxt + ctxt_size),
- conn->compress_algorithm);
- neg_ctxt_cnt++;
- ctxt_size += sizeof(struct smb2_compression_ctx) + 2;
- }
+ /* compression context not yet supported */
+ WARN_ON(conn->compress_algorithm != SMB3_COMPRESS_NONE);
if (conn->posix_ext_supported) {
ctxt_size = round_up(ctxt_size, 8);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 086/154] fs: introduce lock_rename_child() helper
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (84 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 085/154] ksmbd: remove unused compression negotiate ctx packing Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 087/154] ksmbd: fix racy issue from using ->d_parent and ->d_name Namjae Jeon
` (68 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Al Viro, Namjae Jeon
From: Al Viro <viro@zeniv.linux.org.uk>
[ Upstream commit 9bc37e04823b5280dd0f22b6680fc23fe81ca325 ]
Pass the dentry of a source file and the dentry of a destination directory
to lock parent inodes for rename. As soon as this function returns,
->d_parent of the source file dentry is stable and inodes are properly
locked for calling vfs-rename. This helper is needed for ksmbd server.
rename request of SMB protocol has to rename an opened file, no matter
which directory it's in.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/namei.c | 68 ++++++++++++++++++++++++++++++++++++-------
include/linux/namei.h | 1 +
2 files changed, 58 insertions(+), 11 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index ea2785103376..2a6ce6cfb449 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2956,20 +2956,10 @@ static inline int may_create(struct user_namespace *mnt_userns,
return inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC);
}
-/*
- * p1 and p2 should be directories on the same fs.
- */
-struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
+static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2)
{
struct dentry *p;
- if (p1 == p2) {
- inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
- return NULL;
- }
-
- mutex_lock(&p1->d_sb->s_vfs_rename_mutex);
-
p = d_ancestor(p2, p1);
if (p) {
inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
@@ -2988,8 +2978,64 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
I_MUTEX_PARENT, I_MUTEX_PARENT2);
return NULL;
}
+
+/*
+ * p1 and p2 should be directories on the same fs.
+ */
+struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
+{
+ if (p1 == p2) {
+ inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
+ return NULL;
+ }
+
+ mutex_lock(&p1->d_sb->s_vfs_rename_mutex);
+ return lock_two_directories(p1, p2);
+}
EXPORT_SYMBOL(lock_rename);
+/*
+ * c1 and p2 should be on the same fs.
+ */
+struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
+{
+ if (READ_ONCE(c1->d_parent) == p2) {
+ /*
+ * hopefully won't need to touch ->s_vfs_rename_mutex at all.
+ */
+ inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
+ /*
+ * now that p2 is locked, nobody can move in or out of it,
+ * so the test below is safe.
+ */
+ if (likely(c1->d_parent == p2))
+ return NULL;
+
+ /*
+ * c1 got moved out of p2 while we'd been taking locks;
+ * unlock and fall back to slow case.
+ */
+ inode_unlock(p2->d_inode);
+ }
+
+ mutex_lock(&c1->d_sb->s_vfs_rename_mutex);
+ /*
+ * nobody can move out of any directories on this fs.
+ */
+ if (likely(c1->d_parent != p2))
+ return lock_two_directories(c1->d_parent, p2);
+
+ /*
+ * c1 got moved into p2 while we were taking locks;
+ * we need p2 locked and ->s_vfs_rename_mutex unlocked,
+ * for consistency with lock_rename().
+ */
+ inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
+ mutex_unlock(&c1->d_sb->s_vfs_rename_mutex);
+ return NULL;
+}
+EXPORT_SYMBOL(lock_rename_child);
+
void unlock_rename(struct dentry *p1, struct dentry *p2)
{
inode_unlock(p1->d_inode);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 40c693525f79..7868732cce24 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -83,6 +83,7 @@ extern int follow_down(struct path *);
extern int follow_up(struct path *);
extern struct dentry *lock_rename(struct dentry *, struct dentry *);
+extern struct dentry *lock_rename_child(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);
extern int __must_check nd_jump_link(struct path *path);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 087/154] ksmbd: fix racy issue from using ->d_parent and ->d_name
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (85 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 086/154] fs: introduce lock_rename_child() helper Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 088/154] ksmbd: fix racy issue from session setup and logoff Namjae Jeon
` (67 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 74d7970febf7e9005375aeda0df821d2edffc9f7 ]
Al pointed out that ksmbd has racy issue from using ->d_parent and ->d_name
in ksmbd_vfs_unlink and smb2_vfs_rename(). and use new lock_rename_child()
to lock stable parent while underlying rename racy.
Introduce vfs_path_parent_lookup helper to avoid out of share access and
export vfs functions like the following ones to use
vfs_path_parent_lookup().
- rename __lookup_hash() to lookup_one_qstr_excl().
- export lookup_one_qstr_excl().
- export getname_kernel() and putname().
vfs_path_parent_lookup() is used for parent lookup of destination file
using absolute pathname given from FILE_RENAME_INFORMATION request.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 147 ++++----------
fs/ksmbd/vfs.c | 435 ++++++++++++++++++------------------------
fs/ksmbd/vfs.h | 19 +-
fs/ksmbd/vfs_cache.c | 5 +-
fs/namei.c | 57 ++++--
include/linux/namei.h | 6 +
6 files changed, 283 insertions(+), 386 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 37cb9375eb62..d39412f1ddb2 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2456,7 +2456,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
return rc;
}
- rc = ksmbd_vfs_kern_path(work, name, 0, path, 0);
+ rc = ksmbd_vfs_kern_path_locked(work, name, 0, path, 0);
if (rc) {
pr_err("cannot get linux path (%s), err = %d\n",
name, rc);
@@ -2744,8 +2744,10 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
- rc = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
+ rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
if (!rc) {
+ file_present = true;
+
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) {
/*
* If file exists with under flags, return access
@@ -2754,7 +2756,6 @@ int smb2_open(struct ksmbd_work *work)
if (req->CreateDisposition == FILE_OVERWRITE_IF_LE ||
req->CreateDisposition == FILE_OPEN_IF_LE) {
rc = -EACCES;
- path_put(&path);
goto err_out;
}
@@ -2762,26 +2763,23 @@ int smb2_open(struct ksmbd_work *work)
ksmbd_debug(SMB,
"User does not have write permission\n");
rc = -EACCES;
- path_put(&path);
goto err_out;
}
} else if (d_is_symlink(path.dentry)) {
rc = -EACCES;
- path_put(&path);
goto err_out;
}
- }
- if (rc) {
+ file_present = true;
+ user_ns = mnt_user_ns(path.mnt);
+ } else {
if (rc != -ENOENT)
goto err_out;
ksmbd_debug(SMB, "can not get linux path for %s, rc = %d\n",
name, rc);
rc = 0;
- } else {
- file_present = true;
- user_ns = mnt_user_ns(path.mnt);
}
+
if (stream_name) {
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
if (s_type == DATA_STREAM) {
@@ -2909,8 +2907,9 @@ int smb2_open(struct ksmbd_work *work)
if ((daccess & FILE_DELETE_LE) ||
(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
- rc = ksmbd_vfs_may_delete(user_ns,
- path.dentry);
+ rc = inode_permission(user_ns,
+ d_inode(path.dentry->d_parent),
+ MAY_EXEC | MAY_WRITE);
if (rc)
goto err_out;
}
@@ -3281,10 +3280,13 @@ int smb2_open(struct ksmbd_work *work)
}
err_out:
- if (file_present || created)
- path_put(&path);
+ if (file_present || created) {
+ inode_unlock(d_inode(path.dentry->d_parent));
+ dput(path.dentry);
+ }
ksmbd_revert_fsids(work);
err_out1:
+
if (rc) {
if (rc == -EINVAL)
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
@@ -5426,44 +5428,19 @@ int smb2_echo(struct ksmbd_work *work)
static int smb2_rename(struct ksmbd_work *work,
struct ksmbd_file *fp,
- struct user_namespace *user_ns,
struct smb2_file_rename_info *file_info,
struct nls_table *local_nls)
{
struct ksmbd_share_config *share = fp->tcon->share_conf;
- char *new_name = NULL, *abs_oldname = NULL, *old_name = NULL;
- char *pathname = NULL;
- struct path path;
- bool file_present = true;
- int rc;
+ char *new_name = NULL;
+ int rc, flags = 0;
ksmbd_debug(SMB, "setting FILE_RENAME_INFO\n");
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
-
- abs_oldname = file_path(fp->filp, pathname, PATH_MAX);
- if (IS_ERR(abs_oldname)) {
- rc = -EINVAL;
- goto out;
- }
- old_name = strrchr(abs_oldname, '/');
- if (old_name && old_name[1] != '\0') {
- old_name++;
- } else {
- ksmbd_debug(SMB, "can't get last component in path %s\n",
- abs_oldname);
- rc = -ENOENT;
- goto out;
- }
-
new_name = smb2_get_name(file_info->FileName,
le32_to_cpu(file_info->FileNameLength),
local_nls);
- if (IS_ERR(new_name)) {
- rc = PTR_ERR(new_name);
- goto out;
- }
+ if (IS_ERR(new_name))
+ return PTR_ERR(new_name);
if (strchr(new_name, ':')) {
int s_type;
@@ -5489,7 +5466,7 @@ static int smb2_rename(struct ksmbd_work *work,
if (rc)
goto out;
- rc = ksmbd_vfs_setxattr(user_ns,
+ rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp),
fp->filp->f_path.dentry,
xattr_stream_name,
NULL, 0, 0);
@@ -5504,47 +5481,18 @@ static int smb2_rename(struct ksmbd_work *work,
}
ksmbd_debug(SMB, "new name %s\n", new_name);
- rc = ksmbd_vfs_kern_path(work, new_name, LOOKUP_NO_SYMLINKS, &path, 1);
- if (rc) {
- if (rc != -ENOENT)
- goto out;
- file_present = false;
- } else {
- path_put(&path);
- }
-
if (ksmbd_share_veto_filename(share, new_name)) {
rc = -ENOENT;
ksmbd_debug(SMB, "Can't rename vetoed file: %s\n", new_name);
goto out;
}
- if (file_info->ReplaceIfExists) {
- if (file_present) {
- rc = ksmbd_vfs_remove_file(work, new_name);
- if (rc) {
- if (rc != -ENOTEMPTY)
- rc = -EINVAL;
- ksmbd_debug(SMB, "cannot delete %s, rc %d\n",
- new_name, rc);
- goto out;
- }
- }
- } else {
- if (file_present &&
- strncmp(old_name, path.dentry->d_name.name, strlen(old_name))) {
- rc = -EEXIST;
- ksmbd_debug(SMB,
- "cannot rename already existing file\n");
- goto out;
- }
- }
+ if (!file_info->ReplaceIfExists)
+ flags = RENAME_NOREPLACE;
- rc = ksmbd_vfs_fp_rename(work, fp, new_name);
+ rc = ksmbd_vfs_rename(work, &fp->filp->f_path, new_name, flags);
out:
- kfree(pathname);
- if (!IS_ERR(new_name))
- kfree(new_name);
+ kfree(new_name);
return rc;
}
@@ -5584,18 +5532,17 @@ static int smb2_create_link(struct ksmbd_work *work,
}
ksmbd_debug(SMB, "target name is %s\n", target_name);
- rc = ksmbd_vfs_kern_path(work, link_name, LOOKUP_NO_SYMLINKS, &path, 0);
+ rc = ksmbd_vfs_kern_path_locked(work, link_name, LOOKUP_NO_SYMLINKS,
+ &path, 0);
if (rc) {
if (rc != -ENOENT)
goto out;
file_present = false;
- } else {
- path_put(&path);
}
if (file_info->ReplaceIfExists) {
if (file_present) {
- rc = ksmbd_vfs_remove_file(work, link_name);
+ rc = ksmbd_vfs_remove_file(work, &path);
if (rc) {
rc = -EINVAL;
ksmbd_debug(SMB, "cannot delete %s\n",
@@ -5615,6 +5562,10 @@ static int smb2_create_link(struct ksmbd_work *work,
if (rc)
rc = -EINVAL;
out:
+ if (file_present) {
+ inode_unlock(d_inode(path.dentry->d_parent));
+ path_put(&path);
+ }
if (!IS_ERR(link_name))
kfree(link_name);
kfree(pathname);
@@ -5792,12 +5743,6 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
struct smb2_file_rename_info *rename_info,
unsigned int buf_len)
{
- struct user_namespace *user_ns;
- struct ksmbd_file *parent_fp;
- struct dentry *parent;
- struct dentry *dentry = fp->filp->f_path.dentry;
- int ret;
-
if (!(fp->daccess & FILE_DELETE_LE)) {
pr_err("no right to delete : 0x%x\n", fp->daccess);
return -EACCES;
@@ -5807,32 +5752,10 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
le32_to_cpu(rename_info->FileNameLength))
return -EINVAL;
- user_ns = file_mnt_user_ns(fp->filp);
- if (ksmbd_stream_fd(fp))
- goto next;
-
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
- }
-
- parent_fp = ksmbd_lookup_fd_inode(d_inode(parent));
- inode_unlock(d_inode(parent));
- dput(parent);
+ if (!le32_to_cpu(rename_info->FileNameLength))
+ return -EINVAL;
- if (parent_fp) {
- if (parent_fp->daccess & FILE_DELETE_LE) {
- pr_err("parent dir is opened with delete access\n");
- ksmbd_fd_put(work, parent_fp);
- return -ESHARE;
- }
- ksmbd_fd_put(work, parent_fp);
- }
-next:
- return smb2_rename(work, fp, user_ns, rename_info,
- work->conn->local_nls);
+ return smb2_rename(work, fp, rename_info, work->conn->local_nls);
}
static int set_file_disposition_info(struct ksmbd_file *fp,
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 90f657f3b48f..e31584ad80fa 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -18,6 +18,7 @@
#include <linux/vmalloc.h>
#include <linux/sched/xacct.h>
#include <linux/crc32c.h>
+#include <linux/namei.h>
#include "glob.h"
#include "oplock.h"
@@ -35,19 +36,6 @@
#include "mgmt/user_session.h"
#include "mgmt/user_config.h"
-static char *extract_last_component(char *path)
-{
- char *p = strrchr(path, '/');
-
- if (p && p[1] != '\0') {
- *p = '\0';
- p++;
- } else {
- p = NULL;
- }
- return p;
-}
-
static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
struct inode *parent_inode,
struct inode *inode)
@@ -61,65 +49,77 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
/**
* ksmbd_vfs_lock_parent() - lock parent dentry if it is stable
- *
- * the parent dentry got by dget_parent or @parent could be
- * unstable, we try to lock a parent inode and lookup the
- * child dentry again.
- *
- * the reference count of @parent isn't incremented.
*/
-int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
- struct dentry *child)
+int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
{
- struct dentry *dentry;
- int ret = 0;
-
inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
- dentry = lookup_one(user_ns, child->d_name.name, parent,
- child->d_name.len);
- if (IS_ERR(dentry)) {
- ret = PTR_ERR(dentry);
- goto out_err;
- }
-
- if (dentry != child) {
- ret = -ESTALE;
- dput(dentry);
- goto out_err;
+ if (child->d_parent != parent) {
+ inode_unlock(d_inode(parent));
+ return -ENOENT;
}
- dput(dentry);
return 0;
-out_err:
- inode_unlock(d_inode(parent));
- return ret;
}
-int ksmbd_vfs_may_delete(struct user_namespace *user_ns,
- struct dentry *dentry)
+static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
+ char *pathname, unsigned int flags,
+ struct path *path)
{
- struct dentry *parent;
- int ret;
+ struct qstr last;
+ struct filename *filename;
+ struct path *root_share_path = &share_conf->vfs_path;
+ int err, type;
+ struct path parent_path;
+ struct dentry *d;
+
+ if (pathname[0] == '\0') {
+ pathname = share_conf->path;
+ root_share_path = NULL;
+ } else {
+ flags |= LOOKUP_BENEATH;
+ }
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
+ filename = getname_kernel(pathname);
+ if (IS_ERR(filename))
+ return PTR_ERR(filename);
+
+ err = vfs_path_parent_lookup(filename, flags,
+ &parent_path, &last, &type,
+ root_share_path);
+ putname(filename);
+ if (err)
+ return err;
+
+ if (unlikely(type != LAST_NORM)) {
+ path_put(&parent_path);
+ return -ENOENT;
}
- ret = inode_permission(user_ns, d_inode(parent),
- MAY_EXEC | MAY_WRITE);
+ inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
+ d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
+ if (IS_ERR(d))
+ goto err_out;
- inode_unlock(d_inode(parent));
- dput(parent);
- return ret;
+ if (d_is_negative(d)) {
+ dput(d);
+ goto err_out;
+ }
+
+ path->dentry = d;
+ path->mnt = share_conf->vfs_path.mnt;
+ path_put(&parent_path);
+
+ return 0;
+
+err_out:
+ inode_unlock(parent_path.dentry->d_inode);
+ path_put(&parent_path);
+ return -ENOENT;
}
int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
struct dentry *dentry, __le32 *daccess)
{
- struct dentry *parent;
int ret = 0;
*daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
@@ -136,18 +136,9 @@ int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC))
*daccess |= FILE_EXECUTE_LE;
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
- }
-
- if (!inode_permission(user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
+ if (!inode_permission(user_ns, d_inode(dentry->d_parent), MAY_EXEC | MAY_WRITE))
*daccess |= FILE_DELETE_LE;
- inode_unlock(d_inode(parent));
- dput(parent);
return ret;
}
@@ -580,54 +571,32 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
*
* Return: 0 on success, otherwise error
*/
-int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
+int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
{
struct user_namespace *user_ns;
- struct path path;
- struct dentry *parent;
+ struct dentry *parent = path->dentry->d_parent;
int err;
if (ksmbd_override_fsids(work))
return -ENOMEM;
- err = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, false);
- if (err) {
- ksmbd_debug(VFS, "can't get %s, err %d\n", name, err);
- ksmbd_revert_fsids(work);
- return err;
- }
-
- user_ns = mnt_user_ns(path.mnt);
- parent = dget_parent(path.dentry);
- err = ksmbd_vfs_lock_parent(user_ns, parent, path.dentry);
- if (err) {
- dput(parent);
- path_put(&path);
- ksmbd_revert_fsids(work);
- return err;
- }
-
- if (!d_inode(path.dentry)->i_nlink) {
+ if (!d_inode(path->dentry)->i_nlink) {
err = -ENOENT;
goto out_err;
}
- if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
- err = vfs_rmdir(user_ns, d_inode(parent), path.dentry);
+ user_ns = mnt_user_ns(path->mnt);
+ if (S_ISDIR(d_inode(path->dentry)->i_mode)) {
+ err = vfs_rmdir(user_ns, d_inode(parent), path->dentry);
if (err && err != -ENOTEMPTY)
- ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
- err);
+ ksmbd_debug(VFS, "rmdir failed, err %d\n", err);
} else {
- err = vfs_unlink(user_ns, d_inode(parent), path.dentry, NULL);
+ err = vfs_unlink(user_ns, d_inode(parent), path->dentry, NULL);
if (err)
- ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
- err);
+ ksmbd_debug(VFS, "unlink failed, err %d\n", err);
}
out_err:
- inode_unlock(d_inode(parent));
- dput(parent);
- path_put(&path);
ksmbd_revert_fsids(work);
return err;
}
@@ -686,149 +655,114 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
return err;
}
-static int ksmbd_validate_entry_in_use(struct dentry *src_dent)
+int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
+ char *newname, int flags)
{
- struct dentry *dst_dent;
-
- spin_lock(&src_dent->d_lock);
- list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
- struct ksmbd_file *child_fp;
+ struct dentry *old_parent, *new_dentry, *trap;
+ struct dentry *old_child = old_path->dentry;
+ struct path new_path;
+ struct qstr new_last;
+ struct renamedata rd;
+ struct filename *to;
+ struct ksmbd_share_config *share_conf = work->tcon->share_conf;
+ struct ksmbd_file *parent_fp;
+ int new_type;
+ int err, lookup_flags = LOOKUP_NO_SYMLINKS;
- if (d_really_is_negative(dst_dent))
- continue;
+ if (ksmbd_override_fsids(work))
+ return -ENOMEM;
- child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
- if (child_fp) {
- spin_unlock(&src_dent->d_lock);
- ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
- return -EACCES;
- }
+ to = getname_kernel(newname);
+ if (IS_ERR(to)) {
+ err = PTR_ERR(to);
+ goto revert_fsids;
}
- spin_unlock(&src_dent->d_lock);
- return 0;
-}
+retry:
+ err = vfs_path_parent_lookup(to, lookup_flags | LOOKUP_BENEATH,
+ &new_path, &new_last, &new_type,
+ &share_conf->vfs_path);
+ if (err)
+ goto out1;
-static int __ksmbd_vfs_rename(struct ksmbd_work *work,
- struct user_namespace *src_user_ns,
- struct dentry *src_dent_parent,
- struct dentry *src_dent,
- struct user_namespace *dst_user_ns,
- struct dentry *dst_dent_parent,
- struct dentry *trap_dent,
- char *dst_name)
-{
- struct dentry *dst_dent;
- int err;
+ if (old_path->mnt != new_path.mnt) {
+ err = -EXDEV;
+ goto out2;
+ }
- if (!work->tcon->posix_extensions) {
- err = ksmbd_validate_entry_in_use(src_dent);
- if (err)
- return err;
+ trap = lock_rename_child(old_child, new_path.dentry);
+
+ old_parent = dget(old_child->d_parent);
+ if (d_unhashed(old_child)) {
+ err = -EINVAL;
+ goto out3;
}
- if (d_really_is_negative(src_dent_parent))
- return -ENOENT;
- if (d_really_is_negative(dst_dent_parent))
- return -ENOENT;
- if (d_really_is_negative(src_dent))
- return -ENOENT;
- if (src_dent == trap_dent)
- return -EINVAL;
+ parent_fp = ksmbd_lookup_fd_inode(d_inode(old_child->d_parent));
+ if (parent_fp) {
+ if (parent_fp->daccess & FILE_DELETE_LE) {
+ pr_err("parent dir is opened with delete access\n");
+ err = -ESHARE;
+ ksmbd_fd_put(work, parent_fp);
+ goto out3;
+ }
+ ksmbd_fd_put(work, parent_fp);
+ }
- if (ksmbd_override_fsids(work))
- return -ENOMEM;
+ new_dentry = lookup_one_qstr_excl(&new_last, new_path.dentry,
+ lookup_flags | LOOKUP_RENAME_TARGET);
+ if (IS_ERR(new_dentry)) {
+ err = PTR_ERR(new_dentry);
+ goto out3;
+ }
- dst_dent = lookup_one(dst_user_ns, dst_name, dst_dent_parent,
- strlen(dst_name));
- err = PTR_ERR(dst_dent);
- if (IS_ERR(dst_dent)) {
- pr_err("lookup failed %s [%d]\n", dst_name, err);
- goto out;
+ if (d_is_symlink(new_dentry)) {
+ err = -EACCES;
+ goto out4;
}
- err = -ENOTEMPTY;
- if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
- struct renamedata rd = {
- .old_mnt_userns = src_user_ns,
- .old_dir = d_inode(src_dent_parent),
- .old_dentry = src_dent,
- .new_mnt_userns = dst_user_ns,
- .new_dir = d_inode(dst_dent_parent),
- .new_dentry = dst_dent,
- };
- err = vfs_rename(&rd);
+ if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) {
+ err = -EEXIST;
+ goto out4;
}
- if (err)
- pr_err("vfs_rename failed err %d\n", err);
- if (dst_dent)
- dput(dst_dent);
-out:
- ksmbd_revert_fsids(work);
- return err;
-}
-int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *newname)
-{
- struct user_namespace *user_ns;
- struct path dst_path;
- struct dentry *src_dent_parent, *dst_dent_parent;
- struct dentry *src_dent, *trap_dent, *src_child;
- char *dst_name;
- int err;
+ if (old_child == trap) {
+ err = -EINVAL;
+ goto out4;
+ }
- dst_name = extract_last_component(newname);
- if (!dst_name) {
- dst_name = newname;
- newname = "";
+ if (new_dentry == trap) {
+ err = -ENOTEMPTY;
+ goto out4;
}
- src_dent_parent = dget_parent(fp->filp->f_path.dentry);
- src_dent = fp->filp->f_path.dentry;
+ rd.old_mnt_userns = mnt_user_ns(old_path->mnt),
+ rd.old_dir = d_inode(old_parent),
+ rd.old_dentry = old_child,
+ rd.new_mnt_userns = mnt_user_ns(new_path.mnt),
+ rd.new_dir = new_path.dentry->d_inode,
+ rd.new_dentry = new_dentry,
+ rd.flags = flags,
+ err = vfs_rename(&rd);
+ if (err)
+ ksmbd_debug(VFS, "vfs_rename failed err %d\n", err);
- err = ksmbd_vfs_kern_path(work, newname,
- LOOKUP_NO_SYMLINKS | LOOKUP_DIRECTORY,
- &dst_path, false);
- if (err) {
- ksmbd_debug(VFS, "Cannot get path for %s [%d]\n", newname, err);
- goto out;
+out4:
+ dput(new_dentry);
+out3:
+ dput(old_parent);
+ unlock_rename(old_parent, new_path.dentry);
+out2:
+ path_put(&new_path);
+
+ if (retry_estale(err, lookup_flags)) {
+ lookup_flags |= LOOKUP_REVAL;
+ goto retry;
}
- dst_dent_parent = dst_path.dentry;
-
- trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
- dget(src_dent);
- dget(dst_dent_parent);
- user_ns = file_mnt_user_ns(fp->filp);
- src_child = lookup_one(user_ns, src_dent->d_name.name, src_dent_parent,
- src_dent->d_name.len);
- if (IS_ERR(src_child)) {
- err = PTR_ERR(src_child);
- goto out_lock;
- }
-
- if (src_child != src_dent) {
- err = -ESTALE;
- dput(src_child);
- goto out_lock;
- }
- dput(src_child);
-
- err = __ksmbd_vfs_rename(work,
- user_ns,
- src_dent_parent,
- src_dent,
- mnt_user_ns(dst_path.mnt),
- dst_dent_parent,
- trap_dent,
- dst_name);
-out_lock:
- dput(src_dent);
- dput(dst_dent_parent);
- unlock_rename(src_dent_parent, dst_dent_parent);
- path_put(&dst_path);
-out:
- dput(src_dent_parent);
+out1:
+ putname(to);
+revert_fsids:
+ ksmbd_revert_fsids(work);
return err;
}
@@ -1079,14 +1013,16 @@ int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
return vfs_removexattr(user_ns, dentry, attr_name);
}
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
- struct dentry *dir, struct dentry *dentry)
+int ksmbd_vfs_unlink(struct file *filp)
{
int err = 0;
+ struct dentry *dir, *dentry = filp->f_path.dentry;
+ struct user_namespace *user_ns = file_mnt_user_ns(filp);
- err = ksmbd_vfs_lock_parent(user_ns, dir, dentry);
+ dir = dget_parent(dentry);
+ err = ksmbd_vfs_lock_parent(dir, dentry);
if (err)
- return err;
+ goto out;
dget(dentry);
if (S_ISDIR(d_inode(dentry)->i_mode))
@@ -1098,6 +1034,8 @@ int ksmbd_vfs_unlink(struct user_namespace *user_ns,
inode_unlock(d_inode(dir));
if (err)
ksmbd_debug(VFS, "failed to delete, err %d\n", err);
+out:
+ dput(dir);
return err;
}
@@ -1202,7 +1140,7 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
}
/**
- * ksmbd_vfs_kern_path() - lookup a file and get path info
+ * ksmbd_vfs_kern_path_locked() - lookup a file and get path info
* @name: file path that is relative to share
* @flags: lookup flags
* @path: if lookup succeed, return path info
@@ -1210,24 +1148,20 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
*
* Return: 0 on success, otherwise error
*/
-int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
- unsigned int flags, struct path *path, bool caseless)
+int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
+ unsigned int flags, struct path *path,
+ bool caseless)
{
struct ksmbd_share_config *share_conf = work->tcon->share_conf;
int err;
+ struct path parent_path;
- flags |= LOOKUP_BENEATH;
- err = vfs_path_lookup(share_conf->vfs_path.dentry,
- share_conf->vfs_path.mnt,
- name,
- flags,
- path);
+ err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, path);
if (!err)
- return 0;
+ return err;
if (caseless) {
char *filepath;
- struct path parent;
size_t path_len, remain_len;
filepath = kstrdup(name, GFP_KERNEL);
@@ -1237,10 +1171,10 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
path_len = strlen(filepath);
remain_len = path_len;
- parent = share_conf->vfs_path;
- path_get(&parent);
+ parent_path = share_conf->vfs_path;
+ path_get(&parent_path);
- while (d_can_lookup(parent.dentry)) {
+ while (d_can_lookup(parent_path.dentry)) {
char *filename = filepath + path_len - remain_len;
char *next = strchrnul(filename, '/');
size_t filename_len = next - filename;
@@ -1249,12 +1183,11 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
if (filename_len == 0)
break;
- err = ksmbd_vfs_lookup_in_dir(&parent, filename,
+ err = ksmbd_vfs_lookup_in_dir(&parent_path, filename,
filename_len,
work->conn->um);
- path_put(&parent);
if (err)
- goto out;
+ goto out2;
next[0] = '\0';
@@ -1262,23 +1195,31 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
share_conf->vfs_path.mnt,
filepath,
flags,
- &parent);
+ path);
if (err)
- goto out;
- else if (is_last) {
- *path = parent;
- goto out;
- }
+ goto out2;
+ else if (is_last)
+ goto out1;
+ path_put(&parent_path);
+ parent_path = *path;
next[0] = '/';
remain_len -= filename_len + 1;
}
- path_put(&parent);
err = -EINVAL;
-out:
+out2:
+ path_put(&parent_path);
+out1:
kfree(filepath);
}
+
+ if (!err) {
+ err = ksmbd_vfs_lock_parent(parent_path.dentry, path->dentry);
+ if (err)
+ dput(path->dentry);
+ path_put(&parent_path);
+ }
return err;
}
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index 1f0cbd520f12..bd92b8a6edbe 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -110,9 +110,7 @@ struct ksmbd_kstat {
__le32 file_attributes;
};
-int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
- struct dentry *child);
-int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry);
+int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child);
int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
struct dentry *dentry, __le32 *daccess);
int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
@@ -123,12 +121,12 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
char *buf, size_t count, loff_t *pos, bool sync,
ssize_t *written);
int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id);
-int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name);
+int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path);
int ksmbd_vfs_link(struct ksmbd_work *work,
const char *oldname, const char *newname);
int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat);
-int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *newname);
+int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
+ char *newname, int flags);
int ksmbd_vfs_truncate(struct ksmbd_work *work,
struct ksmbd_file *fp, loff_t size);
struct srv_copychunk;
@@ -155,9 +153,9 @@ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
size_t *xattr_stream_name_size, int s_type);
int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
struct dentry *dentry, char *attr_name);
-int ksmbd_vfs_kern_path(struct ksmbd_work *work,
- char *name, unsigned int flags, struct path *path,
- bool caseless);
+int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
+ unsigned int flags, struct path *path,
+ bool caseless);
struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
const char *name,
unsigned int flags,
@@ -170,8 +168,7 @@ struct file_allocated_range_buffer;
int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
struct file_allocated_range_buffer *ranges,
unsigned int in_count, unsigned int *out_count);
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
- struct dentry *dir, struct dentry *dentry);
+int ksmbd_vfs_unlink(struct file *filp);
void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat);
int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
struct user_namespace *user_ns,
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index 6ec6c129465d..bafb34d4b5bb 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -243,7 +243,6 @@ void ksmbd_release_inode_hash(void)
static void __ksmbd_inode_close(struct ksmbd_file *fp)
{
- struct dentry *dir, *dentry;
struct ksmbd_inode *ci = fp->f_ci;
int err;
struct file *filp;
@@ -262,11 +261,9 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
if (atomic_dec_and_test(&ci->m_count)) {
write_lock(&ci->m_lock);
if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
- dentry = filp->f_path.dentry;
- dir = dentry->d_parent;
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
write_unlock(&ci->m_lock);
- ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry);
+ ksmbd_vfs_unlink(filp);
write_lock(&ci->m_lock);
}
write_unlock(&ci->m_lock);
diff --git a/fs/namei.c b/fs/namei.c
index 2a6ce6cfb449..a7f88c5b3d90 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -252,6 +252,7 @@ getname_kernel(const char * filename)
return result;
}
+EXPORT_SYMBOL(getname_kernel);
void putname(struct filename *name)
{
@@ -269,6 +270,7 @@ void putname(struct filename *name)
} else
__putname(name);
}
+EXPORT_SYMBOL(putname);
/**
* check_acl - perform ACL permission checking
@@ -1539,8 +1541,9 @@ static struct dentry *lookup_dcache(const struct qstr *name,
* when directory is guaranteed to have no in-lookup children
* at all.
*/
-static struct dentry *__lookup_hash(const struct qstr *name,
- struct dentry *base, unsigned int flags)
+struct dentry *lookup_one_qstr_excl(const struct qstr *name,
+ struct dentry *base,
+ unsigned int flags)
{
struct dentry *dentry = lookup_dcache(name, base, flags);
struct dentry *old;
@@ -1564,6 +1567,7 @@ static struct dentry *__lookup_hash(const struct qstr *name,
}
return dentry;
}
+EXPORT_SYMBOL(lookup_one_qstr_excl);
static struct dentry *lookup_fast(struct nameidata *nd,
struct inode **inode,
@@ -2508,16 +2512,17 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
}
/* Note: this does not consume "name" */
-static int filename_parentat(int dfd, struct filename *name,
- unsigned int flags, struct path *parent,
- struct qstr *last, int *type)
+static int __filename_parentat(int dfd, struct filename *name,
+ unsigned int flags, struct path *parent,
+ struct qstr *last, int *type,
+ const struct path *root)
{
int retval;
struct nameidata nd;
if (IS_ERR(name))
return PTR_ERR(name);
- set_nameidata(&nd, dfd, name, NULL);
+ set_nameidata(&nd, dfd, name, root);
retval = path_parentat(&nd, flags | LOOKUP_RCU, parent);
if (unlikely(retval == -ECHILD))
retval = path_parentat(&nd, flags, parent);
@@ -2532,6 +2537,13 @@ static int filename_parentat(int dfd, struct filename *name,
return retval;
}
+static int filename_parentat(int dfd, struct filename *name,
+ unsigned int flags, struct path *parent,
+ struct qstr *last, int *type)
+{
+ return __filename_parentat(dfd, name, flags, parent, last, type, NULL);
+}
+
/* does lookup, returns the object with parent locked */
static struct dentry *__kern_path_locked(struct filename *name, struct path *path)
{
@@ -2547,7 +2559,7 @@ static struct dentry *__kern_path_locked(struct filename *name, struct path *pat
return ERR_PTR(-EINVAL);
}
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
- d = __lookup_hash(&last, path->dentry, 0);
+ d = lookup_one_qstr_excl(&last, path->dentry, 0);
if (IS_ERR(d)) {
inode_unlock(path->dentry->d_inode);
path_put(path);
@@ -2575,6 +2587,24 @@ int kern_path(const char *name, unsigned int flags, struct path *path)
}
EXPORT_SYMBOL(kern_path);
+/**
+ * vfs_path_parent_lookup - lookup a parent path relative to a dentry-vfsmount pair
+ * @filename: filename structure
+ * @flags: lookup flags
+ * @parent: pointer to struct path to fill
+ * @last: last component
+ * @type: type of the last component
+ * @root: pointer to struct path of the base directory
+ */
+int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
+ struct path *parent, struct qstr *last, int *type,
+ const struct path *root)
+{
+ return __filename_parentat(AT_FDCWD, filename, flags, parent, last,
+ type, root);
+}
+EXPORT_SYMBOL(vfs_path_parent_lookup);
+
/**
* vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair
* @dentry: pointer to dentry of the base directory
@@ -3809,7 +3839,8 @@ static struct dentry *filename_create(int dfd, struct filename *name,
if (last.name[last.len] && !want_dir)
create_flags = 0;
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
- dentry = __lookup_hash(&last, path->dentry, reval_flag | create_flags);
+ dentry = lookup_one_qstr_excl(&last, path->dentry,
+ reval_flag | create_flags);
if (IS_ERR(dentry))
goto unlock;
@@ -4170,7 +4201,7 @@ int do_rmdir(int dfd, struct filename *name)
goto exit2;
inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
- dentry = __lookup_hash(&last, path.dentry, lookup_flags);
+ dentry = lookup_one_qstr_excl(&last, path.dentry, lookup_flags);
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit3;
@@ -4304,7 +4335,7 @@ int do_unlinkat(int dfd, struct filename *name)
goto exit2;
retry_deleg:
inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
- dentry = __lookup_hash(&last, path.dentry, lookup_flags);
+ dentry = lookup_one_qstr_excl(&last, path.dentry, lookup_flags);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
struct user_namespace *mnt_userns;
@@ -4878,7 +4909,8 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
retry_deleg:
trap = lock_rename(new_path.dentry, old_path.dentry);
- old_dentry = __lookup_hash(&old_last, old_path.dentry, lookup_flags);
+ old_dentry = lookup_one_qstr_excl(&old_last, old_path.dentry,
+ lookup_flags);
error = PTR_ERR(old_dentry);
if (IS_ERR(old_dentry))
goto exit3;
@@ -4886,7 +4918,8 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
error = -ENOENT;
if (d_is_negative(old_dentry))
goto exit4;
- new_dentry = __lookup_hash(&new_last, new_path.dentry, lookup_flags | target_flags);
+ new_dentry = lookup_one_qstr_excl(&new_last, new_path.dentry,
+ lookup_flags | target_flags);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto exit4;
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 7868732cce24..53c03d9ed34c 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -57,12 +57,18 @@ static inline int user_path_at(int dfd, const char __user *name, unsigned flags,
return user_path_at_empty(dfd, name, flags, path, NULL);
}
+struct dentry *lookup_one_qstr_excl(const struct qstr *name,
+ struct dentry *base,
+ unsigned int flags);
extern int kern_path(const char *, unsigned, struct path *);
extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
extern void done_path_create(struct path *, struct dentry *);
extern struct dentry *kern_path_locked(const char *, struct path *);
+int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
+ struct path *parent, struct qstr *last, int *type,
+ const struct path *root);
int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *,
unsigned int, struct path *);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 088/154] ksmbd: fix racy issue from session setup and logoff
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (86 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 087/154] ksmbd: fix racy issue from using ->d_parent and ->d_name Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 089/154] ksmbd: destroy expired sessions Namjae Jeon
` (66 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit f5c779b7ddbda30866cf2a27c63e34158f858c73 ]
This racy issue is triggered by sending concurrent session setup and
logoff requests. This patch does not set connection status as
KSMBD_SESS_GOOD if state is KSMBD_SESS_NEED_RECONNECT in session setup.
And relookup session to validate if session is deleted in logoff.
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20481, ZDI-CAN-20590, ZDI-CAN-20596
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 14 ++++----
fs/ksmbd/connection.h | 39 ++++++++++++---------
fs/ksmbd/mgmt/user_session.c | 1 +
fs/ksmbd/server.c | 3 +-
fs/ksmbd/smb2pdu.c | 67 +++++++++++++++++++++++-------------
fs/ksmbd/transport_tcp.c | 2 +-
6 files changed, 77 insertions(+), 49 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 54888f2819e6..c47b80759603 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -56,7 +56,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
return NULL;
conn->need_neg = true;
- conn->status = KSMBD_SESS_NEW;
+ ksmbd_conn_set_new(conn);
conn->local_nls = load_nls("utf8");
if (!conn->local_nls)
conn->local_nls = load_nls_default();
@@ -147,12 +147,12 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
return ret;
}
-static void ksmbd_conn_lock(struct ksmbd_conn *conn)
+void ksmbd_conn_lock(struct ksmbd_conn *conn)
{
mutex_lock(&conn->srv_mutex);
}
-static void ksmbd_conn_unlock(struct ksmbd_conn *conn)
+void ksmbd_conn_unlock(struct ksmbd_conn *conn)
{
mutex_unlock(&conn->srv_mutex);
}
@@ -243,7 +243,7 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)
if (!ksmbd_server_running())
return false;
- if (conn->status == KSMBD_SESS_EXITING)
+ if (ksmbd_conn_exiting(conn))
return false;
if (kthread_should_stop())
@@ -303,7 +303,7 @@ int ksmbd_conn_handler_loop(void *p)
pdu_size = get_rfc1002_len(hdr_buf);
ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
- if (conn->status == KSMBD_SESS_GOOD)
+ if (ksmbd_conn_good(conn))
max_allowed_pdu_size =
SMB3_MAX_MSGSIZE + conn->vals->max_write_size;
else
@@ -312,7 +312,7 @@ int ksmbd_conn_handler_loop(void *p)
if (pdu_size > max_allowed_pdu_size) {
pr_err_ratelimited("PDU length(%u) exceeded maximum allowed pdu size(%u) on connection(%d)\n",
pdu_size, max_allowed_pdu_size,
- conn->status);
+ READ_ONCE(conn->status));
break;
}
@@ -417,7 +417,7 @@ static void stop_sessions(void)
if (task)
ksmbd_debug(CONN, "Stop session handler %s/%d\n",
task->comm, task_pid_nr(task));
- conn->status = KSMBD_SESS_EXITING;
+ ksmbd_conn_set_exiting(conn);
if (t->ops->shutdown) {
read_unlock(&conn_list_lock);
t->ops->shutdown(t);
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index 0e3a848defaf..98bb5f199fa2 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -162,6 +162,8 @@ void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
int ksmbd_conn_handler_loop(void *p);
int ksmbd_conn_transport_init(void);
void ksmbd_conn_transport_destroy(void);
+void ksmbd_conn_lock(struct ksmbd_conn *conn);
+void ksmbd_conn_unlock(struct ksmbd_conn *conn);
/*
* WARNING
@@ -169,43 +171,48 @@ void ksmbd_conn_transport_destroy(void);
* This is a hack. We will move status to a proper place once we land
* a multi-sessions support.
*/
-static inline bool ksmbd_conn_good(struct ksmbd_work *work)
+static inline bool ksmbd_conn_good(struct ksmbd_conn *conn)
{
- return work->conn->status == KSMBD_SESS_GOOD;
+ return READ_ONCE(conn->status) == KSMBD_SESS_GOOD;
}
-static inline bool ksmbd_conn_need_negotiate(struct ksmbd_work *work)
+static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)
{
- return work->conn->status == KSMBD_SESS_NEED_NEGOTIATE;
+ return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE;
}
-static inline bool ksmbd_conn_need_reconnect(struct ksmbd_work *work)
+static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn)
{
- return work->conn->status == KSMBD_SESS_NEED_RECONNECT;
+ return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT;
}
-static inline bool ksmbd_conn_exiting(struct ksmbd_work *work)
+static inline bool ksmbd_conn_exiting(struct ksmbd_conn *conn)
{
- return work->conn->status == KSMBD_SESS_EXITING;
+ return READ_ONCE(conn->status) == KSMBD_SESS_EXITING;
}
-static inline void ksmbd_conn_set_good(struct ksmbd_work *work)
+static inline void ksmbd_conn_set_new(struct ksmbd_conn *conn)
{
- work->conn->status = KSMBD_SESS_GOOD;
+ WRITE_ONCE(conn->status, KSMBD_SESS_NEW);
}
-static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_work *work)
+static inline void ksmbd_conn_set_good(struct ksmbd_conn *conn)
{
- work->conn->status = KSMBD_SESS_NEED_NEGOTIATE;
+ WRITE_ONCE(conn->status, KSMBD_SESS_GOOD);
}
-static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_work *work)
+static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn)
{
- work->conn->status = KSMBD_SESS_NEED_RECONNECT;
+ WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE);
}
-static inline void ksmbd_conn_set_exiting(struct ksmbd_work *work)
+static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
{
- work->conn->status = KSMBD_SESS_EXITING;
+ WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);
+}
+
+static inline void ksmbd_conn_set_exiting(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_EXITING);
}
#endif /* __CONNECTION_H__ */
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index 1ca2aae4c299..68d40025cfbf 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -315,6 +315,7 @@ static struct ksmbd_session *__session_create(int protocol)
if (ksmbd_init_file_table(&sess->file_table))
goto error;
+ sess->state = SMB2_SESSION_IN_PROGRESS;
set_session_flag(sess, protocol);
xa_init(&sess->tree_conns);
xa_init(&sess->ksmbd_chann_list);
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index 586f948976c8..14df83c20557 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -93,7 +93,8 @@ static inline int check_conn_state(struct ksmbd_work *work)
{
struct smb_hdr *rsp_hdr;
- if (ksmbd_conn_exiting(work) || ksmbd_conn_need_reconnect(work)) {
+ if (ksmbd_conn_exiting(work->conn) ||
+ ksmbd_conn_need_reconnect(work->conn)) {
rsp_hdr = work->response_buf;
rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
return 1;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d39412f1ddb2..ef4550152721 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -265,7 +265,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp = smb2_get_msg(work->response_buf);
- WARN_ON(ksmbd_conn_good(work));
+ WARN_ON(ksmbd_conn_good(conn));
rsp->StructureSize = cpu_to_le16(65);
ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
@@ -295,7 +295,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
conn->use_spnego = true;
- ksmbd_conn_set_need_negotiate(work);
+ ksmbd_conn_set_need_negotiate(conn);
return 0;
}
@@ -574,7 +574,7 @@ int smb2_check_user_session(struct ksmbd_work *work)
cmd == SMB2_SESSION_SETUP_HE)
return 0;
- if (!ksmbd_conn_good(work))
+ if (!ksmbd_conn_good(conn))
return -EIO;
sess_id = le64_to_cpu(req_hdr->SessionId);
@@ -625,7 +625,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
prev_sess->state = SMB2_SESSION_EXPIRED;
xa_for_each(&prev_sess->ksmbd_chann_list, index, chann)
- chann->conn->status = KSMBD_SESS_EXITING;
+ ksmbd_conn_set_exiting(chann->conn);
}
/**
@@ -1081,7 +1081,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Received negotiate request\n");
conn->need_neg = false;
- if (ksmbd_conn_good(work)) {
+ if (ksmbd_conn_good(conn)) {
pr_err("conn->tcp_status is already in CifsGood State\n");
work->send_no_response = 1;
return rc;
@@ -1236,7 +1236,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
}
conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode);
- ksmbd_conn_set_need_negotiate(work);
+ ksmbd_conn_set_need_negotiate(conn);
err_out:
if (rc < 0)
@@ -1658,6 +1658,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
rsp->SecurityBufferLength = 0;
inc_rfc1001_len(work->response_buf, 9);
+ ksmbd_conn_lock(conn);
if (!req->hdr.SessionId) {
sess = ksmbd_smb2_session_create();
if (!sess) {
@@ -1705,6 +1706,12 @@ int smb2_sess_setup(struct ksmbd_work *work)
goto out_err;
}
+ if (ksmbd_conn_need_reconnect(conn)) {
+ rc = -EFAULT;
+ sess = NULL;
+ goto out_err;
+ }
+
if (ksmbd_session_lookup(conn, sess_id)) {
rc = -EACCES;
goto out_err;
@@ -1729,12 +1736,20 @@ int smb2_sess_setup(struct ksmbd_work *work)
rc = -ENOENT;
goto out_err;
}
+
+ if (sess->state == SMB2_SESSION_EXPIRED) {
+ rc = -EFAULT;
+ goto out_err;
+ }
+
+ if (ksmbd_conn_need_reconnect(conn)) {
+ rc = -EFAULT;
+ sess = NULL;
+ goto out_err;
+ }
}
work->sess = sess;
- if (sess->state == SMB2_SESSION_EXPIRED)
- sess->state = SMB2_SESSION_IN_PROGRESS;
-
negblob_off = le16_to_cpu(req->SecurityBufferOffset);
negblob_len = le16_to_cpu(req->SecurityBufferLength);
if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) ||
@@ -1764,8 +1779,10 @@ int smb2_sess_setup(struct ksmbd_work *work)
goto out_err;
}
- ksmbd_conn_set_good(work);
- sess->state = SMB2_SESSION_VALID;
+ if (!ksmbd_conn_need_reconnect(conn)) {
+ ksmbd_conn_set_good(conn);
+ sess->state = SMB2_SESSION_VALID;
+ }
kfree(sess->Preauth_HashValue);
sess->Preauth_HashValue = NULL;
} else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
@@ -1787,8 +1804,10 @@ int smb2_sess_setup(struct ksmbd_work *work)
if (rc)
goto out_err;
- ksmbd_conn_set_good(work);
- sess->state = SMB2_SESSION_VALID;
+ if (!ksmbd_conn_need_reconnect(conn)) {
+ ksmbd_conn_set_good(conn);
+ sess->state = SMB2_SESSION_VALID;
+ }
if (conn->binding) {
struct preauth_session *preauth_sess;
@@ -1856,14 +1875,13 @@ int smb2_sess_setup(struct ksmbd_work *work)
if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION)
try_delay = true;
- xa_erase(&conn->sessions, sess->id);
- ksmbd_session_destroy(sess);
- work->sess = NULL;
+ sess->state = SMB2_SESSION_EXPIRED;
if (try_delay)
ssleep(5);
}
}
+ ksmbd_conn_unlock(conn);
return rc;
}
@@ -2087,21 +2105,24 @@ int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_session *sess = work->sess;
+ struct ksmbd_session *sess;
+ struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
rsp->StructureSize = cpu_to_le16(4);
inc_rfc1001_len(work->response_buf, 4);
ksmbd_debug(SMB, "request\n");
- /* setting CifsExiting here may race with start_tcp_sess */
- ksmbd_conn_set_need_reconnect(work);
+ ksmbd_conn_set_need_reconnect(conn);
ksmbd_close_session_fds(work);
ksmbd_conn_wait_idle(conn);
+ /*
+ * Re-lookup session to validate if session is deleted
+ * while waiting request complete
+ */
+ sess = ksmbd_session_lookup(conn, le64_to_cpu(req->hdr.SessionId));
if (ksmbd_tree_conn_session_logoff(sess)) {
- struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
-
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
smb2_set_err_rsp(work);
@@ -2113,9 +2134,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_free_user(sess->user);
sess->user = NULL;
-
- /* let start_tcp_sess free connection info now */
- ksmbd_conn_set_need_negotiate(work);
+ ksmbd_conn_set_need_negotiate(conn);
return 0;
}
diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
index 20e85e2701f2..eff7a1d793f0 100644
--- a/fs/ksmbd/transport_tcp.c
+++ b/fs/ksmbd/transport_tcp.c
@@ -333,7 +333,7 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
if (length == -EINTR) {
total_read = -ESHUTDOWN;
break;
- } else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
+ } else if (ksmbd_conn_need_reconnect(conn)) {
total_read = -EAGAIN;
break;
} else if (length == -ERESTARTSYS || length == -EAGAIN) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 089/154] ksmbd: destroy expired sessions
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (87 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 088/154] ksmbd: fix racy issue from session setup and logoff Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 090/154] ksmbd: block asynchronous requests when making a delay on session setup Namjae Jeon
` (65 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit ea174a91893956450510945a0c5d1a10b5323656 ]
client can indefinitely send smb2 session setup requests with
the SessionId set to 0, thus indefinitely spawning new sessions,
and causing indefinite memory usage. This patch limit to the number
of sessions using expired timeout and session state.
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20478
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/user_session.c | 68 ++++++++++++++++++++----------------
fs/ksmbd/mgmt/user_session.h | 1 +
fs/ksmbd/smb2pdu.c | 1 +
fs/ksmbd/smb2pdu.h | 2 ++
4 files changed, 41 insertions(+), 31 deletions(-)
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index 68d40025cfbf..3840de7773b9 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -165,70 +165,73 @@ static struct ksmbd_session *__session_lookup(unsigned long long id)
struct ksmbd_session *sess;
hash_for_each_possible(sessions_table, sess, hlist, id) {
- if (id == sess->id)
+ if (id == sess->id) {
+ sess->last_active = jiffies;
return sess;
+ }
}
return NULL;
}
+static void ksmbd_expire_session(struct ksmbd_conn *conn)
+{
+ unsigned long id;
+ struct ksmbd_session *sess;
+
+ xa_for_each(&conn->sessions, id, sess) {
+ if (sess->state != SMB2_SESSION_VALID ||
+ time_after(jiffies,
+ sess->last_active + SMB2_SESSION_TIMEOUT)) {
+ xa_erase(&conn->sessions, sess->id);
+ ksmbd_session_destroy(sess);
+ continue;
+ }
+ }
+}
+
int ksmbd_session_register(struct ksmbd_conn *conn,
struct ksmbd_session *sess)
{
sess->dialect = conn->dialect;
memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
+ ksmbd_expire_session(conn);
return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL));
}
-static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
+static void ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
{
struct channel *chann;
chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
if (!chann)
- return -ENOENT;
+ return;
kfree(chann);
-
- return 0;
}
void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
{
struct ksmbd_session *sess;
+ unsigned long id;
- if (conn->binding) {
- int bkt;
-
- down_write(&sessions_table_lock);
- hash_for_each(sessions_table, bkt, sess, hlist) {
- if (!ksmbd_chann_del(conn, sess)) {
- up_write(&sessions_table_lock);
- goto sess_destroy;
- }
+ xa_for_each(&conn->sessions, id, sess) {
+ ksmbd_chann_del(conn, sess);
+ if (xa_empty(&sess->ksmbd_chann_list)) {
+ xa_erase(&conn->sessions, sess->id);
+ ksmbd_session_destroy(sess);
}
- up_write(&sessions_table_lock);
- } else {
- unsigned long id;
-
- xa_for_each(&conn->sessions, id, sess) {
- if (!ksmbd_chann_del(conn, sess))
- goto sess_destroy;
- }
- }
-
- return;
-
-sess_destroy:
- if (xa_empty(&sess->ksmbd_chann_list)) {
- xa_erase(&conn->sessions, sess->id);
- ksmbd_session_destroy(sess);
}
}
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
unsigned long long id)
{
- return xa_load(&conn->sessions, id);
+ struct ksmbd_session *sess;
+
+ sess = xa_load(&conn->sessions, id);
+ if (sess)
+ sess->last_active = jiffies;
+ return sess;
}
struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
@@ -237,6 +240,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
down_read(&sessions_table_lock);
sess = __session_lookup(id);
+ if (sess)
+ sess->last_active = jiffies;
up_read(&sessions_table_lock);
return sess;
@@ -315,6 +320,7 @@ static struct ksmbd_session *__session_create(int protocol)
if (ksmbd_init_file_table(&sess->file_table))
goto error;
+ sess->last_active = jiffies;
sess->state = SMB2_SESSION_IN_PROGRESS;
set_session_flag(sess, protocol);
xa_init(&sess->tree_conns);
diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h
index b6a9e7a6aae4..f99d475b28db 100644
--- a/fs/ksmbd/mgmt/user_session.h
+++ b/fs/ksmbd/mgmt/user_session.h
@@ -59,6 +59,7 @@ struct ksmbd_session {
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
struct ksmbd_file_table file_table;
+ unsigned long last_active;
};
static inline int test_session_flag(struct ksmbd_session *sess, int bit)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index ef4550152721..2ebd252894de 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1875,6 +1875,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION)
try_delay = true;
+ sess->last_active = jiffies;
sess->state = SMB2_SESSION_EXPIRED;
if (try_delay)
ssleep(5);
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index 9cde1f8e8428..a774889e0aa5 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -619,6 +619,8 @@ struct create_context {
__u8 Buffer[0];
} __packed;
+#define SMB2_SESSION_TIMEOUT (10 * HZ)
+
struct create_durable_req_v2 {
struct create_context ccontext;
__u8 Name[8];
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 090/154] ksmbd: block asynchronous requests when making a delay on session setup
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (88 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 089/154] ksmbd: destroy expired sessions Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 091/154] ksmbd: fix racy issue from smb2 close and logoff with multichannel Namjae Jeon
` (64 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit b096d97f47326b1e2dbdef1c91fab69ffda54d17 ]
ksmbd make a delay of 5 seconds on session setup to avoid dictionary
attacks. But the 5 seconds delay can be bypassed by using asynchronous
requests. This patch block all requests on current connection when
making a delay on sesstion setup failure.
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20482
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 2ebd252894de..29c951c29279 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1877,8 +1877,11 @@ int smb2_sess_setup(struct ksmbd_work *work)
sess->last_active = jiffies;
sess->state = SMB2_SESSION_EXPIRED;
- if (try_delay)
+ if (try_delay) {
+ ksmbd_conn_set_need_reconnect(conn);
ssleep(5);
+ ksmbd_conn_set_need_negotiate(conn);
+ }
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 091/154] ksmbd: fix racy issue from smb2 close and logoff with multichannel
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (89 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 090/154] ksmbd: block asynchronous requests when making a delay on session setup Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 092/154] ksmbd: fix racy issue under cocurrent smb2 tree disconnect Namjae Jeon
` (63 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit abcc506a9a71976a8b4c9bf3ee6efd13229c1e19 ]
When smb client send concurrent smb2 close and logoff request
with multichannel connection, It can cause racy issue. logoff request
free tcon and can cause UAF issues in smb2 close. When receiving logoff
request with multichannel, ksmbd should wait until all remaning requests
complete as well as ones in the current connection, and then make
session expired.
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20796 ZDI-CAN-20595
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 54 +++++++++++++++++++++++++++---------
fs/ksmbd/connection.h | 19 +++++++++++--
fs/ksmbd/mgmt/tree_connect.c | 3 ++
fs/ksmbd/mgmt/user_session.c | 36 ++++++++++++++++++++----
fs/ksmbd/smb2pdu.c | 21 +++++++-------
5 files changed, 101 insertions(+), 32 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index c47b80759603..4a9672d3ef49 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -20,7 +20,7 @@ static DEFINE_MUTEX(init_lock);
static struct ksmbd_conn_ops default_conn_ops;
LIST_HEAD(conn_list);
-DEFINE_RWLOCK(conn_list_lock);
+DECLARE_RWSEM(conn_list_lock);
/**
* ksmbd_conn_free() - free resources of the connection instance
@@ -32,9 +32,9 @@ DEFINE_RWLOCK(conn_list_lock);
*/
void ksmbd_conn_free(struct ksmbd_conn *conn)
{
- write_lock(&conn_list_lock);
+ down_write(&conn_list_lock);
list_del(&conn->conns_list);
- write_unlock(&conn_list_lock);
+ up_write(&conn_list_lock);
xa_destroy(&conn->sessions);
kvfree(conn->request_buf);
@@ -84,9 +84,9 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
spin_lock_init(&conn->llist_lock);
INIT_LIST_HEAD(&conn->lock_list);
- write_lock(&conn_list_lock);
+ down_write(&conn_list_lock);
list_add(&conn->conns_list, &conn_list);
- write_unlock(&conn_list_lock);
+ up_write(&conn_list_lock);
return conn;
}
@@ -95,7 +95,7 @@ bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
struct ksmbd_conn *t;
bool ret = false;
- read_lock(&conn_list_lock);
+ down_read(&conn_list_lock);
list_for_each_entry(t, &conn_list, conns_list) {
if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))
continue;
@@ -103,7 +103,7 @@ bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
ret = true;
break;
}
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
return ret;
}
@@ -157,9 +157,37 @@ void ksmbd_conn_unlock(struct ksmbd_conn *conn)
mutex_unlock(&conn->srv_mutex);
}
-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
+void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
{
+ struct ksmbd_conn *conn;
+
+ down_read(&conn_list_lock);
+ list_for_each_entry(conn, &conn_list, conns_list) {
+ if (conn->binding || xa_load(&conn->sessions, sess_id))
+ WRITE_ONCE(conn->status, status);
+ }
+ up_read(&conn_list_lock);
+}
+
+void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
+{
+ struct ksmbd_conn *bind_conn;
+
wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
+
+ down_read(&conn_list_lock);
+ list_for_each_entry(bind_conn, &conn_list, conns_list) {
+ if (bind_conn == conn)
+ continue;
+
+ if ((bind_conn->binding || xa_load(&bind_conn->sessions, sess_id)) &&
+ !ksmbd_conn_releasing(bind_conn) &&
+ atomic_read(&bind_conn->req_running)) {
+ wait_event(bind_conn->req_running_q,
+ atomic_read(&bind_conn->req_running) == 0);
+ }
+ }
+ up_read(&conn_list_lock);
}
int ksmbd_conn_write(struct ksmbd_work *work)
@@ -361,10 +389,10 @@ int ksmbd_conn_handler_loop(void *p)
}
out:
+ ksmbd_conn_set_releasing(conn);
/* Wait till all reference dropped to the Server object*/
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
-
if (IS_ENABLED(CONFIG_UNICODE))
utf8_unload(conn->um);
unload_nls(conn->local_nls);
@@ -408,7 +436,7 @@ static void stop_sessions(void)
struct ksmbd_transport *t;
again:
- read_lock(&conn_list_lock);
+ down_read(&conn_list_lock);
list_for_each_entry(conn, &conn_list, conns_list) {
struct task_struct *task;
@@ -419,12 +447,12 @@ static void stop_sessions(void)
task->comm, task_pid_nr(task));
ksmbd_conn_set_exiting(conn);
if (t->ops->shutdown) {
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
t->ops->shutdown(t);
- read_lock(&conn_list_lock);
+ down_read(&conn_list_lock);
}
}
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
if (!list_empty(&conn_list)) {
schedule_timeout_interruptible(HZ / 10); /* 100ms */
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index 98bb5f199fa2..ad8dfaa48ffb 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -26,7 +26,8 @@ enum {
KSMBD_SESS_GOOD,
KSMBD_SESS_EXITING,
KSMBD_SESS_NEED_RECONNECT,
- KSMBD_SESS_NEED_NEGOTIATE
+ KSMBD_SESS_NEED_NEGOTIATE,
+ KSMBD_SESS_RELEASING
};
struct ksmbd_stats {
@@ -140,10 +141,10 @@ struct ksmbd_transport {
#define KSMBD_TCP_PEER_SOCKADDR(c) ((struct sockaddr *)&((c)->peer_addr))
extern struct list_head conn_list;
-extern rwlock_t conn_list_lock;
+extern struct rw_semaphore conn_list_lock;
bool ksmbd_conn_alive(struct ksmbd_conn *conn);
-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);
+void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn);
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
@@ -191,6 +192,11 @@ static inline bool ksmbd_conn_exiting(struct ksmbd_conn *conn)
return READ_ONCE(conn->status) == KSMBD_SESS_EXITING;
}
+static inline bool ksmbd_conn_releasing(struct ksmbd_conn *conn)
+{
+ return READ_ONCE(conn->status) == KSMBD_SESS_RELEASING;
+}
+
static inline void ksmbd_conn_set_new(struct ksmbd_conn *conn)
{
WRITE_ONCE(conn->status, KSMBD_SESS_NEW);
@@ -215,4 +221,11 @@ static inline void ksmbd_conn_set_exiting(struct ksmbd_conn *conn)
{
WRITE_ONCE(conn->status, KSMBD_SESS_EXITING);
}
+
+static inline void ksmbd_conn_set_releasing(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_RELEASING);
+}
+
+void ksmbd_all_conn_set_status(u64 sess_id, u32 status);
#endif /* __CONNECTION_H__ */
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index 8ce17b3fb8da..aa9c138d5851 100644
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -129,6 +129,9 @@ int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
struct ksmbd_tree_connect *tc;
unsigned long id;
+ if (!sess)
+ return -EINVAL;
+
xa_for_each(&sess->tree_conns, id, tc)
ret |= ksmbd_tree_conn_disconnect(sess, tc);
xa_destroy(&sess->tree_conns);
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index 3840de7773b9..8a5dcab05614 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -144,10 +144,6 @@ void ksmbd_session_destroy(struct ksmbd_session *sess)
if (!sess)
return;
- down_write(&sessions_table_lock);
- hash_del(&sess->hlist);
- up_write(&sessions_table_lock);
-
if (sess->user)
ksmbd_free_user(sess->user);
@@ -178,15 +174,18 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
unsigned long id;
struct ksmbd_session *sess;
+ down_write(&sessions_table_lock);
xa_for_each(&conn->sessions, id, sess) {
if (sess->state != SMB2_SESSION_VALID ||
time_after(jiffies,
sess->last_active + SMB2_SESSION_TIMEOUT)) {
xa_erase(&conn->sessions, sess->id);
+ hash_del(&sess->hlist);
ksmbd_session_destroy(sess);
continue;
}
}
+ up_write(&sessions_table_lock);
}
int ksmbd_session_register(struct ksmbd_conn *conn,
@@ -198,15 +197,16 @@ int ksmbd_session_register(struct ksmbd_conn *conn,
return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL));
}
-static void ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
+static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
{
struct channel *chann;
chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
if (!chann)
- return;
+ return -ENOENT;
kfree(chann);
+ return 0;
}
void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
@@ -214,13 +214,37 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
struct ksmbd_session *sess;
unsigned long id;
+ down_write(&sessions_table_lock);
+ if (conn->binding) {
+ int bkt;
+ struct hlist_node *tmp;
+
+ hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) {
+ if (!ksmbd_chann_del(conn, sess) &&
+ xa_empty(&sess->ksmbd_chann_list)) {
+ hash_del(&sess->hlist);
+ ksmbd_session_destroy(sess);
+ }
+ }
+ }
+
xa_for_each(&conn->sessions, id, sess) {
+ unsigned long chann_id;
+ struct channel *chann;
+
+ xa_for_each(&sess->ksmbd_chann_list, chann_id, chann) {
+ if (chann->conn != conn)
+ ksmbd_conn_set_exiting(chann->conn);
+ }
+
ksmbd_chann_del(conn, sess);
if (xa_empty(&sess->ksmbd_chann_list)) {
xa_erase(&conn->sessions, sess->id);
+ hash_del(&sess->hlist);
ksmbd_session_destroy(sess);
}
}
+ up_write(&sessions_table_lock);
}
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 29c951c29279..99f61aae0c95 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2111,21 +2111,22 @@ int smb2_session_logoff(struct ksmbd_work *work)
struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess;
struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
+ u64 sess_id = le64_to_cpu(req->hdr.SessionId);
rsp->StructureSize = cpu_to_le16(4);
inc_rfc1001_len(work->response_buf, 4);
ksmbd_debug(SMB, "request\n");
- ksmbd_conn_set_need_reconnect(conn);
+ ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT);
ksmbd_close_session_fds(work);
- ksmbd_conn_wait_idle(conn);
+ ksmbd_conn_wait_idle(conn, sess_id);
/*
* Re-lookup session to validate if session is deleted
* while waiting request complete
*/
- sess = ksmbd_session_lookup(conn, le64_to_cpu(req->hdr.SessionId));
+ sess = ksmbd_session_lookup_all(conn, sess_id);
if (ksmbd_tree_conn_session_logoff(sess)) {
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -2138,7 +2139,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_free_user(sess->user);
sess->user = NULL;
- ksmbd_conn_set_need_negotiate(conn);
+ ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE);
return 0;
}
@@ -6892,7 +6893,7 @@ int smb2_lock(struct ksmbd_work *work)
nolock = 1;
/* check locks in connection list */
- read_lock(&conn_list_lock);
+ down_read(&conn_list_lock);
list_for_each_entry(conn, &conn_list, conns_list) {
spin_lock(&conn->llist_lock);
list_for_each_entry_safe(cmp_lock, tmp2, &conn->lock_list, clist) {
@@ -6909,7 +6910,7 @@ int smb2_lock(struct ksmbd_work *work)
list_del(&cmp_lock->flist);
list_del(&cmp_lock->clist);
spin_unlock(&conn->llist_lock);
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
locks_free_lock(cmp_lock->fl);
kfree(cmp_lock);
@@ -6931,7 +6932,7 @@ int smb2_lock(struct ksmbd_work *work)
cmp_lock->start > smb_lock->start &&
cmp_lock->start < smb_lock->end) {
spin_unlock(&conn->llist_lock);
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
pr_err("previous lock conflict with zero byte lock range\n");
goto out;
}
@@ -6940,7 +6941,7 @@ int smb2_lock(struct ksmbd_work *work)
smb_lock->start > cmp_lock->start &&
smb_lock->start < cmp_lock->end) {
spin_unlock(&conn->llist_lock);
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
pr_err("current lock conflict with zero byte lock range\n");
goto out;
}
@@ -6951,14 +6952,14 @@ int smb2_lock(struct ksmbd_work *work)
cmp_lock->end >= smb_lock->end)) &&
!cmp_lock->zero_len && !smb_lock->zero_len) {
spin_unlock(&conn->llist_lock);
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
pr_err("Not allow lock operation on exclusive lock range\n");
goto out;
}
}
spin_unlock(&conn->llist_lock);
}
- read_unlock(&conn_list_lock);
+ up_read(&conn_list_lock);
out_check_cl:
if (smb_lock->fl->fl_type == F_UNLCK && nolock) {
pr_err("Try to unlock nolocked range\n");
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 092/154] ksmbd: fix racy issue under cocurrent smb2 tree disconnect
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (90 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 091/154] ksmbd: fix racy issue from smb2 close and logoff with multichannel Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 093/154] ksmbd: fix uninitialized pointer read in ksmbd_vfs_rename() Namjae Jeon
` (62 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit 30210947a343b6b3ca13adc9bfc88e1543e16dd5 ]
There is UAF issue under cocurrent smb2 tree disconnect.
This patch introduce TREE_CONN_EXPIRE flags for tcon to avoid cocurrent
access.
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20592
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/tree_connect.c | 10 +++++++++-
fs/ksmbd/mgmt/tree_connect.h | 3 +++
fs/ksmbd/smb2pdu.c | 3 ++-
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index aa9c138d5851..f07a05f37651 100644
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -109,7 +109,15 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
unsigned int id)
{
- return xa_load(&sess->tree_conns, id);
+ struct ksmbd_tree_connect *tcon;
+
+ tcon = xa_load(&sess->tree_conns, id);
+ if (tcon) {
+ if (test_bit(TREE_CONN_EXPIRE, &tcon->status))
+ tcon = NULL;
+ }
+
+ return tcon;
}
struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
diff --git a/fs/ksmbd/mgmt/tree_connect.h b/fs/ksmbd/mgmt/tree_connect.h
index 0f97ddc1e39c..700df36cf3e3 100644
--- a/fs/ksmbd/mgmt/tree_connect.h
+++ b/fs/ksmbd/mgmt/tree_connect.h
@@ -14,6 +14,8 @@ struct ksmbd_share_config;
struct ksmbd_user;
struct ksmbd_conn;
+#define TREE_CONN_EXPIRE 1
+
struct ksmbd_tree_connect {
int id;
@@ -25,6 +27,7 @@ struct ksmbd_tree_connect {
int maximal_access;
bool posix_extensions;
+ unsigned long status;
};
struct ksmbd_tree_conn_status {
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 99f61aae0c95..c492e7f73a7e 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2083,11 +2083,12 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
ksmbd_debug(SMB, "request\n");
- if (!tcon) {
+ if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
struct smb2_tree_disconnect_req *req =
smb2_get_msg(work->request_buf);
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
smb2_set_err_rsp(work);
return 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 093/154] ksmbd: fix uninitialized pointer read in ksmbd_vfs_rename()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (91 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 092/154] ksmbd: fix racy issue under cocurrent smb2 tree disconnect Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 094/154] ksmbd: fix uninitialized pointer read in smb2_create_link() Namjae Jeon
` (61 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Coverity Scan, Steve French
[ Upstream commit 48b47f0caaa8a9f05ed803cb4f335fa3a7bfc622 ]
Uninitialized rd.delegated_inode can be used in vfs_rename().
Fix this by setting rd.delegated_inode to NULL to avoid the uninitialized
read.
Fixes: 74d7970febf7 ("ksmbd: fix racy issue from using ->d_parent and ->d_name")
Reported-by: Coverity Scan <scan-admin@coverity.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index e31584ad80fa..8956131df631 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -743,6 +743,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
rd.new_dir = new_path.dentry->d_inode,
rd.new_dentry = new_dentry,
rd.flags = flags,
+ rd.delegated_inode = NULL,
err = vfs_rename(&rd);
if (err)
ksmbd_debug(VFS, "vfs_rename failed err %d\n", err);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 094/154] ksmbd: fix uninitialized pointer read in smb2_create_link()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (92 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 093/154] ksmbd: fix uninitialized pointer read in ksmbd_vfs_rename() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 095/154] ksmbd: fix multiple out-of-bounds read during context decoding Namjae Jeon
` (60 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Coverity Scan, Steve French
[ Upstream commit df14afeed2e6c1bbadef7d2f9c46887bbd6d8d94 ]
There is a case that file_present is true and path is uninitialized.
This patch change file_present is set to false by default and set to
true when patch is initialized.
Fixes: 74d7970febf7 ("ksmbd: fix racy issue from using ->d_parent and ->d_name")
Reported-by: Coverity Scan <scan-admin@coverity.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index c492e7f73a7e..0e6f39f05af2 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -5529,7 +5529,7 @@ static int smb2_create_link(struct ksmbd_work *work,
{
char *link_name = NULL, *target_name = NULL, *pathname = NULL;
struct path path;
- bool file_present = true;
+ bool file_present = false;
int rc;
if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -5562,8 +5562,8 @@ static int smb2_create_link(struct ksmbd_work *work,
if (rc) {
if (rc != -ENOENT)
goto out;
- file_present = false;
- }
+ } else
+ file_present = true;
if (file_info->ReplaceIfExists) {
if (file_present) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 095/154] ksmbd: fix multiple out-of-bounds read during context decoding
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (93 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 094/154] ksmbd: fix uninitialized pointer read in smb2_create_link() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 096/154] ksmbd: fix UAF issue from opinfo->conn Namjae Jeon
` (59 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Kuan-Ting Chen, Namjae Jeon, Steve French
From: Kuan-Ting Chen <h3xrabbit@gmail.com>
[ Upstream commit 0512a5f89e1fae74251fde6893ff634f1c96c6fb ]
Check the remaining data length before accessing the context structure
to ensure that the entire structure is contained within the packet.
Additionally, since the context data length `ctxt_len` has already been
checked against the total packet length `len_of_ctxts`, update the
comparison to use `ctxt_len`.
Cc: stable@vger.kernel.org
Signed-off-by: Kuan-Ting Chen <h3xrabbit@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 53 +++++++++++++++++++++++++++++-----------------
1 file changed, 34 insertions(+), 19 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 0e6f39f05af2..62bcc440ad31 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -879,13 +879,14 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
struct smb2_preauth_neg_context *pneg_ctxt,
- int len_of_ctxts)
+ int ctxt_len)
{
/*
* sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
* which may not be present. Only check for used HashAlgorithms[1].
*/
- if (len_of_ctxts < 6)
+ if (ctxt_len <
+ sizeof(struct smb2_neg_context) + 6)
return STATUS_INVALID_PARAMETER;
if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
@@ -897,15 +898,23 @@ static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
struct smb2_encryption_neg_context *pneg_ctxt,
- int len_of_ctxts)
+ int ctxt_len)
{
- int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
- int i, cphs_size = cph_cnt * sizeof(__le16);
+ int cph_cnt;
+ int i, cphs_size;
+
+ if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) {
+ pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n");
+ return;
+ }
conn->cipher_type = 0;
+ cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
+ cphs_size = cph_cnt * sizeof(__le16);
+
if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
- len_of_ctxts) {
+ ctxt_len) {
pr_err("Invalid cipher count(%d)\n", cph_cnt);
return;
}
@@ -953,15 +962,22 @@ static void decode_compress_ctxt(struct ksmbd_conn *conn,
static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
struct smb2_signing_capabilities *pneg_ctxt,
- int len_of_ctxts)
+ int ctxt_len)
{
- int sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
- int i, sign_alos_size = sign_algo_cnt * sizeof(__le16);
+ int sign_algo_cnt;
+ int i, sign_alos_size;
+
+ if (sizeof(struct smb2_signing_capabilities) > ctxt_len) {
+ pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n");
+ return;
+ }
conn->signing_negotiated = false;
+ sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
+ sign_alos_size = sign_algo_cnt * sizeof(__le16);
if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
- len_of_ctxts) {
+ ctxt_len) {
pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
return;
}
@@ -999,18 +1015,16 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
len_of_ctxts = len_of_smb - offset;
while (i++ < neg_ctxt_cnt) {
- int clen;
-
- /* check that offset is not beyond end of SMB */
- if (len_of_ctxts == 0)
- break;
+ int clen, ctxt_len;
if (len_of_ctxts < sizeof(struct smb2_neg_context))
break;
pctx = (struct smb2_neg_context *)((char *)pctx + offset);
clen = le16_to_cpu(pctx->DataLength);
- if (clen + sizeof(struct smb2_neg_context) > len_of_ctxts)
+ ctxt_len = clen + sizeof(struct smb2_neg_context);
+
+ if (ctxt_len > len_of_ctxts)
break;
if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
@@ -1021,7 +1035,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
status = decode_preauth_ctxt(conn,
(struct smb2_preauth_neg_context *)pctx,
- len_of_ctxts);
+ ctxt_len);
if (status != STATUS_SUCCESS)
break;
} else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
@@ -1032,7 +1046,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
decode_encrypt_ctxt(conn,
(struct smb2_encryption_neg_context *)pctx,
- len_of_ctxts);
+ ctxt_len);
} else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
ksmbd_debug(SMB,
"deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
@@ -1051,9 +1065,10 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
} else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
ksmbd_debug(SMB,
"deassemble SMB2_SIGNING_CAPABILITIES context\n");
+
decode_sign_cap_ctxt(conn,
(struct smb2_signing_capabilities *)pctx,
- len_of_ctxts);
+ ctxt_len);
}
/* offsets must be 8 byte aligned */
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 096/154] ksmbd: fix UAF issue from opinfo->conn
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (94 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 095/154] ksmbd: fix multiple out-of-bounds read during context decoding Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 097/154] ksmbd: call putname after using the last component Namjae Jeon
` (58 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Per Forlin, Steve French
[ Upstream commit 36322523dddb11107e9f7f528675a0dec2536103 ]
If opinfo->conn is another connection and while ksmbd send oplock break
request to cient on current connection, The connection for opinfo->conn
can be disconnect and conn could be freed. When sending oplock break
request, this ksmbd_conn can be used and cause user-after-free issue.
When getting opinfo from the list, ksmbd check connection is being
released. If it is not released, Increase ->r_count to wait that connection
is freed.
Cc: stable@vger.kernel.org
Reported-by: Per Forlin <per.forlin@axis.com>
Tested-by: Per Forlin <per.forlin@axis.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/oplock.c | 72 +++++++++++++++++++++++++++++++----------------
1 file changed, 47 insertions(+), 25 deletions(-)
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index 919c598a9d66..28c7f2193fb3 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -157,13 +157,42 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
rcu_read_lock();
opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,
op_entry);
- if (opinfo && !atomic_inc_not_zero(&opinfo->refcount))
- opinfo = NULL;
+ if (opinfo) {
+ if (!atomic_inc_not_zero(&opinfo->refcount))
+ opinfo = NULL;
+ else {
+ atomic_inc(&opinfo->conn->r_count);
+ if (ksmbd_conn_releasing(opinfo->conn)) {
+ atomic_dec(&opinfo->conn->r_count);
+ atomic_dec(&opinfo->refcount);
+ opinfo = NULL;
+ }
+ }
+ }
+
rcu_read_unlock();
return opinfo;
}
+static void opinfo_conn_put(struct oplock_info *opinfo)
+{
+ struct ksmbd_conn *conn;
+
+ if (!opinfo)
+ return;
+
+ conn = opinfo->conn;
+ /*
+ * Checking waitqueue to dropping pending requests on
+ * disconnection. waitqueue_active is safe because it
+ * uses atomic operation for condition.
+ */
+ if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+ wake_up(&conn->r_count_q);
+ opinfo_put(opinfo);
+}
+
void opinfo_put(struct oplock_info *opinfo)
{
if (!atomic_dec_and_test(&opinfo->refcount))
@@ -666,13 +695,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
out:
ksmbd_free_work_struct(work);
- /*
- * Checking waitqueue to dropping pending requests on
- * disconnection. waitqueue_active is safe because it
- * uses atomic operation for condition.
- */
- if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
- wake_up(&conn->r_count_q);
}
/**
@@ -706,7 +728,6 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
work->conn = conn;
work->sess = opinfo->sess;
- atomic_inc(&conn->r_count);
if (opinfo->op_state == OPLOCK_ACK_WAIT) {
INIT_WORK(&work->work, __smb2_oplock_break_noti);
ksmbd_queue_work(work);
@@ -776,13 +797,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
out:
ksmbd_free_work_struct(work);
- /*
- * Checking waitqueue to dropping pending requests on
- * disconnection. waitqueue_active is safe because it
- * uses atomic operation for condition.
- */
- if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
- wake_up(&conn->r_count_q);
}
/**
@@ -822,7 +836,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
work->conn = conn;
work->sess = opinfo->sess;
- atomic_inc(&conn->r_count);
if (opinfo->op_state == OPLOCK_ACK_WAIT) {
list_for_each_safe(tmp, t, &opinfo->interim_list) {
struct ksmbd_work *in_work;
@@ -1144,8 +1157,10 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
}
prev_opinfo = opinfo_get_list(ci);
if (!prev_opinfo ||
- (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx))
+ (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) {
+ opinfo_conn_put(prev_opinfo);
goto set_lev;
+ }
prev_op_has_lease = prev_opinfo->is_lease;
if (prev_op_has_lease)
prev_op_state = prev_opinfo->o_lease->state;
@@ -1153,19 +1168,19 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
if (share_ret < 0 &&
prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
err = share_ret;
- opinfo_put(prev_opinfo);
+ opinfo_conn_put(prev_opinfo);
goto err_out;
}
if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
- opinfo_put(prev_opinfo);
+ opinfo_conn_put(prev_opinfo);
goto op_break_not_needed;
}
list_add(&work->interim_entry, &prev_opinfo->interim_list);
err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II);
- opinfo_put(prev_opinfo);
+ opinfo_conn_put(prev_opinfo);
if (err == -ENOENT)
goto set_lev;
/* Check all oplock was freed by close */
@@ -1228,14 +1243,14 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work,
return;
if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
- opinfo_put(brk_opinfo);
+ opinfo_conn_put(brk_opinfo);
return;
}
brk_opinfo->open_trunc = is_trunc;
list_add(&work->interim_entry, &brk_opinfo->interim_list);
oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II);
- opinfo_put(brk_opinfo);
+ opinfo_conn_put(brk_opinfo);
}
/**
@@ -1263,6 +1278,13 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {
if (!atomic_inc_not_zero(&brk_op->refcount))
continue;
+
+ atomic_inc(&brk_op->conn->r_count);
+ if (ksmbd_conn_releasing(brk_op->conn)) {
+ atomic_dec(&brk_op->conn->r_count);
+ continue;
+ }
+
rcu_read_unlock();
if (brk_op->is_lease && (brk_op->o_lease->state &
(~(SMB2_LEASE_READ_CACHING_LE |
@@ -1292,7 +1314,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
brk_op->open_trunc = is_trunc;
oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE);
next:
- opinfo_put(brk_op);
+ opinfo_conn_put(brk_op);
rcu_read_lock();
}
rcu_read_unlock();
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 097/154] ksmbd: call putname after using the last component
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (95 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 096/154] ksmbd: fix UAF issue from opinfo->conn Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 098/154] ksmbd: fix out-of-bound read in deassemble_neg_contexts() Namjae Jeon
` (57 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 6fe55c2799bc29624770c26f98ba7b06214f43e0 ]
last component point filename struct. Currently putname is called after
vfs_path_parent_lookup(). And then last component is used for
lookup_one_qstr_excl(). name in last component is freed by previous
calling putname(). And It cause file lookup failure when testing
generic/464 test of xfstest.
Fixes: 74d7970febf7 ("ksmbd: fix racy issue from using ->d_parent and ->d_name")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 8956131df631..a48d53c4587c 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -86,12 +86,14 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
err = vfs_path_parent_lookup(filename, flags,
&parent_path, &last, &type,
root_share_path);
- putname(filename);
- if (err)
+ if (err) {
+ putname(filename);
return err;
+ }
if (unlikely(type != LAST_NORM)) {
path_put(&parent_path);
+ putname(filename);
return -ENOENT;
}
@@ -108,12 +110,14 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
path->dentry = d;
path->mnt = share_conf->vfs_path.mnt;
path_put(&parent_path);
+ putname(filename);
return 0;
err_out:
inode_unlock(parent_path.dentry->d_inode);
path_put(&parent_path);
+ putname(filename);
return -ENOENT;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 098/154] ksmbd: fix out-of-bound read in deassemble_neg_contexts()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (96 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 097/154] ksmbd: call putname after using the last component Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 099/154] ksmbd: fix out-of-bound read in parse_lease_state() Namjae Jeon
` (56 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Chih-Yen Chang, Steve French
[ Upstream commit f1a411873c85b642f13b01f21b534c2bab81fc1b ]
The check in the beginning is
`clen + sizeof(struct smb2_neg_context) <= len_of_ctxts`,
but in the end of loop, `len_of_ctxts` will subtract
`((clen + 7) & ~0x7) + sizeof(struct smb2_neg_context)`, which causes
integer underflow when clen does the 8 alignment. We should use
`(clen + 7) & ~0x7` in the check to avoid underflow from happening.
Then there are some variables that need to be declared unsigned
instead of signed.
[ 11.671070] BUG: KASAN: slab-out-of-bounds in smb2_handle_negotiate+0x799/0x1610
[ 11.671533] Read of size 2 at addr ffff888005e86cf2 by task kworker/0:0/7
...
[ 11.673383] Call Trace:
[ 11.673541] <TASK>
[ 11.673679] dump_stack_lvl+0x33/0x50
[ 11.673913] print_report+0xcc/0x620
[ 11.674671] kasan_report+0xae/0xe0
[ 11.675171] kasan_check_range+0x35/0x1b0
[ 11.675412] smb2_handle_negotiate+0x799/0x1610
[ 11.676217] ksmbd_smb_negotiate_common+0x526/0x770
[ 11.676795] handle_ksmbd_work+0x274/0x810
...
Cc: stable@vger.kernel.org
Signed-off-by: Chih-Yen Chang <cc85nod@gmail.com>
Tested-by: Chih-Yen Chang <cc85nod@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 62bcc440ad31..d25d3a046a7f 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -997,13 +997,13 @@ static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
struct smb2_negotiate_req *req,
- int len_of_smb)
+ unsigned int len_of_smb)
{
/* +4 is to account for the RFC1001 len field */
struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
int i = 0, len_of_ctxts;
- int offset = le32_to_cpu(req->NegotiateContextOffset);
- int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
+ unsigned int offset = le32_to_cpu(req->NegotiateContextOffset);
+ unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
__le32 status = STATUS_INVALID_PARAMETER;
ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
@@ -1017,7 +1017,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
while (i++ < neg_ctxt_cnt) {
int clen, ctxt_len;
- if (len_of_ctxts < sizeof(struct smb2_neg_context))
+ if (len_of_ctxts < (int)sizeof(struct smb2_neg_context))
break;
pctx = (struct smb2_neg_context *)((char *)pctx + offset);
@@ -1072,9 +1072,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
}
/* offsets must be 8 byte aligned */
- clen = (clen + 7) & ~0x7;
- offset = clen + sizeof(struct smb2_neg_context);
- len_of_ctxts -= clen + sizeof(struct smb2_neg_context);
+ offset = (ctxt_len + 7) & ~0x7;
+ len_of_ctxts -= offset;
}
return status;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 099/154] ksmbd: fix out-of-bound read in parse_lease_state()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (97 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 098/154] ksmbd: fix out-of-bound read in deassemble_neg_contexts() Namjae Jeon
@ 2023-12-18 15:33 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 100/154] ksmbd: fix posix_acls and acls dereferencing possible ERR_PTR() Namjae Jeon
` (55 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:33 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Chih-Yen Chang, Steve French
[ Upstream commit fc6c6a3c324c1b3e93a03d0cfa3749c781f23de0 ]
This bug is in parse_lease_state, and it is caused by the missing check
of `struct create_context`. When the ksmbd traverses the create_contexts,
it doesn't check if the field of `NameOffset` and `Next` is valid,
The KASAN message is following:
[ 6.664323] BUG: KASAN: slab-out-of-bounds in parse_lease_state+0x7d/0x280
[ 6.664738] Read of size 2 at addr ffff888005c08988 by task kworker/0:3/103
...
[ 6.666644] Call Trace:
[ 6.666796] <TASK>
[ 6.666933] dump_stack_lvl+0x33/0x50
[ 6.667167] print_report+0xcc/0x620
[ 6.667903] kasan_report+0xae/0xe0
[ 6.668374] kasan_check_range+0x35/0x1b0
[ 6.668621] parse_lease_state+0x7d/0x280
[ 6.668868] smb2_open+0xbe8/0x4420
[ 6.675137] handle_ksmbd_work+0x282/0x820
Use smb2_find_context_vals() to find smb2 create request lease context.
smb2_find_context_vals validate create context fields.
Cc: stable@vger.kernel.org
Reported-by: Chih-Yen Chang <cc85nod@gmail.com>
Tested-by: Chih-Yen Chang <cc85nod@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/oplock.c | 66 +++++++++++++++++------------------------------
1 file changed, 24 insertions(+), 42 deletions(-)
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index 28c7f2193fb3..e2fb4631f8f7 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -1415,56 +1415,38 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
*/
struct lease_ctx_info *parse_lease_state(void *open_req)
{
- char *data_offset;
struct create_context *cc;
- unsigned int next = 0;
- char *name;
- bool found = false;
struct smb2_create_req *req = (struct smb2_create_req *)open_req;
- struct lease_ctx_info *lreq = kzalloc(sizeof(struct lease_ctx_info),
- GFP_KERNEL);
+ struct lease_ctx_info *lreq;
+
+ cc = smb2_find_context_vals(req, SMB2_CREATE_REQUEST_LEASE, 4);
+ if (IS_ERR_OR_NULL(cc))
+ return NULL;
+
+ lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL);
if (!lreq)
return NULL;
- data_offset = (char *)req + le32_to_cpu(req->CreateContextsOffset);
- cc = (struct create_context *)data_offset;
- do {
- cc = (struct create_context *)((char *)cc + next);
- name = le16_to_cpu(cc->NameOffset) + (char *)cc;
- if (le16_to_cpu(cc->NameLength) != 4 ||
- strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) {
- next = le32_to_cpu(cc->Next);
- continue;
- }
- found = true;
- break;
- } while (next != 0);
+ if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
+ struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
- if (found) {
- if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
- struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
-
- memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
- lreq->req_state = lc->lcontext.LeaseState;
- lreq->flags = lc->lcontext.LeaseFlags;
- lreq->duration = lc->lcontext.LeaseDuration;
- memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
- SMB2_LEASE_KEY_SIZE);
- lreq->version = 2;
- } else {
- struct create_lease *lc = (struct create_lease *)cc;
+ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
+ lreq->req_state = lc->lcontext.LeaseState;
+ lreq->flags = lc->lcontext.LeaseFlags;
+ lreq->duration = lc->lcontext.LeaseDuration;
+ memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
+ SMB2_LEASE_KEY_SIZE);
+ lreq->version = 2;
+ } else {
+ struct create_lease *lc = (struct create_lease *)cc;
- memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
- lreq->req_state = lc->lcontext.LeaseState;
- lreq->flags = lc->lcontext.LeaseFlags;
- lreq->duration = lc->lcontext.LeaseDuration;
- lreq->version = 1;
- }
- return lreq;
+ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
+ lreq->req_state = lc->lcontext.LeaseState;
+ lreq->flags = lc->lcontext.LeaseFlags;
+ lreq->duration = lc->lcontext.LeaseDuration;
+ lreq->version = 1;
}
-
- kfree(lreq);
- return NULL;
+ return lreq;
}
/**
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 100/154] ksmbd: fix posix_acls and acls dereferencing possible ERR_PTR()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (98 preceding siblings ...)
2023-12-18 15:33 ` [PATCH 5.15.y 099/154] ksmbd: fix out-of-bound read in parse_lease_state() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 101/154] ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop Namjae Jeon
` (54 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Dan Carpenter, Steve French
[ Upstream commit 25933573ef48f3586f559c2cac6c436c62dcf63f ]
Dan reported the following error message:
fs/smb/server/smbacl.c:1296 smb_check_perm_dacl()
error: 'posix_acls' dereferencing possible ERR_PTR()
fs/smb/server/vfs.c:1323 ksmbd_vfs_make_xattr_posix_acl()
error: 'posix_acls' dereferencing possible ERR_PTR()
fs/smb/server/vfs.c:1830 ksmbd_vfs_inherit_posix_acl()
error: 'acls' dereferencing possible ERR_PTR()
__get_acl() returns a mix of error pointers and NULL. This change it
with IS_ERR_OR_NULL().
Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smbacl.c | 4 ++--
fs/ksmbd/vfs.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index 253e8133520a..34db75af8c62 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -1311,7 +1311,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
posix_acls = get_acl(d_inode(path->dentry), ACL_TYPE_ACCESS);
- if (posix_acls && !found) {
+ if (!IS_ERR_OR_NULL(posix_acls) && !found) {
unsigned int id = -1;
pa_entry = posix_acls->a_entries;
@@ -1335,7 +1335,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
}
}
}
- if (posix_acls)
+ if (!IS_ERR_OR_NULL(posix_acls))
posix_acl_release(posix_acls);
}
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index a48d53c4587c..97e723956fe8 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -1323,7 +1323,7 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac
return NULL;
posix_acls = get_acl(inode, acl_type);
- if (!posix_acls)
+ if (IS_ERR_OR_NULL(posix_acls))
return NULL;
smb_acl = kzalloc(sizeof(struct xattr_smb_acl) +
@@ -1831,7 +1831,7 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
return -EOPNOTSUPP;
acls = get_acl(parent_inode, ACL_TYPE_DEFAULT);
- if (!acls)
+ if (IS_ERR_OR_NULL(acls))
return -ENOENT;
pace = acls->a_entries;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 101/154] ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (99 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 100/154] ksmbd: fix posix_acls and acls dereferencing possible ERR_PTR() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 102/154] ksmbd: validate smb request protocol id Namjae Jeon
` (53 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Chih-Yen Chang, Steve French
[ Upstream commit 368ba06881c395f1c9a7ba22203cf8d78b4addc0 ]
The length field of netbios header must be greater than the SMB header
sizes(smb1 or smb2 header), otherwise the packet is an invalid SMB packet.
If `pdu_size` is 0, ksmbd allocates a 4 bytes chunk to `conn->request_buf`.
In the function `get_smb2_cmd_val` ksmbd will read cmd from
`rcv_hdr->Command`, which is `conn->request_buf + 12`, causing the KASAN
detector to print the following error message:
[ 7.205018] BUG: KASAN: slab-out-of-bounds in get_smb2_cmd_val+0x45/0x60
[ 7.205423] Read of size 2 at addr ffff8880062d8b50 by task ksmbd:42632/248
...
[ 7.207125] <TASK>
[ 7.209191] get_smb2_cmd_val+0x45/0x60
[ 7.209426] ksmbd_conn_enqueue_request+0x3a/0x100
[ 7.209712] ksmbd_server_process_request+0x72/0x160
[ 7.210295] ksmbd_conn_handler_loop+0x30c/0x550
[ 7.212280] kthread+0x160/0x190
[ 7.212762] ret_from_fork+0x1f/0x30
[ 7.212981] </TASK>
Cc: stable@vger.kernel.org
Reported-by: Chih-Yen Chang <cc85nod@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 4a9672d3ef49..c3c8b64a4adc 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -294,6 +294,9 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)
return true;
}
+#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
+#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
+
/**
* ksmbd_conn_handler_loop() - session thread to listen on new smb requests
* @p: connection instance
@@ -350,6 +353,9 @@ int ksmbd_conn_handler_loop(void *p)
if (pdu_size > MAX_STREAM_PROT_LEN)
break;
+ if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
+ break;
+
/* 4 for rfc1002 length field */
/* 1 for implied bcc[0] */
size = pdu_size + 4 + 1;
@@ -377,6 +383,12 @@ int ksmbd_conn_handler_loop(void *p)
continue;
}
+ if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
+ SMB2_PROTO_NUMBER) {
+ if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
+ break;
+ }
+
if (!default_conn_ops.process_fn) {
pr_err("No connection request callback\n");
break;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 102/154] ksmbd: validate smb request protocol id
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (100 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 101/154] ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 103/154] ksmbd: add mnt_want_write to ksmbd vfs functions Namjae Jeon
` (52 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Chih-Yen Chang, Steve French
[ Upstream commit 1c1bcf2d3ea061613119b534f57507c377df20f9 ]
This patch add the validation for smb request protocol id.
If it is not one of the four ids(SMB1_PROTO_NUMBER, SMB2_PROTO_NUMBER,
SMB2_TRANSFORM_PROTO_NUM, SMB2_COMPRESSION_TRANSFORM_ID), don't allow
processing the request. And this will fix the following KASAN warning
also.
[ 13.905265] BUG: KASAN: slab-out-of-bounds in init_smb2_rsp_hdr+0x1b9/0x1f0
[ 13.905900] Read of size 16 at addr ffff888005fd2f34 by task kworker/0:2/44
...
[ 13.908553] Call Trace:
[ 13.908793] <TASK>
[ 13.908995] dump_stack_lvl+0x33/0x50
[ 13.909369] print_report+0xcc/0x620
[ 13.910870] kasan_report+0xae/0xe0
[ 13.911519] kasan_check_range+0x35/0x1b0
[ 13.911796] init_smb2_rsp_hdr+0x1b9/0x1f0
[ 13.912492] handle_ksmbd_work+0xe5/0x820
Cc: stable@vger.kernel.org
Reported-by: Chih-Yen Chang <cc85nod@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 5 +++--
fs/ksmbd/smb2pdu.h | 1 +
fs/ksmbd/smb_common.c | 14 +++++++++++++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index c3c8b64a4adc..99ea5f1b324d 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -364,8 +364,6 @@ int ksmbd_conn_handler_loop(void *p)
break;
memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
- if (!ksmbd_smb_request(conn))
- break;
/*
* We already read 4 bytes to find out PDU size, now
@@ -383,6 +381,9 @@ int ksmbd_conn_handler_loop(void *p)
continue;
}
+ if (!ksmbd_smb_request(conn))
+ break;
+
if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
SMB2_PROTO_NUMBER) {
if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index a774889e0aa5..e1d0849ee68f 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -109,6 +109,7 @@
#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) /* 'B''M''S' */
#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
+#define SMB2_COMPRESSION_TRANSFORM_ID cpu_to_le32(0x424d53fc)
#define SMB21_DEFAULT_IOSIZE (1024 * 1024)
#define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024)
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index 1c69811610dc..d937e2f45c82 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -158,7 +158,19 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work)
*/
bool ksmbd_smb_request(struct ksmbd_conn *conn)
{
- return conn->request_buf[0] == 0;
+ __le32 *proto = (__le32 *)smb2_get_msg(conn->request_buf);
+
+ if (*proto == SMB2_COMPRESSION_TRANSFORM_ID) {
+ pr_err_ratelimited("smb2 compression not support yet");
+ return false;
+ }
+
+ if (*proto != SMB1_PROTO_NUMBER &&
+ *proto != SMB2_PROTO_NUMBER &&
+ *proto != SMB2_TRANSFORM_PROTO_NUM)
+ return false;
+
+ return true;
}
static bool supported_protocol(int idx)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 103/154] ksmbd: add mnt_want_write to ksmbd vfs functions
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (101 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 102/154] ksmbd: validate smb request protocol id Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 104/154] ksmbd: remove unused ksmbd_tree_conn_share function Namjae Jeon
` (51 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Amir Goldstein, Steve French
[ Upstream commit 40b268d384a22276dca1450549f53eed60e21deb ]
ksmbd is doing write access using vfs helpers. There are the cases that
mnt_want_write() is not called in vfs helper. This patch add missing
mnt_want_write() to ksmbd vfs functions.
Cc: stable@vger.kernel.org
Cc: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 26 +++++-----
fs/ksmbd/smbacl.c | 10 ++--
fs/ksmbd/vfs.c | 112 +++++++++++++++++++++++++++++++++----------
fs/ksmbd/vfs.h | 17 ++++---
fs/ksmbd/vfs_cache.c | 2 +-
5 files changed, 112 insertions(+), 55 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d25d3a046a7f..d6c9092ff230 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2284,7 +2284,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
/* delete the EA only when it exits */
if (rc > 0) {
rc = ksmbd_vfs_remove_xattr(user_ns,
- path->dentry,
+ path,
attr_name);
if (rc < 0) {
@@ -2298,8 +2298,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
/* if the EA doesn't exist, just do nothing. */
rc = 0;
} else {
- rc = ksmbd_vfs_setxattr(user_ns,
- path->dentry, attr_name, value,
+ rc = ksmbd_vfs_setxattr(user_ns, path, attr_name, value,
le16_to_cpu(eabuf->EaValueLength), 0);
if (rc < 0) {
ksmbd_debug(SMB,
@@ -2363,8 +2362,7 @@ static noinline int smb2_set_stream_name_xattr(const struct path *path,
return -EBADF;
}
- rc = ksmbd_vfs_setxattr(user_ns, path->dentry,
- xattr_stream_name, NULL, 0, 0);
+ rc = ksmbd_vfs_setxattr(user_ns, path, xattr_stream_name, NULL, 0, 0);
if (rc < 0)
pr_err("Failed to store XATTR stream name :%d\n", rc);
return 0;
@@ -2392,7 +2390,7 @@ static int smb2_remove_smb_xattrs(const struct path *path)
if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
!strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
STREAM_PREFIX_LEN)) {
- err = ksmbd_vfs_remove_xattr(user_ns, path->dentry,
+ err = ksmbd_vfs_remove_xattr(user_ns, path,
name);
if (err)
ksmbd_debug(SMB, "remove xattr failed : %s\n",
@@ -2439,8 +2437,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt),
- path->dentry, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt), path, &da);
if (rc)
ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
}
@@ -3011,7 +3008,7 @@ int smb2_open(struct ksmbd_work *work)
struct inode *inode = d_inode(path.dentry);
posix_acl_rc = ksmbd_vfs_inherit_posix_acl(user_ns,
- inode,
+ &path,
d_inode(path.dentry->d_parent));
if (posix_acl_rc)
ksmbd_debug(SMB, "inherit posix acl failed : %d\n", posix_acl_rc);
@@ -3027,7 +3024,7 @@ int smb2_open(struct ksmbd_work *work)
if (rc) {
if (posix_acl_rc)
ksmbd_vfs_set_init_posix_acl(user_ns,
- inode);
+ &path);
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_ACL_XATTR)) {
@@ -3067,7 +3064,7 @@ int smb2_open(struct ksmbd_work *work)
rc = ksmbd_vfs_set_sd_xattr(conn,
user_ns,
- path.dentry,
+ &path,
pntsd,
pntsd_size);
kfree(pntsd);
@@ -5506,7 +5503,7 @@ static int smb2_rename(struct ksmbd_work *work,
goto out;
rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp),
- fp->filp->f_path.dentry,
+ &fp->filp->f_path,
xattr_stream_name,
NULL, 0, 0);
if (rc < 0) {
@@ -5671,8 +5668,7 @@ static int set_file_basic_info(struct ksmbd_file *fp,
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
- filp->f_path.dentry, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(user_ns, &filp->f_path, &da);
if (rc)
ksmbd_debug(SMB,
"failed to restore file attribute in EA\n");
@@ -7534,7 +7530,7 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
da.attr = le32_to_cpu(fp->f_ci->m_fattr);
ret = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
- fp->filp->f_path.dentry, &da);
+ &fp->filp->f_path, &da);
if (ret)
fp->f_ci->m_fattr = old_fattr;
}
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index 34db75af8c62..8fbcc6a8cef0 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -1183,8 +1183,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
pntsd_size += sizeof(struct smb_acl) + nt_size;
}
- ksmbd_vfs_set_sd_xattr(conn, user_ns,
- path->dentry, pntsd, pntsd_size);
+ ksmbd_vfs_set_sd_xattr(conn, user_ns, path, pntsd, pntsd_size);
kfree(pntsd);
}
@@ -1404,7 +1403,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
newattrs.ia_valid |= ATTR_MODE;
newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
- ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry);
+ ksmbd_vfs_remove_acl_xattrs(user_ns, path);
/* Update posix acls */
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) {
rc = set_posix_acl(user_ns, inode,
@@ -1435,9 +1434,8 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
/* Update WinACL in xattr */
- ksmbd_vfs_remove_sd_xattrs(user_ns, path->dentry);
- ksmbd_vfs_set_sd_xattr(conn, user_ns,
- path->dentry, pntsd, ntsd_len);
+ ksmbd_vfs_remove_sd_xattrs(user_ns, path);
+ ksmbd_vfs_set_sd_xattr(conn, user_ns, path, pntsd, ntsd_len);
}
out:
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 97e723956fe8..e58fbbfda7b2 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -170,6 +170,10 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
return err;
}
+ err = mnt_want_write(path.mnt);
+ if (err)
+ goto out_err;
+
mode |= S_IFREG;
err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry),
dentry, mode, true);
@@ -179,6 +183,9 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
} else {
pr_err("File(%s): creation failed (err:%d)\n", name, err);
}
+ mnt_drop_write(path.mnt);
+
+out_err:
done_path_create(&path, dentry);
return err;
}
@@ -209,30 +216,35 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
return err;
}
+ err = mnt_want_write(path.mnt);
+ if (err)
+ goto out_err2;
+
user_ns = mnt_user_ns(path.mnt);
mode |= S_IFDIR;
err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
- if (err) {
- goto out;
- } else if (d_unhashed(dentry)) {
+ if (!err && d_unhashed(dentry)) {
struct dentry *d;
d = lookup_one(user_ns, dentry->d_name.name, dentry->d_parent,
dentry->d_name.len);
if (IS_ERR(d)) {
err = PTR_ERR(d);
- goto out;
+ goto out_err1;
}
if (unlikely(d_is_negative(d))) {
dput(d);
err = -ENOENT;
- goto out;
+ goto out_err1;
}
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(d));
dput(d);
}
-out:
+
+out_err1:
+ mnt_drop_write(path.mnt);
+out_err2:
done_path_create(&path, dentry);
if (err)
pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
@@ -443,7 +455,7 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
memcpy(&stream_buf[*pos], buf, count);
err = ksmbd_vfs_setxattr(user_ns,
- fp->filp->f_path.dentry,
+ &fp->filp->f_path,
fp->stream.name,
(void *)stream_buf,
size,
@@ -589,6 +601,10 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
goto out_err;
}
+ err = mnt_want_write(path->mnt);
+ if (err)
+ goto out_err;
+
user_ns = mnt_user_ns(path->mnt);
if (S_ISDIR(d_inode(path->dentry)->i_mode)) {
err = vfs_rmdir(user_ns, d_inode(parent), path->dentry);
@@ -599,6 +615,7 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
if (err)
ksmbd_debug(VFS, "unlink failed, err %d\n", err);
}
+ mnt_drop_write(path->mnt);
out_err:
ksmbd_revert_fsids(work);
@@ -644,11 +661,16 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
goto out3;
}
+ err = mnt_want_write(newpath.mnt);
+ if (err)
+ goto out3;
+
err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt),
d_inode(newpath.dentry),
dentry, NULL);
if (err)
ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
+ mnt_drop_write(newpath.mnt);
out3:
done_path_create(&newpath, dentry);
@@ -694,6 +716,10 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
goto out2;
}
+ err = mnt_want_write(old_path->mnt);
+ if (err)
+ goto out2;
+
trap = lock_rename_child(old_child, new_path.dentry);
old_parent = dget(old_child->d_parent);
@@ -757,6 +783,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
out3:
dput(old_parent);
unlock_rename(old_parent, new_path.dentry);
+ mnt_drop_write(old_path->mnt);
out2:
path_put(&new_path);
@@ -897,19 +924,24 @@ ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
* Return: 0 on success, otherwise error
*/
int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
- struct dentry *dentry, const char *attr_name,
+ const struct path *path, const char *attr_name,
const void *attr_value, size_t attr_size, int flags)
{
int err;
+ err = mnt_want_write(path->mnt);
+ if (err)
+ return err;
+
err = vfs_setxattr(user_ns,
- dentry,
+ path->dentry,
attr_name,
attr_value,
attr_size,
flags);
if (err)
ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
+ mnt_drop_write(path->mnt);
return err;
}
@@ -1013,9 +1045,18 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
}
int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
- struct dentry *dentry, char *attr_name)
+ const struct path *path, char *attr_name)
{
- return vfs_removexattr(user_ns, dentry, attr_name);
+ int err;
+
+ err = mnt_want_write(path->mnt);
+ if (err)
+ return err;
+
+ err = vfs_removexattr(user_ns, path->dentry, attr_name);
+ mnt_drop_write(path->mnt);
+
+ return err;
}
int ksmbd_vfs_unlink(struct file *filp)
@@ -1024,6 +1065,10 @@ int ksmbd_vfs_unlink(struct file *filp)
struct dentry *dir, *dentry = filp->f_path.dentry;
struct user_namespace *user_ns = file_mnt_user_ns(filp);
+ err = mnt_want_write(filp->f_path.mnt);
+ if (err)
+ return err;
+
dir = dget_parent(dentry);
err = ksmbd_vfs_lock_parent(dir, dentry);
if (err)
@@ -1041,6 +1086,7 @@ int ksmbd_vfs_unlink(struct file *filp)
ksmbd_debug(VFS, "failed to delete, err %d\n", err);
out:
dput(dir);
+ mnt_drop_write(filp->f_path.mnt);
return err;
}
@@ -1246,13 +1292,13 @@ struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
}
int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry)
+ const struct path *path)
{
char *name, *xattr_list = NULL;
ssize_t xattr_list_len;
int err = 0;
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
if (xattr_list_len < 0) {
goto out;
} else if (!xattr_list_len) {
@@ -1268,25 +1314,25 @@ int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) ||
!strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) {
- err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
+ err = ksmbd_vfs_remove_xattr(user_ns, path, name);
if (err)
ksmbd_debug(SMB,
"remove acl xattr failed : %s\n", name);
}
}
+
out:
kvfree(xattr_list);
return err;
}
-int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry)
+int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns, const struct path *path)
{
char *name, *xattr_list = NULL;
ssize_t xattr_list_len;
int err = 0;
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
if (xattr_list_len < 0) {
goto out;
} else if (!xattr_list_len) {
@@ -1299,7 +1345,7 @@ int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
- err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
+ err = ksmbd_vfs_remove_xattr(user_ns, path, name);
if (err)
ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
}
@@ -1376,13 +1422,14 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
struct user_namespace *user_ns,
- struct dentry *dentry,
+ const struct path *path,
struct smb_ntsd *pntsd, int len)
{
int rc;
struct ndr sd_ndr = {0}, acl_ndr = {0};
struct xattr_ntacl acl = {0};
struct xattr_smb_acl *smb_acl, *def_smb_acl = NULL;
+ struct dentry *dentry = path->dentry;
struct inode *inode = d_inode(dentry);
acl.version = 4;
@@ -1434,7 +1481,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
goto out;
}
- rc = ksmbd_vfs_setxattr(user_ns, dentry,
+ rc = ksmbd_vfs_setxattr(user_ns, path,
XATTR_NAME_SD, sd_ndr.data,
sd_ndr.offset, 0);
if (rc < 0)
@@ -1524,7 +1571,7 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
}
int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
- struct dentry *dentry,
+ const struct path *path,
struct xattr_dos_attrib *da)
{
struct ndr n;
@@ -1534,7 +1581,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
if (err)
return err;
- err = ksmbd_vfs_setxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE,
+ err = ksmbd_vfs_setxattr(user_ns, path, XATTR_NAME_DOS_ATTRIBUTE,
(void *)n.data, n.offset, 0);
if (err)
ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
@@ -1771,10 +1818,11 @@ void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock)
}
int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
- struct inode *inode)
+ struct path *path)
{
struct posix_acl_state acl_state;
struct posix_acl *acls;
+ struct inode *inode = d_inode(path->dentry);
int rc;
if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
@@ -1803,6 +1851,11 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
return -ENOMEM;
}
posix_state_to_acl(&acl_state, acls->a_entries);
+
+ rc = mnt_want_write(path->mnt);
+ if (rc)
+ goto out_err;
+
rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1815,16 +1868,20 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
}
+ mnt_drop_write(path->mnt);
+
+out_err:
free_acl_state(&acl_state);
posix_acl_release(acls);
return rc;
}
int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
- struct inode *inode, struct inode *parent_inode)
+ struct path *path, struct inode *parent_inode)
{
struct posix_acl *acls;
struct posix_acl_entry *pace;
+ struct inode *inode = d_inode(path->dentry);
int rc, i;
if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
@@ -1842,6 +1899,10 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
}
}
+ rc = mnt_want_write(path->mnt);
+ if (rc)
+ goto out_err;
+
rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1853,6 +1914,9 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
}
+ mnt_drop_write(path->mnt);
+
+out_err:
posix_acl_release(acls);
return rc;
}
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index bd92b8a6edbe..adaf511dace1 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -147,12 +147,12 @@ ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
struct dentry *dentry, char *attr_name,
int attr_name_len);
int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
- struct dentry *dentry, const char *attr_name,
+ const struct path *path, const char *attr_name,
const void *attr_value, size_t attr_size, int flags);
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
size_t *xattr_stream_name_size, int s_type);
int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
- struct dentry *dentry, char *attr_name);
+ const struct path *path, char *attr_name);
int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
unsigned int flags, struct path *path,
bool caseless);
@@ -178,26 +178,25 @@ void ksmbd_vfs_posix_lock_wait(struct file_lock *flock);
int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout);
void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock);
int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry);
-int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry);
+ const struct path *path);
+int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns, const struct path *path);
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
struct user_namespace *user_ns,
- struct dentry *dentry,
+ const struct path *path,
struct smb_ntsd *pntsd, int len);
int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
struct user_namespace *user_ns,
struct dentry *dentry,
struct smb_ntsd **pntsd);
int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
- struct dentry *dentry,
+ const struct path *path,
struct xattr_dos_attrib *da);
int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
struct dentry *dentry,
struct xattr_dos_attrib *da);
int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
- struct inode *inode);
+ struct path *path);
int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
- struct inode *inode,
+ struct path *path,
struct inode *parent_inode);
#endif /* __KSMBD_VFS_H__ */
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index bafb34d4b5bb..94ad8fa07b46 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -251,7 +251,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
err = ksmbd_vfs_remove_xattr(file_mnt_user_ns(filp),
- filp->f_path.dentry,
+ &filp->f_path,
fp->stream.name);
if (err)
pr_err("remove xattr failed : %s\n",
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 104/154] ksmbd: remove unused ksmbd_tree_conn_share function
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (102 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 103/154] ksmbd: add mnt_want_write to ksmbd vfs functions Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 105/154] ksmbd: use kzalloc() instead of __GFP_ZERO Namjae Jeon
` (50 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Sergey Senozhatsky, Steve French
[ Upstream commit 7bd9f0876fdef00f4e155be35e6b304981a53f80 ]
Remove unused ksmbd_tree_conn_share function.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/tree_connect.c | 11 -----------
fs/ksmbd/mgmt/tree_connect.h | 3 ---
2 files changed, 14 deletions(-)
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index f07a05f37651..408cddf2f094 100644
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -120,17 +120,6 @@ struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
return tcon;
}
-struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
- unsigned int id)
-{
- struct ksmbd_tree_connect *tc;
-
- tc = ksmbd_tree_conn_lookup(sess, id);
- if (tc)
- return tc->share_conf;
- return NULL;
-}
-
int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
{
int ret = 0;
diff --git a/fs/ksmbd/mgmt/tree_connect.h b/fs/ksmbd/mgmt/tree_connect.h
index 700df36cf3e3..562d647ad9fa 100644
--- a/fs/ksmbd/mgmt/tree_connect.h
+++ b/fs/ksmbd/mgmt/tree_connect.h
@@ -53,9 +53,6 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
unsigned int id);
-struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
- unsigned int id);
-
int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess);
#endif /* __TREE_CONNECT_MANAGEMENT_H__ */
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 105/154] ksmbd: use kzalloc() instead of __GFP_ZERO
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (103 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 104/154] ksmbd: remove unused ksmbd_tree_conn_share function Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 106/154] ksmbd: return a literal instead of 'err' in ksmbd_vfs_kern_path_locked() Namjae Jeon
` (49 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Namjae Jeon, Dan Carpenter, Sergey Senozhatsky,
Steve French
[ Upstream commit f87d4f85f43f0d4b12ef64b015478d8053e1a33e ]
Use kzalloc() instead of __GFP_ZERO.
Reported-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb_common.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index d937e2f45c82..08d95e1ecc5e 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -359,8 +359,8 @@ static int smb1_check_user_session(struct ksmbd_work *work)
*/
static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
{
- work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
- GFP_KERNEL | __GFP_ZERO);
+ work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
+ GFP_KERNEL);
work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
if (!work->response_buf) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 106/154] ksmbd: return a literal instead of 'err' in ksmbd_vfs_kern_path_locked()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (104 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 105/154] ksmbd: use kzalloc() instead of __GFP_ZERO Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 107/154] ksmbd: Change the return value of ksmbd_vfs_query_maximal_access to void Namjae Jeon
` (48 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Dan Carpenter, Steve French
[ Upstream commit cf5e7f734f445588a30350591360bca2f6bf016f ]
Return a literal instead of 'err' in ksmbd_vfs_kern_path_locked().
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index e58fbbfda7b2..7d239d3f8dbd 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -1209,7 +1209,7 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, path);
if (!err)
- return err;
+ return 0;
if (caseless) {
char *filepath;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 107/154] ksmbd: Change the return value of ksmbd_vfs_query_maximal_access to void
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (105 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 106/154] ksmbd: return a literal instead of 'err' in ksmbd_vfs_kern_path_locked() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 108/154] ksmbd: use kvzalloc instead of kvmalloc Namjae Jeon
` (47 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Lu Hongfei, Namjae Jeon, Steve French
From: Lu Hongfei <luhongfei@vivo.com>
[ Upstream commit ccb5889af97c03c67a83fcd649602034578c0d61 ]
The return value of ksmbd_vfs_query_maximal_access is meaningless,
it is better to modify it to void.
Signed-off-by: Lu Hongfei <luhongfei@vivo.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 4 +---
fs/ksmbd/vfs.c | 6 +-----
fs/ksmbd/vfs.h | 2 +-
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d6c9092ff230..f31cc130f2c5 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2877,11 +2877,9 @@ int smb2_open(struct ksmbd_work *work)
if (!file_present) {
daccess = cpu_to_le32(GENERIC_ALL_FLAGS);
} else {
- rc = ksmbd_vfs_query_maximal_access(user_ns,
+ ksmbd_vfs_query_maximal_access(user_ns,
path.dentry,
&daccess);
- if (rc)
- goto err_out;
already_permitted = true;
}
maximal_access = daccess;
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 7d239d3f8dbd..540c14741194 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -121,11 +121,9 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
return -ENOENT;
}
-int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
+void ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
struct dentry *dentry, __le32 *daccess)
{
- int ret = 0;
-
*daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE))
@@ -142,8 +140,6 @@ int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
if (!inode_permission(user_ns, d_inode(dentry->d_parent), MAY_EXEC | MAY_WRITE))
*daccess |= FILE_DELETE_LE;
-
- return ret;
}
/**
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index adaf511dace1..2e87136f9eba 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -111,7 +111,7 @@ struct ksmbd_kstat {
};
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child);
-int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
+void ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
struct dentry *dentry, __le32 *daccess);
int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 108/154] ksmbd: use kvzalloc instead of kvmalloc
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (106 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 107/154] ksmbd: Change the return value of ksmbd_vfs_query_maximal_access to void Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 109/154] ksmbd: Replace the ternary conditional operator with min() Namjae Jeon
` (46 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, kernel test robot, Steve French
[ Upstream commit 81a94b27847f7d2e499415db14dd9dc7c22b19b0 ]
Use kvzalloc instead of kvmalloc.
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 8 ++++----
fs/ksmbd/transport_ipc.c | 4 ++--
fs/ksmbd/vfs.c | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index f31cc130f2c5..151249bdfe2b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -544,7 +544,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
if (le32_to_cpu(hdr->NextCommand) > 0)
sz = large_sz;
- work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
+ work->response_buf = kvzalloc(sz, GFP_KERNEL);
if (!work->response_buf)
return -ENOMEM;
@@ -6104,7 +6104,7 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
}
work->aux_payload_buf =
- kvmalloc(rpc_resp->payload_sz, GFP_KERNEL | __GFP_ZERO);
+ kvmalloc(rpc_resp->payload_sz, GFP_KERNEL);
if (!work->aux_payload_buf) {
err = -ENOMEM;
goto out;
@@ -6261,7 +6261,7 @@ int smb2_read(struct ksmbd_work *work)
ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
fp->filp, offset, length);
- work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
+ work->aux_payload_buf = kvzalloc(length, GFP_KERNEL);
if (!work->aux_payload_buf) {
err = -ENOMEM;
goto out;
@@ -6410,7 +6410,7 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
int ret;
ssize_t nbytes;
- data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
+ data_buf = kvzalloc(length, GFP_KERNEL);
if (!data_buf)
return -ENOMEM;
diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
index a8313eed4f10..9560c704033e 100644
--- a/fs/ksmbd/transport_ipc.c
+++ b/fs/ksmbd/transport_ipc.c
@@ -228,7 +228,7 @@ static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
struct ksmbd_ipc_msg *msg;
size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
- msg = kvmalloc(msg_sz, GFP_KERNEL | __GFP_ZERO);
+ msg = kvzalloc(msg_sz, GFP_KERNEL);
if (msg)
msg->sz = sz;
return msg;
@@ -267,7 +267,7 @@ static int handle_response(int type, void *payload, size_t sz)
entry->type + 1, type);
}
- entry->response = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
+ entry->response = kvzalloc(sz, GFP_KERNEL);
if (!entry->response) {
ret = -ENOMEM;
break;
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 540c14741194..2b938ebdfd2a 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -436,7 +436,7 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
}
if (v_len < size) {
- wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
+ wbuf = kvzalloc(size, GFP_KERNEL);
if (!wbuf) {
err = -ENOMEM;
goto out;
@@ -853,7 +853,7 @@ ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list)
if (size <= 0)
return size;
- vlist = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
+ vlist = kvzalloc(size, GFP_KERNEL);
if (!vlist)
return -ENOMEM;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 109/154] ksmbd: Replace the ternary conditional operator with min()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (107 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 108/154] ksmbd: use kvzalloc instead of kvmalloc Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 110/154] ksmbd: fix out of bounds read in smb2_sess_setup Namjae Jeon
` (45 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Lu Hongfei, Namjae Jeon, Steve French
From: Lu Hongfei <luhongfei@vivo.com>
[ Upstream commit f65fadb0422537d73f9a6472861852dc2f7a6a5b ]
It would be better to replace the traditional ternary conditional
operator with min() in compare_sids.
Signed-off-by: Lu Hongfei <luhongfei@vivo.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smbacl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index 8fbcc6a8cef0..a8b450e62825 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -97,7 +97,7 @@ int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid)
/* compare all of the subauth values if any */
num_sat = ctsid->num_subauth;
num_saw = cwsid->num_subauth;
- num_subauth = num_sat < num_saw ? num_sat : num_saw;
+ num_subauth = min(num_sat, num_saw);
if (num_subauth) {
for (i = 0; i < num_subauth; ++i) {
if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 110/154] ksmbd: fix out of bounds read in smb2_sess_setup
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (108 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 109/154] ksmbd: Replace the ternary conditional operator with min() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 111/154] ksmbd: add missing compound request handing in some commands Namjae Jeon
` (44 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit 98422bdd4cb3ca4d08844046f6507d7ec2c2b8d8 ]
ksmbd does not consider the case of that smb2 session setup is
in compound request. If this is the second payload of the compound,
OOB read issue occurs while processing the first payload in
the smb2_sess_setup().
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21355
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 151249bdfe2b..8e17334ecee8 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1323,9 +1323,8 @@ static int decode_negotiation_token(struct ksmbd_conn *conn,
static int ntlm_negotiate(struct ksmbd_work *work,
struct negotiate_message *negblob,
- size_t negblob_len)
+ size_t negblob_len, struct smb2_sess_setup_rsp *rsp)
{
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct challenge_message *chgblob;
unsigned char *spnego_blob = NULL;
u16 spnego_blob_len;
@@ -1430,10 +1429,10 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
return user;
}
-static int ntlm_authenticate(struct ksmbd_work *work)
+static int ntlm_authenticate(struct ksmbd_work *work,
+ struct smb2_sess_setup_req *req,
+ struct smb2_sess_setup_rsp *rsp)
{
- struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
struct channel *chann = NULL;
@@ -1567,10 +1566,10 @@ static int ntlm_authenticate(struct ksmbd_work *work)
}
#ifdef CONFIG_SMB_SERVER_KERBEROS5
-static int krb5_authenticate(struct ksmbd_work *work)
+static int krb5_authenticate(struct ksmbd_work *work,
+ struct smb2_sess_setup_req *req,
+ struct smb2_sess_setup_rsp *rsp)
{
- struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
char *in_blob, *out_blob;
@@ -1648,7 +1647,9 @@ static int krb5_authenticate(struct ksmbd_work *work)
return 0;
}
#else
-static int krb5_authenticate(struct ksmbd_work *work)
+static int krb5_authenticate(struct ksmbd_work *work,
+ struct smb2_sess_setup_req *req,
+ struct smb2_sess_setup_rsp *rsp)
{
return -EOPNOTSUPP;
}
@@ -1657,8 +1658,8 @@ static int krb5_authenticate(struct ksmbd_work *work)
int smb2_sess_setup(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_sess_setup_req *req;
+ struct smb2_sess_setup_rsp *rsp;
struct ksmbd_session *sess;
struct negotiate_message *negblob;
unsigned int negblob_len, negblob_off;
@@ -1666,6 +1667,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
ksmbd_debug(SMB, "Received request for session setup\n");
+ WORK_BUFFERS(work, req, rsp);
+
rsp->StructureSize = cpu_to_le16(9);
rsp->SessionFlags = 0;
rsp->SecurityBufferOffset = cpu_to_le16(72);
@@ -1787,7 +1790,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
if (conn->preferred_auth_mech &
(KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5)) {
- rc = krb5_authenticate(work);
+ rc = krb5_authenticate(work, req, rsp);
if (rc) {
rc = -EINVAL;
goto out_err;
@@ -1801,7 +1804,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
sess->Preauth_HashValue = NULL;
} else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
if (negblob->MessageType == NtLmNegotiate) {
- rc = ntlm_negotiate(work, negblob, negblob_len);
+ rc = ntlm_negotiate(work, negblob, negblob_len, rsp);
if (rc)
goto out_err;
rsp->hdr.Status =
@@ -1814,7 +1817,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
le16_to_cpu(rsp->SecurityBufferLength) - 1);
} else if (negblob->MessageType == NtLmAuthenticate) {
- rc = ntlm_authenticate(work);
+ rc = ntlm_authenticate(work, req, rsp);
if (rc)
goto out_err;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 111/154] ksmbd: add missing compound request handing in some commands
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (109 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 110/154] ksmbd: fix out of bounds read in smb2_sess_setup Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 112/154] ksmbd: Use struct_size() helper in ksmbd_negotiate_smb_dialect() Namjae Jeon
` (43 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 7b7d709ef7cf285309157fb94c33f625dd22c5e1 ]
This patch add the compound request handling to the some commands.
Existing clients do not send these commands as compound requests,
but ksmbd should consider that they may come.
Cc: stable@vger.kernel.org
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 78 +++++++++++++++++++++++++++++++---------------
1 file changed, 53 insertions(+), 25 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 8e17334ecee8..964e7182605b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1915,14 +1915,16 @@ int smb2_sess_setup(struct ksmbd_work *work)
int smb2_tree_connect(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_tree_connect_req *req = smb2_get_msg(work->request_buf);
- struct smb2_tree_connect_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_tree_connect_req *req;
+ struct smb2_tree_connect_rsp *rsp;
struct ksmbd_session *sess = work->sess;
char *treename = NULL, *name = NULL;
struct ksmbd_tree_conn_status status;
struct ksmbd_share_config *share;
int rc = -EINVAL;
+ WORK_BUFFERS(work, req, rsp);
+
treename = smb_strndup_from_utf16(req->Buffer,
le16_to_cpu(req->PathLength), true,
conn->local_nls);
@@ -2091,19 +2093,19 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
*/
int smb2_tree_disconnect(struct ksmbd_work *work)
{
- struct smb2_tree_disconnect_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_tree_disconnect_rsp *rsp;
+ struct smb2_tree_disconnect_req *req;
struct ksmbd_session *sess = work->sess;
struct ksmbd_tree_connect *tcon = work->tcon;
+ WORK_BUFFERS(work, req, rsp);
+
rsp->StructureSize = cpu_to_le16(4);
inc_rfc1001_len(work->response_buf, 4);
ksmbd_debug(SMB, "request\n");
if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
- struct smb2_tree_disconnect_req *req =
- smb2_get_msg(work->request_buf);
-
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -2126,10 +2128,14 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_logoff_req *req;
+ struct smb2_logoff_rsp *rsp;
struct ksmbd_session *sess;
- struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
- u64 sess_id = le64_to_cpu(req->hdr.SessionId);
+ u64 sess_id;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ sess_id = le64_to_cpu(req->hdr.SessionId);
rsp->StructureSize = cpu_to_le16(4);
inc_rfc1001_len(work->response_buf, 4);
@@ -2169,12 +2175,14 @@ int smb2_session_logoff(struct ksmbd_work *work)
*/
static noinline int create_smb2_pipe(struct ksmbd_work *work)
{
- struct smb2_create_rsp *rsp = smb2_get_msg(work->response_buf);
- struct smb2_create_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_create_rsp *rsp;
+ struct smb2_create_req *req;
int id;
int err;
char *name;
+ WORK_BUFFERS(work, req, rsp);
+
name = smb_strndup_from_utf16(req->Buffer, le16_to_cpu(req->NameLength),
1, work->conn->local_nls);
if (IS_ERR(name)) {
@@ -5314,8 +5322,10 @@ int smb2_query_info(struct ksmbd_work *work)
static noinline int smb2_close_pipe(struct ksmbd_work *work)
{
u64 id;
- struct smb2_close_req *req = smb2_get_msg(work->request_buf);
- struct smb2_close_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_close_req *req;
+ struct smb2_close_rsp *rsp;
+
+ WORK_BUFFERS(work, req, rsp);
id = req->VolatileFileId;
ksmbd_session_rpc_close(work->sess, id);
@@ -5457,6 +5467,9 @@ int smb2_echo(struct ksmbd_work *work)
{
struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
+ if (work->next_smb2_rcv_hdr_off)
+ rsp = ksmbd_resp_buf_next(work);
+
rsp->StructureSize = cpu_to_le16(4);
rsp->Reserved = 0;
inc_rfc1001_len(work->response_buf, 4);
@@ -6093,8 +6106,10 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
int nbytes = 0, err;
u64 id;
struct ksmbd_rpc_command *rpc_resp;
- struct smb2_read_req *req = smb2_get_msg(work->request_buf);
- struct smb2_read_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_read_req *req;
+ struct smb2_read_rsp *rsp;
+
+ WORK_BUFFERS(work, req, rsp);
id = req->VolatileFileId;
@@ -6347,14 +6362,16 @@ int smb2_read(struct ksmbd_work *work)
*/
static noinline int smb2_write_pipe(struct ksmbd_work *work)
{
- struct smb2_write_req *req = smb2_get_msg(work->request_buf);
- struct smb2_write_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_write_req *req;
+ struct smb2_write_rsp *rsp;
struct ksmbd_rpc_command *rpc_resp;
u64 id = 0;
int err = 0, ret = 0;
char *data_buf;
size_t length;
+ WORK_BUFFERS(work, req, rsp);
+
length = le32_to_cpu(req->Length);
id = req->VolatileFileId;
@@ -6623,6 +6640,9 @@ int smb2_cancel(struct ksmbd_work *work)
struct ksmbd_work *iter;
struct list_head *command_list;
+ if (work->next_smb2_rcv_hdr_off)
+ hdr = ksmbd_resp_buf_next(work);
+
ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
hdr->MessageId, hdr->Flags);
@@ -6782,8 +6802,8 @@ static inline bool lock_defer_pending(struct file_lock *fl)
*/
int smb2_lock(struct ksmbd_work *work)
{
- struct smb2_lock_req *req = smb2_get_msg(work->request_buf);
- struct smb2_lock_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_lock_req *req;
+ struct smb2_lock_rsp *rsp;
struct smb2_lock_element *lock_ele;
struct ksmbd_file *fp = NULL;
struct file_lock *flock = NULL;
@@ -6800,6 +6820,8 @@ int smb2_lock(struct ksmbd_work *work)
LIST_HEAD(rollback_list);
int prior_lock = 0;
+ WORK_BUFFERS(work, req, rsp);
+
ksmbd_debug(SMB, "Received lock request\n");
fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
if (!fp) {
@@ -7913,8 +7935,8 @@ int smb2_ioctl(struct ksmbd_work *work)
*/
static void smb20_oplock_break_ack(struct ksmbd_work *work)
{
- struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
- struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_oplock_break *req;
+ struct smb2_oplock_break *rsp;
struct ksmbd_file *fp;
struct oplock_info *opinfo = NULL;
__le32 err = 0;
@@ -7923,6 +7945,8 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
char req_oplevel = 0, rsp_oplevel = 0;
unsigned int oplock_change_type;
+ WORK_BUFFERS(work, req, rsp);
+
volatile_id = req->VolatileFid;
persistent_id = req->PersistentFid;
req_oplevel = req->OplockLevel;
@@ -8057,8 +8081,8 @@ static int check_lease_state(struct lease *lease, __le32 req_state)
static void smb21_lease_break_ack(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_lease_ack *req = smb2_get_msg(work->request_buf);
- struct smb2_lease_ack *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_lease_ack *req;
+ struct smb2_lease_ack *rsp;
struct oplock_info *opinfo;
__le32 err = 0;
int ret = 0;
@@ -8066,6 +8090,8 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
__le32 lease_state;
struct lease *lease;
+ WORK_BUFFERS(work, req, rsp);
+
ksmbd_debug(OPLOCK, "smb21 lease break, lease state(0x%x)\n",
le32_to_cpu(req->LeaseState));
opinfo = lookup_lease_in_table(conn, req->LeaseKey);
@@ -8191,8 +8217,10 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
*/
int smb2_oplock_break(struct ksmbd_work *work)
{
- struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
- struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_oplock_break *req;
+ struct smb2_oplock_break *rsp;
+
+ WORK_BUFFERS(work, req, rsp);
switch (le16_to_cpu(req->StructureSize)) {
case OP_BREAK_STRUCT_SIZE_20:
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 112/154] ksmbd: Use struct_size() helper in ksmbd_negotiate_smb_dialect()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (110 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 111/154] ksmbd: add missing compound request handing in some commands Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 113/154] ksmbd: Replace one-element array with flexible-array member Namjae Jeon
` (42 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Gustavo A. R. Silva, Kees Cook, Namjae Jeon,
Sergey Senozhatsky, Steve French
From: "Gustavo A. R. Silva" <gustavoars@kernel.org>
[ Upstream commit 5211cc8727ed9701b04976ab47602955e5641bda ]
Prefer struct_size() over open-coded versions.
Link: https://github.com/KSPP/linux/issues/160
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb_common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index 08d95e1ecc5e..f7c907143834 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -266,7 +266,7 @@ static int ksmbd_negotiate_smb_dialect(void *buf)
if (smb2_neg_size > smb_buf_length)
goto err_out;
- if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
+ if (struct_size(req, Dialects, le16_to_cpu(req->DialectCount)) >
smb_buf_length)
goto err_out;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 113/154] ksmbd: Replace one-element array with flexible-array member
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (111 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 112/154] ksmbd: Use struct_size() helper in ksmbd_negotiate_smb_dialect() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 114/154] ksmbd: Fix unsigned expression compared with zero Namjae Jeon
` (41 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Gustavo A. R. Silva, Kees Cook, Namjae Jeon,
Sergey Senozhatsky, Steve French
From: "Gustavo A. R. Silva" <gustavoars@kernel.org>
[ Upstream commit 11d5e2061e973a8d4ff2b95a114b4b8ef8652633 ]
One-element arrays are deprecated, and we are replacing them with flexible
array members instead. So, replace one-element array with flexible-array
member in struct smb_negotiate_req.
This results in no differences in binary output.
Link: https://github.com/KSPP/linux/issues/79
Link: https://github.com/KSPP/linux/issues/317
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb_common.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
index e4a1eb6f8da3..1db027e730e9 100644
--- a/fs/ksmbd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -247,7 +247,7 @@ struct smb_hdr {
struct smb_negotiate_req {
struct smb_hdr hdr; /* wct = 0 */
__le16 ByteCount;
- unsigned char DialectsArray[1];
+ unsigned char DialectsArray[];
} __packed;
struct smb_negotiate_rsp {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 114/154] ksmbd: Fix unsigned expression compared with zero
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (112 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 113/154] ksmbd: Replace one-element array with flexible-array member Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 115/154] ksmbd: check if a mount point is crossed during path lookup Namjae Jeon
` (40 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Wang Ming, Tom Talpey, Namjae Jeon, Steve French
From: Wang Ming <machel@vivo.com>
[ Upstream commit 0266a2f791294e0b4ba36f4a1d89b8615ea3cac0 ]
The return value of the ksmbd_vfs_getcasexattr() is signed.
However, the return value is being assigned to an unsigned
variable and subsequently recasted, causing warnings. Use
a signed type.
Signed-off-by: Wang Ming <machel@vivo.com>
Acked-by: Tom Talpey <tom@talpey.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 2b938ebdfd2a..f2013963cef0 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -412,7 +412,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
{
char *stream_buf = NULL, *wbuf;
struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
- size_t size, v_len;
+ size_t size;
+ ssize_t v_len;
int err = 0;
ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n",
@@ -429,9 +430,9 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
fp->stream.name,
fp->stream.size,
&stream_buf);
- if ((int)v_len < 0) {
+ if (v_len < 0) {
pr_err("not found stream in xattr : %zd\n", v_len);
- err = (int)v_len;
+ err = v_len;
goto out;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 115/154] ksmbd: check if a mount point is crossed during path lookup
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (113 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 114/154] ksmbd: Fix unsigned expression compared with zero Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 116/154] ksmbd: validate session id and tree id in compound request Namjae Jeon
` (39 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 2b57a4322b1b14348940744fdc02f9a86cbbdbeb ]
Since commit 74d7970febf7 ("ksmbd: fix racy issue from using ->d_parent and
->d_name"), ksmbd can not lookup cross mount points. If last component is
a cross mount point during path lookup, check if it is crossed to follow it
down. And allow path lookup to cross a mount point when a crossmnt
parameter is set to 'yes' in smb.conf.
Cc: stable@vger.kernel.org
Fixes: 74d7970febf7 ("ksmbd: fix racy issue from using ->d_parent and ->d_name")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_netlink.h | 3 ++-
fs/ksmbd/smb2pdu.c | 27 +++++++++++--------
fs/ksmbd/vfs.c | 58 +++++++++++++++++++++++-----------------
fs/ksmbd/vfs.h | 4 +--
4 files changed, 53 insertions(+), 39 deletions(-)
diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
index fb9626383f86..821ed8e3cbee 100644
--- a/fs/ksmbd/ksmbd_netlink.h
+++ b/fs/ksmbd/ksmbd_netlink.h
@@ -352,7 +352,8 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_SHARE_FLAG_STREAMS BIT(11)
#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12)
#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)
/*
* Tree connect request flags.
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 964e7182605b..870b0fc9d2f3 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2475,8 +2475,9 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
}
}
-static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
- int open_flags, umode_t posix_mode, bool is_dir)
+static int smb2_creat(struct ksmbd_work *work, struct path *parent_path,
+ struct path *path, char *name, int open_flags,
+ umode_t posix_mode, bool is_dir)
{
struct ksmbd_tree_connect *tcon = work->tcon;
struct ksmbd_share_config *share = tcon->share_conf;
@@ -2503,7 +2504,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
return rc;
}
- rc = ksmbd_vfs_kern_path_locked(work, name, 0, path, 0);
+ rc = ksmbd_vfs_kern_path_locked(work, name, 0, parent_path, path, 0);
if (rc) {
pr_err("cannot get linux path (%s), err = %d\n",
name, rc);
@@ -2570,7 +2571,7 @@ int smb2_open(struct ksmbd_work *work)
struct ksmbd_tree_connect *tcon = work->tcon;
struct smb2_create_req *req;
struct smb2_create_rsp *rsp;
- struct path path;
+ struct path path, parent_path;
struct ksmbd_share_config *share = tcon->share_conf;
struct ksmbd_file *fp = NULL;
struct file *filp = NULL;
@@ -2791,7 +2792,8 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
- rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
+ rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS,
+ &parent_path, &path, 1);
if (!rc) {
file_present = true;
@@ -2911,7 +2913,8 @@ int smb2_open(struct ksmbd_work *work)
/*create file if not present */
if (!file_present) {
- rc = smb2_creat(work, &path, name, open_flags, posix_mode,
+ rc = smb2_creat(work, &parent_path, &path, name, open_flags,
+ posix_mode,
req->CreateOptions & FILE_DIRECTORY_FILE_LE);
if (rc) {
if (rc == -ENOENT) {
@@ -3326,8 +3329,9 @@ int smb2_open(struct ksmbd_work *work)
err_out:
if (file_present || created) {
- inode_unlock(d_inode(path.dentry->d_parent));
- dput(path.dentry);
+ inode_unlock(d_inode(parent_path.dentry));
+ path_put(&path);
+ path_put(&parent_path);
}
ksmbd_revert_fsids(work);
err_out1:
@@ -5553,7 +5557,7 @@ static int smb2_create_link(struct ksmbd_work *work,
struct nls_table *local_nls)
{
char *link_name = NULL, *target_name = NULL, *pathname = NULL;
- struct path path;
+ struct path path, parent_path;
bool file_present = false;
int rc;
@@ -5583,7 +5587,7 @@ static int smb2_create_link(struct ksmbd_work *work,
ksmbd_debug(SMB, "target name is %s\n", target_name);
rc = ksmbd_vfs_kern_path_locked(work, link_name, LOOKUP_NO_SYMLINKS,
- &path, 0);
+ &parent_path, &path, 0);
if (rc) {
if (rc != -ENOENT)
goto out;
@@ -5613,8 +5617,9 @@ static int smb2_create_link(struct ksmbd_work *work,
rc = -EINVAL;
out:
if (file_present) {
- inode_unlock(d_inode(path.dentry->d_parent));
+ inode_unlock(d_inode(parent_path.dentry));
path_put(&path);
+ path_put(&parent_path);
}
if (!IS_ERR(link_name))
kfree(link_name);
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index f2013963cef0..8cb46abf2c76 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -63,13 +63,13 @@ int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
char *pathname, unsigned int flags,
+ struct path *parent_path,
struct path *path)
{
struct qstr last;
struct filename *filename;
struct path *root_share_path = &share_conf->vfs_path;
int err, type;
- struct path parent_path;
struct dentry *d;
if (pathname[0] == '\0') {
@@ -84,7 +84,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
return PTR_ERR(filename);
err = vfs_path_parent_lookup(filename, flags,
- &parent_path, &last, &type,
+ parent_path, &last, &type,
root_share_path);
if (err) {
putname(filename);
@@ -92,13 +92,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
}
if (unlikely(type != LAST_NORM)) {
- path_put(&parent_path);
+ path_put(parent_path);
putname(filename);
return -ENOENT;
}
- inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
- d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
+ inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT);
+ d = lookup_one_qstr_excl(&last, parent_path->dentry, 0);
if (IS_ERR(d))
goto err_out;
@@ -108,15 +108,22 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
}
path->dentry = d;
- path->mnt = share_conf->vfs_path.mnt;
- path_put(&parent_path);
- putname(filename);
+ path->mnt = mntget(parent_path->mnt);
+
+ if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_CROSSMNT)) {
+ err = follow_down(path);
+ if (err < 0) {
+ path_put(path);
+ goto err_out;
+ }
+ }
+ putname(filename);
return 0;
err_out:
- inode_unlock(parent_path.dentry->d_inode);
- path_put(&parent_path);
+ inode_unlock(d_inode(parent_path->dentry));
+ path_put(parent_path);
putname(filename);
return -ENOENT;
}
@@ -1197,14 +1204,14 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
* Return: 0 on success, otherwise error
*/
int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
- unsigned int flags, struct path *path,
- bool caseless)
+ unsigned int flags, struct path *parent_path,
+ struct path *path, bool caseless)
{
struct ksmbd_share_config *share_conf = work->tcon->share_conf;
int err;
- struct path parent_path;
- err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, path);
+ err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, parent_path,
+ path);
if (!err)
return 0;
@@ -1219,10 +1226,10 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
path_len = strlen(filepath);
remain_len = path_len;
- parent_path = share_conf->vfs_path;
- path_get(&parent_path);
+ *parent_path = share_conf->vfs_path;
+ path_get(parent_path);
- while (d_can_lookup(parent_path.dentry)) {
+ while (d_can_lookup(parent_path->dentry)) {
char *filename = filepath + path_len - remain_len;
char *next = strchrnul(filename, '/');
size_t filename_len = next - filename;
@@ -1231,7 +1238,7 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
if (filename_len == 0)
break;
- err = ksmbd_vfs_lookup_in_dir(&parent_path, filename,
+ err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
filename_len,
work->conn->um);
if (err)
@@ -1248,8 +1255,8 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
goto out2;
else if (is_last)
goto out1;
- path_put(&parent_path);
- parent_path = *path;
+ path_put(parent_path);
+ *parent_path = *path;
next[0] = '/';
remain_len -= filename_len + 1;
@@ -1257,16 +1264,17 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
err = -EINVAL;
out2:
- path_put(&parent_path);
+ path_put(parent_path);
out1:
kfree(filepath);
}
if (!err) {
- err = ksmbd_vfs_lock_parent(parent_path.dentry, path->dentry);
- if (err)
- dput(path->dentry);
- path_put(&parent_path);
+ err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
+ if (err) {
+ path_put(path);
+ path_put(parent_path);
+ }
}
return err;
}
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index 2e87136f9eba..b544c882c611 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -154,8 +154,8 @@ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
const struct path *path, char *attr_name);
int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
- unsigned int flags, struct path *path,
- bool caseless);
+ unsigned int flags, struct path *parent_path,
+ struct path *path, bool caseless);
struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
const char *name,
unsigned int flags,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 116/154] ksmbd: validate session id and tree id in compound request
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (114 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 115/154] ksmbd: check if a mount point is crossed during path lookup Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 117/154] ksmbd: fix out of bounds in init_smb2_rsp_hdr() Namjae Jeon
` (38 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit 3df0411e132ee74a87aa13142dfd2b190275332e ]
`smb2_get_msg()` in smb2_get_ksmbd_tcon() and smb2_check_user_session()
will always return the first request smb2 header in a compound request.
if `SMB2_TREE_CONNECT_HE` is the first command in compound request, will
return 0, i.e. The tree id check is skipped.
This patch use ksmbd_req_buf_next() to get current command in compound.
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21506
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 870b0fc9d2f3..27c86f2de393 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -87,9 +87,9 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn
*/
int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
{
- struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
unsigned int cmd = le16_to_cpu(req_hdr->Command);
- int tree_id;
+ unsigned int tree_id;
if (cmd == SMB2_TREE_CONNECT_HE ||
cmd == SMB2_CANCEL_HE ||
@@ -114,7 +114,7 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
pr_err("The first operation in the compound does not have tcon\n");
return -EINVAL;
}
- if (work->tcon->id != tree_id) {
+ if (tree_id != UINT_MAX && work->tcon->id != tree_id) {
pr_err("tree id(%u) is different with id(%u) in first operation\n",
tree_id, work->tcon->id);
return -EINVAL;
@@ -560,9 +560,9 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
*/
int smb2_check_user_session(struct ksmbd_work *work)
{
- struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
struct ksmbd_conn *conn = work->conn;
- unsigned int cmd = conn->ops->get_cmd_val(work);
+ unsigned int cmd = le16_to_cpu(req_hdr->Command);
unsigned long long sess_id;
/*
@@ -588,7 +588,7 @@ int smb2_check_user_session(struct ksmbd_work *work)
pr_err("The first operation in the compound does not have sess\n");
return -EINVAL;
}
- if (work->sess->id != sess_id) {
+ if (sess_id != ULLONG_MAX && work->sess->id != sess_id) {
pr_err("session id(%llu) is different with the first operation(%lld)\n",
sess_id, work->sess->id);
return -EINVAL;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 117/154] ksmbd: fix out of bounds in init_smb2_rsp_hdr()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (115 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 116/154] ksmbd: validate session id and tree id in compound request Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 118/154] ksmbd: switch to use kmemdup_nul() helper Namjae Jeon
` (37 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit 536bb492d39bb6c080c92f31e8a55fe9934f452b ]
If client send smb2 negotiate request and then send smb1 negotiate
request, init_smb2_rsp_hdr is called for smb1 negotiate request since
need_neg is set to false. This patch ignore smb1 packets after ->need_neg
is set to false.
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21541
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/server.c | 7 ++++++-
fs/ksmbd/smb_common.c | 19 +++++++++++--------
fs/ksmbd/smb_common.h | 2 +-
3 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index 14df83c20557..0c0db2e614ef 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -286,6 +286,7 @@ static void handle_ksmbd_work(struct work_struct *wk)
static int queue_ksmbd_work(struct ksmbd_conn *conn)
{
struct ksmbd_work *work;
+ int err;
work = ksmbd_alloc_work_struct();
if (!work) {
@@ -297,7 +298,11 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
work->request_buf = conn->request_buf;
conn->request_buf = NULL;
- ksmbd_init_smb_server(work);
+ err = ksmbd_init_smb_server(work);
+ if (err) {
+ ksmbd_free_work_struct(work);
+ return 0;
+ }
ksmbd_conn_enqueue_request(work);
atomic_inc(&conn->r_count);
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index f7c907143834..c13616857927 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -388,26 +388,29 @@ static struct smb_version_cmds smb1_server_cmds[1] = {
[SMB_COM_NEGOTIATE_EX] = { .proc = smb1_negotiate, },
};
-static void init_smb1_server(struct ksmbd_conn *conn)
+static int init_smb1_server(struct ksmbd_conn *conn)
{
conn->ops = &smb1_server_ops;
conn->cmds = smb1_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+ return 0;
}
-void ksmbd_init_smb_server(struct ksmbd_work *work)
+int ksmbd_init_smb_server(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
__le32 proto;
- if (conn->need_neg == false)
- return;
-
proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+ if (conn->need_neg == false) {
+ if (proto == SMB1_PROTO_NUMBER)
+ return -EINVAL;
+ return 0;
+ }
+
if (proto == SMB1_PROTO_NUMBER)
- init_smb1_server(conn);
- else
- init_smb3_11_server(conn);
+ return init_smb1_server(conn);
+ return init_smb3_11_server(conn);
}
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
index 1db027e730e9..c4978579c541 100644
--- a/fs/ksmbd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -474,7 +474,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
-void ksmbd_init_smb_server(struct ksmbd_work *work);
+int ksmbd_init_smb_server(struct ksmbd_work *work);
struct ksmbd_kstat;
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 118/154] ksmbd: switch to use kmemdup_nul() helper
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (116 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 117/154] ksmbd: fix out of bounds in init_smb2_rsp_hdr() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 119/154] ksmbd: add support for read compound Namjae Jeon
` (36 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Yang Yingliang, Namjae Jeon, Steve French
From: Yang Yingliang <yangyingliang@huawei.com>
[ Upstream commit 084ba46fc41c21ba827fd92e61f78def7a6e52ea ]
Use kmemdup_nul() helper instead of open-coding to
simplify the code.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/asn1.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c
index cc6384f79675..4a4b2b03ff33 100644
--- a/fs/ksmbd/asn1.c
+++ b/fs/ksmbd/asn1.c
@@ -214,12 +214,10 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
{
struct ksmbd_conn *conn = context;
- conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
+ conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL);
if (!conn->mechToken)
return -ENOMEM;
- memcpy(conn->mechToken, value, vlen);
- conn->mechToken[vlen] = '\0';
return 0;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 119/154] ksmbd: add support for read compound
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (117 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 118/154] ksmbd: switch to use kmemdup_nul() helper Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 120/154] ksmbd: fix wrong interim response on compound Namjae Jeon
` (35 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit e2b76ab8b5c9327ab2dae6da05d0752eb2f4771d ]
MacOS sends a compound request including read to the server
(e.g. open-read-close). So far, ksmbd has not handled read as
a compound request. For compatibility between ksmbd and an OS that
supports SMB, This patch provides compound support for read requests.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 11 +-
fs/ksmbd/connection.c | 55 ++--
fs/ksmbd/connection.h | 2 +-
fs/ksmbd/ksmbd_work.c | 91 ++++++-
fs/ksmbd/ksmbd_work.h | 34 ++-
fs/ksmbd/oplock.c | 17 +-
fs/ksmbd/server.c | 8 +-
fs/ksmbd/smb2pdu.c | 510 ++++++++++++++++----------------------
fs/ksmbd/smb_common.c | 13 +-
fs/ksmbd/transport_rdma.c | 4 +-
fs/ksmbd/vfs.c | 4 +-
fs/ksmbd/vfs.h | 4 +-
12 files changed, 381 insertions(+), 372 deletions(-)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index df8fb076f6f1..ee912d24ad94 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -1029,11 +1029,15 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
{
struct scatterlist *sg;
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
- int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
+ int i, *nr_entries, total_entries = 0, sg_idx = 0;
if (!nvec)
return NULL;
+ nr_entries = kcalloc(nvec, sizeof(int), GFP_KERNEL);
+ if (!nr_entries)
+ return NULL;
+
for (i = 0; i < nvec - 1; i++) {
unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
@@ -1051,8 +1055,10 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
total_entries += 2;
sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
- if (!sg)
+ if (!sg) {
+ kfree(nr_entries);
return NULL;
+ }
sg_init_table(sg, total_entries);
smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
@@ -1086,6 +1092,7 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
}
}
smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
+ kfree(nr_entries);
return sg;
}
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 99ea5f1b324d..585f117bda8a 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -123,28 +123,22 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
}
}
-int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
+void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- int ret = 1;
if (list_empty(&work->request_entry) &&
list_empty(&work->async_request_entry))
- return 0;
+ return;
- if (!work->multiRsp)
- atomic_dec(&conn->req_running);
- if (!work->multiRsp) {
- spin_lock(&conn->request_lock);
- list_del_init(&work->request_entry);
- spin_unlock(&conn->request_lock);
- if (work->asynchronous)
- release_async_work(work);
- ret = 0;
- }
+ atomic_dec(&conn->req_running);
+ spin_lock(&conn->request_lock);
+ list_del_init(&work->request_entry);
+ spin_unlock(&conn->request_lock);
+ if (work->asynchronous)
+ release_async_work(work);
wake_up_all(&conn->req_running_q);
- return ret;
}
void ksmbd_conn_lock(struct ksmbd_conn *conn)
@@ -193,41 +187,22 @@ void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
int ksmbd_conn_write(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- size_t len = 0;
int sent;
- struct kvec iov[3];
- int iov_idx = 0;
if (!work->response_buf) {
pr_err("NULL response header\n");
return -EINVAL;
}
- if (work->tr_buf) {
- iov[iov_idx] = (struct kvec) { work->tr_buf,
- sizeof(struct smb2_transform_hdr) + 4 };
- len += iov[iov_idx++].iov_len;
- }
-
- if (work->aux_payload_sz) {
- iov[iov_idx] = (struct kvec) { work->response_buf, work->resp_hdr_sz };
- len += iov[iov_idx++].iov_len;
- iov[iov_idx] = (struct kvec) { work->aux_payload_buf, work->aux_payload_sz };
- len += iov[iov_idx++].iov_len;
- } else {
- if (work->tr_buf)
- iov[iov_idx].iov_len = work->resp_hdr_sz;
- else
- iov[iov_idx].iov_len = get_rfc1002_len(work->response_buf) + 4;
- iov[iov_idx].iov_base = work->response_buf;
- len += iov[iov_idx++].iov_len;
- }
+ if (work->send_no_response)
+ return 0;
ksmbd_conn_lock(conn);
- sent = conn->transport->ops->writev(conn->transport, &iov[0],
- iov_idx, len,
- work->need_invalidate_rkey,
- work->remote_key);
+ sent = conn->transport->ops->writev(conn->transport, work->iov,
+ work->iov_cnt,
+ get_rfc1002_len(work->iov[0].iov_base) + 4,
+ work->need_invalidate_rkey,
+ work->remote_key);
ksmbd_conn_unlock(conn);
if (sent < 0) {
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index ad8dfaa48ffb..ab2583f030ce 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -158,7 +158,7 @@ int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
struct smb2_buffer_desc_v1 *desc,
unsigned int desc_len);
void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
-int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
+void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
int ksmbd_conn_handler_loop(void *p);
int ksmbd_conn_transport_init(void);
diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
index 14b9caebf7a4..f49c2e01ea9f 100644
--- a/fs/ksmbd/ksmbd_work.c
+++ b/fs/ksmbd/ksmbd_work.c
@@ -27,18 +27,35 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void)
INIT_LIST_HEAD(&work->async_request_entry);
INIT_LIST_HEAD(&work->fp_entry);
INIT_LIST_HEAD(&work->interim_entry);
+ INIT_LIST_HEAD(&work->aux_read_list);
+ work->iov_alloc_cnt = 4;
+ work->iov = kcalloc(work->iov_alloc_cnt, sizeof(struct kvec),
+ GFP_KERNEL);
+ if (!work->iov) {
+ kmem_cache_free(work_cache, work);
+ work = NULL;
+ }
}
return work;
}
void ksmbd_free_work_struct(struct ksmbd_work *work)
{
+ struct aux_read *ar, *tmp;
+
WARN_ON(work->saved_cred != NULL);
kvfree(work->response_buf);
- kvfree(work->aux_payload_buf);
+
+ list_for_each_entry_safe(ar, tmp, &work->aux_read_list, entry) {
+ kvfree(ar->buf);
+ list_del(&ar->entry);
+ kfree(ar);
+ }
+
kfree(work->tr_buf);
kvfree(work->request_buf);
+ kfree(work->iov);
if (work->async_id)
ksmbd_release_id(&work->conn->async_ida, work->async_id);
kmem_cache_free(work_cache, work);
@@ -77,3 +94,75 @@ bool ksmbd_queue_work(struct ksmbd_work *work)
{
return queue_work(ksmbd_wq, &work->work);
}
+
+static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib,
+ unsigned int ib_len)
+{
+
+ if (work->iov_alloc_cnt <= work->iov_cnt) {
+ struct kvec *new;
+
+ work->iov_alloc_cnt += 4;
+ new = krealloc(work->iov,
+ sizeof(struct kvec) * work->iov_alloc_cnt,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!new)
+ return -ENOMEM;
+ work->iov = new;
+ }
+
+ work->iov[++work->iov_idx].iov_base = ib;
+ work->iov[work->iov_idx].iov_len = ib_len;
+ work->iov_cnt++;
+
+ return 0;
+}
+
+static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
+ void *aux_buf, unsigned int aux_size)
+{
+ /* Plus rfc_length size on first iov */
+ if (!work->iov_idx) {
+ work->iov[work->iov_idx].iov_base = work->response_buf;
+ *(__be32 *)work->iov[0].iov_base = 0;
+ work->iov[work->iov_idx].iov_len = 4;
+ work->iov_cnt++;
+ }
+
+ ksmbd_realloc_iov_pin(work, ib, len);
+ inc_rfc1001_len(work->iov[0].iov_base, len);
+
+ if (aux_size) {
+ struct aux_read *ar;
+
+ ksmbd_realloc_iov_pin(work, aux_buf, aux_size);
+ inc_rfc1001_len(work->iov[0].iov_base, aux_size);
+
+ ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
+ if (!ar)
+ return -ENOMEM;
+
+ ar->buf = aux_buf;
+ list_add(&ar->entry, &work->aux_read_list);
+ }
+
+ return 0;
+}
+
+int ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len)
+{
+ return __ksmbd_iov_pin_rsp(work, ib, len, NULL, 0);
+}
+
+int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
+ void *aux_buf, unsigned int aux_size)
+{
+ return __ksmbd_iov_pin_rsp(work, ib, len, aux_buf, aux_size);
+}
+
+void ksmbd_iov_reset(struct ksmbd_work *work)
+{
+ work->iov_idx = 0;
+ work->iov_cnt = 0;
+ *(__be32 *)work->iov[0].iov_base = 0;
+}
diff --git a/fs/ksmbd/ksmbd_work.h b/fs/ksmbd/ksmbd_work.h
index f8ae6144c0ae..255157eb26dc 100644
--- a/fs/ksmbd/ksmbd_work.h
+++ b/fs/ksmbd/ksmbd_work.h
@@ -19,6 +19,11 @@ enum {
KSMBD_WORK_CLOSED,
};
+struct aux_read {
+ void *buf;
+ struct list_head entry;
+};
+
/* one of these for every pending CIFS request at the connection */
struct ksmbd_work {
/* Server corresponding to this mid */
@@ -31,13 +36,19 @@ struct ksmbd_work {
/* Response buffer */
void *response_buf;
- /* Read data buffer */
- void *aux_payload_buf;
+ struct list_head aux_read_list;
+
+ struct kvec *iov;
+ int iov_alloc_cnt;
+ int iov_cnt;
+ int iov_idx;
/* Next cmd hdr in compound req buf*/
int next_smb2_rcv_hdr_off;
/* Next cmd hdr in compound rsp buf*/
int next_smb2_rsp_hdr_off;
+ /* Current cmd hdr in compound rsp buf*/
+ int curr_smb2_rsp_hdr_off;
/*
* Current Local FID assigned compound response if SMB2 CREATE
@@ -53,16 +64,11 @@ struct ksmbd_work {
unsigned int credits_granted;
/* response smb header size */
- unsigned int resp_hdr_sz;
unsigned int response_sz;
- /* Read data count */
- unsigned int aux_payload_sz;
void *tr_buf;
unsigned char state;
- /* Multiple responses for one request e.g. SMB ECHO */
- bool multiRsp:1;
/* No response for cancelled request */
bool send_no_response:1;
/* Request is encrypted */
@@ -95,6 +101,15 @@ static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
return work->response_buf + work->next_smb2_rsp_hdr_off + 4;
}
+/**
+ * ksmbd_resp_buf_curr - Get current buffer on compound response.
+ * @work: smb work containing response buffer
+ */
+static inline void *ksmbd_resp_buf_curr(struct ksmbd_work *work)
+{
+ return work->response_buf + work->curr_smb2_rsp_hdr_off + 4;
+}
+
/**
* ksmbd_req_buf_next - Get next buffer on compound request.
* @work: smb work containing response buffer
@@ -113,5 +128,8 @@ int ksmbd_work_pool_init(void);
int ksmbd_workqueue_init(void);
void ksmbd_workqueue_destroy(void);
bool ksmbd_queue_work(struct ksmbd_work *work);
-
+int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
+ void *aux_buf, unsigned int aux_size);
+int ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len);
+void ksmbd_iov_reset(struct ksmbd_work *work);
#endif /* __KSMBD_WORK_H__ */
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index e2fb4631f8f7..13c9842a089c 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -639,7 +639,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
{
struct smb2_oplock_break *rsp = NULL;
struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
- struct ksmbd_conn *conn = work->conn;
struct oplock_break_info *br_info = work->request_buf;
struct smb2_hdr *rsp_hdr;
struct ksmbd_file *fp;
@@ -656,8 +655,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
@@ -684,13 +681,15 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp->PersistentFid = fp->persistent_id;
rsp->VolatileFid = fp->volatile_id;
- inc_rfc1001_len(work->response_buf, 24);
+ ksmbd_fd_put(work, fp);
+ if (ksmbd_iov_pin_rsp(work, (void *)rsp,
+ sizeof(struct smb2_oplock_break)))
+ goto out;
ksmbd_debug(OPLOCK,
"sending oplock break v_id %llu p_id = %llu lock level = %d\n",
rsp->VolatileFid, rsp->PersistentFid, rsp->OplockLevel);
- ksmbd_fd_put(work, fp);
ksmbd_conn_write(work);
out:
@@ -751,7 +750,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
struct smb2_lease_break *rsp = NULL;
struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
struct lease_break_info *br_info = work->request_buf;
- struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *rsp_hdr;
if (allocate_oplock_break_buf(work)) {
@@ -761,8 +759,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
@@ -791,7 +787,9 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp->AccessMaskHint = 0;
rsp->ShareMaskHint = 0;
- inc_rfc1001_len(work->response_buf, 44);
+ if (ksmbd_iov_pin_rsp(work, (void *)rsp,
+ sizeof(struct smb2_lease_break)))
+ goto out;
ksmbd_conn_write(work);
@@ -845,6 +843,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
setup_async_work(in_work, NULL, NULL);
smb2_send_interim_resp(in_work, STATUS_PENDING);
list_del(&in_work->interim_entry);
+ ksmbd_iov_reset(in_work);
}
INIT_WORK(&work->work, __smb2_lease_break_noti);
ksmbd_queue_work(work);
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index 0c0db2e614ef..ff1514c79f16 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -163,6 +163,7 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
{
u16 command = 0;
int rc;
+ bool is_chained = false;
if (conn->ops->allocate_rsp_buf(work))
return;
@@ -229,14 +230,13 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
}
}
+ is_chained = is_chained_smb2_message(work);
+
if (work->sess &&
(work->sess->sign || smb3_11_final_sess_setup_resp(work) ||
conn->ops->is_sign_req(work, command)))
conn->ops->set_sign_rsp(work);
- } while (is_chained_smb2_message(work));
-
- if (work->send_no_response)
- return;
+ } while (is_chained == true);
send:
smb3_preauth_hash_rsp(work);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 27c86f2de393..bee7a022952b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -145,12 +145,18 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
err_rsp = smb2_get_msg(work->response_buf);
if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
+ int err;
+
err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE;
err_rsp->ErrorContextCount = 0;
err_rsp->Reserved = 0;
err_rsp->ByteCount = 0;
err_rsp->ErrorData[0] = 0;
- inc_rfc1001_len(work->response_buf, SMB2_ERROR_STRUCTURE_SIZE2);
+ err = ksmbd_iov_pin_rsp(work, (void *)err_rsp,
+ work->conn->vals->header_size +
+ SMB2_ERROR_STRUCTURE_SIZE2);
+ if (err)
+ work->send_no_response = 1;
}
}
@@ -245,9 +251,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
struct smb2_hdr *rsp_hdr;
struct smb2_negotiate_rsp *rsp;
struct ksmbd_conn *conn = work->conn;
-
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
+ int err;
rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
@@ -286,13 +290,14 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
le16_to_cpu(rsp->SecurityBufferOffset));
- inc_rfc1001_len(work->response_buf,
- sizeof(struct smb2_negotiate_rsp) -
- sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
- AUTH_GSS_LENGTH);
rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY)
rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
+ err = ksmbd_iov_pin_rsp(work, rsp,
+ sizeof(struct smb2_negotiate_rsp) -
+ sizeof(rsp->Buffer) + AUTH_GSS_LENGTH);
+ if (err)
+ return err;
conn->use_spnego = true;
ksmbd_conn_set_need_negotiate(conn);
@@ -391,11 +396,12 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
next_hdr_offset = le32_to_cpu(req->NextCommand);
new_len = ALIGN(len, 8);
- inc_rfc1001_len(work->response_buf,
- sizeof(struct smb2_hdr) + new_len - len);
+ work->iov[work->iov_idx].iov_len += (new_len - len);
+ inc_rfc1001_len(work->response_buf, new_len - len);
rsp->NextCommand = cpu_to_le32(new_len);
work->next_smb2_rcv_hdr_off += next_hdr_offset;
+ work->curr_smb2_rsp_hdr_off = work->next_smb2_rsp_hdr_off;
work->next_smb2_rsp_hdr_off += new_len;
ksmbd_debug(SMB,
"Compound req new_len = %d rcv off = %d rsp off = %d\n",
@@ -471,10 +477,10 @@ bool is_chained_smb2_message(struct ksmbd_work *work)
len = len - get_rfc1002_len(work->response_buf);
if (len) {
ksmbd_debug(SMB, "padding len %u\n", len);
+ work->iov[work->iov_idx].iov_len += len;
inc_rfc1001_len(work->response_buf, len);
- if (work->aux_payload_sz)
- work->aux_payload_sz += len;
}
+ work->curr_smb2_rsp_hdr_off = work->next_smb2_rsp_hdr_off;
}
return false;
}
@@ -489,11 +495,8 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
{
struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf);
struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf);
- struct ksmbd_conn *conn = work->conn;
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->Command = rcv_hdr->Command;
@@ -658,7 +661,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
struct ksmbd_conn *conn = work->conn;
int id;
- rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr = ksmbd_resp_buf_next(work);
rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
id = ksmbd_acquire_async_msg_id(&conn->async_ida);
@@ -708,14 +711,12 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
{
struct smb2_hdr *rsp_hdr;
- rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr = ksmbd_resp_buf_next(work);
smb2_set_err_rsp(work);
rsp_hdr->Status = status;
- work->multiRsp = 1;
ksmbd_conn_write(work);
rsp_hdr->Status = 0;
- work->multiRsp = 0;
}
static __le32 smb2_get_reparse_tag_special_file(umode_t mode)
@@ -822,9 +823,8 @@ static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
pneg_ctxt->Name[15] = 0x7C;
}
-static void assemble_neg_contexts(struct ksmbd_conn *conn,
- struct smb2_negotiate_rsp *rsp,
- void *smb2_buf_len)
+static unsigned int assemble_neg_contexts(struct ksmbd_conn *conn,
+ struct smb2_negotiate_rsp *rsp)
{
char * const pneg_ctxt = (char *)rsp +
le32_to_cpu(rsp->NegotiateContextOffset);
@@ -835,7 +835,6 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
"assemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt,
conn->preauth_info->Preauth_HashId);
- inc_rfc1001_len(smb2_buf_len, AUTH_GSS_PADDING);
ctxt_size = sizeof(struct smb2_preauth_neg_context);
if (conn->cipher_type) {
@@ -874,7 +873,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
}
rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
- inc_rfc1001_len(smb2_buf_len, ctxt_size);
+ return ctxt_size + AUTH_GSS_PADDING;
}
static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
@@ -1090,7 +1089,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf);
struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf);
int rc = 0;
- unsigned int smb2_buf_len, smb2_neg_size;
+ unsigned int smb2_buf_len, smb2_neg_size, neg_ctxt_len = 0;
__le32 status;
ksmbd_debug(SMB, "Received negotiate request\n");
@@ -1183,7 +1182,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
conn->preauth_info->Preauth_HashValue);
rsp->NegotiateContextOffset =
cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
- assemble_neg_contexts(conn, rsp, work->response_buf);
+ neg_ctxt_len = assemble_neg_contexts(conn, rsp);
break;
case SMB302_PROT_ID:
init_smb3_02_server(conn);
@@ -1233,9 +1232,6 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
le16_to_cpu(rsp->SecurityBufferOffset));
- inc_rfc1001_len(work->response_buf, sizeof(struct smb2_negotiate_rsp) -
- sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
- AUTH_GSS_LENGTH);
rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
conn->use_spnego = true;
@@ -1253,9 +1249,16 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
ksmbd_conn_set_need_negotiate(conn);
err_out:
+ if (rc)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ if (!rc)
+ rc = ksmbd_iov_pin_rsp(work, rsp,
+ sizeof(struct smb2_negotiate_rsp) -
+ sizeof(rsp->Buffer) +
+ AUTH_GSS_LENGTH + neg_ctxt_len);
if (rc < 0)
smb2_set_err_rsp(work);
-
return rc;
}
@@ -1455,7 +1458,6 @@ static int ntlm_authenticate(struct ksmbd_work *work,
memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
kfree(spnego_blob);
- inc_rfc1001_len(work->response_buf, spnego_blob_len - 1);
}
user = session_user(conn, req);
@@ -1601,7 +1603,6 @@ static int krb5_authenticate(struct ksmbd_work *work,
return -EINVAL;
}
rsp->SecurityBufferLength = cpu_to_le16(out_len);
- inc_rfc1001_len(work->response_buf, out_len - 1);
if ((conn->sign || server_conf.enforced_signing) ||
(req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
@@ -1673,7 +1674,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
rsp->SessionFlags = 0;
rsp->SecurityBufferOffset = cpu_to_le16(72);
rsp->SecurityBufferLength = 0;
- inc_rfc1001_len(work->response_buf, 9);
ksmbd_conn_lock(conn);
if (!req->hdr.SessionId) {
@@ -1809,13 +1809,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
goto out_err;
rsp->hdr.Status =
STATUS_MORE_PROCESSING_REQUIRED;
- /*
- * Note: here total size -1 is done as an
- * adjustment for 0 size blob
- */
- inc_rfc1001_len(work->response_buf,
- le16_to_cpu(rsp->SecurityBufferLength) - 1);
-
} else if (negblob->MessageType == NtLmAuthenticate) {
rc = ntlm_authenticate(work, req, rsp);
if (rc)
@@ -1900,6 +1893,17 @@ int smb2_sess_setup(struct ksmbd_work *work)
ksmbd_conn_set_need_negotiate(conn);
}
}
+ } else {
+ unsigned int iov_len;
+
+ if (rsp->SecurityBufferLength)
+ iov_len = offsetof(struct smb2_sess_setup_rsp, Buffer) +
+ le16_to_cpu(rsp->SecurityBufferLength);
+ else
+ iov_len = sizeof(struct smb2_sess_setup_rsp);
+ rc = ksmbd_iov_pin_rsp(work, rsp, iov_len);
+ if (rc)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
}
ksmbd_conn_unlock(conn);
@@ -1978,13 +1982,16 @@ int smb2_tree_connect(struct ksmbd_work *work)
status.tree_conn->posix_extensions = true;
rsp->StructureSize = cpu_to_le16(16);
- inc_rfc1001_len(work->response_buf, 16);
out_err1:
rsp->Capabilities = 0;
rsp->Reserved = 0;
/* default manual caching */
rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
+ rc = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_tree_connect_rsp));
+ if (rc)
+ status.ret = KSMBD_TREE_CONN_STATUS_NOMEM;
+
if (!IS_ERR(treename))
kfree(treename);
if (!IS_ERR(name))
@@ -2097,20 +2104,27 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
struct smb2_tree_disconnect_req *req;
struct ksmbd_session *sess = work->sess;
struct ksmbd_tree_connect *tcon = work->tcon;
+ int err;
WORK_BUFFERS(work, req, rsp);
- rsp->StructureSize = cpu_to_le16(4);
- inc_rfc1001_len(work->response_buf, 4);
-
ksmbd_debug(SMB, "request\n");
+ rsp->StructureSize = cpu_to_le16(4);
+ err = ksmbd_iov_pin_rsp(work, rsp,
+ sizeof(struct smb2_tree_disconnect_rsp));
+ if (err) {
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ smb2_set_err_rsp(work);
+ return err;
+ }
+
if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
smb2_set_err_rsp(work);
- return 0;
+ return -ENOENT;
}
ksmbd_close_tree_conn_fds(work);
@@ -2132,15 +2146,21 @@ int smb2_session_logoff(struct ksmbd_work *work)
struct smb2_logoff_rsp *rsp;
struct ksmbd_session *sess;
u64 sess_id;
+ int err;
WORK_BUFFERS(work, req, rsp);
+ ksmbd_debug(SMB, "request\n");
+
sess_id = le64_to_cpu(req->hdr.SessionId);
rsp->StructureSize = cpu_to_le16(4);
- inc_rfc1001_len(work->response_buf, 4);
-
- ksmbd_debug(SMB, "request\n");
+ err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));
+ if (err) {
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ smb2_set_err_rsp(work);
+ return err;
+ }
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT);
ksmbd_close_session_fds(work);
@@ -2155,7 +2175,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
smb2_set_err_rsp(work);
- return 0;
+ return -ENOENT;
}
ksmbd_destroy_file_table(&sess->file_table);
@@ -2216,7 +2236,10 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
- inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
+ err = ksmbd_iov_pin_rsp(work, rsp, offsetof(struct smb2_create_rsp, Buffer));
+ if (err)
+ goto out;
+
kfree(name);
return 0;
@@ -2595,6 +2618,7 @@ int smb2_open(struct ksmbd_work *work)
u64 time;
umode_t posix_mode = 0;
__le32 daccess, maximal_access = 0;
+ int iov_len = 0;
WORK_BUFFERS(work, req, rsp);
@@ -3246,7 +3270,7 @@ int smb2_open(struct ksmbd_work *work)
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
- inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
+ iov_len = offsetof(struct smb2_create_rsp, Buffer);
/* If lease is request send lease context response */
if (opinfo && opinfo->is_lease) {
@@ -3261,8 +3285,7 @@ int smb2_open(struct ksmbd_work *work)
create_lease_buf(rsp->Buffer, opinfo->o_lease);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_lease_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_lease_size);
+ iov_len += conn->vals->create_lease_size;
next_ptr = &lease_ccontext->Next;
next_off = conn->vals->create_lease_size;
}
@@ -3282,8 +3305,7 @@ int smb2_open(struct ksmbd_work *work)
le32_to_cpu(maximal_access));
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_mxac_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_mxac_size);
+ iov_len += conn->vals->create_mxac_size;
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
next_ptr = &mxac_ccontext->Next;
@@ -3301,8 +3323,7 @@ int smb2_open(struct ksmbd_work *work)
stat.ino, tcon->id);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_disk_id_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_disk_id_size);
+ iov_len += conn->vals->create_disk_id_size;
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
next_ptr = &disk_id_ccontext->Next;
@@ -3316,8 +3337,7 @@ int smb2_open(struct ksmbd_work *work)
fp);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_posix_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_posix_size);
+ iov_len += conn->vals->create_posix_size;
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
}
@@ -3335,7 +3355,8 @@ int smb2_open(struct ksmbd_work *work)
}
ksmbd_revert_fsids(work);
err_out1:
-
+ if (!rc)
+ rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len);
if (rc) {
if (rc == -EINVAL)
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
@@ -4062,7 +4083,10 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->OutputBufferOffset = cpu_to_le16(0);
rsp->OutputBufferLength = cpu_to_le32(0);
rsp->Buffer[0] = 0;
- inc_rfc1001_len(work->response_buf, 9);
+ rc = ksmbd_iov_pin_rsp(work, (void *)rsp,
+ sizeof(struct smb2_query_directory_rsp));
+ if (rc)
+ goto err_out;
} else {
no_buf_len:
((struct file_directory_info *)
@@ -4074,7 +4098,11 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72);
rsp->OutputBufferLength = cpu_to_le32(d_info.data_count);
- inc_rfc1001_len(work->response_buf, 8 + d_info.data_count);
+ rc = ksmbd_iov_pin_rsp(work, (void *)rsp,
+ offsetof(struct smb2_query_directory_rsp, Buffer) +
+ d_info.data_count);
+ if (rc)
+ goto err_out;
}
kfree(srch_ptr);
@@ -4121,21 +4149,13 @@ int smb2_query_dir(struct ksmbd_work *work)
*/
static int buffer_check_err(int reqOutputBufferLength,
struct smb2_query_info_rsp *rsp,
- void *rsp_org, int infoclass_size)
+ void *rsp_org)
{
if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) {
- if (reqOutputBufferLength < infoclass_size) {
- pr_err("Invalid Buffer Size Requested\n");
- rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
- *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr));
- return -EINVAL;
- }
-
- ksmbd_debug(SMB, "Buffer Overflow\n");
- rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
- *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr) +
- reqOutputBufferLength);
- rsp->OutputBufferLength = cpu_to_le32(reqOutputBufferLength);
+ pr_err("Invalid Buffer Size Requested\n");
+ rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
+ *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr));
+ return -EINVAL;
}
return 0;
}
@@ -4154,7 +4174,6 @@ static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp,
sinfo->Directory = 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_standard_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_standard_info));
}
static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
@@ -4168,7 +4187,6 @@ static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63));
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_internal_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
}
static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
@@ -4194,14 +4212,12 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
case FILE_STANDARD_INFORMATION:
get_standard_info_pipe(rsp, rsp_org);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, rsp_org,
- FILE_STANDARD_INFORMATION_SIZE);
+ rsp, rsp_org);
break;
case FILE_INTERNAL_INFORMATION:
get_internal_info_pipe(rsp, id, rsp_org);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, rsp_org,
- FILE_INTERNAL_INFORMATION_SIZE);
+ rsp, rsp_org);
break;
default:
ksmbd_debug(SMB, "smb2_info_file_pipe for %u not supported\n",
@@ -4369,7 +4385,6 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
if (rsp_data_cnt == 0)
rsp->hdr.Status = STATUS_NO_EAS_ON_FILE;
rsp->OutputBufferLength = cpu_to_le32(rsp_data_cnt);
- inc_rfc1001_len(rsp_org, rsp_data_cnt);
out:
kvfree(xattr_list);
return rc;
@@ -4384,7 +4399,6 @@ static void get_file_access_info(struct smb2_query_info_rsp *rsp,
file_info->AccessFlags = fp->daccess;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_access_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_access_info));
}
static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
@@ -4414,7 +4428,6 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
basic_info->Pad1 = 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_basic_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_basic_info));
return 0;
}
@@ -4439,8 +4452,6 @@ static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_standard_info));
- inc_rfc1001_len(rsp_org,
- sizeof(struct smb2_file_standard_info));
}
static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
@@ -4452,8 +4463,6 @@ static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
file_info->AlignmentRequirement = 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_alignment_info));
- inc_rfc1001_len(rsp_org,
- sizeof(struct smb2_file_alignment_info));
}
static int get_file_all_info(struct ksmbd_work *work,
@@ -4517,7 +4526,6 @@ static int get_file_all_info(struct ksmbd_work *work,
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_all_info) + conv_len - 1);
kfree(filename);
- inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
return 0;
}
@@ -4540,7 +4548,6 @@ static void get_file_alternate_info(struct ksmbd_work *work,
file_info->FileNameLength = cpu_to_le32(conv_len);
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
- inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
}
static void get_file_stream_info(struct ksmbd_work *work,
@@ -4640,7 +4647,6 @@ static void get_file_stream_info(struct ksmbd_work *work,
kvfree(xattr_list);
rsp->OutputBufferLength = cpu_to_le32(nbytes);
- inc_rfc1001_len(rsp_org, nbytes);
}
static void get_file_internal_info(struct smb2_query_info_rsp *rsp,
@@ -4655,7 +4661,6 @@ static void get_file_internal_info(struct smb2_query_info_rsp *rsp,
file_info->IndexNumber = cpu_to_le64(stat.ino);
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_internal_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
}
static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
@@ -4691,7 +4696,6 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
file_info->Reserved = cpu_to_le32(0);
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_ntwrk_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ntwrk_info));
return 0;
}
@@ -4703,7 +4707,6 @@ static void get_file_ea_info(struct smb2_query_info_rsp *rsp, void *rsp_org)
file_info->EASize = 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_ea_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ea_info));
}
static void get_file_position_info(struct smb2_query_info_rsp *rsp,
@@ -4715,7 +4718,6 @@ static void get_file_position_info(struct smb2_query_info_rsp *rsp,
file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_pos_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_pos_info));
}
static void get_file_mode_info(struct smb2_query_info_rsp *rsp,
@@ -4727,7 +4729,6 @@ static void get_file_mode_info(struct smb2_query_info_rsp *rsp,
file_info->Mode = fp->coption & FILE_MODE_INFO_MASK;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_mode_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_mode_info));
}
static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
@@ -4749,7 +4750,6 @@ static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_comp_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_comp_info));
}
static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
@@ -4768,11 +4768,10 @@ static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
file_info->ReparseTag = 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_attr_tag_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_attr_tag_info));
return 0;
}
-static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
+static void find_file_posix_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org)
{
struct smb311_posix_qinfo *file_info;
@@ -4812,8 +4811,6 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
(struct smb_sid *)&file_info->Sids[16]);
rsp->OutputBufferLength = cpu_to_le32(out_buf_len);
- inc_rfc1001_len(rsp_org, out_buf_len);
- return out_buf_len;
}
static int smb2_get_info_file(struct ksmbd_work *work,
@@ -4823,7 +4820,6 @@ static int smb2_get_info_file(struct ksmbd_work *work,
struct ksmbd_file *fp;
int fileinfoclass = 0;
int rc = 0;
- int file_infoclass_size;
unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
if (test_share_config_flag(work->tcon->share_conf,
@@ -4856,85 +4852,69 @@ static int smb2_get_info_file(struct ksmbd_work *work,
switch (fileinfoclass) {
case FILE_ACCESS_INFORMATION:
get_file_access_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ACCESS_INFORMATION_SIZE;
break;
case FILE_BASIC_INFORMATION:
rc = get_file_basic_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_BASIC_INFORMATION_SIZE;
break;
case FILE_STANDARD_INFORMATION:
get_file_standard_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_STANDARD_INFORMATION_SIZE;
break;
case FILE_ALIGNMENT_INFORMATION:
get_file_alignment_info(rsp, work->response_buf);
- file_infoclass_size = FILE_ALIGNMENT_INFORMATION_SIZE;
break;
case FILE_ALL_INFORMATION:
rc = get_file_all_info(work, rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ALL_INFORMATION_SIZE;
break;
case FILE_ALTERNATE_NAME_INFORMATION:
get_file_alternate_info(work, rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ALTERNATE_NAME_INFORMATION_SIZE;
break;
case FILE_STREAM_INFORMATION:
get_file_stream_info(work, rsp, fp, work->response_buf);
- file_infoclass_size = FILE_STREAM_INFORMATION_SIZE;
break;
case FILE_INTERNAL_INFORMATION:
get_file_internal_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_INTERNAL_INFORMATION_SIZE;
break;
case FILE_NETWORK_OPEN_INFORMATION:
rc = get_file_network_open_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_NETWORK_OPEN_INFORMATION_SIZE;
break;
case FILE_EA_INFORMATION:
get_file_ea_info(rsp, work->response_buf);
- file_infoclass_size = FILE_EA_INFORMATION_SIZE;
break;
case FILE_FULL_EA_INFORMATION:
rc = smb2_get_ea(work, fp, req, rsp, work->response_buf);
- file_infoclass_size = FILE_FULL_EA_INFORMATION_SIZE;
break;
case FILE_POSITION_INFORMATION:
get_file_position_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_POSITION_INFORMATION_SIZE;
break;
case FILE_MODE_INFORMATION:
get_file_mode_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_MODE_INFORMATION_SIZE;
break;
case FILE_COMPRESSION_INFORMATION:
get_file_compression_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_COMPRESSION_INFORMATION_SIZE;
break;
case FILE_ATTRIBUTE_TAG_INFORMATION:
rc = get_file_attribute_tag_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ATTRIBUTE_TAG_INFORMATION_SIZE;
break;
case SMB_FIND_FILE_POSIX_INFO:
if (!work->tcon->posix_extensions) {
pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
rc = -EOPNOTSUPP;
} else {
- file_infoclass_size = find_file_posix_info(rsp, fp,
- work->response_buf);
+ find_file_posix_info(rsp, fp, work->response_buf);
}
break;
default:
@@ -4944,8 +4924,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
}
if (!rc)
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, work->response_buf,
- file_infoclass_size);
+ rsp, work->response_buf);
ksmbd_fd_put(work, fp);
return rc;
}
@@ -4961,7 +4940,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
struct kstatfs stfs;
struct path path;
int rc = 0, len;
- int fs_infoclass_size = 0;
if (!share->path)
return -EIO;
@@ -4991,8 +4969,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->DeviceType = cpu_to_le32(stfs.f_type);
info->DeviceCharacteristics = cpu_to_le32(0x00000020);
rsp->OutputBufferLength = cpu_to_le32(8);
- inc_rfc1001_len(work->response_buf, 8);
- fs_infoclass_size = FS_DEVICE_INFORMATION_SIZE;
break;
}
case FS_ATTRIBUTE_INFORMATION:
@@ -5021,8 +4997,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->FileSystemNameLen = cpu_to_le32(len);
sz = sizeof(struct filesystem_attribute_info) - 2 + len;
rsp->OutputBufferLength = cpu_to_le32(sz);
- inc_rfc1001_len(work->response_buf, sz);
- fs_infoclass_size = FS_ATTRIBUTE_INFORMATION_SIZE;
break;
}
case FS_VOLUME_INFORMATION:
@@ -5049,8 +5023,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->Reserved = 0;
sz = sizeof(struct filesystem_vol_info) - 2 + len;
rsp->OutputBufferLength = cpu_to_le32(sz);
- inc_rfc1001_len(work->response_buf, sz);
- fs_infoclass_size = FS_VOLUME_INFORMATION_SIZE;
break;
}
case FS_SIZE_INFORMATION:
@@ -5063,8 +5035,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(24);
- inc_rfc1001_len(work->response_buf, 24);
- fs_infoclass_size = FS_SIZE_INFORMATION_SIZE;
break;
}
case FS_FULL_SIZE_INFORMATION:
@@ -5080,8 +5050,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(32);
- inc_rfc1001_len(work->response_buf, 32);
- fs_infoclass_size = FS_FULL_SIZE_INFORMATION_SIZE;
break;
}
case FS_OBJECT_ID_INFORMATION:
@@ -5101,8 +5069,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->extended_info.rel_date = 0;
memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0"));
rsp->OutputBufferLength = cpu_to_le32(64);
- inc_rfc1001_len(work->response_buf, 64);
- fs_infoclass_size = FS_OBJECT_ID_INFORMATION_SIZE;
break;
}
case FS_SECTOR_SIZE_INFORMATION:
@@ -5124,8 +5090,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->ByteOffsetForSectorAlignment = 0;
info->ByteOffsetForPartitionAlignment = 0;
rsp->OutputBufferLength = cpu_to_le32(28);
- inc_rfc1001_len(work->response_buf, 28);
- fs_infoclass_size = FS_SECTOR_SIZE_INFORMATION_SIZE;
break;
}
case FS_CONTROL_INFORMATION:
@@ -5146,8 +5110,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID);
info->Padding = 0;
rsp->OutputBufferLength = cpu_to_le32(48);
- inc_rfc1001_len(work->response_buf, 48);
- fs_infoclass_size = FS_CONTROL_INFORMATION_SIZE;
break;
}
case FS_POSIX_INFORMATION:
@@ -5167,8 +5129,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->TotalFileNodes = cpu_to_le64(stfs.f_files);
info->FreeFileNodes = cpu_to_le64(stfs.f_ffree);
rsp->OutputBufferLength = cpu_to_le32(56);
- inc_rfc1001_len(work->response_buf, 56);
- fs_infoclass_size = FS_POSIX_INFORMATION_SIZE;
}
break;
}
@@ -5177,8 +5137,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
return -EOPNOTSUPP;
}
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, work->response_buf,
- fs_infoclass_size);
+ rsp, work->response_buf);
path_put(&path);
return rc;
}
@@ -5212,7 +5171,6 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
secdesclen = sizeof(struct smb_ntsd);
rsp->OutputBufferLength = cpu_to_le32(secdesclen);
- inc_rfc1001_len(work->response_buf, secdesclen);
return 0;
}
@@ -5257,7 +5215,6 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
return rc;
rsp->OutputBufferLength = cpu_to_le32(secdesclen);
- inc_rfc1001_len(work->response_buf, secdesclen);
return 0;
}
@@ -5296,6 +5253,14 @@ int smb2_query_info(struct ksmbd_work *work)
rc = -EOPNOTSUPP;
}
+ if (!rc) {
+ rsp->StructureSize = cpu_to_le16(9);
+ rsp->OutputBufferOffset = cpu_to_le16(72);
+ rc = ksmbd_iov_pin_rsp(work, (void *)rsp,
+ offsetof(struct smb2_query_info_rsp, Buffer) +
+ le32_to_cpu(rsp->OutputBufferLength));
+ }
+
if (rc < 0) {
if (rc == -EACCES)
rsp->hdr.Status = STATUS_ACCESS_DENIED;
@@ -5303,6 +5268,8 @@ int smb2_query_info(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_FILE_CLOSED;
else if (rc == -EIO)
rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
+ else if (rc == -ENOMEM)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
else if (rc == -EOPNOTSUPP || rsp->hdr.Status == 0)
rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
smb2_set_err_rsp(work);
@@ -5311,9 +5278,6 @@ int smb2_query_info(struct ksmbd_work *work)
rc);
return rc;
}
- rsp->StructureSize = cpu_to_le16(9);
- rsp->OutputBufferOffset = cpu_to_le16(72);
- inc_rfc1001_len(work->response_buf, 8);
return 0;
}
@@ -5344,8 +5308,9 @@ static noinline int smb2_close_pipe(struct ksmbd_work *work)
rsp->AllocationSize = 0;
rsp->EndOfFile = 0;
rsp->Attributes = 0;
- inc_rfc1001_len(work->response_buf, 60);
- return 0;
+
+ return ksmbd_iov_pin_rsp(work, (void *)rsp,
+ sizeof(struct smb2_close_rsp));
}
/**
@@ -5450,15 +5415,17 @@ int smb2_close(struct ksmbd_work *work)
err = ksmbd_close_fd(work, volatile_id);
out:
+ if (!err)
+ err = ksmbd_iov_pin_rsp(work, (void *)rsp,
+ sizeof(struct smb2_close_rsp));
+
if (err) {
if (rsp->hdr.Status == 0)
rsp->hdr.Status = STATUS_FILE_CLOSED;
smb2_set_err_rsp(work);
- } else {
- inc_rfc1001_len(work->response_buf, 60);
}
- return 0;
+ return err;
}
/**
@@ -5476,8 +5443,7 @@ int smb2_echo(struct ksmbd_work *work)
rsp->StructureSize = cpu_to_le16(4);
rsp->Reserved = 0;
- inc_rfc1001_len(work->response_buf, 4);
- return 0;
+ return ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_echo_rsp));
}
static int smb2_rename(struct ksmbd_work *work,
@@ -6071,7 +6037,10 @@ int smb2_set_info(struct ksmbd_work *work)
goto err_out;
rsp->StructureSize = cpu_to_le16(2);
- inc_rfc1001_len(work->response_buf, 2);
+ rc = ksmbd_iov_pin_rsp(work, (void *)rsp,
+ sizeof(struct smb2_set_info_rsp));
+ if (rc)
+ goto err_out;
ksmbd_fd_put(work, fp);
return 0;
@@ -6118,28 +6087,36 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
id = req->VolatileFileId;
- inc_rfc1001_len(work->response_buf, 16);
rpc_resp = ksmbd_rpc_read(work->sess, id);
if (rpc_resp) {
+ void *aux_payload_buf;
+
if (rpc_resp->flags != KSMBD_RPC_OK) {
err = -EINVAL;
goto out;
}
- work->aux_payload_buf =
+ aux_payload_buf =
kvmalloc(rpc_resp->payload_sz, GFP_KERNEL);
- if (!work->aux_payload_buf) {
+ if (!aux_payload_buf) {
err = -ENOMEM;
goto out;
}
- memcpy(work->aux_payload_buf, rpc_resp->payload,
- rpc_resp->payload_sz);
+ memcpy(aux_payload_buf, rpc_resp->payload, rpc_resp->payload_sz);
nbytes = rpc_resp->payload_sz;
- work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
- work->aux_payload_sz = nbytes;
kvfree(rpc_resp);
+ err = ksmbd_iov_pin_rsp_read(work, (void *)rsp,
+ offsetof(struct smb2_read_rsp, Buffer),
+ aux_payload_buf, nbytes);
+ if (err)
+ goto out;
+ } else {
+ err = ksmbd_iov_pin_rsp(work, (void *)rsp,
+ offsetof(struct smb2_read_rsp, Buffer));
+ if (err)
+ goto out;
}
rsp->StructureSize = cpu_to_le16(17);
@@ -6148,7 +6125,6 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
- inc_rfc1001_len(work->response_buf, nbytes);
return 0;
out:
@@ -6222,13 +6198,8 @@ int smb2_read(struct ksmbd_work *work)
int err = 0;
bool is_rdma_channel = false;
unsigned int max_read_size = conn->vals->max_read_size;
-
- WORK_BUFFERS(work, req, rsp);
- if (work->next_smb2_rcv_hdr_off) {
- work->send_no_response = 1;
- err = -EOPNOTSUPP;
- goto out;
- }
+ unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
+ void *aux_payload_buf;
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_PIPE)) {
@@ -6236,6 +6207,25 @@ int smb2_read(struct ksmbd_work *work)
return smb2_read_pipe(work);
}
+ if (work->next_smb2_rcv_hdr_off) {
+ req = ksmbd_req_buf_next(work);
+ rsp = ksmbd_resp_buf_next(work);
+ if (!has_file_id(req->VolatileFileId)) {
+ ksmbd_debug(SMB, "Compound request set FID = %llu\n",
+ work->compound_fid);
+ id = work->compound_fid;
+ pid = work->compound_pfid;
+ }
+ } else {
+ req = smb2_get_msg(work->request_buf);
+ rsp = smb2_get_msg(work->response_buf);
+ }
+
+ if (!has_file_id(id)) {
+ id = req->VolatileFileId;
+ pid = req->PersistentFileId;
+ }
+
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
is_rdma_channel = true;
@@ -6258,7 +6248,7 @@ int smb2_read(struct ksmbd_work *work)
goto out;
}
- fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
+ fp = ksmbd_lookup_fd_slow(work, id, pid);
if (!fp) {
err = -ENOENT;
goto out;
@@ -6284,21 +6274,20 @@ int smb2_read(struct ksmbd_work *work)
ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
fp->filp, offset, length);
- work->aux_payload_buf = kvzalloc(length, GFP_KERNEL);
- if (!work->aux_payload_buf) {
+ aux_payload_buf = kvzalloc(length, GFP_KERNEL);
+ if (!aux_payload_buf) {
err = -ENOMEM;
goto out;
}
- nbytes = ksmbd_vfs_read(work, fp, length, &offset);
+ nbytes = ksmbd_vfs_read(work, fp, length, &offset, aux_payload_buf);
if (nbytes < 0) {
err = nbytes;
goto out;
}
if ((nbytes == 0 && length != 0) || nbytes < mincount) {
- kvfree(work->aux_payload_buf);
- work->aux_payload_buf = NULL;
+ kvfree(aux_payload_buf);
rsp->hdr.Status = STATUS_END_OF_FILE;
smb2_set_err_rsp(work);
ksmbd_fd_put(work, fp);
@@ -6311,10 +6300,9 @@ int smb2_read(struct ksmbd_work *work)
if (is_rdma_channel == true) {
/* write data to the client using rdma channel */
remain_bytes = smb2_read_rdma_channel(work, req,
- work->aux_payload_buf,
+ aux_payload_buf,
nbytes);
- kvfree(work->aux_payload_buf);
- work->aux_payload_buf = NULL;
+ kvfree(aux_payload_buf);
nbytes = 0;
if (remain_bytes < 0) {
@@ -6329,10 +6317,11 @@ int smb2_read(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = cpu_to_le32(remain_bytes);
rsp->Reserved2 = 0;
- inc_rfc1001_len(work->response_buf, 16);
- work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
- work->aux_payload_sz = nbytes;
- inc_rfc1001_len(work->response_buf, nbytes);
+ err = ksmbd_iov_pin_rsp_read(work, (void *)rsp,
+ offsetof(struct smb2_read_rsp, Buffer),
+ aux_payload_buf, nbytes);
+ if (err)
+ goto out;
ksmbd_fd_put(work, fp);
return 0;
@@ -6415,8 +6404,8 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(length);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
- inc_rfc1001_len(work->response_buf, 16);
- return 0;
+ err = ksmbd_iov_pin_rsp(work, (void *)rsp,
+ offsetof(struct smb2_write_rsp, Buffer));
out:
if (err) {
rsp->hdr.Status = STATUS_INVALID_HANDLE;
@@ -6572,7 +6561,9 @@ int smb2_write(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
- inc_rfc1001_len(work->response_buf, 16);
+ err = ksmbd_iov_pin_rsp(work, rsp, offsetof(struct smb2_write_rsp, Buffer));
+ if (err)
+ goto out;
ksmbd_fd_put(work, fp);
return 0;
@@ -6619,15 +6610,11 @@ int smb2_flush(struct ksmbd_work *work)
rsp->StructureSize = cpu_to_le16(4);
rsp->Reserved = 0;
- inc_rfc1001_len(work->response_buf, 4);
- return 0;
+ return ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_flush_rsp));
out:
- if (err) {
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- smb2_set_err_rsp(work);
- }
-
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ smb2_set_err_rsp(work);
return err;
}
@@ -7064,6 +7051,8 @@ int smb2_lock(struct ksmbd_work *work)
list_del(&work->fp_entry);
spin_unlock(&fp->f_lock);
+ ksmbd_iov_reset(work);
+
if (work->state != KSMBD_WORK_ACTIVE) {
list_del(&smb_lock->llist);
spin_lock(&work->conn->llist_lock);
@@ -7082,7 +7071,6 @@ int smb2_lock(struct ksmbd_work *work)
}
init_smb2_rsp_hdr(work);
- smb2_set_err_rsp(work);
rsp->hdr.Status =
STATUS_RANGE_NOT_LOCKED;
kfree(smb_lock);
@@ -7117,7 +7105,10 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_debug(SMB, "successful in taking lock\n");
rsp->hdr.Status = STATUS_SUCCESS;
rsp->Reserved = 0;
- inc_rfc1001_len(work->response_buf, 4);
+ err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_lock_rsp));
+ if (err)
+ goto out;
+
ksmbd_fd_put(work, fp);
return 0;
@@ -7913,9 +7904,9 @@ int smb2_ioctl(struct ksmbd_work *work)
rsp->Reserved = cpu_to_le16(0);
rsp->Flags = cpu_to_le32(0);
rsp->Reserved2 = cpu_to_le32(0);
- inc_rfc1001_len(work->response_buf, 48 + nbytes);
-
- return 0;
+ ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_ioctl_rsp) + nbytes);
+ if (!ret)
+ return ret;
out:
if (ret == -EACCES)
@@ -8050,8 +8041,9 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
rsp->Reserved2 = 0;
rsp->VolatileFid = volatile_id;
rsp->PersistentFid = persistent_id;
- inc_rfc1001_len(work->response_buf, 24);
- return;
+ ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_oplock_break));
+ if (!ret)
+ return;
err_out:
opinfo->op_state = OPLOCK_STATE_NONE;
@@ -8201,8 +8193,9 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
memcpy(rsp->LeaseKey, req->LeaseKey, 16);
rsp->LeaseState = lease_state;
rsp->LeaseDuration = 0;
- inc_rfc1001_len(work->response_buf, 36);
- return;
+ ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_lease_ack));
+ if (!ret)
+ return;
err_out:
opinfo->op_state = OPLOCK_STATE_NONE;
@@ -8340,43 +8333,19 @@ int smb2_check_sign_req(struct ksmbd_work *work)
void smb2_set_sign_rsp(struct ksmbd_work *work)
{
struct smb2_hdr *hdr;
- struct smb2_hdr *req_hdr;
char signature[SMB2_HMACSHA256_SIZE];
- struct kvec iov[2];
- size_t len;
+ struct kvec *iov;
int n_vec = 1;
- hdr = smb2_get_msg(work->response_buf);
- if (work->next_smb2_rsp_hdr_off)
- hdr = ksmbd_resp_buf_next(work);
-
- req_hdr = ksmbd_req_buf_next(work);
-
- if (!work->next_smb2_rsp_hdr_off) {
- len = get_rfc1002_len(work->response_buf);
- if (req_hdr->NextCommand)
- len = ALIGN(len, 8);
- } else {
- len = get_rfc1002_len(work->response_buf) -
- work->next_smb2_rsp_hdr_off;
- len = ALIGN(len, 8);
- }
-
- if (req_hdr->NextCommand)
- hdr->NextCommand = cpu_to_le32(len);
-
+ hdr = ksmbd_resp_buf_curr(work);
hdr->Flags |= SMB2_FLAGS_SIGNED;
memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
- iov[0].iov_base = (char *)&hdr->ProtocolId;
- iov[0].iov_len = len;
-
- if (work->aux_payload_sz) {
- iov[0].iov_len -= work->aux_payload_sz;
-
- iov[1].iov_base = work->aux_payload_buf;
- iov[1].iov_len = work->aux_payload_sz;
+ if (hdr->Command == SMB2_READ) {
+ iov = &work->iov[work->iov_idx - 1];
n_vec++;
+ } else {
+ iov = &work->iov[work->iov_idx];
}
if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
@@ -8452,29 +8421,14 @@ int smb3_check_sign_req(struct ksmbd_work *work)
void smb3_set_sign_rsp(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_hdr *req_hdr, *hdr;
+ struct smb2_hdr *hdr;
struct channel *chann;
char signature[SMB2_CMACAES_SIZE];
- struct kvec iov[2];
+ struct kvec *iov;
int n_vec = 1;
- size_t len;
char *signing_key;
- hdr = smb2_get_msg(work->response_buf);
- if (work->next_smb2_rsp_hdr_off)
- hdr = ksmbd_resp_buf_next(work);
-
- req_hdr = ksmbd_req_buf_next(work);
-
- if (!work->next_smb2_rsp_hdr_off) {
- len = get_rfc1002_len(work->response_buf);
- if (req_hdr->NextCommand)
- len = ALIGN(len, 8);
- } else {
- len = get_rfc1002_len(work->response_buf) -
- work->next_smb2_rsp_hdr_off;
- len = ALIGN(len, 8);
- }
+ hdr = ksmbd_resp_buf_curr(work);
if (conn->binding == false &&
le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
@@ -8490,21 +8444,18 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
if (!signing_key)
return;
- if (req_hdr->NextCommand)
- hdr->NextCommand = cpu_to_le32(len);
-
hdr->Flags |= SMB2_FLAGS_SIGNED;
memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
- iov[0].iov_base = (char *)&hdr->ProtocolId;
- iov[0].iov_len = len;
- if (work->aux_payload_sz) {
- iov[0].iov_len -= work->aux_payload_sz;
- iov[1].iov_base = work->aux_payload_buf;
- iov[1].iov_len = work->aux_payload_sz;
+
+ if (hdr->Command == SMB2_READ) {
+ iov = &work->iov[work->iov_idx - 1];
n_vec++;
+ } else {
+ iov = &work->iov[work->iov_idx];
}
- if (!ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec, signature))
+ if (!ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec,
+ signature))
memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
}
@@ -8571,45 +8522,22 @@ static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
int smb3_encrypt_resp(struct ksmbd_work *work)
{
- char *buf = work->response_buf;
- struct kvec iov[3];
+ struct kvec *iov = work->iov;
int rc = -ENOMEM;
- int buf_size = 0, rq_nvec = 2 + (work->aux_payload_sz ? 1 : 0);
+ void *tr_buf;
- if (ARRAY_SIZE(iov) < rq_nvec)
- return -ENOMEM;
-
- work->tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, GFP_KERNEL);
- if (!work->tr_buf)
+ tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, GFP_KERNEL);
+ if (!tr_buf)
return rc;
/* fill transform header */
- fill_transform_hdr(work->tr_buf, buf, work->conn->cipher_type);
+ fill_transform_hdr(tr_buf, work->response_buf, work->conn->cipher_type);
- iov[0].iov_base = work->tr_buf;
+ iov[0].iov_base = tr_buf;
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
- buf_size += iov[0].iov_len - 4;
-
- iov[1].iov_base = buf + 4;
- iov[1].iov_len = get_rfc1002_len(buf);
- if (work->aux_payload_sz) {
- iov[1].iov_len = work->resp_hdr_sz - 4;
-
- iov[2].iov_base = work->aux_payload_buf;
- iov[2].iov_len = work->aux_payload_sz;
- buf_size += iov[2].iov_len;
- }
- buf_size += iov[1].iov_len;
- work->resp_hdr_sz = iov[1].iov_len;
+ work->tr_buf = tr_buf;
- rc = ksmbd_crypt_message(work, iov, rq_nvec, 1);
- if (rc)
- return rc;
-
- memmove(buf, iov[1].iov_base, iov[1].iov_len);
- *(__be32 *)work->tr_buf = cpu_to_be32(buf_size);
-
- return rc;
+ return ksmbd_crypt_message(work, iov, work->iov_idx + 1, 1);
}
bool smb3_is_transform_hdr(void *buf)
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index c13616857927..894bf71218b6 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -319,12 +319,6 @@ static int init_smb1_rsp_hdr(struct ksmbd_work *work)
struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
- /*
- * Remove 4 byte direct TCP header.
- */
- *(__be32 *)work->response_buf =
- cpu_to_be32(sizeof(struct smb_hdr) - 4);
-
rsp_hdr->Command = SMB_COM_NEGOTIATE;
*(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
rsp_hdr->Flags = SMBFLG_RESPONSE;
@@ -560,10 +554,11 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
- /* Add 2 byte bcc and 2 byte DialectIndex. */
- inc_rfc1001_len(work->response_buf, 4);
- neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
+ if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp,
+ sizeof(struct smb_negotiate_rsp) - 4))
+ return -ENOMEM;
+ neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
neg_rsp->hdr.WordCount = 1;
neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
neg_rsp->ByteCount = 0;
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 68077150ad2f..3e0fd0f50b7f 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1241,14 +1241,12 @@ static int smb_direct_writev(struct ksmbd_transport *t,
//FIXME: skip RFC1002 header..
buflen -= 4;
- iov[0].iov_base += 4;
- iov[0].iov_len -= 4;
remaining_data_length = buflen;
ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen);
smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key);
- start = i = 0;
+ start = i = 1;
buflen = 0;
while (true) {
buflen += iov[i].iov_len;
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 8cb46abf2c76..6b24355800aa 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -367,15 +367,15 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end,
* @fid: file id of open file
* @count: read byte count
* @pos: file pos
+ * @rbuf: read data buffer
*
* Return: number of read bytes on success, otherwise error
*/
int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
- loff_t *pos)
+ loff_t *pos, char *rbuf)
{
struct file *filp = fp->filp;
ssize_t nbytes = 0;
- char *rbuf = work->aux_payload_buf;
struct inode *inode = file_inode(filp);
if (S_ISDIR(inode->i_mode))
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index b544c882c611..97804cb97f27 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -115,8 +115,8 @@ void ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
struct dentry *dentry, __le32 *daccess);
int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
-int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp,
- size_t count, loff_t *pos);
+int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
+ loff_t *pos, char *rbuf);
int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
char *buf, size_t count, loff_t *pos, bool sync,
ssize_t *written);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 120/154] ksmbd: fix wrong interim response on compound
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (118 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 119/154] ksmbd: add support for read compound Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 121/154] ksmbd: fix `force create mode' and `force directory mode' Namjae Jeon
` (34 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 041bba4414cda37d00063952c9bff9c3d5812a19 ]
If smb2_lock or smb2_open request is compound, ksmbd could send wrong
interim response to client. ksmbd allocate new interim buffer instead of
using resonse buffer to support compound request.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_work.c | 10 ++++++----
fs/ksmbd/ksmbd_work.h | 2 +-
fs/ksmbd/oplock.c | 14 ++------------
fs/ksmbd/smb2pdu.c | 26 +++++++++++++++++---------
4 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
index f49c2e01ea9f..51def3ca74c0 100644
--- a/fs/ksmbd/ksmbd_work.c
+++ b/fs/ksmbd/ksmbd_work.c
@@ -160,9 +160,11 @@ int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
return __ksmbd_iov_pin_rsp(work, ib, len, aux_buf, aux_size);
}
-void ksmbd_iov_reset(struct ksmbd_work *work)
+int allocate_interim_rsp_buf(struct ksmbd_work *work)
{
- work->iov_idx = 0;
- work->iov_cnt = 0;
- *(__be32 *)work->iov[0].iov_base = 0;
+ work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
+ if (!work->response_buf)
+ return -ENOMEM;
+ work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+ return 0;
}
diff --git a/fs/ksmbd/ksmbd_work.h b/fs/ksmbd/ksmbd_work.h
index 255157eb26dc..8ca2c813246e 100644
--- a/fs/ksmbd/ksmbd_work.h
+++ b/fs/ksmbd/ksmbd_work.h
@@ -131,5 +131,5 @@ bool ksmbd_queue_work(struct ksmbd_work *work);
int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
void *aux_buf, unsigned int aux_size);
int ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len);
-void ksmbd_iov_reset(struct ksmbd_work *work);
+int allocate_interim_rsp_buf(struct ksmbd_work *work);
#endif /* __KSMBD_WORK_H__ */
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index 13c9842a089c..13185c74b912 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -616,15 +616,6 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
return 0;
}
-static inline int allocate_oplock_break_buf(struct ksmbd_work *work)
-{
- work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
- if (!work->response_buf)
- return -ENOMEM;
- work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
- return 0;
-}
-
/**
* __smb2_oplock_break_noti() - send smb2 oplock break cmd from conn
* to client
@@ -647,7 +638,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
if (!fp)
goto out;
- if (allocate_oplock_break_buf(work)) {
+ if (allocate_interim_rsp_buf(work)) {
pr_err("smb2_allocate_rsp_buf failed! ");
ksmbd_fd_put(work, fp);
goto out;
@@ -752,7 +743,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
struct lease_break_info *br_info = work->request_buf;
struct smb2_hdr *rsp_hdr;
- if (allocate_oplock_break_buf(work)) {
+ if (allocate_interim_rsp_buf(work)) {
ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");
goto out;
}
@@ -843,7 +834,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
setup_async_work(in_work, NULL, NULL);
smb2_send_interim_resp(in_work, STATUS_PENDING);
list_del(&in_work->interim_entry);
- ksmbd_iov_reset(in_work);
}
INIT_WORK(&work->work, __smb2_lease_break_noti);
ksmbd_queue_work(work);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index bee7a022952b..3eede04bdcb2 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -153,8 +153,8 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
err_rsp->ByteCount = 0;
err_rsp->ErrorData[0] = 0;
err = ksmbd_iov_pin_rsp(work, (void *)err_rsp,
- work->conn->vals->header_size +
- SMB2_ERROR_STRUCTURE_SIZE2);
+ __SMB2_HEADER_STRUCTURE_SIZE +
+ SMB2_ERROR_STRUCTURE_SIZE2);
if (err)
work->send_no_response = 1;
}
@@ -710,13 +710,24 @@ void release_async_work(struct ksmbd_work *work)
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
{
struct smb2_hdr *rsp_hdr;
+ struct ksmbd_work *in_work = ksmbd_alloc_work_struct();
- rsp_hdr = ksmbd_resp_buf_next(work);
- smb2_set_err_rsp(work);
+ if (allocate_interim_rsp_buf(in_work)) {
+ pr_err("smb_allocate_rsp_buf failed!\n");
+ ksmbd_free_work_struct(in_work);
+ return;
+ }
+
+ in_work->conn = work->conn;
+ memcpy(smb2_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work),
+ __SMB2_HEADER_STRUCTURE_SIZE);
+
+ rsp_hdr = smb2_get_msg(in_work->response_buf);
+ smb2_set_err_rsp(in_work);
rsp_hdr->Status = status;
- ksmbd_conn_write(work);
- rsp_hdr->Status = 0;
+ ksmbd_conn_write(in_work);
+ ksmbd_free_work_struct(in_work);
}
static __le32 smb2_get_reparse_tag_special_file(umode_t mode)
@@ -7051,8 +7062,6 @@ int smb2_lock(struct ksmbd_work *work)
list_del(&work->fp_entry);
spin_unlock(&fp->f_lock);
- ksmbd_iov_reset(work);
-
if (work->state != KSMBD_WORK_ACTIVE) {
list_del(&smb_lock->llist);
spin_lock(&work->conn->llist_lock);
@@ -7070,7 +7079,6 @@ int smb2_lock(struct ksmbd_work *work)
goto out;
}
- init_smb2_rsp_hdr(work);
rsp->hdr.Status =
STATUS_RANGE_NOT_LOCKED;
kfree(smb_lock);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 121/154] ksmbd: fix `force create mode' and `force directory mode'
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (119 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 120/154] ksmbd: fix wrong interim response on compound Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 122/154] ksmbd: reduce descriptor size if remaining bytes is less than request size Namjae Jeon
` (33 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Atte Heikkilä, Namjae Jeon, Steve French
From: Atte Heikkilä <atteh.mailbox@gmail.com>
[ Upstream commit 65656f5242e500dcfeffa6a0a1519eae14724f86 ]
`force create mode' and `force directory mode' should be bitwise ORed
with the perms after `create mask' and `directory mask' have been
applied, respectively.
Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/share_config.h | 29 +++++++++++------------------
1 file changed, 11 insertions(+), 18 deletions(-)
diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h
index 3fd338293942..5f591751b923 100644
--- a/fs/ksmbd/mgmt/share_config.h
+++ b/fs/ksmbd/mgmt/share_config.h
@@ -34,29 +34,22 @@ struct ksmbd_share_config {
#define KSMBD_SHARE_INVALID_UID ((__u16)-1)
#define KSMBD_SHARE_INVALID_GID ((__u16)-1)
-static inline int share_config_create_mode(struct ksmbd_share_config *share,
- umode_t posix_mode)
+static inline umode_t
+share_config_create_mode(struct ksmbd_share_config *share,
+ umode_t posix_mode)
{
- if (!share->force_create_mode) {
- if (!posix_mode)
- return share->create_mask;
- else
- return posix_mode & share->create_mask;
- }
- return share->force_create_mode & share->create_mask;
+ umode_t mode = (posix_mode ?: (umode_t)-1) & share->create_mask;
+
+ return mode | share->force_create_mode;
}
-static inline int share_config_directory_mode(struct ksmbd_share_config *share,
- umode_t posix_mode)
+static inline umode_t
+share_config_directory_mode(struct ksmbd_share_config *share,
+ umode_t posix_mode)
{
- if (!share->force_directory_mode) {
- if (!posix_mode)
- return share->directory_mask;
- else
- return posix_mode & share->directory_mask;
- }
+ umode_t mode = (posix_mode ?: (umode_t)-1) & share->directory_mask;
- return share->force_directory_mode & share->directory_mask;
+ return mode | share->force_directory_mode;
}
static inline int test_share_config_flag(struct ksmbd_share_config *share,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 122/154] ksmbd: reduce descriptor size if remaining bytes is less than request size
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (120 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 121/154] ksmbd: fix `force create mode' and `force directory mode' Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 123/154] ksmbd: Fix one kernel-doc comment Namjae Jeon
` (32 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit e628bf939aafb61fbc56e9bdac8795cea5127e25 ]
Create 3 kinds of files to reproduce this problem.
dd if=/dev/urandom of=127k.bin bs=1024 count=127
dd if=/dev/urandom of=128k.bin bs=1024 count=128
dd if=/dev/urandom of=129k.bin bs=1024 count=129
When copying files from ksmbd share to windows or cifs.ko, The following
error message happen from windows client.
"The file '129k.bin' is too large for the destination filesystem."
We can see the error logs from ksmbd debug prints
[48394.611537] ksmbd: RDMA r/w request 0x0: token 0x669d, length 0x20000
[48394.612054] ksmbd: smb_direct: RDMA write, len 0x20000, needed credits 0x1
[48394.612572] ksmbd: filename 129k.bin, offset 131072, len 131072
[48394.614189] ksmbd: nbytes 1024, offset 132096 mincount 0
[48394.614585] ksmbd: Failed to process 8 [-22]
And we can reproduce it with cifs.ko,
e.g. dd if=129k.bin of=/dev/null bs=128KB count=2
This problem is that ksmbd rdma return error if remaining bytes is less
than Length of Buffer Descriptor V1 Structure.
smb_direct_rdma_xmit()
...
if (desc_buf_len == 0 || total_length > buf_len ||
total_length > t->max_rdma_rw_size)
return -EINVAL;
This patch reduce descriptor size with remaining bytes and remove the
check for total_length and buf_len.
Cc: stable@vger.kernel.org
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 3e0fd0f50b7f..80765bbe8efc 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1364,24 +1364,35 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
LIST_HEAD(msg_list);
char *desc_buf;
int credits_needed;
- unsigned int desc_buf_len;
- size_t total_length = 0;
+ unsigned int desc_buf_len, desc_num = 0;
if (t->status != SMB_DIRECT_CS_CONNECTED)
return -ENOTCONN;
+ if (buf_len > t->max_rdma_rw_size)
+ return -EINVAL;
+
/* calculate needed credits */
credits_needed = 0;
desc_buf = buf;
for (i = 0; i < desc_len / sizeof(*desc); i++) {
+ if (!buf_len)
+ break;
+
desc_buf_len = le32_to_cpu(desc[i].length);
+ if (!desc_buf_len)
+ return -EINVAL;
+
+ if (desc_buf_len > buf_len) {
+ desc_buf_len = buf_len;
+ desc[i].length = cpu_to_le32(desc_buf_len);
+ buf_len = 0;
+ }
credits_needed += calc_rw_credits(t, desc_buf, desc_buf_len);
desc_buf += desc_buf_len;
- total_length += desc_buf_len;
- if (desc_buf_len == 0 || total_length > buf_len ||
- total_length > t->max_rdma_rw_size)
- return -EINVAL;
+ buf_len -= desc_buf_len;
+ desc_num++;
}
ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n",
@@ -1393,7 +1404,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
/* build rdma_rw_ctx for each descriptor */
desc_buf = buf;
- for (i = 0; i < desc_len / sizeof(*desc); i++) {
+ for (i = 0; i < desc_num; i++) {
msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
if (!msg) {
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 123/154] ksmbd: Fix one kernel-doc comment
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (121 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 122/154] ksmbd: reduce descriptor size if remaining bytes is less than request size Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 124/154] ksmbd: fix slub overflow in ksmbd_decode_ntlmssp_auth_blob() Namjae Jeon
` (31 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Yang Li, Namjae Jeon, Steve French
From: Yang Li <yang.lee@linux.alibaba.com>
[ Upstream commit bf26f1b4e0918f017775edfeacf6d867204b680b ]
Fix one kernel-doc comment to silence the warning:
fs/smb/server/smb2pdu.c:4160: warning: Excess function parameter 'infoclass_size' description in 'buffer_check_err'
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 3eede04bdcb2..67eb41255903 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -4154,7 +4154,6 @@ int smb2_query_dir(struct ksmbd_work *work)
* @reqOutputBufferLength: max buffer length expected in command response
* @rsp: query info response buffer contains output buffer length
* @rsp_org: base response buffer pointer in case of chained response
- * @infoclass_size: query info class response buffer size
*
* Return: 0 on success, otherwise error
*/
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 124/154] ksmbd: fix slub overflow in ksmbd_decode_ntlmssp_auth_blob()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (122 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 123/154] ksmbd: Fix one kernel-doc comment Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 125/154] ksmbd: add missing calling smb2_set_err_rsp() on error Namjae Jeon
` (30 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, zdi-disclosures, Steve French
[ Upstream commit 4b081ce0d830b684fdf967abc3696d1261387254 ]
If authblob->SessionKey.Length is bigger than session key
size(CIFS_KEY_SIZE), slub overflow can happen in key exchange codes.
cifs_arc4_crypt copy to session key array from SessionKey from client.
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21940
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/auth.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
index ee912d24ad94..9a08e6a90b94 100644
--- a/fs/ksmbd/auth.c
+++ b/fs/ksmbd/auth.c
@@ -355,6 +355,9 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
if (blob_len < (u64)sess_key_off + sess_key_len)
return -EINVAL;
+ if (sess_key_len > CIFS_KEY_SIZE)
+ return -EINVAL;
+
ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
if (!ctx_arc4)
return -ENOMEM;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 125/154] ksmbd: add missing calling smb2_set_err_rsp() on error
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (123 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 124/154] ksmbd: fix slub overflow in ksmbd_decode_ntlmssp_auth_blob() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 126/154] ksmbd: remove experimental warning Namjae Jeon
` (29 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 0e2378eaa2b3a663726cf740d4aaa8a801e2cb31 ]
If some error happen on smb2_sess_setup(), Need to call
smb2_set_err_rsp() to set error response.
This patch add missing calling smb2_set_err_rsp() on error.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 67eb41255903..ef3878bb313b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1904,6 +1904,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
ksmbd_conn_set_need_negotiate(conn);
}
}
+ smb2_set_err_rsp(work);
} else {
unsigned int iov_len;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 126/154] ksmbd: remove experimental warning
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (124 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 125/154] ksmbd: add missing calling smb2_set_err_rsp() on error Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 127/154] ksmbd: remove unneeded mark_inode_dirty in set_info_sec() Namjae Jeon
` (28 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Steve French, Namjae Jeon
From: Steve French <stfrench@microsoft.com>
[ Upstream commit f5069159f32c8c943e047f22731317463c8e9b84 ]
ksmbd has made significant improvements over the past two
years and is regularly tested and used. Remove the experimental
warning.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/Kconfig | 2 +-
fs/ksmbd/server.c | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/fs/ksmbd/Kconfig b/fs/ksmbd/Kconfig
index 7055cb5d2880..d036ab80fec3 100644
--- a/fs/ksmbd/Kconfig
+++ b/fs/ksmbd/Kconfig
@@ -1,5 +1,5 @@
config SMB_SERVER
- tristate "SMB3 server support (EXPERIMENTAL)"
+ tristate "SMB3 server support"
depends on INET
depends on MULTIUSER
depends on FILE_LOCKING
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index ff1514c79f16..f5d8e405cf6f 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -591,8 +591,6 @@ static int __init ksmbd_server_init(void)
if (ret)
goto err_crypto_destroy;
- pr_warn_once("The ksmbd server is experimental\n");
-
return 0;
err_crypto_destroy:
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 127/154] ksmbd: remove unneeded mark_inode_dirty in set_info_sec()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (125 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 126/154] ksmbd: remove experimental warning Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 128/154] ksmbd: fix passing freed memory 'aux_payload_buf' Namjae Jeon
` (27 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit e4e14095cc68a2efefba6f77d95efe1137e751d4 ]
mark_inode_dirty will be called in notify_change().
This patch remove unneeded mark_inode_dirty in set_info_sec().
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smbacl.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index a8b450e62825..d7fd5a15dac4 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -1441,7 +1441,6 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
out:
posix_acl_release(fattr.cf_acls);
posix_acl_release(fattr.cf_dacls);
- mark_inode_dirty(inode);
return rc;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 128/154] ksmbd: fix passing freed memory 'aux_payload_buf'
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (126 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 127/154] ksmbd: remove unneeded mark_inode_dirty in set_info_sec() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 129/154] ksmbd: return invalid parameter error response if smb2 request is invalid Namjae Jeon
` (26 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Dan Carpenter, Steve French
[ Upstream commit 59d8d24f4610333560cf2e8fe3f44cafe30322eb ]
The patch e2b76ab8b5c9: "ksmbd: add support for read compound" leads
to the following Smatch static checker warning:
fs/smb/server/smb2pdu.c:6329 smb2_read()
warn: passing freed memory 'aux_payload_buf'
It doesn't matter that we're passing a freed variable because nbytes is
zero. This patch set "aux_payload_buf = NULL" to make smatch silence.
Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index ef3878bb313b..26aa554a4f6c 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6314,7 +6314,7 @@ int smb2_read(struct ksmbd_work *work)
aux_payload_buf,
nbytes);
kvfree(aux_payload_buf);
-
+ aux_payload_buf = NULL;
nbytes = 0;
if (remain_bytes < 0) {
err = (int)remain_bytes;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 129/154] ksmbd: return invalid parameter error response if smb2 request is invalid
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (127 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 128/154] ksmbd: fix passing freed memory 'aux_payload_buf' Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 130/154] ksmbd: check iov vector index in ksmbd_conn_write() Namjae Jeon
` (25 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Tom Talpey, Steve French
[ Upstream commit f2f11fca5d7112e2f91c4854cddd68a059fdaa4a ]
If smb2 request from client is invalid, The following kernel oops could
happen. The patch e2b76ab8b5c9: "ksmbd: add support for read compound"
leads this issue. When request is invalid, It doesn't set anything in
the response buffer. This patch add missing set invalid parameter error
response.
[ 673.085542] ksmbd: cli req too short, len 184 not 142. cmd:5 mid:109
[ 673.085580] BUG: kernel NULL pointer dereference, address: 0000000000000000
[ 673.085591] #PF: supervisor read access in kernel mode
[ 673.085600] #PF: error_code(0x0000) - not-present page
[ 673.085608] PGD 0 P4D 0
[ 673.085620] Oops: 0000 [#1] PREEMPT SMP NOPTI
[ 673.085631] CPU: 3 PID: 1039 Comm: kworker/3:0 Not tainted 6.6.0-rc2-tmt #16
[ 673.085643] Hardware name: AZW U59/U59, BIOS JTKT001 05/05/2022
[ 673.085651] Workqueue: ksmbd-io handle_ksmbd_work [ksmbd]
[ 673.085719] RIP: 0010:ksmbd_conn_write+0x68/0xc0 [ksmbd]
[ 673.085808] RAX: 0000000000000000 RBX: ffff88811ade4f00 RCX: 0000000000000000
[ 673.085817] RDX: 0000000000000000 RSI: ffff88810c2a9780 RDI: ffff88810c2a9ac0
[ 673.085826] RBP: ffffc900005e3e00 R08: 0000000000000000 R09: 0000000000000000
[ 673.085834] R10: ffffffffa3168160 R11: 63203a64626d736b R12: ffff8881057c8800
[ 673.085842] R13: ffff8881057c8820 R14: ffff8882781b2380 R15: ffff8881057c8800
[ 673.085852] FS: 0000000000000000(0000) GS:ffff888278180000(0000) knlGS:0000000000000000
[ 673.085864] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 673.085872] CR2: 0000000000000000 CR3: 000000015b63c000 CR4: 0000000000350ee0
[ 673.085883] Call Trace:
[ 673.085890] <TASK>
[ 673.085900] ? show_regs+0x6a/0x80
[ 673.085916] ? __die+0x25/0x70
[ 673.085926] ? page_fault_oops+0x154/0x4b0
[ 673.085938] ? tick_nohz_tick_stopped+0x18/0x50
[ 673.085954] ? __irq_work_queue_local+0xba/0x140
[ 673.085967] ? do_user_addr_fault+0x30f/0x6c0
[ 673.085979] ? exc_page_fault+0x79/0x180
[ 673.085992] ? asm_exc_page_fault+0x27/0x30
[ 673.086009] ? ksmbd_conn_write+0x68/0xc0 [ksmbd]
[ 673.086067] ? ksmbd_conn_write+0x46/0xc0 [ksmbd]
[ 673.086123] handle_ksmbd_work+0x28d/0x4b0 [ksmbd]
[ 673.086177] process_one_work+0x178/0x350
[ 673.086193] ? __pfx_worker_thread+0x10/0x10
[ 673.086202] worker_thread+0x2f3/0x420
[ 673.086210] ? _raw_spin_unlock_irqrestore+0x27/0x50
[ 673.086222] ? __pfx_worker_thread+0x10/0x10
[ 673.086230] kthread+0x103/0x140
[ 673.086242] ? __pfx_kthread+0x10/0x10
[ 673.086253] ret_from_fork+0x39/0x60
[ 673.086263] ? __pfx_kthread+0x10/0x10
[ 673.086274] ret_from_fork_asm+0x1b/0x30
Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound")
Reported-by: Tom Talpey <tom@talpey.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/server.c | 4 +++-
fs/ksmbd/smb2misc.c | 4 +---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index f5d8e405cf6f..633383e55723 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -115,8 +115,10 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
if (check_conn_state(work))
return SERVER_HANDLER_CONTINUE;
- if (ksmbd_verify_smb_message(work))
+ if (ksmbd_verify_smb_message(work)) {
+ conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
return SERVER_HANDLER_ABORT;
+ }
command = conn->ops->get_cmd_val(work);
*cmd = command;
diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c
index 8ef9503c4ab9..39e523f115d2 100644
--- a/fs/ksmbd/smb2misc.c
+++ b/fs/ksmbd/smb2misc.c
@@ -441,10 +441,8 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
validate_credit:
if ((work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) &&
- smb2_validate_credit_charge(work->conn, hdr)) {
- work->conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
+ smb2_validate_credit_charge(work->conn, hdr))
return 1;
- }
return 0;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 130/154] ksmbd: check iov vector index in ksmbd_conn_write()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (128 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 129/154] ksmbd: return invalid parameter error response if smb2 request is invalid Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 131/154] ksmbd: fix race condition between session lookup and expire Namjae Jeon
` (24 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 73f949ea87c7d697210653501ca21efe57295327 ]
If ->iov_idx is zero, This means that the iov vector for the response
was not added during the request process. In other words, it means that
there is a problem in generating a response, So this patch return as
an error to avoid NULL pointer dereferencing problem.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 585f117bda8a..9e12738a56c6 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -197,6 +197,9 @@ int ksmbd_conn_write(struct ksmbd_work *work)
if (work->send_no_response)
return 0;
+ if (!work->iov_idx)
+ return -EINVAL;
+
ksmbd_conn_lock(conn);
sent = conn->transport->ops->writev(conn->transport, work->iov,
work->iov_cnt,
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 131/154] ksmbd: fix race condition between session lookup and expire
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (129 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 130/154] ksmbd: check iov vector index in ksmbd_conn_write() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 132/154] ksmbd: fix race condition with fp Namjae Jeon
` (23 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, luosili, Steve French
[ Upstream commit 53ff5cf89142b978b1a5ca8dc4d4425e6a09745f ]
Thread A + Thread B
ksmbd_session_lookup | smb2_sess_setup
sess = xa_load |
|
| xa_erase(&conn->sessions, sess->id);
|
| ksmbd_session_destroy(sess) --> kfree(sess)
|
// UAF! |
sess->last_active = jiffies |
+
This patch add rwsem to fix race condition between ksmbd_session_lookup
and ksmbd_expire_session.
Reported-by: luosili <rootlab@huawei.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 2 ++
fs/ksmbd/connection.h | 1 +
fs/ksmbd/mgmt/user_session.c | 10 +++++++---
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 9e12738a56c6..28b65a43fa39 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -84,6 +84,8 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
spin_lock_init(&conn->llist_lock);
INIT_LIST_HEAD(&conn->lock_list);
+ init_rwsem(&conn->session_lock);
+
down_write(&conn_list_lock);
list_add(&conn->conns_list, &conn_list);
up_write(&conn_list_lock);
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index ab2583f030ce..3c005246a32e 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -50,6 +50,7 @@ struct ksmbd_conn {
struct nls_table *local_nls;
struct unicode_map *um;
struct list_head conns_list;
+ struct rw_semaphore session_lock;
/* smb session 1 per user */
struct xarray sessions;
unsigned long last_active;
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index 8a5dcab05614..b8be14a96cf6 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -174,7 +174,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
unsigned long id;
struct ksmbd_session *sess;
- down_write(&sessions_table_lock);
+ down_write(&conn->session_lock);
xa_for_each(&conn->sessions, id, sess) {
if (sess->state != SMB2_SESSION_VALID ||
time_after(jiffies,
@@ -185,7 +185,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
continue;
}
}
- up_write(&sessions_table_lock);
+ up_write(&conn->session_lock);
}
int ksmbd_session_register(struct ksmbd_conn *conn,
@@ -227,7 +227,9 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
}
}
}
+ up_write(&sessions_table_lock);
+ down_write(&conn->session_lock);
xa_for_each(&conn->sessions, id, sess) {
unsigned long chann_id;
struct channel *chann;
@@ -244,7 +246,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
ksmbd_session_destroy(sess);
}
}
- up_write(&sessions_table_lock);
+ up_write(&conn->session_lock);
}
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
@@ -252,9 +254,11 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
{
struct ksmbd_session *sess;
+ down_read(&conn->session_lock);
sess = xa_load(&conn->sessions, id);
if (sess)
sess->last_active = jiffies;
+ up_read(&conn->session_lock);
return sess;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 132/154] ksmbd: fix race condition with fp
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (130 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 131/154] ksmbd: fix race condition between session lookup and expire Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 133/154] ksmbd: fix race condition from parallel smb2 logoff requests Namjae Jeon
` (22 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, luosili, Steve French
[ Upstream commit 5a7ee91d1154f35418367a6eaae74046fd06ed89 ]
fp can used in each command. If smb2_close command is coming at the
same time, UAF issue can happen by race condition.
Time
+
Thread A | Thread B1 B2 .... B5
smb2_open | smb2_close
|
__open_id |
insert fp to file_table |
|
| atomic_dec_and_test(&fp->refcount)
| if fp->refcount == 0, free fp by kfree.
// UAF! |
use fp |
+
This patch add f_state not to use freed fp is used and not to free fp in
use.
Reported-by: luosili <rootlab@huawei.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 4 +++-
fs/ksmbd/vfs_cache.c | 23 ++++++++++++++++++++---
fs/ksmbd/vfs_cache.h | 9 +++++++++
3 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 26aa554a4f6c..2f1ffd3bf2fb 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3367,8 +3367,10 @@ int smb2_open(struct ksmbd_work *work)
}
ksmbd_revert_fsids(work);
err_out1:
- if (!rc)
+ if (!rc) {
+ ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED);
rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len);
+ }
if (rc) {
if (rc == -EINVAL)
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index 94ad8fa07b46..f600279b0a9e 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -332,6 +332,9 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp)
{
+ if (fp->f_state != FP_INITED)
+ return NULL;
+
if (!atomic_inc_not_zero(&fp->refcount))
return NULL;
return fp;
@@ -381,15 +384,20 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
return 0;
ft = &work->sess->file_table;
- read_lock(&ft->lock);
+ write_lock(&ft->lock);
fp = idr_find(ft->idr, id);
if (fp) {
set_close_state_blocked_works(fp);
- if (!atomic_dec_and_test(&fp->refcount))
+ if (fp->f_state != FP_INITED)
fp = NULL;
+ else {
+ fp->f_state = FP_CLOSED;
+ if (!atomic_dec_and_test(&fp->refcount))
+ fp = NULL;
+ }
}
- read_unlock(&ft->lock);
+ write_unlock(&ft->lock);
if (!fp)
return -EINVAL;
@@ -569,6 +577,7 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
fp->tcon = work->tcon;
fp->volatile_id = KSMBD_NO_FID;
fp->persistent_id = KSMBD_NO_FID;
+ fp->f_state = FP_NEW;
fp->f_ci = ksmbd_inode_get(fp);
if (!fp->f_ci) {
@@ -590,6 +599,14 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
return ERR_PTR(ret);
}
+void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
+ unsigned int state)
+{
+ write_lock(&ft->lock);
+ fp->f_state = state;
+ write_unlock(&ft->lock);
+}
+
static int
__close_file_table_ids(struct ksmbd_file_table *ft,
struct ksmbd_tree_connect *tcon,
diff --git a/fs/ksmbd/vfs_cache.h b/fs/ksmbd/vfs_cache.h
index fcb13413fa8d..03d0bf941216 100644
--- a/fs/ksmbd/vfs_cache.h
+++ b/fs/ksmbd/vfs_cache.h
@@ -60,6 +60,12 @@ struct ksmbd_inode {
__le32 m_fattr;
};
+enum {
+ FP_NEW = 0,
+ FP_INITED,
+ FP_CLOSED
+};
+
struct ksmbd_file {
struct file *filp;
u64 persistent_id;
@@ -98,6 +104,7 @@ struct ksmbd_file {
/* if ls is happening on directory, below is valid*/
struct ksmbd_readdir_data readdir_data;
int dot_dotdot[2];
+ unsigned int f_state;
};
static inline void set_ctx_actor(struct dir_context *ctx,
@@ -142,6 +149,8 @@ int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode);
int ksmbd_init_global_file_table(void);
void ksmbd_free_global_file_table(void);
void ksmbd_set_fd_limit(unsigned long limit);
+void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
+ unsigned int state);
/*
* INODE hash
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 133/154] ksmbd: fix race condition from parallel smb2 logoff requests
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (131 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 132/154] ksmbd: fix race condition with fp Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 134/154] ksmbd: fix race condition from parallel smb2 lock requests Namjae Jeon
` (21 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, luosili, Steve French
[ Upstream commit 7ca9da7d873ee8024e9548d3366101c2b6843eab ]
If parallel smb2 logoff requests come in before closing door, running
request count becomes more than 1 even though connection status is set to
KSMBD_SESS_NEED_RECONNECT. It can't get condition true, and sleep forever.
This patch fix race condition problem by returning error if connection
status was already set to KSMBD_SESS_NEED_RECONNECT.
Reported-by: luosili <rootlab@huawei.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 2f1ffd3bf2fb..924b561e8c81 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2164,17 +2164,17 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_debug(SMB, "request\n");
- sess_id = le64_to_cpu(req->hdr.SessionId);
-
- rsp->StructureSize = cpu_to_le16(4);
- err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));
- if (err) {
- rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ ksmbd_conn_lock(conn);
+ if (!ksmbd_conn_good(conn)) {
+ ksmbd_conn_unlock(conn);
+ rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
smb2_set_err_rsp(work);
- return err;
+ return -ENOENT;
}
-
+ sess_id = le64_to_cpu(req->hdr.SessionId);
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT);
+ ksmbd_conn_unlock(conn);
+
ksmbd_close_session_fds(work);
ksmbd_conn_wait_idle(conn, sess_id);
@@ -2196,6 +2196,14 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_free_user(sess->user);
sess->user = NULL;
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE);
+
+ rsp->StructureSize = cpu_to_le16(4);
+ err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));
+ if (err) {
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ smb2_set_err_rsp(work);
+ return err;
+ }
return 0;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 134/154] ksmbd: fix race condition from parallel smb2 lock requests
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (132 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 133/154] ksmbd: fix race condition from parallel smb2 logoff requests Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 135/154] ksmbd: fix race condition between tree conn lookup and disconnect Namjae Jeon
` (20 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, luosili, Steve French
[ Upstream commit 75ac9a3dd65f7eab4d12b0a0f744234b5300a491 ]
There is a race condition issue between parallel smb2 lock request.
Time
+
Thread A | Thread A
smb2_lock | smb2_lock
|
insert smb_lock to lock_list |
spin_unlock(&work->conn->llist_lock) |
|
| spin_lock(&conn->llist_lock);
| kfree(cmp_lock);
|
// UAF! |
list_add(&smb_lock->llist, &rollback_list) +
This patch swaps the line for adding the smb lock to the rollback list and
adding the lock list of connection to fix the race issue.
Reported-by: luosili <rootlab@huawei.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 924b561e8c81..560d81799647 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -7040,10 +7040,6 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_debug(SMB,
"would have to wait for getting lock\n");
- spin_lock(&work->conn->llist_lock);
- list_add_tail(&smb_lock->clist,
- &work->conn->lock_list);
- spin_unlock(&work->conn->llist_lock);
list_add(&smb_lock->llist, &rollback_list);
argv = kmalloc(sizeof(void *), GFP_KERNEL);
@@ -7074,9 +7070,6 @@ int smb2_lock(struct ksmbd_work *work)
if (work->state != KSMBD_WORK_ACTIVE) {
list_del(&smb_lock->llist);
- spin_lock(&work->conn->llist_lock);
- list_del(&smb_lock->clist);
- spin_unlock(&work->conn->llist_lock);
locks_free_lock(flock);
if (work->state == KSMBD_WORK_CANCELLED) {
@@ -7096,19 +7089,16 @@ int smb2_lock(struct ksmbd_work *work)
}
list_del(&smb_lock->llist);
- spin_lock(&work->conn->llist_lock);
- list_del(&smb_lock->clist);
- spin_unlock(&work->conn->llist_lock);
release_async_work(work);
goto retry;
} else if (!rc) {
+ list_add(&smb_lock->llist, &rollback_list);
spin_lock(&work->conn->llist_lock);
list_add_tail(&smb_lock->clist,
&work->conn->lock_list);
list_add_tail(&smb_lock->flist,
&fp->lock_list);
spin_unlock(&work->conn->llist_lock);
- list_add(&smb_lock->llist, &rollback_list);
ksmbd_debug(SMB, "successful in taking lock\n");
} else {
goto out;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 135/154] ksmbd: fix race condition between tree conn lookup and disconnect
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (133 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 134/154] ksmbd: fix race condition from parallel smb2 lock requests Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 136/154] ksmbd: fix wrong error response status by using set_smb2_rsp_status() Namjae Jeon
` (19 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, luosili, Steve French
[ Upstream commit 33b235a6e6ebe0f05f3586a71e8d281d00f71e2e ]
if thread A in smb2_write is using work-tcon, other thread B use
smb2_tree_disconnect free the tcon, then thread A will use free'd tcon.
Time
+
Thread A | Thread A
smb2_write | smb2_tree_disconnect
|
|
| kfree(tree_conn)
|
// UAF! |
work->tcon->share_conf |
+
This patch add state, reference count and lock for tree conn to fix race
condition issue.
Reported-by: luosili <rootlab@huawei.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/tree_connect.c | 42 +++++++++++++++++++++++++++---
fs/ksmbd/mgmt/tree_connect.h | 11 ++++++--
fs/ksmbd/mgmt/user_session.c | 1 +
fs/ksmbd/mgmt/user_session.h | 1 +
fs/ksmbd/server.c | 2 ++
fs/ksmbd/smb2pdu.c | 50 +++++++++++++++++++++++++++---------
6 files changed, 90 insertions(+), 17 deletions(-)
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
index 408cddf2f094..d2c81a8a11dd 100644
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ b/fs/ksmbd/mgmt/tree_connect.c
@@ -73,7 +73,10 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
tree_conn->user = sess->user;
tree_conn->share_conf = sc;
+ tree_conn->t_state = TREE_NEW;
status.tree_conn = tree_conn;
+ atomic_set(&tree_conn->refcount, 1);
+ init_waitqueue_head(&tree_conn->refcount_q);
ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
GFP_KERNEL));
@@ -93,14 +96,33 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
return status;
}
+void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon)
+{
+ /*
+ * Checking waitqueue to releasing tree connect on
+ * tree disconnect. waitqueue_active is safe because it
+ * uses atomic operation for condition.
+ */
+ if (!atomic_dec_return(&tcon->refcount) &&
+ waitqueue_active(&tcon->refcount_q))
+ wake_up(&tcon->refcount_q);
+}
+
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *tree_conn)
{
int ret;
+ write_lock(&sess->tree_conns_lock);
+ xa_erase(&sess->tree_conns, tree_conn->id);
+ write_unlock(&sess->tree_conns_lock);
+
+ if (!atomic_dec_and_test(&tree_conn->refcount))
+ wait_event(tree_conn->refcount_q,
+ atomic_read(&tree_conn->refcount) == 0);
+
ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
ksmbd_release_tree_conn_id(sess, tree_conn->id);
- xa_erase(&sess->tree_conns, tree_conn->id);
ksmbd_share_config_put(tree_conn->share_conf);
kfree(tree_conn);
return ret;
@@ -111,11 +133,15 @@ struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
{
struct ksmbd_tree_connect *tcon;
+ read_lock(&sess->tree_conns_lock);
tcon = xa_load(&sess->tree_conns, id);
if (tcon) {
- if (test_bit(TREE_CONN_EXPIRE, &tcon->status))
+ if (tcon->t_state != TREE_CONNECTED)
+ tcon = NULL;
+ else if (!atomic_inc_not_zero(&tcon->refcount))
tcon = NULL;
}
+ read_unlock(&sess->tree_conns_lock);
return tcon;
}
@@ -129,8 +155,18 @@ int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
if (!sess)
return -EINVAL;
- xa_for_each(&sess->tree_conns, id, tc)
+ xa_for_each(&sess->tree_conns, id, tc) {
+ write_lock(&sess->tree_conns_lock);
+ if (tc->t_state == TREE_DISCONNECTED) {
+ write_unlock(&sess->tree_conns_lock);
+ ret = -ENOENT;
+ continue;
+ }
+ tc->t_state = TREE_DISCONNECTED;
+ write_unlock(&sess->tree_conns_lock);
+
ret |= ksmbd_tree_conn_disconnect(sess, tc);
+ }
xa_destroy(&sess->tree_conns);
return ret;
}
diff --git a/fs/ksmbd/mgmt/tree_connect.h b/fs/ksmbd/mgmt/tree_connect.h
index 562d647ad9fa..6377a70b811c 100644
--- a/fs/ksmbd/mgmt/tree_connect.h
+++ b/fs/ksmbd/mgmt/tree_connect.h
@@ -14,7 +14,11 @@ struct ksmbd_share_config;
struct ksmbd_user;
struct ksmbd_conn;
-#define TREE_CONN_EXPIRE 1
+enum {
+ TREE_NEW = 0,
+ TREE_CONNECTED,
+ TREE_DISCONNECTED
+};
struct ksmbd_tree_connect {
int id;
@@ -27,7 +31,9 @@ struct ksmbd_tree_connect {
int maximal_access;
bool posix_extensions;
- unsigned long status;
+ atomic_t refcount;
+ wait_queue_head_t refcount_q;
+ unsigned int t_state;
};
struct ksmbd_tree_conn_status {
@@ -46,6 +52,7 @@ struct ksmbd_session;
struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
const char *share_name);
+void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon);
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *tree_conn);
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index b8be14a96cf6..15f68ee05089 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -355,6 +355,7 @@ static struct ksmbd_session *__session_create(int protocol)
xa_init(&sess->ksmbd_chann_list);
xa_init(&sess->rpc_handle_list);
sess->sequence_number = 1;
+ rwlock_init(&sess->tree_conns_lock);
ret = __init_smb2_session(sess);
if (ret)
diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h
index f99d475b28db..63cb08fffde8 100644
--- a/fs/ksmbd/mgmt/user_session.h
+++ b/fs/ksmbd/mgmt/user_session.h
@@ -60,6 +60,7 @@ struct ksmbd_session {
struct ksmbd_file_table file_table;
unsigned long last_active;
+ rwlock_t tree_conns_lock;
};
static inline int test_session_flag(struct ksmbd_session *sess, int bit)
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index 633383e55723..11b201e6ee44 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -241,6 +241,8 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
} while (is_chained == true);
send:
+ if (work->tcon)
+ ksmbd_tree_connect_put(work->tcon);
smb3_preauth_hash_rsp(work);
if (work->sess && work->sess->enc && work->encrypted &&
conn->ops->encrypt_resp) {
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 560d81799647..358ff5bf6dcc 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1993,6 +1993,9 @@ int smb2_tree_connect(struct ksmbd_work *work)
if (conn->posix_ext_supported)
status.tree_conn->posix_extensions = true;
+ write_lock(&sess->tree_conns_lock);
+ status.tree_conn->t_state = TREE_CONNECTED;
+ write_unlock(&sess->tree_conns_lock);
rsp->StructureSize = cpu_to_le16(16);
out_err1:
rsp->Capabilities = 0;
@@ -2122,27 +2125,50 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
ksmbd_debug(SMB, "request\n");
+ if (!tcon) {
+ ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+
+ rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+ err = -ENOENT;
+ goto err_out;
+ }
+
+ ksmbd_close_tree_conn_fds(work);
+
+ write_lock(&sess->tree_conns_lock);
+ if (tcon->t_state == TREE_DISCONNECTED) {
+ write_unlock(&sess->tree_conns_lock);
+ rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+ err = -ENOENT;
+ goto err_out;
+ }
+
+ WARN_ON_ONCE(atomic_dec_and_test(&tcon->refcount));
+ tcon->t_state = TREE_DISCONNECTED;
+ write_unlock(&sess->tree_conns_lock);
+
+ err = ksmbd_tree_conn_disconnect(sess, tcon);
+ if (err) {
+ rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+ goto err_out;
+ }
+
+ work->tcon = NULL;
+
rsp->StructureSize = cpu_to_le16(4);
err = ksmbd_iov_pin_rsp(work, rsp,
sizeof(struct smb2_tree_disconnect_rsp));
if (err) {
rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
- smb2_set_err_rsp(work);
- return err;
+ goto err_out;
}
- if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
- ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+ return 0;
- rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
- smb2_set_err_rsp(work);
- return -ENOENT;
- }
+err_out:
+ smb2_set_err_rsp(work);
+ return err;
- ksmbd_close_tree_conn_fds(work);
- ksmbd_tree_conn_disconnect(sess, tcon);
- work->tcon = NULL;
- return 0;
}
/**
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 136/154] ksmbd: fix wrong error response status by using set_smb2_rsp_status()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (134 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 135/154] ksmbd: fix race condition between tree conn lookup and disconnect Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 137/154] ksmbd: fix Null pointer dereferences in ksmbd_update_fstate() Namjae Jeon
` (18 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit be0f89d4419dc5413a1cf06db3671c9949be0d52 ]
set_smb2_rsp_status() after __process_request() sets the wrong error
status. This patch resets all iov vectors and sets the error status
on clean one.
Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 358ff5bf6dcc..19cee16bb3eb 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -231,11 +231,12 @@ void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
{
struct smb2_hdr *rsp_hdr;
- if (work->next_smb2_rcv_hdr_off)
- rsp_hdr = ksmbd_resp_buf_next(work);
- else
- rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr = smb2_get_msg(work->response_buf);
rsp_hdr->Status = err;
+
+ work->iov_idx = 0;
+ work->iov_cnt = 0;
+ work->next_smb2_rcv_hdr_off = 0;
smb2_set_err_rsp(work);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 137/154] ksmbd: fix Null pointer dereferences in ksmbd_update_fstate()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (135 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 136/154] ksmbd: fix wrong error response status by using set_smb2_rsp_status() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 138/154] ksmbd: fix potential double free on smb2_read_pipe() error path Namjae Jeon
` (17 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Coverity Scan, Steve French
[ Upstream commit 414849040fcf11d45025b8ae26c9fd91da1465da ]
Coverity Scan report the following one. This report is a false alarm.
Because fp is never NULL when rc is zero. This patch add null check for fp
in ksmbd_update_fstate to make alarm silence.
*** CID 1568583: Null pointer dereferences (FORWARD_NULL)
/fs/smb/server/smb2pdu.c: 3408 in smb2_open()
3402 path_put(&path);
3403 path_put(&parent_path);
3404 }
3405 ksmbd_revert_fsids(work);
3406 err_out1:
3407 if (!rc) {
>>> CID 1568583: Null pointer dereferences (FORWARD_NULL)
>>> Passing null pointer "fp" to "ksmbd_update_fstate", which dereferences it.
3408 ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED);
3409 rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len);
3410 }
3411 if (rc) {
3412 if (rc == -EINVAL)
3413 rsp->hdr.Status = STATUS_INVALID_PARAMETER;
Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound")
Reported-by: Coverity Scan <scan-admin@coverity.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs_cache.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index f600279b0a9e..38f414e803ad 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -602,6 +602,9 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
unsigned int state)
{
+ if (!fp)
+ return;
+
write_lock(&ft->lock);
fp->f_state = state;
write_unlock(&ft->lock);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 138/154] ksmbd: fix potential double free on smb2_read_pipe() error path
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (136 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 137/154] ksmbd: fix Null pointer dereferences in ksmbd_update_fstate() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 139/154] ksmbd: Remove unused field in ksmbd_user struct Namjae Jeon
` (16 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Namjae Jeon, kernel test robot, Dan Carpenter,
Steve French
[ Upstream commit 1903e6d0578118e9aab1ee23f4a9de55737d1d05 ]
Fix new smatch warnings:
fs/smb/server/smb2pdu.c:6131 smb2_read_pipe() error: double free of 'rpc_resp'
Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound")
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 19cee16bb3eb..8dad33251925 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -6154,12 +6154,12 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
memcpy(aux_payload_buf, rpc_resp->payload, rpc_resp->payload_sz);
nbytes = rpc_resp->payload_sz;
- kvfree(rpc_resp);
err = ksmbd_iov_pin_rsp_read(work, (void *)rsp,
offsetof(struct smb2_read_rsp, Buffer),
aux_payload_buf, nbytes);
if (err)
goto out;
+ kvfree(rpc_resp);
} else {
err = ksmbd_iov_pin_rsp(work, (void *)rsp,
offsetof(struct smb2_read_rsp, Buffer));
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 139/154] ksmbd: Remove unused field in ksmbd_user struct
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (137 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 138/154] ksmbd: fix potential double free on smb2_read_pipe() error path Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 140/154] ksmbd: reorganize ksmbd_iov_pin_rsp() Namjae Jeon
` (15 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Cheng-Han Wu, Namjae Jeon, Steve French
From: Cheng-Han Wu <hank20010209@gmail.com>
[ Upstream commit eacc655e18d1dec9b50660d16a1ddeeb4d6c48f2 ]
fs/smb/server/mgmt/user_config.h:21: Remove the unused field 'failed_login_count' from the ksmbd_user struct.
Signed-off-by: Cheng-Han Wu <hank20010209@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/mgmt/user_config.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/ksmbd/mgmt/user_config.h b/fs/ksmbd/mgmt/user_config.h
index 6a44109617f1..e068a19fd904 100644
--- a/fs/ksmbd/mgmt/user_config.h
+++ b/fs/ksmbd/mgmt/user_config.h
@@ -18,7 +18,6 @@ struct ksmbd_user {
size_t passkey_sz;
char *passkey;
- unsigned int failed_login_count;
};
static inline bool user_guest(struct ksmbd_user *user)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 140/154] ksmbd: reorganize ksmbd_iov_pin_rsp()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (138 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 139/154] ksmbd: Remove unused field in ksmbd_user struct Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 141/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_setxattr() Namjae Jeon
` (14 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 1819a904299942b309f687cc0f08b123500aa178 ]
If ksmbd_iov_pin_rsp fail, io vertor should be rollback.
This patch moves memory allocations to before setting the io vector
to avoid rollbacks.
Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_work.c | 43 ++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
index 51def3ca74c0..a2ed441e837a 100644
--- a/fs/ksmbd/ksmbd_work.c
+++ b/fs/ksmbd/ksmbd_work.c
@@ -95,11 +95,28 @@ bool ksmbd_queue_work(struct ksmbd_work *work)
return queue_work(ksmbd_wq, &work->work);
}
-static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib,
- unsigned int ib_len)
+static inline void __ksmbd_iov_pin(struct ksmbd_work *work, void *ib,
+ unsigned int ib_len)
{
+ work->iov[++work->iov_idx].iov_base = ib;
+ work->iov[work->iov_idx].iov_len = ib_len;
+ work->iov_cnt++;
+}
+
+static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
+ void *aux_buf, unsigned int aux_size)
+{
+ struct aux_read *ar;
+ int need_iov_cnt = 1;
- if (work->iov_alloc_cnt <= work->iov_cnt) {
+ if (aux_size) {
+ need_iov_cnt++;
+ ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
+ if (!ar)
+ return -ENOMEM;
+ }
+
+ if (work->iov_alloc_cnt < work->iov_cnt + need_iov_cnt) {
struct kvec *new;
work->iov_alloc_cnt += 4;
@@ -111,16 +128,6 @@ static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib,
work->iov = new;
}
- work->iov[++work->iov_idx].iov_base = ib;
- work->iov[work->iov_idx].iov_len = ib_len;
- work->iov_cnt++;
-
- return 0;
-}
-
-static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
- void *aux_buf, unsigned int aux_size)
-{
/* Plus rfc_length size on first iov */
if (!work->iov_idx) {
work->iov[work->iov_idx].iov_base = work->response_buf;
@@ -129,19 +136,13 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
work->iov_cnt++;
}
- ksmbd_realloc_iov_pin(work, ib, len);
+ __ksmbd_iov_pin(work, ib, len);
inc_rfc1001_len(work->iov[0].iov_base, len);
if (aux_size) {
- struct aux_read *ar;
-
- ksmbd_realloc_iov_pin(work, aux_buf, aux_size);
+ __ksmbd_iov_pin(work, aux_buf, aux_size);
inc_rfc1001_len(work->iov[0].iov_base, aux_size);
- ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
- if (!ar)
- return -ENOMEM;
-
ar->buf = aux_buf;
list_add(&ar->entry, &work->aux_read_list);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 141/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_setxattr()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (139 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 140/154] ksmbd: reorganize ksmbd_iov_pin_rsp() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 142/154] ksmbd: fix recursive locking in vfs helpers Namjae Jeon
` (13 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, kernel test robot, Steve French
[ Upstream commit 3354db668808d5b6d7c5e0cb19ff4c9da4bb5e58 ]
Fix argument list that the kdoc format and script verified in
ksmbd_vfs_setxattr().
fs/smb/server/vfs.c:929: warning: Function parameter or member 'path'
not described in 'ksmbd_vfs_setxattr'
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 6b24355800aa..85346780704d 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -919,7 +919,7 @@ ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
/**
* ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
* @user_ns: user namespace
- * @dentry: dentry to set XATTR at
+ * @path: path of dentry to set XATTR at
* @attr_name: xattr name for setxattr
* @attr_value: xattr value to set
* @attr_size: size of xattr value
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 142/154] ksmbd: fix recursive locking in vfs helpers
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (140 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 141/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_setxattr() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 143/154] ksmbd: fix missing RDMA-capable flag for IPoIB device in ksmbd_rdma_capable_netdev() Namjae Jeon
` (12 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Marios Makassikis, Namjae Jeon, Steve French
From: Marios Makassikis <mmakassikis@freebox.fr>
[ Upstream commit 807252f028c59b9a3bac4d62ad84761548c10f11 ]
Running smb2.rename test from Samba smbtorture suite against a kernel built
with lockdep triggers a "possible recursive locking detected" warning.
This is because mnt_want_write() is called twice with no mnt_drop_write()
in between:
-> ksmbd_vfs_mkdir()
-> ksmbd_vfs_kern_path_create()
-> kern_path_create()
-> filename_create()
-> mnt_want_write()
-> mnt_want_write()
Fix this by removing the mnt_want_write/mnt_drop_write calls from vfs
helpers that call kern_path_create().
Full lockdep trace below:
============================================
WARNING: possible recursive locking detected
6.6.0-rc5 #775 Not tainted
--------------------------------------------
kworker/1:1/32 is trying to acquire lock:
ffff888005ac83f8 (sb_writers#5){.+.+}-{0:0}, at: ksmbd_vfs_mkdir+0xe1/0x410
but task is already holding lock:
ffff888005ac83f8 (sb_writers#5){.+.+}-{0:0}, at: filename_create+0xb6/0x260
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(sb_writers#5);
lock(sb_writers#5);
*** DEADLOCK ***
May be due to missing lock nesting notation
4 locks held by kworker/1:1/32:
#0: ffff8880064e4138 ((wq_completion)ksmbd-io){+.+.}-{0:0}, at: process_one_work+0x40e/0x980
#1: ffff888005b0fdd0 ((work_completion)(&work->work)){+.+.}-{0:0}, at: process_one_work+0x40e/0x980
#2: ffff888005ac83f8 (sb_writers#5){.+.+}-{0:0}, at: filename_create+0xb6/0x260
#3: ffff8880057ce760 (&type->i_mutex_dir_key#3/1){+.+.}-{3:3}, at: filename_create+0x123/0x260
Cc: stable@vger.kernel.org
Fixes: 40b268d384a2 ("ksmbd: add mnt_want_write to ksmbd vfs functions")
Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 23 +++--------------------
1 file changed, 3 insertions(+), 20 deletions(-)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 85346780704d..ffcc8f8f35bf 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -173,10 +173,6 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
return err;
}
- err = mnt_want_write(path.mnt);
- if (err)
- goto out_err;
-
mode |= S_IFREG;
err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry),
dentry, mode, true);
@@ -186,9 +182,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
} else {
pr_err("File(%s): creation failed (err:%d)\n", name, err);
}
- mnt_drop_write(path.mnt);
-out_err:
done_path_create(&path, dentry);
return err;
}
@@ -219,10 +213,6 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
return err;
}
- err = mnt_want_write(path.mnt);
- if (err)
- goto out_err2;
-
user_ns = mnt_user_ns(path.mnt);
mode |= S_IFDIR;
err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
@@ -233,21 +223,19 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
dentry->d_name.len);
if (IS_ERR(d)) {
err = PTR_ERR(d);
- goto out_err1;
+ goto out_err;
}
if (unlikely(d_is_negative(d))) {
dput(d);
err = -ENOENT;
- goto out_err1;
+ goto out_err;
}
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(d));
dput(d);
}
-out_err1:
- mnt_drop_write(path.mnt);
-out_err2:
+out_err:
done_path_create(&path, dentry);
if (err)
pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
@@ -665,16 +653,11 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
goto out3;
}
- err = mnt_want_write(newpath.mnt);
- if (err)
- goto out3;
-
err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt),
d_inode(newpath.dentry),
dentry, NULL);
if (err)
ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
- mnt_drop_write(newpath.mnt);
out3:
done_path_create(&newpath, dentry);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 143/154] ksmbd: fix missing RDMA-capable flag for IPoIB device in ksmbd_rdma_capable_netdev()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (141 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 142/154] ksmbd: fix recursive locking in vfs helpers Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 144/154] ksmbd: add support for surrogate pair conversion Namjae Jeon
` (11 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Kangjing Huang, Namjae Jeon, Tom Talpey, Steve French
From: Kangjing Huang <huangkangjing@gmail.com>
[ Upstream commit ecce70cf17d91c3dd87a0c4ea00b2d1387729701 ]
Physical ib_device does not have an underlying net_device, thus its
association with IPoIB net_device cannot be retrieved via
ops.get_netdev() or ib_device_get_by_netdev(). ksmbd reads physical
ib_device port GUID from the lower 16 bytes of the hardware addresses on
IPoIB net_device and match its underlying ib_device using ib_find_gid()
Signed-off-by: Kangjing Huang <huangkangjing@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Tom Talpey <tom@talpey.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/transport_rdma.c | 40 +++++++++++++++++++++++++++++----------
1 file changed, 30 insertions(+), 10 deletions(-)
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 80765bbe8efc..252a1e7afcc0 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -2140,8 +2140,7 @@ static int smb_direct_ib_client_add(struct ib_device *ib_dev)
if (ib_dev->node_type != RDMA_NODE_IB_CA)
smb_direct_port = SMB_DIRECT_PORT_IWARP;
- if (!ib_dev->ops.get_netdev ||
- !rdma_frwr_is_supported(&ib_dev->attrs))
+ if (!rdma_frwr_is_supported(&ib_dev->attrs))
return 0;
smb_dev = kzalloc(sizeof(*smb_dev), GFP_KERNEL);
@@ -2241,17 +2240,38 @@ bool ksmbd_rdma_capable_netdev(struct net_device *netdev)
for (i = 0; i < smb_dev->ib_dev->phys_port_cnt; i++) {
struct net_device *ndev;
- ndev = smb_dev->ib_dev->ops.get_netdev(smb_dev->ib_dev,
- i + 1);
- if (!ndev)
- continue;
+ if (smb_dev->ib_dev->ops.get_netdev) {
+ ndev = smb_dev->ib_dev->ops.get_netdev(
+ smb_dev->ib_dev, i + 1);
+ if (!ndev)
+ continue;
- if (ndev == netdev) {
+ if (ndev == netdev) {
+ dev_put(ndev);
+ rdma_capable = true;
+ goto out;
+ }
dev_put(ndev);
- rdma_capable = true;
- goto out;
+ /* if ib_dev does not implement ops.get_netdev
+ * check for matching infiniband GUID in hw_addr
+ */
+ } else if (netdev->type == ARPHRD_INFINIBAND) {
+ struct netdev_hw_addr *ha;
+ union ib_gid gid;
+ u32 port_num;
+ int ret;
+
+ netdev_hw_addr_list_for_each(
+ ha, &netdev->dev_addrs) {
+ memcpy(&gid, ha->addr + 4, sizeof(gid));
+ ret = ib_find_gid(smb_dev->ib_dev, &gid,
+ &port_num, NULL);
+ if (!ret) {
+ rdma_capable = true;
+ goto out;
+ }
+ }
}
- dev_put(ndev);
}
}
out:
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 144/154] ksmbd: add support for surrogate pair conversion
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (142 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 143/154] ksmbd: fix missing RDMA-capable flag for IPoIB device in ksmbd_rdma_capable_netdev() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 145/154] ksmbd: no need to wait for binded connection termination at logoff Namjae Jeon
` (10 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Marios Makassikis, Steve French
[ Upstream commit 0c180317c654a494fe429adbf7bc9b0793caf9e2 ]
ksmbd is missing supporting to convert filename included surrogate pair
characters. It triggers a "file or folder does not exist" error in
Windows client.
[Steps to Reproduce for bug]
1. Create surrogate pair file
touch $(echo -e '\xf0\x9d\x9f\xa3')
touch $(echo -e '\xf0\x9d\x9f\xa4')
2. Try to open these files in ksmbd share through Windows client.
This patch update unicode functions not to consider about surrogate pair
(and IVS).
Reviewed-by: Marios Makassikis <mmakassikis@freebox.fr>
Tested-by: Marios Makassikis <mmakassikis@freebox.fr>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/unicode.c | 187 +++++++++++++++++++++++++++++++++------------
1 file changed, 138 insertions(+), 49 deletions(-)
diff --git a/fs/ksmbd/unicode.c b/fs/ksmbd/unicode.c
index 9ae676906ed3..33fc6d45c0f3 100644
--- a/fs/ksmbd/unicode.c
+++ b/fs/ksmbd/unicode.c
@@ -14,46 +14,10 @@
#include "uniupr.h"
#include "smb_common.h"
-/*
- * smb_utf16_bytes() - how long will a string be after conversion?
- * @from: pointer to input string
- * @maxbytes: don't go past this many bytes of input string
- * @codepage: destination codepage
- *
- * Walk a utf16le string and return the number of bytes that the string will
- * be after being converted to the given charset, not including any null
- * termination required. Don't walk past maxbytes in the source buffer.
- *
- * Return: string length after conversion
- */
-static int smb_utf16_bytes(const __le16 *from, int maxbytes,
- const struct nls_table *codepage)
-{
- int i;
- int charlen, outlen = 0;
- int maxwords = maxbytes / 2;
- char tmp[NLS_MAX_CHARSET_SIZE];
- __u16 ftmp;
-
- for (i = 0; i < maxwords; i++) {
- ftmp = get_unaligned_le16(&from[i]);
- if (ftmp == 0)
- break;
-
- charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE);
- if (charlen > 0)
- outlen += charlen;
- else
- outlen++;
- }
-
- return outlen;
-}
-
/*
* cifs_mapchar() - convert a host-endian char to proper char in codepage
* @target: where converted character should be copied
- * @src_char: 2 byte host-endian source character
+ * @from: host-endian source string
* @cp: codepage to which character should be converted
* @mapchar: should character be mapped according to mapchars mount option?
*
@@ -64,10 +28,13 @@ static int smb_utf16_bytes(const __le16 *from, int maxbytes,
* Return: string length after conversion
*/
static int
-cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
+cifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp,
bool mapchar)
{
int len = 1;
+ __u16 src_char;
+
+ src_char = *from;
if (!mapchar)
goto cp_convert;
@@ -105,12 +72,66 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
cp_convert:
len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
- if (len <= 0) {
- *target = '?';
- len = 1;
- }
+ if (len <= 0)
+ goto surrogate_pair;
goto out;
+
+surrogate_pair:
+ /* convert SURROGATE_PAIR and IVS */
+ if (strcmp(cp->charset, "utf8"))
+ goto unknown;
+ len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6);
+ if (len <= 0)
+ goto unknown;
+ return len;
+
+unknown:
+ *target = '?';
+ len = 1;
+ goto out;
+}
+
+/*
+ * smb_utf16_bytes() - compute converted string length
+ * @from: pointer to input string
+ * @maxbytes: input string length
+ * @codepage: destination codepage
+ *
+ * Walk a utf16le string and return the number of bytes that the string will
+ * be after being converted to the given charset, not including any null
+ * termination required. Don't walk past maxbytes in the source buffer.
+ *
+ * Return: string length after conversion
+ */
+static int smb_utf16_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage)
+{
+ int i, j;
+ int charlen, outlen = 0;
+ int maxwords = maxbytes / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+ __u16 ftmp[3];
+
+ for (i = 0; i < maxwords; i++) {
+ ftmp[0] = get_unaligned_le16(&from[i]);
+ if (ftmp[0] == 0)
+ break;
+ for (j = 1; j <= 2; j++) {
+ if (i + j < maxwords)
+ ftmp[j] = get_unaligned_le16(&from[i + j]);
+ else
+ ftmp[j] = 0;
+ }
+
+ charlen = cifs_mapchar(tmp, ftmp, codepage, 0);
+ if (charlen > 0)
+ outlen += charlen;
+ else
+ outlen++;
+ }
+
+ return outlen;
}
/*
@@ -140,12 +161,12 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
const struct nls_table *codepage, bool mapchar)
{
- int i, charlen, safelen;
+ int i, j, charlen, safelen;
int outlen = 0;
int nullsize = nls_nullsize(codepage);
int fromwords = fromlen / 2;
char tmp[NLS_MAX_CHARSET_SIZE];
- __u16 ftmp;
+ __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */
/*
* because the chars can be of varying widths, we need to take care
@@ -156,9 +177,15 @@ static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
for (i = 0; i < fromwords; i++) {
- ftmp = get_unaligned_le16(&from[i]);
- if (ftmp == 0)
+ ftmp[0] = get_unaligned_le16(&from[i]);
+ if (ftmp[0] == 0)
break;
+ for (j = 1; j <= 2; j++) {
+ if (i + j < fromwords)
+ ftmp[j] = get_unaligned_le16(&from[i + j]);
+ else
+ ftmp[j] = 0;
+ }
/*
* check to see if converting this character might make the
@@ -173,6 +200,19 @@ static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
/* put converted char into 'to' buffer */
charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar);
outlen += charlen;
+
+ /*
+ * charlen (=bytes of UTF-8 for 1 character)
+ * 4bytes UTF-8(surrogate pair) is charlen=4
+ * (4bytes UTF-16 code)
+ * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4
+ * (2 UTF-8 pairs divided to 2 UTF-16 pairs)
+ */
+ if (charlen == 4)
+ i++;
+ else if (charlen >= 5)
+ /* 5-6bytes UTF-8 */
+ i += 2;
}
/* properly null-terminate string */
@@ -307,6 +347,9 @@ int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
char src_char;
__le16 dst_char;
wchar_t tmp;
+ wchar_t wchar_to[6]; /* UTF-16 */
+ int ret;
+ unicode_t u;
if (!mapchars)
return smb_strtoUTF16(target, source, srclen, cp);
@@ -349,11 +392,57 @@ int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
* if no match, use question mark, which at least in
* some cases serves as wild card
*/
- if (charlen < 1) {
- dst_char = cpu_to_le16(0x003f);
- charlen = 1;
+ if (charlen > 0)
+ goto ctoUTF16;
+
+ /* convert SURROGATE_PAIR */
+ if (strcmp(cp->charset, "utf8"))
+ goto unknown;
+ if (*(source + i) & 0x80) {
+ charlen = utf8_to_utf32(source + i, 6, &u);
+ if (charlen < 0)
+ goto unknown;
+ } else
+ goto unknown;
+ ret = utf8s_to_utf16s(source + i, charlen,
+ UTF16_LITTLE_ENDIAN,
+ wchar_to, 6);
+ if (ret < 0)
+ goto unknown;
+
+ i += charlen;
+ dst_char = cpu_to_le16(*wchar_to);
+ if (charlen <= 3)
+ /* 1-3bytes UTF-8 to 2bytes UTF-16 */
+ put_unaligned(dst_char, &target[j]);
+ else if (charlen == 4) {
+ /*
+ * 4bytes UTF-8(surrogate pair) to 4bytes UTF-16
+ * 7-8bytes UTF-8(IVS) divided to 2 UTF-16
+ * (charlen=3+4 or 4+4)
+ */
+ put_unaligned(dst_char, &target[j]);
+ dst_char = cpu_to_le16(*(wchar_to + 1));
+ j++;
+ put_unaligned(dst_char, &target[j]);
+ } else if (charlen >= 5) {
+ /* 5-6bytes UTF-8 to 6bytes UTF-16 */
+ put_unaligned(dst_char, &target[j]);
+ dst_char = cpu_to_le16(*(wchar_to + 1));
+ j++;
+ put_unaligned(dst_char, &target[j]);
+ dst_char = cpu_to_le16(*(wchar_to + 2));
+ j++;
+ put_unaligned(dst_char, &target[j]);
}
+ continue;
+
+unknown:
+ dst_char = cpu_to_le16(0x003f);
+ charlen = 1;
}
+
+ctoUTF16:
/*
* character may take more than one byte in the source string,
* but will take exactly two bytes in the target string
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 145/154] ksmbd: no need to wait for binded connection termination at logoff
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (143 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 144/154] ksmbd: add support for surrogate pair conversion Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 146/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_kern_path_locked() Namjae Jeon
` (9 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 67797da8a4b82446d42c52b6ee1419a3100d78ff ]
The connection could be binded to the existing session for Multichannel.
session will be destroyed when binded connections are released.
So no need to wait for that's connection at logoff.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/connection.c | 16 ----------------
1 file changed, 16 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 28b65a43fa39..0a7a30bd531f 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -167,23 +167,7 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
{
- struct ksmbd_conn *bind_conn;
-
wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
-
- down_read(&conn_list_lock);
- list_for_each_entry(bind_conn, &conn_list, conns_list) {
- if (bind_conn == conn)
- continue;
-
- if ((bind_conn->binding || xa_load(&bind_conn->sessions, sess_id)) &&
- !ksmbd_conn_releasing(bind_conn) &&
- atomic_read(&bind_conn->req_running)) {
- wait_event(bind_conn->req_running_q,
- atomic_read(&bind_conn->req_running) == 0);
- }
- }
- up_read(&conn_list_lock);
}
int ksmbd_conn_write(struct ksmbd_work *work)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 146/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_kern_path_locked()
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (144 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 145/154] ksmbd: no need to wait for binded connection termination at logoff Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 147/154] ksmbd: handle malformed smb1 message Namjae Jeon
` (8 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, kernel test robot, Steve French
[ Upstream commit f6049712e520287ad695e9d4f1572ab76807fa0c ]
Fix argument list that the kdoc format and script verified in
ksmbd_vfs_kern_path_locked().
fs/smb/server/vfs.c:1207: warning: Function parameter or member 'parent_path'
not described in 'ksmbd_vfs_kern_path_locked'
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/vfs.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index ffcc8f8f35bf..84571bacadef 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -1179,9 +1179,10 @@ 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
- * @name: file path that is relative to share
- * @flags: lookup flags
- * @path: if lookup succeed, return path info
+ * @name: file path that is relative to share
+ * @flags: lookup flags
+ * @parent_path: if lookup succeed, return parent_path info
+ * @path: if lookup succeed, return path info
* @caseless: caseless filename lookup
*
* Return: 0 on success, otherwise error
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 147/154] ksmbd: handle malformed smb1 message
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (145 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 146/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_kern_path_locked() Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 148/154] ksmbd: prevent memory leak on error return Namjae Jeon
` (7 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Robert Morris, Steve French
[ Upstream commit 5a5409d90bd05f87fe5623a749ccfbf3f7c7d400 ]
If set_smb1_rsp_status() is not implemented, It will cause NULL pointer
dereferece error when client send malformed smb1 message.
This patch add set_smb1_rsp_status() to ignore malformed smb1 message.
Cc: stable@vger.kernel.org
Reported-by: Robert Morris <rtm@csail.mit.edu>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb_common.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index 894bf71218b6..d160363c09eb 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -366,11 +366,22 @@ static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
return 0;
}
+/**
+ * set_smb1_rsp_status() - set error type in smb response header
+ * @work: smb work containing smb response header
+ * @err: error code to set in response
+ */
+static void set_smb1_rsp_status(struct ksmbd_work *work, __le32 err)
+{
+ work->send_no_response = 1;
+}
+
static struct smb_version_ops smb1_server_ops = {
.get_cmd_val = get_smb1_cmd_val,
.init_rsp_hdr = init_smb1_rsp_hdr,
.allocate_rsp_buf = smb1_allocate_rsp_buf,
.check_user_session = smb1_check_user_session,
+ .set_rsp_status = set_smb1_rsp_status,
};
static int smb1_negotiate(struct ksmbd_work *work)
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 148/154] ksmbd: prevent memory leak on error return
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (146 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 147/154] ksmbd: handle malformed smb1 message Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 149/154] ksmbd: fix possible deadlock in smb2_open Namjae Jeon
` (6 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable
Cc: smfrench, Zongmin Zhou, kernel test robot, Dan Carpenter,
Namjae Jeon, Steve French
From: Zongmin Zhou <zhouzongmin@kylinos.cn>
[ Upstream commit 90044481e7cca6cb3125b3906544954a25f1309f ]
When allocated memory for 'new' failed,just return
will cause memory leak of 'ar'.
Fixes: 1819a9042999 ("ksmbd: reorganize ksmbd_iov_pin_rsp()")
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <error27@gmail.com>
Closes: https://lore.kernel.org/r/202311031837.H3yo7JVl-lkp@intel.com/
Signed-off-by: Zongmin Zhou<zhouzongmin@kylinos.cn>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_work.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
index a2ed441e837a..2510b9f3c8c1 100644
--- a/fs/ksmbd/ksmbd_work.c
+++ b/fs/ksmbd/ksmbd_work.c
@@ -106,7 +106,7 @@ static inline void __ksmbd_iov_pin(struct ksmbd_work *work, void *ib,
static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
void *aux_buf, unsigned int aux_size)
{
- struct aux_read *ar;
+ struct aux_read *ar = NULL;
int need_iov_cnt = 1;
if (aux_size) {
@@ -123,8 +123,11 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
new = krealloc(work->iov,
sizeof(struct kvec) * work->iov_alloc_cnt,
GFP_KERNEL | __GFP_ZERO);
- if (!new)
+ if (!new) {
+ kfree(ar);
+ work->iov_alloc_cnt -= 4;
return -ENOMEM;
+ }
work->iov = new;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 149/154] ksmbd: fix possible deadlock in smb2_open
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (147 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 148/154] ksmbd: prevent memory leak on error return Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 150/154] ksmbd: separately allocate ci per dentry Namjae Jeon
` (5 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Marios Makassikis, Steve French
[ Upstream commit 864fb5d3716303a045c3ffb397f651bfd37bfb36 ]
[ 8743.393379] ======================================================
[ 8743.393385] WARNING: possible circular locking dependency detected
[ 8743.393391] 6.4.0-rc1+ #11 Tainted: G OE
[ 8743.393397] ------------------------------------------------------
[ 8743.393402] kworker/0:2/12921 is trying to acquire lock:
[ 8743.393408] ffff888127a14460 (sb_writers#8){.+.+}-{0:0}, at: ksmbd_vfs_setxattr+0x3d/0xd0 [ksmbd]
[ 8743.393510]
but task is already holding lock:
[ 8743.393515] ffff8880360d97f0 (&type->i_mutex_dir_key#6/1){+.+.}-{3:3}, at: ksmbd_vfs_kern_path_locked+0x181/0x670 [ksmbd]
[ 8743.393618]
which lock already depends on the new lock.
[ 8743.393623]
the existing dependency chain (in reverse order) is:
[ 8743.393628]
-> #1 (&type->i_mutex_dir_key#6/1){+.+.}-{3:3}:
[ 8743.393648] down_write_nested+0x9a/0x1b0
[ 8743.393660] filename_create+0x128/0x270
[ 8743.393670] do_mkdirat+0xab/0x1f0
[ 8743.393680] __x64_sys_mkdir+0x47/0x60
[ 8743.393690] do_syscall_64+0x5d/0x90
[ 8743.393701] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[ 8743.393711]
-> #0 (sb_writers#8){.+.+}-{0:0}:
[ 8743.393728] __lock_acquire+0x2201/0x3b80
[ 8743.393737] lock_acquire+0x18f/0x440
[ 8743.393746] mnt_want_write+0x5f/0x240
[ 8743.393755] ksmbd_vfs_setxattr+0x3d/0xd0 [ksmbd]
[ 8743.393839] ksmbd_vfs_set_dos_attrib_xattr+0xcc/0x110 [ksmbd]
[ 8743.393924] compat_ksmbd_vfs_set_dos_attrib_xattr+0x39/0x50 [ksmbd]
[ 8743.394010] smb2_open+0x3432/0x3cc0 [ksmbd]
[ 8743.394099] handle_ksmbd_work+0x2c9/0x7b0 [ksmbd]
[ 8743.394187] process_one_work+0x65a/0xb30
[ 8743.394198] worker_thread+0x2cf/0x700
[ 8743.394209] kthread+0x1ad/0x1f0
[ 8743.394218] ret_from_fork+0x29/0x50
This patch add mnt_want_write() above parent inode lock and remove
nested mnt_want_write calls in smb2_open().
Fixes: 40b268d384a2 ("ksmbd: add mnt_want_write to ksmbd vfs functions")
Cc: stable@vger.kernel.org
Reported-by: Marios Makassikis <mmakassikis@freebox.fr>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 47 +++++++++++++++-----------------
fs/ksmbd/smbacl.c | 7 +++--
fs/ksmbd/smbacl.h | 2 +-
fs/ksmbd/vfs.c | 68 ++++++++++++++++++++++++++++------------------
fs/ksmbd/vfs.h | 10 +++++--
5 files changed, 75 insertions(+), 59 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 8dad33251925..b0fc55bfe920 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2380,7 +2380,8 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
rc = 0;
} else {
rc = ksmbd_vfs_setxattr(user_ns, path, attr_name, value,
- le16_to_cpu(eabuf->EaValueLength), 0);
+ le16_to_cpu(eabuf->EaValueLength),
+ 0, true);
if (rc < 0) {
ksmbd_debug(SMB,
"ksmbd_vfs_setxattr is failed(%d)\n",
@@ -2443,7 +2444,7 @@ static noinline int smb2_set_stream_name_xattr(const struct path *path,
return -EBADF;
}
- rc = ksmbd_vfs_setxattr(user_ns, path, xattr_stream_name, NULL, 0, 0);
+ rc = ksmbd_vfs_setxattr(user_ns, path, xattr_stream_name, NULL, 0, 0, false);
if (rc < 0)
pr_err("Failed to store XATTR stream name :%d\n", rc);
return 0;
@@ -2518,7 +2519,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt), path, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt), path, &da, false);
if (rc)
ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
}
@@ -2608,7 +2609,7 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
sizeof(struct create_sd_buf_req))
return -EINVAL;
return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd,
- le32_to_cpu(sd_buf->ccontext.DataLength), true);
+ le32_to_cpu(sd_buf->ccontext.DataLength), true, false);
}
static void ksmbd_acls_fattr(struct smb_fattr *fattr,
@@ -3149,7 +3150,8 @@ int smb2_open(struct ksmbd_work *work)
user_ns,
&path,
pntsd,
- pntsd_size);
+ pntsd_size,
+ false);
kfree(pntsd);
if (rc)
pr_err("failed to store ntacl in xattr : %d\n",
@@ -3225,12 +3227,6 @@ int smb2_open(struct ksmbd_work *work)
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
ksmbd_fd_set_delete_on_close(fp, file_info);
- if (need_truncate) {
- rc = smb2_create_truncate(&path);
- if (rc)
- goto err_out;
- }
-
if (req->CreateContextsOffset) {
struct create_alloc_size_req *az_req;
@@ -3395,11 +3391,12 @@ int smb2_open(struct ksmbd_work *work)
}
err_out:
- if (file_present || created) {
- inode_unlock(d_inode(parent_path.dentry));
- path_put(&path);
- path_put(&parent_path);
- }
+ if (file_present || created)
+ ksmbd_vfs_kern_path_unlock(&parent_path, &path);
+
+ if (fp && need_truncate)
+ rc = smb2_create_truncate(&fp->filp->f_path);
+
ksmbd_revert_fsids(work);
err_out1:
if (!rc) {
@@ -5537,7 +5534,7 @@ static int smb2_rename(struct ksmbd_work *work,
rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp),
&fp->filp->f_path,
xattr_stream_name,
- NULL, 0, 0);
+ NULL, 0, 0, true);
if (rc < 0) {
pr_err("failed to store stream name in xattr: %d\n",
rc);
@@ -5630,11 +5627,9 @@ static int smb2_create_link(struct ksmbd_work *work,
if (rc)
rc = -EINVAL;
out:
- if (file_present) {
- inode_unlock(d_inode(parent_path.dentry));
- path_put(&path);
- path_put(&parent_path);
- }
+ if (file_present)
+ ksmbd_vfs_kern_path_unlock(&parent_path, &path);
+
if (!IS_ERR(link_name))
kfree(link_name);
kfree(pathname);
@@ -5701,7 +5696,8 @@ static int set_file_basic_info(struct ksmbd_file *fp,
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(user_ns, &filp->f_path, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(user_ns, &filp->f_path, &da,
+ true);
if (rc)
ksmbd_debug(SMB,
"failed to restore file attribute in EA\n");
@@ -6015,7 +6011,7 @@ static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
fp->saccess |= FILE_SHARE_DELETE_LE;
return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd,
- buf_len, false);
+ buf_len, false, true);
}
/**
@@ -7584,7 +7580,8 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
da.attr = le32_to_cpu(fp->f_ci->m_fattr);
ret = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
- &fp->filp->f_path, &da);
+ &fp->filp->f_path,
+ &da, true);
if (ret)
fp->f_ci->m_fattr = old_fattr;
}
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index d7fd5a15dac4..9ace5027684d 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -1183,7 +1183,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
pntsd_size += sizeof(struct smb_acl) + nt_size;
}
- ksmbd_vfs_set_sd_xattr(conn, user_ns, path, pntsd, pntsd_size);
+ ksmbd_vfs_set_sd_xattr(conn, user_ns, path, pntsd, pntsd_size, false);
kfree(pntsd);
}
@@ -1375,7 +1375,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
- bool type_check)
+ bool type_check, bool get_write)
{
int rc;
struct smb_fattr fattr = {{0}};
@@ -1435,7 +1435,8 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
/* Update WinACL in xattr */
ksmbd_vfs_remove_sd_xattrs(user_ns, path);
- ksmbd_vfs_set_sd_xattr(conn, user_ns, path, pntsd, ntsd_len);
+ ksmbd_vfs_set_sd_xattr(conn, user_ns, path, pntsd, ntsd_len,
+ get_write);
}
out:
diff --git a/fs/ksmbd/smbacl.h b/fs/ksmbd/smbacl.h
index f06abf247445..17f81a510f23 100644
--- a/fs/ksmbd/smbacl.h
+++ b/fs/ksmbd/smbacl.h
@@ -207,7 +207,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
__le32 *pdaccess, int uid);
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
- bool type_check);
+ bool type_check, bool get_write);
void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
void ksmbd_init_domain(u32 *sub_auth);
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 84571bacadef..99fd29761bca 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -97,6 +97,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
return -ENOENT;
}
+ err = mnt_want_write(parent_path->mnt);
+ if (err) {
+ path_put(parent_path);
+ putname(filename);
+ return -ENOENT;
+ }
+
inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT);
d = lookup_one_qstr_excl(&last, parent_path->dentry, 0);
if (IS_ERR(d))
@@ -123,6 +130,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
err_out:
inode_unlock(d_inode(parent_path->dentry));
+ mnt_drop_write(parent_path->mnt);
path_put(parent_path);
putname(filename);
return -ENOENT;
@@ -451,7 +459,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
fp->stream.name,
(void *)stream_buf,
size,
- 0);
+ 0,
+ true);
if (err < 0)
goto out;
@@ -593,10 +602,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
goto out_err;
}
- err = mnt_want_write(path->mnt);
- if (err)
- goto out_err;
-
user_ns = mnt_user_ns(path->mnt);
if (S_ISDIR(d_inode(path->dentry)->i_mode)) {
err = vfs_rmdir(user_ns, d_inode(parent), path->dentry);
@@ -607,7 +612,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
if (err)
ksmbd_debug(VFS, "unlink failed, err %d\n", err);
}
- mnt_drop_write(path->mnt);
out_err:
ksmbd_revert_fsids(work);
@@ -907,18 +911,22 @@ ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
* @attr_value: xattr value to set
* @attr_size: size of xattr value
* @flags: destination buffer length
+ * @get_write: get write access to a mount
*
* Return: 0 on success, otherwise error
*/
int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
const struct path *path, const char *attr_name,
- const void *attr_value, size_t attr_size, int flags)
+ const void *attr_value, size_t attr_size, int flags,
+ bool get_write)
{
int err;
- err = mnt_want_write(path->mnt);
- if (err)
- return err;
+ if (get_write == true) {
+ err = mnt_want_write(path->mnt);
+ if (err)
+ return err;
+ }
err = vfs_setxattr(user_ns,
path->dentry,
@@ -928,7 +936,8 @@ int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
flags);
if (err)
ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
- mnt_drop_write(path->mnt);
+ if (get_write == true)
+ mnt_drop_write(path->mnt);
return err;
}
@@ -1254,6 +1263,13 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
}
if (!err) {
+ err = mnt_want_write(parent_path->mnt);
+ if (err) {
+ path_put(path);
+ path_put(parent_path);
+ return err;
+ }
+
err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
if (err) {
path_put(path);
@@ -1263,6 +1279,14 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
return err;
}
+void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path)
+{
+ inode_unlock(d_inode(parent_path->dentry));
+ mnt_drop_write(parent_path->mnt);
+ path_put(path);
+ path_put(parent_path);
+}
+
struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
const char *name,
unsigned int flags,
@@ -1412,7 +1436,8 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
struct user_namespace *user_ns,
const struct path *path,
- struct smb_ntsd *pntsd, int len)
+ struct smb_ntsd *pntsd, int len,
+ bool get_write)
{
int rc;
struct ndr sd_ndr = {0}, acl_ndr = {0};
@@ -1472,7 +1497,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
rc = ksmbd_vfs_setxattr(user_ns, path,
XATTR_NAME_SD, sd_ndr.data,
- sd_ndr.offset, 0);
+ sd_ndr.offset, 0, get_write);
if (rc < 0)
pr_err("Failed to store XATTR ntacl :%d\n", rc);
@@ -1561,7 +1586,8 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
const struct path *path,
- struct xattr_dos_attrib *da)
+ struct xattr_dos_attrib *da,
+ bool get_write)
{
struct ndr n;
int err;
@@ -1571,7 +1597,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
return err;
err = ksmbd_vfs_setxattr(user_ns, path, XATTR_NAME_DOS_ATTRIBUTE,
- (void *)n.data, n.offset, 0);
+ (void *)n.data, n.offset, 0, get_write);
if (err)
ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
kfree(n.data);
@@ -1841,10 +1867,6 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
}
posix_state_to_acl(&acl_state, acls->a_entries);
- rc = mnt_want_write(path->mnt);
- if (rc)
- goto out_err;
-
rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1857,9 +1879,7 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
}
- mnt_drop_write(path->mnt);
-out_err:
free_acl_state(&acl_state);
posix_acl_release(acls);
return rc;
@@ -1888,10 +1908,6 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
}
}
- rc = mnt_want_write(path->mnt);
- if (rc)
- goto out_err;
-
rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1903,9 +1919,7 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
}
- mnt_drop_write(path->mnt);
-out_err:
posix_acl_release(acls);
return rc;
}
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index 97804cb97f27..6d108cba7e0c 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -148,7 +148,8 @@ ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
int attr_name_len);
int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
const struct path *path, const char *attr_name,
- const void *attr_value, size_t attr_size, int flags);
+ const void *attr_value, size_t attr_size, int flags,
+ bool get_write);
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
size_t *xattr_stream_name_size, int s_type);
int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
@@ -156,6 +157,7 @@ int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
unsigned int flags, struct path *parent_path,
struct path *path, bool caseless);
+void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path);
struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
const char *name,
unsigned int flags,
@@ -183,14 +185,16 @@ int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns, const struct path
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
struct user_namespace *user_ns,
const struct path *path,
- struct smb_ntsd *pntsd, int len);
+ struct smb_ntsd *pntsd, int len,
+ bool get_write);
int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
struct user_namespace *user_ns,
struct dentry *dentry,
struct smb_ntsd **pntsd);
int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
const struct path *path,
- struct xattr_dos_attrib *da);
+ struct xattr_dos_attrib *da,
+ bool get_write);
int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
struct dentry *dentry,
struct xattr_dos_attrib *da);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 150/154] ksmbd: separately allocate ci per dentry
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (148 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 149/154] ksmbd: fix possible deadlock in smb2_open Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 151/154] ksmbd: move oplock handling after unlock parent dir Namjae Jeon
` (4 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 4274a9dc6aeb9fea66bffba15697a35ae8983b6a ]
xfstests generic/002 test fail when enabling smb2 leases feature.
This test create hard link file, but removeal failed.
ci has a file open count to count file open through the smb client,
but in the case of hard link files, The allocation of ci per inode
cause incorrectly open count for file deletion. This patch allocate
ci per dentry to counts open counts for hard link.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 2 +-
fs/ksmbd/vfs.c | 2 +-
fs/ksmbd/vfs_cache.c | 33 +++++++++++++--------------------
fs/ksmbd/vfs_cache.h | 6 +++---
4 files changed, 18 insertions(+), 25 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index b0fc55bfe920..f0708feedf37 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -3036,7 +3036,7 @@ int smb2_open(struct ksmbd_work *work)
}
}
- rc = ksmbd_query_inode_status(d_inode(path.dentry->d_parent));
+ rc = ksmbd_query_inode_status(path.dentry->d_parent);
if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) {
rc = -EBUSY;
goto err_out;
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 99fd29761bca..a89529b21c86 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -719,7 +719,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
goto out3;
}
- parent_fp = ksmbd_lookup_fd_inode(d_inode(old_child->d_parent));
+ parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent);
if (parent_fp) {
if (parent_fp->daccess & FILE_DELETE_LE) {
pr_err("parent dir is opened with delete access\n");
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index 38f414e803ad..774a387fccce 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -65,14 +65,14 @@ static unsigned long inode_hash(struct super_block *sb, unsigned long hashval)
return tmp & inode_hash_mask;
}
-static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode)
+static struct ksmbd_inode *__ksmbd_inode_lookup(struct dentry *de)
{
struct hlist_head *head = inode_hashtable +
- inode_hash(inode->i_sb, inode->i_ino);
+ inode_hash(d_inode(de)->i_sb, (unsigned long)de);
struct ksmbd_inode *ci = NULL, *ret_ci = NULL;
hlist_for_each_entry(ci, head, m_hash) {
- if (ci->m_inode == inode) {
+ if (ci->m_de == de) {
if (atomic_inc_not_zero(&ci->m_count))
ret_ci = ci;
break;
@@ -83,26 +83,16 @@ static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode)
static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp)
{
- return __ksmbd_inode_lookup(file_inode(fp->filp));
+ return __ksmbd_inode_lookup(fp->filp->f_path.dentry);
}
-static struct ksmbd_inode *ksmbd_inode_lookup_by_vfsinode(struct inode *inode)
-{
- struct ksmbd_inode *ci;
-
- read_lock(&inode_hash_lock);
- ci = __ksmbd_inode_lookup(inode);
- read_unlock(&inode_hash_lock);
- return ci;
-}
-
-int ksmbd_query_inode_status(struct inode *inode)
+int ksmbd_query_inode_status(struct dentry *dentry)
{
struct ksmbd_inode *ci;
int ret = KSMBD_INODE_STATUS_UNKNOWN;
read_lock(&inode_hash_lock);
- ci = __ksmbd_inode_lookup(inode);
+ ci = __ksmbd_inode_lookup(dentry);
if (ci) {
ret = KSMBD_INODE_STATUS_OK;
if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS))
@@ -142,7 +132,7 @@ void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
static void ksmbd_inode_hash(struct ksmbd_inode *ci)
{
struct hlist_head *b = inode_hashtable +
- inode_hash(ci->m_inode->i_sb, ci->m_inode->i_ino);
+ inode_hash(d_inode(ci->m_de)->i_sb, (unsigned long)ci->m_de);
hlist_add_head(&ci->m_hash, b);
}
@@ -156,7 +146,6 @@ static void ksmbd_inode_unhash(struct ksmbd_inode *ci)
static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
{
- ci->m_inode = file_inode(fp->filp);
atomic_set(&ci->m_count, 1);
atomic_set(&ci->op_count, 0);
atomic_set(&ci->sop_count, 0);
@@ -165,6 +154,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
INIT_LIST_HEAD(&ci->m_fp_list);
INIT_LIST_HEAD(&ci->m_op_list);
rwlock_init(&ci->m_lock);
+ ci->m_de = fp->filp->f_path.dentry;
return 0;
}
@@ -487,12 +477,15 @@ struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid)
return fp;
}
-struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
+struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry)
{
struct ksmbd_file *lfp;
struct ksmbd_inode *ci;
+ struct inode *inode = d_inode(dentry);
- ci = ksmbd_inode_lookup_by_vfsinode(inode);
+ read_lock(&inode_hash_lock);
+ ci = __ksmbd_inode_lookup(dentry);
+ read_unlock(&inode_hash_lock);
if (!ci)
return NULL;
diff --git a/fs/ksmbd/vfs_cache.h b/fs/ksmbd/vfs_cache.h
index 03d0bf941216..8325cf4527c4 100644
--- a/fs/ksmbd/vfs_cache.h
+++ b/fs/ksmbd/vfs_cache.h
@@ -51,7 +51,7 @@ struct ksmbd_inode {
atomic_t op_count;
/* opinfo count for streams */
atomic_t sop_count;
- struct inode *m_inode;
+ struct dentry *m_de;
unsigned int m_flags;
struct hlist_node m_hash;
struct list_head m_fp_list;
@@ -140,7 +140,7 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp);
struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id);
struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
-struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode);
+struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry);
unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp);
void ksmbd_close_tree_conn_fds(struct ksmbd_work *work);
@@ -164,7 +164,7 @@ enum KSMBD_INODE_STATUS {
KSMBD_INODE_STATUS_PENDING_DELETE,
};
-int ksmbd_query_inode_status(struct inode *inode);
+int ksmbd_query_inode_status(struct dentry *dentry);
bool ksmbd_inode_pending_delete(struct ksmbd_file *fp);
void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 151/154] ksmbd: move oplock handling after unlock parent dir
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (149 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 150/154] ksmbd: separately allocate ci per dentry Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 152/154] ksmbd: release interim response after sending status pending response Namjae Jeon
` (3 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 2e450920d58b4991a436c8cecf3484bcacd8e535 ]
ksmbd should process secound parallel smb2 create request during waiting
oplock break ack. parent lock range that is too large in smb2_open() causes
smb2_open() to be serialized. Move the oplock handling to the bottom of
smb2_open() and make it called after parent unlock. This fixes the failure
of smb2.lease.breaking1 testcase.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 121 ++++++++++++++++++++++++---------------------
1 file changed, 65 insertions(+), 56 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index f0708feedf37..73eb3ea6441b 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -2688,7 +2688,7 @@ int smb2_open(struct ksmbd_work *work)
*(char *)req->Buffer == '\\') {
pr_err("not allow directory name included leading slash\n");
rc = -EINVAL;
- goto err_out1;
+ goto err_out2;
}
name = smb2_get_name(req->Buffer,
@@ -2699,7 +2699,7 @@ int smb2_open(struct ksmbd_work *work)
if (rc != -ENOMEM)
rc = -ENOENT;
name = NULL;
- goto err_out1;
+ goto err_out2;
}
ksmbd_debug(SMB, "converted name = %s\n", name);
@@ -2707,28 +2707,28 @@ int smb2_open(struct ksmbd_work *work)
if (!test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_STREAMS)) {
rc = -EBADF;
- goto err_out1;
+ goto err_out2;
}
rc = parse_stream_name(name, &stream_name, &s_type);
if (rc < 0)
- goto err_out1;
+ goto err_out2;
}
rc = ksmbd_validate_filename(name);
if (rc < 0)
- goto err_out1;
+ goto err_out2;
if (ksmbd_share_veto_filename(share, name)) {
rc = -ENOENT;
ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n",
name);
- goto err_out1;
+ goto err_out2;
}
} else {
name = kstrdup("", GFP_KERNEL);
if (!name) {
rc = -ENOMEM;
- goto err_out1;
+ goto err_out2;
}
}
@@ -2741,14 +2741,14 @@ int smb2_open(struct ksmbd_work *work)
le32_to_cpu(req->ImpersonationLevel));
rc = -EIO;
rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL;
- goto err_out1;
+ goto err_out2;
}
if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK)) {
pr_err("Invalid create options : 0x%x\n",
le32_to_cpu(req->CreateOptions));
rc = -EINVAL;
- goto err_out1;
+ goto err_out2;
} else {
if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE &&
req->CreateOptions & FILE_RANDOM_ACCESS_LE)
@@ -2758,13 +2758,13 @@ int smb2_open(struct ksmbd_work *work)
(FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION |
FILE_RESERVE_OPFILTER_LE)) {
rc = -EOPNOTSUPP;
- goto err_out1;
+ goto err_out2;
}
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) {
rc = -EINVAL;
- goto err_out1;
+ goto err_out2;
} else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) {
req->CreateOptions = ~(FILE_NO_COMPRESSION_LE);
}
@@ -2776,21 +2776,21 @@ int smb2_open(struct ksmbd_work *work)
pr_err("Invalid create disposition : 0x%x\n",
le32_to_cpu(req->CreateDisposition));
rc = -EINVAL;
- goto err_out1;
+ goto err_out2;
}
if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) {
pr_err("Invalid desired access : 0x%x\n",
le32_to_cpu(req->DesiredAccess));
rc = -EACCES;
- goto err_out1;
+ goto err_out2;
}
if (req->FileAttributes && !(req->FileAttributes & ATTR_MASK_LE)) {
pr_err("Invalid file attribute : 0x%x\n",
le32_to_cpu(req->FileAttributes));
rc = -EINVAL;
- goto err_out1;
+ goto err_out2;
}
if (req->CreateContextsOffset) {
@@ -2798,19 +2798,19 @@ int smb2_open(struct ksmbd_work *work)
context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4);
if (IS_ERR(context)) {
rc = PTR_ERR(context);
- goto err_out1;
+ goto err_out2;
} else if (context) {
ea_buf = (struct create_ea_buf_req *)context;
if (le16_to_cpu(context->DataOffset) +
le32_to_cpu(context->DataLength) <
sizeof(struct create_ea_buf_req)) {
rc = -EINVAL;
- goto err_out1;
+ goto err_out2;
}
if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) {
rsp->hdr.Status = STATUS_ACCESS_DENIED;
rc = -EACCES;
- goto err_out1;
+ goto err_out2;
}
}
@@ -2818,7 +2818,7 @@ int smb2_open(struct ksmbd_work *work)
SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4);
if (IS_ERR(context)) {
rc = PTR_ERR(context);
- goto err_out1;
+ goto err_out2;
} else if (context) {
ksmbd_debug(SMB,
"get query maximal access context\n");
@@ -2829,11 +2829,11 @@ int smb2_open(struct ksmbd_work *work)
SMB2_CREATE_TIMEWARP_REQUEST, 4);
if (IS_ERR(context)) {
rc = PTR_ERR(context);
- goto err_out1;
+ goto err_out2;
} else if (context) {
ksmbd_debug(SMB, "get timewarp context\n");
rc = -EBADF;
- goto err_out1;
+ goto err_out2;
}
if (tcon->posix_extensions) {
@@ -2841,7 +2841,7 @@ int smb2_open(struct ksmbd_work *work)
SMB2_CREATE_TAG_POSIX, 16);
if (IS_ERR(context)) {
rc = PTR_ERR(context);
- goto err_out1;
+ goto err_out2;
} else if (context) {
struct create_posix *posix =
(struct create_posix *)context;
@@ -2849,7 +2849,7 @@ int smb2_open(struct ksmbd_work *work)
le32_to_cpu(context->DataLength) <
sizeof(struct create_posix) - 4) {
rc = -EINVAL;
- goto err_out1;
+ goto err_out2;
}
ksmbd_debug(SMB, "get posix context\n");
@@ -2861,7 +2861,7 @@ int smb2_open(struct ksmbd_work *work)
if (ksmbd_override_fsids(work)) {
rc = -ENOMEM;
- goto err_out1;
+ goto err_out2;
}
rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS,
@@ -3174,11 +3174,6 @@ int smb2_open(struct ksmbd_work *work)
fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE |
FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE));
- if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
- !fp->attrib_only && !stream_name) {
- smb_break_all_oplock(work, fp);
- need_truncate = 1;
- }
/* fp should be searchable through ksmbd_inode.m_fp_list
* after daccess, saccess, attrib_only, and stream are
@@ -3194,13 +3189,39 @@ int smb2_open(struct ksmbd_work *work)
goto err_out;
}
+ rc = ksmbd_vfs_getattr(&path, &stat);
+ if (rc)
+ goto err_out;
+
+ if (stat.result_mask & STATX_BTIME)
+ fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
+ else
+ fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
+ if (req->FileAttributes || fp->f_ci->m_fattr == 0)
+ fp->f_ci->m_fattr =
+ cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
+
+ if (!created)
+ smb2_update_xattrs(tcon, &path, fp);
+ else
+ smb2_new_xattrs(tcon, &path, fp);
+
+ if (file_present || created)
+ ksmbd_vfs_kern_path_unlock(&parent_path, &path);
+
+ if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
+ !fp->attrib_only && !stream_name) {
+ smb_break_all_oplock(work, fp);
+ need_truncate = 1;
+ }
+
share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
(req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
!(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) {
if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
rc = share_ret;
- goto err_out;
+ goto err_out1;
}
} else {
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
@@ -3210,7 +3231,7 @@ int smb2_open(struct ksmbd_work *work)
name, req_op_level, lc->req_state);
rc = find_same_lease_key(sess, fp->f_ci, lc);
if (rc)
- goto err_out;
+ goto err_out1;
} else if (open_flags == O_RDONLY &&
(req_op_level == SMB2_OPLOCK_LEVEL_BATCH ||
req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
@@ -3221,12 +3242,18 @@ int smb2_open(struct ksmbd_work *work)
le32_to_cpu(req->hdr.Id.SyncId.TreeId),
lc, share_ret);
if (rc < 0)
- goto err_out;
+ goto err_out1;
}
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
ksmbd_fd_set_delete_on_close(fp, file_info);
+ if (need_truncate) {
+ rc = smb2_create_truncate(&fp->filp->f_path);
+ if (rc)
+ goto err_out1;
+ }
+
if (req->CreateContextsOffset) {
struct create_alloc_size_req *az_req;
@@ -3234,7 +3261,7 @@ int smb2_open(struct ksmbd_work *work)
SMB2_CREATE_ALLOCATION_SIZE, 4);
if (IS_ERR(az_req)) {
rc = PTR_ERR(az_req);
- goto err_out;
+ goto err_out1;
} else if (az_req) {
loff_t alloc_size;
int err;
@@ -3243,7 +3270,7 @@ int smb2_open(struct ksmbd_work *work)
le32_to_cpu(az_req->ccontext.DataLength) <
sizeof(struct create_alloc_size_req)) {
rc = -EINVAL;
- goto err_out;
+ goto err_out1;
}
alloc_size = le64_to_cpu(az_req->AllocationSize);
ksmbd_debug(SMB,
@@ -3261,30 +3288,13 @@ int smb2_open(struct ksmbd_work *work)
context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
if (IS_ERR(context)) {
rc = PTR_ERR(context);
- goto err_out;
+ goto err_out1;
} else if (context) {
ksmbd_debug(SMB, "get query on disk id context\n");
query_disk_id = 1;
}
}
- rc = ksmbd_vfs_getattr(&path, &stat);
- if (rc)
- goto err_out;
-
- if (stat.result_mask & STATX_BTIME)
- fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
- else
- fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
- if (req->FileAttributes || fp->f_ci->m_fattr == 0)
- fp->f_ci->m_fattr =
- cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
-
- if (!created)
- smb2_update_xattrs(tcon, &path, fp);
- else
- smb2_new_xattrs(tcon, &path, fp);
-
memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
rsp->StructureSize = cpu_to_le16(89);
@@ -3391,14 +3401,13 @@ int smb2_open(struct ksmbd_work *work)
}
err_out:
- if (file_present || created)
+ if (rc && (file_present || created))
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
- if (fp && need_truncate)
- rc = smb2_create_truncate(&fp->filp->f_path);
-
- ksmbd_revert_fsids(work);
err_out1:
+ ksmbd_revert_fsids(work);
+
+err_out2:
if (!rc) {
ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED);
rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 152/154] ksmbd: release interim response after sending status pending response
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (150 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 151/154] ksmbd: move oplock handling after unlock parent dir Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 153/154] ksmbd: move setting SMB2_FLAGS_ASYNC_COMMAND and AsyncId Namjae Jeon
` (2 subsequent siblings)
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 2a3f7857ec742e212d6cee7fbbf7b0e2ae7f5161 ]
Add missing release async id and delete interim response entry after
sending status pending response. This only cause when smb2 lease is enable.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/ksmbd_work.c | 3 +++
fs/ksmbd/oplock.c | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
index 2510b9f3c8c1..d7c676c151e2 100644
--- a/fs/ksmbd/ksmbd_work.c
+++ b/fs/ksmbd/ksmbd_work.c
@@ -56,6 +56,9 @@ void ksmbd_free_work_struct(struct ksmbd_work *work)
kfree(work->tr_buf);
kvfree(work->request_buf);
kfree(work->iov);
+ if (!list_empty(&work->interim_entry))
+ list_del(&work->interim_entry);
+
if (work->async_id)
ksmbd_release_id(&work->conn->async_ida, work->async_id);
kmem_cache_free(work_cache, work);
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
index 13185c74b912..1cf2d2a3746a 100644
--- a/fs/ksmbd/oplock.c
+++ b/fs/ksmbd/oplock.c
@@ -833,7 +833,8 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
interim_entry);
setup_async_work(in_work, NULL, NULL);
smb2_send_interim_resp(in_work, STATUS_PENDING);
- list_del(&in_work->interim_entry);
+ list_del_init(&in_work->interim_entry);
+ release_async_work(in_work);
}
INIT_WORK(&work->work, __smb2_lease_break_noti);
ksmbd_queue_work(work);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 153/154] ksmbd: move setting SMB2_FLAGS_ASYNC_COMMAND and AsyncId
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (151 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 152/154] ksmbd: release interim response after sending status pending response Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 154/154] ksmbd: don't update ->op_state as OPLOCK_STATE_NONE on error Namjae Jeon
2023-12-20 14:41 ` [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Greg KH
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit 9ac45ac7cf65b0623ceeab9b28b307a08efa22dc ]
Directly set SMB2_FLAGS_ASYNC_COMMAND flags and AsyncId in smb2 header of
interim response instead of current response header.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 73eb3ea6441b..2b990ed35fde 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -658,13 +658,9 @@ smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
{
- struct smb2_hdr *rsp_hdr;
struct ksmbd_conn *conn = work->conn;
int id;
- rsp_hdr = ksmbd_resp_buf_next(work);
- rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
-
id = ksmbd_acquire_async_msg_id(&conn->async_ida);
if (id < 0) {
pr_err("Failed to alloc async message id\n");
@@ -672,7 +668,6 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
}
work->asynchronous = true;
work->async_id = id;
- rsp_hdr->Id.AsyncId = cpu_to_le64(id);
ksmbd_debug(SMB,
"Send interim Response to inform async request id : %d\n",
@@ -724,6 +719,8 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
__SMB2_HEADER_STRUCTURE_SIZE);
rsp_hdr = smb2_get_msg(in_work->response_buf);
+ rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
+ rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id);
smb2_set_err_rsp(in_work);
rsp_hdr->Status = status;
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* [PATCH 5.15.y 154/154] ksmbd: don't update ->op_state as OPLOCK_STATE_NONE on error
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (152 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 153/154] ksmbd: move setting SMB2_FLAGS_ASYNC_COMMAND and AsyncId Namjae Jeon
@ 2023-12-18 15:34 ` Namjae Jeon
2023-12-20 14:41 ` [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Greg KH
154 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 15:34 UTC (permalink / raw)
To: gregkh, stable; +Cc: smfrench, Namjae Jeon, Steve French
[ Upstream commit cd80ce7e68f1624ac29cd0a6b057789d1236641e ]
ksmbd set ->op_state as OPLOCK_STATE_NONE on lease break ack error.
op_state of lease should not be updated because client can send lease
break ack again. This patch fix smb2.lease.breaking2 test failure.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/ksmbd/smb2pdu.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 2b990ed35fde..6db18a109022 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -8236,7 +8236,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
return;
err_out:
- opinfo->op_state = OPLOCK_STATE_NONE;
wake_up_interruptible_all(&opinfo->oplock_q);
atomic_dec(&opinfo->breaking_cnt);
wake_up_interruptible_all(&opinfo->oplock_brk);
--
2.25.1
^ permalink raw reply related [flat|nested] 158+ messages in thread
* Re: [PATCH 5.15.y 003/154] ksmbd: Remove redundant 'flush_workqueue()' calls
2023-12-18 15:32 ` [PATCH 5.15.y 003/154] ksmbd: Remove redundant 'flush_workqueue()' calls Namjae Jeon
@ 2023-12-18 17:56 ` Christophe JAILLET
2023-12-18 20:31 ` Namjae Jeon
0 siblings, 1 reply; 158+ messages in thread
From: Christophe JAILLET @ 2023-12-18 17:56 UTC (permalink / raw)
To: Namjae Jeon, gregkh, stable; +Cc: smfrench, Steve French
Hi,
unless explicitly needed because of other patches that rely on it,
patches 03, 28 and 42 / 154 don't look as good candidate for backport.
CJ
Le 18/12/2023 à 16:32, Namjae Jeon a écrit :
> From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>
> [ Upstream commit e8d585b2f68c0b10c966ee55146de043429085a3 ]
>
> 'destroy_workqueue()' already drains the queue before destroying it, so
> there is no need to flush it explicitly.
>
> Remove the redundant 'flush_workqueue()' calls.
>
> This was generated with coccinelle:
>
> @@
> expression E;
> @@
> - flush_workqueue(E);
> destroy_workqueue(E);
>
> Acked-by: Namjae Jeon <linkinjeon@kernel.org>
> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> Signed-off-by: Steve French <stfrench@microsoft.com>
> ---
> fs/ksmbd/ksmbd_work.c | 1 -
> fs/ksmbd/transport_rdma.c | 1 -
> 2 files changed, 2 deletions(-)
>
> diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
> index fd58eb4809f6..14b9caebf7a4 100644
> --- a/fs/ksmbd/ksmbd_work.c
> +++ b/fs/ksmbd/ksmbd_work.c
> @@ -69,7 +69,6 @@ int ksmbd_workqueue_init(void)
>
> void ksmbd_workqueue_destroy(void)
> {
> - flush_workqueue(ksmbd_wq);
> destroy_workqueue(ksmbd_wq);
> ksmbd_wq = NULL;
> }
> diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
> index 9ca29cdb7898..86446742f4ad 100644
> --- a/fs/ksmbd/transport_rdma.c
> +++ b/fs/ksmbd/transport_rdma.c
> @@ -2049,7 +2049,6 @@ int ksmbd_rdma_destroy(void)
> smb_direct_listener.cm_id = NULL;
>
> if (smb_direct_wq) {
> - flush_workqueue(smb_direct_wq);
> destroy_workqueue(smb_direct_wq);
> smb_direct_wq = NULL;
> }
^ permalink raw reply [flat|nested] 158+ messages in thread
* Re: [PATCH 5.15.y 003/154] ksmbd: Remove redundant 'flush_workqueue()' calls
2023-12-18 17:56 ` Christophe JAILLET
@ 2023-12-18 20:31 ` Namjae Jeon
0 siblings, 0 replies; 158+ messages in thread
From: Namjae Jeon @ 2023-12-18 20:31 UTC (permalink / raw)
To: Christophe JAILLET; +Cc: gregkh, stable, smfrench, Steve French
2023-12-19 2:56 GMT+09:00, Christophe JAILLET <christophe.jaillet@wanadoo.fr>:
> Hi,
Hi Christophe,
>
> unless explicitly needed because of other patches that rely on it,
> patches 03, 28 and 42 / 154 don't look as good candidate for backport.
Even if there is no problem now, a hunk failure may occur later when
the new change near these patches is applied. So I decided to apply
clean-up patches as well.
Thanks.
>
> CJ
>
>
> Le 18/12/2023 à 16:32, Namjae Jeon a écrit :
>> From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>>
>> [ Upstream commit e8d585b2f68c0b10c966ee55146de043429085a3 ]
>>
>> 'destroy_workqueue()' already drains the queue before destroying it, so
>> there is no need to flush it explicitly.
>>
>> Remove the redundant 'flush_workqueue()' calls.
>>
>> This was generated with coccinelle:
>>
>> @@
>> expression E;
>> @@
>> - flush_workqueue(E);
>> destroy_workqueue(E);
>>
>> Acked-by: Namjae Jeon <linkinjeon@kernel.org>
>> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>> Signed-off-by: Steve French <stfrench@microsoft.com>
>> ---
>> fs/ksmbd/ksmbd_work.c | 1 -
>> fs/ksmbd/transport_rdma.c | 1 -
>> 2 files changed, 2 deletions(-)
>>
>> diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
>> index fd58eb4809f6..14b9caebf7a4 100644
>> --- a/fs/ksmbd/ksmbd_work.c
>> +++ b/fs/ksmbd/ksmbd_work.c
>> @@ -69,7 +69,6 @@ int ksmbd_workqueue_init(void)
>>
>> void ksmbd_workqueue_destroy(void)
>> {
>> - flush_workqueue(ksmbd_wq);
>> destroy_workqueue(ksmbd_wq);
>> ksmbd_wq = NULL;
>> }
>> diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
>> index 9ca29cdb7898..86446742f4ad 100644
>> --- a/fs/ksmbd/transport_rdma.c
>> +++ b/fs/ksmbd/transport_rdma.c
>> @@ -2049,7 +2049,6 @@ int ksmbd_rdma_destroy(void)
>> smb_direct_listener.cm_id = NULL;
>>
>> if (smb_direct_wq) {
>> - flush_workqueue(smb_direct_wq);
>> destroy_workqueue(smb_direct_wq);
>> smb_direct_wq = NULL;
>> }
>
^ permalink raw reply [flat|nested] 158+ messages in thread
* Re: [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
` (153 preceding siblings ...)
2023-12-18 15:34 ` [PATCH 5.15.y 154/154] ksmbd: don't update ->op_state as OPLOCK_STATE_NONE on error Namjae Jeon
@ 2023-12-20 14:41 ` Greg KH
154 siblings, 0 replies; 158+ messages in thread
From: Greg KH @ 2023-12-20 14:41 UTC (permalink / raw)
To: Namjae Jeon; +Cc: stable, smfrench
On Tue, Dec 19, 2023 at 12:32:20AM +0900, Namjae Jeon wrote:
> This patchset backport ksmbd patches between 5.16 and 6.7-rc5 kernel.
> Bug fixes and CVE patches were not applied well due to clean-up and new
> feautre patches. To facilitate backport, This patch-set included
> clean-up patches and new feature patches of ksmbd for stable 5.15
> kernel.
All now queued up, thanks!
greg k-h
^ permalink raw reply [flat|nested] 158+ messages in thread
end of thread, other threads:[~2023-12-20 14:41 UTC | newest]
Thread overview: 158+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-18 15:32 [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 001/154] ksmbd: use ksmbd_req_buf_next() in ksmbd_verify_smb_message() Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 002/154] ksmdb: use cmd helper variable in smb2_get_ksmbd_tcon() Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 003/154] ksmbd: Remove redundant 'flush_workqueue()' calls Namjae Jeon
2023-12-18 17:56 ` Christophe JAILLET
2023-12-18 20:31 ` Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 004/154] ksmbd: remove md4 leftovers Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 005/154] ksmbd: remove smb2_buf_length in smb2_hdr Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 006/154] ksmbd: remove smb2_buf_length in smb2_transform_hdr Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 007/154] ksmbd: change LeaseKey data type to u8 array Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 008/154] ksmbd: use oid registry functions to decode OIDs Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 009/154] ksmbd: Remove unused parameter from smb2_get_name() Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 010/154] ksmbd: Remove unused fields from ksmbd_file struct definition Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 011/154] ksmbd: set both ipv4 and ipv6 in FSCTL_QUERY_NETWORK_INTERFACE_INFO Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 012/154] ksmbd: Fix buffer_check_err() kernel-doc comment Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 013/154] ksmbd: Fix smb2_set_info_file() " Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 014/154] ksmbd: Delete an invalid argument description in smb2_populate_readdir_entry() Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 015/154] ksmbd: Fix smb2_get_name() kernel-doc comment Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 016/154] ksmbd: register ksmbd ib client with ib_register_client() Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 017/154] ksmbd: set 445 port to smbdirect port by default Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 018/154] ksmbd: smbd: call rdma_accept() under CM handler Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 019/154] ksmbd: smbd: create MR pool Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 020/154] ksmbd: smbd: change the default maximum read/write, receive size Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 021/154] ksmbd: add smb-direct shutdown Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 022/154] ksmbd: smbd: fix missing client's memory region invalidation Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 023/154] ksmbd: smbd: validate buffer descriptor structures Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 024/154] ksmbd: add support for key exchange Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 025/154] ksmbd: use netif_is_bridge_port Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 026/154] ksmbd: store fids as opaque u64 integers Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 027/154] ksmbd: shorten experimental warning on loading the module Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 028/154] ksmbd: Remove a redundant zeroing of memory Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 029/154] ksmbd: replace usage of found with dedicated list iterator variable Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 030/154] smb3: fix ksmbd bigendian bug in oplock break, and move its struct to smbfs_common Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 031/154] ksmbd: remove filename in ksmbd_file Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 032/154] ksmbd: validate length in smb2_write() Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 033/154] ksmbd: smbd: change prototypes of RDMA read/write related functions Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 034/154] ksmbd: smbd: introduce read/write credits for RDMA read/write Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 035/154] ksmbd: smbd: simplify tracking pending packets Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 036/154] ksmbd: smbd: change the return value of get_sg_list Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 037/154] ksmbd: smbd: handle multiple Buffer descriptors Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 038/154] ksmbd: fix wrong smbd max read/write size check Namjae Jeon
2023-12-18 15:32 ` [PATCH 5.15.y 039/154] ksmbd: Fix some kernel-doc comments Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 040/154] ksmbd: smbd: fix connection dropped issue Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 041/154] ksmbd: smbd: relax the count of sges required Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 042/154] ksmbd: smbd: Remove useless license text when SPDX-License-Identifier is already used Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 043/154] ksmbd: remove duplicate flag set in smb2_write Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 044/154] ksmbd: remove unused ksmbd_share_configs_cleanup function Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 045/154] ksmbd: use wait_event instead of schedule_timeout() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 046/154] ksmbd: request update to stale share config Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 047/154] ksmbd: remove unnecessary generic_fillattr in smb2_open Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 048/154] ksmbd: don't open-code file_path() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 049/154] ksmbd: don't open-code %pD Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 050/154] ksmbd: constify struct path Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 051/154] ksmbd: remove generic_fillattr use in smb2_open() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 052/154] ksmbd: casefold utf-8 share names and fix ascii lowercase conversion Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 053/154] ksmbd: change security id to the one samba used for posix extension Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 054/154] ksmbd: set file permission mode to match Samba server posix extension behavior Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 055/154] ksmbd: fill sids in SMB_FIND_FILE_POSIX_INFO response Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 056/154] ksmbd: fix encryption failure issue for session logoff response Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 057/154] ksmbd: set NTLMSSP_NEGOTIATE_SEAL flag to challenge blob Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 058/154] ksmbd: decrease the number of SMB3 smbdirect server SGEs Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 059/154] ksmbd: reduce server smbdirect max send/receive segment sizes Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 060/154] ksmbd: hide socket error message when ipv6 config is disable Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 061/154] ksmbd: make utf-8 file name comparison work in __caseless_lookup() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 062/154] ksmbd: call ib_drain_qp when disconnected Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 063/154] ksmbd: validate share name from share config response Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 064/154] ksmbd: replace one-element arrays with flexible-array members Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 065/154] ksmbd: set SMB2_SESSION_FLAG_ENCRYPT_DATA when enforcing data encryption for this share Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 066/154] ksmbd: use F_SETLK when unlocking a file Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 067/154] ksmbd: Fix resource leak in smb2_lock() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 068/154] ksmbd: Convert to use sysfs_emit()/sysfs_emit_at() APIs Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 069/154] ksmbd: send proper error response in smb2_tree_connect() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 070/154] ksmbd: Implements sess->ksmbd_chann_list as xarray Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 071/154] ksmbd: Implements sess->rpc_handle_list " Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 072/154] ksmbd: fix typo, syncronous->synchronous Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 073/154] ksmbd: Remove duplicated codes Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 074/154] ksmbd: update Kconfig to note Kerberos support and fix indentation Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 075/154] ksmbd: Fix spelling mistake "excceed" -> "exceeded" Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 076/154] ksmbd: Fix parameter name and comment mismatch Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 077/154] ksmbd: fix possible memory leak in smb2_lock() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 078/154] ksmbd: fix wrong signingkey creation when encryption is AES256 Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 079/154] ksmbd: remove unused is_char_allowed function Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 080/154] ksmbd: delete asynchronous work from list Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 081/154] ksmbd: fix slab-out-of-bounds in init_smb2_rsp_hdr Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 082/154] ksmbd: avoid out of bounds access in decode_preauth_ctxt() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 083/154] ksmbd: set NegotiateContextCount once instead of every inc Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 084/154] ksmbd: avoid duplicate negotiate ctx offset increments Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 085/154] ksmbd: remove unused compression negotiate ctx packing Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 086/154] fs: introduce lock_rename_child() helper Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 087/154] ksmbd: fix racy issue from using ->d_parent and ->d_name Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 088/154] ksmbd: fix racy issue from session setup and logoff Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 089/154] ksmbd: destroy expired sessions Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 090/154] ksmbd: block asynchronous requests when making a delay on session setup Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 091/154] ksmbd: fix racy issue from smb2 close and logoff with multichannel Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 092/154] ksmbd: fix racy issue under cocurrent smb2 tree disconnect Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 093/154] ksmbd: fix uninitialized pointer read in ksmbd_vfs_rename() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 094/154] ksmbd: fix uninitialized pointer read in smb2_create_link() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 095/154] ksmbd: fix multiple out-of-bounds read during context decoding Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 096/154] ksmbd: fix UAF issue from opinfo->conn Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 097/154] ksmbd: call putname after using the last component Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 098/154] ksmbd: fix out-of-bound read in deassemble_neg_contexts() Namjae Jeon
2023-12-18 15:33 ` [PATCH 5.15.y 099/154] ksmbd: fix out-of-bound read in parse_lease_state() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 100/154] ksmbd: fix posix_acls and acls dereferencing possible ERR_PTR() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 101/154] ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 102/154] ksmbd: validate smb request protocol id Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 103/154] ksmbd: add mnt_want_write to ksmbd vfs functions Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 104/154] ksmbd: remove unused ksmbd_tree_conn_share function Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 105/154] ksmbd: use kzalloc() instead of __GFP_ZERO Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 106/154] ksmbd: return a literal instead of 'err' in ksmbd_vfs_kern_path_locked() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 107/154] ksmbd: Change the return value of ksmbd_vfs_query_maximal_access to void Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 108/154] ksmbd: use kvzalloc instead of kvmalloc Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 109/154] ksmbd: Replace the ternary conditional operator with min() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 110/154] ksmbd: fix out of bounds read in smb2_sess_setup Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 111/154] ksmbd: add missing compound request handing in some commands Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 112/154] ksmbd: Use struct_size() helper in ksmbd_negotiate_smb_dialect() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 113/154] ksmbd: Replace one-element array with flexible-array member Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 114/154] ksmbd: Fix unsigned expression compared with zero Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 115/154] ksmbd: check if a mount point is crossed during path lookup Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 116/154] ksmbd: validate session id and tree id in compound request Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 117/154] ksmbd: fix out of bounds in init_smb2_rsp_hdr() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 118/154] ksmbd: switch to use kmemdup_nul() helper Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 119/154] ksmbd: add support for read compound Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 120/154] ksmbd: fix wrong interim response on compound Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 121/154] ksmbd: fix `force create mode' and `force directory mode' Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 122/154] ksmbd: reduce descriptor size if remaining bytes is less than request size Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 123/154] ksmbd: Fix one kernel-doc comment Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 124/154] ksmbd: fix slub overflow in ksmbd_decode_ntlmssp_auth_blob() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 125/154] ksmbd: add missing calling smb2_set_err_rsp() on error Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 126/154] ksmbd: remove experimental warning Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 127/154] ksmbd: remove unneeded mark_inode_dirty in set_info_sec() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 128/154] ksmbd: fix passing freed memory 'aux_payload_buf' Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 129/154] ksmbd: return invalid parameter error response if smb2 request is invalid Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 130/154] ksmbd: check iov vector index in ksmbd_conn_write() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 131/154] ksmbd: fix race condition between session lookup and expire Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 132/154] ksmbd: fix race condition with fp Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 133/154] ksmbd: fix race condition from parallel smb2 logoff requests Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 134/154] ksmbd: fix race condition from parallel smb2 lock requests Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 135/154] ksmbd: fix race condition between tree conn lookup and disconnect Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 136/154] ksmbd: fix wrong error response status by using set_smb2_rsp_status() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 137/154] ksmbd: fix Null pointer dereferences in ksmbd_update_fstate() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 138/154] ksmbd: fix potential double free on smb2_read_pipe() error path Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 139/154] ksmbd: Remove unused field in ksmbd_user struct Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 140/154] ksmbd: reorganize ksmbd_iov_pin_rsp() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 141/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_setxattr() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 142/154] ksmbd: fix recursive locking in vfs helpers Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 143/154] ksmbd: fix missing RDMA-capable flag for IPoIB device in ksmbd_rdma_capable_netdev() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 144/154] ksmbd: add support for surrogate pair conversion Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 145/154] ksmbd: no need to wait for binded connection termination at logoff Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 146/154] ksmbd: fix kernel-doc comment of ksmbd_vfs_kern_path_locked() Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 147/154] ksmbd: handle malformed smb1 message Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 148/154] ksmbd: prevent memory leak on error return Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 149/154] ksmbd: fix possible deadlock in smb2_open Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 150/154] ksmbd: separately allocate ci per dentry Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 151/154] ksmbd: move oplock handling after unlock parent dir Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 152/154] ksmbd: release interim response after sending status pending response Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 153/154] ksmbd: move setting SMB2_FLAGS_ASYNC_COMMAND and AsyncId Namjae Jeon
2023-12-18 15:34 ` [PATCH 5.15.y 154/154] ksmbd: don't update ->op_state as OPLOCK_STATE_NONE on error Namjae Jeon
2023-12-20 14:41 ` [PATCH 5.15.y 000/154] ksmbd backport patches for 5.15.y Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox