apache / apache/brpc

uretprobe会触发brpc服务SIGILL

Open
#2,486 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
17.6k
Forks
4.1k
Avg merge
2d 12h
Merged PRs (30d)
69

Description

**Describe the bug (描述bug)**
用bcc工具[funclatency](https://github.com/iovisor/bcc/blob/master/tools/funclatency.py)观察服务里某个函数的耗时时,发现会触发服务SIGILL信号,导致服务异常退出,且稳定复现。
该工具观察函数耗时是通过[uprobe/uretprobe](https://docs.kernel.org/trace/kprobes.html)来实现的,其中uretprobe会**修改栈上的函数返回地址**,所以怀疑跟bthread用户态切换栈有关。

Go服务也存在类似问题[issue](https://github.com/iovisor/bcc/issues/1320#issuecomment-325149456),是因为Go服务会对栈进行扩缩容等操作导致栈内存移动,但是bthread的栈内存应该不会有扩缩容等移动栈内存的操作。

**To Reproduce (复现方法)**
参照[funclatency_example](https://github.com/iovisor/bcc/blob/master/tools/funclatency_example.txt)观察brpc服务的用户态函数耗时就可以触发。或者使用其他依赖uretprobe的工具。

**Expected behavior (期望行为)**
期望brpc服务可以正常使用uretprobe/kretprobe

**Versions (各种版本)**
OS: centos7
Compiler: gcc7.3
brpc:
protobuf:

**Additional context/screenshots (更多上下文/截图)**
服务报SIGILL的现场:
![image](https://github.com/apache/brpc/assets/6281497/5c5ec599-3027-4659-8bb2-7ee819cfc2e5)

进程的内存分布 (cat /proc/pid/maps | grep uprobes)
uprobes的内存块首地址,也就是uprobes桩函数的首地址,是 0x00007fffffffe000,**非法指令的地址正好是它的后一字节!**
![image](https://github.com/apache/brpc/assets/6281497/237a4cce-d9e2-40d4-a761-dd5a08666012)

现场描述:
1. 服务执行到0x00007fffffffe001地址时遇到非法指令,该地址应该是压在栈上的函数返回地址,且是被uretprobe修改过的。
2. 正常uprobes会在进入函数时,就把函数返回地址修改为uprobes内存块的首地址0x00007fffffffe000,而且通过gdb观察栈内存,在进入函数时也确实修改对了。
3. 函数执行完后,开始执行返回地址对应的指令,这时返回地址变成了0x00007fffffffe001(往后移了1字节)

所以问题应该出在函数处理过程中,在函数处理过程中,栈上的函数返回地址又被修改了。
这期间可能存在bthread调度,因为函数内部可能会创建bthread,或者调用bthread::Mutex锁间接触发切换。

求助社区大佬有没有遇到类似问题的,或者有什么解决思路?感谢!

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the failure with bcc's funclatency.py and funclatency_example against a brpc service. Then investigate how uretprobe changes return addresses during bthread user-space stack switching, including paths involving bthread creation or bthread::Mutex. Done means brpc services can use uretprobe and kretprobe without SIGILL.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, linux
Domain
backend, operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.