Skip to content

Commit e991558

Browse files
wangyufen316gregkh
authored andcommitted
bpf, sockmap: Fix sk->sk_forward_alloc warn_on in sk_stream_kill_queues
[ Upstream commit d8616ee ] During TCP sockmap redirect pressure test, the following warning is triggered: WARNING: CPU: 3 PID: 2145 at net/core/stream.c:205 sk_stream_kill_queues+0xbc/0xd0 CPU: 3 PID: 2145 Comm: iperf Kdump: loaded Tainted: G W 5.10.0+ #9 Call Trace: inet_csk_destroy_sock+0x55/0x110 inet_csk_listen_stop+0xbb/0x380 tcp_close+0x41b/0x480 inet_release+0x42/0x80 __sock_release+0x3d/0xa0 sock_close+0x11/0x20 __fput+0x9d/0x240 task_work_run+0x62/0x90 exit_to_user_mode_prepare+0x110/0x120 syscall_exit_to_user_mode+0x27/0x190 entry_SYSCALL_64_after_hwframe+0x44/0xa9 The reason we observed is that: When the listener is closing, a connection may have completed the three-way handshake but not accepted, and the client has sent some packets. The child sks in accept queue release by inet_child_forget()->inet_csk_destroy_sock(), but psocks of child sks have not released. To fix, add sock_map_destroy to release psocks. Signed-off-by: Wang Yufen <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Jakub Sitnicki <[email protected]> Acked-by: John Fastabend <[email protected]> Link: https://lore.kernel.org/bpf/[email protected] Stable-dep-of: 8bbabb3 ("bpf, sock_map: Move cancel_work_sync() out of sock lock") Signed-off-by: Sasha Levin <[email protected]>
1 parent 5ad95d7 commit e991558

File tree

5 files changed

+27
-0
lines changed

5 files changed

+27
-0
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,7 @@ int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
20222022
int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);
20232023
int sock_map_update_elem_sys(struct bpf_map *map, void *key, void *value, u64 flags);
20242024
void sock_map_unhash(struct sock *sk);
2025+
void sock_map_destroy(struct sock *sk);
20252026
void sock_map_close(struct sock *sk, long timeout);
20262027
#else
20272028
static inline int bpf_prog_offload_init(struct bpf_prog *prog,

include/linux/skmsg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct sk_psock {
9696
spinlock_t link_lock;
9797
refcount_t refcnt;
9898
void (*saved_unhash)(struct sock *sk);
99+
void (*saved_destroy)(struct sock *sk);
99100
void (*saved_close)(struct sock *sk, long timeout);
100101
void (*saved_write_space)(struct sock *sk);
101102
void (*saved_data_ready)(struct sock *sk);

net/core/skmsg.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)
720720
psock->eval = __SK_NONE;
721721
psock->sk_proto = prot;
722722
psock->saved_unhash = prot->unhash;
723+
psock->saved_destroy = prot->destroy;
723724
psock->saved_close = prot->close;
724725
psock->saved_write_space = sk->sk_write_space;
725726

net/core/sock_map.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,29 @@ void sock_map_unhash(struct sock *sk)
15241524
}
15251525
EXPORT_SYMBOL_GPL(sock_map_unhash);
15261526

1527+
void sock_map_destroy(struct sock *sk)
1528+
{
1529+
void (*saved_destroy)(struct sock *sk);
1530+
struct sk_psock *psock;
1531+
1532+
rcu_read_lock();
1533+
psock = sk_psock_get(sk);
1534+
if (unlikely(!psock)) {
1535+
rcu_read_unlock();
1536+
if (sk->sk_prot->destroy)
1537+
sk->sk_prot->destroy(sk);
1538+
return;
1539+
}
1540+
1541+
saved_destroy = psock->saved_destroy;
1542+
sock_map_remove_links(sk, psock);
1543+
rcu_read_unlock();
1544+
sk_psock_stop(psock, true);
1545+
sk_psock_put(sk, psock);
1546+
saved_destroy(sk);
1547+
}
1548+
EXPORT_SYMBOL_GPL(sock_map_destroy);
1549+
15271550
void sock_map_close(struct sock *sk, long timeout)
15281551
{
15291552
void (*saved_close)(struct sock *sk, long timeout);

net/ipv4/tcp_bpf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],
543543
struct proto *base)
544544
{
545545
prot[TCP_BPF_BASE] = *base;
546+
prot[TCP_BPF_BASE].destroy = sock_map_destroy;
546547
prot[TCP_BPF_BASE].close = sock_map_close;
547548
prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg;
548549
prot[TCP_BPF_BASE].sock_is_readable = sk_msg_is_readable;

0 commit comments

Comments
 (0)