Skip to content

Commit eb4a099

Browse files
committed
Merge tag '6.17-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - fix refcount issue that can cause memory leak - rate limit repeated connections from IPv6, not just IPv4 addresses - fix potential null pointer access of smb direct work queue * tag '6.17-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: fix refcount leak causing resource not released ksmbd: extend the connection limiting mechanism to support IPv6 smb: server: split ksmbd_rdma_stop_listening() out of ksmbd_rdma_destroy()
2 parents 068a56e + 89bb430 commit eb4a099

File tree

6 files changed

+48
-10
lines changed

6 files changed

+48
-10
lines changed

fs/smb/server/connection.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ void ksmbd_conn_transport_destroy(void)
504504
{
505505
mutex_lock(&init_lock);
506506
ksmbd_tcp_destroy();
507-
ksmbd_rdma_destroy();
507+
ksmbd_rdma_stop_listening();
508508
stop_sessions();
509+
ksmbd_rdma_destroy();
509510
mutex_unlock(&init_lock);
510511
}

fs/smb/server/connection.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ struct ksmbd_conn {
4646
struct mutex srv_mutex;
4747
int status;
4848
unsigned int cli_cap;
49-
__be32 inet_addr;
49+
union {
50+
__be32 inet_addr;
51+
#if IS_ENABLED(CONFIG_IPV6)
52+
u8 inet6_addr[16];
53+
#endif
54+
};
5055
char *request_buf;
5156
struct ksmbd_transport *transport;
5257
struct nls_table *local_nls;

fs/smb/server/oplock.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,8 +1102,10 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
11021102
if (!atomic_inc_not_zero(&opinfo->refcount))
11031103
continue;
11041104

1105-
if (ksmbd_conn_releasing(opinfo->conn))
1105+
if (ksmbd_conn_releasing(opinfo->conn)) {
1106+
opinfo_put(opinfo);
11061107
continue;
1108+
}
11071109

11081110
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
11091111
opinfo_put(opinfo);
@@ -1139,8 +1141,11 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
11391141
if (!atomic_inc_not_zero(&opinfo->refcount))
11401142
continue;
11411143

1142-
if (ksmbd_conn_releasing(opinfo->conn))
1144+
if (ksmbd_conn_releasing(opinfo->conn)) {
1145+
opinfo_put(opinfo);
11431146
continue;
1147+
}
1148+
11441149
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
11451150
opinfo_put(opinfo);
11461151
}
@@ -1343,8 +1348,10 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
13431348
if (!atomic_inc_not_zero(&brk_op->refcount))
13441349
continue;
13451350

1346-
if (ksmbd_conn_releasing(brk_op->conn))
1351+
if (ksmbd_conn_releasing(brk_op->conn)) {
1352+
opinfo_put(brk_op);
13471353
continue;
1354+
}
13481355

13491356
if (brk_op->is_lease && (brk_op->o_lease->state &
13501357
(~(SMB2_LEASE_READ_CACHING_LE |

fs/smb/server/transport_rdma.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2194,7 +2194,7 @@ int ksmbd_rdma_init(void)
21942194
return 0;
21952195
}
21962196

2197-
void ksmbd_rdma_destroy(void)
2197+
void ksmbd_rdma_stop_listening(void)
21982198
{
21992199
if (!smb_direct_listener.cm_id)
22002200
return;
@@ -2203,7 +2203,10 @@ void ksmbd_rdma_destroy(void)
22032203
rdma_destroy_id(smb_direct_listener.cm_id);
22042204

22052205
smb_direct_listener.cm_id = NULL;
2206+
}
22062207

2208+
void ksmbd_rdma_destroy(void)
2209+
{
22072210
if (smb_direct_wq) {
22082211
destroy_workqueue(smb_direct_wq);
22092212
smb_direct_wq = NULL;

fs/smb/server/transport_rdma.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,15 @@ struct smb_direct_data_transfer {
5454

5555
#ifdef CONFIG_SMB_SERVER_SMBDIRECT
5656
int ksmbd_rdma_init(void);
57+
void ksmbd_rdma_stop_listening(void);
5758
void ksmbd_rdma_destroy(void);
5859
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
5960
void init_smbd_max_io_size(unsigned int sz);
6061
unsigned int get_smbd_max_read_write_size(void);
6162
#else
6263
static inline int ksmbd_rdma_init(void) { return 0; }
63-
static inline int ksmbd_rdma_destroy(void) { return 0; }
64+
static inline void ksmbd_rdma_stop_listening(void) { }
65+
static inline void ksmbd_rdma_destroy(void) { }
6466
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
6567
static inline void init_smbd_max_io_size(unsigned int sz) { }
6668
static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }

fs/smb/server/transport_tcp.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,14 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
8585
return NULL;
8686
}
8787

88+
#if IS_ENABLED(CONFIG_IPV6)
89+
if (client_sk->sk->sk_family == AF_INET6)
90+
memcpy(&conn->inet6_addr, &client_sk->sk->sk_v6_daddr, 16);
91+
else
92+
conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr;
93+
#else
8894
conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr;
95+
#endif
8996
conn->transport = KSMBD_TRANS(t);
9097
KSMBD_TRANS(t)->conn = conn;
9198
KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops;
@@ -229,7 +236,6 @@ static int ksmbd_kthread_fn(void *p)
229236
{
230237
struct socket *client_sk = NULL;
231238
struct interface *iface = (struct interface *)p;
232-
struct inet_sock *csk_inet;
233239
struct ksmbd_conn *conn;
234240
int ret;
235241

@@ -252,13 +258,27 @@ static int ksmbd_kthread_fn(void *p)
252258
/*
253259
* Limits repeated connections from clients with the same IP.
254260
*/
255-
csk_inet = inet_sk(client_sk->sk);
256261
down_read(&conn_list_lock);
257262
list_for_each_entry(conn, &conn_list, conns_list)
258-
if (csk_inet->inet_daddr == conn->inet_addr) {
263+
#if IS_ENABLED(CONFIG_IPV6)
264+
if (client_sk->sk->sk_family == AF_INET6) {
265+
if (memcmp(&client_sk->sk->sk_v6_daddr,
266+
&conn->inet6_addr, 16) == 0) {
267+
ret = -EAGAIN;
268+
break;
269+
}
270+
} else if (inet_sk(client_sk->sk)->inet_daddr ==
271+
conn->inet_addr) {
272+
ret = -EAGAIN;
273+
break;
274+
}
275+
#else
276+
if (inet_sk(client_sk->sk)->inet_daddr ==
277+
conn->inet_addr) {
259278
ret = -EAGAIN;
260279
break;
261280
}
281+
#endif
262282
up_read(&conn_list_lock);
263283
if (ret == -EAGAIN)
264284
continue;

0 commit comments

Comments
 (0)