release 6.14.6
This commit is contained in:
@@ -1,108 +0,0 @@
|
||||
From f9567920fca6215aed3fa0658c09ae57f3168ed0 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Date: Thu, 17 Apr 2025 10:10:15 +0900
|
||||
Subject: ksmbd: fix use-after-free in ksmbd_session_rpc_open
|
||||
|
||||
A UAF issue can occur due to a race condition between
|
||||
ksmbd_session_rpc_open() and __session_rpc_close().
|
||||
Add rpc_lock to the session to protect it.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Reported-by: Norbert Szetei <norbert@doyensec.com>
|
||||
Tested-by: Norbert Szetei <norbert@doyensec.com>
|
||||
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/mgmt/user_session.c | 20 ++++++++++++++------
|
||||
fs/smb/server/mgmt/user_session.h | 1 +
|
||||
2 files changed, 15 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/fs/smb/server/mgmt/user_session.c
|
||||
+++ b/fs/smb/server/mgmt/user_session.c
|
||||
@@ -59,10 +59,12 @@ static void ksmbd_session_rpc_clear_list
|
||||
struct ksmbd_session_rpc *entry;
|
||||
long index;
|
||||
|
||||
+ down_write(&sess->rpc_lock);
|
||||
xa_for_each(&sess->rpc_handle_list, index, entry) {
|
||||
xa_erase(&sess->rpc_handle_list, index);
|
||||
__session_rpc_close(sess, entry);
|
||||
}
|
||||
+ up_write(&sess->rpc_lock);
|
||||
|
||||
xa_destroy(&sess->rpc_handle_list);
|
||||
}
|
||||
@@ -92,7 +94,7 @@ int ksmbd_session_rpc_open(struct ksmbd_
|
||||
{
|
||||
struct ksmbd_session_rpc *entry, *old;
|
||||
struct ksmbd_rpc_command *resp;
|
||||
- int method;
|
||||
+ int method, id;
|
||||
|
||||
method = __rpc_method(rpc_name);
|
||||
if (!method)
|
||||
@@ -102,26 +104,29 @@ int ksmbd_session_rpc_open(struct ksmbd_
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
+ down_read(&sess->rpc_lock);
|
||||
entry->method = method;
|
||||
- entry->id = ksmbd_ipc_id_alloc();
|
||||
- if (entry->id < 0)
|
||||
+ entry->id = id = ksmbd_ipc_id_alloc();
|
||||
+ if (id < 0)
|
||||
goto free_entry;
|
||||
- old = xa_store(&sess->rpc_handle_list, entry->id, entry, KSMBD_DEFAULT_GFP);
|
||||
+ old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP);
|
||||
if (xa_is_err(old))
|
||||
goto free_id;
|
||||
|
||||
- resp = ksmbd_rpc_open(sess, entry->id);
|
||||
+ resp = ksmbd_rpc_open(sess, id);
|
||||
if (!resp)
|
||||
goto erase_xa;
|
||||
|
||||
+ up_read(&sess->rpc_lock);
|
||||
kvfree(resp);
|
||||
- return entry->id;
|
||||
+ return id;
|
||||
erase_xa:
|
||||
xa_erase(&sess->rpc_handle_list, entry->id);
|
||||
free_id:
|
||||
ksmbd_rpc_id_free(entry->id);
|
||||
free_entry:
|
||||
kfree(entry);
|
||||
+ up_read(&sess->rpc_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -129,9 +134,11 @@ void ksmbd_session_rpc_close(struct ksmb
|
||||
{
|
||||
struct ksmbd_session_rpc *entry;
|
||||
|
||||
+ down_write(&sess->rpc_lock);
|
||||
entry = xa_erase(&sess->rpc_handle_list, id);
|
||||
if (entry)
|
||||
__session_rpc_close(sess, entry);
|
||||
+ up_write(&sess->rpc_lock);
|
||||
}
|
||||
|
||||
int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
|
||||
@@ -439,6 +446,7 @@ static struct ksmbd_session *__session_c
|
||||
sess->sequence_number = 1;
|
||||
rwlock_init(&sess->tree_conns_lock);
|
||||
atomic_set(&sess->refcnt, 2);
|
||||
+ init_rwsem(&sess->rpc_lock);
|
||||
|
||||
ret = __init_smb2_session(sess);
|
||||
if (ret)
|
||||
--- a/fs/smb/server/mgmt/user_session.h
|
||||
+++ b/fs/smb/server/mgmt/user_session.h
|
||||
@@ -63,6 +63,7 @@ struct ksmbd_session {
|
||||
rwlock_t tree_conns_lock;
|
||||
|
||||
atomic_t refcnt;
|
||||
+ struct rw_semaphore rpc_lock;
|
||||
};
|
||||
|
||||
static inline int test_session_flag(struct ksmbd_session *sess, int bit)
|
33
debian/patches/patchset-pf/smb/0001-ksmbd-prevent-rename-with-empty-string.patch
vendored
Normal file
33
debian/patches/patchset-pf/smb/0001-ksmbd-prevent-rename-with-empty-string.patch
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
From 7b3f0f8d11f1b4319f593ba02d4dece890755dfa Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Date: Wed, 30 Apr 2025 11:18:28 +0900
|
||||
Subject: ksmbd: prevent rename with empty string
|
||||
|
||||
Client can send empty newname string to ksmbd server.
|
||||
It will cause a kernel oops from d_alloc.
|
||||
This patch return the error when attempting to rename
|
||||
a file or directory with an empty new name string.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Reported-by: Norbert Szetei <norbert@doyensec.com>
|
||||
Tested-by: Norbert Szetei <norbert@doyensec.com>
|
||||
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/smb2pdu.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/fs/smb/server/smb2pdu.c
|
||||
+++ b/fs/smb/server/smb2pdu.c
|
||||
@@ -633,6 +633,11 @@ smb2_get_name(const char *src, const int
|
||||
return name;
|
||||
}
|
||||
|
||||
+ if (*name == '\0') {
|
||||
+ kfree(name);
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ }
|
||||
+
|
||||
if (*name == '\\') {
|
||||
pr_err("not allow directory name included leading slash\n");
|
||||
kfree(name);
|
@@ -1,56 +0,0 @@
|
||||
From 6e367a428b98393cd5d0ab993983ba40dc748ca5 Mon Sep 17 00:00:00 2001
|
||||
From: Sean Heelan <seanheelan@gmail.com>
|
||||
Date: Sat, 19 Apr 2025 19:59:28 +0100
|
||||
Subject: ksmbd: fix use-after-free in kerberos authentication
|
||||
|
||||
Setting sess->user = NULL was introduced to fix the dangling pointer
|
||||
created by ksmbd_free_user. However, it is possible another thread could
|
||||
be operating on the session and make use of sess->user after it has been
|
||||
passed to ksmbd_free_user but before sess->user is set to NULL.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Sean Heelan <seanheelan@gmail.com>
|
||||
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/auth.c | 14 +++++++++++++-
|
||||
fs/smb/server/smb2pdu.c | 5 -----
|
||||
2 files changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/fs/smb/server/auth.c
|
||||
+++ b/fs/smb/server/auth.c
|
||||
@@ -550,7 +550,19 @@ int ksmbd_krb5_authenticate(struct ksmbd
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
- sess->user = user;
|
||||
+
|
||||
+ if (!sess->user) {
|
||||
+ /* First successful authentication */
|
||||
+ sess->user = user;
|
||||
+ } else {
|
||||
+ if (!ksmbd_compare_user(sess->user, user)) {
|
||||
+ ksmbd_debug(AUTH, "different user tried to reuse session\n");
|
||||
+ retval = -EPERM;
|
||||
+ ksmbd_free_user(user);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ ksmbd_free_user(user);
|
||||
+ }
|
||||
|
||||
memcpy(sess->sess_key, resp->payload, resp->session_key_len);
|
||||
memcpy(out_blob, resp->payload + resp->session_key_len,
|
||||
--- a/fs/smb/server/smb2pdu.c
|
||||
+++ b/fs/smb/server/smb2pdu.c
|
||||
@@ -1602,11 +1602,6 @@ static int krb5_authenticate(struct ksmb
|
||||
if (prev_sess_id && prev_sess_id != sess->id)
|
||||
destroy_previous_session(conn, sess->user, prev_sess_id);
|
||||
|
||||
- if (sess->state == SMB2_SESSION_VALID) {
|
||||
- ksmbd_free_user(sess->user);
|
||||
- sess->user = NULL;
|
||||
- }
|
||||
-
|
||||
retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
|
||||
out_blob, &out_len);
|
||||
if (retval) {
|
37
debian/patches/patchset-pf/smb/0002-ksmbd-prevent-out-of-bounds-stream-writes-by-validat.patch
vendored
Normal file
37
debian/patches/patchset-pf/smb/0002-ksmbd-prevent-out-of-bounds-stream-writes-by-validat.patch
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
From fb87d390de327c76b11ed544de83771118f7b0c5 Mon Sep 17 00:00:00 2001
|
||||
From: Norbert Szetei <norbert@doyensec.com>
|
||||
Date: Fri, 2 May 2025 08:21:58 +0900
|
||||
Subject: ksmbd: prevent out-of-bounds stream writes by validating *pos
|
||||
|
||||
ksmbd_vfs_stream_write() did not validate whether the write offset
|
||||
(*pos) was within the bounds of the existing stream data length (v_len).
|
||||
If *pos was greater than or equal to v_len, this could lead to an
|
||||
out-of-bounds memory write.
|
||||
|
||||
This patch adds a check to ensure *pos is less than v_len before
|
||||
proceeding. If the condition fails, -EINVAL is returned.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
|
||||
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/vfs.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/fs/smb/server/vfs.c
|
||||
+++ b/fs/smb/server/vfs.c
|
||||
@@ -443,6 +443,13 @@ static int ksmbd_vfs_stream_write(struct
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if (v_len <= *pos) {
|
||||
+ pr_err("stream write position %lld is out of bounds (stream length: %zd)\n",
|
||||
+ *pos, v_len);
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
if (v_len < size) {
|
||||
wbuf = kvzalloc(size, KSMBD_DEFAULT_GFP);
|
||||
if (!wbuf) {
|
74
debian/patches/patchset-pf/smb/0003-ksmbd-Fix-UAF-in-__close_file_table_ids.patch
vendored
Normal file
74
debian/patches/patchset-pf/smb/0003-ksmbd-Fix-UAF-in-__close_file_table_ids.patch
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
From 67ea573ce44aeac74e659879cdeb6ac39212d0b9 Mon Sep 17 00:00:00 2001
|
||||
From: Sean Heelan <seanheelan@gmail.com>
|
||||
Date: Tue, 6 May 2025 22:04:52 +0900
|
||||
Subject: ksmbd: Fix UAF in __close_file_table_ids
|
||||
|
||||
A use-after-free is possible if one thread destroys the file
|
||||
via __ksmbd_close_fd while another thread holds a reference to
|
||||
it. The existing checks on fp->refcount are not sufficient to
|
||||
prevent this.
|
||||
|
||||
The fix takes ft->lock around the section which removes the
|
||||
file from the file table. This prevents two threads acquiring the
|
||||
same file pointer via __close_file_table_ids, as well as the other
|
||||
functions which retrieve a file from the IDR and which already use
|
||||
this same lock.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Sean Heelan <seanheelan@gmail.com>
|
||||
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/vfs_cache.c | 33 ++++++++++++++++++++++++++-------
|
||||
1 file changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/smb/server/vfs_cache.c
|
||||
+++ b/fs/smb/server/vfs_cache.c
|
||||
@@ -661,21 +661,40 @@ __close_file_table_ids(struct ksmbd_file
|
||||
bool (*skip)(struct ksmbd_tree_connect *tcon,
|
||||
struct ksmbd_file *fp))
|
||||
{
|
||||
- unsigned int id;
|
||||
- struct ksmbd_file *fp;
|
||||
- int num = 0;
|
||||
+ struct ksmbd_file *fp;
|
||||
+ unsigned int id = 0;
|
||||
+ int num = 0;
|
||||
|
||||
- idr_for_each_entry(ft->idr, fp, id) {
|
||||
- if (skip(tcon, fp))
|
||||
+ while (1) {
|
||||
+ write_lock(&ft->lock);
|
||||
+ fp = idr_get_next(ft->idr, &id);
|
||||
+ if (!fp) {
|
||||
+ write_unlock(&ft->lock);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (skip(tcon, fp) ||
|
||||
+ !atomic_dec_and_test(&fp->refcount)) {
|
||||
+ id++;
|
||||
+ write_unlock(&ft->lock);
|
||||
continue;
|
||||
+ }
|
||||
|
||||
set_close_state_blocked_works(fp);
|
||||
+ idr_remove(ft->idr, fp->volatile_id);
|
||||
+ fp->volatile_id = KSMBD_NO_FID;
|
||||
+ write_unlock(&ft->lock);
|
||||
+
|
||||
+ down_write(&fp->f_ci->m_lock);
|
||||
+ list_del_init(&fp->node);
|
||||
+ up_write(&fp->f_ci->m_lock);
|
||||
|
||||
- if (!atomic_dec_and_test(&fp->refcount))
|
||||
- continue;
|
||||
__ksmbd_close_fd(ft, fp);
|
||||
+
|
||||
num++;
|
||||
+ id++;
|
||||
}
|
||||
+
|
||||
return num;
|
||||
}
|
||||
|
@@ -1,31 +0,0 @@
|
||||
From 818b4d086f287e0a5cc6368eb72703b68b0603d0 Mon Sep 17 00:00:00 2001
|
||||
From: Sean Heelan <seanheelan@gmail.com>
|
||||
Date: Mon, 21 Apr 2025 15:39:29 +0000
|
||||
Subject: ksmbd: fix use-after-free in session logoff
|
||||
|
||||
The sess->user object can currently be in use by another thread, for
|
||||
example if another connection has sent a session setup request to
|
||||
bind to the session being free'd. The handler for that connection could
|
||||
be in the smb2_sess_setup function which makes use of sess->user.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Sean Heelan <seanheelan@gmail.com>
|
||||
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/smb2pdu.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
--- a/fs/smb/server/smb2pdu.c
|
||||
+++ b/fs/smb/server/smb2pdu.c
|
||||
@@ -2244,10 +2244,6 @@ int smb2_session_logoff(struct ksmbd_wor
|
||||
sess->state = SMB2_SESSION_EXPIRED;
|
||||
up_write(&conn->session_lock);
|
||||
|
||||
- if (sess->user) {
|
||||
- ksmbd_free_user(sess->user);
|
||||
- sess->user = NULL;
|
||||
- }
|
||||
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP);
|
||||
|
||||
rsp->StructureSize = cpu_to_le16(4);
|
Reference in New Issue
Block a user