diff --git a/config.json b/config.json new file mode 100644 index 0000000..4f0836f --- /dev/null +++ b/config.json @@ -0,0 +1,10 @@ +{ + "mount": [], + "romount": ["/etc", "/var", "/usr", "/opt", ".oh-my-zsh", ".zsh", ".zshrc"], + "symlinks": [ + {"src": "usr/lib", "dst": "/lib"}, + {"src": "usr/lib64", "dst": "/lib64"}, + {"src": "usr/bin", "dst": "/bin"}, + {"src": "usr/sbin", "dst": "/sbin"} + ] +} diff --git a/lib/bwrap.nim b/lib/bwrap.nim index 758d2ba..25cb19e 100644 --- a/lib/bwrap.nim +++ b/lib/bwrap.nim @@ -15,4 +15,4 @@ proc addMount*(call: var BwrapCall, mType: string, path: string): var BwrapCall proc exec*(call: var BwrapCall) = echo call.args - discard execv("/usr/bin/bwrap", allocCStringArray(@["bwrap"].concat(call.args))) \ No newline at end of file + discard execv("/usr/bin/bwrap", allocCStringArray(@["bwrap"].concat(call.args))) diff --git a/lib/config.nim b/lib/config.nim new file mode 100644 index 0000000..002bd9e --- /dev/null +++ b/lib/config.nim @@ -0,0 +1,10 @@ +import options + +type Link* = object + src*: string + dst*: string + +type Config* = object + mount*: Option[seq[string]] + romount*: Option[seq[string]] + symlinks*: Option[seq[Link]] diff --git a/lib/sandbox.nim b/lib/sandbox.nim new file mode 100644 index 0000000..9d4d859 --- /dev/null +++ b/lib/sandbox.nim @@ -0,0 +1,55 @@ +import os +import json +import bwrap +import config +import options + +const CONFIG_LOCATION = "config.json" + +proc homePath(p: string): string = + joinPath(getHomeDir(), p) + +proc checkRelativePath(p: string): string = + if p[0] == '/': + return p + homePath(p) + +proc applyConfig(call: var BwrapCall, config: Config) = + for mount in config.mount.get(@[]): + call.addMount("--bind", checkRelativePath(mount)) + + for mount in config.romount.get(@[]): + call.addMount("--ro-bind", checkRelativePath(mount)) + + for symlink in config.symlinks.get(@[]): + call.addArg("--symlink", symlink.src, symlink.dst) + +proc loadConfig(path: string): Config = + return readFile(path).parseJson().to(Config) + +proc sandboxExec*(name: string, command: string) = + let sandboxPath = homePath(joinPath(".sandboxes", name)) + let sandboxFiles = joinPath(sandboxPath, "files") + let sandboxInfo = joinPath(sandboxPath, "info") + + createDir(sandboxFiles) + var call = BwrapCall() + + call + .addArg("--bind", sandboxFiles, getHomeDir()) + .addMount("--dev-bind", "/dev") + .addArg("--dir", "/tmp") + .addArg("--proc", "/proc") + .addArg("--unshare-all") + .addArg("--share-net") + .addArg("--die-with-parent") + .addArg("--hostname", name) + .addArg("--chdir", getHomeDir()) + .applyConfig(loadConfig(CONFIG_LOCATION)) + + let configPath = sandboxPath.joinPath("config.json") + echo configPath + if fileExists(configPath): + call.applyConfig(loadConfig(configPath)) + + call.addArg(command).exec() diff --git a/main.nim b/main.nim index 2993821..44e9029 100644 --- a/main.nim +++ b/main.nim @@ -1,88 +1,24 @@ +import lib/sandbox import strformat -import lib/bwrap import os -proc homePath(p: string): string = - joinPath(getHomeDir(), p) +proc main() = + let mode = splitPath(getAppFilename()).tail + let args = commandLineParams() + let argc = paramCount() -let mode = splitPath(getAppFilename()).tail -let args = commandLineParams() -let argc = paramCount() + if argc == 0: + echo &"Usage: {mode} [command]" + quit(1) -if argc == 0: - echo &"Usage: {mode} [command]" - quit(1) + let name = args[0] + var command: string -let name = args[0] -var command = "" + if argc > 1: + command = args[1] + else: + command = getEnv("SHELL", "/bin/sh") -if argc > 1: - command = args[1] -else: - command = getEnv("SHELL", "/bin/sh") + sandboxExec(name, command) -let sandboxPath = homePath(joinPath("sandboxes", name)) -let sandboxFiles = joinPath(sandboxPath, "files") -let sandboxInfo = joinPath(sandboxPath, "info") - -createDir(sandboxFiles) - -var call = BwrapCall() - -call.addArg("--bind", sandboxFiles, getHomeDir()) - -for mount in ["/sys"]: - call.addMount("--bind", mount) - -for mount in ["/etc", "/var", "/usr", "/opt", homePath(".oh-my-zsh"), homePath(".zsh"), homePath(".zshrc")]: - call.addMount("--ro-bind", mount) - -call - .addMount("--dev-bind", "/dev") - .addArg("--dir", "/tmp") - .addArg("--symlink", "usr/lib", "/lib") - .addArg("--symlink", "usr/lib64", "/lib64") - .addArg("--symlink", "usr/bin", "/bin") - .addArg("--symlink", "usr/sbin", "/sbin") - .addArg("--proc", "/proc") - .addArg("--unshare-all") - .addArg("--share-net") - .addArg("--die-with-parent") - .addArg("--hostname", name) - .addArg("--chdir", getHomeDir()) - .addArg(command) - .exec() - -#[ -(exec bwrap --bind $sandbox_files $HOME \ - ${cli_mode:+--bind $(pwd) $(pwd)} \ - ${cli_mode:+--bind $SSH_AUTH_SOCK $SSH_AUTH_SOCK} \ - ${gui_mode:+--bind /run/user/$(id -u)/pulse /run/user/$(id -u)/pulse} \ - ${gui_mode:+--bind /run/user/$(id -u)/wayland-0 /run/user/$(id -u)/wayland-0} \ - --bind /sys /sys \ - --ro-bind /etc /etc \ - --ro-bind /var /var \ - --ro-bind /usr /usr \ - --ro-bind /opt /opt \ - --ro-bind $HOME/.zshrc $HOME/.zshrc \ - --ro-bind $HOME/.zsh $HOME/.zsh \ - --ro-bind $HOME/.oh-my-zsh $HOME/.oh-my-zsh \ - --ro-bind $HOME/.ssh/known_hosts $HOME/.ssh/known_hosts \ - --dev-bind /dev /dev \ - --dir /tmp \ - --dir $HOME/.ssh \ - --symlink usr/lib /lib \ - --symlink usr/lib64 /lib64 \ - --symlink usr/bin /bin \ - --symlink usr/sbin /sbin \ - --proc /proc \ - --unshare-all \ - --share-net \ - --die-with-parent \ - --setenv XDG_RUNTIME_DIR "/run/user/$(id -u)" \ - --hostname "$name" \ - --chdir "$run_chdir" \ - --info-fd 11 \ - "$run_command") \ - 11> "$sandbox_info" -]# \ No newline at end of file +main()