Skip to content

Commit eb555cb

Browse files
committed
Merge tag '5.20-rc-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull ksmbd updates from Steve French: - fixes for memory access bugs (out of bounds access, oops, leak) - multichannel fixes - session disconnect performance improvement, and session register improvement - cleanup * tag '5.20-rc-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: fix heap-based overflow in set_ntacl_dacl() ksmbd: prevent out of bound read for SMB2_TREE_CONNNECT ksmbd: prevent out of bound read for SMB2_WRITE ksmbd: fix use-after-free bug in smb2_tree_disconect ksmbd: fix memory leak in smb2_handle_negotiate ksmbd: fix racy issue while destroying session on multichannel ksmbd: use wait_event instead of schedule_timeout() ksmbd: fix kernel oops from idr_remove() ksmbd: add channel rwlock ksmbd: replace sessions list in connection with xarray MAINTAINERS: ksmbd: add entry for documentation ksmbd: remove unused ksmbd_share_configs_cleanup function
2 parents f30adc0 + 8f05411 commit eb555cb

20 files changed

+322
-220
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11063,6 +11063,7 @@ R: Sergey Senozhatsky <[email protected]>
1106311063
1106411064
S: Maintained
1106511065
T: git git://git.samba.org/ksmbd.git
11066+
F: Documentation/filesystems/cifs/ksmbd.rst
1106611067
F: fs/ksmbd/
1106711068
F: fs/smbfs_common/
1106811069

fs/ksmbd/auth.c

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
121121
return rc;
122122
}
123123

124-
static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
125-
char *dname)
124+
static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
125+
char *ntlmv2_hash, char *dname)
126126
{
127127
int ret, len, conv_len;
128128
wchar_t *domain = NULL;
@@ -158,7 +158,7 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
158158
}
159159

160160
conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
161-
sess->conn->local_nls);
161+
conn->local_nls);
162162
if (conv_len < 0 || conv_len > len) {
163163
ret = -EINVAL;
164164
goto out;
@@ -182,7 +182,7 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
182182
}
183183

184184
conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
185-
sess->conn->local_nls);
185+
conn->local_nls);
186186
if (conv_len < 0 || conv_len > len) {
187187
ret = -EINVAL;
188188
goto out;
@@ -215,8 +215,9 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
215215
*
216216
* Return: 0 on success, error number on error
217217
*/
218-
int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2,
219-
int blen, char *domain_name, char *cryptkey)
218+
int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
219+
struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
220+
char *cryptkey)
220221
{
221222
char ntlmv2_hash[CIFS_ENCPWD_SIZE];
222223
char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
@@ -230,7 +231,7 @@ int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2,
230231
return -ENOMEM;
231232
}
232233

