landdown

Simple Sandboxing for shell scripts.

git clone git://mccd.space/landdown

commit 8719bfb36a7247dd2d7d4393c4a5f7ad130c58b5
parent 0ac1dad37508cd691b29c9f682dab51c28a362e4
Author: Marc <marc@coquand.email>
Date:   Tue, 31 Mar 2026 14:51:24 +0200

Correct stdin handling

Diffstat:
MREADME.md | 1-
Mgo.mod | 4++--
Mgo.sum | 2++
Mmain.go | 25++++++++++++-------------
4 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
@@ -86,4 +86,3 @@ curl https://www.google.com
 ```
 
 Try removing `ro /etc/ssl`, `rof /etc/resolv.conf`, or `connect 443` and it should fail.
-
diff --git a/go.mod b/go.mod
@@ -1,9 +1,9 @@
 module git.sr.ht/~marcc/landdown
 
-go 1.25
+go 1.25.0
 
 require (
 	github.com/landlock-lsm/go-landlock v0.7.0 // indirect
-	golang.org/x/sys v0.40.0 // indirect
+	golang.org/x/sys v0.42.0 // indirect
 	kernel.org/pub/linux/libs/security/libcap/psx v1.2.77 // indirect
 )
diff --git a/go.sum b/go.sum
@@ -2,5 +2,7 @@ github.com/landlock-lsm/go-landlock v0.7.0 h1:gXz0+Phg3vddZjpPzXL4pQy/MgsTMHZBs+
 github.com/landlock-lsm/go-landlock v0.7.0/go.mod h1:mn5GSi81Jf7yMs5WSi+SUi4sUeNLUGVdbT4Id6wXNQw=
 golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
 golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
 kernel.org/pub/linux/libs/security/libcap/psx v1.2.77 h1:Z06sMOzc0GNCwp6efaVrIrz4ywGJ1v+DP0pjVkOfDuA=
 kernel.org/pub/linux/libs/security/libcap/psx v1.2.77/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
diff --git a/main.go b/main.go
@@ -11,6 +11,8 @@ import (
 	"strings"
 	"syscall"
 
+	"golang.org/x/sys/unix"
+
 	"github.com/landlock-lsm/go-landlock/landlock"
 )
 
@@ -125,21 +127,18 @@ func main() {
 	argv := append(execCmd, extraArgs...)
 
 	env := os.Environ()
-
-	// Replace file descriptor 0 with data after second shebang,
-	// so the exec'd process gets the script content instead
-	if len(stdinData) > 0 {
-		r, w, err := os.Pipe()
+	// Create a memfile that is the content of the script
+	// we actually want to run, execute the script with that.
+ 	if len(stdinData) > 0 {
+		fd, err := unix.MemfdCreate("landdown", 0)
 		if err != nil {
-			log.Fatalf("failed to create pipe: %v", err)
+		    log.Fatalf("memfd_create failed: %v", err)
 		}
-		go func() {
-			w.Write(stdinData)
-			w.Close()
-		}()
-		syscall.Dup2(int(r.Fd()), 0)
-		r.Close()
-	}
+		unix.Write(fd, stdinData)
+		// Rewind
+		unix.Seek(fd, 0, 0)
+		argv = append(argv, fmt.Sprintf("/dev/fd/%d", fd))
+ 	}
 
 	if err := syscall.Exec(fullPath, argv, env); err != nil {
 		log.Fatalf("failed to exec: %v", err)