lib: Improve the sandbox derivation
This commit is contained in:
136
lib/sandbox.nix
136
lib/sandbox.nix
@@ -5,38 +5,38 @@
|
||||
}:
|
||||
|
||||
{
|
||||
name
|
||||
, package
|
||||
, binaryName
|
||||
, version ? "1.0.0"
|
||||
, desktopFileArgs ? null
|
||||
, copyIntoSandbox ? null
|
||||
name # Name of the sandboxed package, e.g. "package-wrapped"
|
||||
, launchScriptName # Name of the script that will be placed in $out/bin
|
||||
, binary # The binary to execute inside the sandbox
|
||||
, extraArgs ? [] # Extra arguments to add to the argv
|
||||
, desktopFileAttributes ? {} # Arguments to apply to the desktop file
|
||||
, preDesktopFilePhase ? "" # Code to run during the install phase before building the desktop file
|
||||
, enableDesktopFile ? false # Whether to build a desktop file
|
||||
, copyIntoSandbox ? {} # Source -> destination relative to $out
|
||||
, unshareUser ? true
|
||||
, unshareIpc ? true
|
||||
, unsharePid ? true
|
||||
, unshareNet ? false
|
||||
, unshareUts ? true
|
||||
, unshareCgroup ? true
|
||||
, dieWithParent ? true
|
||||
, mountInHome ? []
|
||||
, chdirTo ? "\"$(pwd)\""
|
||||
, additionalBlacklist ? []
|
||||
, additionalMounts ? []
|
||||
, extraEnv ? {}
|
||||
, dieWithParent ? true # Should bubblewrap exit when the parents exits
|
||||
, mountInHome ? [] # Files, directories to mount inside the sandbox
|
||||
, chdirTo ? "\"$(pwd)\"" # What should be the CWD when entering the sandbox
|
||||
, additionalBlacklist ? [] # Root directories that should not be mounted
|
||||
, additionalMounts ? [] # Files, directories outside the home directory to mount inside the sandbox
|
||||
, extraEnv ? {} # Extra environment variables to set inside the sandbox
|
||||
, enableAlsa ? true # Mount ALSA files from /etc/
|
||||
, enableSudo ? true # Mount sudo files from /etc/
|
||||
, enableShells ? true # Mount shell related files from /etc/
|
||||
, enableNix ? true # Mount nix related files from /etc/
|
||||
, enableOsInfo ? true # Mount /etc/{machine-id,os-release}
|
||||
}:
|
||||
|
||||
let
|
||||
mountHome = mountInHome == [];
|
||||
|
||||
etcBindFlags = let
|
||||
files = [
|
||||
# NixOS Compatibility
|
||||
"static"
|
||||
"nix" # mainly for nixUnstable users, but also for access to nix/netrc
|
||||
# Shells
|
||||
"bashrc"
|
||||
"zshenv"
|
||||
"zshrc"
|
||||
"zinputrc"
|
||||
"zprofile"
|
||||
# Users, Groups, NSS
|
||||
"passwd"
|
||||
"group"
|
||||
@@ -46,30 +46,23 @@ let
|
||||
"nsswitch.conf"
|
||||
# User profiles
|
||||
"profiles"
|
||||
# Sudo & Su
|
||||
"login.defs"
|
||||
"sudoers"
|
||||
"sudoers.d"
|
||||
# Time
|
||||
"localtime"
|
||||
"zoneinfo"
|
||||
# Other Core Stuff
|
||||
"machine-id"
|
||||
"os-release"
|
||||
# PAM
|
||||
"pam.d"
|
||||
# Fonts
|
||||
"fonts"
|
||||
# ALSA
|
||||
"alsa"
|
||||
"asound.conf"
|
||||
# SSL
|
||||
"ssl/certs"
|
||||
"pki"
|
||||
];
|
||||
in builtins.concatStringsSep "\n "
|
||||
(map (file: "--ro-bind-try /etc/${file} /etc/${file}") files);
|
||||
|
||||
]
|
||||
++ (lib.optionals enableNix [ "static" "nix" ])
|
||||
++ (lib.optionals enableShells [ "bashrc" "zshenv" "zshrc" "zinputrc" "zprofile" ])
|
||||
++ (lib.optionals enableSudo [ "login.defs" "sudoers" "sudoers.d" ])
|
||||
++ (lib.optionals enableAlsa [ "alsa" "asound.conf" ])
|
||||
++ (lib.optionals enableOsInfo [ "machine-id" "os-release" ])
|
||||
# Only add SSL stuff when we have networking enabled
|
||||
++ (lib.optionals (!unshareNet) [ "ssl/certs" "pki" ]);
|
||||
in builtins.concatStringsSep "\n " (map (file: "--ro-bind-try /etc/${file} /etc/${file}") files);
|
||||
|
||||
# Create this on the fly instead of linking from /nix
|
||||
# The container might have to modify it and re-run ldconfig if there are
|
||||
# issues running some binary with LD_LIBRARY_PATH
|
||||
@@ -88,15 +81,21 @@ let
|
||||
EOF
|
||||
ldconfig &> /dev/null
|
||||
'';
|
||||
init = run: writeShellScriptBin "${binaryName}-init" ''
|
||||
sandboxInitScriptName = "${name}-wrapped-init.sh";
|
||||
sandboxInitScript = writeShellScriptBin sandboxInitScriptName ''
|
||||
source /etc/profile
|
||||
${createLdConfCache}
|
||||
exec ${run} "$@"
|
||||
exec ${binary} "$@"
|
||||
'';
|
||||
extraEnvString = lib.foldl (acc: val: acc + val + "\n") "" (lib.mapAttrsToList (name: value: "--setenv ${name} \"${value}\"") extraEnv);
|
||||
mountHome = mountInHome == [];
|
||||
initStr = init "${package}/bin/${binaryName}";
|
||||
bwrapCmd = { initArgs ? "" }: ''
|
||||
|
||||
|
||||
sandboxScriptName = "${name}-wrapped.sh";
|
||||
sandboxScript = let
|
||||
extraEnvString = lib.foldl (acc: val: acc + val + "\n") "" (lib.mapAttrsToList (name: value: "--setenv ${name} \"${value}\"") extraEnv);
|
||||
stringify = x: "\"${x}\"";
|
||||
safeAdditionalMounts = map stringify additionalMounts;
|
||||
safeMountInHome = map stringify mountInHome;
|
||||
in writeShellScriptBin sandboxScriptName ''
|
||||
blacklist=(/nix /dev /proc /etc ${lib.optionalString (!mountHome) "/home"} ${builtins.toString additionalBlacklist})
|
||||
ro_mounts=()
|
||||
symlinks=()
|
||||
@@ -112,13 +111,13 @@ let
|
||||
done
|
||||
|
||||
if [[ "${lib.optionalString (!mountHome) "1"}" = "1" ]]; then
|
||||
for entry in ${builtins.toString mountInHome}; do
|
||||
for entry in ${builtins.toString safeMountInHome}; do
|
||||
auto_mounts+=(--bind "/home/$USER/$entry" "/home/$USER/$entry")
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ ! -z "${builtins.toString additionalMounts}" ]]; then
|
||||
for entry in ${builtins.toString additionalMounts}; do
|
||||
for entry in ${builtins.toString safeAdditionalMounts}; do
|
||||
auto_mounts+=(--bind "$entry" "$entry")
|
||||
done
|
||||
fi
|
||||
@@ -158,27 +157,40 @@ let
|
||||
"''${symlinks[@]}"
|
||||
"''${auto_mounts[@]}"
|
||||
${extraEnvString}
|
||||
${initStr}/bin/${name}-init ${initArgs}
|
||||
${sandboxInitScript}/bin/${sandboxInitScriptName}
|
||||
)
|
||||
exec "''${cmd[@]}"
|
||||
exec "''${cmd[@]}" $@
|
||||
'';
|
||||
bin = writeShellScriptBin name (bwrapCmd { initArgs = ''"$@"''; });
|
||||
desktopItem = makeDesktopItem (desktopFileArgs // {
|
||||
exec = "${bin}/bin/${name}";
|
||||
});
|
||||
copyIntoSandboxString = lib.concatStrings (map (x: "cp -Lr ${package}/${x} $out/${x}\n") copyIntoSandbox);
|
||||
in stdenv.mkDerivation {
|
||||
pname = "${name}-sandboxed";
|
||||
version = version;
|
||||
pname = name;
|
||||
version = "1.0.0";
|
||||
|
||||
unpackPhase = ":";
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
|
||||
installPhase = let
|
||||
desktopFilePhase = let
|
||||
desktopFile = makeDesktopItem (desktopFileAttributes // {
|
||||
exec = "${sandboxScript}/bin/${sandboxScriptName}";
|
||||
});
|
||||
in ''
|
||||
cp -r ${desktopFile}/share/applications $out/share
|
||||
'';
|
||||
copyIntoSandboxPhase = let
|
||||
attrs = builtins.attrNames copyIntoSandbox;
|
||||
cps = map (x: "cp -Lr ${x} $out/${copyIntoSandbox."${x}"}\n") attrs;
|
||||
in lib.concatStrings cps;
|
||||
in ''
|
||||
mkdir -p $out/bin
|
||||
ln -s ${bin}/bin/${name} $out/bin/${name}
|
||||
'' + lib.strings.optionalString (!(builtins.isNull desktopFileArgs)) ''
|
||||
mkdir -p $out/share/
|
||||
cp -r ${desktopItem}/share/applications $out/share
|
||||
'' + lib.strings.optionalString (!(builtins.isNull copyIntoSandbox)) copyIntoSandboxString;
|
||||
ln -s ${sandboxScript}/bin/${sandboxScriptName} $out/bin/${launchScriptName}
|
||||
|
||||
|
||||
# Generate the desktop file, if enabled
|
||||
${lib.optionalString enableDesktopFile "mkdir -p $out/share"}
|
||||
${lib.optionalString enableDesktopFile preDesktopFilePhase}
|
||||
${lib.optionalString enableDesktopFile desktopFilePhase}
|
||||
|
||||
# Copy extra files if they are specified
|
||||
${lib.optionalString (copyIntoSandbox != {}) copyIntoSandboxPhase}
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user