-
Notifications
You must be signed in to change notification settings - Fork 18k
syscall.Faccessat and os.LookPath regression in Go 1.20 [1.20 backport] #58624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Labels
Milestone
Comments
Change https://go.dev/cl/469956 mentions this issue: |
Please consider this backport -- it is a serious regression in Go 1.20, preventing a binary from being executed in a certain scenario (see details in the original issue). |
34 tasks
Closed by merging aef8a8c to release-branch.go1.20. |
gopherbot
pushed a commit
that referenced
this issue
Feb 28, 2023
…E on Linux CL 416115 added using faccessat2(2) from syscall.Faccessat on Linux (which is the only true way to implement AT_EACCESS flag handing), if available. If not available, it uses some heuristics to mimic the kernel behavior, mostly taken from glibc (see CL 126415). Next, CL 414824 added using the above call (via unix.Eaccess) to exec.LookPath in order to check if the binary can really be executed. As a result, in a very specific scenario, described below, syscall.Faccessat (and thus exec.LookPath) mistakenly tells that the binary can not be executed, while in reality it can be. This makes this bug a regression in Go 1.20. This scenario involves all these conditions: - no faccessat2 support available (i.e. either Linux kernel < 5.8, or a seccomp set up to disable faccessat2); - the current user is not root (i.e. geteuid() != 0); - CAP_DAC_OVERRIDE capability is set for the current process; - the file to be executed does not have executable permission bit set for either the current EUID or EGID; - the file to be executed have at least one executable bit set. Unfortunately, this set of conditions was observed in the wild -- a container run as a non-root user with the binary file owned by root with executable permission set for a user only [1]. Essentially it means it is not as rare as it may seem. Now, CAP_DAC_OVERRIDE essentially makes the kernel bypass most of the checks, so execve(2) and friends work the same was as for root user, i.e. if at least one executable bit it set, the permission to execute is granted (see generic_permission() function in the Linux kernel). Modify the code to check for CAP_DAC_OVERRIDE and mimic the kernel behavior for permission checks. [1] opencontainers/runc#3715 For #58552. Fixes #58624. Change-Id: I82a7e757ab3fd3d0193690a65c3b48fee46ff067 Reviewed-on: https://go-review.googlesource.com/c/go/+/468735 Reviewed-by: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> (cherry picked from commit 031401a) Reviewed-on: https://go-review.googlesource.com/c/go/+/469956 Auto-Submit: Dmitri Shuralyov <[email protected]> Run-TryBot: Than McIntosh <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
romaindoumenc
pushed a commit
to TroutSoftware/go
that referenced
this issue
Mar 3, 2023
…E on Linux CL 416115 added using faccessat2(2) from syscall.Faccessat on Linux (which is the only true way to implement AT_EACCESS flag handing), if available. If not available, it uses some heuristics to mimic the kernel behavior, mostly taken from glibc (see CL 126415). Next, CL 414824 added using the above call (via unix.Eaccess) to exec.LookPath in order to check if the binary can really be executed. As a result, in a very specific scenario, described below, syscall.Faccessat (and thus exec.LookPath) mistakenly tells that the binary can not be executed, while in reality it can be. This makes this bug a regression in Go 1.20. This scenario involves all these conditions: - no faccessat2 support available (i.e. either Linux kernel < 5.8, or a seccomp set up to disable faccessat2); - the current user is not root (i.e. geteuid() != 0); - CAP_DAC_OVERRIDE capability is set for the current process; - the file to be executed does not have executable permission bit set for either the current EUID or EGID; - the file to be executed have at least one executable bit set. Unfortunately, this set of conditions was observed in the wild -- a container run as a non-root user with the binary file owned by root with executable permission set for a user only [1]. Essentially it means it is not as rare as it may seem. Now, CAP_DAC_OVERRIDE essentially makes the kernel bypass most of the checks, so execve(2) and friends work the same was as for root user, i.e. if at least one executable bit it set, the permission to execute is granted (see generic_permission() function in the Linux kernel). Modify the code to check for CAP_DAC_OVERRIDE and mimic the kernel behavior for permission checks. [1] opencontainers/runc#3715 For golang#58552. Fixes golang#58624. Change-Id: I82a7e757ab3fd3d0193690a65c3b48fee46ff067 Reviewed-on: https://go-review.googlesource.com/c/go/+/468735 Reviewed-by: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> (cherry picked from commit 031401a) Reviewed-on: https://go-review.googlesource.com/c/go/+/469956 Auto-Submit: Dmitri Shuralyov <[email protected]> Run-TryBot: Than McIntosh <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
kolyshkin
added a commit
to kolyshkin/runc
that referenced
this issue
Mar 8, 2023
Go 1.20.2 has an important fix to an issue described in [1]. Switch from using Go 1.19 from Dockerfile (used for release binaries and some CI) as well as from cirrus-ci. Note in cirrus-ci we have to specify the patch number explicitly, as otherwise go 1.20 will be used, while in Dockerfile saying 1.20 means to use 1.20.x (which is 1.20.2 now). [1] golang/go#58624 Signed-off-by: Kir Kolyshkin <[email protected]>
kolyshkin
added a commit
to kolyshkin/runc
that referenced
this issue
Mar 9, 2023
Go 1.20.2 has an important fix to an issue described in [1]. Switch from using Go 1.19 from Dockerfile (used for release binaries and some CI) as well as from cirrus-ci. Note in cirrus-ci we have to specify the patch number explicitly, as otherwise go 1.20 will be used, while in Dockerfile saying 1.20 means to use 1.20.x (which is 1.20.2 now). [1] golang/go#58624 Signed-off-by: Kir Kolyshkin <[email protected]>
kolyshkin
added a commit
to kolyshkin/runc
that referenced
this issue
Mar 16, 2023
Go 1.20.2 has an important fix to an issue described in [1]. Switch from using Go 1.19 from Dockerfile (used for release binaries and some CI) as well as from cirrus-ci. Note in cirrus-ci we have to specify the patch number explicitly, as otherwise go 1.20 will be used, while in Dockerfile saying 1.20 means to use 1.20.x (which is 1.20.2 now). [1] golang/go#58624 Signed-off-by: Kir Kolyshkin <[email protected]>
kolyshkin
added a commit
to kolyshkin/runc
that referenced
this issue
Mar 27, 2023
Go 1.20.2 has an important fix to an issue described in [1]. Switch from using Go 1.19 from Dockerfile, which is used for release binaries and some CI. [1] golang/go#58624 Signed-off-by: Kir Kolyshkin <[email protected]>
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
@kolyshkin requested issue #58552 to be considered for backport to the next 1.20 minor release.
The text was updated successfully, but these errors were encountered: