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

fix https://github.com/gojue/ecapture/issues/513 #514

Closed
wants to merge 1 commit into from
Closed

fix https://github.com/gojue/ecapture/issues/513 #514

wants to merge 1 commit into from

Conversation

sancppp
Copy link
Contributor

@sancppp sancppp commented Apr 1, 2024

No description provided.

Copy link
Member

@cfc4n cfc4n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to my testing, the problem is not that simple. On ubuntu 22.04 system with x86_64, the traced process crashes.


根据我测试的情况来看,问题不是这么简单。 在x86_64的ubuntu 22.04系统上,被跟踪的进程会崩溃。

@cfc4n cfc4n added the bug Something isn't working label Apr 1, 2024
@wlingze
Copy link
Contributor

wlingze commented Apr 2, 2024

this error in debug/gosym, please see: wlingze#2

rootcause:

debug/gosym assigns the parameter PC passed when calling NewLineTable to t.textStart, in our code, this address is gc.goElf.Section(".text").Addr. But this t.textStart should be get from pclntable.

The relevant code changed by go pr 366695

solution:

  1. use symbols from *elf.File like nopie case, you can get correct address. (Checked)
  2. use symbols get runtime.text address, pass to NewLineTable, like go pr 366695 (NoChecked)

@cfc4n
Copy link
Member

cfc4n commented Apr 5, 2024

@wlingze 感谢你的PR。我在ubuntu 22.04 arm64上测试了docker的符号表读取,读取到的offset依旧是错误的,两个单元测试文件也是失败。

程序读取的offset无效

sudo bin/ecapture gotls -m text --elfpath=/usr/bin/docker
tls_2024/04/05 15:15:51 ECAPTURE :: ecapture Version : linux_aarch64:0.7.5-20240303-bfb4a8c:[CORE]
tls_2024/04/05 15:15:51 ECAPTURE :: Pid Info : 346937
tls_2024/04/05 15:15:51 ECAPTURE :: Kernel Info : 5.15.143
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	module initialization
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	master key keylogger:
tls_2024/04/05 15:15:51 ECAPTURE ::	Module.Run()
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	Text MODEL
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	eBPF Function Name:gotls_write_register, isRegisterABI:true
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	Golang buildInfo version:go1.20.3, Params:  -buildmode=pie -compiler=gc -ldflags= -X "github.com/docker/cli/cli/version.GitCommit=24.0.5-0ubuntu1~22.04.1" -X "github.com/docker/cli/cli/version.BuildTime=2023-08-21T19:50:14Z" -X "github.com/docker/cli/cli/version.Version=24.0.5" -tags=pkcs11 CGO_ENABLED=1 GOARCH=arm64 GOOS=linux
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	Golang elf buildmode with pie
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	add uretprobe function :crypto/tls.(*Conn).Read, offset:0x46EF70
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	add uretprobe function :crypto/tls.(*Conn).Read, offset:0x46EF98
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	add uretprobe function :crypto/tls.(*Conn).Read, offset:0x46EFFC
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	add uretprobe function :crypto/tls.(*Conn).Read, offset:0x46F118
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	add uretprobe function :crypto/tls.(*Conn).Read, offset:0x46F148
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	add uretprobe function :crypto/tls.(*Conn).Read, offset:0x46F1A8
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	add uretprobe function :crypto/tls.(*Conn).Read, offset:0x46F1C4
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	target all process.
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	target all users.
tls_2024/04/05 15:15:51 EBPFProbeGoTLS	BPF bytecode filename:user/bytecode/gotls_kern.o
tls_2024/04/05 15:15:52 EBPFProbeGoTLS	perfEventReader created. mapSize:4 MB
tls_2024/04/05 15:15:52 EBPFProbeGoTLS	module started successfully.
^Ctls_2024/04/05 15:16:40 EBPFProbeGoTLS	close.
tls_2024/04/05 15:16:40 EBPFProbeGoTLS	close

另一个终端

运行docker pull任意资源

单测失败

