From 679c77e4f05e01946333e5e364ec1e3f31fcd72c Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Mon, 6 Jan 2025 14:01:09 -0800 Subject: [PATCH] proc: Allow interrupting generation of /proc/pid/mount{s,info} In some cases, generating /proc/pid/mount{s,info} can take a long time. This change allows the process to be interrupted. Reported-by: syzbot+9e7465bc6f00665727ad@syzkaller.appspotmail.com Signed-off-by: Andrei Vagin --- pkg/sentry/fsimpl/proc/task_files.go | 6 ++---- pkg/sentry/vfs/mount.go | 12 ++++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pkg/sentry/fsimpl/proc/task_files.go b/pkg/sentry/fsimpl/proc/task_files.go index 366d9476a..55f87f130 100644 --- a/pkg/sentry/fsimpl/proc/task_files.go +++ b/pkg/sentry/fsimpl/proc/task_files.go @@ -1201,8 +1201,7 @@ func (i *mountInfoData) Generate(ctx context.Context, buf *bytes.Buffer) error { return nil } defer i.fs.SafeDecRef(ctx, rootDir) - i.task.Kernel().VFS().GenerateProcMountInfo(ctx, rootDir, buf) - return nil + return i.task.Kernel().VFS().GenerateProcMountInfo(ctx, rootDir, buf) } // mountsData is used to implement /proc/[pid]/mounts. @@ -1233,8 +1232,7 @@ func (i *mountsData) Generate(ctx context.Context, buf *bytes.Buffer) error { return nil } defer i.fs.SafeDecRef(ctx, rootDir) - i.task.Kernel().VFS().GenerateProcMounts(ctx, rootDir, buf) - return nil + return i.task.Kernel().VFS().GenerateProcMounts(ctx, rootDir, buf) } // +stateify savable diff --git a/pkg/sentry/vfs/mount.go b/pkg/sentry/vfs/mount.go index c612138cf..615368957 100644 --- a/pkg/sentry/vfs/mount.go +++ b/pkg/sentry/vfs/mount.go @@ -1342,7 +1342,7 @@ func (mnt *Mount) Root() *Dentry { // GenerateProcMounts emits the contents of /proc/[pid]/mounts for vfs to buf. // // Preconditions: taskRootDir.Ok(). -func (vfs *VirtualFilesystem) GenerateProcMounts(ctx context.Context, taskRootDir VirtualDentry, buf *bytes.Buffer) { +func (vfs *VirtualFilesystem) GenerateProcMounts(ctx context.Context, taskRootDir VirtualDentry, buf *bytes.Buffer) error { rootMnt := taskRootDir.mount vfs.lockMounts() @@ -1361,6 +1361,9 @@ func (vfs *VirtualFilesystem) GenerateProcMounts(ctx context.Context, taskRootDi sort.Slice(mounts, func(i, j int) bool { return mounts[i].ID < mounts[j].ID }) for _, mnt := range mounts { + if ctx.Interrupted() { + return linuxerr.ErrInterrupted + } // Get the path to this mount relative to task root. mntRootVD := VirtualDentry{ mount: mnt, @@ -1404,13 +1407,14 @@ func (vfs *VirtualFilesystem) GenerateProcMounts(ctx context.Context, taskRootDi // is allowed. fmt.Fprintf(buf, "%s %s %s %s %d %d\n", "none", path, mnt.fs.FilesystemType().Name(), opts, 0, 0) } + return nil } // GenerateProcMountInfo emits the contents of /proc/[pid]/mountinfo for vfs to // buf. // // Preconditions: taskRootDir.Ok(). -func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRootDir VirtualDentry, buf *bytes.Buffer) { +func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRootDir VirtualDentry, buf *bytes.Buffer) error { rootMnt := taskRootDir.mount vfs.lockMounts() @@ -1431,6 +1435,9 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo creds := auth.CredentialsFromContext(ctx) for _, mnt := range mounts { + if ctx.Interrupted() { + return linuxerr.ErrInterrupted + } // Get the path to this mount relative to task root. mntRootVD := VirtualDentry{ mount: mnt, @@ -1530,6 +1537,7 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo // (11) Superblock options, and final newline. fmt.Fprintf(buf, "%s\n", superBlockOpts(pathFromRoot, mnt)) } + return nil } // manglePath replaces ' ', '\t', '\n', and '\\' with their octal equivalents.