mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Return ENOENT when reading /proc/{pid}/task of an exited process
There will be a deadloop when we use getdents to read /proc/{pid}/task
of an exited process
Like this:
Process A is running
Process B: open /proc/{pid of A}/task
Process A exits
Process B: getdents /proc/{pid of A}/task
Then, process B will fall into deadloop, and return "." and ".."
in loops and never ends.
This patch returns ENOENT when use getdents to read /proc/{pid}/task
if the process is just exited.
Signed-off-by: chris.zn <chris.zn@antfin.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/sentry/context"
|
||||
@@ -162,6 +163,11 @@ func (f *subtasksFile) Readdir(ctx context.Context, file *fs.File, ser fs.Dentry
|
||||
// subtask to emit.
|
||||
offset := file.Offset()
|
||||
|
||||
tasks := f.t.ThreadGroup().MemberIDs(f.pidns)
|
||||
if len(tasks) == 0 {
|
||||
return offset, syscall.ENOENT
|
||||
}
|
||||
|
||||
if offset == 0 {
|
||||
// Serialize "." and "..".
|
||||
root := fs.RootFromContext(ctx)
|
||||
@@ -178,7 +184,6 @@ func (f *subtasksFile) Readdir(ctx context.Context, file *fs.File, ser fs.Dentry
|
||||
}
|
||||
|
||||
// Serialize tasks.
|
||||
tasks := f.t.ThreadGroup().MemberIDs(f.pidns)
|
||||
taskInts := make([]int, 0, len(tasks))
|
||||
for _, tid := range tasks {
|
||||
taskInts = append(taskInts, int(tid))
|
||||
|
||||
@@ -1908,6 +1908,25 @@ void CheckDuplicatesRecursively(std::string path) {
|
||||
|
||||
TEST(Proc, NoDuplicates) { CheckDuplicatesRecursively("/proc"); }
|
||||
|
||||
TEST(Proc, Getdents) {
|
||||
int child_pid = fork();
|
||||
ASSERT_GE(child_pid, 0);
|
||||
if (child_pid == 0) {
|
||||
while(1){
|
||||
sleep(100);
|
||||
}
|
||||
}
|
||||
ASSERT_THAT(child_pid, SyscallSucceeds());
|
||||
char name[100];
|
||||
char buf[1024];
|
||||
int fd;
|
||||
sprintf(name, "/proc/%d/task", child_pid);
|
||||
fd = open(name, O_RDONLY | O_DIRECTORY);
|
||||
ASSERT_THAT(kill(child_pid, SIGKILL), SyscallSucceeds());
|
||||
ASSERT_THAT(waitpid(child_pid, NULL, 0), SyscallSucceedsWithValue(child_pid));
|
||||
ASSERT_THAT(syscall(SYS_getdents, fd, buf, 1024), SyscallFailsWithErrno(ENOENT));
|
||||
}
|
||||
|
||||
// Most /proc/PID files are owned by the task user with SUID_DUMP_USER.
|
||||
TEST(ProcPid, UserDumpableOwner) {
|
||||
int before;
|
||||
|
||||
Reference in New Issue
Block a user