aboutsummaryrefslogtreecommitdiffhomepage
path: root/helper/bwrap/config.go
blob: 9e15a29a11f25b7624d65ed262382794e344083d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package bwrap

import (
	"encoding/gob"
	"os"
	"strconv"
)

func init() {
	gob.Register(new(PermConfig[SymlinkConfig]))
	gob.Register(new(PermConfig[*TmpfsConfig]))
}

type Config struct {
	// unshare every namespace we support by default if nil
	// (--unshare-all)
	Unshare *UnshareConfig `json:"unshare,omitempty"`
	// retain the network namespace (can only combine with nil Unshare)
	// (--share-net)
	Net bool `json:"net"`

	// disable further use of user namespaces inside sandbox and fail unless
	// further use of user namespace inside sandbox is disabled if false
	// (--disable-userns) (--assert-userns-disabled)
	UserNS bool `json:"userns"`

	// custom uid in the sandbox, requires new user namespace
	// (--uid UID)
	UID *int `json:"uid,omitempty"`
	// custom gid in the sandbox, requires new user namespace
	// (--gid GID)
	GID *int `json:"gid,omitempty"`
	// custom hostname in the sandbox, requires new uts namespace
	// (--hostname NAME)
	Hostname string `json:"hostname,omitempty"`

	// change directory
	// (--chdir DIR)
	Chdir string `json:"chdir,omitempty"`
	// unset all environment variables
	// (--clearenv)
	Clearenv bool `json:"clearenv"`
	// set environment variable
	// (--setenv VAR VALUE)
	SetEnv map[string]string `json:"setenv,omitempty"`
	// unset environment variables
	// (--unsetenv VAR)
	UnsetEnv []string `json:"unsetenv,omitempty"`

	// take a lock on file while sandbox is running
	// (--lock-file DEST)
	LockFile []string `json:"lock_file,omitempty"`

	// ordered filesystem args
	Filesystem []FSBuilder

	// change permissions (must already exist)
	// (--chmod OCTAL PATH)
	Chmod ChmodConfig `json:"chmod,omitempty"`

	// create a new terminal session
	// (--new-session)
	NewSession bool `json:"new_session"`
	// kills with SIGKILL child process (COMMAND) when bwrap or bwrap's parent dies.
	// (--die-with-parent)
	DieWithParent bool `json:"die_with_parent"`
	// do not install a reaper process with PID=1
	// (--as-pid-1)
	AsInit bool `json:"as_init"`

	// keep this fd open while sandbox is running
	// (--sync-fd FD)
	sync *os.File

	/* unmapped options include:
	    --unshare-user-try           Create new user namespace if possible else continue by skipping it
	    --unshare-cgroup-try         Create new cgroup namespace if possible else continue by skipping it
	    --userns FD                  Use this user namespace (cannot combine with --unshare-user)
	    --userns2 FD                 After setup switch to this user namespace, only useful with --userns
	    --pidns FD                   Use this pid namespace (as parent namespace if using --unshare-pid)
	    --exec-label LABEL           Exec label for the sandbox
	    --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
	    --seccomp FD                 Load and use seccomp rules from FD (not 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
	    --userns-block-fd FD         Block on FD until the user namespace is ready
	    --info-fd FD                 Write information about the running container to FD
	    --json-status-fd FD          Write container status to FD as multiple JSON documents
	    --cap-add CAP                Add cap CAP when running as privileged user
	    --cap-drop CAP               Drop cap CAP when running as privileged user

	among which --args is used internally for passing arguments */
}

// Sync keep this fd open while sandbox is running
// (--sync-fd FD)
func (c *Config) Sync() *os.File {
	return c.sync
}

type UnshareConfig struct {
	// (--unshare-user)
	// create new user namespace
	User bool `json:"user"`
	// (--unshare-ipc)
	// create new ipc namespace
	IPC bool `json:"ipc"`
	// (--unshare-pid)
	// create new pid namespace
	PID bool `json:"pid"`
	// (--unshare-net)
	// create new network namespace
	Net bool `json:"net"`
	// (--unshare-uts)
	// create new uts namespace
	UTS bool `json:"uts"`
	// (--unshare-cgroup)
	// create new cgroup namespace
	CGroup bool `json:"cgroup"`
}

type PermConfig[T FSBuilder] struct {
	// set permissions of next argument
	// (--perms OCTAL)
	Mode *os.FileMode `json:"mode,omitempty"`
	// path to get the new permission
	// (--bind-data, --file, etc.)
	Inner T `json:"path"`
}

func (p *PermConfig[T]) Path() string {
	return p.Inner.Path()
}

func (p *PermConfig[T]) Len() int {
	if p.Mode != nil {
		return p.Inner.Len() + 2
	} else {
		return p.Inner.Len()
	}
}

func (p *PermConfig[T]) Append(args *[]string) {
	if p.Mode != nil {
		*args = append(*args, intArgs[Perms], strconv.FormatInt(int64(*p.Mode), 8))
	}
	p.Inner.Append(args)
}

type TmpfsConfig struct {
	// set size of tmpfs
	// (--size BYTES)
	Size int `json:"size,omitempty"`
	// mount point of new tmpfs
	// (--tmpfs DEST)
	Dir string `json:"dir"`
}

func (t *TmpfsConfig) Path() string {
	return t.Dir
}

func (t *TmpfsConfig) Len() int {
	if t.Size > 0 {
		return 4
	} else {
		return 2
	}
}

func (t *TmpfsConfig) Append(args *[]string) {
	if t.Size > 0 {
		*args = append(*args, intArgs[Size], strconv.Itoa(t.Size))
	}
	*args = append(*args, awkwardArgs[Tmpfs], t.Dir)
}

type SymlinkConfig [2]string

func (s SymlinkConfig) Path() string {
	return s[1]
}

func (s SymlinkConfig) Len() int {
	return 3
}

func (s SymlinkConfig) Append(args *[]string) {
	*args = append(*args, awkwardArgs[Symlink], s[0], s[1])
}

type ChmodConfig map[string]os.FileMode

func (c ChmodConfig) Len() int {
	return len(c)
}

func (c ChmodConfig) Append(args *[]string) {
	for path, mode := range c {
		*args = append(*args, pairArgs[Chmod], strconv.FormatInt(int64(mode), 8), path)
	}
}