forked from mirrors/nixpkgs
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.
This commit is contained in:
parent
72af71d626
commit
7c480ad896
|
@ -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
|
||||
'';
|
||||
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue