summary refs log tree commit diff
path: root/pkgs/build-support/build-fhs-userenv-bubblewrap
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-08-04 10:43:07 +0000
committerAlyssa Ross <hi@alyssa.is>2021-08-04 10:43:07 +0000
commit62614cbef7da005c1eda8c9400160f6bcd6546b8 (patch)
treec2630f69080637987b68acb1ee8676d2681fe304 /pkgs/build-support/build-fhs-userenv-bubblewrap
parentd9c82ed3044c72cecf01c6ea042489d30914577c (diff)
parente24069138dfec3ef94f211f1da005bb5395adc11 (diff)
downloadnixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.gz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.bz2
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.lz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.xz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.zst
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.zip
Merge branch 'nixpkgs-update' into master
Diffstat (limited to 'pkgs/build-support/build-fhs-userenv-bubblewrap')
-rw-r--r--pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix134
-rw-r--r--pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix23
2 files changed, 123 insertions, 34 deletions
diff --git a/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix b/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
index c7cfd27d3fa..23718bf636c 100644
--- a/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
+++ b/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
@@ -1,28 +1,43 @@
-{ callPackage, runCommandLocal, writeShellScriptBin, stdenv, coreutils, bubblewrap }:
+{ lib, callPackage, runCommandLocal, writeShellScriptBin, glibc, pkgsi686Linux, coreutils, bubblewrap }:
 
 let buildFHSEnv = callPackage ./env.nix { }; in
 
 args @ {
-  name,
-  runScript ? "bash",
-  extraInstallCommands ? "",
-  meta ? {},
-  passthru ? {},
-  ...
+  name
+, runScript ? "bash"
+, extraInstallCommands ? ""
+, meta ? {}
+, passthru ? {}
+, unshareUser ? true
+, unshareIpc ? true
+, unsharePid ? true
+, unshareNet ? false
+, unshareUts ? true
+, unshareCgroup ? true
+, dieWithParent ? true
+, ...
 }:
 
 with builtins;
 let
+  buildFHSEnv = callPackage ./env.nix { };
+
   env = buildFHSEnv (removeAttrs args [
-    "runScript" "extraInstallCommands" "meta" "passthru"
+    "runScript" "extraInstallCommands" "meta" "passthru" "dieWithParent"
+    "unshareUser" "unshareCgroup" "unshareUts" "unshareNet" "unsharePid" "unshareIpc"
   ]);
 
-  chrootenv = callPackage ./chrootenv {};
-
   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"
@@ -30,6 +45,8 @@ let
       "hosts"
       "resolv.conf"
       "nsswitch.conf"
+      # User profiles
+      "profiles"
       # Sudo & Su
       "login.defs"
       "sudoers"
@@ -45,60 +62,115 @@ let
       # Fonts
       "fonts"
       # ALSA
+      "alsa"
       "asound.conf"
       # SSL
       "ssl/certs"
       "pki"
     ];
-  in concatStringsSep " \\\n  "
+  in 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
+  createLdConfCache = ''
+    cat > /etc/ld.so.conf <<EOF
+    /lib
+    /lib/x86_64-linux-gnu
+    /lib64
+    /usr/lib
+    /usr/lib/x86_64-linux-gnu
+    /usr/lib64
+    /lib/i386-linux-gnu
+    /lib32
+    /usr/lib/i386-linux-gnu
+    /usr/lib32
+    EOF
+    ldconfig &> /dev/null
+  '';
   init = run: writeShellScriptBin "${name}-init" ''
     source /etc/profile
+    ${createLdConfCache}
     exec ${run} "$@"
   '';
 
   bwrapCmd = { initArgs ? "" }: ''
-    blacklist="/nix /dev /proc /etc"
-    ro_mounts=""
+    blacklist=(/nix /dev /proc /etc)
+    ro_mounts=()
+    symlinks=()
     for i in ${env}/*; do
       path="/''${i##*/}"
       if [[ $path == '/etc' ]]; then
-        continue
+        :
+      elif [[ -L $i ]]; then
+        symlinks+=(--symlink "$(${coreutils}/bin/readlink "$i")" "$path")
+        blacklist+=("$path")
+      else
+        ro_mounts+=(--ro-bind "$i" "$path")
+        blacklist+=("$path")
       fi
-      ro_mounts="$ro_mounts --ro-bind $i $path"
-      blacklist="$blacklist $path"
     done
 
     if [[ -d ${env}/etc ]]; then
       for i in ${env}/etc/*; do
         path="/''${i##*/}"
-        ro_mounts="$ro_mounts --ro-bind $i /etc$path"
+        # NOTE: we're binding /etc/fonts and /etc/ssl/certs from the host so we
+        # don't want to override it with a path from the FHS environment.
+        if [[ $path == '/fonts' || $path == '/ssl' ]]; then
+          continue
+        fi
+        ro_mounts+=(--ro-bind "$i" "/etc$path")
       done
     fi
 
