mirror of
https://github.com/xcat2/xcat-dep.git
synced 2026-09-30 14:55:17 +00:00
Merge pull request #74 from VersatusHPC/fix/riscv64-net-dns-key-record
fix(xcat-dep): riscv64 ships a Net::DNS without the KEY record
This commit is contained in:
@@ -69,6 +69,7 @@ jobs:
|
||||
prove -v t/goconserver_cross_build.t
|
||||
prove -v t/ipxe_xcat_payload.t
|
||||
prove -v t/mockbuild-all.t
|
||||
prove -v t/net_dns_rr_types.t
|
||||
prove -v t/repo-lock-race.t
|
||||
prove -v t/nfslock.t
|
||||
prove -v -It/lib t/genesis_openembedded_release.t
|
||||
|
||||
@@ -489,10 +489,14 @@ Deliberately not built for riscv64:
|
||||
Test::XML) are EPEL-only as well, so it can neither be built nor installed without EPEL;
|
||||
xCAT uses it for HP blade and VirtualBox support only.
|
||||
|
||||
Known differences from the EPEL-fed x86_64 repo: perl-Net-DNS is the 0.80 release of
|
||||
`perl-Net-DNS/Net-DNS.spec`, built pure-perl (`--noxs`) as noarch, where EPEL 10 ships
|
||||
1.47 -- its spec BuildRequires perl(Net::LibIDN2), which is EPEL-only too. A newer,
|
||||
XS-free perl-Net-DNS without that BuildRequires is a follow-up. The riscv64 goconserver
|
||||
perl-Net-DNS is built from `perl-Net-DNS/Net-DNS.spec` at 1.57. xCAT needs the KEY record,
|
||||
which release 0.80 left to the separate Net::DNS::SEC distribution. 1.57 is newer than the
|
||||
1.47 that EPEL 10 ships, because 1.56 and 1.57 fix CVE-2026-64193, CVE-2026-64194 and an
|
||||
unbounded recursion on TSIG. This spec
|
||||
does not take the EPEL-only perl(Net::LibIDN2) BuildRequires of the EPEL package:
|
||||
Net::DNS treats Net::LibIDN2 as optional and uses it for internationalised names only.
|
||||
|
||||
Known difference from the EPEL-fed x86_64 repo: the riscv64 goconserver
|
||||
binaries are stripped by the Go linker (`-ldflags "-s -w"`, cross build only) because the
|
||||
host's brp-strip cannot strip a riscv64 ELF.
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ perl-Crypt-Rijndael=1.13
|
||||
perl-Digest-SHA1=2.13
|
||||
perl-Expect=1.35
|
||||
perl-Mail-Sender=0.903
|
||||
perl-Net-DNS=0.80
|
||||
perl-Net-DNS=1.57
|
||||
perl-Net-IP=1.26
|
||||
perl-Path-Class=0.37
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
How to build the perl-Net-DNS
|
||||
|
||||
1. cp the Net-DNS-0.80.tar.gz to the rpmbuild/SOURCES/
|
||||
1. cp the Net-DNS-1.57.tar.gz to the rpmbuild/SOURCES/
|
||||
2. cp the Net-DNS.spec to the rpmbuild/SPECS/
|
||||
3. cd rpmbuild/SPECS/
|
||||
4. rpmbuild -bb Net-DNS.spec (The default buildarch in Net-DNS.spec is x86_64, needs to modify buildarch if the build arch is not x86_64)
|
||||
4. rpmbuild -bb Net-DNS.spec (Net::DNS is pure perl, so the rpm is noarch and one
|
||||
build serves every architecture.)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
# - Net::DNS -
|
||||
# This spec file was automatically generated by cpan2rpm [ver: 2.028]
|
||||
# The following arguments were used:
|
||||
# ./Net-DNS-0.80.tar.gz
|
||||
# ./Net-DNS-1.57.tar.gz
|
||||
# For more information on cpan2rpm please visit: http://perl.arix.com/
|
||||
#
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
name: perl-Net-DNS
|
||||
summary: Net-DNS - Perl DNS resolver module
|
||||
version: 0.80
|
||||
release: 2
|
||||
version: 1.57
|
||||
release: 1
|
||||
vendor: Olaf Kolkman <olaf@net-dns.org>
|
||||
packager: Arix International <cpan2rpm@arix.com>
|
||||
license: Artistic
|
||||
@@ -23,7 +23,7 @@ url: http://www.cpan.org
|
||||
buildroot: %{_tmppath}/%{name}-%{version}-%(id -u -n)
|
||||
buildarch: noarch
|
||||
prefix: %(echo %{_prefix})
|
||||
source: Net-DNS-0.80.tar.gz
|
||||
source: Net-DNS-1.57.tar.gz
|
||||
|
||||
# cpan2rpm specs carry no BuildRequires; an EL10 buildroot has neither perl nor make, and
|
||||
# perl-generators is what makes rpm compute the perl(...) Requires.
|
||||
@@ -34,9 +34,15 @@ BuildRequires: perl(ExtUtils::MakeMaker)
|
||||
BuildRequires: perl(Digest::HMAC)
|
||||
BuildRequires: perl(Digest::MD5)
|
||||
BuildRequires: perl(Digest::SHA)
|
||||
BuildRequires: perl(IO::Socket::IP)
|
||||
BuildRequires: perl(MIME::Base64)
|
||||
BuildRequires: perl(Test::More)
|
||||
|
||||
# The perl dependency generator reads "use base OS_CONF" in Net::DNS::Resolver::Base as a module
|
||||
# name. OS_CONF is a constant that names the platform resolver class at run time, so no package
|
||||
# provides perl(OS_CONF) and the generated dependency stops dnf from installing the rpm.
|
||||
%global __requires_exclude ^perl\\(OS_CONF\\)$
|
||||
|
||||
%description
|
||||
Net::DNS is a collection of Perl modules that act as a Domain Name System
|
||||
(DNS) resolver. It allows the programmer to perform DNS queries that are
|
||||
@@ -61,8 +67,9 @@ grep -rsl '^#!.*perl' . |
|
||||
grep -v '.bak$' |xargs --no-run-if-empty \
|
||||
%__perl -MExtUtils::MakeMaker -e 'MY->fixin(@ARGV)'
|
||||
CFLAGS="$RPM_OPT_FLAGS"
|
||||
# --noxs: pure-perl Net::DNS (no compiled dn_expand), so one noarch rpm serves every arch
|
||||
%{__perl} Makefile.PL --noxs `%{__perl} -MExtUtils::MakeMaker -e ' print qq|PREFIX=%{buildroot}%{_prefix}| if \$ExtUtils::MakeMaker::VERSION =~ /5\.9[1-6]|6\.0[0-5]/ '`
|
||||
# Net::DNS is pure perl from 1.01 on, so one noarch rpm serves every arch. The mock chroot has
|
||||
# no network: --noonline-tests keeps the resolver tests from waiting for one.
|
||||
%{__perl} Makefile.PL --noonline-tests `%{__perl} -MExtUtils::MakeMaker -e ' print qq|PREFIX=%{buildroot}%{_prefix}| if \$ExtUtils::MakeMaker::VERSION =~ /5\.9[1-6]|6\.0[0-5]/ '`
|
||||
%{__make}
|
||||
%if %maketest
|
||||
%{__make} test
|
||||
@@ -99,7 +106,7 @@ find %{buildroot}%{_prefix} \
|
||||
|
||||
%{__perl} -MFile::Find -le '
|
||||
find({ wanted => \&wanted, no_chdir => 1}, "%{buildroot}");
|
||||
print "%doc Changes README TODO contrib demo";
|
||||
print "%doc Changes LICENSE README contrib demo";
|
||||
for my $x (sort @dirs, @files) {
|
||||
push @ret, $x unless indirs($x);
|
||||
}
|
||||
@@ -139,6 +146,19 @@ find %{buildroot}%{_prefix} \
|
||||
%defattr(-,root,root)
|
||||
|
||||
%changelog
|
||||
* Tue Sep 29 2026 xCAT build - 1.57-1
|
||||
- Net::DNS 1.57. 1.47 carries CVE-2026-64193 (code injection via EDNS
|
||||
EXTENDED-ERROR) and CVE-2026-64194 (deep compression pointer chains),
|
||||
fixed in 1.56, and unbounded recursion on a misplaced TSIG, fixed in 1.57.
|
||||
|
||||
* Sat Sep 05 2026 xCAT build - 1.47-1
|
||||
- Net::DNS 1.47. Release 0.80 leaves the DNSSEC records to Net::DNS::SEC, so
|
||||
Net::DNS::RR->new("<key>. IN KEY ...") dies and xCAT makedns fails. 1.47 is
|
||||
also the release EPEL 10 ships, so every architecture now gets the same one.
|
||||
- Makefile.PL of 1.47 rejects --noxs (the module carries no XS); pass
|
||||
--noonline-tests instead, because the mock chroot has no network.
|
||||
- BuildRequires perl(IO::Socket::IP), which Makefile.PL needs to configure.
|
||||
|
||||
* Thu Aug 20 2026 xCAT build - 0.80-2
|
||||
- Build the pure-perl module (--noxs) as noarch instead of an XS x86_64 rpm.
|
||||
- BuildRequires for an EL10 buildroot (make, perl-interpreter, perl-generators,
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/perl
|
||||
# The xCAT ddns plugin signs a DDNS update with a key record that it builds itself:
|
||||
# Net::DNS::RR->new("<keyname>. IN KEY 512 3 <algorithm> <secret>")
|
||||
# Net::DNS 0.80 leaves the DNSSEC records, KEY included, to the separate Net::DNS::SEC
|
||||
# distribution, so that call dies with "zone file representation not defined for KEY" and
|
||||
# makedns returns non-zero. The x86_64 and ppc64le repositories take Net::DNS from EPEL and
|
||||
# never showed the gap; riscv64 has no EPEL and builds this one, so only that architecture
|
||||
# shipped a Net::DNS without KEY.
|
||||
#
|
||||
# The test drives the Net::DNS that the shipped source tarball contains. It does not read the
|
||||
# module text: it extracts the tarball, puts its lib first on @INC, loads Net::DNS::RR from
|
||||
# there, and constructs the records xCAT constructs.
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More;
|
||||
use FindBin qw($RealBin);
|
||||
use lib "$RealBin/..", "$RealBin/../lib";
|
||||
use File::Temp qw(tempdir);
|
||||
use Archive::Tar;
|
||||
use version;
|
||||
use MockBuildUtils qw(read_manifest version_matches);
|
||||
use XCAT::BuildUtils qw(read_lines);
|
||||
|
||||
# The records xCAT builds, and the class Net::DNS must return for each. The numbers are the
|
||||
# algorithm codes of xCAT::DHCP::OmapiPolicy (157 hmac-md5, 163 hmac-sha256, 165 hmac-sha512).
|
||||
my $SECRET = 'c2VjcmV0';
|
||||
my @RECORDS = (
|
||||
{ rr => "xcat_key. IN KEY 512 3 157 $SECRET", type => 'KEY' },
|
||||
{ rr => "xcat_key. IN KEY 512 3 163 $SECRET", type => 'KEY' },
|
||||
{ rr => "xcat_key. IN KEY 512 3 165 $SECRET", type => 'KEY' },
|
||||
);
|
||||
|
||||
my $root = "$RealBin/..";
|
||||
|
||||
# The spec is the artifact here: it names the version built and the tarball it is built from.
|
||||
# read_lines dies when the spec is gone.
|
||||
my @spec = read_lines("$root/perl-Net-DNS/Net-DNS.spec");
|
||||
my ($version) = map { /^version:\s*(\S+)/i ? $1 : () } @spec;
|
||||
my ($source) = map { /^source:\s*(\S+)/i ? $1 : () } @spec;
|
||||
die "the Net::DNS spec declares no version and source; this test covers nothing\n"
|
||||
unless $version && $source;
|
||||
|
||||
# Net::DNS moved the DNSSEC records, KEY included, into the core distribution at release 1.01.
|
||||
# Below that release the KEY record lives in the separate Net::DNS::SEC distribution, which
|
||||
# xcat-dep does not build.
|
||||
my $KEY_FLOOR = '1.01';
|
||||
|
||||
# Net::DNS pads the minor field (0.80, 1.01, 1.47), so the decimal form of version.pm orders
|
||||
# the releases correctly.
|
||||
sub at_least_floor { return version->parse($_[0]) >= version->parse($KEY_FLOOR) ? 1 : 0 }
|
||||
|
||||
ok(at_least_floor($version),
|
||||
"the spec builds Net::DNS $KEY_FLOOR or newer ($version), so KEY is in the core distribution");
|
||||
|
||||
# Every target whose manifest section lists perl-Net-DNS builds it from this one spec, so the
|
||||
# records must work for all of them. A target that takes Net::DNS from EPEL is not listed.
|
||||
my %manifest = read_manifest("$root/packages-manifest.conf");
|
||||
my @targets = grep { exists $manifest{$_}{'perl-Net-DNS'} } sort keys %manifest;
|
||||
die 'no manifest target builds perl-Net-DNS; this test covers nothing' unless @targets;
|
||||
|
||||
# The pin is the second place the version is written down, and mockbuild-all.pl fails the run
|
||||
# when the built rpm does not match it. A pin below $KEY_FLOOR puts a Net::DNS without KEY back
|
||||
# into the repositories a service node reads, which have no EPEL copy to outrank it. An operator
|
||||
# pin (">= 0.80") accepts such a build too, so only an exact version is allowed here.
|
||||
for my $target (@targets) {
|
||||
my $pin = $manifest{$target}{'perl-Net-DNS'};
|
||||
my $exact = $pin =~ /\A\d+(?:\.\d+)+\z/ ? 1 : 0;
|
||||
ok($exact, "[$target] the perl-Net-DNS pin ($pin) names one exact version");
|
||||
ok($exact && at_least_floor($pin),
|
||||
"[$target] the perl-Net-DNS pin ($pin) is $KEY_FLOOR or newer");
|
||||
ok(version_matches($version, $pin),
|
||||
"[$target] the perl-Net-DNS pin ($pin) accepts the version the spec builds ($version)");
|
||||
}
|
||||
|
||||
my $tarball = "$root/perl-Net-DNS/$source";
|
||||
die "$tarball is missing, so the spec cannot build" unless -f $tarball;
|
||||
|
||||
# The tarball, the spec and the Buildnote name one release. A second tarball beside the spec is a
|
||||
# release that nothing builds, and a Buildnote that names it sends a manual build to the wrong one.
|
||||
my @tarballs = map { s{.*/}{}r } glob("$root/perl-Net-DNS/Net-DNS-*.tar.gz");
|
||||
is_deeply(\@tarballs, [$source], "perl-Net-DNS/ holds only the tarball the spec builds ($source)");
|
||||
my @buildnote = read_lines("$root/perl-Net-DNS/Buildnote");
|
||||
my @named = map { /(Net-DNS-[\d.]+\.tar\.gz)/ ? $1 : () } @buildnote;
|
||||
is_deeply(\@named, [$source], "the Buildnote names the tarball the spec builds ($source)");
|
||||
|
||||
my $tmp = tempdir(CLEANUP => 1);
|
||||
{
|
||||
my $tar = Archive::Tar->new;
|
||||
$tar->read($tarball) or die "Cannot read $tarball: " . Archive::Tar->error;
|
||||
$tar->setcwd($tmp);
|
||||
$tar->extract or die "Cannot extract $tarball: " . Archive::Tar->error;
|
||||
}
|
||||
my ($libdir) = grep { -d } glob("$tmp/*/lib");
|
||||
die "$tarball holds no lib/ directory" unless defined $libdir;
|
||||
|
||||
# The extracted copy goes first on @INC, so it, and not a Net::DNS installed on the build host,
|
||||
# answers the calls. The test checks which file each module came from.
|
||||
unshift @INC, $libdir;
|
||||
require Net::DNS::RR;
|
||||
|
||||
my $loaded = $INC{'Net/DNS/RR.pm'} // '(nothing)';
|
||||
is(index($loaded, $tmp), 0, 'Net::DNS::RR is loaded from the shipped tarball, not from the host')
|
||||
or diag("loaded: $loaded");
|
||||
|
||||
for my $want (@RECORDS) {
|
||||
my $rr = eval { Net::DNS::RR->new($want->{rr}) };
|
||||
ok($rr, "Net::DNS builds '$want->{rr}'") or diag($@);
|
||||
next unless $rr;
|
||||
is($rr->type, $want->{type}, "... as a $want->{type} record");
|
||||
is(ref($rr), "Net::DNS::RR::$want->{type}", "... of class Net::DNS::RR::$want->{type}");
|
||||
is($rr->key, $SECRET, '... carrying the key material given to it');
|
||||
}
|
||||
|
||||
my $key_module = $INC{'Net/DNS/RR/KEY.pm'} // '(nothing)';
|
||||
is(index($key_module, $tmp), 0, 'the KEY record class also comes from the shipped tarball')
|
||||
or diag("loaded: $key_module");
|
||||
|
||||
# CVE-2026-64194: a reply whose owner name is a long chain of compression pointers makes the
|
||||
# decoder recurse once per pointer. Net::DNS 1.56 stops the chain; 1.47 decodes all of it.
|
||||
# The reply below holds a NULL record whose rdata is 200 pointers, each to the one before it,
|
||||
# and an A record whose owner name points at the last one.
|
||||
{
|
||||
my $reply = pack('n6', 1, 0x8100, 1, 2, 0, 0) . "\x01a\x00" . pack('nn', 1, 1);
|
||||
my $rdata_at = length($reply) + 12;
|
||||
my ($chain, $prev) = ('', 12);
|
||||
for (1 .. 200) {
|
||||
my $here = $rdata_at + length $chain;
|
||||
$chain .= pack 'n', 0xC000 | $prev;
|
||||
$prev = $here;
|
||||
}
|
||||
$reply .= pack('nnnNn', 0xC00C, 10, 1, 0, length $chain) . $chain;
|
||||
$reply .= pack('nnnNn', 0xC000 | $prev, 1, 1, 0, 4) . "\x7f\0\0\1";
|
||||
|
||||
require Net::DNS::Packet;
|
||||
local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /^Deep recursion/ };
|
||||
# Packet->new reports a decode error in $@ and returns, as the resolver expects.
|
||||
Net::DNS::Packet->new(\$reply);
|
||||
like($@, qr/deep compression recursion/,
|
||||
'Net::DNS rejects a reply that chains 200 compression pointers (CVE-2026-64194)');
|
||||
}
|
||||
|
||||
# rt.cpan.org #181125, fixed in Net::DNS 1.57: a reply with a TSIG record in the answer section,
|
||||
# followed by another record, makes the re-encode of that reply recurse without bound. 1.56 and
|
||||
# 1.47 recurse. The wrapper stops the recursion at 20 levels and records that it did: Net::DNS
|
||||
# catches the die inside the TSIG encoder, so the re-encode itself still returns.
|
||||
{
|
||||
my $reply = pack('n6', 1, 0x8100, 1, 2, 0, 0) . "\x07example\x00" . pack('nn', 1, 1);
|
||||
my $rdata = "\x0bhmac-sha256\x00" . pack('nNn nnnn', 0, 0, 300, 0, 1, 0, 0);
|
||||
$reply .= "\x03key\x00" . pack('nnNn', 250, 255, 0, length $rdata) . $rdata;
|
||||
$reply .= "\x00" . pack('nnNn', 1, 1, 0, 4) . "\x7f\0\0\1";
|
||||
|
||||
my $encode = \&Net::DNS::Packet::encode;
|
||||
my ($depth, $stopped) = (0, 0);
|
||||
no warnings 'redefine';
|
||||
local *Net::DNS::Packet::encode = sub {
|
||||
if (++$depth > 20) {
|
||||
$stopped = 1;
|
||||
die "Net::DNS::Packet::encode recursed more than 20 levels deep\n";
|
||||
}
|
||||
my $wire = eval { $encode->(@_) };
|
||||
my $error = $@;
|
||||
$depth--;
|
||||
die $error if $error;
|
||||
return $wire;
|
||||
};
|
||||
local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /misplaced or corrupt TSIG/ };
|
||||
my $packet = Net::DNS::Packet->new(\$reply);
|
||||
ok($packet, 'Net::DNS decodes a reply with a misplaced TSIG record') or diag($@);
|
||||
my $data = $packet && eval { $packet->data };
|
||||
ok(defined $data, 'Net::DNS re-encodes that reply') or diag($@);
|
||||
ok(!$stopped, 'the re-encode does not recurse without bound (rt.cpan.org #181125)');
|
||||
}
|
||||
|
||||
done_testing;
|
||||
Reference in New Issue
Block a user