Skip to content

Commit

Permalink
fix: oci: enter cgroup before executing crun as non-root
Browse files Browse the repository at this point in the history
When executed from a root-owned cgroup, such as the session scope
resulting from a bare ssh login, crun will fail to create our
requested container cgroup.

If we are running as non-root, create and move into a user-owned
cgroup, so that there's a common user-owned ancestor. This avoids the
`crun` error.

Note that no workaround is needed for `runc` as it is able to create
the requested container cgroup without any issue.

Fixes sylabs#1538
  • Loading branch information
dtrudg committed Apr 11, 2023
1 parent bea0b04 commit 61871c7
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
inner id mapping is applied correctly.
- Use `/dev/loop-control` for loop device creation, to avoid issues with recent
kernel patch where `max_loop` is not set.
- Avoid `runc` cgroup creation error when using `--oci` from a root-owned cgroup (e.g.
ssh login session scope).

## 3.11.1 \[2023-03-14\]

Expand Down
37 changes: 37 additions & 0 deletions internal/pkg/runtime/launcher/oci/launcher_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,11 @@ func (l *Launcher) Exec(ctx context.Context, image string, process string, args
return fmt.Errorf("launcher SysContext must be set for OCI image handling")
}

// If we need to, enter a new cgroup to workaround an issue with crun container cgroup creation (#1538).
if err := l.crunNestCgroup(); err != nil {
return fmt.Errorf("while applying crun cgroup workaround: %w", err)
}

bundleDir, err := os.MkdirTemp("", "oci-bundle")
if err != nil {
return nil
Expand Down Expand Up @@ -439,6 +444,38 @@ func (l *Launcher) getCgroup() (path string, resources *specs.LinuxResources, er
return path, resources, nil
}

// crunNestCgroup will check whether we are using crun, and enter a cgroup if running as a non-root user.
// This is required to satisfy a common user-owned ancestor cgroup requirement on e.g. bare ssh logins.
// See: https://github.com/sylabs/singularity/issues/1538
func (l *Launcher) crunNestCgroup() error {
r, err := runtime()
if err != nil {
return err
}

// No workaround required for runc.
if filepath.Base(r) == "runc" {
return nil
}

// No workaround required if we are run as root.
if os.Getuid() == 0 {
return nil
}

// We are running crun as a user. Enter a cgroup now.
pid := os.Getpid()
sylog.Debugf("crun workaround - adding process %d to sibling cgroup", pid)
manager, err := cgroups.NewManagerWithSpec(&specs.LinuxResources{}, pid, "", l.singularityConf.SystemdCgroups)
if err != nil {
return fmt.Errorf("couldn't create cgroup manager: %w", err)
}
cgPath, _ := manager.GetCgroupRelPath()
sylog.Debugf("In sibling cgroup: %s", cgPath)

return nil
}

func mergeMap(a map[string]string, b map[string]string) map[string]string {
for k, v := range b {
a[k] = v
Expand Down

0 comments on commit 61871c7

Please sign in to comment.