Skip to content

Commit ca91b95

Browse files
committed
Merge tag 'v6.15-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - Fix three potential use after frees: in session logoff, in krb5 auth, and in RPC open - Fix missing rc check in session setup authentication * tag 'v6.15-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: fix use-after-free in session logoff ksmbd: fix use-after-free in kerberos authentication ksmbd: fix use-after-free in ksmbd_session_rpc_open smb: server: smb2pdu: check return value of xa_store()
2 parents 78109c5 + 2fc9fef commit ca91b95

File tree

4 files changed

+35
-18
lines changed

4 files changed

+35
-18
lines changed

fs/smb/server/auth.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,19 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
550550
retval = -ENOMEM;
551551
goto out;
552552
}
553-
sess->user = user;
553+
554+
if (!sess->user) {
555+
/* First successful authentication */
556+
sess->user = user;
557+
} else {
558+
if (!ksmbd_compare_user(sess->user, user)) {
559+
ksmbd_debug(AUTH, "different user tried to reuse session\n");
560+
retval = -EPERM;
561+
ksmbd_free_user(user);
562+
goto out;
563+
}
564+
ksmbd_free_user(user);
565+
}
554566

555567
memcpy(sess->sess_key, resp->payload, resp->session_key_len);
556568
memcpy(out_blob, resp->payload + resp->session_key_len,

fs/smb/server/mgmt/user_session.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@ static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
5959
struct ksmbd_session_rpc *entry;
6060
long index;
6161

62+
down_write(&sess->rpc_lock);
6263
xa_for_each(&sess->rpc_handle_list, index, entry) {
6364
xa_erase(&sess->rpc_handle_list, index);
6465
__session_rpc_close(sess, entry);
6566
}
67+
up_write(&sess->rpc_lock);
6668

6769
xa_destroy(&sess->rpc_handle_list);
6870
}
@@ -92,7 +94,7 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
9294
{
9395
struct ksmbd_session_rpc *entry, *old;
9496
struct ksmbd_rpc_command *resp;
95-
int method;
97+
int method, id;
9698

9799
method = __rpc_method(rpc_name);
98100
if (!method)
@@ -102,36 +104,41 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
102104
if (!entry)
103105
return -ENOMEM;
104106

107+
down_read(&sess->rpc_lock);
105108
entry->method = method;
106-
entry->id = ksmbd_ipc_id_alloc();
107-
if (entry->id < 0)
109+
entry->id = id = ksmbd_ipc_id_alloc();
110+
if (id < 0)
108111
goto free_entry;
109-
old = xa_store(&sess->rpc_handle_list, entry->id, entry, KSMBD_DEFAULT_GFP);
112+
old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP);
110113
if (xa_is_err(old))
111114
goto free_id;
112115

113-
resp = ksmbd_rpc_open(sess, entry->id);
116+
resp = ksmbd_rpc_open(sess, id);
114117
if (!resp)
115118
goto erase_xa;
116119

120+
up_read(&sess->rpc_lock);
117121
kvfree(resp);
118-
return entry->id;
122+
return id;
119123
erase_xa:
120124
xa_erase(&sess->rpc_handle_list, entry->id);
121125
free_id:
122126
ksmbd_rpc_id_free(entry->id);
123127
free_entry:
124128
kfree(entry);
129+
up_read(&sess->rpc_lock);
125130
return -EINVAL;
126131
}
127132

128133
void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
129134
{
130135
struct ksmbd_session_rpc *entry;
131136

137+
down_write(&sess->rpc_lock);
132138
entry = xa_erase(&sess->rpc_handle_list, id);
133139
if (entry)
134140
__session_rpc_close(sess, entry);
141+
up_write(&sess->rpc_lock);
135142
}
136143

137144
int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
@@ -439,6 +446,7 @@ static struct ksmbd_session *__session_create(int protocol)
439446
sess->sequence_number = 1;
440447
rwlock_init(&sess->tree_conns_lock);
441448
atomic_set(&sess->refcnt, 2);
449+
init_rwsem(&sess->rpc_lock);
442450

443451
ret = __init_smb2_session(sess);
444452
if (ret)

fs/smb/server/mgmt/user_session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct ksmbd_session {
6363
rwlock_t tree_conns_lock;
6464

6565
atomic_t refcnt;
66+
struct rw_semaphore rpc_lock;
6667
};
6768

6869
static inline int test_session_flag(struct ksmbd_session *sess, int bit)

fs/smb/server/smb2pdu.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
14451445
{
14461446
struct ksmbd_conn *conn = work->conn;
14471447
struct ksmbd_session *sess = work->sess;
1448-
struct channel *chann = NULL;
1448+
struct channel *chann = NULL, *old;
14491449
struct ksmbd_user *user;
14501450
u64 prev_id;
14511451
int sz, rc;
@@ -1557,7 +1557,12 @@ static int ntlm_authenticate(struct ksmbd_work *work,
15571557
return -ENOMEM;
15581558

15591559
chann->conn = conn;
1560-
xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP);
1560+
old = xa_store(&sess->ksmbd_chann_list, (long)conn, chann,
1561+
KSMBD_DEFAULT_GFP);
1562+
if (xa_is_err(old)) {
1563+
kfree(chann);
1564+
return xa_err(old);
1565+
}
15611566
}
15621567
}
15631568

@@ -1602,11 +1607,6 @@ static int krb5_authenticate(struct ksmbd_work *work,
16021607
if (prev_sess_id && prev_sess_id != sess->id)
16031608
destroy_previous_session(conn, sess->user, prev_sess_id);
16041609

1605-
if (sess->state == SMB2_SESSION_VALID) {
1606-
ksmbd_free_user(sess->user);
1607-
sess->user = NULL;
1608-
}
1609-
16101610
retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
16111611
out_blob, &out_len);
16121612
if (retval) {
@@ -2249,10 +2249,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
22492249
sess->state = SMB2_SESSION_EXPIRED;
22502250
up_write(&conn->session_lock);
22512251

2252-
if (sess->user) {
2253-
ksmbd_free_user(sess->user);
2254-
sess->user = NULL;
2255-
}
22562252
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP);
22572253

22582254
rsp->StructureSize = cpu_to_le16(4);

0 commit comments

Comments
 (0)