-
Notifications
You must be signed in to change notification settings - Fork 43
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
capability: add separate ambient and bound API #176
Conversation
Signed-off-by: Kir Kolyshkin <[email protected]>
Signed-off-by: lifubang <[email protected]> Signed-off-by: Kir Kolyshkin <[email protected]>
All the prctl calls that we make (or can potentially make) are limited to 3 arguments, so it's sufficient to use Syscall (rather than Syscall6). This is mostly a cosmetic change. Signed-off-by: Kir Kolyshkin <[email protected]>
RawSyscall is preferable for syscalls that do not block, and neither of the ones used by this package do. This makes the whole thing a bit faster. Signed-off-by: Kir Kolyshkin <[email protected]>
We need to lock OS thread as this library deals with per-thread capabilities. Signed-off-by: Kir Kolyshkin <[email protected]>
func ignoreEINVAL(err error) error { | ||
if errors.Is(err, syscall.EINVAL) { | ||
err = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reminds me that I stumbled on this package which had a "consider integrating with moby/sys todo; https://github.com/moby/moby/blob/dc225798cbddebd47bfaa0fd8337d145c91fc6ba/internal/unix_noeintr/fs_unix.go#L3-L5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That thing in there is something entirely different -- it's a retry-on-EINTR, and here we have ignore-EINVAL.
As to autogenerating stuff, even github.com/golang/go doesn't do it -- they use helper functions here and there but it's all manual.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
log.Fatalf("Get(AMBIENT, %s): want %v, got %v", cap, want, got) | ||
} | ||
} | ||
os.Exit(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL, had to look twice, but then saw it's called from testInChild
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it's somewhat complicated here since we modify capabilities and if we do it in a current process the following tests are toasted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm way outside my understanding, but isn't that what runtime.LockOSThread
is for/does?
(makes sure the capabilities are adjusted for the thread we're on, and then if we don't unlock the thread, it exits instead of being reused?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are actually re-executing the test binary here (or, rather, in testInChild
), so here we have a separate process (not a bare go thread) running.
It never occurred to be we can test all this in a separate go thread (rather than a process). Let me give it a try :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quickly tried that and it did't work. I'll add it to TODO and merge this as is for now, since it's just a test case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, the runtime.LockOSThread()
, as added, is needed so that Go runtime won't suddenly switch the goroutine to other OS thread while we run the test.
Practically, for users of this package, it means we need to change capabilities (in a locked OS thread) and then re-exec (which is what runc does).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was looking at capabilities being a per thread attribute and scratching my beard 😂 sorry it didn't work out, but at least now you know!
@AkihiroSuda @tianon ptal |
capability/syscall_linux.go
Outdated
func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { | ||
_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) | ||
func prctl(option int, arg2, arg3 uintptr) (err error) { | ||
_, _, e1 := syscall.Syscall(syscall.SYS_PRCTL, uintptr(option), arg2, arg3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could've sworn these numbered ones were deprecated, but that was for windows there they added a SyscallN()
; https://github.com/golang/go/blob/6d39245514c675cdea5c7fd7f778e97bf0728dd5/src/syscall/dll_windows.go#L27-L45
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonder why they did this change only for Windows. Perhaps it's better aligned to native windows apis.
The API is the same as in kernel.org/pub/linux/libs/security/libcap/cap package, although the implementation is a bit simpler (here we only set capabilities for the calling thread). Co-authored-by: lifubang <[email protected]> Signed-off-by: Kir Kolyshkin <[email protected]>
6449fa9
to
c61ae88
Compare
This removes the last unversioned package in runc's direct dependencies. Draft pending moby/sys#176 merge and v0.4.0 release. Signed-off-by: Kir Kolyshkin <[email protected]>
This removes the last unversioned package in runc's direct dependencies. Draft pending moby/sys#176 merge and v0.4.0 release. Signed-off-by: Kir Kolyshkin <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good (and IMO totally fine to merge as-is) -- I left a couple questions, but I don't think they're super important.
capability/capability_linux.go
Outdated
} | ||
if (1<<uint(CAP_SETPCAP))&data[0].effective != 0 { | ||
for i := Cap(0); i <= last; i++ { | ||
if c.Get(BOUNDING, i) { | ||
continue | ||
} | ||
err = prctl(syscall.PR_CAPBSET_DROP, uintptr(i), 0, 0, 0) | ||
// Ignore EINVAL since the capability may not be supported in this system. | ||
err = ignoreEINVAL(prctl(syscall.PR_CAPBSET_DROP, uintptr(i), 0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a huge deal (certainly not a dealbreaker), but it does seem weird to still use prctl
directly here when all the rest have switched to your new wrappers -- was there a reason not to use dropBound
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch, thanks!
I added GetBound/DropBound at the last moment, and this here is part of an earlier patch. Still makes sense to use dropBound here -- updated.
log.Fatalf("Get(AMBIENT, %s): want %v, got %v", cap, want, got) | ||
} | ||
} | ||
os.Exit(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm way outside my understanding, but isn't that what runtime.LockOSThread
is for/does?
(makes sure the capabilities are adjusted for the thread we're on, and then if we don't unlock the thread, it exits instead of being reused?)
Signed-off-by: Kir Kolyshkin <[email protected]>
c61ae88
to
c1ade77
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API being added is the same as in kernel.org/pub/linux/libs/security/libcap/cap
package, although the implementation is a bit simpler (here we only set
capabilities for the calling thread).
With this, we can switch runc to moby/sys/capability.
Co-authored-by: @lifubang
Closes: #165