feat: Add support for Landlock based Sandbox for Linux (#238)

* feat: Initial implementation of landlock based sandbox driver

* fix: Handle seccom probe failure

* fix: Remove unnecessary seccomp probe

* fix: Use file based policy load

* fix: Keep bpf filter in memory

* fix: Use TSYNC for seccom filter

* fix: Use TSYNC for seccom filter

* fix: Update landlock translator

* fix: Landlock sandbox implementation

* fix: Landlock + seccomp based sandboxing on Linux

* fix: Misc fixes

* fix: Cleanup sandbox files

* fix: Handle mandatory deny API change post merge

* fix: Landlock write access translation

* chore: Fix linter issues

* ci: Use /tmp for npm cache for landlock
This commit is contained in:
Abhisek Datta
2026-05-07 12:42:28 +05:30
committed by GitHub
parent 5122a1594c
commit 4c42ceca0e
27 changed files with 4356 additions and 122 deletions
@@ -0,0 +1,33 @@
//go:build linux
package landlock
import (
"github.com/safedep/pmg/sandbox/platform"
"github.com/spf13/cobra"
)
// NewLandlockSandboxExecCommand returns the hidden Cobra command used as the
// helper process entry point for the Landlock sandbox driver.
func NewLandlockSandboxExecCommand() *cobra.Command {
var policyFile string
var auditSocket string
cmd := &cobra.Command{
Use: "__landlock_sandbox_exec",
Hidden: true,
// Skip parent pmg initialization (config, event log, analytics) —
// RunLandlockHelper sets up its own minimal logger.
PersistentPreRun: func(cmd *cobra.Command, args []string) {},
RunE: func(cmd *cobra.Command, args []string) error {
return platform.RunLandlockHelper(policyFile, auditSocket, args)
},
}
cmd.Flags().StringVar(&policyFile, "policy-file", "", "Path to policy JSON file")
cmd.Flags().StringVar(&auditSocket, "audit-socket", "", "Path to audit unix socket")
_ = cmd.MarkFlagRequired("policy-file")
_ = cmd.MarkFlagRequired("audit-socket")
return cmd
}
@@ -0,0 +1,9 @@
//go:build !linux
package landlock
import "github.com/spf13/cobra"
// NewLandlockSandboxExecCommand returns nil on non-Linux platforms where
// Landlock is not available.
func NewLandlockSandboxExecCommand() *cobra.Command { return nil }
+38
View File
@@ -0,0 +1,38 @@
//go:build linux
package landlock
import (
"github.com/safedep/pmg/sandbox/platform"
"github.com/spf13/cobra"
)
// NewLandlockShimCommand returns the hidden Cobra command used as the
// inside-user-namespace shim. The helper process (pmg __landlock_sandbox_exec)
// clones a child with CLONE_NEWUSER + uid/gid mapping (0 -> host uid) so the
// shim boots as uid 0 inside the ns with CAP_SYS_ADMIN. The shim installs the
// seccomp filter WITHOUT PR_SET_NO_NEW_PRIVS (allowed by CAP_SYS_ADMIN in the
// ns) and applies Landlock; this keeps the shim (and every descendant) with
// dumpable=1, so the helper can open /proc/<pid>/mem to resolve openat(2)
// path arguments for seccomp-notify.
func NewLandlockShimCommand() *cobra.Command {
var policyFile string
var notifySocketFd int
cmd := &cobra.Command{
Use: "__landlock_shim",
Hidden: true,
DisableFlagParsing: false,
// Skip parent pmg initialization — the shim re-execs almost
// immediately and does not need config/analytics/etc.
PersistentPreRun: func(cmd *cobra.Command, args []string) {},
RunE: func(cmd *cobra.Command, args []string) error {
return platform.RunLandlockShim(policyFile, notifySocketFd, args)
},
}
cmd.Flags().StringVar(&policyFile, "policy-file", "", "Path to policy JSON file")
cmd.Flags().IntVar(&notifySocketFd, "notify-socket-fd", 0, "FD of socketpair end used to send the seccomp notify fd to the supervisor")
_ = cmd.MarkFlagRequired("policy-file")
_ = cmd.MarkFlagRequired("notify-socket-fd")
return cmd
}
+8
View File
@@ -0,0 +1,8 @@
//go:build !linux
package landlock
import "github.com/spf13/cobra"
// NewLandlockShimCommand returns nil on non-Linux platforms.
func NewLandlockShimCommand() *cobra.Command { return nil }