2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-07-31 18:19:40 +00:00

fix(statelite): reject invalid NFS root options early

This commit is contained in:
Vinícius Ferrão
2026-07-17 20:36:51 -03:00
parent 24e2c98957
commit 68a4855c7f
4 changed files with 90 additions and 7 deletions
+28 -6
View File
@@ -2415,13 +2415,12 @@ sub getplatform {
return $platform;
}
# Build the dracut root=nfs parameter while preserving statelite's read-only
# root filesystem contract.
sub build_statelite_nfsroot_parameter {
shift if @_ && defined($_[0]) && $_[0] eq __PACKAGE__;
my ($server, $rootdir, $additional_options) = @_;
# Parse statelite NFS root options once so command-time validation and the
# dracut root=nfs renderer enforce the same rules.
sub _parse_statelite_nfsroot_options {
my ($additional_options) = @_;
my @mount_options = ('ro');
my @mount_options;
if (defined($additional_options) && $additional_options ne '') {
foreach my $option (split(/,/, $additional_options, -1)) {
if ($option eq '' || $option =~ /\s/) {
@@ -2438,6 +2437,29 @@ sub build_statelite_nfsroot_parameter {
}
}
return (\@mount_options, undef);
}
# Return an error message when statelite NFS root options violate the
# read-only root filesystem contract.
sub validate_statelite_nfsroot_options {
shift if @_ && defined($_[0]) && $_[0] eq __PACKAGE__;
my ($additional_options) = @_;
my ($mount_options, $error) = _parse_statelite_nfsroot_options($additional_options);
return $error;
}
# Build the dracut root=nfs parameter while preserving statelite's read-only
# root filesystem contract.
sub build_statelite_nfsroot_parameter {
shift if @_ && defined($_[0]) && $_[0] eq __PACKAGE__;
my ($server, $rootdir, $additional_options) = @_;
my ($additional_mount_options, $error) = _parse_statelite_nfsroot_options($additional_options);
return (undef, $error) if $error;
my @mount_options = ('ro', @{$additional_mount_options});
return ('root=nfs:' . $server . ':' . $rootdir . ':' . join(',', @mount_options), undef);
}
@@ -369,6 +369,19 @@ sub parse_attr_for_osimage {
return 0;
}
sub validate_osimage_nfsrootopts {
my $attr_hash = shift;
return 0 unless exists($attr_hash->{nfsrootopts});
my $validation_error = xCAT::SvrUtils->validate_statelite_nfsroot_options($attr_hash->{nfsrootopts});
return 0 unless $validation_error;
my $rsp;
$rsp->{data}->[0] = $validation_error;
xCAT::MsgUtils->message("E", $rsp, $::callback);
return 1;
}
#----------------------------------------------------------------------------
=head3 processArgs
@@ -1886,6 +1899,13 @@ sub defmk
next;
}
if (($type eq 'osimage') && validate_osimage_nfsrootopts($::FINALATTRS{$obj}))
{
$error = 1;
delete $::FINALATTRS{$obj};
next;
}
if ($object_exists && $::opt_f)
{
# remove the old object after the replacement definition is known valid
@@ -2531,6 +2551,13 @@ sub defch
$isDefined = 1;
}
if (($type eq 'osimage') && !$::opt_m && validate_osimage_nfsrootopts($::FINALATTRS{$obj}))
{
$error = 1;
delete($::FINALATTRS{$obj});
next;
}
if ($type eq 'network')
{
my $isInvalid = 0;
+26 -1
View File
@@ -34,6 +34,32 @@ cmd:rmdef -t node testnode
check:rc==0
end
start:chdef_osimage_nfsrootopts_validation
description:Reject invalid statelite NFS root options before provisioning without changing the osimage
label:mn_only,ci_test,db,statelite,nfsrootopts
cmd:rmdef -t node -o xcatnfsoptscinode >/dev/null 2>&1; rmdef -t osimage -o xcatnfsoptsciimage >/dev/null 2>&1; rm -rf /tmp/xcat-nfsrootopts-ci-root /tftpboot/xcat/osimage/xcatnfsoptsciimage; rm -f /tftpboot/xcat/xnba/nodes/xcatnfsoptscinode*
cmd:mkdir -p /tmp/xcat-nfsrootopts-ci-root; touch /tmp/xcat-nfsrootopts-ci-root/kernel /tmp/xcat-nfsrootopts-ci-root/initrd-statelite.gz
check:rc==0
cmd:mkdef -t osimage -o xcatnfsoptsciimage imagetype=linux provmethod=statelite profile=compute osname=Linux osvers=rhels6.99 osarch=x86_64 rootfstype=nfs rootimgdir=/tmp/xcat-nfsrootopts-ci-root nfsrootopts=noac
check:rc==0
cmd:mkdef -t node -o xcatnfsoptscinode groups=all arch=x86_64 netboot=xnba os=rhels6.99 profile=compute ip=192.0.2.100 mac=02:00:00:00:00:01
check:rc==0
cmd:chdef -t osimage -o xcatnfsoptsciimage nfsrootopts=rw
check:rc!=0
check:output=~nfsrootopts cannot contain 'rw'; statelite NFS roots are always read-only
cmd:lsdef -t osimage -o xcatnfsoptsciimage -i nfsrootopts
check:rc==0
check:output=~nfsrootopts=noac
check:output!~nfsrootopts=rw
cmd:nodeset xcatnfsoptscinode osimage=xcatnfsoptsciimage
check:rc==0
check:output!~nfsrootopts
cmd:grep 'root=nfs:.*:ro,noac' /tftpboot/xcat/xnba/nodes/xcatnfsoptscinode
check:rc==0
cmd:rmdef -t node -o xcatnfsoptscinode; rmdef -t osimage -o xcatnfsoptsciimage; rm -rf /tmp/xcat-nfsrootopts-ci-root /tftpboot/xcat/osimage/xcatnfsoptsciimage; rm -f /tftpboot/xcat/xnba/nodes/xcatnfsoptscinode*
check:rc==0
end
start:chdef_t_network
description:chdef -t network
label:mn_only,ci_test,db
@@ -324,4 +350,3 @@ cmd:rmdef -t network -o aaaaa_not_exist
check:rc==0
cmd:rm -rf /tmp/bbbbb_not_exist.def
end
+9
View File
@@ -38,8 +38,17 @@ foreach my $invalid ('rw', 'RW', 'noac,rw', 'defaults', 'noac, actimeo=0', 'noac
($parameter, $error) = build_nfsroot($invalid);
is($parameter, undef, "invalid option list '$invalid' is rejected");
like($error, qr/^nfsrootopts /, "invalid option list '$invalid' reports the attribute name");
like(
xCAT::SvrUtils->validate_statelite_nfsroot_options($invalid),
qr/^nfsrootopts /,
"command-time validation rejects '$invalid'"
);
}
is(xCAT::SvrUtils->validate_statelite_nfsroot_options(undef), undef, 'command-time validation accepts an unset value');
is(xCAT::SvrUtils->validate_statelite_nfsroot_options(''), undef, 'command-time validation accepts an empty value');
is(xCAT::SvrUtils->validate_statelite_nfsroot_options('noac,actimeo=0'), undef, 'command-time validation accepts valid options');
ok(
scalar(grep { $_ eq 'nfsrootopts' } @{ $xCAT::Schema::tabspec{osimage}->{cols} }),
'osimage table includes nfsrootopts'