Skip to content

Commit 109daa2

Browse files
committed
Merge tag '6.13-rc-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server updates from Steve French: - fix use after free due to race in ksmd workqueue handler - debugging improvements - fix incorrectly formatted response when client attempts SMB1 - improve memory allocation to reduce chance of OOM - improve delays between retries when killing sessions * tag '6.13-rc-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: fix use-after-free in SMB request handling ksmbd: add debug print for pending request during server shutdown ksmbd: add netdev-up/down event debug print ksmbd: add debug prints to know what smb2 requests were received ksmbd: add debug print for rdma capable ksmbd: use msleep instaed of schedule_timeout_interruptible() ksmbd: use __GFP_RETRY_MAYFAIL ksmbd: fix malformed unsupported smb1 negotiate response
2 parents d8b7806 + 9a8c5d8 commit 109daa2

24 files changed

+171
-130
lines changed

fs/smb/server/asn1.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
104104
oid_len + ntlmssp_len) * 2 +
105105
neg_result_len + oid_len + ntlmssp_len;
106106

107-
buf = kmalloc(total_len, GFP_KERNEL);
107+
buf = kmalloc(total_len, KSMBD_DEFAULT_GFP);
108108
if (!buf)
109109
return -ENOMEM;
110110

@@ -140,7 +140,7 @@ int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
140140
int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
141141
neg_result_len;
142142

143-
buf = kmalloc(total_len, GFP_KERNEL);
143+
buf = kmalloc(total_len, KSMBD_DEFAULT_GFP);
144144
if (!buf)
145145
return -ENOMEM;
146146

@@ -217,7 +217,7 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
217217
if (!vlen)
218218
return -EINVAL;
219219

220-
conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL);
220+
conn->mechToken = kmemdup_nul(value, vlen, KSMBD_DEFAULT_GFP);
221221
if (!conn->mechToken)
222222
return -ENOMEM;
223223

fs/smb/server/auth.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
151151

152152
/* convert user_name to unicode */
153153
len = strlen(user_name(sess->user));
154-
uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
154+
uniname = kzalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
155155
if (!uniname) {
156156
ret = -ENOMEM;
157157
goto out;
@@ -175,7 +175,7 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
175175

176176
/* Convert domain name or conn name to unicode and uppercase */
177177
len = strlen(dname);
178-
domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
178+
domain = kzalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
179179
if (!domain) {
180180
ret = -ENOMEM;
181181
goto out;
@@ -254,7 +254,7 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
254254
}
255255

256256
len = CIFS_CRYPTO_KEY_SIZE + blen;
257-
construct = kzalloc(len, GFP_KERNEL);
257+
construct = kzalloc(len, KSMBD_DEFAULT_GFP);
258258
if (!construct) {
259259
rc = -ENOMEM;
260260
goto out;
@@ -361,7 +361,7 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
361361
if (sess_key_len > CIFS_KEY_SIZE)
362362
return -EINVAL;
363363

364-
ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
364+
ctx_arc4 = kmalloc(sizeof(*ctx_arc4), KSMBD_DEFAULT_GFP);
365365
if (!ctx_arc4)
366366
return -ENOMEM;
367367

@@ -451,7 +451,7 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
451451

452452
chgblob->NegotiateFlags = cpu_to_le32(flags);
453453
len = strlen(ksmbd_netbios_name());
454-
name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
454+
name = kmalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
455455
if (!name)
456456
return -ENOMEM;
457457

@@ -1043,7 +1043,7 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
10431043
if (!nvec)
10441044
return NULL;
10451045

1046-
nr_entries = kcalloc(nvec, sizeof(int), GFP_KERNEL);
1046+
nr_entries = kcalloc(nvec, sizeof(int), KSMBD_DEFAULT_GFP);
10471047
if (!nr_entries)
10481048
return NULL;
10491049

@@ -1063,7 +1063,8 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
10631063
/* Add two entries for transform header and signature */
10641064
total_entries += 2;
10651065

1066-
sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
1066+
sg = kmalloc_array(total_entries, sizeof(struct scatterlist),
1067+
KSMBD_DEFAULT_GFP);
10671068
if (!sg) {
10681069
kfree(nr_entries);
10691070
return NULL;
@@ -1163,7 +1164,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
11631164
goto free_ctx;
11641165
}
11651166

1166-
req = aead_request_alloc(tfm, GFP_KERNEL);
1167+
req = aead_request_alloc(tfm, KSMBD_DEFAULT_GFP);
11671168
if (!req) {
11681169
rc = -ENOMEM;
11691170
goto free_ctx;
@@ -1182,7 +1183,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
11821183
}
11831184

11841185
iv_len = crypto_aead_ivsize(tfm);
1185-
iv = kzalloc(iv_len, GFP_KERNEL);
1186+
iv = kzalloc(iv_len, KSMBD_DEFAULT_GFP);
11861187
if (!iv) {
11871188
rc = -ENOMEM;
11881189
goto free_sg;

fs/smb/server/connection.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
5252
{
5353
struct ksmbd_conn *conn;
5454

55-
conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);
55+
conn = kzalloc(sizeof(struct ksmbd_conn), KSMBD_DEFAULT_GFP);
5656
if (!conn)
5757
return NULL;
5858

@@ -359,7 +359,7 @@ int ksmbd_conn_handler_loop(void *p)
359359
/* 4 for rfc1002 length field */
360360
/* 1 for implied bcc[0] */
361361
size = pdu_size + 4 + 1;
362-
conn->request_buf = kvmalloc(size, GFP_KERNEL);
362+
conn->request_buf = kvmalloc(size, KSMBD_DEFAULT_GFP);
363363
if (!conn->request_buf)
364364
break;
365365

@@ -404,6 +404,7 @@ int ksmbd_conn_handler_loop(void *p)
404404
out:
405405
ksmbd_conn_set_releasing(conn);
406406
/* Wait till all reference dropped to the Server object*/
407+
ksmbd_debug(CONN, "Wait for all pending requests(%d)\n", atomic_read(&conn->r_count));
407408
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
408409

409410
if (IS_ENABLED(CONFIG_UNICODE))
@@ -462,7 +463,7 @@ static void stop_sessions(void)
462463
up_read(&conn_list_lock);
463464

464465
if (!list_empty(&conn_list)) {
465-
schedule_timeout_interruptible(HZ / 10); /* 100ms */
466+
msleep(100);
466467
goto again;
467468
}
468469
}

fs/smb/server/crypto_ctx.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static struct shash_desc *alloc_shash_desc(int id)
8989
return NULL;
9090

9191
shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
92-
GFP_KERNEL);
92+
KSMBD_DEFAULT_GFP);
9393
if (!shash)
9494
crypto_free_shash(tfm);
9595
else
@@ -133,7 +133,7 @@ static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
133133
ctx_list.avail_ctx++;
134134
spin_unlock(&ctx_list.ctx_lock);
135135

