mirror of
https://github.com/webmin/webmin.git
synced 2026-06-04 20:30:22 +01:00
Fix to harden GRUB manual editor allowlist
This commit is contained in:
@@ -1406,7 +1406,7 @@ if ($grub_dir ne '' && -d $grub_dir && opendir(my $dh, $grub_dir)) {
|
||||
# Hide dotfiles and only expose regular generator/text files.
|
||||
next if ($base =~ /^\./);
|
||||
my $file = "$grub_dir/$base";
|
||||
next if (!-f $file);
|
||||
next if (!&grub2_manual_file_safe($file, $grub_dir, 1));
|
||||
my $type = defined($custom_file) && $file eq $custom_file ? 'custom' :
|
||||
(-x $file || $base =~ /^\d+_/) ? 'grub_script' :
|
||||
'text';
|
||||
@@ -1422,7 +1422,7 @@ if ($bls_dir ne '' && -d $bls_dir && opendir(my $dh, $bls_dir)) {
|
||||
# Disabled rescue files deliberately do not appear in the editor.
|
||||
next if ($base =~ /^\./ || $base !~ /\.conf\z/);
|
||||
my $file = "$bls_dir/$base";
|
||||
next if (!-f $file);
|
||||
next if (!&grub2_manual_file_safe($file, $bls_dir, 1));
|
||||
&add_grub2_manual_file(\@files, \%seen, 'bls_dir', $file,
|
||||
'bls');
|
||||
}
|
||||
@@ -1438,9 +1438,23 @@ sub add_grub2_manual_file
|
||||
{
|
||||
my ($files, $seen, $key, $file, $type) = @_;
|
||||
return if (!defined($file) || $file eq '' || $seen->{$file}++);
|
||||
return if (!&grub2_manual_file_safe($file, undef, 0));
|
||||
push(@$files, { 'key' => $key, 'file' => $file, 'type' => $type });
|
||||
}
|
||||
|
||||
# grub2_manual_file_safe(file, [parent-dir], must-exist?)
|
||||
# Returns true if a path is safe for the manual editor allowlist.
|
||||
sub grub2_manual_file_safe
|
||||
{
|
||||
my ($file, $parent, $must_exist) = @_;
|
||||
return 0 if (!defined($file) || $file eq '');
|
||||
my @st = lstat($file);
|
||||
return $must_exist ? 0 : 1 if (!@st);
|
||||
# Symlinks would be followed by the Webmin write path, so reject them here.
|
||||
return 0 if (-l _ || !-f _);
|
||||
return $parent ? &grub2_path_is_under($file, $parent) : 1;
|
||||
}
|
||||
|
||||
# grub2_manual_file(file)
|
||||
# Returns the manual-edit descriptor for an allowed file path.
|
||||
sub grub2_manual_file
|
||||
|
||||
@@ -677,6 +677,35 @@ ok(grub2_manual_file($os_prober_file), 'grub.d script is manual-edit allowlisted
|
||||
ok(grub2_manual_file($readme_file), 'grub.d regular file is manual-edit allowlisted');
|
||||
ok(grub2_manual_file($bls_entry_file), 'BLS entry is manual-edit allowlisted');
|
||||
ok(!grub2_manual_file("$work/not-allowed"), 'unexpected file is rejected');
|
||||
SKIP: {
|
||||
my $outside_manual = "$work/outside-manual-target";
|
||||
my $manual_link = "$work/grub.d/09_symlink";
|
||||
write_test_file($outside_manual, "outside\n");
|
||||
skip 'symlink unavailable', 5 if (!symlink($outside_manual, $manual_link));
|
||||
ok(!grub2_manual_file($manual_link),
|
||||
'grub.d symlink is not manual-edit allowlisted');
|
||||
is(save_manual_grub_file($manual_link, "#!/bin/sh\nexit 0\n"),
|
||||
$text{'manual_efile'}, 'manual save rejects grub.d symlink');
|
||||
is(slurp_test_file($outside_manual), "outside\n",
|
||||
'manual save does not write through grub.d symlink');
|
||||
|
||||
my $outside_bls = "$work/outside-bls-target";
|
||||
my $bls_link = "$bls_dir/symlink.conf";
|
||||
write_test_file($outside_bls, "title Outside\nlinux /vmlinuz\n");
|
||||
if (!symlink($outside_bls, $bls_link)) {
|
||||
unlink($manual_link);
|
||||
skip 'second symlink unavailable', 2;
|
||||
}
|
||||
ok(!grub2_manual_file($bls_link),
|
||||
'BLS symlink is not manual-edit allowlisted');
|
||||
{
|
||||
local $config{'custom_file'} = $manual_link;
|
||||
ok(!grub2_manual_file($manual_link),
|
||||
'configured custom symlink is not manual-edit allowlisted');
|
||||
}
|
||||
unlink($manual_link);
|
||||
unlink($bls_link);
|
||||
}
|
||||
is(save_manual_grub_file($default_file, $saved), undef,
|
||||
'manual save validates default file');
|
||||
is(save_manual_grub_file($custom_file, "menuentry 'X' { true }\n"), undef,
|
||||
|
||||
Reference in New Issue
Block a user