Skip to content

Commit 25ac8c1

Browse files
committed
Merge tag '6.3-rc-ksmbd-fixes' of git://git.samba.org/ksmbd
Pull ksmbd server updates from Steve French: - Fix for memory leak - Two important fixes for frame length checks (which are also now stricter) - four minor cleanup fixes - Fix to clarify ksmbd/Kconfig to indent properl - Conversion of the channel list and rpc handle list to xarrays * tag '6.3-rc-ksmbd-fixes' of git://git.samba.org/ksmbd: ksmbd: fix possible memory leak in smb2_lock() ksmbd: do not allow the actual frame length to be smaller than the rfc1002 length ksmbd: fix wrong data area length for smb2 lock request ksmbd: Fix parameter name and comment mismatch ksmbd: Fix spelling mistake "excceed" -> "exceeded" ksmbd: update Kconfig to note Kerberos support and fix indentation ksmbd: Remove duplicated codes ksmbd: fix typo, syncronous->synchronous ksmbd: Implements sess->rpc_handle_list as xarray ksmbd: Implements sess->ksmbd_chann_list as xarray
2 parents 232dd59 + d3ca9f7 commit 25ac8c1

File tree

10 files changed

+99
-152
lines changed

10 files changed

+99
-152
lines changed

fs/ksmbd/Kconfig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,16 @@ config SMB_SERVER
3333
in ksmbd-tools, available from
3434
https://github.com/cifsd-team/ksmbd-tools.
3535
More detail about how to run the ksmbd kernel server is
36-
available via README file
36+
available via the README file
3737
(https://github.com/cifsd-team/ksmbd-tools/blob/master/README).
3838

3939
ksmbd kernel server includes support for auto-negotiation,
4040
Secure negotiate, Pre-authentication integrity, oplock/lease,
4141
compound requests, multi-credit, packet signing, RDMA(smbdirect),
4242
smb3 encryption, copy-offload, secure per-user session
43-
establishment via NTLM or NTLMv2.
43+
establishment via Kerberos or NTLMv2.
44+
45+
if SMB_SERVER
4446

4547
config SMB_SERVER_SMBDIRECT
4648
bool "Support for SMB Direct protocol"
@@ -54,6 +56,8 @@ config SMB_SERVER_SMBDIRECT
5456
SMB Direct allows transferring SMB packets over RDMA. If unsure,
5557
say N.
5658

59+
endif
60+
5761
config SMB_SERVER_CHECK_CAP_NET_ADMIN
5862
bool "Enable check network administration capability"
5963
depends on SMB_SERVER

fs/ksmbd/asn1.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,9 @@ int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
208208
return 0;
209209
}
210210

211-
int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
212-
unsigned char tag, const void *value,
213-
size_t vlen)
211+
static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
212+
unsigned char tag, const void *value,
213+
size_t vlen)
214214
{
215215
struct ksmbd_conn *conn = context;
216216

@@ -223,17 +223,16 @@ int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
223223
return 0;
224224
}
225225

226-
int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
226+
int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
227227
unsigned char tag, const void *value,
228228
size_t vlen)
229229
{
230-
struct ksmbd_conn *conn = context;
231-
232-
conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
233-
if (!conn->mechToken)
234-
return -ENOMEM;
230+
return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
231+
}
235232

236-
memcpy(conn->mechToken, value, vlen);
237-
conn->mechToken[vlen] = '\0';
238-
return 0;
233+
int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
234+
unsigned char tag, const void *value,
235+
size_t vlen)
236+
{
237+
return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
239238
}

fs/ksmbd/connection.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
114114

115115
if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
116116
requests_queue = &conn->requests;
117-
work->syncronous = true;
117+
work->synchronous = true;
118118
}
119119

120120
if (requests_queue) {
@@ -139,7 +139,7 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
139139
spin_lock(&conn->request_lock);
140140
if (!work->multiRsp) {
141141
list_del_init(&work->request_entry);
142-
if (work->syncronous == false)
142+
if (!work->synchronous)
143143
list_del_init(&work->async_request_entry);
144144
ret = 0;
145145
}
@@ -312,7 +312,7 @@ int ksmbd_conn_handler_loop(void *p)
312312
max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
313313

314314
if (pdu_size > max_allowed_pdu_size) {
315-
pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n",
315+
pr_err_ratelimited("PDU length(%u) exceeded maximum allowed pdu size(%u) on connection(%d)\n",
316316
pdu_size, max_allowed_pdu_size,
317317
conn->status);
318318
break;

fs/ksmbd/ksmbd_work.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ struct ksmbd_work {
6868
/* Request is encrypted */
6969
bool encrypted:1;
7070
/* Is this SYNC or ASYNC ksmbd_work */
71-
bool syncronous:1;
71+
bool synchronous:1;
7272
bool need_invalidate_rkey:1;
7373

7474
unsigned int remote_key;

fs/ksmbd/mgmt/user_session.c

Lines changed: 38 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,19 @@ static DECLARE_RWSEM(sessions_table_lock);
2525
struct ksmbd_session_rpc {
2626
int id;
2727
unsigned int method;
28-
struct list_head list;
2928
};
3029

3130
static void free_channel_list(struct ksmbd_session *sess)
3231
{
33-
struct channel *chann, *tmp;
32+
struct channel *chann;
33+
unsigned long index;
3434

35-
write_lock(&sess->chann_lock);
36-
list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
37-
chann_list) {
38-
list_del(&chann->chann_list);
35+
xa_for_each(&sess->ksmbd_chann_list, index, chann) {
36+
xa_erase(&sess->ksmbd_chann_list, index);
3937
kfree(chann);
4038
}
41-
write_unlock(&sess->chann_lock);
39+
40+
xa_destroy(&sess->ksmbd_chann_list);
4241
}
4342

4443
static void __session_rpc_close(struct ksmbd_session *sess,
@@ -58,15 +57,14 @@ static void __session_rpc_close(struct ksmbd_session *sess,
5857
static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
5958
{
6059
struct ksmbd_session_rpc *entry;
60+
long index;
6161

62-
while (!list_empty(&sess->rpc_handle_list)) {
63-
entry = list_entry(sess->rpc_handle_list.next,
64-
struct ksmbd_session_rpc,
65-
list);
66-
67-
list_del(&entry->list);
62+
xa_for_each(&sess->rpc_handle_list, index, entry) {
63+
xa_erase(&sess->rpc_handle_list, index);
6864
__session_rpc_close(sess, entry);
6965
}
66+
67+
xa_destroy(&sess->rpc_handle_list);
7068
}
7169

7270
static int __rpc_method(char *rpc_name)
@@ -102,13 +100,13 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
102100

103101
entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL);
104102
if (!entry)
105-
return -EINVAL;
103+
return -ENOMEM;
106104

107-
list_add(&entry->list, &sess->rpc_handle_list);
108105
entry->method = method;
109106
entry->id = ksmbd_ipc_id_alloc();
110107
if (entry->id < 0)
111108
goto free_entry;
109+
xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL);
112110

113111
resp = ksmbd_rpc_open(sess, entry->id);
114112
if (!resp)
@@ -117,9 +115,9 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
117115
kvfree(resp);
118116
return entry->id;
119117
free_id:
118+
xa_erase(&sess->rpc_handle_list, entry->id);
120119
ksmbd_rpc_id_free(entry->id);
121120
free_entry:
122-
list_del(&entry->list);
123121
kfree(entry);
124122
return -EINVAL;
125123
}
@@ -128,24 +126,17 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
128126
{
129127
struct ksmbd_session_rpc *entry;
130128

131-
list_for_each_entry(entry, &sess->rpc_handle_list, list) {
132-
if (entry->id == id) {
133-
list_del(&entry->list);
134-
__session_rpc_close(sess, entry);
135-
break;
136-
}
137-
}
129+
entry = xa_erase(&sess->rpc_handle_list, id);
130+
if (entry)
131+
__session_rpc_close(sess, entry);
138132
}
139133

140134
int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
141135
{
142136
struct ksmbd_session_rpc *entry;
143137

144-
list_for_each_entry(entry, &sess->rpc_handle_list, list) {
145-
if (entry->id == id)
146-
return entry->method;
147-
}
148-
return 0;
138+
entry = xa_load(&sess->rpc_handle_list, id);
139+
return entry ? entry->method : 0;
149140
}
150141

151142
void ksmbd_session_destroy(struct ksmbd_session *sess)
@@ -190,21 +181,15 @@ int ksmbd_session_register(struct ksmbd_conn *conn,
190181

191182
static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
192183
{
193-
struct channel *chann, *tmp;
194-
195-
write_lock(&sess->chann_lock);
196-
list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
197-
chann_list) {
198-
if (chann->conn == conn) {
199-
list_del(&chann->chann_list);
200-
kfree(chann);
201-
write_unlock(&sess->chann_lock);
202-
return 0;
203-
}
204-
}
205-
write_unlock(&sess->chann_lock);
184+
struct channel *chann;
185+
186+
chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
187+
if (!chann)
188+
return -ENOENT;
206189

207-
return -ENOENT;
190+
kfree(chann);
191+
192+
return 0;
208193
}
209194

210195
void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
@@ -234,7 +219,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
234219
return;
235220

236221
sess_destroy:
237-
if (list_empty(&sess->ksmbd_chann_list)) {
222+
if (xa_empty(&sess->ksmbd_chann_list)) {
238223
xa_erase(&conn->sessions, sess->id);
239224
ksmbd_session_destroy(sess);
240225
}
@@ -320,6 +305,9 @@ static struct ksmbd_session *__session_create(int protocol)
320305
struct ksmbd_session *sess;
321306
int ret;
322307

308+
if (protocol != CIFDS_SESSION_FLAG_SMB2)
309+
return NULL;
310+
323311
sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL);
324312
if (!sess)
325313
return NULL;
@@ -329,30 +317,20 @@ static struct ksmbd_session *__session_create(int protocol)
329317

330318
set_session_flag(sess, protocol);
331319
xa_init(&sess->tree_conns);
332-
INIT_LIST_HEAD(&sess->ksmbd_chann_list);
333-
INIT_LIST_HEAD(&sess->rpc_handle_list);
320+
xa_init(&sess->ksmbd_chann_list);
321+
xa_init(&sess->rpc_handle_list);
334322
sess->sequence_number = 1;
335-
rwlock_init(&sess->chann_lock);
336-
337-
switch (protocol) {
338-
case CIFDS_SESSION_FLAG_SMB2:
339-
ret = __init_smb2_session(sess);
340-
break;
341-
default:
342-
ret = -EINVAL;
343-
break;
344-
}
345323

324+
ret = __init_smb2_session(sess);
346325
if (ret)
347326
goto error;
348327

349328
ida_init(&sess->tree_conn_ida);
350329

351-
if (protocol == CIFDS_SESSION_FLAG_SMB2) {
352-
down_write(&sessions_table_lock);
353-
hash_add(sessions_table, &sess->hlist, sess->id);
354-
up_write(&sessions_table_lock);
355-
}
330+
down_write(&sessions_table_lock);
331+
hash_add(sessions_table, &sess->hlist, sess->id);
332+
up_write(&sessions_table_lock);
333+
356334
return sess;
357335

358336
error:

fs/ksmbd/mgmt/user_session.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ struct ksmbd_file_table;
2121
struct channel {
2222
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
2323
struct ksmbd_conn *conn;
24-
struct list_head chann_list;
2524
};
2625

2726
struct preauth_session {
@@ -50,11 +49,10 @@ struct ksmbd_session {
5049
char sess_key[CIFS_KEY_SIZE];
5150

5251
struct hlist_node hlist;
53-
rwlock_t chann_lock;
54-
struct list_head ksmbd_chann_list;
52+
struct xarray ksmbd_chann_list;
5553
struct xarray tree_conns;
5654
struct ida tree_conn_ida;
57-
struct list_head rpc_handle_list;
55+
struct xarray rpc_handle_list;
5856

5957
__u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
6058
__u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];

fs/ksmbd/smb2misc.c

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,11 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
149149
break;
150150
case SMB2_LOCK:
151151
{
152-
int lock_count;
152+
unsigned short lock_count;
153153

154-
/*
155-
* smb2_lock request size is 48 included single
156-
* smb2_lock_element structure size.
157-
*/
158-
lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount) - 1;
154+
lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount);
159155
if (lock_count > 0) {
160-
*off = __SMB2_HEADER_STRUCTURE_SIZE + 48;
156+
*off = offsetof(struct smb2_lock_req, locks);
161157
*len = sizeof(struct smb2_lock_element) * lock_count;
162158
}
163159
break;
@@ -412,20 +408,19 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
412408
goto validate_credit;
413409

414410
/*
415-
* windows client also pad up to 8 bytes when compounding.
416-
* If pad is longer than eight bytes, log the server behavior
417-
* (once), since may indicate a problem but allow it and
418-
* continue since the frame is parseable.
411+
* SMB2 NEGOTIATE request will be validated when message
412+
* handling proceeds.
419413
*/
420-
if (clc_len < len) {
421-
ksmbd_debug(SMB,
422-
"cli req padded more than expected. Length %d not %d for cmd:%d mid:%llu\n",
423-
len, clc_len, command,
424-
le64_to_cpu(hdr->MessageId));
414+
if (command == SMB2_NEGOTIATE_HE)
415+
goto validate_credit;
416+
417+
/*
418+
* Allow a message that padded to 8byte boundary.
419+
*/
420+
if (clc_len < len && (len - clc_len) < 8)
425421
goto validate_credit;
426-
}
427422

428-
ksmbd_debug(SMB,
423+
pr_err_ratelimited(
429424
"cli req too short, len %d not %d. cmd:%d mid:%llu\n",
430425
len, clc_len, command,
431426
le64_to_cpu(hdr->MessageId));

0 commit comments

Comments
 (0)