diff --git a/pkg/sentry/fsimpl/cgroupfs/base.go b/pkg/sentry/fsimpl/cgroupfs/base.go index 862c82a33..9d039ac11 100644 --- a/pkg/sentry/fsimpl/cgroupfs/base.go +++ b/pkg/sentry/fsimpl/cgroupfs/base.go @@ -163,7 +163,7 @@ type cgroupInode struct { var _ kernel.CgroupImpl = (*cgroupInode)(nil) -func (fs *filesystem) newCgroupInode(ctx context.Context, creds *auth.Credentials, parent *cgroupInode) kernfs.Inode { +func (fs *filesystem) newCgroupInode(ctx context.Context, creds *auth.Credentials, parent *cgroupInode, mode linux.FileMode) kernfs.Inode { c := &cgroupInode{ dir: dir{fs: fs}, ts: make(map[*kernel.Task]struct{}), @@ -190,7 +190,7 @@ func (fs *filesystem) newCgroupInode(ctx context.Context, creds *auth.Credential } } - c.dir.InodeAttrs.Init(ctx, creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|linux.FileMode(0555)) + c.dir.InodeAttrs.Init(ctx, creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), mode) c.dir.OrderedChildren.Init(kernfs.OrderedChildrenOptions{Writable: true}) c.dir.IncLinks(c.dir.OrderedChildren.Populate(contents)) diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go index fe765d0c8..5ba44d6e0 100644 --- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go +++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go @@ -78,9 +78,11 @@ import ( const ( // Name is the default filesystem name. - Name = "cgroup" - readonlyFileMode = linux.FileMode(0444) - writableFileMode = linux.FileMode(0644) + Name = "cgroup" + readonlyFileMode = linux.FileMode(0444) + writableFileMode = linux.FileMode(0644) + defaultDirMode = linux.FileMode(0555) | linux.ModeDirectory + defaultMaxCachedDentries = uint64(1000) ) @@ -297,7 +299,7 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt fs.kcontrollers = append(fs.kcontrollers, c) } - root := fs.newCgroupInode(ctx, creds, nil) + root := fs.newCgroupInode(ctx, creds, nil, defaultDirMode) var rootD kernfs.Dentry rootD.InitRoot(&fs.Filesystem, root) fs.root = &rootD @@ -346,7 +348,7 @@ func (fs *filesystem) prepareInitialCgroup(ctx context.Context, vfsObj *vfs.Virt // Have initial cgroup target, create the tree. cgDir := fs.root.Inode().(*cgroupInode) for pit := initPath.Begin; pit.Ok(); pit = pit.Next() { - cgDirI, err := cgDir.NewDir(ctx, pit.String(), vfs.MkdirOptions{}) + cgDirI, err := cgDir.NewDir(ctx, pit.String(), vfs.MkdirOptions{Mode: defaultDirMode}) if err != nil { return err } @@ -452,9 +454,10 @@ func (d *dir) NewDir(ctx context.Context, name string, opts vfs.MkdirOptions) (k if strings.Contains(name, "\n") { return nil, linuxerr.EINVAL } + mode := opts.Mode.Permissions() | linux.ModeDirectory return d.OrderedChildren.Inserter(name, func() kernfs.Inode { d.IncLinks(1) - return d.fs.newCgroupInode(ctx, auth.CredentialsFromContext(ctx), d.cgi) + return d.fs.newCgroupInode(ctx, auth.CredentialsFromContext(ctx), d.cgi, mode) }) } diff --git a/test/syscalls/linux/cgroup.cc b/test/syscalls/linux/cgroup.cc index ede156706..7d1e58f0a 100644 --- a/test/syscalls/linux/cgroup.cc +++ b/test/syscalls/linux/cgroup.cc @@ -457,7 +457,8 @@ TEST(Cgroup, DirSetStat) { Cgroup child = ASSERT_NO_ERRNO_AND_VALUE(c.CreateChild("child")); const struct stat child_before = ASSERT_NO_ERRNO_AND_VALUE(Stat(child.Path())); - EXPECT_THAT(child_before.st_mode, PermissionIs(0555)); // Default. + // Mkdir passes 0755 by default. + EXPECT_THAT(child_before.st_mode, PermissionIs(0755)); ASSERT_NO_ERRNO(Chmod(child.Path(), 0757)); const struct stat child_after = ASSERT_NO_ERRNO_AND_VALUE(Stat(child.Path())); @@ -468,6 +469,25 @@ TEST(Cgroup, DirSetStat) { EXPECT_THAT(parent_after.st_mode, PermissionIs(0755)); } +TEST(Cgroup, MkdirWithPermissions) { + SKIP_IF(!CgroupsAvailable()); + Mounter m(ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir())); + Cgroup c = ASSERT_NO_ERRNO_AND_VALUE(m.MountCgroupfs("")); + + std::string child1_path = JoinPath(c.Path(), "child1"); + std::string child2_path = JoinPath(c.Path(), "child2"); + + ASSERT_NO_ERRNO(Mkdir(child1_path, 0444)); + const struct stat s1 = ASSERT_NO_ERRNO_AND_VALUE(Stat(child1_path)); + EXPECT_THAT(s1.st_mode, PermissionIs(0444)); + EXPECT_TRUE(S_ISDIR(s1.st_mode)); + + ASSERT_NO_ERRNO(Mkdir(child2_path, 0)); + const struct stat s2 = ASSERT_NO_ERRNO_AND_VALUE(Stat(child2_path)); + EXPECT_THAT(s2.st_mode, PermissionIs(0000)); + EXPECT_TRUE(S_ISDIR(s2.st_mode)); +} + TEST(MemoryCgroup, MemoryUsageInBytes) { SKIP_IF(!CgroupsAvailable());