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
This commit is contained in:
Steve Silva
2021-05-06 18:03:42 -07:00
committed by gVisor bot
parent 9800fd8e47
commit 3390012040
4 changed files with 40 additions and 10 deletions
+1
View File
@@ -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{}),
+29 -10
View File
@@ -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
}
+1
View File
@@ -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,
+9
View File
@@ -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 =