From e56e9a4e0bd6eca81ef4528918f296274e066668 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 20 Sep 2024 11:24:43 -0700 Subject: [PATCH 1/2] capability: fix "generated code" comment According to [1], the generated files should contain a comment which matches the following regexp: ^// Code generated .* DO NOT EDIT\.$ Fix accordingly. [1]: https://pkg.go.dev/cmd/go#hdr-Generate_Go_files_by_processing_source Signed-off-by: Kir Kolyshkin --- capability/enum_gen.go | 2 +- capability/enumgen/gen.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/capability/enum_gen.go b/capability/enum_gen.go index 2ff9bf4d..b5e5ccac 100644 --- a/capability/enum_gen.go +++ b/capability/enum_gen.go @@ -1,4 +1,4 @@ -// generated file; DO NOT EDIT - use go generate in directory with source +// Code generated by go generate; DO NOT EDIT. package capability diff --git a/capability/enumgen/gen.go b/capability/enumgen/gen.go index 2813e031..df5a169f 100644 --- a/capability/enumgen/gen.go +++ b/capability/enumgen/gen.go @@ -23,7 +23,7 @@ type generator struct { } func (g *generator) writeHeader() { - g.buf.WriteString("// generated file; DO NOT EDIT - use go generate in directory with source\n") + g.buf.WriteString("// Code generated by go generate; DO NOT EDIT.\n") g.buf.WriteString("\n") g.buf.WriteString("package capability") } From 166b98b9abc3f93bef88f97de11be54f4dcf0ec4 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 20 Sep 2024 12:28:56 -0700 Subject: [PATCH 2/2] capability: deprecate List, add ListKnown, ListSupported Apparently, most users of capability.List wants the list of supported capabilities (i.e. they go on to exclude capabilities above the last known one). Let's provide ListSupported to such users. Also, provide ListKnown, and deprecate List. Finally, amend LastCap documentation with a link to ListSupported, as this is what most users are using it for. Signed-off-by: Kir Kolyshkin --- capability/capability.go | 2 ++ capability/capability_test.go | 52 ++++++++++++++++++++++++++--------- capability/enum.go | 27 ++++++++++++++++++ capability/enum_gen.go | 3 +- capability/enumgen/gen.go | 3 +- 5 files changed, 70 insertions(+), 17 deletions(-) diff --git a/capability/capability.go b/capability/capability.go index e6e418a0..1b36f5f2 100644 --- a/capability/capability.go +++ b/capability/capability.go @@ -137,6 +137,8 @@ func NewFile2(path string) (Capabilities, error) { // LastCap returns highest valid capability of the running kernel, // or an error if it can not be obtained. +// +// See also: [ListSupported]. func LastCap() (Cap, error) { return lastCap() } diff --git a/capability/capability_test.go b/capability/capability_test.go index ec03f18a..bb405e6f 100644 --- a/capability/capability_test.go +++ b/capability/capability_test.go @@ -9,6 +9,18 @@ import ( "testing" ) +// Based on the fact Go 1.18+ supports Linux >= 2.6.32, and +// - CAP_MAC_ADMIN (33) was added in 2.6.25; +// - CAP_SYSLOG (34) was added in 2.6.38; +// - CAP_CHECKPOINT_RESTORE (40) was added in 5.9, and it is +// the last added capability as of today (July 2024); +// +// LastCap return value should be between minLastCap and maxLastCap. +const ( + minLastCap = CAP_MAC_ADMIN + maxLastCap = CAP_CHECKPOINT_RESTORE +) + func TestLastCap(t *testing.T) { last, err := LastCap() switch runtime.GOOS { @@ -24,21 +36,35 @@ func TestLastCap(t *testing.T) { } // Sanity checks (Linux only). - // - // Based on the fact Go 1.18+ supports Linux >= 2.6.32, and - // - CAP_MAC_ADMIN (33) was added in 2.6.25; - // - CAP_SYSLOG (34) was added in 2.6.38; - // - CAP_CHECKPOINT_RESTORE (40) was added in 5.9, and it is - // the last added capability as of today (July 2024); - // LastCap return value should be between minCap and maxCap. - minCap := CAP_MAC_ADMIN - maxCap := CAP_CHECKPOINT_RESTORE - if last < minCap { + if last < minLastCap { t.Fatalf("LastCap returned %d (%s), expected >= %d (%s)", - last, last, minCap, minCap) + last, last, minLastCap, minLastCap) } - if last > maxCap { + if last > maxLastCap { t.Fatalf("LastCap returned %d, expected <= %d (%s). Package needs to be updated.", - last, maxCap, maxCap) + last, maxLastCap, maxLastCap) + } +} + +func TestListSupported(t *testing.T) { + list, err := ListSupported() + switch runtime.GOOS { + case "linux": + if err != nil { + t.Fatal(err) + } + default: + if err == nil { + t.Fatal(runtime.GOOS, ": want error, got nil") + } + } + if runtime.GOOS != "linux" { + return + } + // Sanity check (Linux only). + t.Logf("got +%v (len %d)", list, len(list)) + minLen := int(minLastCap) + 1 + if len(list) < minLen { + t.Fatalf("result is too short (got %d, want %d): +%v", len(list), minLen, list) } } diff --git a/capability/enum.go b/capability/enum.go index bbbc84db..f89f0273 100644 --- a/capability/enum.go +++ b/capability/enum.go @@ -7,6 +7,8 @@ package capability +import "slices" + type CapType uint func (c CapType) String() string { @@ -301,3 +303,28 @@ const ( // Introduced in kernel 5.9 CAP_CHECKPOINT_RESTORE = Cap(40) ) + +// List returns the list of all capabilities known to the package. +// +// Deprecated: use [ListKnown] or [ListSupported] instead. +func List() []Cap { + return ListKnown() +} + +// ListKnown returns the list of all capabilities known to the package. +func ListKnown() []Cap { + return list() +} + +// ListSupported retuns the list of all capabilities known to the package, +// except those that are not supported by the currently running Linux kernel. +func ListSupported() ([]Cap, error) { + last, err := LastCap() + if err != nil { + return nil, err + } + return slices.DeleteFunc(list(), func(c Cap) bool { + // Remove caps not supported by the kernel. + return c > last + }), nil +} diff --git a/capability/enum_gen.go b/capability/enum_gen.go index b5e5ccac..f72cd43a 100644 --- a/capability/enum_gen.go +++ b/capability/enum_gen.go @@ -90,8 +90,7 @@ func (c Cap) String() string { return "unknown" } -// List returns list of all supported capabilities -func List() []Cap { +func list() []Cap { return []Cap{ CAP_CHOWN, CAP_DAC_OVERRIDE, diff --git a/capability/enumgen/gen.go b/capability/enumgen/gen.go index df5a169f..88d40cae 100644 --- a/capability/enumgen/gen.go +++ b/capability/enumgen/gen.go @@ -43,8 +43,7 @@ func (g *generator) writeStringFunc() { func (g *generator) writeListFunc() { g.buf.WriteString("\n") - g.buf.WriteString("// List returns list of all supported capabilities\n") - g.buf.WriteString("func List() []Cap {\n") + g.buf.WriteString("func list() []Cap {\n") g.buf.WriteString("return []Cap{\n") for _, cap := range g.caps { fmt.Fprintf(&g.buf, "%s,\n", cap)