From 94bf4b64690b3e3426f4e9758d2948491d79fb68 Mon Sep 17 00:00:00 2001 From: Jamie Liu Date: Mon, 26 Jun 2023 13:41:35 -0700 Subject: [PATCH] Return consistent IDs for PID namespaces via procfs. PiperOrigin-RevId: 543529000 --- pkg/sentry/fsimpl/proc/task.go | 6 +++--- pkg/sentry/fsimpl/proc/task_files.go | 13 ++++++++++++- pkg/sentry/kernel/threads.go | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/pkg/sentry/fsimpl/proc/task.go b/pkg/sentry/fsimpl/proc/task.go index 89ce31d64..4ab06eb1d 100644 --- a/pkg/sentry/fsimpl/proc/task.go +++ b/pkg/sentry/fsimpl/proc/task.go @@ -72,9 +72,9 @@ func (fs *filesystem) newTaskInode(ctx context.Context, task *kernel.Task, pidns "mounts": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0444, &mountsData{fs: fs, task: task}), "net": fs.newTaskNetDir(ctx, task), "ns": fs.newTaskOwnedDir(ctx, task, fs.NextIno(), 0511, map[string]kernfs.Inode{ - "net": fs.newNamespaceSymlink(ctx, task, fs.NextIno(), "net"), - "pid": fs.newNamespaceSymlink(ctx, task, fs.NextIno(), "pid"), - "user": fs.newNamespaceSymlink(ctx, task, fs.NextIno(), "user"), + "net": fs.newFakeNamespaceSymlink(ctx, task, fs.NextIno(), "net"), + "pid": fs.newPIDNamespaceSymlink(ctx, task, fs.NextIno()), + "user": fs.newFakeNamespaceSymlink(ctx, task, fs.NextIno(), "user"), }), "oom_score": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0444, newStaticFile("0\n")), "oom_score_adj": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0644, &oomScoreAdj{task: task}), diff --git a/pkg/sentry/fsimpl/proc/task_files.go b/pkg/sentry/fsimpl/proc/task_files.go index da24fdc12..a5b1f6691 100644 --- a/pkg/sentry/fsimpl/proc/task_files.go +++ b/pkg/sentry/fsimpl/proc/task_files.go @@ -1226,7 +1226,18 @@ type namespaceSymlink struct { task *kernel.Task } -func (fs *filesystem) newNamespaceSymlink(ctx context.Context, task *kernel.Task, ino uint64, ns string) kernfs.Inode { +func (fs *filesystem) newPIDNamespaceSymlink(ctx context.Context, task *kernel.Task, ino uint64) kernfs.Inode { + target := fmt.Sprintf("pid:[%d]", task.PIDNamespace().ID()) + + inode := &namespaceSymlink{task: task} + // Note: credentials are overridden by taskOwnedInode. + inode.Init(ctx, task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, ino, target) + + taskInode := &taskOwnedInode{Inode: inode, owner: task} + return taskInode +} + +func (fs *filesystem) newFakeNamespaceSymlink(ctx context.Context, task *kernel.Task, ino uint64, ns string) kernfs.Inode { // Namespace symlinks should contain the namespace name and the inode number // for the namespace instance, so for example user:[123456]. We currently fake // the inode number by sticking the symlink inode in its place. diff --git a/pkg/sentry/kernel/threads.go b/pkg/sentry/kernel/threads.go index b90118ee2..791c4d1bd 100644 --- a/pkg/sentry/kernel/threads.go +++ b/pkg/sentry/kernel/threads.go @@ -149,6 +149,9 @@ type PIDNamespace struct { // appropriate capabilities in userns. The userns pointer is immutable. userns *auth.UserNamespace + // id is a unique ID assigned to the PID namespace. id is immutable. + id uint64 + // The following fields are protected by owner.mu. // last is the last ThreadID to be allocated in this namespace. @@ -198,6 +201,7 @@ func newPIDNamespace(ts *TaskSet, parent *PIDNamespace, userns *auth.UserNamespa owner: ts, parent: parent, userns: userns, + id: lastPIDNSID.Add(1), tasks: make(map[ThreadID]*Task), tids: make(map[*Task]ThreadID), tgids: make(map[*ThreadGroup]ThreadID), @@ -209,6 +213,13 @@ func newPIDNamespace(ts *TaskSet, parent *PIDNamespace, userns *auth.UserNamespa } } +// lastPIDNSID is the last value of PIDNamespace.ID assigned to a PID +// namespace. +// +// This is global rather than being per-TaskSet or Kernel because +// NewRootPIDNamespace() is called before the Kernel is initialized. +var lastPIDNSID atomicbitops.Uint64 + // NewRootPIDNamespace creates the root PID namespace. 'owner' is not available // yet when root namespace is created and must be set by caller. func NewRootPIDNamespace(userns *auth.UserNamespace) *PIDNamespace { @@ -230,6 +241,11 @@ func (ns *PIDNamespace) TaskWithID(tid ThreadID) *Task { return t } +// ID returns a non-zero ID that is unique across PID namespaces. +func (ns *PIDNamespace) ID() uint64 { + return ns.id +} + // ThreadGroupWithID returns the thread group led by the task with thread ID // tid in PID namespace ns. If no task has that TID, or if the task with that // TID is not a thread group leader, ThreadGroupWithID returns nil.