From b39064037625d1757a65913086ec3a247ad5bb29 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Fri, 10 Apr 2026 23:56:45 +0900 Subject: internal/landlock: relocate from package container This is not possible to use directly, so remove it from the public API. Signed-off-by: Ophestra --- container/container.go | 11 +- container/container_test.go | 3 +- container/landlock.go | 259 ------------------------------------- container/landlock_test.go | 65 ---------- internal/landlock/landlock.go | 259 +++++++++++++++++++++++++++++++++++++ internal/landlock/landlock_test.go | 65 ++++++++++ internal/pkg/pkg_test.go | 3 +- 7 files changed, 335 insertions(+), 330 deletions(-) delete mode 100644 container/landlock.go delete mode 100644 container/landlock_test.go create mode 100644 internal/landlock/landlock.go create mode 100644 internal/landlock/landlock_test.go diff --git a/container/container.go b/container/container.go index aeea3dcc..a798084a 100644 --- a/container/container.go +++ b/container/container.go @@ -21,6 +21,7 @@ import ( "hakurei.app/container/std" "hakurei.app/ext" "hakurei.app/fhs" + "hakurei.app/internal/landlock" "hakurei.app/message" ) @@ -317,12 +318,14 @@ func (p *Container) Start() error { // landlock: depends on per-thread state but acts on a process group { - rulesetAttr := &RulesetAttr{Scoped: LANDLOCK_SCOPE_SIGNAL} + rulesetAttr := &landlock.RulesetAttr{ + Scoped: landlock.LANDLOCK_SCOPE_SIGNAL, + } if !p.HostAbstract { - rulesetAttr.Scoped |= LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET + rulesetAttr.Scoped |= landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET } - if abi, err := LandlockGetABI(); err != nil { + if abi, err := landlock.GetABI(); err != nil { if p.HostAbstract || !p.HostNet { // landlock can be skipped here as it restricts access // to resources already covered by namespaces (pid, net) @@ -351,7 +354,7 @@ func (p *Container) Start() error { } } else { p.msg.Verbosef("enforcing landlock ruleset %s", rulesetAttr) - if err = LandlockRestrictSelf(rulesetFd, 0); err != nil { + if err = landlock.RestrictSelf(rulesetFd, 0); err != nil { _ = Close(rulesetFd) return &StartError{ Fatal: true, diff --git a/container/container_test.go b/container/container_test.go index 092a7a37..41d39f68 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -26,6 +26,7 @@ import ( "hakurei.app/fhs" "hakurei.app/hst" "hakurei.app/internal/info" + "hakurei.app/internal/landlock" "hakurei.app/internal/params" "hakurei.app/ldd" "hakurei.app/message" @@ -456,7 +457,7 @@ func TestContainer(t *testing.T) { c.RetainSession = tc.session c.HostNet = tc.net if info.CanDegrade { - if _, err := container.LandlockGetABI(); err != nil { + if _, err := landlock.GetABI(); err != nil { if !errors.Is(err, syscall.ENOSYS) { t.Fatalf("LandlockGetABI: error = %v", err) } diff --git a/container/landlock.go b/container/landlock.go deleted file mode 100644 index a8007692..00000000 --- a/container/landlock.go +++ /dev/null @@ -1,259 +0,0 @@ -package container - -import ( - "strings" - "syscall" - "unsafe" - - "hakurei.app/ext" -) - -// include/uapi/linux/landlock.h - -const ( - LANDLOCK_CREATE_RULESET_VERSION = 1 << iota -) - -// LandlockAccessFS is bitmask of handled filesystem actions. -type LandlockAccessFS uint64 - -const ( - LANDLOCK_ACCESS_FS_EXECUTE LandlockAccessFS = 1 << iota - LANDLOCK_ACCESS_FS_WRITE_FILE - LANDLOCK_ACCESS_FS_READ_FILE - LANDLOCK_ACCESS_FS_READ_DIR - LANDLOCK_ACCESS_FS_REMOVE_DIR - LANDLOCK_ACCESS_FS_REMOVE_FILE - LANDLOCK_ACCESS_FS_MAKE_CHAR - LANDLOCK_ACCESS_FS_MAKE_DIR - LANDLOCK_ACCESS_FS_MAKE_REG - LANDLOCK_ACCESS_FS_MAKE_SOCK - LANDLOCK_ACCESS_FS_MAKE_FIFO - LANDLOCK_ACCESS_FS_MAKE_BLOCK - LANDLOCK_ACCESS_FS_MAKE_SYM - LANDLOCK_ACCESS_FS_REFER - LANDLOCK_ACCESS_FS_TRUNCATE - LANDLOCK_ACCESS_FS_IOCTL_DEV - - _LANDLOCK_ACCESS_FS_DELIM -) - -// String returns a space-separated string of [LandlockAccessFS] flags. -func (f LandlockAccessFS) String() string { - switch f { - case LANDLOCK_ACCESS_FS_EXECUTE: - return "execute" - - case LANDLOCK_ACCESS_FS_WRITE_FILE: - return "write_file" - - case LANDLOCK_ACCESS_FS_READ_FILE: - return "read_file" - - case LANDLOCK_ACCESS_FS_READ_DIR: - return "read_dir" - - case LANDLOCK_ACCESS_FS_REMOVE_DIR: - return "remove_dir" - - case LANDLOCK_ACCESS_FS_REMOVE_FILE: - return "remove_file" - - case LANDLOCK_ACCESS_FS_MAKE_CHAR: - return "make_char" - - case LANDLOCK_ACCESS_FS_MAKE_DIR: - return "make_dir" - - case LANDLOCK_ACCESS_FS_MAKE_REG: - return "make_reg" - - case LANDLOCK_ACCESS_FS_MAKE_SOCK: - return "make_sock" - - case LANDLOCK_ACCESS_FS_MAKE_FIFO: - return "make_fifo" - - case LANDLOCK_ACCESS_FS_MAKE_BLOCK: - return "make_block" - - case LANDLOCK_ACCESS_FS_MAKE_SYM: - return "make_sym" - - case LANDLOCK_ACCESS_FS_REFER: - return "fs_refer" - - case LANDLOCK_ACCESS_FS_TRUNCATE: - return "fs_truncate" - - case LANDLOCK_ACCESS_FS_IOCTL_DEV: - return "fs_ioctl_dev" - - default: - var c []LandlockAccessFS - for i := LandlockAccessFS(1); i < _LANDLOCK_ACCESS_FS_DELIM; i <<= 1 { - if f&i != 0 { - c = append(c, i) - } - } - if len(c) == 0 { - return "NULL" - } - s := make([]string, len(c)) - for i, v := range c { - s[i] = v.String() - } - return strings.Join(s, " ") - } -} - -// LandlockAccessNet is bitmask of handled network actions. -type LandlockAccessNet uint64 - -const ( - LANDLOCK_ACCESS_NET_BIND_TCP LandlockAccessNet = 1 << iota - LANDLOCK_ACCESS_NET_CONNECT_TCP - - _LANDLOCK_ACCESS_NET_DELIM -) - -// String returns a space-separated string of [LandlockAccessNet] flags. -func (f LandlockAccessNet) String() string { - switch f { - case LANDLOCK_ACCESS_NET_BIND_TCP: - return "bind_tcp" - - case LANDLOCK_ACCESS_NET_CONNECT_TCP: - return "connect_tcp" - - default: - var c []LandlockAccessNet - for i := LandlockAccessNet(1); i < _LANDLOCK_ACCESS_NET_DELIM; i <<= 1 { - if f&i != 0 { - c = append(c, i) - } - } - if len(c) == 0 { - return "NULL" - } - s := make([]string, len(c)) - for i, v := range c { - s[i] = v.String() - } - return strings.Join(s, " ") - } -} - -// LandlockScope is bitmask of scopes restricting a Landlock domain from accessing outside resources. -type LandlockScope uint64 - -const ( - LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET LandlockScope = 1 << iota - LANDLOCK_SCOPE_SIGNAL - - _LANDLOCK_SCOPE_DELIM -) - -// String returns a space-separated string of [LandlockScope] flags. -func (f LandlockScope) String() string { - switch f { - case LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET: - return "abstract_unix_socket" - - case LANDLOCK_SCOPE_SIGNAL: - return "signal" - - default: - var c []LandlockScope - for i := LandlockScope(1); i < _LANDLOCK_SCOPE_DELIM; i <<= 1 { - if f&i != 0 { - c = append(c, i) - } - } - if len(c) == 0 { - return "NULL" - } - s := make([]string, len(c)) - for i, v := range c { - s[i] = v.String() - } - return strings.Join(s, " ") - } -} - -// RulesetAttr is equivalent to struct landlock_ruleset_attr. -type RulesetAttr struct { - // Bitmask of handled filesystem actions. - HandledAccessFS LandlockAccessFS - // Bitmask of handled network actions. - HandledAccessNet LandlockAccessNet - // Bitmask of scopes restricting a Landlock domain from accessing outside - // resources (e.g. IPCs). - Scoped LandlockScope -} - -// String returns a user-facing description of [RulesetAttr]. -func (rulesetAttr *RulesetAttr) String() string { - if rulesetAttr == nil { - return "NULL" - } - elems := make([]string, 0, 3) - if rulesetAttr.HandledAccessFS > 0 { - elems = append(elems, "fs: "+rulesetAttr.HandledAccessFS.String()) - } - if rulesetAttr.HandledAccessNet > 0 { - elems = append(elems, "net: "+rulesetAttr.HandledAccessNet.String()) - } - if rulesetAttr.Scoped > 0 { - elems = append(elems, "scoped: "+rulesetAttr.Scoped.String()) - } - if len(elems) == 0 { - return "0" - } - return strings.Join(elems, ", ") -} - -// Create loads the ruleset into the kernel. -func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) { - var pointer, size uintptr - // NULL needed for abi version - if rulesetAttr != nil { - pointer = uintptr(unsafe.Pointer(rulesetAttr)) - size = unsafe.Sizeof(*rulesetAttr) - } - - rulesetFd, _, errno := syscall.Syscall( - ext.SYS_LANDLOCK_CREATE_RULESET, - pointer, size, - flags, - ) - fd = int(rulesetFd) - err = errno - if fd < 0 { - return - } - - if rulesetAttr != nil { // not a fd otherwise - syscall.CloseOnExec(fd) - } - return fd, nil -} - -// LandlockGetABI returns the ABI version supported by the kernel. -func LandlockGetABI() (int, error) { - return (*RulesetAttr)(nil).Create(LANDLOCK_CREATE_RULESET_VERSION) -} - -// LandlockRestrictSelf applies a loaded ruleset to the calling thread. -func LandlockRestrictSelf(rulesetFd int, flags uintptr) error { - r, _, errno := syscall.Syscall( - ext.SYS_LANDLOCK_RESTRICT_SELF, - uintptr(rulesetFd), - flags, - 0, - ) - if r != 0 { - return errno - } - return nil -} diff --git a/container/landlock_test.go b/container/landlock_test.go deleted file mode 100644 index 87dc2496..00000000 --- a/container/landlock_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package container_test - -import ( - "testing" - "unsafe" - - "hakurei.app/container" -) - -func TestLandlockString(t *testing.T) { - t.Parallel() - - testCases := []struct { - name string - rulesetAttr *container.RulesetAttr - want string - }{ - {"nil", nil, "NULL"}, - {"zero", new(container.RulesetAttr), "0"}, - {"some", &container.RulesetAttr{Scoped: container.LANDLOCK_SCOPE_SIGNAL}, "scoped: signal"}, - {"set", &container.RulesetAttr{ - HandledAccessFS: container.LANDLOCK_ACCESS_FS_MAKE_SYM | container.LANDLOCK_ACCESS_FS_IOCTL_DEV | container.LANDLOCK_ACCESS_FS_WRITE_FILE, - HandledAccessNet: container.LANDLOCK_ACCESS_NET_BIND_TCP, - Scoped: container.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | container.LANDLOCK_SCOPE_SIGNAL, - }, "fs: write_file make_sym fs_ioctl_dev, net: bind_tcp, scoped: abstract_unix_socket signal"}, - {"all", &container.RulesetAttr{ - HandledAccessFS: container.LANDLOCK_ACCESS_FS_EXECUTE | - container.LANDLOCK_ACCESS_FS_WRITE_FILE | - container.LANDLOCK_ACCESS_FS_READ_FILE | - container.LANDLOCK_ACCESS_FS_READ_DIR | - container.LANDLOCK_ACCESS_FS_REMOVE_DIR | - container.LANDLOCK_ACCESS_FS_REMOVE_FILE | - container.LANDLOCK_ACCESS_FS_MAKE_CHAR | - container.LANDLOCK_ACCESS_FS_MAKE_DIR | - container.LANDLOCK_ACCESS_FS_MAKE_REG | - container.LANDLOCK_ACCESS_FS_MAKE_SOCK | - container.LANDLOCK_ACCESS_FS_MAKE_FIFO | - container.LANDLOCK_ACCESS_FS_MAKE_BLOCK | - container.LANDLOCK_ACCESS_FS_MAKE_SYM | - container.LANDLOCK_ACCESS_FS_REFER | - container.LANDLOCK_ACCESS_FS_TRUNCATE | - container.LANDLOCK_ACCESS_FS_IOCTL_DEV, - HandledAccessNet: container.LANDLOCK_ACCESS_NET_BIND_TCP | - container.LANDLOCK_ACCESS_NET_CONNECT_TCP, - Scoped: container.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | - container.LANDLOCK_SCOPE_SIGNAL, - }, "fs: execute write_file read_file read_dir remove_dir remove_file make_char make_dir make_reg make_sock make_fifo make_block make_sym fs_refer fs_truncate fs_ioctl_dev, net: bind_tcp connect_tcp, scoped: abstract_unix_socket signal"}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - if got := tc.rulesetAttr.String(); got != tc.want { - t.Errorf("String: %s, want %s", got, tc.want) - } - }) - } -} - -func TestLandlockAttrSize(t *testing.T) { - t.Parallel() - want := 24 - if got := unsafe.Sizeof(container.RulesetAttr{}); got != uintptr(want) { - t.Errorf("Sizeof: %d, want %d", got, want) - } -} diff --git a/internal/landlock/landlock.go b/internal/landlock/landlock.go new file mode 100644 index 00000000..b65e3ebe --- /dev/null +++ b/internal/landlock/landlock.go @@ -0,0 +1,259 @@ +package landlock + +import ( + "strings" + "syscall" + "unsafe" + + "hakurei.app/ext" +) + +// include/uapi/linux/landlock.h + +const ( + LANDLOCK_CREATE_RULESET_VERSION = 1 << iota +) + +// AccessFS is bitmask of handled filesystem actions. +type AccessFS uint64 + +const ( + LANDLOCK_ACCESS_FS_EXECUTE AccessFS = 1 << iota + LANDLOCK_ACCESS_FS_WRITE_FILE + LANDLOCK_ACCESS_FS_READ_FILE + LANDLOCK_ACCESS_FS_READ_DIR + LANDLOCK_ACCESS_FS_REMOVE_DIR + LANDLOCK_ACCESS_FS_REMOVE_FILE + LANDLOCK_ACCESS_FS_MAKE_CHAR + LANDLOCK_ACCESS_FS_MAKE_DIR + LANDLOCK_ACCESS_FS_MAKE_REG + LANDLOCK_ACCESS_FS_MAKE_SOCK + LANDLOCK_ACCESS_FS_MAKE_FIFO + LANDLOCK_ACCESS_FS_MAKE_BLOCK + LANDLOCK_ACCESS_FS_MAKE_SYM + LANDLOCK_ACCESS_FS_REFER + LANDLOCK_ACCESS_FS_TRUNCATE + LANDLOCK_ACCESS_FS_IOCTL_DEV + + _LANDLOCK_ACCESS_FS_DELIM +) + +// String returns a space-separated string of [AccessFS] flags. +func (f AccessFS) String() string { + switch f { + case LANDLOCK_ACCESS_FS_EXECUTE: + return "execute" + + case LANDLOCK_ACCESS_FS_WRITE_FILE: + return "write_file" + + case LANDLOCK_ACCESS_FS_READ_FILE: + return "read_file" + + case LANDLOCK_ACCESS_FS_READ_DIR: + return "read_dir" + + case LANDLOCK_ACCESS_FS_REMOVE_DIR: + return "remove_dir" + + case LANDLOCK_ACCESS_FS_REMOVE_FILE: + return "remove_file" + + case LANDLOCK_ACCESS_FS_MAKE_CHAR: + return "make_char" + + case LANDLOCK_ACCESS_FS_MAKE_DIR: + return "make_dir" + + case LANDLOCK_ACCESS_FS_MAKE_REG: + return "make_reg" + + case LANDLOCK_ACCESS_FS_MAKE_SOCK: + return "make_sock" + + case LANDLOCK_ACCESS_FS_MAKE_FIFO: + return "make_fifo" + + case LANDLOCK_ACCESS_FS_MAKE_BLOCK: + return "make_block" + + case LANDLOCK_ACCESS_FS_MAKE_SYM: + return "make_sym" + + case LANDLOCK_ACCESS_FS_REFER: + return "fs_refer" + + case LANDLOCK_ACCESS_FS_TRUNCATE: + return "fs_truncate" + + case LANDLOCK_ACCESS_FS_IOCTL_DEV: + return "fs_ioctl_dev" + + default: + var c []AccessFS + for i := AccessFS(1); i < _LANDLOCK_ACCESS_FS_DELIM; i <<= 1 { + if f&i != 0 { + c = append(c, i) + } + } + if len(c) == 0 { + return "NULL" + } + s := make([]string, len(c)) + for i, v := range c { + s[i] = v.String() + } + return strings.Join(s, " ") + } +} + +// AccessNet is bitmask of handled network actions. +type AccessNet uint64 + +const ( + LANDLOCK_ACCESS_NET_BIND_TCP AccessNet = 1 << iota + LANDLOCK_ACCESS_NET_CONNECT_TCP + + _LANDLOCK_ACCESS_NET_DELIM +) + +// String returns a space-separated string of [AccessNet] flags. +func (f AccessNet) String() string { + switch f { + case LANDLOCK_ACCESS_NET_BIND_TCP: + return "bind_tcp" + + case LANDLOCK_ACCESS_NET_CONNECT_TCP: + return "connect_tcp" + + default: + var c []AccessNet + for i := AccessNet(1); i < _LANDLOCK_ACCESS_NET_DELIM; i <<= 1 { + if f&i != 0 { + c = append(c, i) + } + } + if len(c) == 0 { + return "NULL" + } + s := make([]string, len(c)) + for i, v := range c { + s[i] = v.String() + } + return strings.Join(s, " ") + } +} + +// Scope is bitmask of scopes restricting a Landlock domain from accessing outside resources. +type Scope uint64 + +const ( + LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET Scope = 1 << iota + LANDLOCK_SCOPE_SIGNAL + + _LANDLOCK_SCOPE_DELIM +) + +// String returns a space-separated string of [Scope] flags. +func (f Scope) String() string { + switch f { + case LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET: + return "abstract_unix_socket" + + case LANDLOCK_SCOPE_SIGNAL: + return "signal" + + default: + var c []Scope + for i := Scope(1); i < _LANDLOCK_SCOPE_DELIM; i <<= 1 { + if f&i != 0 { + c = append(c, i) + } + } + if len(c) == 0 { + return "NULL" + } + s := make([]string, len(c)) + for i, v := range c { + s[i] = v.String() + } + return strings.Join(s, " ") + } +} + +// RulesetAttr is equivalent to struct landlock_ruleset_attr. +type RulesetAttr struct { + // Bitmask of handled filesystem actions. + HandledAccessFS AccessFS + // Bitmask of handled network actions. + HandledAccessNet AccessNet + // Bitmask of scopes restricting a Landlock domain from accessing outside + // resources (e.g. IPCs). + Scoped Scope +} + +// String returns a user-facing description of [RulesetAttr]. +func (rulesetAttr *RulesetAttr) String() string { + if rulesetAttr == nil { + return "NULL" + } + elems := make([]string, 0, 3) + if rulesetAttr.HandledAccessFS > 0 { + elems = append(elems, "fs: "+rulesetAttr.HandledAccessFS.String()) + } + if rulesetAttr.HandledAccessNet > 0 { + elems = append(elems, "net: "+rulesetAttr.HandledAccessNet.String()) + } + if rulesetAttr.Scoped > 0 { + elems = append(elems, "scoped: "+rulesetAttr.Scoped.String()) + } + if len(elems) == 0 { + return "0" + } + return strings.Join(elems, ", ") +} + +// Create loads the ruleset into the kernel. +func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) { + var pointer, size uintptr + // NULL needed for abi version + if rulesetAttr != nil { + pointer = uintptr(unsafe.Pointer(rulesetAttr)) + size = unsafe.Sizeof(*rulesetAttr) + } + + rulesetFd, _, errno := syscall.Syscall( + ext.SYS_LANDLOCK_CREATE_RULESET, + pointer, size, + flags, + ) + fd = int(rulesetFd) + err = errno + if fd < 0 { + return + } + + if rulesetAttr != nil { // not a fd otherwise + syscall.CloseOnExec(fd) + } + return fd, nil +} + +// GetABI returns the ABI version supported by the kernel. +func GetABI() (int, error) { + return (*RulesetAttr)(nil).Create(LANDLOCK_CREATE_RULESET_VERSION) +} + +// RestrictSelf applies a loaded ruleset to the calling thread. +func RestrictSelf(rulesetFd int, flags uintptr) error { + r, _, errno := syscall.Syscall( + ext.SYS_LANDLOCK_RESTRICT_SELF, + uintptr(rulesetFd), + flags, + 0, + ) + if r != 0 { + return errno + } + return nil +} diff --git a/internal/landlock/landlock_test.go b/internal/landlock/landlock_test.go new file mode 100644 index 00000000..6f30fc6b --- /dev/null +++ b/internal/landlock/landlock_test.go @@ -0,0 +1,65 @@ +package landlock_test + +import ( + "testing" + "unsafe" + + "hakurei.app/internal/landlock" +) + +func TestLandlockString(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + rulesetAttr *landlock.RulesetAttr + want string + }{ + {"nil", nil, "NULL"}, + {"zero", new(landlock.RulesetAttr), "0"}, + {"some", &landlock.RulesetAttr{Scoped: landlock.LANDLOCK_SCOPE_SIGNAL}, "scoped: signal"}, + {"set", &landlock.RulesetAttr{ + HandledAccessFS: landlock.LANDLOCK_ACCESS_FS_MAKE_SYM | landlock.LANDLOCK_ACCESS_FS_IOCTL_DEV | landlock.LANDLOCK_ACCESS_FS_WRITE_FILE, + HandledAccessNet: landlock.LANDLOCK_ACCESS_NET_BIND_TCP, + Scoped: landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | landlock.LANDLOCK_SCOPE_SIGNAL, + }, "fs: write_file make_sym fs_ioctl_dev, net: bind_tcp, scoped: abstract_unix_socket signal"}, + {"all", &landlock.RulesetAttr{ + HandledAccessFS: landlock.LANDLOCK_ACCESS_FS_EXECUTE | + landlock.LANDLOCK_ACCESS_FS_WRITE_FILE | + landlock.LANDLOCK_ACCESS_FS_READ_FILE | + landlock.LANDLOCK_ACCESS_FS_READ_DIR | + landlock.LANDLOCK_ACCESS_FS_REMOVE_DIR | + landlock.LANDLOCK_ACCESS_FS_REMOVE_FILE | + landlock.LANDLOCK_ACCESS_FS_MAKE_CHAR | + landlock.LANDLOCK_ACCESS_FS_MAKE_DIR | + landlock.LANDLOCK_ACCESS_FS_MAKE_REG | + landlock.LANDLOCK_ACCESS_FS_MAKE_SOCK | + landlock.LANDLOCK_ACCESS_FS_MAKE_FIFO | + landlock.LANDLOCK_ACCESS_FS_MAKE_BLOCK | + landlock.LANDLOCK_ACCESS_FS_MAKE_SYM | + landlock.LANDLOCK_ACCESS_FS_REFER | + landlock.LANDLOCK_ACCESS_FS_TRUNCATE | + landlock.LANDLOCK_ACCESS_FS_IOCTL_DEV, + HandledAccessNet: landlock.LANDLOCK_ACCESS_NET_BIND_TCP | + landlock.LANDLOCK_ACCESS_NET_CONNECT_TCP, + Scoped: landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | + landlock.LANDLOCK_SCOPE_SIGNAL, + }, "fs: execute write_file read_file read_dir remove_dir remove_file make_char make_dir make_reg make_sock make_fifo make_block make_sym fs_refer fs_truncate fs_ioctl_dev, net: bind_tcp connect_tcp, scoped: abstract_unix_socket signal"}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if got := tc.rulesetAttr.String(); got != tc.want { + t.Errorf("String: %s, want %s", got, tc.want) + } + }) + } +} + +func TestLandlockAttrSize(t *testing.T) { + t.Parallel() + want := 24 + if got := unsafe.Sizeof(landlock.RulesetAttr{}); got != uintptr(want) { + t.Errorf("Sizeof: %d, want %d", got, want) + } +} diff --git a/internal/pkg/pkg_test.go b/internal/pkg/pkg_test.go index e1deaf3d..b2a5dfbc 100644 --- a/internal/pkg/pkg_test.go +++ b/internal/pkg/pkg_test.go @@ -25,6 +25,7 @@ import ( "hakurei.app/container" "hakurei.app/fhs" "hakurei.app/internal/info" + "hakurei.app/internal/landlock" "hakurei.app/internal/pkg" "hakurei.app/internal/stub" "hakurei.app/message" @@ -293,7 +294,7 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) { flags := tc.flags if info.CanDegrade { - if _, err := container.LandlockGetABI(); err != nil { + if _, err := landlock.GetABI(); err != nil { if !errors.Is(err, syscall.ENOSYS) { t.Fatalf("LandlockGetABI: error = %v", err) } -- cgit v1.3.1