summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2020-12-17 11:11:23 -0800
committergVisor bot <gvisor-bot@google.com>2020-12-17 11:16:06 -0800
commit1ea241e4cc9529d45817e448c66f85213778f948 (patch)
tree367e9c9047c27478f1c04d8728b2bebd0425e09f
parent028271b5308708463d2aa593122840e70c93f02c (diff)
Fix seek on /proc/pid/cmdline when task is zombie.
PiperOrigin-RevId: 348056159
-rw-r--r--pkg/sentry/fsimpl/proc/task_files.go17
-rw-r--r--test/syscalls/linux/proc.cc27
2 files changed, 38 insertions, 6 deletions
diff --git a/pkg/sentry/fsimpl/proc/task_files.go b/pkg/sentry/fsimpl/proc/task_files.go
index a3780b222..75be6129f 100644
--- a/pkg/sentry/fsimpl/proc/task_files.go
+++ b/pkg/sentry/fsimpl/proc/task_files.go
@@ -57,9 +57,6 @@ func getMM(task *kernel.Task) *mm.MemoryManager {
// MemoryManager's users count is incremented, and must be decremented by the
// caller when it is no longer in use.
func getMMIncRef(task *kernel.Task) (*mm.MemoryManager, error) {
- if task.ExitState() == kernel.TaskExitDead {
- return nil, syserror.ESRCH
- }
var m *mm.MemoryManager
task.WithMuLocked(func(t *kernel.Task) {
m = t.MemoryManager()
@@ -111,9 +108,13 @@ var _ dynamicInode = (*auxvData)(nil)
// Generate implements vfs.DynamicBytesSource.Generate.
func (d *auxvData) Generate(ctx context.Context, buf *bytes.Buffer) error {
+ if d.task.ExitState() == kernel.TaskExitDead {
+ return syserror.ESRCH
+ }
m, err := getMMIncRef(d.task)
if err != nil {
- return err
+ // Return empty file.
+ return nil
}
defer m.DecUsers(ctx)
@@ -157,9 +158,13 @@ var _ dynamicInode = (*cmdlineData)(nil)
// Generate implements vfs.DynamicBytesSource.Generate.
func (d *cmdlineData) Generate(ctx context.Context, buf *bytes.Buffer) error {
+ if d.task.ExitState() == kernel.TaskExitDead {
+ return syserror.ESRCH
+ }
m, err := getMMIncRef(d.task)
if err != nil {
- return err
+ // Return empty file.
+ return nil
}
defer m.DecUsers(ctx)
@@ -472,7 +477,7 @@ func (fd *memFD) PRead(ctx context.Context, dst usermem.IOSequence, offset int64
}
m, err := getMMIncRef(fd.inode.task)
if err != nil {
- return 0, nil
+ return 0, err
}
defer m.DecUsers(ctx)
// Buffer the read data because of MM locks
diff --git a/test/syscalls/linux/proc.cc b/test/syscalls/linux/proc.cc
index 575be014c..e508ce27f 100644
--- a/test/syscalls/linux/proc.cc
+++ b/test/syscalls/linux/proc.cc
@@ -1802,6 +1802,33 @@ TEST(ProcPidCmdline, SubprocessForkSameCmdline) {
}
}
+TEST(ProcPidCmdline, SubprocessSeekCmdline) {
+ FileDescriptor fd;
+ ASSERT_NO_ERRNO(WithSubprocess(
+ [&](int pid) -> PosixError {
+ // Running. Open /proc/pid/cmdline.
+ ASSIGN_OR_RETURN_ERRNO(
+ fd, Open(absl::StrCat("/proc/", pid, "/cmdline"), O_RDONLY));
+ return NoError();
+ },
+ [&](int pid) -> PosixError {
+ // Zombie, but seek should still succeed.
+ int ret = lseek(fd.get(), 0x801, 0);
+ if (ret < 0) {
+ return PosixError(errno);
+ }
+ return NoError();
+ },
+ [&](int pid) -> PosixError {
+ // Exited.
+ int ret = lseek(fd.get(), 0x801, 0);
+ if (ret < 0) {
+ return PosixError(errno);
+ }
+ return NoError();
+ }));
+}
+
// Test whether /proc/PID/ symlinks can be read for a running process.
TEST(ProcPidSymlink, SubprocessRunning) {
char buf[1];