summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteve Silva <stevesilva@google.com>2021-05-06 18:00:49 -0700
committergVisor bot <gvisor-bot@google.com>2021-05-06 18:03:42 -0700
commit339001204000a3060628256cd9131ea2a2d4e08a (patch)
tree518e103c362ebd106fdf96cedb1d08fdade42376
parent9800fd8e4717133476afb9bdc64f8384c53f82dd (diff)
Implement /proc/cmdline
This change implements /proc/cmdline with a basic faux command line "BOOT_IMAGE=/vmlinuz-[version]-gvisor quiet" so apps that may expect it do not receive errors. Also tests for the existence of /proc/cmdline as part of the system call test suite PiperOrigin-RevId: 372462070
-rw-r--r--pkg/sentry/fsimpl/proc/tasks.go1
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_files.go39
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_test.go1
-rw-r--r--test/syscalls/linux/proc.cc9
4 files changed, 40 insertions, 10 deletions
diff --git a/pkg/sentry/fsimpl/proc/tasks.go b/pkg/sentry/fsimpl/proc/tasks.go
index 7c7543f14..cf905fae4 100644
--- a/pkg/sentry/fsimpl/proc/tasks.go
+++ b/pkg/sentry/fsimpl/proc/tasks.go
@@ -65,6 +65,7 @@ var _ kernfs.Inode = (*tasksInode)(nil)
func (fs *filesystem) newTasksInode(ctx context.Context, k *kernel.Kernel, pidns *kernel.PIDNamespace, fakeCgroupControllers map[string]string) *tasksInode {
root := auth.NewRootCredentials(pidns.UserNamespace())
contents := map[string]kernfs.Inode{
+ "cmdline": fs.newInode(ctx, root, 0444, &cmdLineData{}),
"cpuinfo": fs.newInode(ctx, root, 0444, newStaticFileSetStat(cpuInfoData(k))),
"filesystems": fs.newInode(ctx, root, 0444, &filesystemsData{}),
"loadavg": fs.newInode(ctx, root, 0444, &loadavgData{}),
diff --git a/pkg/sentry/fsimpl/proc/tasks_files.go b/pkg/sentry/fsimpl/proc/tasks_files.go
index e1a8b4409..045ed7a2d 100644
--- a/pkg/sentry/fsimpl/proc/tasks_files.go
+++ b/pkg/sentry/fsimpl/proc/tasks_files.go
@@ -336,15 +336,6 @@ var _ dynamicInode = (*versionData)(nil)
// Generate implements vfs.DynamicBytesSource.Generate.
func (*versionData) Generate(ctx context.Context, buf *bytes.Buffer) error {
- k := kernel.KernelFromContext(ctx)
- init := k.GlobalInit()
- if init == nil {
- // Attempted to read before the init Task is created. This can
- // only occur during startup, which should never need to read
- // this file.
- panic("Attempted to read version before initial Task is available")
- }
-
// /proc/version takes the form:
//
// "SYSNAME version RELEASE (COMPILE_USER@COMPILE_HOST)
@@ -364,7 +355,7 @@ func (*versionData) Generate(ctx context.Context, buf *bytes.Buffer) error {
// FIXME(mpratt): Using Version from the init task SyscallTable
// disregards the different version a task may have (e.g., in a uts
// namespace).
- ver := init.Leader().SyscallTable().Version
+ ver := kernelVersion(ctx)
fmt.Fprintf(buf, "%s version %s %s\n", ver.Sysname, ver.Release, ver.Version)
return nil
}
@@ -400,3 +391,31 @@ func (*cgroupsData) Generate(ctx context.Context, buf *bytes.Buffer) error {
r.GenerateProcCgroups(buf)
return nil
}
+
+// cmdLineData backs /proc/cmdline.
+//
+// +stateify savable
+type cmdLineData struct {
+ dynamicBytesFileSetAttr
+}
+
+var _ dynamicInode = (*cmdLineData)(nil)
+
+// Generate implements vfs.DynamicByteSource.Generate.
+func (*cmdLineData) Generate(ctx context.Context, buf *bytes.Buffer) error {
+ fmt.Fprintf(buf, "BOOT_IMAGE=/vmlinuz-%s-gvisor quiet\n", kernelVersion(ctx).Release)
+ return nil
+}
+
+// kernelVersion returns the kernel version.
+func kernelVersion(ctx context.Context) kernel.Version {
+ k := kernel.KernelFromContext(ctx)
+ init := k.GlobalInit()
+ if init == nil {
+ // Attempted to read before the init Task is created. This can
+ // only occur during startup, which should never need to read
+ // this file.
+ panic("Attempted to read version before initial Task is available")
+ }
+ return init.Leader().SyscallTable().Version
+}
diff --git a/pkg/sentry/fsimpl/proc/tasks_test.go b/pkg/sentry/fsimpl/proc/tasks_test.go
index d6f076cd6..e534fbca8 100644
--- a/pkg/sentry/fsimpl/proc/tasks_test.go
+++ b/pkg/sentry/fsimpl/proc/tasks_test.go
@@ -47,6 +47,7 @@ var (
var (
tasksStaticFiles = map[string]testutil.DirentType{
+ "cmdline": linux.DT_REG,
"cpuinfo": linux.DT_REG,
"filesystems": linux.DT_REG,
"loadavg": linux.DT_REG,
diff --git a/test/syscalls/linux/proc.cc b/test/syscalls/linux/proc.cc
index 143075e2d..24928d876 100644
--- a/test/syscalls/linux/proc.cc
+++ b/test/syscalls/linux/proc.cc
@@ -1201,6 +1201,15 @@ TEST(ProcSelfCwd, Absolute) {
EXPECT_EQ(exe[0], '/');
}
+// Sanity check that /proc/cmdline is present.
+TEST(ProcCmdline, IsPresent) {
+ SKIP_IF(IsRunningWithVFS1());
+
+ std::string proc_cmdline =
+ ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/cmdline"));
+ ASSERT_FALSE(proc_cmdline.empty());
+}
+
// Sanity check for /proc/cpuinfo fields that must be present.
TEST(ProcCpuinfo, RequiredFieldsArePresent) {
std::string proc_cpuinfo =