136-
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
136+
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), KSMBD_DEFAULT_GFP);
137137
if (!ctx) {
138138
spin_lock(&ctx_list.ctx_lock);
139139
ctx_list.avail_ctx--;
@@ -258,7 +258,7 @@ int ksmbd_crypto_create(void)
258258
init_waitqueue_head(&ctx_list.ctx_wait);
259259
ctx_list.avail_ctx = 1;
260260

261-
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
261+
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), KSMBD_DEFAULT_GFP);
262262
if (!ctx)
263263
return -ENOMEM;
264264
list_add(&ctx->list, &ctx_list.idle_ctx);

fs/smb/server/glob.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,6 @@ extern int ksmbd_debug_types;
4444

4545
#define UNICODE_LEN(x) ((x) * 2)
4646

47+
#define KSMBD_DEFAULT_GFP (GFP_KERNEL | __GFP_RETRY_MAYFAIL)
48+
4749
#endif /* __KSMBD_GLOB_H */

fs/smb/server/ksmbd_work.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ static struct workqueue_struct *ksmbd_wq;
1818

1919
struct ksmbd_work *ksmbd_alloc_work_struct(void)
2020
{
21-
struct ksmbd_work *work = kmem_cache_zalloc(work_cache, GFP_KERNEL);
21+
struct ksmbd_work *work = kmem_cache_zalloc(work_cache, KSMBD_DEFAULT_GFP);
2222

2323
if (work) {
2424
work->compound_fid = KSMBD_NO_FID;
@@ -30,7 +30,7 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void)
3030
INIT_LIST_HEAD(&work->aux_read_list);
3131
work->iov_alloc_cnt = 4;
3232
work->iov = kcalloc(work->iov_alloc_cnt, sizeof(struct kvec),
33-
GFP_KERNEL);
33+
KSMBD_DEFAULT_GFP);
3434
if (!work->iov) {
3535
kmem_cache_free(work_cache, work);
3636
work = NULL;
@@ -114,7 +114,7 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
114114

115115
if (aux_size) {
116116
need_iov_cnt++;
117-
ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
117+
ar = kmalloc(sizeof(struct aux_read), KSMBD_DEFAULT_GFP);
118118
if (!ar)
119119
return -ENOMEM;
120120
}
@@ -125,7 +125,7 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
125125
work->iov_alloc_cnt += 4;
126126
new = krealloc(work->iov,
127127
sizeof(struct kvec) * work->iov_alloc_cnt,
128-
GFP_KERNEL | __GFP_ZERO);
128+
KSMBD_DEFAULT_GFP | __GFP_ZERO);
129129
if (!new) {
130130
kfree(ar);
131131
work->iov_alloc_cnt -= 4;
@@ -169,7 +169,7 @@ int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
169169

170170
int allocate_interim_rsp_buf(struct ksmbd_work *work)
171171
{
172-
work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
172+
work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, KSMBD_DEFAULT_GFP);
173173
if (!work->response_buf)
174174
return -ENOMEM;
175175
work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;

fs/smb/server/mgmt/ksmbd_ida.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,32 @@
44
*/
55

66
#include "ksmbd_ida.h"
7+
#include "../glob.h"
78

89
int ksmbd_acquire_smb2_tid(struct ida *ida)
910
{
10-
return ida_alloc_range(ida, 1, 0xFFFFFFFE, GFP_KERNEL);
11+
return ida_alloc_range(ida, 1, 0xFFFFFFFE, KSMBD_DEFAULT_GFP);
1112
}
1213

1314
int ksmbd_acquire_smb2_uid(struct ida *ida)
1415
{
1516
int id;
1617

17-
id = ida_alloc_min(ida, 1, GFP_KERNEL);
18+
id = ida_alloc_min(ida, 1, KSMBD_DEFAULT_GFP);
1819
if (id == 0xFFFE)
19-
id = ida_alloc_min(ida, 1, GFP_KERNEL);
20+
id = ida_alloc_min(ida, 1, KSMBD_DEFAULT_GFP);
2021

2122
return id;
2223
}
2324

2425
int ksmbd_acquire_async_msg_id(struct ida *ida)
2526
{
26-
return ida_alloc_min(ida, 1, GFP_KERNEL);
27+
return ida_alloc_min(ida, 1, KSMBD_DEFAULT_GFP);
2728
}
2829

2930
int ksmbd_acquire_id(struct ida *ida)
3031
{
31-
return ida_alloc(ida, GFP_KERNEL);
32+
return ida_alloc(ida, KSMBD_DEFAULT_GFP);
3233
}
3334

3435
void ksmbd_release_id(struct ida *ida, int id)

fs/smb/server/mgmt/share_config.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ static int parse_veto_list(struct ksmbd_share_config *share,
102102
if (!sz)
103103
break;
104104

105-
p = kzalloc(sizeof(struct ksmbd_veto_pattern), GFP_KERNEL);
105+
p = kzalloc(sizeof(struct ksmbd_veto_pattern), KSMBD_DEFAULT_GFP);
106106
if (!p)
107107
return -ENOMEM;
108108

109-
p->pattern = kstrdup(veto_list, GFP_KERNEL);
109+
p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
110110
if (!p->pattern) {
111111
kfree(p);
112112
return -ENOMEM;
@@ -150,14 +150,14 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
150150
goto out;
151151
}
152152

153-
share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
153+
share = kzalloc(sizeof(struct ksmbd_share_config), KSMBD_DEFAULT_GFP);
154154
if (!share)
155155
goto out;
156156

157157
share->flags = resp->flags;
158158
atomic_set(&share->refcount, 1);
159159
INIT_LIST_HEAD(&share->veto_list);
160-
share->name = kstrdup(name, GFP_KERNEL);
160+
share->name = kstrdup(name, KSMBD_DEFAULT_GFP);
161161

162162
if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
163163
int path_len = PATH_MAX;
@@ -166,7 +166,7 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
166166
path_len = resp->payload_sz - resp->veto_list_sz;
167167

168168
share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
169-
GFP_KERNEL);
169+
KSMBD_DEFAULT_GFP);
170170
if (share->path) {
171171
share->path_sz = strlen(share->path);
172172
while (share->path_sz > 1 &&

fs/smb/server/mgmt/tree_connect.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
3131
if (!sc)
3232
return status;
3333

34-
tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect), GFP_KERNEL);
34+
tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect),
35+
KSMBD_DEFAULT_GFP);
3536
if (!tree_conn) {
3637
status.ret = -ENOMEM;
3738
goto out_error;
@@ -80,7 +81,7 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
8081
init_waitqueue_head(&tree_conn->refcount_q);
8182

8283
ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
83-
GFP_KERNEL));
84+
KSMBD_DEFAULT_GFP));
8485
if (ret) {
8586
status.ret = -ENOMEM;
8687
goto out_error;

fs/smb/server/mgmt/user_config.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp,
3636
{
3737
struct ksmbd_user *user;
3838

39-
user = kmalloc(sizeof(struct ksmbd_user), GFP_KERNEL);
39+
user = kmalloc(sizeof(struct ksmbd_user), KSMBD_DEFAULT_GFP);
4040
if (!user)
4141
return NULL;
4242

43-
user->name = kstrdup(resp->account, GFP_KERNEL);
43+
user->name = kstrdup(resp->account, KSMBD_DEFAULT_GFP);
4444
user->flags = resp->status;
4545
user->gid = resp->gid;
4646
user->uid = resp->uid;
4747
user->passkey_sz = resp->hash_sz;
48-
user->passkey = kmalloc(resp->hash_sz, GFP_KERNEL);
48+
user->passkey = kmalloc(resp->hash_sz, KSMBD_DEFAULT_GFP);
4949
if (user->passkey)
5050
memcpy(user->passkey, resp->hash, resp->hash_sz);
5151

@@ -64,7 +64,7 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp,
6464

6565
user->sgid = kmemdup(resp_ext->____payload,
6666
resp_ext->ngroups * sizeof(gid_t),
67-
GFP_KERNEL);
67+
KSMBD_DEFAULT_GFP);
6868
if (!user->sgid)
6969
goto err_free;
7070

0 commit comments

Comments
 (0)