233-
rc = calc_ntlmv2_hash(sess, ntlmv2_hash, domain_name);
234+
rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name);
234235
if (rc) {
235236
ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
236237
goto out;
@@ -333,7 +334,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
333334
/* process NTLMv2 authentication */
334335
ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n",
335336
domain_name);
336-
ret = ksmbd_auth_ntlmv2(sess, (struct ntlmv2_resp *)((char *)authblob + nt_off),
337+
ret = ksmbd_auth_ntlmv2(conn, sess,
338+
(struct ntlmv2_resp *)((char *)authblob + nt_off),
337339
nt_len - CIFS_ENCPWD_SIZE,
338340
domain_name, conn->ntlmssp.cryptkey);
339341
kfree(domain_name);
@@ -659,8 +661,9 @@ struct derivation {
659661
bool binding;
660662
};
661663

662-
static int generate_key(struct ksmbd_session *sess, struct kvec label,
663-
struct kvec context, __u8 *key, unsigned int key_size)
664+
static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
665+
struct kvec label, struct kvec context, __u8 *key,
666+
unsigned int key_size)
664667
{
665668
unsigned char zero = 0x0;
666669
__u8 i[4] = {0, 0, 0, 1};
@@ -720,8 +723,8 @@ static int generate_key(struct ksmbd_session *sess, struct kvec label,
720723
goto smb3signkey_ret;
721724
}
722725

723-
if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
724-
sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
726+
if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
727+
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
725728
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
726729
else
727730
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
@@ -756,17 +759,17 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
756759
if (!chann)
757760
return 0;
758761

759-
if (sess->conn->dialect >= SMB30_PROT_ID && signing->binding)
762+
if (conn->dialect >= SMB30_PROT_ID && signing->binding)
760763
key = chann->smb3signingkey;
761764
else
762765
key = sess->smb3signingkey;
763766

764-
rc = generate_key(sess, signing->label, signing->context, key,
767+
rc = generate_key(conn, sess, signing->label, signing->context, key,
765768
SMB3_SIGN_KEY_SIZE);
766769
if (rc)
767770
return rc;
768771

769-
if (!(sess->conn->dialect >= SMB30_PROT_ID && signing->binding))
772+
if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
770773
memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
771774

772775
ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
@@ -820,30 +823,31 @@ struct derivation_twin {
820823
struct derivation decryption;
821824
};
822825

823-
static int generate_smb3encryptionkey(struct ksmbd_session *sess,
826+
static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
827+
struct ksmbd_session *sess,
824828
const struct derivation_twin *ptwin)
825829
{
826830
int rc;
827831

828-
rc = generate_key(sess, ptwin->encryption.label,
832+
rc = generate_key(conn, sess, ptwin->encryption.label,
829833
ptwin->encryption.context, sess->smb3encryptionkey,
830834
SMB3_ENC_DEC_KEY_SIZE);
831835
if (rc)
832836
return rc;
833837

834-
rc = generate_key(sess, ptwin->decryption.label,
838+
rc = generate_key(conn, sess, ptwin->decryption.label,
835839
ptwin->decryption.context,
836840
sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
837841
if (rc)
838842
return rc;
839843

840844
ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
841-
ksmbd_debug(AUTH, "Cipher type %d\n", sess->conn->cipher_type);
845+
ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type);
842846
ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
843847
ksmbd_debug(AUTH, "Session Key %*ph\n",
844848
SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
845-
if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
846-
sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
849+
if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
850+
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
847851
ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
848852
SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
849853
ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
@@ -857,7 +861,8 @@ static int generate_smb3encryptionkey(struct ksmbd_session *sess,
857861
return 0;
858862
}
859863

860-
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess)
864+
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
865+
struct ksmbd_session *sess)
861866
{
862867
struct derivation_twin twin;
863868
struct derivation *d;
@@ -874,10 +879,11 @@ int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess)
874879
d->context.iov_base = "ServerIn ";
875880
d->context.iov_len = 10;
876881

877-
return generate_smb3encryptionkey(sess, &twin);
882+
return generate_smb3encryptionkey(conn, sess, &twin);
878883
}
879884

880-
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess)
885+
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
886+
struct ksmbd_session *sess)
881887
{
882888
struct derivation_twin twin;
883889
struct derivation *d;
@@ -894,7 +900,7 @@ int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess)
894900
d->context.iov_base = sess->Preauth_HashValue;
895901
d->context.iov_len = 64;
896902

897-
return generate_smb3encryptionkey(sess, &twin);
903+
return generate_smb3encryptionkey(conn, sess, &twin);
898904
}
899905

900906
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,

fs/ksmbd/auth.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ struct kvec;
3838
int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
3939
unsigned int nvec, int enc);
4040
void ksmbd_copy_gss_neg_header(void *buf);
41-
int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2,
42-
int blen, char *domain_name, char *cryptkey);
41+
int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
42+
struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
43+
char *cryptkey);
4344
int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
4445
int blob_len, struct ksmbd_conn *conn,
4546
struct ksmbd_session *sess);
@@ -58,8 +59,10 @@ int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
5859
struct ksmbd_conn *conn);
5960
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
6061
struct ksmbd_conn *conn);
61-
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess);
62-
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess);
62+
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
63+
struct ksmbd_session *sess);
64+
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
65+
struct ksmbd_session *sess);
6366
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
6467
__u8 *pi_hash);
6568
int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,

fs/ksmbd/connection.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
3636
list_del(&conn->conns_list);
3737
write_unlock(&conn_list_lock);
3838

39+
xa_destroy(&conn->sessions);
3940
kvfree(conn->request_buf);
4041
kfree(conn->preauth_info);
4142
kfree(conn);
@@ -65,13 +66,14 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
6566
conn->outstanding_credits = 0;
6667

6768
init_waitqueue_head(&conn->req_running_q);
69+
init_waitqueue_head(&conn->r_count_q);
6870
INIT_LIST_HEAD(&conn->conns_list);
69-
INIT_LIST_HEAD(&conn->sessions);
7071
INIT_LIST_HEAD(&conn->requests);
7172
INIT_LIST_HEAD(&conn->async_requests);
7273
spin_lock_init(&conn->request_lock);
7374
spin_lock_init(&conn->credits_lock);
7475
ida_init(&conn->async_ida);
76+
xa_init(&conn->sessions);
7577

