Version in base suite: 2.038-1 Base version: libsocket-perl_2.038-1 Target version: libsocket-perl_2.038-1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libs/libsocket-perl/libsocket-perl_2.038-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libs/libsocket-perl/libsocket-perl_2.038-1+deb13u1.dsc changelog | 12 ++ patches/CVE-2026-12087-test.patch | 62 ++++++++++++++ patches/CVE-2026-12087.patch | 164 ++++++++++++++++++++++++++++++++++++++ patches/series | 2 4 files changed, 240 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpibyjoiay/libsocket-perl_2.038-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpibyjoiay/libsocket-perl_2.038-1+deb13u1.dsc: no acceptable signature found diff -Nru libsocket-perl-2.038/debian/changelog libsocket-perl-2.038/debian/changelog --- libsocket-perl-2.038/debian/changelog 2024-04-19 14:42:09.000000000 +0000 +++ libsocket-perl-2.038/debian/changelog 2026-08-31 13:46:55.000000000 +0000 @@ -1,3 +1,15 @@ +libsocket-perl (2.038-1+deb13u1) trixie; urgency=medium + + [ Kentaro Hayashi ] + * Backport patch to fix CVE-2026-12087 + (out-of-bounds heap read in pack_ip_mreq_source()). + - Added CVE-2026-12087.patch + - Added CVE-2026-12087-test.patch for testing + + Closes: #1146063 + + -- gregor herrmann Mon, 31 Aug 2026 15:46:55 +0200 + libsocket-perl (2.038-1) unstable; urgency=medium * Import upstream version 2.038. diff -Nru libsocket-perl-2.038/debian/patches/CVE-2026-12087-test.patch libsocket-perl-2.038/debian/patches/CVE-2026-12087-test.patch --- libsocket-perl-2.038/debian/patches/CVE-2026-12087-test.patch 1970-01-01 00:00:00.000000000 +0000 +++ libsocket-perl-2.038/debian/patches/CVE-2026-12087-test.patch 2026-08-31 13:46:55.000000000 +0000 @@ -0,0 +1,62 @@ +From: Kentaro Hayashi +Date: Mon, 17 Aug 2026 11:28:23 +0000 +Subject: Add regression test for CVE-2026-12087 + +Description: Add a regression test for the pack_ip_mreq_source() fix + pack_ip_mreq_source() validated the length of $source against a stale + STRLEN len left over from $multiaddr, so a $source shorter than an + in_addr passed validation and the unconditional 4 byte Copy() into + imr_sourceaddr read past the end of its buffer, leaking adjacent heap + memory into the returned string. + . + t/cve-2026-12087.t calls pack_ip_mreq_source() with a 1 byte $source and + asserts that it croaks. The test fails without CVE-2026-12087.patch and + passes with it; the rest of the test suite passes either way, so this is + the only coverage of the issue. + . + Kept separate from CVE-2026-12087.patch so that patch stays identical to + the referenced upstream commit. +Forwarded: no +Bug-Debian: https://bugs.debian.org/1146063 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-12087 +--- + MANIFEST | 1 + + t/cve-2026-12087.t | 17 +++++++++++++++++ + 2 files changed, 18 insertions(+) + create mode 100644 t/cve-2026-12087.t + +diff --git a/MANIFEST b/MANIFEST +index 77ee9f3..a96516e 100644 +--- a/MANIFEST ++++ b/MANIFEST +@@ -8,6 +8,7 @@ MANIFEST This list of files + MANIFEST.SKIP + Socket.pm + Socket.xs ++t/cve-2026-12087.t + t/getaddrinfo.t + t/getnameinfo.t + t/ip_mreq.t +diff --git a/t/cve-2026-12087.t b/t/cve-2026-12087.t +new file mode 100644 +index 0000000..823fe74 +--- /dev/null ++++ b/t/cve-2026-12087.t +@@ -0,0 +1,17 @@ ++use strict; ++use warnings; ++use Test::More; ++ ++use Socket qw( INADDR_ANY pack_ip_mreq_source ); ++ ++# CVE-2026-12087: pack_ip_mreq_source() checked the length of $source against a ++# stale len left over from $multiaddr, so a short $source passed validation and ++# the 4 byte Copy() into imr_sourceaddr read past the end of its buffer. ++ ++plan skip_all => "No pack_ip_mreq_source" ++ unless defined eval { pack_ip_mreq_source "\xe0\0\0\2", "\x0a\0\0\1", INADDR_ANY }; ++ ++plan tests => 1; ++ ++eval { pack_ip_mreq_source "\xe0\0\0\2", "\x0a", INADDR_ANY }; ++like( $@, qr/Bad arg length/, 'pack_ip_mreq_source rejects short source' ); diff -Nru libsocket-perl-2.038/debian/patches/CVE-2026-12087.patch libsocket-perl-2.038/debian/patches/CVE-2026-12087.patch --- libsocket-perl-2.038/debian/patches/CVE-2026-12087.patch 1970-01-01 00:00:00.000000000 +0000 +++ libsocket-perl-2.038/debian/patches/CVE-2026-12087.patch 2026-08-31 13:46:55.000000000 +0000 @@ -0,0 +1,164 @@ +From: Kentaro Hayashi +Date: Mon, 17 Aug 2026 19:41:41 +0900 +Subject: Backport CVE-2026-12087 patch + +Origin: https://github.com/Perl/perl5/commit/de19a0b0ad1900fef976c5c1400bd8f11ec6c6cb +Forwarded: not-needed +From: "Paul \"LeoNerd\" Evans" + + From de19a0b0ad1900fef976c5c1400bd8f11ec6c6cb Mon Sep 17 00:00:00 2001 + Date: Mon, 4 May 2026 16:12:49 +0100 + Subject: [PATCH] cpan/Socket - Update to version 2.041 + + 2.041 2026-03-26 + [CHANGES] + * Modernise Pod documentation formatting + + [BUGFIXES] + * Fix reuse of `STRLEN len` variable in pack_ip_mreq_source() + + +Bug-Debian: https://bugs.debian.org/1146063 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-12087 + +--- + Socket.xs | 83 ++++++++++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 56 insertions(+), 27 deletions(-) + +diff --git a/Socket.xs b/Socket.xs +index 1bd52a1..ded347e 100644 +--- a/Socket.xs ++++ b/Socket.xs +@@ -1272,26 +1272,35 @@ pack_ip_mreq(multiaddr, interface=&PL_sv_undef) + struct ip_mreq mreq; + char * multiaddrbytes; + char * interfacebytes; +- STRLEN len; +- if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1)) +- croak("Wide character in %s", "Socket::pack_ip_mreq"); +- multiaddrbytes = SvPVbyte(multiaddr, len); +- if (len != sizeof(mreq.imr_multiaddr)) +- croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, +- "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_multiaddr)); ++ ++ { ++ if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1)) ++ croak("Wide character in %s", "Socket::pack_ip_mreq"); ++ ++ STRLEN len; ++ multiaddrbytes = SvPVbyte(multiaddr, len); ++ if (len != sizeof(mreq.imr_multiaddr)) ++ croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, ++ "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_multiaddr)); ++ } ++ + Zero(&mreq, sizeof(mreq), char); + Copy(multiaddrbytes, &mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr), char); + if(SvOK(interface)) { + if (DO_UTF8(interface) && !sv_utf8_downgrade(interface, 1)) + croak("Wide character in %s", "Socket::pack_ip_mreq"); ++ ++ STRLEN len; + interfacebytes = SvPVbyte(interface, len); + if (len != sizeof(mreq.imr_interface)) + croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, + "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_interface)); ++ + Copy(interfacebytes, &mreq.imr_interface, sizeof(mreq.imr_interface), char); + } + else + mreq.imr_interface.s_addr = INADDR_ANY; ++ + ST(0) = sv_2mortal(newSVpvn((char *)&mreq, sizeof(mreq))); + #else + not_here("pack_ip_mreq"); +@@ -1331,25 +1340,38 @@ pack_ip_mreq_source(multiaddr, source, interface=&PL_sv_undef) + char * multiaddrbytes; + char * sourcebytes; + char * interfacebytes; +- STRLEN len; +- if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1)) +- croak("Wide character in %s", "Socket::pack_ip_mreq_source"); +- multiaddrbytes = SvPVbyte(multiaddr, len); +- if (len != sizeof(mreq.imr_multiaddr)) +- croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, +- "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_multiaddr)); +- if (DO_UTF8(source) && !sv_utf8_downgrade(source, 1)) +- croak("Wide character in %s", "Socket::pack_ip_mreq_source"); +- if (len != sizeof(mreq.imr_sourceaddr)) +- croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, +- "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_sourceaddr)); +- sourcebytes = SvPVbyte(source, len); ++ ++ { ++ if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1)) ++ croak("Wide character in %s", "Socket::pack_ip_mreq_source"); ++ ++ STRLEN len; ++ multiaddrbytes = SvPVbyte(multiaddr, len); ++ if (len != sizeof(mreq.imr_multiaddr)) ++ croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, ++ "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_multiaddr)); ++ } ++ ++ { ++ if (DO_UTF8(source) && !sv_utf8_downgrade(source, 1)) ++ croak("Wide character in %s", "Socket::pack_ip_mreq_source"); ++ ++ STRLEN len; ++ sourcebytes = SvPVbyte(source, len); ++ if (len != sizeof(mreq.imr_sourceaddr)) ++ croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, ++ "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_sourceaddr)); ++ } ++ + Zero(&mreq, sizeof(mreq), char); + Copy(multiaddrbytes, &mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr), char); + Copy(sourcebytes, &mreq.imr_sourceaddr, sizeof(mreq.imr_sourceaddr), char); ++ + if(SvOK(interface)) { + if (DO_UTF8(interface) && !sv_utf8_downgrade(interface, 1)) + croak("Wide character in %s", "Socket::pack_ip_mreq"); ++ ++ STRLEN len; + interfacebytes = SvPVbyte(interface, len); + if (len != sizeof(mreq.imr_interface)) + croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, +@@ -1358,6 +1380,7 @@ pack_ip_mreq_source(multiaddr, source, interface=&PL_sv_undef) + } + else + mreq.imr_interface.s_addr = INADDR_ANY; ++ + ST(0) = sv_2mortal(newSVpvn((char *)&mreq, sizeof(mreq))); + #else + PERL_UNUSED_VAR(multiaddr); +@@ -1398,16 +1421,22 @@ pack_ipv6_mreq(multiaddr, ifindex) + #ifdef HAS_IPV6_MREQ + struct ipv6_mreq mreq; + char * multiaddrbytes; +- STRLEN len; +- if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1)) +- croak("Wide character in %s", "Socket::pack_ipv6_mreq"); +- multiaddrbytes = SvPVbyte(multiaddr, len); +- if (len != sizeof(mreq.ipv6mr_multiaddr)) +- croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, +- "Socket::pack_ipv6_mreq", (UV)len, (UV)sizeof(mreq.ipv6mr_multiaddr)); ++ ++ { ++ if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1)) ++ croak("Wide character in %s", "Socket::pack_ipv6_mreq"); ++ ++ STRLEN len; ++ multiaddrbytes = SvPVbyte(multiaddr, len); ++ if (len != sizeof(mreq.ipv6mr_multiaddr)) ++ croak("Bad arg length %s, length is %" UVuf ", should be %" UVuf, ++ "Socket::pack_ipv6_mreq", (UV)len, (UV)sizeof(mreq.ipv6mr_multiaddr)); ++ } ++ + Zero(&mreq, sizeof(mreq), char); + Copy(multiaddrbytes, &mreq.ipv6mr_multiaddr, sizeof(mreq.ipv6mr_multiaddr), char); + mreq.ipv6mr_interface = ifindex; ++ + ST(0) = sv_2mortal(newSVpvn((char *)&mreq, sizeof(mreq))); + #else + PERL_UNUSED_VAR(multiaddr); diff -Nru libsocket-perl-2.038/debian/patches/series libsocket-perl-2.038/debian/patches/series --- libsocket-perl-2.038/debian/patches/series 2024-04-19 14:42:09.000000000 +0000 +++ libsocket-perl-2.038/debian/patches/series 2026-08-31 13:46:55.000000000 +0000 @@ -1 +1,3 @@ disable-network-tests.patch +CVE-2026-12087.patch +CVE-2026-12087-test.patch