linux 'clone()'返回strace报告的非PID的原因是什么?

rn0zuynd  于 2023-03-07  发布在  Linux
关注(0)|答案(1)|浏览(141)

我试图通过分析strace的输出来跟踪进程的创建,在分析了几千行之后,我遇到了一个以前从未见过的情况。在下面这个简短的代码片段中,您可以看到PID=501135的第一次出现:

501133 1677685727.376373 clone(child_stack=0x7fbb38c77000, flags=CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID|SIGCHLD) = 501134
501134 1677685727.377751 openat(AT_FDCWD, "/proc/self/setgroups", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
501134 1677685727.377897 openat(AT_FDCWD, "/proc/self/uid_map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
501134 1677685727.377998 openat(AT_FDCWD, "/proc/self/gid_map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
501134 1677685727.378102 openat(AT_FDCWD, "/proc/self/mounts", O_RDONLY|O_CLOEXEC) = 3
501134 1677685727.378926 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fbb38c78a10) = 2
501135 1677685727.380065 execve("/bin/true", ["/bin/true"], []) = 0
501135 1677685727.388634 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
501135 1677685727.388742 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
501135 1677685727.389288 +++ exited with 0 +++

正如您所看到的,PID=501135突然出现,并且没有vforkcloneclone3或任何指示其创建的内容。
此外,在第一次出现之前的最后一行中,有一个clone()返回2而不是PID,所以我怀疑它是clone,* 应该 * 返回501135
我知道unfinished ...... resumed行可以暂时隐藏PID的创建,直到相应的... resumed行显示出来。我已经在处理这个问题了,grep在完整的日志中除了我粘贴的行之外没有显示501135
我错过了什么?是否有机会使用strace可靠地跟踪每个PID(或替代方法,我不知道任何..)

    • 更新**:

多亏了@tkausl关于CLONE_NEWPID标志的提示,我成功地解决了许多以前失败的PID查找问题。

  • 保持Mappid_offset:PID-〉初始PID
  • 每次CLONE_NEWPIDclone()标志中时更新Map:
if "CLONE_NEWPID" in clone.flags:
    pid_offset[strace.result] = strace.pid
  • 每次使用pid_offset中Map的PID执行clone()时,我都会根据clone()的结果和偏移量重新计算"实际" PID:
new_pid = strace.result_nr
if strace.pid in pid_offset:
    new_pid = strace.result + pid_offset[strace.pid]
    pid_offset[new_pid] = pid_offset[strace.pid]

奇怪的是,这适用于大多数情况,但不是所有情况。下面是一个我仍然偶然遇到的情况(剥离到clone()的相关调用。我没有跟踪的PID是501376

# Here is a case which actually works: 
# PID 501133 creates 501134 with CLONE_NEWPID and as a result
# 501134 successfully creates 501135:
#
501133 1677685727.376373 clone(child_stack=0x7fbb38c77000, flags=CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID|SIGCHLD) = 501134
+++ CLONE_NEWPID for clone() with PID=501133: 501133

501134 1677685727.378926 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fbb38c78a10) = 2
+++ clone_PID: 501134, new_PID = PID_offset=501133 + result=2 = 501135

# Now comes a long chain of `clone()` calls starting with
# 501149 cloning with CLONE_NEWPID, working in the beginning:
#
501149 1677685727.761916 clone(child_stack=0x7f24b72cc000, flags=CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID|CLONE_NEWNET|SIGCHLD) = 501150
+++ CLONE_NEWPID for clone() with PID=501149: 501149

501150 1677685727.776125 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24b72cda10) = 2
+++ clone_PID: 501150, new_PID = PID_offset=501149 + result=2 = 501151
501151 1677685727.838544 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f0d7075aa10) = 3
+++ clone_PID: 501151, new_PID = PID_offset=501149 + result=3 = 501152

... here the PIDS 501152..501373 get created successfully

501161 1677685728.487811 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f28da126ad0) = 225
+++ clone_PID: 501161, new_PID = PID_offset=501149 + result=225 = 501374
501161 1677685728.488968 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f28da126ad0) = 226
+++ clone_PID: 501161, new_PID = PID_offset=501149 + result=226 = 501375

501376 1677685728.489090 execve("/opt/bin/touch", [CMD..], [ENV...]) = -1 ENOENT (No such file or directory)

最后一行显示PID = 501376,我不知道它是在哪里创建的,也不知道如何计算值501376
我怀疑有一个错误,但是简单地在某个地方添加+ 1只会导致在其他地方出现未知的PID。
我哪里做错了?

2q5ifsrm

2q5ifsrm1#

As you can see PID=501135 suddenly shows up and there is no vfork, clone, clone3 or whatsoever indicating it's creation.

Also in the last line before the first occurrence there is a clone() returning 2 instead of a PID, so I suspect it to be the clone that should return 501135.

这是正确的,第二个克隆确实创建了PID,但仍然正确地返回了PID 2。这是因为第一个克隆创建了一个新的PID命名空间(CLONE_NEWPID),它在新命名空间内获得PID 1。下一个克隆 * 来自该命名空间 *,在该命名空间内获得PID 2,并在父命名空间中获得PID 501135。

相关问题