From 619de4f01ea85dc9f80c7447c222d35e68fea9eb Mon Sep 17 00:00:00 2001 From: lifubang Date: Sat, 5 Oct 2024 10:10:17 +0800 Subject: [PATCH 1/3] capability: improve error handling for func Apply Signed-off-by: lifubang --- capability/capability_linux.go | 43 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/capability/capability_linux.go b/capability/capability_linux.go index 07321955..4fabeae3 100644 --- a/capability/capability_linux.go +++ b/capability/capability_linux.go @@ -117,6 +117,13 @@ func newPid(pid int) (c Capabilities, retErr error) { return } +func ignoreEINVAL(err error) error { + if errors.Is(err, syscall.EINVAL) { + err = nil + } + return err +} + type capsV3 struct { hdr capHeader data [2]capData @@ -327,7 +334,7 @@ func (c *capsV3) Load() (err error) { return } -func (c *capsV3) Apply(kind CapType) (err error) { +func (c *capsV3) Apply(kind CapType) error { last, err := LastCap() if err != nil { return err @@ -336,21 +343,17 @@ func (c *capsV3) Apply(kind CapType) (err error) { var data [2]capData err = capget(&c.hdr, &data[0]) if err != nil { - return + return err } if (1< Date: Sat, 5 Oct 2024 10:17:07 +0800 Subject: [PATCH 2/3] capability: add some api for ambient cap Signed-off-by: lifubang --- capability/capability.go | 15 +++++++++++++++ capability/capability_linux.go | 26 ++++++++++++++++++++++++-- capability/capability_noop.go | 12 ++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/capability/capability.go b/capability/capability.go index 1b36f5f2..0412cb5f 100644 --- a/capability/capability.go +++ b/capability/capability.go @@ -142,3 +142,18 @@ func NewFile2(path string) (Capabilities, error) { func LastCap() (Cap, error) { return lastCap() } + +// AmbientRaise raises specified ambient capabilities for the calling process. +func AmbientRaise(cap ...Cap) error { + return ambientRaise(cap...) +} + +// AmbientLower lowers specified ambient capabilities for the calling process. +func AmbientLower(cap ...Cap) error { + return ambientLower(cap...) +} + +// AmbientClearAll lowers all ambient capabilities for the calling process. +func AmbientClearAll() error { + return ambientClearAll() +} diff --git a/capability/capability_linux.go b/capability/capability_linux.go index 4fabeae3..cefa0ac5 100644 --- a/capability/capability_linux.go +++ b/capability/capability_linux.go @@ -368,7 +368,7 @@ func (c *capsV3) Apply(kind CapType) error { if kind&AMBS == AMBS { // Ignore EINVAL as not supported on kernels before 4.3 - err = ignoreEINVAL(prctl(pr_CAP_AMBIENT, pr_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0)) + err = ignoreEINVAL(ambientClearAll()) if err != nil { return err } @@ -377,7 +377,7 @@ func (c *capsV3) Apply(kind CapType) error { continue } // Ignore EINVAL as not supported on kernels before 4.3 - err = ignoreEINVAL(prctl(pr_CAP_AMBIENT, pr_CAP_AMBIENT_RAISE, uintptr(i), 0, 0)) + err = ignoreEINVAL(ambientRaise(i)) if err != nil { return err } @@ -387,6 +387,28 @@ func (c *capsV3) Apply(kind CapType) error { return nil } +func setAmbient(op uintptr, cap ...Cap) error { + for _, val := range cap { + err := prctl(pr_CAP_AMBIENT, op, uintptr(val), 0, 0) + if err != nil { + return err + } + } + return nil +} + +func ambientRaise(cap ...Cap) error { + return setAmbient(pr_CAP_AMBIENT_RAISE, cap...) +} + +func ambientLower(cap ...Cap) error { + return setAmbient(pr_CAP_AMBIENT_LOWER, cap...) +} + +func ambientClearAll() error { + return prctl(pr_CAP_AMBIENT, pr_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) +} + func newFile(path string) (c Capabilities, err error) { c = &capsFile{path: path} return diff --git a/capability/capability_noop.go b/capability/capability_noop.go index ba819ff0..2138195f 100644 --- a/capability/capability_noop.go +++ b/capability/capability_noop.go @@ -24,3 +24,15 @@ func newFile(_ string) (Capabilities, error) { func lastCap() (Cap, error) { return -1, errNotSup } + +func ambientRaise(cap ...Cap) error { + return errNotSup +} + +func ambientLower(cap ...Cap) error { + return errNotSup +} + +func ambientClearAll() error { + return errNotSup +} From 11c8cd16a40a8de891bccc9344097797dfe66b44 Mon Sep 17 00:00:00 2001 From: lifubang Date: Sun, 13 Oct 2024 18:17:54 +0800 Subject: [PATCH 3/3] add test for Ambient API Signed-off-by: lifubang --- capability/capability_test.go | 71 ++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/capability/capability_test.go b/capability/capability_test.go index 2b901ad3..4a14474c 100644 --- a/capability/capability_test.go +++ b/capability/capability_test.go @@ -137,7 +137,7 @@ func TestNewPid2Load(t *testing.T) { } } -func TestAmbientCapSet(t *testing.T) { +func TestApplyCaps(t *testing.T) { if runtime.GOOS != "linux" { return } @@ -193,3 +193,72 @@ func childAmbientCapSet() { } os.Exit(0) } + +func TestAmbientCapAPI(t *testing.T) { + if runtime.GOOS != "linux" { + return + } + requirePCapSet(t) + + out := testInChild(t, childAmbientCapSetByAPI) + + t.Logf("output from child:\n%s", out) +} + +func childAmbientCapSetByAPI() { + log.SetFlags(log.Lshortfile) + + pid, err := NewPid2(0) + if err != nil { + log.Fatal(err) + } + + list := []Cap{CAP_KILL, CAP_CHOWN, CAP_SYS_CHROOT} + pid.Set(CAPS|AMBIENT, list...) + if err = pid.Apply(CAPS); err != nil { + log.Fatal(err) + } + if err = AmbientRaise(list...); err != nil { + log.Fatal(err) + } + + // Check if ambient caps were raised. + if err = pid.Load(); err != nil { + log.Fatal(err) + } + for _, cap := range list { + want := true + if got := pid.Get(AMBIENT, cap); want != got { + log.Fatalf("Get(AMBIENT, %s): want %v, got %v", cap, want, got) + } + } + + // Lower one ambient cap. + const unsetIdx = 1 + if err = AmbientLower(list[unsetIdx]); err != nil { + log.Fatal(err) + } + if err = pid.Load(); err != nil { + log.Fatal(err) + } + for i, cap := range list { + want := i != unsetIdx + if got := pid.Get(AMBIENT, cap); want != got { + log.Fatalf("Get(AMBIENT, %s): want %v, got %v", cap, want, got) + } + } + + // Lower all ambient caps + if err = AmbientClearAll(); err != nil { + log.Fatal(err) + } + if err = pid.Load(); err != nil { + log.Fatal(err) + } + for _, cap := range list { + if got := pid.Get(AMBIENT, cap); got { + log.Fatalf("Get(AMBIENT, %s): want false, got %v", cap, got) + } + } + os.Exit(0) +}