-    auto_mounts=""
+    declare -a auto_mounts
     # loop through all directories in the root
     for dir in /*; do
       # if it is a directory and it is not in the blacklist
-      if [[ -d "$dir" ]] && grep -v "$dir" <<< "$blacklist" >/dev/null; then
+      if [[ -d "$dir" ]] && [[ ! "''${blacklist[@]}" =~ "$dir" ]]; then
         # add it to the mount list
-        auto_mounts="$auto_mounts --bind $dir $dir"
+        auto_mounts+=(--bind "$dir" "$dir")
       fi
     done
 
-    exec ${bubblewrap}/bin/bwrap \
-      --dev-bind /dev /dev \
-      --proc /proc \
-      --chdir "$(pwd)" \
-      --unshare-all \
-      --share-net \
-      --die-with-parent \
-      --ro-bind /nix /nix \
-      ${etcBindFlags} \
-      $ro_mounts \
-      $auto_mounts \
+    cmd=(
+      ${bubblewrap}/bin/bwrap
+      --dev-bind /dev /dev
+      --proc /proc
+      --chdir "$(pwd)"
+      ${lib.optionalString unshareUser "--unshare-user"}
+      ${lib.optionalString unshareIpc "--unshare-ipc"}
+      ${lib.optionalString unsharePid "--unshare-pid"}
+      ${lib.optionalString unshareNet "--unshare-net"}
+      ${lib.optionalString unshareUts "--unshare-uts"}
+      ${lib.optionalString unshareCgroup "--unshare-cgroup"}
+      ${lib.optionalString dieWithParent "--die-with-parent"}
+      --ro-bind /nix /nix
+      # Our glibc will look for the cache in its own path in `/nix/store`.
+      # As such, we need a cache to exist there, because pressure-vessel
+      # depends on the existence of an ld cache. However, adding one
+      # globally proved to be a bad idea (see #100655), the solution we
+      # settled on being mounting one via bwrap.
+      # Also, the cache needs to go to both 32 and 64 bit glibcs, for games
+      # of both architectures to work.
+      --tmpfs ${glibc}/etc \
+      --symlink /etc/ld.so.conf ${glibc}/etc/ld.so.conf \
+      --symlink /etc/ld.so.cache ${glibc}/etc/ld.so.cache \
+      --ro-bind ${glibc}/etc/rpc ${glibc}/etc/rpc \
+      --remount-ro ${glibc}/etc \
+      --tmpfs ${pkgsi686Linux.glibc}/etc \
+      --symlink /etc/ld.so.conf ${pkgsi686Linux.glibc}/etc/ld.so.conf \
+      --symlink /etc/ld.so.cache ${pkgsi686Linux.glibc}/etc/ld.so.cache \
+      --ro-bind ${pkgsi686Linux.glibc}/etc/rpc ${pkgsi686Linux.glibc}/etc/rpc \
+      --remount-ro ${pkgsi686Linux.glibc}/etc \
+      ${etcBindFlags}
+      "''${ro_mounts[@]}"
+      "''${symlinks[@]}"
+      "''${auto_mounts[@]}"
       ${init runScript}/bin/${name}-init ${initArgs}
+    )
+    exec "''${cmd[@]}"
   '';
 
   bin = writeShellScriptBin name (bwrapCmd { initArgs = ''"$@"''; });
diff --git a/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix b/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
index 8b2d46c4ae9..b9c719a4c78 100644
--- a/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
+++ b/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
@@ -1,4 +1,4 @@
-{ stdenv, buildEnv, writeText, pkgs, pkgsi686Linux }:
+{ stdenv, lib, buildEnv, writeText, writeShellScriptBin, pkgs, pkgsi686Linux }:
 
 { name, profile ? ""
 , targetPkgs ? pkgs: [], multiPkgs ? pkgs: []
@@ -49,6 +49,9 @@ let
     [ (toString gcc.cc.lib)
     ];
 
+  ldconfig = writeShellScriptBin "ldconfig" ''
+    exec ${pkgs.glibc.bin}/bin/ldconfig -f /etc/ld.so.conf -C /etc/ld.so.cache "$@"
+  '';
   etcProfile = writeText "profile" ''
     export PS1='${name}-chrootenv:\u@\h:\w\$ '
     export LOCALE_ARCHIVE='/usr/lib/locale/locale-archive'
@@ -86,7 +89,8 @@ let
   # Composes a /usr-like directory structure
   staticUsrProfileTarget = buildEnv {
     name = "${name}-usr-target";
-    paths = [ etcPkg ] ++ basePkgs ++ targetPaths;
+    # ldconfig wrapper must come first so it overrides the original ldconfig
+    paths = [ etcPkg ldconfig ] ++ basePkgs ++ targetPaths;
     extraOutputsToInstall = [ "out" "lib" "bin" ] ++ extraOutputsToInstall;
     ignoreCollisions = true;
   };
@@ -132,7 +136,20 @@ let
     mkdir -m0755 usr
     cd usr
     ${setupLibDirs}
-    for i in bin sbin share include; do
+    ${lib.optionalString isMultiBuild ''
+    if [ -d "${staticUsrProfileMulti}/share" ]; then
+      cp -rLf ${staticUsrProfileMulti}/share share
+    fi
+    ''}
+    if [ -d "${staticUsrProfileTarget}/share" ]; then
+      if [ -d share ]; then
+        chmod -R 755 share
+        cp -rLTf ${staticUsrProfileTarget}/share share
+      else
+        cp -rLf ${staticUsrProfileTarget}/share share
+      fi
+    fi
+    for i in bin sbin include; do
       if [ -d "${staticUsrProfileTarget}/$i" ]; then
         cp -rsHf "${staticUsrProfileTarget}/$i" "$i"
       fi