Skip to content

Instantly share code, notes, and snippets.

@Profpatsch
Created October 4, 2019 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Profpatsch/f7238fe129a93db9917e6b912d1b9b42 to your computer and use it in GitHub Desktop.
Save Profpatsch/f7238fe129a93db9917e6b912d1b9b42 to your computer and use it in GitHub Desktop.
let
# lightweight sandbox; execute any command in an unshared
# namespace that only has access to /nix and the specified
# directories.
sandbox = { extraMounts ? [] }:
let
pathsToMount = [ "/nix" "/dev" "/proc" "/sys" ];
# chain execlines and exit immediately if one fails
all = builtins.concatMap (c: [ "if" c ]);
mount = "${pkgs.utillinux}/bin/mount";
# this is the directory the sandbox runs under (in a separate mount namespace)
newroot = pkgs.runCommand "sandbox-root" {} ''mkdir "$out"'';
# this runs in a separate namespace, sets up a chroot root
# and then chroots into the new root.
sandbox = writeExecline "sandbox" {} (builtins.concatLists [
# first, unshare the mount namespace and make us root
# -> requires user namespaces!
[ "unshare" "--mount" "--map-root-user" ]
(all
# mount a temporary file system which we can chroot to;
# we can use the fixed path newroot here, because the resulting
# tmpfs cannot be seen from the outside world (we are in an unshared
# mount namespace)
([ [ mount "-t" "tmpfs" "container_root" newroot ] ]
# now mount the file system parts we need into the chroot
++ builtins.concatMap
(rootPath: [
[ "${pkgs.coreutils}/bin/mkdir" "-p" "${newroot}${rootPath}" ]
[ mount "--rbind" rootPath "${newroot}${rootPath}" ]
])
pathsToMount))
# finally, chroot into our new root directory
[ "${pkgs.coreutils}/bin/chroot" newroot "$@" ]
]);
in sandbox;
in sandbox;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment