Skip to content

Commit

Permalink
Fix runc run "permission denied" when rootless
Browse files Browse the repository at this point in the history
Since commit 957d97b was made to fix issue [7],
a few things happened:

- a similar functionality appeared in go 1.20 [1], so the issue
  mentioned in the comment (being removed) is no longer true;
- a bug in runc was found [2], which also affects go [3];
- the bug was fixed in go 1.21 [4] and 1.20.2 [5];
- a similar fix was made to x/sys/unix.Faccessat [6].

The essense of [2] is, even if a (non-root) user that the container is
run as does not have execute permission bit set for the executable, it
should still work in case runc has the CAP_DAC_OVERRIDE capability set.

To fix this [2] without reintroducing the older bug [7]:
- drop own Eaccess implementation;
- use the one from x/sys/unix for Go 1.19 (depends on [6]);
- do not use anything when Go 1.20+ is used.

NOTE it is virtually impossible to fix the bug [2] when Go 1.20 or Go
1.20.1 is used because of [3].

A test case is added by a separate commit.

Fixes: #3715.

[1] https://go-review.googlesource.com/c/go/+/414824
[2] opencontainers/runc#3715
[3] https://go.dev/issue/58552
[4] https://go-review.googlesource.com/c/go/+/468735
[5] https://go-review.googlesource.com/c/go/+/469956
[6] https://go-review.googlesource.com/c/sys/+/468877
[7] opencontainers/runc#3520

Signed-off-by: Kir Kolyshkin <[email protected]>
(cherry picked from commit 8491d33)
Signed-off-by: Kir Kolyshkin <[email protected]>
  • Loading branch information
kolyshkin committed Apr 7, 2023
1 parent ea9fb99 commit a868c2b
Showing 1 changed file with 0 additions and 19 deletions.
19 changes: 0 additions & 19 deletions libcontainer/system/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,6 @@ func (p ParentDeathSignal) Set() error {
return SetParentDeathSignal(uintptr(p))
}

// Eaccess is similar to unix.Access except for setuid/setgid binaries
// it checks against the effective (rather than real) uid and gid.
func Eaccess(path string) error {
err := unix.Faccessat2(unix.AT_FDCWD, path, unix.X_OK, unix.AT_EACCESS)
if err != unix.ENOSYS && err != unix.EPERM { //nolint:errorlint // unix errors are bare
return err
}

// Faccessat2() not available; check if we are a set[ug]id binary.
if os.Getuid() == os.Geteuid() && os.Getgid() == os.Getegid() {
// For a non-set[ug]id binary, use access(2).
return unix.Access(path, unix.X_OK)
}

// For a setuid/setgid binary, there is no fallback way
// so assume we can execute the binary.
return nil
}

func Execv(cmd string, args []string, env []string) error {
name, err := exec.LookPath(cmd)
if err != nil {
Expand Down

0 comments on commit a868c2b

Please sign in to comment.