Skip to content

Commit 9c34e38

Browse files
wangyufen316borkmann
authored andcommitted
bpf, sockmap: Fix memleak in tcp_bpf_sendmsg while sk msg is full
If tcp_bpf_sendmsg() is running while sk msg is full. When sk_msg_alloc() returns -ENOMEM error, tcp_bpf_sendmsg() goes to wait_for_memory. If partial memory has been alloced by sk_msg_alloc(), that is, msg_tx->sg.size is greater than osize after sk_msg_alloc(), memleak occurs. To fix we use sk_msg_trim() to release the allocated memory, then goto wait for memory. Other call paths of sk_msg_alloc() have the similar issue, such as tls_sw_sendmsg(), so handle sk_msg_trim logic inside sk_msg_alloc(), as Cong Wang suggested. This issue can cause the following info: WARNING: CPU: 3 PID: 7950 at net/core/stream.c:208 sk_stream_kill_queues+0xd4/0x1a0 Call Trace: <TASK> inet_csk_destroy_sock+0x55/0x110 __tcp_close+0x279/0x470 tcp_close+0x1f/0x60 inet_release+0x3f/0x80 __sock_release+0x3d/0xb0 sock_close+0x11/0x20 __fput+0x92/0x250 task_work_run+0x6a/0xa0 do_exit+0x33b/0xb60 do_group_exit+0x2f/0xa0 get_signal+0xb6/0x950 arch_do_signal_or_restart+0xac/0x2a0 exit_to_user_mode_prepare+0xa9/0x200 syscall_exit_to_user_mode+0x12/0x30 do_syscall_64+0x46/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae </TASK> WARNING: CPU: 3 PID: 2094 at net/ipv4/af_inet.c:155 inet_sock_destruct+0x13c/0x260 Call Trace: <TASK> __sk_destruct+0x24/0x1f0 sk_psock_destroy+0x19b/0x1c0 process_one_work+0x1b3/0x3c0 kthread+0xe6/0x110 ret_from_fork+0x22/0x30 </TASK> Fixes: 604326b ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: Wang Yufen <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: John Fastabend <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 938d348 commit 9c34e38

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

net/core/skmsg.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
2727
int elem_first_coalesce)
2828
{
2929
struct page_frag *pfrag = sk_page_frag(sk);
30+
u32 osize = msg->sg.size;
3031
int ret = 0;
3132

3233
len -= msg->sg.size;
@@ -35,13 +36,17 @@ int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
3536
u32 orig_offset;
3637
int use, i;
3738

38-
if (!sk_page_frag_refill(sk, pfrag))
39-
return -ENOMEM;
39+
if (!sk_page_frag_refill(sk, pfrag)) {
40+
ret = -ENOMEM;
41+
goto msg_trim;
42+
}
4043

4144
orig_offset = pfrag->offset;
4245
use = min_t(int, len, pfrag->size - orig_offset);
43-
if (!sk_wmem_schedule(sk, use))
44-
return -ENOMEM;
46+
if (!sk_wmem_schedule(sk, use)) {
47+
ret = -ENOMEM;
48+
goto msg_trim;
49+
}
4550

4651
i = msg->sg.end;
4752
sk_msg_iter_var_prev(i);
@@ -71,6 +76,10 @@ int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
7176
}
7277

7378
return ret;
79+
80+
msg_trim:
81+
sk_msg_trim(sk, msg, osize);
82+
return ret;
7483
}
7584
EXPORT_SYMBOL_GPL(sk_msg_alloc);
7685

0 commit comments

Comments
 (0)