summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-07-25 12:48:21 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-07-25 14:29:08 +0200
commit7c480ad89695c1309cc2ed5d07c166722476cd8c (patch)
treefb37df38f42a5a24bcf48d50f92f20ef9e0a4046 /nixos
parent72af71d626d2e82f2db397a06a820da51c30bb0a (diff)
downloadnixlib-7c480ad89695c1309cc2ed5d07c166722476cd8c.tar
nixlib-7c480ad89695c1309cc2ed5d07c166722476cd8c.tar.gz
nixlib-7c480ad89695c1309cc2ed5d07c166722476cd8c.tar.bz2
nixlib-7c480ad89695c1309cc2ed5d07c166722476cd8c.tar.lz
nixlib-7c480ad89695c1309cc2ed5d07c166722476cd8c.tar.xz
nixlib-7c480ad89695c1309cc2ed5d07c166722476cd8c.tar.zst
nixlib-7c480ad89695c1309cc2ed5d07c166722476cd8c.zip
setup-etc.pl: Keep track of copied files
We now track copied files in /etc/.clean. This is important, because
otherwise files that are removed from environment.etc will not
actually be removed from the file system. In particular, changing
users.extraUsers.<user>.openssh.authorizedKeys.keys to an empty list
would not cause /etc/ssh/authorized_keys.d/<user> to be removed, which
was a security issue.
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/system/etc/etc.nix2
-rw-r--r--nixos/modules/system/etc/setup-etc.pl41
2 files changed, 32 insertions, 11 deletions
diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix
index 22d55a9e246c..b57b03bcf962 100644
--- a/nixos/modules/system/etc/etc.nix
+++ b/nixos/modules/system/etc/etc.nix
@@ -132,7 +132,7 @@ in
       ''
         # Set up the statically computed bits of /etc.
         echo "setting up /etc..."
-        ${pkgs.perl}/bin/perl ${./setup-etc.pl} ${etc}/etc
+        ${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl ${./setup-etc.pl} ${etc}/etc
       '';
 
   };
diff --git a/nixos/modules/system/etc/setup-etc.pl b/nixos/modules/system/etc/setup-etc.pl
index 8ba9a370b27a..d7e15eccefcd 100644
--- a/nixos/modules/system/etc/setup-etc.pl
+++ b/nixos/modules/system/etc/setup-etc.pl
@@ -3,6 +3,7 @@ use File::Find;
 use File::Copy;
 use File::Path;
 use File::Basename;
+use File::Slurp;
 
 my $etc = $ARGV[0] or die;
 my $static = "/etc/static";
@@ -46,35 +47,55 @@ sub cleanup {
 find(\&cleanup, "/etc");
 
 
+# Use /etc/.clean to keep track of copied files.
+my @oldCopied = read_file("/etc/.clean", chomp => 1, err_mode => 'quiet');
+open CLEAN, ">>/etc/.clean";
+
+
 # For every file in the etc tree, create a corresponding symlink in
 # /etc to /etc/static.  The indirection through /etc/static is to make
 # switching to a new configuration somewhat more atomic.
+my %created;
+my @copied;
+
 sub link {
     my $fn = substr $File::Find::name, length($etc) + 1 or next;
     my $target = "/etc/$fn";
     File::Path::make_path(dirname $target);
+    $created{$fn} = 1;
     if (-e "$_.mode") {
-        open MODE, "<$_.mode";
-        my $mode = <MODE>; chomp $mode;
-        close MODE;
+        my $mode = read_file("$_.mode"); chomp $mode;
         if ($mode eq "direct-symlink") {
             atomicSymlink readlink("$static/$fn"), $target or warn;
         } else {
-            open UID, "<$_.uid";
-            my $uid = <UID>; chomp $uid;
-            close UID;
-            open GID, "<$_.gid";
-            my $gid = <GID>; chomp $gid;
-            close GID;
-
+            my $uid = read_file("$_.uid"); chomp $uid;
+            my $gid = read_file("$_.gid"); chomp $gid;
             copy "$static/$fn", "$target.tmp" or warn;
             chown int($uid), int($gid), "$target.tmp" or warn;
             chmod oct($mode), "$target.tmp" or warn;
             rename "$target.tmp", $target or warn;
         }
+        push @copied, $fn;
+        print CLEAN "$fn\n";
     } elsif (-l "$_") {
         atomicSymlink "$static/$fn", $target or warn;
     }
 }
 
 find(\&link, $etc);
+
+
+# Delete files that were copied in a previous version but not in the
+# current.
+foreach my $fn (@oldCopied) {
+    if (!defined $created{$fn}) {
+        $fn = "/etc/$fn";
+        print STDERR "removing obsolete file ‘$fn’...\n";
+        unlink "$fn";
+    }
+}
+
+
+# Rewrite /etc/.clean.
+close CLEAN;
+write_file("/etc/.clean", map { "$_\n" } @copied);