mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-16 14:54:29 +01:00
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
2 changed files with 32 additions and 11 deletions
|
@ -132,7 +132,7 @@ in
|
||||||
''
|
''
|
||||||
# Set up the statically computed bits of /etc.
|
# Set up the statically computed bits of /etc.
|
||||||
echo "setting up /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::Copy;
|
||||||
use File::Path;
|
use File::Path;
|
||||||
use File::Basename;
|
use File::Basename;
|
||||||
|
use File::Slurp;
|
||||||
|
|
||||||
my $etc = $ARGV[0] or die;
|
my $etc = $ARGV[0] or die;
|
||||||
my $static = "/etc/static";
|
my $static = "/etc/static";
|
||||||
|
@ -46,35 +47,55 @@ sub cleanup {
|
||||||
find(\&cleanup, "/etc");
|
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
|
# For every file in the etc tree, create a corresponding symlink in
|
||||||
# /etc to /etc/static. The indirection through /etc/static is to make
|
# /etc to /etc/static. The indirection through /etc/static is to make
|
||||||
# switching to a new configuration somewhat more atomic.
|
# switching to a new configuration somewhat more atomic.
|
||||||
|
my %created;
|
||||||
|
my @copied;
|
||||||
|
|
||||||
sub link {
|
sub link {
|
||||||
my $fn = substr $File::Find::name, length($etc) + 1 or next;
|
my $fn = substr $File::Find::name, length($etc) + 1 or next;
|
||||||
my $target = "/etc/$fn";
|
my $target = "/etc/$fn";
|
||||||
File::Path::make_path(dirname $target);
|
File::Path::make_path(dirname $target);
|
||||||
|
$created{$fn} = 1;
|
||||||
if (-e "$_.mode") {
|
if (-e "$_.mode") {
|
||||||
open MODE, "<$_.mode";
|
my $mode = read_file("$_.mode"); chomp $mode;
|
||||||
my $mode = <MODE>; chomp $mode;
|
|
||||||
close MODE;
|
|
||||||
if ($mode eq "direct-symlink") {
|
if ($mode eq "direct-symlink") {
|
||||||
atomicSymlink readlink("$static/$fn"), $target or warn;
|
atomicSymlink readlink("$static/$fn"), $target or warn;
|
||||||
} else {
|
} else {
|
||||||
open UID, "<$_.uid";
|
my $uid = read_file("$_.uid"); chomp $uid;
|
||||||
my $uid = <UID>; chomp $uid;
|
my $gid = read_file("$_.gid"); chomp $gid;
|
||||||
close UID;
|
|
||||||
open GID, "<$_.gid";
|
|
||||||
my $gid = <GID>; chomp $gid;
|
|
||||||
close GID;
|
|
||||||
|
|
||||||
copy "$static/$fn", "$target.tmp" or warn;
|
copy "$static/$fn", "$target.tmp" or warn;
|
||||||
chown int($uid), int($gid), "$target.tmp" or warn;
|
chown int($uid), int($gid), "$target.tmp" or warn;
|
||||||
chmod oct($mode), "$target.tmp" or warn;
|
chmod oct($mode), "$target.tmp" or warn;
|
||||||
rename "$target.tmp", $target or warn;
|
rename "$target.tmp", $target or warn;
|
||||||
}
|
}
|
||||||
|
push @copied, $fn;
|
||||||
|
print CLEAN "$fn\n";
|
||||||
} elsif (-l "$_") {
|
} elsif (-l "$_") {
|
||||||
atomicSymlink "$static/$fn", $target or warn;
|
atomicSymlink "$static/$fn", $target or warn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
find(\&link, $etc);
|
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