Skip to content

os/exec: add way to influence the ambient capability set on Linux #19713

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

Closed
stapelberg opened this issue Mar 25, 2017 · 4 comments
Closed

os/exec: add way to influence the ambient capability set on Linux #19713

stapelberg opened this issue Mar 25, 2017 · 4 comments
Labels
FeatureRequest Issues asking for a new feature that does not need a proposal. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@stapelberg
Copy link
Contributor

Motivation

I’d like to use capabilities in order to run unprivileged programs under unprivileged user accounts with only precisely the capabilities the program needs. A concrete example is removing all privileges but CAP_SYS_TIME from an NTP client.

Example/details on what’s not working

Unfortunately, it seems like Go currently doesn’t provide a way to do this.

Here are 2 example programs:

  1. https://play.golang.org/p/_EN2RzKPE3 prints the current capabilities and tries to enable CAP_SYS_TIME
  2. https://play.golang.org/p/Yk6AKHyJGw sets the CAP_SYS_TIME capability in the inheritable and ambient capability set, then runs the first example program.

The output of program 2 is:

2017/03/25 17:58:00 ntp.go:17: caps = { effective="empty" permitted="empty" inheritable="sys_time" bounding="full" }
2017/03/25 17:58:00 ntp.go:22: could not apply caps: operation not permitted
2017/03/25 17:58:00 exit status 1

I would have expected the program to include sys_time in its effective capabilities set and not report an error.

Upon closer investigation, it turns out that setuid(2) clears the ambient capability set. Since forkAndExecInChild (src/syscall/exec_linux.go) applies cmd.SysProcAttr.Credential using setuid(2), the ambient capability set is cleared before my program is started.

Looking at systemd, you can see that they restore the ambient capability set after applying credentials: https://github.com/systemd/systemd/blob/1539a651a9d31c18273df917bbfe175ab3606025/src/core/execute.c#L2711-L2748

Proof of concept

Directly modifying the standard library to set the CAP_SYS_TIME capability as follows…

--- i/src/syscall/exec_linux.go
+++ w/src/syscall/exec_linux.go
@@ -227,6 +227,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
                if err1 != 0 {
                        goto childerror
                }
+
+               _, _, err1 = RawSyscall(SYS_PRCTL, 47 /* PR_CAP_AMBIENT */, uintptr(2), uintptr(25) /* TIME */)
+               if err1 != 0 {
+                     goto childerror
+               }
        }
 
        // Chdir

…results in my test programs working:

2017/03/25 17:50:52 ntp.go:18: caps = { effective="sys_time" permitted="sys_time" inheritable="sys_time" bounding="full" }
2017/03/25 17:50:52 ntp.go:22: now: { effective="sys_time" permitted="sys_time" inheritable="sys_time" bounding="full" }

Question

Would a CL which adds an ambient capability struct member to syscall.SysProcAttr be accepted? If not, which other way would you recommend for starting processes with an ambient capability set?

Further reading

@bradfitz
Copy link
Contributor

Sounds reasonable. @ianlancetaylor?

@bradfitz bradfitz added this to the Go1.9Maybe milestone Mar 25, 2017
@bradfitz bradfitz added FeatureRequest Issues asking for a new feature that does not need a proposal. NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. labels Mar 25, 2017
@ianlancetaylor
Copy link
Member

Yes, I think it would be OK to add a uint64 to syscall.SysProcAttr on GNU/Linux systems to specify the set of ambient capabilities to install.

@ianlancetaylor ianlancetaylor removed the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Apr 7, 2017
@stapelberg
Copy link
Contributor Author

Great. I’ll send a CL.

@gopherbot
Copy link
Contributor

CL https://golang.org/cl/43512 mentions this issue.

@bradfitz bradfitz added the NeedsFix The path to resolution is known, but the work has not been done. label Jun 27, 2017
@golang golang locked and limited conversation to collaborators Jun 28, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FeatureRequest Issues asking for a new feature that does not need a proposal. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

4 participants