系统调用 read() 返回比 count 更大的数字

lst*_*kov 5 linux debian system-calls linux-kernel strace

我读取了数据/proc/<pid>/environ并得到了奇怪的结果。这怎么可能?

open("/proc/24696/environ", O_RDONLY)   = 10
read(10, "24694\nPPid:\t2606\nTracerPid:\t0\nUi"..., 4096) = 1470144576

open("/proc/25387/environ", O_RDONLY)   = 10
read(10, "686\nPPid:\t1\nTracerPid:\t0\nUid:\t10"..., 4096) = 5905728
Run Code Online (Sandbox Code Playgroud)

为什么read返回的值比count(4096) 更大?

不过,这种情况并非每次都会发生。

Debian 7、3.2.0-4-amd64 #1 SMP Debian 3.2.84-1 x86_64 GNU/Linux

更新:

我不认为这是strace错误 - 我还打印了 glibcread函数的结果,结果相同。

更新2:

我创建了一个重现问题的测试应用程序,https://gist.github.com/lstipakov/70c5b5e96112c7f1f6204d70b2c8280e

它枚举文件下的所有进程/proc并从文件中读取environ。问题在不到一分钟内重现:

// do read, which sometimes returns weird values on 3.2.0-4-amd64 #1 SMP Debian 3.2.84-1 x86_64 GNU/Linux
char tmp[4096];
auto val = read(fd, tmp, sizeof(tmp));
if (val > sizeof(tmp)) {
    std::cout << path << " read " << val << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

CXXFLAGS="-std=c++11" make proc && sudo ./proc

几秒钟后:

/proc/24341/environ 读取 812785856

可以通过循环编译 openvpn 来重现:

$ while true; do make clean; make; done
Run Code Online (Sandbox Code Playgroud)