aboutsummaryrefslogtreecommitdiff
path: root/cap/convenience.go
diff options
context:
space:
mode:
Diffstat (limited to 'cap/convenience.go')
-rw-r--r--cap/convenience.go62
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])
}