From fc8e1745c01be9fca7ae511ffdd292b1ca22a3d5 Mon Sep 17 00:00:00 2001 From: Florian Jacob <projects+git@florianjacob.de> Date: Tue, 13 Nov 2018 10:13:23 +0100 Subject: [PATCH 1/4] nixos/etc: Make symlinks relative instead of absolute so that the links can be followed if the NixOS installation is not mounted as filesystem root. In particular, this makes /etc/os-release adhere to the standard: https://www.freedesktop.org/software/systemd/man/os-release.html Fixes #28833. --- nixos/doc/manual/release-notes/rl-1903.xml | 8 ++++++++ nixos/lib/make-system-tarball.sh | 2 +- nixos/modules/system/etc/make-etc.sh | 15 ++++++++++----- nixos/modules/system/etc/setup-etc.pl | 12 ++++++++++-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml index 7ccbf65dd46a..3e42294a5f87 100644 --- a/nixos/doc/manual/release-notes/rl-1903.xml +++ b/nixos/doc/manual/release-notes/rl-1903.xml @@ -457,6 +457,14 @@ use <literal>nixos-rebuild boot; reboot</literal>. </para> </listitem> + <listitem> + <para> + Symlinks in <filename>/etc</filename> are now relative instead of absolute, + so that the links can be followed if the NixOS installation is not mounted as filesystem root. + In particular, this makes <filename>/etc/os-release</filename> adhere to + <link xlink:href="https://www.freedesktop.org/software/systemd/man/os-release.html">the standard</link>. + </para> + </listitem> <listitem> <para> Flat volumes are now disabled by default in <literal>hardware.pulseaudio</literal>. diff --git a/nixos/lib/make-system-tarball.sh b/nixos/lib/make-system-tarball.sh index 1a0017a1799a..6bce8fb0eea5 100644 --- a/nixos/lib/make-system-tarball.sh +++ b/nixos/lib/make-system-tarball.sh @@ -40,7 +40,7 @@ for ((n = 0; n < ${#objects[*]}; n++)); do symlink=${symlinks[$n]} if test "$symlink" != "none"; then mkdir -p $(dirname ./$symlink) - ln -s $object ./$symlink + ln -s --relative ./$object ./$symlink fi done diff --git a/nixos/modules/system/etc/make-etc.sh b/nixos/modules/system/etc/make-etc.sh index 1ca4c3046f0e..9c0520e92fc2 100644 --- a/nixos/modules/system/etc/make-etc.sh +++ b/nixos/modules/system/etc/make-etc.sh @@ -10,6 +10,11 @@ users_=($users) groups_=($groups) set +f +# Create relative symlinks, so that the links can be followed if +# the NixOS installation is not mounted as filesystem root. +# Absolute symlinks violate the os-release format +# at https://www.freedesktop.org/software/systemd/man/os-release.html +# and break e.g. systemd-nspawn and os-prober. for ((i = 0; i < ${#targets_[@]}; i++)); do source="${sources_[$i]}" target="${targets_[$i]}" @@ -19,14 +24,14 @@ for ((i = 0; i < ${#targets_[@]}; i++)); do # If the source name contains '*', perform globbing. mkdir -p $out/etc/$target for fn in $source; do - ln -s "$fn" $out/etc/$target/ + ln -s --relative "$fn" $out/etc/$target/ done else - + mkdir -p $out/etc/$(dirname $target) if ! [ -e $out/etc/$target ]; then - ln -s $source $out/etc/$target + ln -s --relative $source $out/etc/$target else echo "duplicate entry $target -> $source" if test "$(readlink $out/etc/$target)" != "$source"; then @@ -34,13 +39,13 @@ for ((i = 0; i < ${#targets_[@]}; i++)); do exit 1 fi fi - + if test "${modes_[$i]}" != symlink; then echo "${modes_[$i]}" > $out/etc/$target.mode echo "${users_[$i]}" > $out/etc/$target.uid echo "${groups_[$i]}" > $out/etc/$target.gid fi - + fi done diff --git a/nixos/modules/system/etc/setup-etc.pl b/nixos/modules/system/etc/setup-etc.pl index eed20065087f..6cbf0e17793d 100644 --- a/nixos/modules/system/etc/setup-etc.pl +++ b/nixos/modules/system/etc/setup-etc.pl @@ -4,6 +4,7 @@ use File::Copy; use File::Path; use File::Basename; use File::Slurp; +use File::Spec; my $etc = $ARGV[0] or die; my $static = "/etc/static"; @@ -12,7 +13,13 @@ sub atomicSymlink { my ($source, $target) = @_; my $tmp = "$target.tmp"; unlink $tmp; - symlink $source, $tmp or return 0; + # Create relative symlinks, so that the links can be followed if + # the NixOS installation is not mounted as filesystem root. + # Absolute symlinks violate the os-release format + # at https://www.freedesktop.org/software/systemd/man/os-release.html + # and break e.g. systemd-nspawn and os-prober. + my $rel = File::Spec->abs2rel($source, dirname $target); + symlink $rel, $tmp or return 0; rename $tmp, $target or return 0; return 1; } @@ -30,7 +37,8 @@ sub isStatic { if (-l $path) { my $target = readlink $path; - return substr($target, 0, length "/etc/static/") eq "/etc/static/"; + my $rel = File::Spec->abs2rel("/etc/static", dirname $path); + return substr($target, 0, length $rel) eq $rel; } if (-d $path) { From f47bfce584b81ba84aa78617d1bede441cfff570 Mon Sep 17 00:00:00 2001 From: danbst <abcz2.uprola@gmail.com> Date: Wed, 23 Jan 2019 22:19:50 +0200 Subject: [PATCH 2/4] make back /etc/static absolute symlink --- nixos/doc/manual/release-notes/rl-1903.xml | 14 +++++++---- nixos/modules/system/etc/setup-etc.pl | 27 ++++++++++++++-------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml index 3e42294a5f87..0a51e5b1a936 100644 --- a/nixos/doc/manual/release-notes/rl-1903.xml +++ b/nixos/doc/manual/release-notes/rl-1903.xml @@ -459,10 +459,16 @@ </listitem> <listitem> <para> - Symlinks in <filename>/etc</filename> are now relative instead of absolute, - so that the links can be followed if the NixOS installation is not mounted as filesystem root. - In particular, this makes <filename>/etc/os-release</filename> adhere to - <link xlink:href="https://www.freedesktop.org/software/systemd/man/os-release.html">the standard</link>. + Symlinks in <filename>/etc</filename> (except <filename>/etc/static</filename>) + are now relative instead of absolute. This makes possible to examine + NixOS container's <filename>/etc</filename> directory from host system + (previously it pointed to host <filename>/etc</filename> when viewed from host, + and to container <filename>/etc</filename> when viewed from container chroot). + </para> + <para> + This also makes <filename>/etc/os-release</filename> adhere to + <link xlink:href="https://www.freedesktop.org/software/systemd/man/os-release.html">the standard</link> + for NixOS containers. </para> </listitem> <listitem> diff --git a/nixos/modules/system/etc/setup-etc.pl b/nixos/modules/system/etc/setup-etc.pl index 6cbf0e17793d..82ef49a2a27e 100644 --- a/nixos/modules/system/etc/setup-etc.pl +++ b/nixos/modules/system/etc/setup-etc.pl @@ -13,18 +13,26 @@ sub atomicSymlink { my ($source, $target) = @_; my $tmp = "$target.tmp"; unlink $tmp; - # Create relative symlinks, so that the links can be followed if - # the NixOS installation is not mounted as filesystem root. - # Absolute symlinks violate the os-release format - # at https://www.freedesktop.org/software/systemd/man/os-release.html - # and break e.g. systemd-nspawn and os-prober. + symlink $source, $tmp or return 0; + rename $tmp, $target or return 0; + return 1; +} + +# Create relative symlinks, so that the links can be followed if +# the NixOS installation is not mounted as filesystem root. +# Absolute symlinks violate the os-release format +# at https://www.freedesktop.org/software/systemd/man/os-release.html +# and break e.g. systemd-nspawn and os-prober. +sub atomicRelativeSymlink { + my ($source, $target) = @_; + my $tmp = "$target.tmp"; + unlink $tmp; my $rel = File::Spec->abs2rel($source, dirname $target); symlink $rel, $tmp or return 0; rename $tmp, $target or return 0; return 1; } - # Atomically update /etc/static to point at the etc files of the # current configuration. atomicSymlink $etc, $static or die; @@ -37,8 +45,7 @@ sub isStatic { if (-l $path) { my $target = readlink $path; - my $rel = File::Spec->abs2rel("/etc/static", dirname $path); - return substr($target, 0, length $rel) eq $rel; + return substr($target, 0, length "/etc/static/") eq "/etc/static/"; } if (-d $path) { @@ -111,7 +118,7 @@ sub link { if (-e "$_.mode") { my $mode = read_file("$_.mode"); chomp $mode; if ($mode eq "direct-symlink") { - atomicSymlink readlink("$static/$fn"), $target or warn; + atomicRelativeSymlink readlink("$static/$fn"), $target or warn; } else { my $uid = read_file("$_.uid"); chomp $uid; my $gid = read_file("$_.gid"); chomp $gid; @@ -125,7 +132,7 @@ sub link { push @copied, $fn; print CLEAN "$fn\n"; } elsif (-l "$_") { - atomicSymlink "$static/$fn", $target or warn; + atomicRelativeSymlink "$static/$fn", $target or warn; } } From fd807c68c0f6c85fc74b532f4bca21e38049a635 Mon Sep 17 00:00:00 2001 From: danbst <abcz2.uprola@gmail.com> Date: Thu, 31 Jan 2019 10:04:03 +0200 Subject: [PATCH 3/4] this is not related to this PR --- nixos/lib/make-system-tarball.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/lib/make-system-tarball.sh b/nixos/lib/make-system-tarball.sh index 6bce8fb0eea5..80b1db3f4640 100644 --- a/nixos/lib/make-system-tarball.sh +++ b/nixos/lib/make-system-tarball.sh @@ -40,7 +40,7 @@ for ((n = 0; n < ${#objects[*]}; n++)); do symlink=${symlinks[$n]} if test "$symlink" != "none"; then mkdir -p $(dirname ./$symlink) - ln -s --relative ./$object ./$symlink + ln -s ./$object ./$symlink fi done From 3ae5420c9da797a4d57ea3e14e51be5920375dbb Mon Sep 17 00:00:00 2001 From: danbst <abcz2.uprola@gmail.com> Date: Thu, 31 Jan 2019 10:05:56 +0200 Subject: [PATCH 4/4] :facepalm: --- nixos/lib/make-system-tarball.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/lib/make-system-tarball.sh b/nixos/lib/make-system-tarball.sh index 80b1db3f4640..1a0017a1799a 100644 --- a/nixos/lib/make-system-tarball.sh +++ b/nixos/lib/make-system-tarball.sh @@ -40,7 +40,7 @@ for ((n = 0; n < ${#objects[*]}; n++)); do symlink=${symlinks[$n]} if test "$symlink" != "none"; then mkdir -p $(dirname ./$symlink) - ln -s ./$object ./$symlink + ln -s $object ./$symlink fi done