From cb6a139286d13adc65ade8c1ac24ae1cc4210cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sat, 25 Jul 2026 17:28:27 -0300 Subject: [PATCH] fix(grub2): anchor the netboot protocol validation regex noderes.netboot is parsed as grub2- and validated with /^http|tftp$/, which reads as (^http)|(tftp$) and so also accepts values such as https, httpx and xtftp. A value that passes but is not exactly "http" then falls through to set root=$grub2protocol,$serverip, which drops site.httpport, so the mistake surfaces as a confusing grub2 failure at boot instead of the "Invalid netboot method" error this check exists to give. grub2-https cannot work in any case, since only "insmod http" is emitted. Supported values are unchanged: grub2, grub2-http and grub2-tftp. --- xCAT-server/lib/xcat/plugins/grub2.pm | 2 +- xCAT-test/unit/grub2_netboot_protocol.t | 35 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 xCAT-test/unit/grub2_netboot_protocol.t diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index cbe57965c..88a693069 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -224,7 +224,7 @@ sub setstate { $grub2protocol = $1; } - unless ($grub2protocol =~ /^http|tftp$/) { + unless ($grub2protocol =~ /^(http|tftp)$/) { close($pcfg); return (1, "Invalid netboot method, please check noderes.netboot for $node"); } diff --git a/xCAT-test/unit/grub2_netboot_protocol.t b/xCAT-test/unit/grub2_netboot_protocol.t new file mode 100644 index 000000000..0c401977c --- /dev/null +++ b/xCAT-test/unit/grub2_netboot_protocol.t @@ -0,0 +1,35 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; + +my $grub2_path = defined $ENV{XCATROOT} ? "$ENV{XCATROOT}/lib/perl/xCAT_plugin/grub2.pm" : ''; +$grub2_path = "xCAT-server/lib/xcat/plugins/grub2.pm" + unless -f $grub2_path; + +plan skip_all => "grub2.pm not found" unless -f $grub2_path; + +my $grub2 = do { local $/; open my $fh, '<', $grub2_path or die $!; <$fh> }; + +# pull the real validation pattern out of the plugin so this tests the shipped +# regex rather than a copy of it +my ($pattern) = $grub2 =~ m{unless \(\$grub2protocol =~ (/[^/]+/[a-z]*)\)}; +ok($pattern, 'found the netboot protocol validation regex in grub2.pm'); + +my $accepts = eval "sub { my \$v = shift; return scalar(\$v =~ $pattern) }"; +ok($accepts, 'validation regex compiles'); + +# noderes.netboot is documented as grub2, grub2-http and grub2-tftp, so the +# protocol taken from grub2- may only ever be http or tftp +ok($accepts->('http'), 'grub2-http is accepted'); +ok($accepts->('tftp'), 'grub2-tftp is accepted'); + +# an unanchored alternation, /^http|tftp$/, reads as (^http)|(tftp$) and lets +# these through; they then skip the httpport branch and drop the port +ok(!$accepts->('https'), 'grub2-https is rejected rather than silently dropping site.httpport'); +ok(!$accepts->('httpx'), 'a protocol merely starting with http is rejected'); +ok(!$accepts->('xtftp'), 'a protocol merely ending with tftp is rejected'); +ok(!$accepts->('ftp'), 'an unsupported protocol is rejected'); +ok(!$accepts->(''), 'an empty protocol is rejected'); + +done_testing();