build-fhs-userenv: add extraBindMounts support

Changed files
+33 -18
pkgs
build-support
build-fhs-userenv
+31 -17
pkgs/build-support/build-fhs-userenv/chroot-user.rb
···
#!/usr/bin/env ruby
-
# Bind mounts hierarchy: [from, to (relative)]
+
# Bind mounts hierarchy: from => to (relative)
# If 'to' is nil, path will be the same
-
mounts = [ ['/nix/store', nil],
-
['/dev', nil],
-
['/proc', nil],
-
['/sys', nil],
-
['/etc', 'host-etc'],
-
['/tmp', 'host-tmp'],
-
['/home', nil],
-
['/var', nil],
-
['/run', nil],
-
['/root', nil],
-
]
+
mounts = { '/nix/store' => nil,
+
'/dev' => nil,
+
'/proc' => nil,
+
'/sys' => nil,
+
'/etc' => 'host-etc',
+
'/tmp' => 'host-tmp',
+
'/home' => nil,
+
'/var' => nil,
+
'/run' => nil,
+
'/root' => nil,
+
}
# Propagate environment variables
envvars = [ 'TERM',
···
swdir = Pathname.new ARGV[0]
execp = ARGV.drop 1
+
# Populate extra mounts
+
if not ENV["CHROOTENV_EXTRA_BINDS"].nil?
+
for extra in ENV["CHROOTENV_EXTRA_BINDS"].split(':')
+
paths = extra.split('=')
+
if not paths.empty?
+
if paths.size <= 2
+
mounts[paths[0]] = paths[1]
+
else
+
$stderr.puts "Ignoring invalid entry in CHROOTENV_EXTRA_BINDS: #{extra}"
+
end
+
end
+
end
+
end
+
# Set destination paths for mounts
-
mounts.map! { |x| [x[0], x[1].nil? ? x[0].sub(/^\/*/, '') : x[1]] }
+
mounts = mounts.map { |k, v| [k, v.nil? ? k.sub(/^\/*/, '') : v] }.to_h
# Create temporary directory for root and chdir
root = Dir.mktmpdir 'chrootenv'
···
write_file '/proc/self/gid_map', "#{gid} #{gid} 1"
# Do rbind mounts.
-
mounts.each do |x|
-
to = "#{root}/#{x[1]}"
+
mounts.each do |from, rto|
+
to = "#{root}/#{rto}"
FileUtils.mkdir_p to
-
$mount.call x[0], to, nil, MS_BIND | MS_REC, nil
+
$mount.call from, to, nil, MS_BIND | MS_REC, nil
end
# Chroot!
···
Dir.chdir '/'
# Symlink swdir hierarchy
-
mount_dirs = Set.new mounts.map { |x| Pathname.new x[1] }
+
mount_dirs = Set.new mounts.map { |_, v| Pathname.new v }
link_swdir = lambda do |swdir, prefix|
swdir.find do |path|
rel = prefix.join path.relative_path_from(swdir)
+2 -1
pkgs/build-support/build-fhs-userenv/default.nix
···
-
{ runCommand, writeText, writeScriptBin, stdenv, ruby } : { env, runScript ? "bash" } :
+
{ runCommand, lib, writeText, writeScriptBin, stdenv, ruby } : { env, runScript ? "bash", extraBindMounts ? [] } :
let
name = env.pname;
···
passthru.env =
runCommand "${name}-shell-env" {
shellHook = ''
+
export CHROOTENV_EXTRA_BINDS="${lib.makeSearchPath extraBindMounts}:$CHROOTENV_EXTRA_BINDS"
exec ${chroot-user}/bin/chroot-user ${env} bash -l ${init "bash"} "$(pwd)"
'';
} ''