7678
spin_lock_init(&conn->llist_lock);
7779
INIT_LIST_HEAD(&conn->lock_list);
@@ -164,7 +166,6 @@ int ksmbd_conn_write(struct ksmbd_work *work)
164166
struct kvec iov[3];
165167
int iov_idx = 0;
166168

167-
ksmbd_conn_try_dequeue_request(work);
168169
if (!work->response_buf) {
169170
pr_err("NULL response header\n");
170171
return -EINVAL;
@@ -346,8 +347,8 @@ int ksmbd_conn_handler_loop(void *p)
346347

347348
out:
348349
/* Wait till all reference dropped to the Server object*/
349-
while (atomic_read(&conn->r_count) > 0)
350-
schedule_timeout(HZ);
350+
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
351+
351352

352353
unload_nls(conn->local_nls);
353354
if (default_conn_ops.terminate_fn)

fs/ksmbd/connection.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,6 @@
2020

2121
#define KSMBD_SOCKET_BACKLOG 16
2222

23-
/*
24-
* WARNING
25-
*
26-
* This is nothing but a HACK. Session status should move to channel
27-
* or to session. As of now we have 1 tcp_conn : 1 ksmbd_session, but
28-
* we need to change it to 1 tcp_conn : N ksmbd_sessions.
29-
*/
3023
enum {
3124
KSMBD_SESS_NEW = 0,
3225
KSMBD_SESS_GOOD,
@@ -55,7 +48,7 @@ struct ksmbd_conn {
5548
struct nls_table *local_nls;
5649
struct list_head conns_list;
5750
/* smb session 1 per user */
58-
struct list_head sessions;
51+
struct xarray sessions;
5952
unsigned long last_active;
6053
/* How many request are running currently */
6154
atomic_t req_running;
@@ -65,6 +58,7 @@ struct ksmbd_conn {
6558
unsigned int outstanding_credits;
6659
spinlock_t credits_lock;
6760
wait_queue_head_t req_running_q;
61+
wait_queue_head_t r_count_q;
6862
/* Lock to protect requests list*/
6963
spinlock_t request_lock;
7064
struct list_head requests;

fs/ksmbd/mgmt/share_config.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,3 @@ bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
222222
}
223223
return false;
224224
}
225-
226-
void ksmbd_share_configs_cleanup(void)
227-
{
228-
struct ksmbd_share_config *share;
229-
struct hlist_node *tmp;
230-
int i;
231-
232-
down_write(&shares_table_lock);
233-
hash_for_each_safe(shares_table, i, tmp, share, hlist) {
234-
hash_del(&share->hlist);
235-
kill_share(share);
236-
}
237-
up_write(&shares_table_lock);
238-
}

fs/ksmbd/mgmt/share_config.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,4 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
7676
struct ksmbd_share_config *ksmbd_share_config_get(char *name);
7777
bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
7878
const char *filename);
79-
void ksmbd_share_configs_cleanup(void);
80-
8179
#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */

fs/ksmbd/mgmt/tree_connect.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
#include "user_session.h"
1717

1818
struct ksmbd_tree_conn_status
19-
ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name)
19+
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
20+
char *share_name)
2021
{
2122
struct ksmbd_tree_conn_status status = {-EINVAL, NULL};
2223
struct ksmbd_tree_connect_response *resp = NULL;
@@ -41,7 +42,7 @@ ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name)
4142
goto out_error;
4243
}
4344

44-
peer_addr = KSMBD_TCP_PEER_SOCKADDR(sess->conn);
45+
peer_addr = KSMBD_TCP_PEER_SOCKADDR(conn);
4546
resp = ksmbd_ipc_tree_connect_request(sess,
4647
sc,
4748
tree_conn,

fs/ksmbd/mgmt/tree_connect.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
struct ksmbd_share_config;
1414
struct ksmbd_user;
15+
struct ksmbd_conn;
1516

1617
struct ksmbd_tree_connect {
1718
int id;
@@ -40,7 +41,8 @@ static inline int test_tree_conn_flag(struct ksmbd_tree_connect *tree_conn,
4041
struct ksmbd_session;
4142

4243
struct ksmbd_tree_conn_status
43-
ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name);
44+
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
45+
char *share_name);
4446

4547
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
4648
struct ksmbd_tree_connect *tree_conn);

0 commit comments

Comments
 (0)