Three ksmbd smb3 server fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmimazEACgkQiiy9cAdy T1GHBwwAvWiPXvkA4MBZ1U649q/i2QsThCbEx1aLr4eZVeJkGD3Np3jBq3Pa6ciG 9S23jb1XasIb9+dX4Tz5MTCPGKIbzfOl4WOiMkkPz3/IZjqDIYn7AbUqdTziFjSt Eu2IHA2eDz+bm8VPxu2MdqWOfdKIE2L+mKYbDZWHdFd1rd6s72UHmAUFJlaEJAiT wP25g0+jS6sgi1B9AW3ADev1FjWSwBo5rHARjRIoUkDq61DbsuEQcsvLC1F4Ly+f 7T7OF3mtOMyzpM28A5LBbEJsjJJ1MXYed1xFGPKIYdghOElr3wJChkZ5QaaFMkFp VDOSgr69jCPtkGR5X+jGUAJENJvSqb77yAS38ACrcq/2+84XGKKO0cruq04HWCEG 7/T/4aH18ECySsMwWKn4GO+mffGu3ZQXG6L8wJPzA3tZBdZLk7m3jgwn6qsyIzB3 CBSHZ83eD/nngW0Muzxu0+prjGdYSkaM7sOrnxMa/NYd9cOLeFzVMxnmi4iDTLDr q9/QpwE2 =pxR5 -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
eb4a0992dd
|
|
@ -504,7 +504,8 @@ void ksmbd_conn_transport_destroy(void)
|
|||
{
|
||||
mutex_lock(&init_lock);
|
||||
ksmbd_tcp_destroy();
|
||||
ksmbd_rdma_destroy();
|
||||
ksmbd_rdma_stop_listening();
|
||||
stop_sessions();
|
||||
ksmbd_rdma_destroy();
|
||||
mutex_unlock(&init_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,12 @@ struct ksmbd_conn {
|
|||
struct mutex srv_mutex;
|
||||
int status;
|
||||
unsigned int cli_cap;
|
||||
__be32 inet_addr;
|
||||
union {
|
||||
__be32 inet_addr;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
u8 inet6_addr[16];
|
||||
#endif
|
||||
};
|
||||
char *request_buf;
|
||||
struct ksmbd_transport *transport;
|
||||
struct nls_table *local_nls;
|
||||
|
|
|
|||
|
|
@ -1102,8 +1102,10 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
|
|||
if (!atomic_inc_not_zero(&opinfo->refcount))
|
||||
continue;
|
||||
|
||||
if (ksmbd_conn_releasing(opinfo->conn))
|
||||
if (ksmbd_conn_releasing(opinfo->conn)) {
|
||||
opinfo_put(opinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
|
||||
opinfo_put(opinfo);
|
||||
|
|
@ -1139,8 +1141,11 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
|
|||
if (!atomic_inc_not_zero(&opinfo->refcount))
|
||||
continue;
|
||||
|
||||
if (ksmbd_conn_releasing(opinfo->conn))
|
||||
if (ksmbd_conn_releasing(opinfo->conn)) {
|
||||
opinfo_put(opinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
|
||||
opinfo_put(opinfo);
|
||||
}
|
||||
|
|
@ -1343,8 +1348,10 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||
if (!atomic_inc_not_zero(&brk_op->refcount))
|
||||
continue;
|
||||
|
||||
if (ksmbd_conn_releasing(brk_op->conn))
|
||||
if (ksmbd_conn_releasing(brk_op->conn)) {
|
||||
opinfo_put(brk_op);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (brk_op->is_lease && (brk_op->o_lease->state &
|
||||
(~(SMB2_LEASE_READ_CACHING_LE |
|
||||
|
|
|
|||
|
|
@ -2194,7 +2194,7 @@ int ksmbd_rdma_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ksmbd_rdma_destroy(void)
|
||||
void ksmbd_rdma_stop_listening(void)
|
||||
{
|
||||
if (!smb_direct_listener.cm_id)
|
||||
return;
|
||||
|
|
@ -2203,7 +2203,10 @@ void ksmbd_rdma_destroy(void)
|
|||
rdma_destroy_id(smb_direct_listener.cm_id);
|
||||
|
||||
smb_direct_listener.cm_id = NULL;
|
||||
}
|
||||
|
||||
void ksmbd_rdma_destroy(void)
|
||||
{
|
||||
if (smb_direct_wq) {
|
||||
destroy_workqueue(smb_direct_wq);
|
||||
smb_direct_wq = NULL;
|
||||
|
|
|
|||
|
|
@ -54,13 +54,15 @@ struct smb_direct_data_transfer {
|
|||
|
||||
#ifdef CONFIG_SMB_SERVER_SMBDIRECT
|
||||
int ksmbd_rdma_init(void);
|
||||
void ksmbd_rdma_stop_listening(void);
|
||||
void ksmbd_rdma_destroy(void);
|
||||
bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
|
||||
void init_smbd_max_io_size(unsigned int sz);
|
||||
unsigned int get_smbd_max_read_write_size(void);
|
||||
#else
|
||||
static inline int ksmbd_rdma_init(void) { return 0; }
|
||||
static inline int ksmbd_rdma_destroy(void) { return 0; }
|
||||
static inline void ksmbd_rdma_stop_listening(void) { }
|
||||
static inline void ksmbd_rdma_destroy(void) { }
|
||||
static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
|
||||
static inline void init_smbd_max_io_size(unsigned int sz) { }
|
||||
static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
|
||||
|
|
|
|||
|
|
@ -85,7 +85,14 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (client_sk->sk->sk_family == AF_INET6)
|
||||
memcpy(&conn->inet6_addr, &client_sk->sk->sk_v6_daddr, 16);
|
||||
else
|
||||
conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr;
|
||||
#else
|
||||
conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr;
|
||||
#endif
|
||||
conn->transport = KSMBD_TRANS(t);
|
||||
KSMBD_TRANS(t)->conn = conn;
|
||||
KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops;
|
||||
|
|
@ -229,7 +236,6 @@ static int ksmbd_kthread_fn(void *p)
|
|||
{
|
||||
struct socket *client_sk = NULL;
|
||||
struct interface *iface = (struct interface *)p;
|
||||
struct inet_sock *csk_inet;
|
||||
struct ksmbd_conn *conn;
|
||||
int ret;
|
||||
|
||||
|
|
@ -252,13 +258,27 @@ static int ksmbd_kthread_fn(void *p)
|
|||
/*
|
||||
* Limits repeated connections from clients with the same IP.
|
||||
*/
|
||||
csk_inet = inet_sk(client_sk->sk);
|
||||
down_read(&conn_list_lock);
|
||||
list_for_each_entry(conn, &conn_list, conns_list)
|
||||
if (csk_inet->inet_daddr == conn->inet_addr) {
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (client_sk->sk->sk_family == AF_INET6) {
|
||||
if (memcmp(&client_sk->sk->sk_v6_daddr,
|
||||
&conn->inet6_addr, 16) == 0) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
} else if (inet_sk(client_sk->sk)->inet_daddr ==
|
||||
conn->inet_addr) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (inet_sk(client_sk->sk)->inet_daddr ==
|
||||
conn->inet_addr) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
up_read(&conn_list_lock);
|
||||
if (ret == -EAGAIN)
|
||||
continue;
|
||||
|
|
|
|||
Loading…
Reference in New Issue