Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf: monitor use of splice to avoid kernel bug #16

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

jschwinger233
Copy link
Owner

@jschwinger233 jschwinger233 commented Apr 23, 2024

Background

由于内核 bug 导致 bpf_msg_redirect 和 splice 不能同时使用 (https://github.com/jschwinger233/bpf_msg_redirect_bug_reproducer) , daeuniverse#481 会导致 dae-0.6 和 glider 无法一起工作,因为 glider 会用 splice 来接收 TCP。

这个 PR 来解决上述问题。整体思路是建立 “快速 TCP 白名单,对于白名单上的进程允许使用 sockmap + msg_redirect 直连,反之使用传统的内核网络栈”。白名单是一个 bpf map, key 是进程名 task->comm 。一个进程必须完成一次 TCP 会话,在会话结束的时候检查这个进程有没有调用过 splice syscall,如果有调用过就标记 allow=0,反之 allow=1。

具体来说,考虑 curl 1.1.1.2:80 被 WAN 劫持给 dae 这个场景:

  1. curl 第一次 TCP 会话建立的时候,由于白名单里没有 curl 进程的记录,会触发一次探测,代码里会调用 bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG); , 从而在这次 TCP 会话状态变化的时候会被回调。只有一个进程的第一次 TCP 会话会走这个探测流程,第二次就不会了,因为第二次直接查询名名单,无论 allow/!allow 都有记录。
  2. curl 的第一次 TCP 会话会走正常的网络栈,curl -> wan0(egress) -> dae0(egress) -> dae0peer -> dae。
  3. curl 的第一次 TCP 会话结束的时候,触发回调,代码里判断这次会话是否调用 splice: called = bpf_map_lookup_elem(&splice_called_map, &pid) ,然后把记录写入白名单。
  4. 之后 curl 发起第二次 TCP 会话(不一定是同一进程,只要进程名 task->comm 相同就行),在 TCP established 的时候检查白名单,发现有记录,如果 allow 就走快速 TCP 通道, !allow 就继续走内核网络栈。

如果是 glider 进程走上述流程,会在第一次 TCP 会话发起 splice 探测的时候发现 splice called,从而白名单里标记 allow=0,不走快速 TCP 就万事大吉。

Requirements

由于需要探测是否调用 splice syscall,需要使用 syscall tracepoint,所以要求内核有编译配置 CONFIG_HAVE_SYSCALL_TRACEPOINTS=y。(因为不会有太大问题,吧?)

这个 PR 本质是内核 bug 的临时 workaround,我已经把 bug 上报给内核社区并引起了注意,等未来修复 bug 并且 backport 到了 LTS (6.6, 6.1, 5.15, 5.10) 之后,我们可以考虑再删除这些临时措施。

Checklist

Full Changelogs

  • [Implement ...]

Issue Reference

Closes #[issue number]

Test Result

@jschwinger233 jschwinger233 force-pushed the pr/gray/fast-sock-fix branch 2 times, most recently from 646e9e4 to 40b9609 Compare April 25, 2024 18:42
@jschwinger233 jschwinger233 force-pushed the pr/gray/fast-sock-fix branch from 40b9609 to 29f3f50 Compare April 25, 2024 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant