ecapture icon indicating copy to clipboard operation
ecapture copied to clipboard

以明文形式捕获 tls 内容时部分信息展示不正确

Open xxxxxliil opened this issue 1 year ago • 12 comments

Describe the bug 使用 ecapture 捕获时,日志展示夸张的 FD 和不能获得的访问地址 且在 /sys/kernel/debug/tracing/trace_pipe 中发现以下内容:

            curl-204590  [000] ...11 175870.494020: bpf_trace_printk: openssl uprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.494022: bpf_trace_printk: openssl uprobe SSL_write FD:811562928, version:0

            curl-204590  [000] ...11 175870.495026: bpf_trace_printk: openssl uretprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.495113: bpf_trace_printk: openssl uprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.495116: bpf_trace_printk: openssl uprobe SSL_write FD:811562928, version:0

            curl-204590  [000] ...11 175870.495191: bpf_trace_printk: openssl uretprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.710355: bpf_trace_printk: openssl uprobe/SSL_read pid :204590

            curl-204590  [000] ...11 175870.710365: bpf_trace_printk: openssl uprobe PID:204590, SSL_read FD:811562928

To Reproduce Steps to reproduce the behavior:

  1. build ebpf-tc-uid-filter branch
  2. # ecapture --debug tls
  3. $ curl -L 1.1.1.1/cdn-cgi/trace
  4. See error

Expected behavior 显示正确的 fd 和正确的地址

Screenshots image

Linux Server/Android (please complete the following information):

  • Env: [run make env to get the environment variables]
  • OS: arch
  • Arch: amd64
  • Kernel Version: 6.10.6-zen1-1-zen
  • Version: linux_amd64:0.8.5-20240825-a0b5f1d:6.10.6-zen1-1-zen

Additional context 每个程序的每个实例都有独立且固定的错误 fd

xxxxxliil avatar Aug 25 '24 06:08 xxxxxliil

看上去只是数字比较大而已,你认为错误fd的依据是什么?

cfc4n avatar Aug 25 '24 10:08 cfc4n

看上去只是数字比较大而已,你认为错误fd的依据是什么?

我用 sysdig 检查 curl 的 syscall,发现没有 syscall 返回过如此大的 fd,且 ulimit -n 的输出是 4096

xxxxxliil avatar Aug 25 '24 10:08 xxxxxliil

4096只是同时打开的FD的总数,并不是FD这个数字最大值的限制。

如果再有这种现场,你可以配合lsof等命令,确认FD是不是正确的值。

cfc4n avatar Aug 25 '24 11:08 cfc4n

4096只是同时打开的FD的总数,并不是FD这个数字最大值的限制。

如果再有这种现场,你可以配合lsof等命令,确认FD是不是正确的值。

怎么保持对应的 fd 为打开状态呢?

xxxxxliil avatar Aug 25 '24 12:08 xxxxxliil

4096只是同时打开的FD的总数,并不是FD这个数字最大值的限制。 如果再有这种现场,你可以配合lsof等命令,确认FD是不是正确的值。

怎么保持对应的 fd 为打开状态呢?

单线程下个大文件

blaisewang avatar Aug 26 '24 03:08 blaisewang

image image curl 在下载文件时暂停后截的图

补图: image image image

接下来也许还要怀疑发起请求的和传输下载内容的 tcp fd 不是同一个?虽然昨天我说过已经用 sysdig 看过没有任何 syscall 返回过那么大的文件描述符

这是码

#include <stdio.h>
#include <stdint.h>

#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    system("echo $(($(ulimit -n) - 1)) is max fd");
    int udfd = atoi(argv[1]);
    int o_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    printf("open socket fd: %i, errno: %i, strerr: %s\n", o_fd, errno, strerror(errno));
    int n_fd = dup2(o_fd, udfd);
    printf("dup2 origin fd: %i, user define fd: %i, new fd: %i, errno: %i, strerr: %s\n",
        o_fd, udfd, n_fd, errno, strerror(errno));
    getchar();
    return 0;
}

最大 fd 数量就是 fd 最大值

$ gcc t.c; ./a.out 4095
4095 is max fd
open socket fd: 3, errno: 0, strerr: Success
dup2 origin fd: 3, user define fd: 4095, new fd: 4095, errno: 0, strerr: Success

如果尝试更高的值就会

$ gcc t.c; ./a.out 4096
4095 is max fd
open socket fd: 3, errno: 0, strerr: Success
dup2 origin fd: 3, user define fd: 4096, new fd: -1, errno: 9, strerr: Bad file descriptor

xxxxxliil avatar Aug 26 '24 06:08 xxxxxliil

偶尔close一些fd啊。否则都持有着,肯定超过不了4096

cfc4n avatar Aug 26 '24 14:08 cfc4n

偶尔close一些fd啊。否则都持有着,肯定超过不了4096

在上面的示例中只有 5 个 fd,但是 fd 号仍然不能超过 ulimit 中同时打开的 fd 上限

man 2 dup:

ERRORS
       EBADF  oldfd isn't an open file descriptor.

       EBADF  newfd is out of the allowed range for file descriptors (see the discussion of RLIMIT_NOFILE in getrlimit(2)).

man 3p dup:

The dup2() function shall fail if:

EBADF  The fildes argument is not a valid open file descriptor or the argument fildes2 is negative or greater than or equal to {OPEN_MAX}.

man 3p getrlimit:

RLIMIT_NOFILE
This is a number one greater than the maximum value that the system may assign to a newly-created descriptor.
If this limit is exceeded, functions that allocate a file descriptor shall fail with errno set to [EMFILE].
This limit constrains the number of file descriptors that  a  process  may allocate.

我是真的想见识一下如何分配值大于 RLIMIT_NOFILE 的 fd。网上搜不行,自己测试不行,文档说不行。但你一直说这是可以随意做到的,请讲解一下如何做到

xxxxxliil avatar Aug 27 '24 08:08 xxxxxliil

不好意思,工作日比较忙,我周末验证一下,再回复。

cfc4n avatar Aug 27 '24 13:08 cfc4n

@cfc4n 我已经知道问题出在哪里了,但是因为个人原因(我承认是在赌气),请你先演示一下如何在主线内核中取得一个比 ulimit 中比 fd 上限更高数值的 fd

xxxxxliil avatar Oct 06 '24 12:10 xxxxxliil

我找了点资料看了一下,是我对linux内核的fd回收机制理解不对,close的fd会被内核复用,做不到fd的值大于ulimit的情况。

看得出来,你还在赌气。 对我来说,个人精力有限,不能及时挨个回答用户问题,更何况是特定场景下的小众问题。你说你在赌气,我完全无法理解,换位思考一下,我是做开源软件的,你用我写的软件,没收你钱,还在持续帮你解决问题,凭什么要承诺解决方案的准确性、可靠性?

其次,我不是所有领域的专家,对个别知识点理解不对,给出错误结论是很正常的事情。 任何人在成长的过程中,都是伴随着错误知识不断迭代修正。

友好交流,有问题就互相纠正吧,情绪化不可取。

cfc4n avatar Oct 14 '24 13:10 cfc4n

我找了点资料看了一下,是我对linux内核的fd回收机制理解不对,close的fd会被内核复用,做不到fd的值大于ulimit的情况。

看得出来,你还在赌气。 对我来说,个人精力有限,不能及时挨个回答用户问题,更何况是特定场景下的小众问题。你说你在赌气,我完全无法理解,换位思考一下,我是做开源软件的,你用我写的软件,没收你钱,还在持续帮你解决问题,凭什么要承诺解决方案的准确性、可靠性?

我没有要求承诺可用性,是有点难以接受在你第二次回复时提出的问题。在第一次的提问中我已经使用 syadig 检查过 curl 执行过程中调用的 syscall,curl 从未有过 ecapture 报告的那么巨大的 fd。但第二次回复中只是觉得它有点大,并希望我在下一次发现问题的现场用 lsof 看一看 fd 是不是正确的。

其次,我不是所有领域的专家,对个别知识点理解不对,给出错误结论是很正常的事情。 任何人在成长的过程中,都是伴随着错误知识不断迭代修正。

友好交流,有问题就互相纠正吧,情绪化不可取。

理解,但是交 pr 很可能因为前几天时不时用 codespace 看 commit 记录并且没及时停止导致免费市场用完,等下个月才能了。

xxxxxliil avatar Oct 14 '24 16:10 xxxxxliil

这个问题本质上是 openssl 3 以上的 libssl.so .rodata 段中不再存在版本信息,且开 issue 时对于检查不到版本且根据文件后缀回退到默认的 3.0.0 时的日志等级为 info,导致使用时很难注意到是版本没有正确匹配导致的输出信息有误,同时发生的现象还有 keylog 和 pcap 都不能进行抓取解密的 tls 流量。

xxxxxliil avatar Nov 08 '24 08:11 xxxxxliil