diff options
Diffstat (limited to 'cap/convenience.go')
-rw-r--r-- | cap/convenience.go | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/cap/convenience.go b/cap/convenience.go index 9580903..d604ad1 100644 --- a/cap/convenience.go +++ b/cap/convenience.go @@ -2,6 +2,7 @@ package cap import ( "errors" + "fmt" "syscall" "unsafe" ) @@ -33,6 +34,7 @@ const ( // defines from uapi/linux/prctl.h const ( + prGetKeepCaps = 7 prSetKeepCaps = 8 prGetSecureBits = 27 prSetSecureBits = 28 @@ -57,9 +59,9 @@ func (sc *syscaller) setSecbits(s Secbits) error { // will raise cap.SETPCAP in order to achieve this operation, and will // completely lower the Effective vector of the process returning. func (s Secbits) Set() error { - scwMu.Lock() - defer scwMu.Unlock() - return multisc.setSecbits(s) + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setSecbits(s) } // Mode summarizes a complicated secure-bits and capability mode in a @@ -181,9 +183,9 @@ func (sc *syscaller) setMode(m Mode) error { // permission or because (some of) the Secbits are already locked for // the current process. func (m Mode) Set() error { - scwMu.Lock() - defer scwMu.Unlock() - return multisc.setMode(m) + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setMode(m) } // String returns the libcap conventional string for this mode. @@ -238,9 +240,9 @@ func (sc *syscaller) setUID(uid int) error { // performs a change of UID cap.SETUID is available, and the action // does not alter the Permitted Flag of the process' Set. func SetUID(uid int) error { - scwMu.Lock() - defer scwMu.Unlock() - return multisc.setUID(uid) + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setUID(uid) } //go:uintptrescapes @@ -286,7 +288,43 @@ func (sc *syscaller) setGroups(gid int, suppl []int) error { // completely lower the Effective Flag of the process Set before // returning. func SetGroups(gid int, suppl ...int) error { - scwMu.Lock() - defer scwMu.Unlock() - return multisc.setGroups(gid, suppl) + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setGroups(gid, suppl) +} + +//go:uintptrescapes + +// Prctlw is a convenience function for performing a syscall.Prctl() +// call that executes on all the threads of the process. It is called +// Prctlw because it is only appropriate to call this function when it +// is writing thread state that the caller wants to set on all OS +// threads of the process to observe POSIX semantics when Linux +// doesn't natively honor them. (Check prctl documentation for when it +// is appropriate to use this vs. a normal syscall.Prctl() call.) +func Prctlw(prVal uintptr, args ...uintptr) (int, error) { + if n := len(args); n > 5 { + return -1, fmt.Errorf("prctl supports up to 5 arguments (not %d)", n) + } + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + as := make([]uintptr, 5) + copy(as, args) + return sc.prctlwcall6(prVal, as[0], as[1], as[2], as[3], as[4]) +} + +//go:uintptrescapes + +// Prctl is a convenience function that performs a syscall.Prctl() +// that either reads state using a single OS thread, or performs a +// Prctl that is treated as a process wide setting. It is provided for +// symmetry reasons, but is equivalent to simply calling the +// corresponding syscall function. +func Prctl(prVal uintptr, args ...uintptr) (int, error) { + if n := len(args); n > 5 { + return -1, fmt.Errorf("prctl supports up to 5 arguments (not %d)", n) + } + as := make([]uintptr, 5) + copy(as, args) + return singlesc.prctlrcall6(prVal, as[0], as[1], as[2], as[3], as[4]) } |