From b16a3b0d4395e9dd79847526499fbe051ffa72cc Mon Sep 17 00:00:00 2001 From: Klemens Nanni Date: Wed, 23 Oct 2024 00:37:31 +0300 Subject: [PATCH] Use unveil(2) on OpenBSD After #1175 removed ioctl(2) fallback code shelling out to ifconfig(8), there is no code left (compiled on OpenBSD) that would fork(2) or execve(2). Drop the ability to run any executable file to double down on this, thus reducing the attack surface of this this experimental, internet facing daemon running as root. pledge(2) is doable, but needs more polish. unveil(2), however, is as simple as it gets. On other systems, this code is a NOOP, but can still help to implement similar safety belts. --- cmd/yggdrasil/main.go | 16 ++++++++++++++++ go.mod | 1 + go.sum | 2 ++ 3 files changed, 19 insertions(+) diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go index 0ae8ab42c..7b206758c 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/yggdrasil/main.go @@ -14,6 +14,8 @@ import ( "strings" "syscall" + "suah.dev/protect" + "github.com/gologme/log" gsyslog "github.com/hashicorp/go-syslog" "github.com/hjson/hjson-go/v4" @@ -39,6 +41,20 @@ type node struct { // The main function is responsible for configuring and starting Yggdrasil. func main() { + // Not all operations are coverable with pledge(2), so immediately + // limit file system access with unveil(2), effectively preventing + // "proc exec" promises right from the start: + // + // - read arbitrary config file + // - create/write arbitrary log file + // - read/write/chmod/remove admin socket, if at all + if err := protect.Unveil("/", "rwc"); err != nil { + panic(fmt.Sprintf("unveil /: %v", err)) + } + if err := protect.UnveilBlock(); err != nil { + panic(fmt.Sprintf("unveil: %v", err)) + } + genconf := flag.Bool("genconf", false, "print a new config to stdout") useconf := flag.Bool("useconf", false, "read HJSON/JSON config from stdin") useconffile := flag.String("useconffile", "", "read HJSON/JSON config from specified file path") diff --git a/go.mod b/go.mod index 76641a605..fdbbcaf23 100644 --- a/go.mod +++ b/go.mod @@ -45,4 +45,5 @@ require ( github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 github.com/vishvananda/netns v0.0.4 // indirect + suah.dev/protect v1.2.4 ) diff --git a/go.sum b/go.sum index 89dd0c7bc..75e4811df 100644 --- a/go.sum +++ b/go.sum @@ -155,3 +155,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ= gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY= +suah.dev/protect v1.2.4 h1:iVZG/zQB63FKNpITDYM/cXoAeCTIjCiXHuFVByJFDzg= +suah.dev/protect v1.2.4/go.mod h1:vVrquYO3u1Ep9Ez2z8x+6N6/czm+TBmWKZfiXU2tb54=