go test ./tests/issue_513/
--- FAIL: TestDockerSymbol_ByElfSymbol (0.00s)
    docker_test.go:29: get symbol crypto/tls.(*Conn).Read error: symbol not found
--- FAIL: TestDockerSymbol_BySymbolTable (0.02s)
    docker_test.go:55: error symbol address: got[0x0046ed30] vs want[0x00635cb0], dec: 0x001c6f80
--- FAIL: TestDockerSymbolFromPclntab (0.01s)
    gosym_test.go:117: error symbol address: got[0x0046ed30] vs want[0x00635cb0]
FAIL
FAIL	ecapture/tests/issue_513	0.032s
FAIL

@wlingze
Copy link
Contributor

wlingze commented Apr 7, 2024

@cfc4n
预期应该成功的第一个通过elf符号获取的测试,失败,报错为:symbol not found, 看起来在实际运行环境中的docker可能是去除符号的,因此在第一个测试中查找不到符号,通过file 应该可以看到 "stripped"字样,通过使用readelf -sW ./testdata/docker_aarch64/docker | grep "crypto/tls.(\*Conn).Read$"也应该是无法查询到地址的。

这时候只能借助gopclntable获取函数地址,但是debug/gosym中的textStart处理有问题,我想我们应该找到Magic以后手动读取textStart的信息,他是一个固定的偏移量,然后将这个地址传入NewLineTable中。这个我已经在 #516 中实现。

另外我认为在是否使用pclntab的判断不应该是gc.IsPieBuildMode,应该是根据是否stripped剥离符号,如果没有去除符号的话,我们可以直接通过elf.Symbol获得,如果去掉了符号则elf.Symbol则全部为空,只能通过pclntab获取函数地址,这点和是否pie模式编译没有关系。

@cfc4n
Copy link
Member

cfc4n commented Apr 7, 2024

通过使用readelf -sW ./testdata/docker_aarch64/docker | grep "crypto/tls.(\*Conn).Read$"也应该是无法查询到地址的。

这个方式不能用于判断是否可以还原这个符号表的依据。
PIE编译模式下,会使用.data.rel.ro.gopclntab.data.rel.ro等段,是可以通过这些section来还原符号的。

IsPieBuildMode模式的判断,是在go的debug包里已判断了。 确实应该不需要我们再判断。

不过,我不赞同stripped剥离符号作为可以还原符号表的依据。

@wlingze
Copy link
Contributor

wlingze commented Apr 8, 2024

在普通的ELF文件中,为了重定向, 程序一般会保留一部分的函数符号,因此可以通过 readelf -sW 获取符号,对应的golang的代码也就是使用debug/elf这个库, 在本项目中是findRetOffsets, 但是如果面对去除符号的情况,则会从elf中获取不到任何符号,这种方法失效。

在Golang编译的二进制文件中,可以使用pclntab这个信息表来获取函数地址。对应的golang代码是使用debug/gosym这个库,在本项目中是findPieSymbolAddr
因为golang自己做了一套runtime,这个表也是runtime的一部分,在解析符号时会直接使用这个表。在编译时golang将会吧所有的函数都整理在这个表内,然后按照一定的方案编译到二进制, 在golang的标准库也提供了debug/gosym用于解析这个段,但是他的实现有一些问题,我们需要传入一个地址,这个地址应该是程序的runtime.text 而非 .text段的地址。
而这个pclntab储存的位置是和你说的一样,可能会在开启pie以后发生变化的。

因此我其实觉得,
尝试通过elf获取函数: 如果可以直接通过elf的符号获取到函数的话,那是最好直接继续分析return地址即可。
如果编译追加了-ldflags '-s'就会去除符号(大部分的release发行都会带),这时候没有符号,只能通过pclntab来获取符号, 那么就解析pclntab,获取其中保存的runtime.text地址并传入NewLineTable中。

@cfc4n
Copy link
Member

cfc4n commented Apr 12, 2024

fixed at #516 and #517.

@cfc4n cfc4n closed this Apr 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants