Skip to content

Commit 9d7cce9

Browse files
wangyufen316Nobody
authored andcommitted
bpf, sockmap: Add sk_rmem_alloc check for tcp_bpf_ingress()
We use sk_msg to redirect with sock hash, like this: skA redirect skB Tx <-----------> Rx And construct a scenario where the packet sending speed is high, the packet receiving speed is slow, so the packets are stacked in the ingress queue on the receiving side. After a period of time, the memory is exhausted and the system ooms. To fix, we add sk_rmem_alloc while sk_msg queued in the ingress queue and subtract sk_rmem_alloc while sk_msg dequeued from the ingress queue and check sk_rmem_alloc at the beginning of bpf_tcp_ingress(). Signed-off-by: Wang Yufen <wangyufen@huawei.com>
1 parent 0490a19 commit 9d7cce9

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

include/linux/skmsg.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,10 @@ static inline void sk_psock_queue_msg(struct sk_psock *psock,
308308
struct sk_msg *msg)
309309
{
310310
spin_lock_bh(&psock->ingress_lock);
311-
if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
311+
if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
312312
list_add_tail(&msg->list, &psock->ingress_msg);
313-
else {
313+
atomic_add(msg->sg.size, &psock->sk->sk_rmem_alloc);
314+
} else {
314315
sk_msg_free(psock->sk, msg);
315316
kfree(msg);
316317
}
@@ -323,8 +324,10 @@ static inline struct sk_msg *sk_psock_dequeue_msg(struct sk_psock *psock)
323324

324325
spin_lock_bh(&psock->ingress_lock);
325326
msg = list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list);
326-
if (msg)
327+
if (msg) {
327328
list_del(&msg->list);
329+
atomic_sub(msg->sg.size, &psock->sk->sk_rmem_alloc);
330+
}
328331
spin_unlock_bh(&psock->ingress_lock);
329332
return msg;
330333
}

net/core/skmsg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
445445
if (!msg_rx->skb)
446446
sk_mem_uncharge(sk, copy);
447447
msg_rx->sg.size -= copy;
448+
atomic_sub(copy, &sk->sk_rmem_alloc);
448449

449450
if (!sge->length) {
450451
sk_msg_iter_var_next(i);
@@ -754,6 +755,7 @@ static void __sk_psock_purge_ingress_msg(struct sk_psock *psock)
754755

755756
list_for_each_entry_safe(msg, tmp, &psock->ingress_msg, list) {
756757
list_del(&msg->list);
758+
atomic_sub(msg->sg.size, &psock->sk->sk_rmem_alloc);
757759
sk_msg_free(psock->sk, msg);
758760
kfree(msg);
759761
}

net/ipv4/tcp_bpf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
2424
return -ENOMEM;
2525

2626
lock_sock(sk);
27+
if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) {
28+
release_sock(sk);
29+
kfree(tmp);
30+
return -EAGAIN;
31+
}
32+
2733
tmp->sg.start = msg->sg.start;
2834
i = msg->sg.start;
2935
do {

0 commit comments

Comments
 (0)