Compare commits
	
		
			4 Commits
		
	
	
		
			a0062d8275
			...
			f955b15b84
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f955b15b84 | |||
| 0340c67995 | |||
| 72b0160aad | |||
| ea8d1c07df | 
@ -1,6 +1,8 @@
 | 
				
			|||||||
package bwrap
 | 
					package bwrap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "os"
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
Bind binds mount src on host to dest in sandbox.
 | 
					Bind binds mount src on host to dest in sandbox.
 | 
				
			||||||
@ -61,6 +63,29 @@ func (c *Config) Bind(src, dest string, opts ...bool) *Config {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Write copy from FD to destination DEST
 | 
				
			||||||
 | 
					// (--file FD DEST)
 | 
				
			||||||
 | 
					func (c *Config) Write(dest string, payload []byte) *Config {
 | 
				
			||||||
 | 
						c.Filesystem = append(c.Filesystem, &DataConfig{Dest: dest, Data: payload, Type: DataWrite})
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					CopyBind copy from FD to file which is readonly bind-mounted on DEST
 | 
				
			||||||
 | 
					(--ro-bind-data FD DEST)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CopyBind(dest, payload, true) copy from FD to file which is bind-mounted on DEST
 | 
				
			||||||
 | 
					(--bind-data FD DEST)
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					func (c *Config) CopyBind(dest string, payload []byte, opts ...bool) *Config {
 | 
				
			||||||
 | 
						t := DataROBind
 | 
				
			||||||
 | 
						if len(opts) > 0 && opts[0] {
 | 
				
			||||||
 | 
							t = DataBind
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Filesystem = append(c.Filesystem, &DataConfig{Dest: dest, Data: payload, Type: t})
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Dir create dir in sandbox
 | 
					// Dir create dir in sandbox
 | 
				
			||||||
// (--dir DEST)
 | 
					// (--dir DEST)
 | 
				
			||||||
func (c *Config) Dir(dest string) *Config {
 | 
					func (c *Config) Dir(dest string) *Config {
 | 
				
			||||||
 | 
				
			|||||||
@ -71,9 +71,6 @@ type Config struct {
 | 
				
			|||||||
	    --ro-bind-fd FD DEST         Bind open directory or path fd read-only on DEST
 | 
						    --ro-bind-fd FD DEST         Bind open directory or path fd read-only on DEST
 | 
				
			||||||
	    --exec-label LABEL           Exec label for the sandbox
 | 
						    --exec-label LABEL           Exec label for the sandbox
 | 
				
			||||||
	    --file-label LABEL           File label for temporary sandbox content
 | 
						    --file-label LABEL           File label for temporary sandbox content
 | 
				
			||||||
	    --file FD DEST               Copy from FD to destination DEST
 | 
					 | 
				
			||||||
	    --bind-data FD DEST          Copy from FD to file which is bind-mounted on DEST
 | 
					 | 
				
			||||||
	    --ro-bind-data FD DEST       Copy from FD to file which is readonly bind-mounted on DEST
 | 
					 | 
				
			||||||
	    --add-seccomp-fd FD          Load and use seccomp rules from FD (repeatable)
 | 
						    --add-seccomp-fd FD          Load and use seccomp rules from FD (repeatable)
 | 
				
			||||||
	    --block-fd FD                Block on FD until some data to read is available
 | 
						    --block-fd FD                Block on FD until some data to read is available
 | 
				
			||||||
	    --userns-block-fd FD         Block on FD until the user namespace is ready
 | 
						    --userns-block-fd FD         Block on FD until the user namespace is ready
 | 
				
			||||||
 | 
				
			|||||||
@ -21,15 +21,14 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
		want []string
 | 
							want []string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "bind",
 | 
								"bind", (new(bwrap.Config)).
 | 
				
			||||||
			conf: (new(bwrap.Config)).
 | 
					 | 
				
			||||||
				Bind("/etc", "/.fortify/etc").
 | 
									Bind("/etc", "/.fortify/etc").
 | 
				
			||||||
				Bind("/etc", "/.fortify/etc", true).
 | 
									Bind("/etc", "/.fortify/etc", true).
 | 
				
			||||||
				Bind("/run", "/.fortify/run", false, true).
 | 
									Bind("/run", "/.fortify/run", false, true).
 | 
				
			||||||
				Bind("/sys/devices", "/.fortify/sys/devices", true, true).
 | 
									Bind("/sys/devices", "/.fortify/sys/devices", true, true).
 | 
				
			||||||
				Bind("/dev/dri", "/.fortify/dev/dri", false, true, true).
 | 
									Bind("/dev/dri", "/.fortify/dev/dri", false, true, true).
 | 
				
			||||||
				Bind("/dev/dri", "/.fortify/dev/dri", true, true, true),
 | 
									Bind("/dev/dri", "/.fortify/dev/dri", true, true, true),
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				// Bind("/etc", "/.fortify/etc")
 | 
									// Bind("/etc", "/.fortify/etc")
 | 
				
			||||||
@ -47,14 +46,13 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "dir remount-ro proc dev mqueue",
 | 
								"dir remount-ro proc dev mqueue", (new(bwrap.Config)).
 | 
				
			||||||
			conf: (new(bwrap.Config)).
 | 
					 | 
				
			||||||
				Dir("/.fortify").
 | 
									Dir("/.fortify").
 | 
				
			||||||
				RemountRO("/home").
 | 
									RemountRO("/home").
 | 
				
			||||||
				Procfs("/proc").
 | 
									Procfs("/proc").
 | 
				
			||||||
				DevTmpfs("/dev").
 | 
									DevTmpfs("/dev").
 | 
				
			||||||
				Mqueue("/dev/mqueue"),
 | 
									Mqueue("/dev/mqueue"),
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				// Dir("/.fortify")
 | 
									// Dir("/.fortify")
 | 
				
			||||||
@ -70,11 +68,10 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "tmpfs",
 | 
								"tmpfs", (new(bwrap.Config)).
 | 
				
			||||||
			conf: (new(bwrap.Config)).
 | 
					 | 
				
			||||||
				Tmpfs("/run/user", 8192).
 | 
									Tmpfs("/run/user", 8192).
 | 
				
			||||||
				Tmpfs("/run/dbus", 8192, 0755),
 | 
									Tmpfs("/run/dbus", 8192, 0755),
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				// Tmpfs("/run/user", 8192)
 | 
									// Tmpfs("/run/user", 8192)
 | 
				
			||||||
@ -84,11 +81,10 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "symlink",
 | 
								"symlink", (new(bwrap.Config)).
 | 
				
			||||||
			conf: (new(bwrap.Config)).
 | 
					 | 
				
			||||||
				Symlink("/.fortify/sbin/init", "/sbin/init").
 | 
									Symlink("/.fortify/sbin/init", "/sbin/init").
 | 
				
			||||||
				Symlink("/.fortify/sbin/init", "/sbin/init", 0755),
 | 
									Symlink("/.fortify/sbin/init", "/sbin/init", 0755),
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				// Symlink("/.fortify/sbin/init", "/sbin/init")
 | 
									// Symlink("/.fortify/sbin/init", "/sbin/init")
 | 
				
			||||||
@ -98,12 +94,11 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "overlayfs",
 | 
								"overlayfs", (new(bwrap.Config)).
 | 
				
			||||||
			conf: (new(bwrap.Config)).
 | 
					 | 
				
			||||||
				Overlay("/etc", "/etc").
 | 
									Overlay("/etc", "/etc").
 | 
				
			||||||
				Join("/.fortify/bin", "/bin", "/usr/bin", "/usr/local/bin").
 | 
									Join("/.fortify/bin", "/bin", "/usr/bin", "/usr/local/bin").
 | 
				
			||||||
				Persist("/nix", "/data/data/org.chromium.Chromium/overlay/rwsrc", "/data/data/org.chromium.Chromium/workdir", "/data/app/org.chromium.Chromium/nix"),
 | 
									Persist("/nix", "/data/data/org.chromium.Chromium/overlay/rwsrc", "/data/data/org.chromium.Chromium/workdir", "/data/app/org.chromium.Chromium/nix"),
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				// Overlay("/etc", "/etc")
 | 
									// Overlay("/etc", "/etc")
 | 
				
			||||||
@ -117,8 +112,23 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "unshare",
 | 
								"copy", (new(bwrap.Config)).
 | 
				
			||||||
			conf: &bwrap.Config{Unshare: &bwrap.UnshareConfig{
 | 
									Write("/.fortify/version", make([]byte, 8)).
 | 
				
			||||||
 | 
									CopyBind("/etc/group", make([]byte, 8)).
 | 
				
			||||||
 | 
									CopyBind("/etc/passwd", make([]byte, 8), true),
 | 
				
			||||||
 | 
								[]string{
 | 
				
			||||||
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
 | 
									// Write("/.fortify/version", make([]byte, 8))
 | 
				
			||||||
 | 
									"--file", "3", "/.fortify/version",
 | 
				
			||||||
 | 
									// CopyBind("/etc/group", make([]byte, 8))
 | 
				
			||||||
 | 
									"--ro-bind-data", "4", "/etc/group",
 | 
				
			||||||
 | 
									// CopyBind("/etc/passwd", make([]byte, 8), true)
 | 
				
			||||||
 | 
									"--bind-data", "5", "/etc/passwd",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"unshare", &bwrap.Config{Unshare: &bwrap.UnshareConfig{
 | 
				
			||||||
				User:   false,
 | 
									User:   false,
 | 
				
			||||||
				IPC:    false,
 | 
									IPC:    false,
 | 
				
			||||||
				PID:    false,
 | 
									PID:    false,
 | 
				
			||||||
@ -126,14 +136,13 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
				UTS:    false,
 | 
									UTS:    false,
 | 
				
			||||||
				CGroup: false,
 | 
									CGroup: false,
 | 
				
			||||||
			}},
 | 
								}},
 | 
				
			||||||
			want: []string{"--disable-userns", "--assert-userns-disabled"},
 | 
								[]string{"--disable-userns", "--assert-userns-disabled"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "uid gid sync",
 | 
								"uid gid sync", (new(bwrap.Config)).
 | 
				
			||||||
			conf: (new(bwrap.Config)).
 | 
					 | 
				
			||||||
				SetUID(1971).
 | 
									SetUID(1971).
 | 
				
			||||||
				SetGID(100),
 | 
									SetGID(100),
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				// SetUID(1971)
 | 
									// SetUID(1971)
 | 
				
			||||||
@ -143,8 +152,7 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "hostname chdir setenv unsetenv lockfile chmod syscall",
 | 
								"hostname chdir setenv unsetenv lockfile chmod syscall", &bwrap.Config{
 | 
				
			||||||
			conf: &bwrap.Config{
 | 
					 | 
				
			||||||
				Hostname: "fortify",
 | 
									Hostname: "fortify",
 | 
				
			||||||
				Chdir:    "/.fortify",
 | 
									Chdir:    "/.fortify",
 | 
				
			||||||
				SetEnv:   map[string]string{"FORTIFY_INIT": "/.fortify/sbin/init"},
 | 
									SetEnv:   map[string]string{"FORTIFY_INIT": "/.fortify/sbin/init"},
 | 
				
			||||||
@ -153,7 +161,7 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
				Syscall:  new(bwrap.SyscallPolicy),
 | 
									Syscall:  new(bwrap.SyscallPolicy),
 | 
				
			||||||
				Chmod:    map[string]os.FileMode{"/.fortify/sbin/init": 0755},
 | 
									Chmod:    map[string]os.FileMode{"/.fortify/sbin/init": 0755},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				// Hostname: "fortify"
 | 
									// Hostname: "fortify"
 | 
				
			||||||
@ -175,8 +183,7 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "xdg-dbus-proxy constraint sample",
 | 
								"xdg-dbus-proxy constraint sample", (&bwrap.Config{Clearenv: true, DieWithParent: true}).
 | 
				
			||||||
			conf: (&bwrap.Config{Clearenv: true, DieWithParent: true}).
 | 
					 | 
				
			||||||
				Symlink("usr/bin", "/bin").
 | 
									Symlink("usr/bin", "/bin").
 | 
				
			||||||
				Symlink("var/home", "/home").
 | 
									Symlink("var/home", "/home").
 | 
				
			||||||
				Symlink("usr/lib", "/lib").
 | 
									Symlink("usr/lib", "/lib").
 | 
				
			||||||
@ -199,7 +206,7 @@ func TestConfig_Args(t *testing.T) {
 | 
				
			|||||||
				Bind("/sysroot", "/sysroot").
 | 
									Bind("/sysroot", "/sysroot").
 | 
				
			||||||
				Bind("/usr", "/usr").
 | 
									Bind("/usr", "/usr").
 | 
				
			||||||
				Bind("/etc", "/etc"),
 | 
									Bind("/etc", "/etc"),
 | 
				
			||||||
			want: []string{
 | 
								[]string{
 | 
				
			||||||
				"--unshare-all", "--unshare-user",
 | 
									"--unshare-all", "--unshare-user",
 | 
				
			||||||
				"--disable-userns", "--assert-userns-disabled",
 | 
									"--disable-userns", "--assert-userns-disabled",
 | 
				
			||||||
				"--clearenv", "--die-with-parent",
 | 
									"--clearenv", "--die-with-parent",
 | 
				
			||||||
 | 
				
			|||||||
@ -2,14 +2,19 @@ package bwrap
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/gob"
 | 
						"encoding/gob"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.gensokyo.uk/security/fortify/helper/proc"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	gob.Register(new(PermConfig[SymlinkConfig]))
 | 
						gob.Register(new(PermConfig[SymlinkConfig]))
 | 
				
			||||||
	gob.Register(new(PermConfig[*TmpfsConfig]))
 | 
						gob.Register(new(PermConfig[*TmpfsConfig]))
 | 
				
			||||||
	gob.Register(new(OverlayConfig))
 | 
						gob.Register(new(OverlayConfig))
 | 
				
			||||||
 | 
						gob.Register(new(DataConfig))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PositionalArg int
 | 
					type PositionalArg int
 | 
				
			||||||
@ -44,6 +49,10 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	SyncFd
 | 
						SyncFd
 | 
				
			||||||
	Seccomp
 | 
						Seccomp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						File
 | 
				
			||||||
 | 
						BindData
 | 
				
			||||||
 | 
						ROBindData
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var positionalArgs = [...]string{
 | 
					var positionalArgs = [...]string{
 | 
				
			||||||
@ -74,6 +83,10 @@ var positionalArgs = [...]string{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	SyncFd:  "--sync-fd",
 | 
						SyncFd:  "--sync-fd",
 | 
				
			||||||
	Seccomp: "--seccomp",
 | 
						Seccomp: "--seccomp",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						File:       "--file",
 | 
				
			||||||
 | 
						BindData:   "--bind-data",
 | 
				
			||||||
 | 
						ROBindData: "--ro-bind-data",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PermConfig[T FSBuilder] struct {
 | 
					type PermConfig[T FSBuilder] struct {
 | 
				
			||||||
@ -202,12 +215,59 @@ func (s SymlinkConfig) Append(args *[]string) { *args = append(*args, Symlink.St
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type ChmodConfig map[string]os.FileMode
 | 
					type ChmodConfig map[string]os.FileMode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c ChmodConfig) Len() int {
 | 
					func (c ChmodConfig) Len() int { return len(c) }
 | 
				
			||||||
	return len(c)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c ChmodConfig) Append(args *[]string) {
 | 
					func (c ChmodConfig) Append(args *[]string) {
 | 
				
			||||||
	for path, mode := range c {
 | 
						for path, mode := range c {
 | 
				
			||||||
		*args = append(*args, Chmod.String(), strconv.FormatInt(int64(mode), 8), path)
 | 
							*args = append(*args, Chmod.String(), strconv.FormatInt(int64(mode), 8), path)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						DataWrite = iota
 | 
				
			||||||
 | 
						DataBind
 | 
				
			||||||
 | 
						DataROBind
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DataConfig struct {
 | 
				
			||||||
 | 
						Dest string `json:"dest"`
 | 
				
			||||||
 | 
						Data []byte `json:"data,omitempty"`
 | 
				
			||||||
 | 
						Type int    `json:"type"`
 | 
				
			||||||
 | 
						proc.File
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *DataConfig) Path() string { return d.Dest }
 | 
				
			||||||
 | 
					func (d *DataConfig) Len() int {
 | 
				
			||||||
 | 
						if d == nil || d.Data == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 3
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (d *DataConfig) Init(fd uintptr, v **os.File) uintptr {
 | 
				
			||||||
 | 
						if d.File != nil {
 | 
				
			||||||
 | 
							panic("file initialised twice")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						d.File = proc.NewWriterTo(d)
 | 
				
			||||||
 | 
						return d.File.Init(fd, v)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (d *DataConfig) WriteTo(w io.Writer) (int64, error) {
 | 
				
			||||||
 | 
						n, err := w.Write(d.Data)
 | 
				
			||||||
 | 
						return int64(n), err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (d *DataConfig) Append(args *[]string) {
 | 
				
			||||||
 | 
						if d == nil || d.Data == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var a PositionalArg
 | 
				
			||||||
 | 
						switch d.Type {
 | 
				
			||||||
 | 
						case DataWrite:
 | 
				
			||||||
 | 
							a = File
 | 
				
			||||||
 | 
						case DataBind:
 | 
				
			||||||
 | 
							a = BindData
 | 
				
			||||||
 | 
						case DataROBind:
 | 
				
			||||||
 | 
							a = ROBindData
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("invalid type %d", a))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*args = append(*args, a.String(), strconv.Itoa(int(d.Fd())), d.Dest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -62,8 +62,6 @@ var testCasesNixos = []sealTestCase{
 | 
				
			|||||||
			Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
 | 
								Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
 | 
				
			||||||
			Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
 | 
								Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
 | 
				
			||||||
			Ephemeral(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", acl.Execute).
 | 
								Ephemeral(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", acl.Execute).
 | 
				
			||||||
			WriteType(system.Process, "/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/passwd", "u0_a1:x:1971:1971:Fortify:/var/lib/persist/module/fortify/0/1:/run/current-system/sw/bin/zsh\n").
 | 
					 | 
				
			||||||
			WriteType(system.Process, "/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/group", "fortify:x:1971:\n").
 | 
					 | 
				
			||||||
			Link("/run/user/1971/wayland-0", "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/wayland").
 | 
								Link("/run/user/1971/wayland-0", "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/wayland").
 | 
				
			||||||
			UpdatePermType(system.EWayland, "/run/user/1971/wayland-0", acl.Read, acl.Write, acl.Execute).
 | 
								UpdatePermType(system.EWayland, "/run/user/1971/wayland-0", acl.Read, acl.Write, acl.Execute).
 | 
				
			||||||
			Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse").
 | 
								Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse").
 | 
				
			||||||
@ -212,13 +210,15 @@ var testCasesNixos = []sealTestCase{
 | 
				
			|||||||
			Tmpfs("/run/user", 1048576).
 | 
								Tmpfs("/run/user", 1048576).
 | 
				
			||||||
			Tmpfs("/run/user/1971", 8388608).
 | 
								Tmpfs("/run/user/1971", 8388608).
 | 
				
			||||||
			Bind("/var/lib/persist/module/fortify/0/1", "/var/lib/persist/module/fortify/0/1", false, true).
 | 
								Bind("/var/lib/persist/module/fortify/0/1", "/var/lib/persist/module/fortify/0/1", false, true).
 | 
				
			||||||
			Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/passwd", "/etc/passwd").
 | 
								CopyBind("/etc/passwd", []byte("u0_a1:x:1971:1971:Fortify:/var/lib/persist/module/fortify/0/1:/run/current-system/sw/bin/zsh\n")).
 | 
				
			||||||
			Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/group", "/etc/group").
 | 
								CopyBind("/etc/group", []byte("fortify:x:1971:\n")).
 | 
				
			||||||
			Bind("/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/wayland", "/run/user/1971/wayland-0").
 | 
								Bind("/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/wayland", "/run/user/1971/wayland-0").
 | 
				
			||||||
			Bind("/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse", "/run/user/1971/pulse/native").
 | 
								Bind("/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse", "/run/user/1971/pulse/native").
 | 
				
			||||||
			Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/pulse-cookie", fst.Tmp+"/pulse-cookie").
 | 
								Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/pulse-cookie", fst.Tmp+"/pulse-cookie").
 | 
				
			||||||
			Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", "/run/user/1971/bus").
 | 
								Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", "/run/user/1971/bus").
 | 
				
			||||||
			Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", "/run/dbus/system_bus_socket").
 | 
								Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", "/run/dbus/system_bus_socket").
 | 
				
			||||||
			Tmpfs("/var/run/nscd", 8192),
 | 
								Tmpfs("/var/run/nscd", 8192).
 | 
				
			||||||
 | 
								Bind("/run/wrappers/bin/fortify", "/.fortify/sbin/fortify").
 | 
				
			||||||
 | 
								Symlink("fortify", "/.fortify/sbin/init"),
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -32,9 +32,7 @@ var testCasesPd = []sealTestCase{
 | 
				
			|||||||
			Ensure("/tmp/fortify.1971/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/0", acl.Read, acl.Write, acl.Execute).
 | 
								Ensure("/tmp/fortify.1971/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/0", acl.Read, acl.Write, acl.Execute).
 | 
				
			||||||
			Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
 | 
								Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
 | 
				
			||||||
			Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
 | 
								Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
 | 
				
			||||||
			Ephemeral(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", acl.Execute).
 | 
								Ephemeral(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", acl.Execute),
 | 
				
			||||||
			WriteType(system.Process, "/tmp/fortify.1971/4a450b6596d7bc15bd01780eb9a607ac/passwd", "chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n").
 | 
					 | 
				
			||||||
			WriteType(system.Process, "/tmp/fortify.1971/4a450b6596d7bc15bd01780eb9a607ac/group", "fortify:x:65534:\n"),
 | 
					 | 
				
			||||||
		(&bwrap.Config{
 | 
							(&bwrap.Config{
 | 
				
			||||||
			Net:      true,
 | 
								Net:      true,
 | 
				
			||||||
			UserNS:   true,
 | 
								UserNS:   true,
 | 
				
			||||||
@ -154,9 +152,11 @@ var testCasesPd = []sealTestCase{
 | 
				
			|||||||
			Tmpfs("/run/user", 1048576).
 | 
								Tmpfs("/run/user", 1048576).
 | 
				
			||||||
			Tmpfs("/run/user/65534", 8388608).
 | 
								Tmpfs("/run/user/65534", 8388608).
 | 
				
			||||||
			Bind("/home/chronos", "/home/chronos", false, true).
 | 
								Bind("/home/chronos", "/home/chronos", false, true).
 | 
				
			||||||
			Bind("/tmp/fortify.1971/4a450b6596d7bc15bd01780eb9a607ac/passwd", "/etc/passwd").
 | 
								CopyBind("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
 | 
				
			||||||
			Bind("/tmp/fortify.1971/4a450b6596d7bc15bd01780eb9a607ac/group", "/etc/group").
 | 
								CopyBind("/etc/group", []byte("fortify:x:65534:\n")).
 | 
				
			||||||
			Tmpfs("/var/run/nscd", 8192),
 | 
								Tmpfs("/var/run/nscd", 8192).
 | 
				
			||||||
 | 
								Bind("/run/wrappers/bin/fortify", "/.fortify/sbin/fortify").
 | 
				
			||||||
 | 
								Symlink("fortify", "/.fortify/sbin/init"),
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		"nixos permissive defaults chromium", new(stubNixOS),
 | 
							"nixos permissive defaults chromium", new(stubNixOS),
 | 
				
			||||||
@ -216,8 +216,6 @@ var testCasesPd = []sealTestCase{
 | 
				
			|||||||
			Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
 | 
								Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
 | 
				
			||||||
			Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
 | 
								Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
 | 
				
			||||||
			Ephemeral(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", acl.Execute).
 | 
								Ephemeral(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", acl.Execute).
 | 
				
			||||||
			WriteType(system.Process, "/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/passwd", "chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n").
 | 
					 | 
				
			||||||
			WriteType(system.Process, "/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/group", "fortify:x:65534:\n").
 | 
					 | 
				
			||||||
			Ensure("/tmp/fortify.1971/wayland", 0711).
 | 
								Ensure("/tmp/fortify.1971/wayland", 0711).
 | 
				
			||||||
			Wayland("/tmp/fortify.1971/wayland/ebf083d1b175911782d413369b64ce7c", "/run/user/1971/wayland-0", "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
 | 
								Wayland("/tmp/fortify.1971/wayland/ebf083d1b175911782d413369b64ce7c", "/run/user/1971/wayland-0", "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
 | 
				
			||||||
			Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse").
 | 
								Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse").
 | 
				
			||||||
@ -380,13 +378,15 @@ var testCasesPd = []sealTestCase{
 | 
				
			|||||||
			Tmpfs("/run/user", 1048576).
 | 
								Tmpfs("/run/user", 1048576).
 | 
				
			||||||
			Tmpfs("/run/user/65534", 8388608).
 | 
								Tmpfs("/run/user/65534", 8388608).
 | 
				
			||||||
			Bind("/home/chronos", "/home/chronos", false, true).
 | 
								Bind("/home/chronos", "/home/chronos", false, true).
 | 
				
			||||||
			Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/passwd", "/etc/passwd").
 | 
								CopyBind("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
 | 
				
			||||||
			Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/group", "/etc/group").
 | 
								CopyBind("/etc/group", []byte("fortify:x:65534:\n")).
 | 
				
			||||||
			Bind("/tmp/fortify.1971/wayland/ebf083d1b175911782d413369b64ce7c", "/run/user/65534/wayland-0").
 | 
								Bind("/tmp/fortify.1971/wayland/ebf083d1b175911782d413369b64ce7c", "/run/user/65534/wayland-0").
 | 
				
			||||||
			Bind("/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse", "/run/user/65534/pulse/native").
 | 
								Bind("/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse", "/run/user/65534/pulse/native").
 | 
				
			||||||
			Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/pulse-cookie", fst.Tmp+"/pulse-cookie").
 | 
								Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/pulse-cookie", fst.Tmp+"/pulse-cookie").
 | 
				
			||||||
			Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", "/run/user/65534/bus").
 | 
								Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", "/run/user/65534/bus").
 | 
				
			||||||
			Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", "/run/dbus/system_bus_socket").
 | 
								Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", "/run/dbus/system_bus_socket").
 | 
				
			||||||
			Tmpfs("/var/run/nscd", 8192),
 | 
								Tmpfs("/var/run/nscd", 8192).
 | 
				
			||||||
 | 
								Bind("/run/wrappers/bin/fortify", "/.fortify/sbin/fortify").
 | 
				
			||||||
 | 
								Symlink("fortify", "/.fortify/sbin/init"),
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,9 +16,12 @@ type stubNixOS struct {
 | 
				
			|||||||
	usernameErr map[string]error
 | 
						usernameErr map[string]error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *stubNixOS) Geteuid() int {
 | 
					func (s *stubNixOS) Geteuid() int                             { return 1971 }
 | 
				
			||||||
	return 1971
 | 
					func (s *stubNixOS) TempDir() string                          { return "/tmp" }
 | 
				
			||||||
}
 | 
					func (s *stubNixOS) MustExecutable() string                   { return "/run/wrappers/bin/fortify" }
 | 
				
			||||||
 | 
					func (s *stubNixOS) Exit(code int)                            { panic("called exit on stub with code " + strconv.Itoa(code)) }
 | 
				
			||||||
 | 
					func (s *stubNixOS) EvalSymlinks(path string) (string, error) { return path, nil }
 | 
				
			||||||
 | 
					func (s *stubNixOS) Uid(aid int) (int, error)                 { return 1000000 + 0*10000 + aid, nil }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *stubNixOS) LookupEnv(key string) (string, bool) {
 | 
					func (s *stubNixOS) LookupEnv(key string) (string, bool) {
 | 
				
			||||||
	switch key {
 | 
						switch key {
 | 
				
			||||||
@ -39,10 +42,6 @@ func (s *stubNixOS) LookupEnv(key string) (string, bool) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *stubNixOS) TempDir() string {
 | 
					 | 
				
			||||||
	return "/tmp"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *stubNixOS) LookPath(file string) (string, error) {
 | 
					func (s *stubNixOS) LookPath(file string) (string, error) {
 | 
				
			||||||
	if s.lookPathErr != nil {
 | 
						if s.lookPathErr != nil {
 | 
				
			||||||
		if err, ok := s.lookPathErr[file]; ok {
 | 
							if err, ok := s.lookPathErr[file]; ok {
 | 
				
			||||||
@ -60,10 +59,6 @@ func (s *stubNixOS) LookPath(file string) (string, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *stubNixOS) Executable() (string, error) {
 | 
					 | 
				
			||||||
	return "/home/ophestra/.nix-profile/bin/fortify", nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *stubNixOS) LookupGroup(name string) (*user.Group, error) {
 | 
					func (s *stubNixOS) LookupGroup(name string) (*user.Group, error) {
 | 
				
			||||||
	switch name {
 | 
						switch name {
 | 
				
			||||||
	case "video":
 | 
						case "video":
 | 
				
			||||||
@ -127,14 +122,6 @@ func (s *stubNixOS) Open(name string) (fs.File, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *stubNixOS) EvalSymlinks(path string) (string, error) {
 | 
					 | 
				
			||||||
	return path, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *stubNixOS) Exit(code int) {
 | 
					 | 
				
			||||||
	panic("called exit on stub with code " + strconv.Itoa(code))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *stubNixOS) Paths() linux.Paths {
 | 
					func (s *stubNixOS) Paths() linux.Paths {
 | 
				
			||||||
	return linux.Paths{
 | 
						return linux.Paths{
 | 
				
			||||||
		SharePath:   "/tmp/fortify.1971",
 | 
							SharePath:   "/tmp/fortify.1971",
 | 
				
			||||||
@ -142,11 +129,3 @@ func (s *stubNixOS) Paths() linux.Paths {
 | 
				
			|||||||
		RunDirPath:  "/run/user/1971/fortify",
 | 
							RunDirPath:  "/run/user/1971/fortify",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *stubNixOS) Uid(aid int) (int, error) {
 | 
					 | 
				
			||||||
	return 1000000 + 0*10000 + aid, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *stubNixOS) SdBooted() bool {
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -113,34 +113,25 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os linux.System) error {
 | 
				
			|||||||
		sh = s
 | 
							sh = s
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// generate /etc/passwd
 | 
						// bind home directory
 | 
				
			||||||
	passwdPath := path.Join(seal.share, "passwd")
 | 
					 | 
				
			||||||
	username := "chronos"
 | 
					 | 
				
			||||||
	if seal.sys.user.username != "" {
 | 
					 | 
				
			||||||
		username = seal.sys.user.username
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	homeDir := "/var/empty"
 | 
						homeDir := "/var/empty"
 | 
				
			||||||
	if seal.sys.user.home != "" {
 | 
						if seal.sys.user.home != "" {
 | 
				
			||||||
		homeDir = seal.sys.user.home
 | 
							homeDir = seal.sys.user.home
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						username := "chronos"
 | 
				
			||||||
	// bind home directory
 | 
						if seal.sys.user.username != "" {
 | 
				
			||||||
 | 
							username = seal.sys.user.username
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	seal.sys.bwrap.Bind(seal.sys.user.data, homeDir, false, true)
 | 
						seal.sys.bwrap.Bind(seal.sys.user.data, homeDir, false, true)
 | 
				
			||||||
	seal.sys.bwrap.Chdir = homeDir
 | 
						seal.sys.bwrap.Chdir = homeDir
 | 
				
			||||||
 | 
					 | 
				
			||||||
	seal.sys.bwrap.SetEnv["USER"] = username
 | 
					 | 
				
			||||||
	seal.sys.bwrap.SetEnv["HOME"] = homeDir
 | 
						seal.sys.bwrap.SetEnv["HOME"] = homeDir
 | 
				
			||||||
 | 
						seal.sys.bwrap.SetEnv["USER"] = username
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	passwd := username + ":x:" + seal.sys.mappedIDString + ":" + seal.sys.mappedIDString + ":Fortify:" + homeDir + ":" + sh + "\n"
 | 
						// generate /etc/passwd and /etc/group
 | 
				
			||||||
	seal.sys.Write(passwdPath, passwd)
 | 
						seal.sys.bwrap.CopyBind("/etc/passwd",
 | 
				
			||||||
 | 
							[]byte(username+":x:"+seal.sys.mappedIDString+":"+seal.sys.mappedIDString+":Fortify:"+homeDir+":"+sh+"\n"))
 | 
				
			||||||
	// write /etc/group
 | 
						seal.sys.bwrap.CopyBind("/etc/group",
 | 
				
			||||||
	groupPath := path.Join(seal.share, "group")
 | 
							[]byte("fortify:x:"+seal.sys.mappedIDString+":\n"))
 | 
				
			||||||
	seal.sys.Write(groupPath, "fortify:x:"+seal.sys.mappedIDString+":\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// bind /etc/passwd and /etc/group
 | 
					 | 
				
			||||||
	seal.sys.bwrap.Bind(passwdPath, "/etc/passwd")
 | 
					 | 
				
			||||||
	seal.sys.bwrap.Bind(groupPath, "/etc/group")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
		Display servers
 | 
							Display servers
 | 
				
			||||||
@ -293,6 +284,10 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os linux.System) error {
 | 
				
			|||||||
		seal.sys.bwrap.Tmpfs(dest, 8*1024)
 | 
							seal.sys.bwrap.Tmpfs(dest, 8*1024)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// mount fortify in sandbox for init
 | 
				
			||||||
 | 
						seal.sys.bwrap.Bind(os.MustExecutable(), path.Join(fst.Tmp, "sbin/fortify"))
 | 
				
			||||||
 | 
						seal.sys.bwrap.Symlink("fortify", path.Join(fst.Tmp, "sbin/init"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// append extra perms
 | 
						// append extra perms
 | 
				
			||||||
	for _, p := range seal.extraPerms {
 | 
						for _, p := range seal.extraPerms {
 | 
				
			||||||
		if p == nil {
 | 
							if p == nil {
 | 
				
			||||||
 | 
				
			|||||||
@ -19,8 +19,8 @@ type System interface {
 | 
				
			|||||||
	TempDir() string
 | 
						TempDir() string
 | 
				
			||||||
	// LookPath provides [exec.LookPath].
 | 
						// LookPath provides [exec.LookPath].
 | 
				
			||||||
	LookPath(file string) (string, error)
 | 
						LookPath(file string) (string, error)
 | 
				
			||||||
	// Executable provides [os.Executable].
 | 
						// MustExecutable provides [proc.MustExecutable].
 | 
				
			||||||
	Executable() (string, error)
 | 
						MustExecutable() string
 | 
				
			||||||
	// LookupGroup provides [user.LookupGroup].
 | 
						// LookupGroup provides [user.LookupGroup].
 | 
				
			||||||
	LookupGroup(name string) (*user.Group, error)
 | 
						LookupGroup(name string) (*user.Group, error)
 | 
				
			||||||
	// ReadDir provides [os.ReadDir].
 | 
						// ReadDir provides [os.ReadDir].
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.gensokyo.uk/security/fortify/helper/proc"
 | 
				
			||||||
	"git.gensokyo.uk/security/fortify/internal"
 | 
						"git.gensokyo.uk/security/fortify/internal"
 | 
				
			||||||
	"git.gensokyo.uk/security/fortify/internal/fmsg"
 | 
						"git.gensokyo.uk/security/fortify/internal/fmsg"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -32,7 +33,7 @@ func (s *Std) Geteuid() int                                 { return os.Geteuid(
 | 
				
			|||||||
func (s *Std) LookupEnv(key string) (string, bool)          { return os.LookupEnv(key) }
 | 
					func (s *Std) LookupEnv(key string) (string, bool)          { return os.LookupEnv(key) }
 | 
				
			||||||
func (s *Std) TempDir() string                              { return os.TempDir() }
 | 
					func (s *Std) TempDir() string                              { return os.TempDir() }
 | 
				
			||||||
func (s *Std) LookPath(file string) (string, error)         { return exec.LookPath(file) }
 | 
					func (s *Std) LookPath(file string) (string, error)         { return exec.LookPath(file) }
 | 
				
			||||||
func (s *Std) Executable() (string, error)                  { return os.Executable() }
 | 
					func (s *Std) MustExecutable() string                       { return proc.MustExecutable() }
 | 
				
			||||||
func (s *Std) LookupGroup(name string) (*user.Group, error) { return user.LookupGroup(name) }
 | 
					func (s *Std) LookupGroup(name string) (*user.Group, error) { return user.LookupGroup(name) }
 | 
				
			||||||
func (s *Std) ReadDir(name string) ([]os.DirEntry, error)   { return os.ReadDir(name) }
 | 
					func (s *Std) ReadDir(name string) ([]os.DirEntry, error)   { return os.ReadDir(name) }
 | 
				
			||||||
func (s *Std) Stat(name string) (fs.FileInfo, error)        { return os.Stat(name) }
 | 
					func (s *Std) Stat(name string) (fs.FileInfo, error)        { return os.Stat(name) }
 | 
				
			||||||
 | 
				
			|||||||
@ -121,21 +121,12 @@ func Main() {
 | 
				
			|||||||
		}()
 | 
							}()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// bind fortify inside sandbox
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		innerSbin    = path.Join(fst.Tmp, "sbin")
 | 
					 | 
				
			||||||
		innerFortify = path.Join(innerSbin, "fortify")
 | 
					 | 
				
			||||||
		innerInit    = path.Join(innerSbin, "init")
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	conf.Bind(proc.MustExecutable(), innerFortify)
 | 
					 | 
				
			||||||
	conf.Symlink("fortify", innerInit)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	helper.BubblewrapName = payload.Exec[0] // resolved bwrap path by parent
 | 
						helper.BubblewrapName = payload.Exec[0] // resolved bwrap path by parent
 | 
				
			||||||
	if fmsg.Verbose() {
 | 
						if fmsg.Verbose() {
 | 
				
			||||||
		seccomp.CPrintln = fmsg.Println
 | 
							seccomp.CPrintln = fmsg.Println
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if b, err := helper.NewBwrap(
 | 
						if b, err := helper.NewBwrap(
 | 
				
			||||||
		conf, innerInit,
 | 
							conf, path.Join(fst.Tmp, "sbin/init"),
 | 
				
			||||||
		nil, func(int, int) []string { return make([]string, 0) },
 | 
							nil, func(int, int) []string { return make([]string, 0) },
 | 
				
			||||||
		extraFiles,
 | 
							extraFiles,
 | 
				
			||||||
		syncFd,
 | 
							syncFd,
 | 
				
			||||||
 | 
				
			|||||||
@ -42,26 +42,9 @@ func (sys *I) LinkFileType(et Enablement, oldname, newname string) *I {
 | 
				
			|||||||
	return sys
 | 
						return sys
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Write registers an Op that writes dst with the contents of src.
 | 
					 | 
				
			||||||
func (sys *I) Write(dst, src string) *I {
 | 
					 | 
				
			||||||
	return sys.WriteType(Process, dst, src)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WriteType registers a file writing Op labelled with type et.
 | 
					 | 
				
			||||||
func (sys *I) WriteType(et Enablement, dst, src string) *I {
 | 
					 | 
				
			||||||
	sys.lock.Lock()
 | 
					 | 
				
			||||||
	sys.ops = append(sys.ops, &Tmpfile{et, tmpfileWrite, dst, src})
 | 
					 | 
				
			||||||
	sys.lock.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sys.UpdatePermType(et, dst, acl.Read)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sys
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	tmpfileCopy uint8 = iota
 | 
						tmpfileCopy uint8 = iota
 | 
				
			||||||
	tmpfileLink
 | 
						tmpfileLink
 | 
				
			||||||
	tmpfileWrite
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Tmpfile struct {
 | 
					type Tmpfile struct {
 | 
				
			||||||
@ -84,10 +67,6 @@ func (t *Tmpfile) apply(_ *I) error {
 | 
				
			|||||||
		fmsg.VPrintln("linking tmpfile", t)
 | 
							fmsg.VPrintln("linking tmpfile", t)
 | 
				
			||||||
		return fmsg.WrapErrorSuffix(os.Link(t.src, t.dst),
 | 
							return fmsg.WrapErrorSuffix(os.Link(t.src, t.dst),
 | 
				
			||||||
			fmt.Sprintf("cannot link tmpfile %q:", t.dst))
 | 
								fmt.Sprintf("cannot link tmpfile %q:", t.dst))
 | 
				
			||||||
	case tmpfileWrite:
 | 
					 | 
				
			||||||
		fmsg.VPrintln("writing", t)
 | 
					 | 
				
			||||||
		return fmsg.WrapErrorSuffix(os.WriteFile(t.dst, []byte(t.src), 0600),
 | 
					 | 
				
			||||||
			fmt.Sprintf("cannot write tmpfile %q:", t.dst))
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("invalid tmpfile method " + strconv.Itoa(int(t.method)))
 | 
							panic("invalid tmpfile method " + strconv.Itoa(int(t.method)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -109,12 +88,7 @@ func (t *Tmpfile) Is(o Op) bool {
 | 
				
			|||||||
	return ok && t0 != nil && *t == *t0
 | 
						return ok && t0 != nil && *t == *t0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (t *Tmpfile) Path() string {
 | 
					func (t *Tmpfile) Path() string { return t.src }
 | 
				
			||||||
	if t.method == tmpfileWrite {
 | 
					 | 
				
			||||||
		return fmt.Sprintf("(%d bytes of data)", len(t.src))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return t.src
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (t *Tmpfile) String() string {
 | 
					func (t *Tmpfile) String() string {
 | 
				
			||||||
	switch t.method {
 | 
						switch t.method {
 | 
				
			||||||
@ -122,8 +96,6 @@ func (t *Tmpfile) String() string {
 | 
				
			|||||||
		return fmt.Sprintf("%q from %q", t.dst, t.src)
 | 
							return fmt.Sprintf("%q from %q", t.dst, t.src)
 | 
				
			||||||
	case tmpfileLink:
 | 
						case tmpfileLink:
 | 
				
			||||||
		return fmt.Sprintf("%q from %q", t.dst, t.src)
 | 
							return fmt.Sprintf("%q from %q", t.dst, t.src)
 | 
				
			||||||
	case tmpfileWrite:
 | 
					 | 
				
			||||||
		return fmt.Sprintf("%d bytes of data to %q", len(t.src), t.dst)
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("invalid tmpfile method " + strconv.Itoa(int(t.method)))
 | 
							panic("invalid tmpfile method " + strconv.Itoa(int(t.method)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
package system
 | 
					package system
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.gensokyo.uk/security/fortify/acl"
 | 
						"git.gensokyo.uk/security/fortify/acl"
 | 
				
			||||||
@ -83,47 +82,6 @@ func TestLinkFileType(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestWrite(t *testing.T) {
 | 
					 | 
				
			||||||
	testCases := []struct {
 | 
					 | 
				
			||||||
		dst, src string
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{"/etc/passwd", "chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n"},
 | 
					 | 
				
			||||||
		{"/etc/group", "fortify:x:65534:\n"},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range testCases {
 | 
					 | 
				
			||||||
		t.Run("write "+strconv.Itoa(len(tc.src))+" bytes to "+tc.dst, func(t *testing.T) {
 | 
					 | 
				
			||||||
			sys := New(150)
 | 
					 | 
				
			||||||
			sys.Write(tc.dst, tc.src)
 | 
					 | 
				
			||||||
			(&tcOp{Process, "(" + strconv.Itoa(len(tc.src)) + " bytes of data)"}).test(t, sys.ops, []Op{
 | 
					 | 
				
			||||||
				&Tmpfile{Process, tmpfileWrite, tc.dst, tc.src},
 | 
					 | 
				
			||||||
				&ACL{Process, tc.dst, []acl.Perm{acl.Read}},
 | 
					 | 
				
			||||||
			}, "Write")
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestWriteType(t *testing.T) {
 | 
					 | 
				
			||||||
	testCases := []struct {
 | 
					 | 
				
			||||||
		et       Enablement
 | 
					 | 
				
			||||||
		dst, src string
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{Process, "/etc/passwd", "chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n"},
 | 
					 | 
				
			||||||
		{Process, "/etc/group", "fortify:x:65534:\n"},
 | 
					 | 
				
			||||||
		{User, "/etc/passwd", "chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n"},
 | 
					 | 
				
			||||||
		{User, "/etc/group", "fortify:x:65534:\n"},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range testCases {
 | 
					 | 
				
			||||||
		t.Run("write "+strconv.Itoa(len(tc.src))+" bytes to "+tc.dst+" with type "+TypeString(tc.et), func(t *testing.T) {
 | 
					 | 
				
			||||||
			sys := New(150)
 | 
					 | 
				
			||||||
			sys.WriteType(tc.et, tc.dst, tc.src)
 | 
					 | 
				
			||||||
			(&tcOp{tc.et, "(" + strconv.Itoa(len(tc.src)) + " bytes of data)"}).test(t, sys.ops, []Op{
 | 
					 | 
				
			||||||
				&Tmpfile{tc.et, tmpfileWrite, tc.dst, tc.src},
 | 
					 | 
				
			||||||
				&ACL{tc.et, tc.dst, []acl.Perm{acl.Read}},
 | 
					 | 
				
			||||||
			}, "WriteType")
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestTmpfile_String(t *testing.T) {
 | 
					func TestTmpfile_String(t *testing.T) {
 | 
				
			||||||
	t.Run("invalid method panic", func(t *testing.T) {
 | 
						t.Run("invalid method panic", func(t *testing.T) {
 | 
				
			||||||
		defer func() {
 | 
							defer func() {
 | 
				
			||||||
@ -147,10 +105,6 @@ func TestTmpfile_String(t *testing.T) {
 | 
				
			|||||||
			`"/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/wayland" from "/run/user/1971/wayland-0"`},
 | 
								`"/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/wayland" from "/run/user/1971/wayland-0"`},
 | 
				
			||||||
		{tmpfileLink, "/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse", "/run/user/1971/pulse/native",
 | 
							{tmpfileLink, "/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse", "/run/user/1971/pulse/native",
 | 
				
			||||||
			`"/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse" from "/run/user/1971/pulse/native"`},
 | 
								`"/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse" from "/run/user/1971/pulse/native"`},
 | 
				
			||||||
		{tmpfileWrite, "/tmp/fortify.1971/4b6bdc9182fb2f1d3a965c5fa8b9b66e/passwd", "chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n",
 | 
					 | 
				
			||||||
			`75 bytes of data to "/tmp/fortify.1971/4b6bdc9182fb2f1d3a965c5fa8b9b66e/passwd"`},
 | 
					 | 
				
			||||||
		{tmpfileWrite, "/tmp/fortify.1971/4b6bdc9182fb2f1d3a965c5fa8b9b66e/group", "fortify:x:65534:\n",
 | 
					 | 
				
			||||||
			`17 bytes of data to "/tmp/fortify.1971/4b6bdc9182fb2f1d3a965c5fa8b9b66e/group"`},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user