mirror of
https://git.FreeBSD.org/doc.git
synced 2026-06-02 19:35:07 +00:00
Add EN-26:11 and EN-26:12.
Approved by: so
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
# Sort errata notices by year, month and day
|
||||
# $FreeBSD$
|
||||
|
||||
[[notices]]
|
||||
name = "FreeBSD-EN-26:12.freebsd-update"
|
||||
date = "2026-05-01"
|
||||
|
||||
[[notices]]
|
||||
name = "FreeBSD-EN-26:11.dhclient"
|
||||
date = "2026-05-01"
|
||||
|
||||
[[notices]]
|
||||
name = "FreeBSD-EN-26:10.amd64"
|
||||
date = "2026-04-29"
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA512
|
||||
|
||||
=============================================================================
|
||||
FreeBSD-EN-26:11.dhclient Errata Notice
|
||||
The FreeBSD Project
|
||||
|
||||
Topic: dhclient(8) lease validation is too strict
|
||||
|
||||
Category: core
|
||||
Module: dhclient
|
||||
Announced: 2026-05-01
|
||||
Affects: All supported versions of FreeBSD.
|
||||
Corrected: 2026-04-30 21:07:00 UTC (stable/15, 15.0-STABLE)
|
||||
2026-05-01 15:08:46 UTC (releng/15.0, 15.0-RELEASE-p8)
|
||||
2026-04-30 21:07:11 UTC (stable/14, 14.4-STABLE)
|
||||
2026-05-01 15:08:37 UTC (releng/14.4, 14.4-RELEASE-p4)
|
||||
2026-05-01 15:08:30 UTC (releng/14.3, 14.3-RELEASE-p13)
|
||||
2026-04-30 21:07:24 UTC (stable/13, 13.5-STABLE)
|
||||
2026-05-01 15:08:19 UTC (releng/13.5, 13.5-RELEASE-p14)
|
||||
|
||||
For general information regarding FreeBSD Errata Notices and Security
|
||||
Advisories, including descriptions of the fields above, security
|
||||
branches, and the following sections, please visit
|
||||
<URL:https://security.FreeBSD.org/>.
|
||||
|
||||
Note: While FreeBSD 13.5 is end of life (EOL) as of May 1st, 2026, the
|
||||
Security Team has decided to patch this issue as it was identified and a fix
|
||||
was in-flight before the EOL date.
|
||||
|
||||
I. Background
|
||||
|
||||
dhclient(8) is the default IPv4 DHCP client used on FreeBSD. It is
|
||||
responsible for contacting DHCP servers on a network segment and for
|
||||
initialising and configuring network interfaces based on received
|
||||
information.
|
||||
|
||||
When processing a DHCP offer, dhclient passes various parameters provided by
|
||||
the server to dhclient-script(8). DHCP options, as documented in
|
||||
dhcp-options(5), are passed via the environment.
|
||||
|
||||
II. Problem Description
|
||||
|
||||
The patch for FreeBSD-SA-26:15.dhclient introduced some validation of the
|
||||
boot file DHCP option to prevent unescaped values from being written to the
|
||||
stored lease file. This validation is overly strict and rejects Windows
|
||||
paths.
|
||||
|
||||
III. Impact
|
||||
|
||||
The overly strict validation may cause dhclient(8) to reject valid leases.
|
||||
|
||||
IV. Workaround
|
||||
|
||||
No workaround is available. Systems not running dhclient(8) are not
|
||||
affected.
|
||||
|
||||
V. Solution
|
||||
|
||||
Upgrade your system to a supported FreeBSD stable or release / security
|
||||
branch (releng) dated after the correction date.
|
||||
|
||||
Perform one of the following:
|
||||
|
||||
1) To update your system installed from base system packages:
|
||||
|
||||
Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64
|
||||
platforms, which were installed using base system packages, can be updated
|
||||
via the pkg(8) utility:
|
||||
|
||||
# pkg upgrade -r FreeBSD-base
|
||||
|
||||
2) To update your system installed from binary distribution sets:
|
||||
|
||||
Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms,
|
||||
or the i386 platform on FreeBSD 13, which were not installed using base
|
||||
system packages, can be updated via the freebsd-update(8) utility:
|
||||
|
||||
# freebsd-update fetch
|
||||
# freebsd-update install
|
||||
|
||||
3) To update your system via a source code patch:
|
||||
|
||||
The following patches have been verified to apply to the applicable
|
||||
FreeBSD release branches.
|
||||
|
||||
a) Download the relevant patch from the location below, and verify the
|
||||
detached PGP signature using your PGP utility.
|
||||
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:11/dhclient.patch
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:11/dhclient.patch.asc
|
||||
# gpg --verify dhclient.patch.asc
|
||||
|
||||
b) Apply the patch. Execute the following commands as root:
|
||||
|
||||
# cd /usr/src
|
||||
# patch < /path/to/patch
|
||||
|
||||
c) Recompile the operating system using buildworld and installworld as
|
||||
described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>.
|
||||
|
||||
Restart the applicable daemons, or reboot the system.
|
||||
|
||||
VI. Correction details
|
||||
|
||||
This issue is corrected as of the corresponding Git commit hash in the
|
||||
following stable and release branches:
|
||||
|
||||
Branch/path Hash Revision
|
||||
- -------------------------------------------------------------------------
|
||||
stable/15/ 252f603d1704 stable/15-n283453
|
||||
releng/15.0/ dc8762cfb6e2 releng/15.0-n281035
|
||||
stable/14/ 2f9478ad42c4 stable/14-n274094
|
||||
releng/14.4/ dfcb69cdb07e releng/14.4-n273699
|
||||
releng/14.3/ 5bad905eb37f releng/14.3-n271499
|
||||
stable/13/ b1ece85741db stable/13-n259871
|
||||
releng/13.5/ b362b6b6c8f2 releng/13.5-n259221
|
||||
- -------------------------------------------------------------------------
|
||||
|
||||
Run the following command to see which files were modified by a
|
||||
particular commit:
|
||||
|
||||
# git show --stat <commit hash>
|
||||
|
||||
Or visit the following URL, replacing NNNNNN with the hash:
|
||||
|
||||
<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN>
|
||||
|
||||
To determine the commit count in a working tree (for comparison against
|
||||
nNNNNNN in the table above), run:
|
||||
|
||||
# git rev-list --count --first-parent HEAD
|
||||
|
||||
VII. References
|
||||
|
||||
<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=294886>
|
||||
|
||||
The latest revision of this advisory is available at
|
||||
<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:11.dhclient.asc>
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xiAbFIAAAAAABAAO
|
||||
bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvJnEQAJ8ZYWjGt7iYjMkOZiM1
|
||||
I7NLl7RygvIWU25ThAOXlA7zPA7LbS23+nca4QlNdvTVkpcfsCrmxhJYY4ymkZh7
|
||||
QuEVDEp20n02S7362S9kCpmp3NDXQvuCPNt8zRel4ek3u/b8/9KCASL1jN+1eSgR
|
||||
G8ZVWVheRzKgsaYJsDIyX0AjNk41gQk8ASYoWjeIk5F14kFk3ozlfJTrBL2XlOuL
|
||||
J28P47d5lEgU2x04xLSZF9xQrF1I13XZa8pMtogF3aveTXXVzHDJFZIcppu0uQYY
|
||||
tp9uvyQ6NnzNPBXWztVCJ+eRdxS4RLp3Dp3U9/3GrqVuCfG8BO7kE5OhcjO0EPVC
|
||||
lmvXBJLqQnsodEQA0BysAsMxlMcw+n6z0np2DFdFCkyLrPCx3Bm+D/WRLngRcp4s
|
||||
+FBIgoF+ywUXVwLRkVJeCsQJTNzVhneq8rtcfE6LdJoIgW/oOUyNEJTBpgvhXmz6
|
||||
/pmW47cmNY+CFWCXAL/7fLZVX1dYvEpSn+Iqqs8Efr2OFfQqRXZunJXNXnKuMtfT
|
||||
p82Hl////cHObQSqlI95J5yJmdBzOxlpzHTwSLVTD5SfvAcN3PzN3hRhFFqG8lg5
|
||||
HV64Fu1xPqLX1mthTw1Sbng5mTUL+MJ5BN26M+UevYZBi02m5nMUyjWH+D4Bn3RS
|
||||
gajZ9Z16VPgdlPsNPihqsx7k
|
||||
=Ro3y
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -0,0 +1,177 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA512
|
||||
|
||||
=============================================================================
|
||||
FreeBSD-EN-26:12.freebsd-update Errata Notice
|
||||
The FreeBSD Project
|
||||
|
||||
Topic: Source inconsistency between freebsd-update, EN/SAs, and git
|
||||
|
||||
Category: core
|
||||
Module: freebsd-update
|
||||
Announced: 2026-05-01
|
||||
Affects: All supported versions of FreeBSD.
|
||||
Corrected: 2026-05-01 15:08:47 UTC (releng/15.0, 15.0-RELEASE-p8)
|
||||
2026-05-01 15:08:38 UTC (releng/14.4, 14.4-RELEASE-p4)
|
||||
2026-05-01 15:08:31 UTC (releng/14.3, 14.3-RELEASE-p13)
|
||||
2026-05-01 15:08:20 UTC (releng/13.5, 13.5-RELEASE-p14)
|
||||
|
||||
For general information regarding FreeBSD Errata Notices and Security
|
||||
Advisories, including descriptions of the fields above, security
|
||||
branches, and the following sections, please visit
|
||||
<URL:https://security.FreeBSD.org/>.
|
||||
|
||||
Note: While FreeBSD 13.5 is end of life (EOL) as of May 1st, 2026, the
|
||||
Security Team has decided to patch this issue as it was identified and a fix
|
||||
was in-flight before the EOL date.
|
||||
|
||||
I. Background
|
||||
|
||||
The FreeBSD Security Team distributes patches for supported releases via the
|
||||
git version control system, as patches link through errata and advisories,
|
||||
and through the freebsd-update binary update system.
|
||||
|
||||
Both freebsd-update and the errata/advisories do not directly use the
|
||||
authoritative git repo but instead rely on individual patch files.
|
||||
|
||||
II. Problem Description
|
||||
|
||||
Due to the manual nature of patch file development and management, there are
|
||||
instances where either a freebsd-update maintained machine or a patched
|
||||
source tree from errata/advisories have become out of sync with the
|
||||
authoritative git repository.
|
||||
|
||||
Specifically, an earlier version of the patch associated with SA-26:11.amd64
|
||||
was distributed via freebsd-update. The source patch linked in the advisory
|
||||
did match the source in git.
|
||||
|
||||
Additionally, patches distributed via freebsd-update and errata/advisories
|
||||
are occasionally missing test or non-material ancillary files to minimize
|
||||
patch size and improve compatibility across releases, causing an additional
|
||||
source of drift from the authoritative git respository.
|
||||
|
||||
Pkgbase is unaffected as it directly builds from the authoritative git
|
||||
repository.
|
||||
|
||||
III. Impact
|
||||
|
||||
As a result of this drift, the FreeBSD Security Team has changed the
|
||||
freebsd-update build mechanism to retrieve source directly from the
|
||||
authoritative git respository. This has caused a binary update to rectify the
|
||||
SA-26:11.amd64 issue as well as alter a few additional files that have been
|
||||
updated in git but were not distributed via freebsd-update.
|
||||
|
||||
IV. Workaround
|
||||
|
||||
No workaround is available. Systems using pkgbase or building directly from
|
||||
source obtained from the authoritative git repository are unaffected.
|
||||
|
||||
V. Solution
|
||||
|
||||
Upgrade your system to a supported FreeBSD stable or release / security
|
||||
branch (releng) dated after the correction date and reboot the system.
|
||||
|
||||
Perform one of the following:
|
||||
|
||||
1) If your system is installed from base system packages:
|
||||
|
||||
No update is needed as pkgbase is not affected by this issue.
|
||||
|
||||
2) To update your system installed from binary distribution sets:
|
||||
|
||||
Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms,
|
||||
or the i386 platform on FreeBSD 13, which were not installed using base
|
||||
system packages, can be updated via the freebsd-update(8) utility:
|
||||
|
||||
# freebsd-update fetch
|
||||
# freebsd-update install
|
||||
# shutdown -r +10min "Rebooting for a system update"
|
||||
|
||||
3) To update your system via a source code patch:
|
||||
|
||||
The following patches are only intended to be used for source trees have been
|
||||
maintained with patches linked by previous EN/SAs.
|
||||
|
||||
a) Download the relevant patch from the location below, and verify the
|
||||
detached PGP signature using your PGP utility.
|
||||
|
||||
[FreeBSD 15.0]
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-150.patch
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-150.patch.asc
|
||||
# gpg --verify ensa-150.patch.asc
|
||||
|
||||
[FreeBSD 14.4]
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-144.patch
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-144.patch.asc
|
||||
# gpg --verify ensa-144.patch.asc
|
||||
|
||||
[FreeBSD 14.3]
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-143.patch
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-143.patch.asc
|
||||
# gpg --verify ensa-143.patch.asc
|
||||
|
||||
[FreeBSD 13.5]
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-135.patch
|
||||
# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-135.patch.asc
|
||||
# gpg --verify ensa-135.patch.asc
|
||||
|
||||
b) Apply the patch. Execute the following commands as root:
|
||||
|
||||
# cd /usr/src
|
||||
# patch < /path/to/patch
|
||||
|
||||
c) Recompile the operating system using buildworld and installworld as
|
||||
described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>.
|
||||
|
||||
Reboot the system.
|
||||
|
||||
VI. Correction details
|
||||
|
||||
This issue is corrected as of the corresponding Git commit hash in the
|
||||
following stable and release branches:
|
||||
|
||||
Branch/path Hash Revision
|
||||
- -------------------------------------------------------------------------
|
||||
releng/15.0/ 53054229dcb3 releng/15.0-n281036
|
||||
releng/14.4/ 49be56ed6fea releng/14.4-n273700
|
||||
releng/14.3/ 4f4b48e8a547 releng/14.3-n271500
|
||||
releng/13.5/ 2e6399fe39b3 releng/13.5-n259222
|
||||
- -------------------------------------------------------------------------
|
||||
|
||||
Run the following command to see which files were modified by a
|
||||
particular commit:
|
||||
|
||||
# git show --stat <commit hash>
|
||||
|
||||
Or visit the following URL, replacing NNNNNN with the hash:
|
||||
|
||||
<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN>
|
||||
|
||||
To determine the commit count in a working tree (for comparison against
|
||||
nNNNNNN in the table above), run:
|
||||
|
||||
# git rev-list --count --first-parent HEAD
|
||||
|
||||
VII. References
|
||||
|
||||
<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=270166>
|
||||
|
||||
The latest revision of this advisory is available at
|
||||
<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:12.freebsd-update.asc>
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xicbFIAAAAAABAAO
|
||||
bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrv//EP/jc0GG1wu9K9TdzGWn4m
|
||||
F74a1Gstl13HdTilFhNbF+iQtcuEui4QyBNgy2O7XG1kRsbCYQDN32BzbZl+VhmY
|
||||
kBzUO+jRANPQ3J8cReMeyE2sg2jTAqtioKrbMtXqCNB7peC2AekWLSXrWQA99+qO
|
||||
qQ/rWW6zCnYWhsiX4fPfVbxw8PS4jdBriOxeBU7gBAQ8lQmdHW5A1hnW2ZzKWWDF
|
||||
8m6MuyI4yiA+eDGzkHHn8WetWOgZrbbpFa5H7upYmpSX8jcIlivHqW0j+RMpWG9Z
|
||||
UPIcD26dmbw423BNXXxy9SSUWF6fwlNaWzAaPxT9rpVE2kgeP8QbEhPRvTxQ95CJ
|
||||
PwVASKSfJ5tMSzZpxl5Vp3U5OyanvpBoFVIj/2tlsAcRm9ywXiqS4HLS1CY67uwb
|
||||
G7NkMO8oteO0ZPgXS5sLLGnMlfl/tkhG440tH8UKtWMRXzrXP6sLBwuk3v7RQxN0
|
||||
XZHPM4sBA7b8aIi0VKcNR5yby1xDFnI+fdRUT9ILmG8OCijmowFE0fknY78kzmr7
|
||||
HF1CRelNU3Wy5hlt6Q5MAY87E5Piw2TU0QY7AZU6eZeb0qLIFsUwVawDATvsqias
|
||||
C3RJ9OWSwJTCaUNjwCvwX+1miwfjqLCE30ze0qzZ6NcF67qQBc1pIMUg0HCWkS3E
|
||||
rhVyscH7IOUNqCLG9uBCXKL5
|
||||
=TZ6g
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -0,0 +1,112 @@
|
||||
--- sbin/dhclient/dhclient.c.orig
|
||||
+++ sbin/dhclient/dhclient.c
|
||||
@@ -1161,7 +1161,7 @@
|
||||
lease = malloc(sizeof(struct client_lease));
|
||||
|
||||
if (!lease) {
|
||||
- warning("dhcpoffer: no memory to record lease.");
|
||||
+ warning("dhcpoffer: no memory to record lease");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -1211,7 +1211,7 @@
|
||||
|
||||
/* If the server name was filled out, copy it.
|
||||
Do not attempt to validate the server name as a host name.
|
||||
- RFC 2131 merely states that sname is NUL-terminated (which do
|
||||
+ RFC 2131 merely states that sname is NUL-terminated (which we
|
||||
do not assume) and that it is the server's host name. Since
|
||||
the ISC client and server allow arbitrary characters, we do
|
||||
as well. */
|
||||
@@ -1219,39 +1219,72 @@
|
||||
!(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
|
||||
packet->raw->sname[0]) {
|
||||
lease->server_name = malloc(DHCP_SNAME_LEN + 1);
|
||||
- if (!lease->server_name) {
|
||||
- warning("dhcpoffer: no memory for server name.");
|
||||
+ if (lease->server_name == NULL) {
|
||||
+ warning("dhcpoffer: no memory for server name");
|
||||
free_client_lease(lease);
|
||||
return (NULL);
|
||||
}
|
||||
- memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
|
||||
- lease->server_name[DHCP_SNAME_LEN]='\0';
|
||||
- if (strchr(lease->server_name, '"') != NULL ||
|
||||
- strchr(lease->server_name, '\\') != NULL) {
|
||||
- warning("dhcpoffer: server name contains invalid characters.");
|
||||
- free_client_lease(lease);
|
||||
- return (NULL);
|
||||
+ for (i = 0; i < DHCP_SNAME_LEN; i++) {
|
||||
+ if (packet->raw->sname[i] == '\0') {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (packet->raw->sname[i] < ' ' ||
|
||||
+ packet->raw->sname[i] == '"' ||
|
||||
+ packet->raw->sname[i] == '\\') {
|
||||
+ warning("dhcpoffer: server name contains "
|
||||
+ "unsafe characters");
|
||||
+ free(lease->server_name);
|
||||
+ lease->server_name = NULL;
|
||||
+ break;
|
||||
+ }
|
||||
+ lease->server_name[i] = packet->raw->sname[i];
|
||||
+ }
|
||||
+ /* Terminate and zero-pad */
|
||||
+ if (lease->server_name != NULL) {
|
||||
+ while (i < DHCP_SNAME_LEN + 1) {
|
||||
+ lease->server_name[i++] = '\0';
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
- /* Ditto for the filename. */
|
||||
+ /* Ditto for the file name. */
|
||||
if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
|
||||
!(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
|
||||
packet->raw->file[0]) {
|
||||
/* Don't count on the NUL terminator. */
|
||||
lease->filename = malloc(DHCP_FILE_LEN + 1);
|
||||
- if (!lease->filename) {
|
||||
- warning("dhcpoffer: no memory for filename.");
|
||||
+ if (lease->filename == NULL) {
|
||||
+ warning("dhcpoffer: no memory for file name");
|
||||
free_client_lease(lease);
|
||||
return (NULL);
|
||||
}
|
||||
- memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
|
||||
- lease->filename[DHCP_FILE_LEN]='\0';
|
||||
- if (strchr(lease->filename, '"') != NULL ||
|
||||
- strchr(lease->filename, '\\') != NULL) {
|
||||
- warning("dhcpoffer: filename contains invalid characters.");
|
||||
- free_client_lease(lease);
|
||||
- return (NULL);
|
||||
+ for (i = 0; i < DHCP_FILE_LEN; i++) {
|
||||
+ if (packet->raw->file[i] == '\0') {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (packet->raw->file[i] < ' ' ||
|
||||
+ packet->raw->file[i] == '"') {
|
||||
+ warning("dhcpoffer: file name contains "
|
||||
+ "unsafe characters");
|
||||
+ free(lease->filename);
|
||||
+ lease->filename = NULL;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (packet->raw->file[i] == '\\') {
|
||||
+ /*
|
||||
+ * This is common in Windows-centric
|
||||
+ * environments. Instead of rejecting,
|
||||
+ * silently convert to forward slash.
|
||||
+ */
|
||||
+ packet->raw->file[i] = '/';
|
||||
+ }
|
||||
+ lease->filename[i] = packet->raw->file[i];
|
||||
+ }
|
||||
+ /* Terminate and zero-pad */
|
||||
+ if (lease->filename != NULL) {
|
||||
+ while (i < DHCP_FILE_LEN + 1) {
|
||||
+ lease->filename[i++] = '\0';
|
||||
+ }
|
||||
}
|
||||
}
|
||||
return lease;
|
||||
@@ -0,0 +1,17 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xiUbFIAAAAAABAAO
|
||||
bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvP3IP/jxonX89dJSBsH0i12F0
|
||||
dVgVOeCYMf9dhEnd9Oyw/KY6p8OMWkNHg2D3rRR0wDzEf8k7RAVNoD87uKzOHfQk
|
||||
IeKE6n5LubG3WdLbEnWSMScHjvJ7+8+vDbU2brkXdWaBQxqdZRJ/QReRvLvLHR/8
|
||||
2xomS4l3uS1He+xxCPXk5G116zaDfEZWnYL1rHEbBI81Nxnktb/mSNwHLxf41E3A
|
||||
QdGOaPKCbuKKkq98Bo5zaTu9B/68iXq9yDGnPHJoUhZnpCSXA/21PNkUP+G4N1VG
|
||||
6bzCgl7e0tWL048nBv7V8A0cyZ8K0rCSjurlPNF82QxGGUD/Z6qKaclpwuQO/X50
|
||||
t3gzh0nJ1g6/F/FmywVjZEDAUIIpgHkyMGlWdzqlzLZ1jymSRXnZGGJVGU1tpcPF
|
||||
AZC/avfvGAZNrSXVaM5IoduzW7xLzlF4XyJt3aT2GbmegnVmfWD2hgIVzktq/bWj
|
||||
5UfalA/T/+2dusWLtbnUVQrZLppQBe5XfH1uNUONwguV4YDQ0ndP9hGUV5UM40Os
|
||||
RvrMnHGPjszURPWKN01V5GQRoMZkur/vIglOkFPLcKfr6rYRP4yxpJN70E1xV/pK
|
||||
AIjKUxIflDtAUdcgL0uaJHGJX6O8R4eXrl2RjdPv8EGDJcz/Y+zULSDbujCbcLys
|
||||
BT3xt7JyKXIB92PonZo28Xn5
|
||||
=2BEv
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -0,0 +1,56 @@
|
||||
--- tests/sys/netpfil/pf/sctp.py.orig
|
||||
+++ tests/sys/netpfil/pf/sctp.py
|
||||
@@ -448,53 +448,6 @@
|
||||
|
||||
@pytest.mark.require_user("root")
|
||||
@pytest.mark.require_progs(["scapy"])
|
||||
- def test_initiate_tag_check(self):
|
||||
- # Ensure we don't send ABORTs in response to the other end's INIT_ACK
|
||||
- # That'd interfere with our test.
|
||||
- ToolsHelper.print_output("/sbin/sysctl net.inet.sctp.blackhole=2")
|
||||
-
|
||||
- import scapy.all as sp
|
||||
-
|
||||
- packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \
|
||||
- / sp.SCTP(sport=1234, dport=1234) \
|
||||
- / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500)
|
||||
- packet.show()
|
||||
-
|
||||
- r = sp.sr1(packet, timeout=3)
|
||||
- assert r
|
||||
- r.show()
|
||||
- assert r.getlayer(sp.SCTP)
|
||||
- assert r.getlayer(sp.SCTPChunkInitAck)
|
||||
- assert r.getlayer(sp.SCTP).tag == 1
|
||||
-
|
||||
- # Send another INIT with the same initiate tag, expect another init ack
|
||||
- packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \
|
||||
- / sp.SCTP(sport=1234, dport=1234) \
|
||||
- / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500)
|
||||
- packet.show()
|
||||
-
|
||||
- r = sp.sr1(packet, timeout=3)
|
||||
- assert r
|
||||
- r.show()
|
||||
- assert r.getlayer(sp.SCTP)
|
||||
- assert r.getlayer(sp.SCTPChunkInitAck)
|
||||
- assert r.getlayer(sp.SCTP).tag == 1
|
||||
-
|
||||
- # Send an INIT with a different initiate tag, expect another init ack
|
||||
- packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \
|
||||
- / sp.SCTP(sport=1234, dport=1234) \
|
||||
- / sp.SCTPChunkInit(init_tag=42, n_in_streams=1, n_out_streams=1, a_rwnd=1500)
|
||||
- packet.show()
|
||||
-
|
||||
- r = sp.sr1(packet, timeout=3)
|
||||
- assert r
|
||||
- r.show()
|
||||
- assert r.getlayer(sp.SCTP)
|
||||
- assert r.getlayer(sp.SCTPChunkInitAck)
|
||||
- assert r.getlayer(sp.SCTP).tag == 42
|
||||
-
|
||||
- @pytest.mark.require_user("root")
|
||||
- @pytest.mark.require_progs(["scapy"])
|
||||
def test_too_many_add_ip(self):
|
||||
import scapy.all as sp
|
||||
DEPTH=90
|
||||
@@ -0,0 +1,17 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xigbFIAAAAAABAAO
|
||||
bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvKRoQAOoQG727h+K+Ggup1bPR
|
||||
abGWXO72V+ouikfjx34bFYoZkti0/beAnH0/C8KhFCql23kdWVAk576nLz6a1TYe
|
||||
6XAkw+MbsL/TN07xexstUfZzBlO6oZGvOed1fkGsK7FNdN47NvTn5bAaSDOIwyvr
|
||||
c35FsjD2+ojqc+KdlyaNMidSlS58SbKtcZ1OrcJD3VMB3FJZ6D+ko0adCoXgyfPN
|
||||
noaWId+aANmFTksykWsDAgMKEdlyE8d+/dAec9m9qDY6Yza1IgU3bi2jh91lAx/y
|
||||
/n3QRfvdllFh1gJ+YTe0B1SpIimqjBnvGjUNNcDrpgbVrc5Yp9fPiPKSnxSit6eP
|
||||
dcLNNs3o4yLBScG9R5raZ184H64Uv1boD69I1MFEGWi2qkGxlc0hREj5G5v2NOny
|
||||
oGIOzA0yXEb9aXAAH1fP+WV9eADYheCQy3OJqZeJAEOda5actOKFfdoAOpNMNFAm
|
||||
2gUlOZO2hrR6RNJiAAJO0vzusuo66Wx97FPJUez/SoQSHriNY/e+yOnnGWe1Fjp+
|
||||
2EYa/cUcfHTs5nGy+cUXCjYKL0AL7HD7kiEiOoTG2TT438RtcMNLDH29gjPsnY6F
|
||||
nRBF7Sm994wwCKlWW1cmgxyZczpBVByHI8/mAT3i7wEyZsuBij0fkyIJZlHAxJQb
|
||||
XPcrcVNqkzLQzucFwGQ1jczC
|
||||
=Mn9N
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -0,0 +1,487 @@
|
||||
--- lib/libnv/tests/Makefile.orig
|
||||
+++ lib/libnv/tests/Makefile
|
||||
@@ -1,6 +1,15 @@
|
||||
+.include <src.opts.mk>
|
||||
|
||||
ATF_TESTS_C= \
|
||||
nvlist_send_recv_test
|
||||
+
|
||||
+.PATH: ${SRCTOP}/lib/libnv
|
||||
+SRCS.nvlist_send_recv_test= msgio.c nvlist_send_recv_test.c
|
||||
+CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/sys/contrib/libnv
|
||||
+CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/lib/libnv
|
||||
+.if ${MK_ASAN} != "yes"
|
||||
+CFLAGS.nvlist_send_recv_test+=-DNO_ASAN
|
||||
+.endif
|
||||
|
||||
ATF_TESTS_CXX= \
|
||||
cnv_tests \
|
||||
--- lib/libnv/tests/nv_array_tests.cc.orig
|
||||
+++ lib/libnv/tests/nv_array_tests.cc
|
||||
@@ -1,6 +1,5 @@
|
||||
/*-
|
||||
- * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
- * All rights reserved.
|
||||
+ * Copyright (c) 2015-2024 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -28,6 +27,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/nv.h>
|
||||
+#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
@@ -1162,6 +1162,58 @@
|
||||
free(packed);
|
||||
}
|
||||
|
||||
+
|
||||
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array_nonull__pack);
|
||||
+ATF_TEST_CASE_BODY(nvlist_string_array_nonull__pack)
|
||||
+{
|
||||
+ nvlist_t *testnvl, *unpacked;
|
||||
+ const char *somestr[3] = { "a", "b", "XXX" };
|
||||
+ uint8_t *packed, *twopages, *dataptr, *secondpage;
|
||||
+ size_t packed_size, page_size;
|
||||
+ bool found;
|
||||
+
|
||||
+ page_size = sysconf(_SC_PAGESIZE);
|
||||
+ testnvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(testnvl != NULL);
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0);
|
||||
+ nvlist_add_string_array(testnvl, "nvl/string", somestr,
|
||||
+ nitems(somestr));
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0);
|
||||
+
|
||||
+ packed = (uint8_t *)nvlist_pack(testnvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+
|
||||
+ twopages = (uint8_t *)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,
|
||||
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
+ ATF_REQUIRE(twopages != MAP_FAILED);
|
||||
+ dataptr = &twopages[page_size - packed_size];
|
||||
+ secondpage = &twopages[page_size];
|
||||
+
|
||||
+ memset(twopages, 'A', page_size * 2);
|
||||
+
|
||||
+ mprotect(secondpage, page_size, PROT_NONE);
|
||||
+ memcpy(dataptr, packed, packed_size);
|
||||
+
|
||||
+ found = false;
|
||||
+ for (size_t i = 0; i < packed_size - 3; i++) {
|
||||
+ if (dataptr[i] == 'X' && dataptr[i + 1] == 'X' &&
|
||||
+ dataptr[i + 2] == 'X' && dataptr[i + 3] == '\0') {
|
||||
+ dataptr[i + 3] = 'X';
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ ATF_REQUIRE(found == true);
|
||||
+
|
||||
+ unpacked = nvlist_unpack(dataptr, packed_size, 0);
|
||||
+ ATF_REQUIRE(unpacked == NULL);
|
||||
+
|
||||
+ nvlist_destroy(testnvl);
|
||||
+ free(packed);
|
||||
+ munmap(twopages, page_size * 2);
|
||||
+}
|
||||
+
|
||||
+
|
||||
ATF_INIT_TEST_CASES(tp)
|
||||
{
|
||||
|
||||
@@ -1191,5 +1243,7 @@
|
||||
ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__pack)
|
||||
ATF_ADD_TEST_CASE(tp, nvlist_string_array__pack)
|
||||
ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__pack)
|
||||
+
|
||||
+ ATF_ADD_TEST_CASE(tp, nvlist_string_array_nonull__pack)
|
||||
}
|
||||
|
||||
--- lib/libnv/tests/nvlist_send_recv_test.c.orig
|
||||
+++ lib/libnv/tests/nvlist_send_recv_test.c
|
||||
@@ -1,5 +1,8 @@
|
||||
/*-
|
||||
+ * SPDX-License-Identifier: BSD-2-Clause
|
||||
+ *
|
||||
* Copyright (c) 2013 The FreeBSD Foundation
|
||||
+ * Copyright (c) 2024-2026 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
*
|
||||
* This software was developed by Pawel Jakub Dawidek under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
@@ -28,6 +31,8 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
+#include <sys/resource.h>
|
||||
+#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -44,6 +49,9 @@
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
+#include <nv_impl.h>
|
||||
+#include <msgio.h>
|
||||
+
|
||||
#define ALPHABET "abcdefghijklmnopqrstuvwxyz"
|
||||
#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
|
||||
|
||||
@@ -531,6 +539,59 @@
|
||||
nvlist_send_recv__send_nvlist(SOCK_STREAM);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Regression test for fd_wait(): the previous select(2)-based implementation
|
||||
+ * called FD_SET() unconditionally, which is an out-of-bounds stack write when
|
||||
+ * the socket fd is >= FD_SETSIZE. Force the socketpair fds above FD_SETSIZE
|
||||
+ * and verify a full nvlist round-trip still works.
|
||||
+ */
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__highfd);
|
||||
+ATF_TC_BODY(nvlist_send_recv__highfd, tc)
|
||||
+{
|
||||
+ struct rlimit rl;
|
||||
+ nvlist_t *nvl;
|
||||
+ int socks[2], hi_send, hi_recv, status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ hi_send = FD_SETSIZE + 5;
|
||||
+ hi_recv = FD_SETSIZE + 6;
|
||||
+
|
||||
+ rl.rlim_cur = rl.rlim_max = hi_recv + 1;
|
||||
+ if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
|
||||
+ atf_tc_skip("cannot raise RLIMIT_NOFILE: %s", strerror(errno));
|
||||
+
|
||||
+ ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0);
|
||||
+ ATF_REQUIRE(dup2(socks[0], hi_recv) == hi_recv);
|
||||
+ ATF_REQUIRE(dup2(socks[1], hi_send) == hi_send);
|
||||
+ (void)close(socks[0]);
|
||||
+ (void)close(socks[1]);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+ if (pid == 0) {
|
||||
+ /* Child: send. */
|
||||
+ (void)close(hi_recv);
|
||||
+ nvl = nvlist_create(0);
|
||||
+ nvlist_add_string(nvl, "key", "value");
|
||||
+ if (nvlist_send(hi_send, nvl) != 0)
|
||||
+ err(EXIT_FAILURE, "nvlist_send");
|
||||
+ nvlist_destroy(nvl);
|
||||
+ _exit(0);
|
||||
+ }
|
||||
+
|
||||
+ (void)close(hi_send);
|
||||
+ nvl = nvlist_recv(hi_recv, 0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
|
||||
+ ATF_REQUIRE(nvlist_exists_string(nvl, "key"));
|
||||
+ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "key"), "value") == 0);
|
||||
+ nvlist_destroy(nvl);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+ (void)close(hi_recv);
|
||||
+}
|
||||
+
|
||||
ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram);
|
||||
ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc)
|
||||
{
|
||||
@@ -543,15 +604,260 @@
|
||||
nvlist_send_recv__send_closed_fd(SOCK_STREAM);
|
||||
}
|
||||
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc)
|
||||
+{
|
||||
+ nvlist_t *nvl;
|
||||
+ void *packed;
|
||||
+ size_t packed_size;
|
||||
+ struct nvlist_header *header;
|
||||
+ int fd, socks[2], status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+#ifdef NO_ASAN
|
||||
+ atf_tc_skip("This test requires ASAN");
|
||||
+#endif
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ /* Child. */
|
||||
+ fd = socks[0];
|
||||
+ close(socks[1]);
|
||||
+
|
||||
+ nvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_empty(nvl));
|
||||
+
|
||||
+ packed = nvlist_pack(nvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
|
||||
+
|
||||
+ header = (struct nvlist_header *)packed;
|
||||
+ header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
|
||||
+ (ssize_t)sizeof(struct nvlist_header));
|
||||
+
|
||||
+ nvlist_destroy(nvl);
|
||||
+ free(packed);
|
||||
+
|
||||
+ exit(0);
|
||||
+ } else {
|
||||
+ /* Parent */
|
||||
+ fd = socks[1];
|
||||
+ close(socks[0]);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(fd, 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure it has failed on EINVAL, and not on
|
||||
+ * errors returned by malloc or recv.
|
||||
+ */
|
||||
+ ATF_REQUIRE(errno == EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+ close(fd);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_big_endian_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_big_endian_size, tc)
|
||||
+{
|
||||
+ static const unsigned char payload[] = {
|
||||
+ 0x6c, /* magic */
|
||||
+ 0x00, /* version */
|
||||
+ 0x80, /* flags: NV_FLAG_BIG_ENDIAN */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5,
|
||||
+ };
|
||||
+ nvlist_t *nvl;
|
||||
+ int sv[2];
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
+ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)),
|
||||
+ (ssize_t)sizeof(payload));
|
||||
+ ATF_REQUIRE_EQ(close(sv[1]), 0);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(sv[0], 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+ ATF_REQUIRE_EQ(errno, EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(close(sv[0]), 0);
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_little_endian_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_little_endian_size, tc)
|
||||
+{
|
||||
+ static const unsigned char payload[] = {
|
||||
+ 0x6c, /* magic */
|
||||
+ 0x00, /* version */
|
||||
+ 0x00, /* flags */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ };
|
||||
+ nvlist_t *nvl;
|
||||
+ int sv[2];
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
+ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)),
|
||||
+ (ssize_t)sizeof(payload));
|
||||
+ ATF_REQUIRE_EQ(close(sv[1]), 0);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(sv[0], 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+ ATF_REQUIRE_EQ(errno, EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(close(sv[0]), 0);
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc)
|
||||
+{
|
||||
+ nvlist_t *nvl;
|
||||
+ void *packed;
|
||||
+ size_t packed_size;
|
||||
+ struct nvlist_header *header;
|
||||
+ int fd, socks[2], status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ /* Child. */
|
||||
+ fd = socks[0];
|
||||
+ close(socks[1]);
|
||||
+
|
||||
+ nvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_empty(nvl));
|
||||
+
|
||||
+ nvlist_add_string(nvl, "nvl/string", "test");
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
|
||||
+
|
||||
+ packed = nvlist_pack(nvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
|
||||
+
|
||||
+ header = (struct nvlist_header *)packed;
|
||||
+ header->nvlh_descriptors = 0x20;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
|
||||
+ (ssize_t)packed_size);
|
||||
+
|
||||
+ nvlist_destroy(nvl);
|
||||
+ free(packed);
|
||||
+
|
||||
+ exit(0);
|
||||
+ } else {
|
||||
+ /* Parent */
|
||||
+ fd = socks[1];
|
||||
+ close(socks[0]);
|
||||
+
|
||||
+ nvl = nvlist_recv(fd, 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+ }
|
||||
+
|
||||
+ close(fd);
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc)
|
||||
+{
|
||||
+ nvlist_t *nvl;
|
||||
+ void *packed;
|
||||
+ size_t packed_size;
|
||||
+ struct nvlist_header *header;
|
||||
+ int fd, socks[2], fds[1], status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ /* Child. */
|
||||
+ fd = socks[0];
|
||||
+ close(socks[1]);
|
||||
+
|
||||
+ nvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_empty(nvl));
|
||||
+
|
||||
+ nvlist_add_string(nvl, "nvl/string", "test");
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
|
||||
+
|
||||
+ packed = nvlist_pack(nvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
|
||||
+
|
||||
+ header = (struct nvlist_header *)packed;
|
||||
+ header->nvlh_descriptors = 0x4000000000000002;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
|
||||
+ (ssize_t)packed_size);
|
||||
+
|
||||
+ fds[0] = dup(STDERR_FILENO);
|
||||
+ ATF_REQUIRE(fds[0] >= 0);
|
||||
+ ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0);
|
||||
+
|
||||
+ nvlist_destroy(nvl);
|
||||
+ free(packed);
|
||||
+
|
||||
+ close(fds[0]);
|
||||
+ close(fd);
|
||||
+
|
||||
+ exit(0);
|
||||
+ } else {
|
||||
+ /* Parent */
|
||||
+ fd = socks[1];
|
||||
+ close(socks[0]);
|
||||
+
|
||||
+ nvl = nvlist_recv(fd, 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+
|
||||
+ /* Make sure that fd was not parsed by nvlist */
|
||||
+ ATF_REQUIRE(fd_recv(fd, fds, 1) == 0);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+
|
||||
+ close(fds[0]);
|
||||
+ close(fd);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__highfd);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream);
|
||||
+
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_big_endian_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_little_endian_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size);
|
||||
|
||||
return (atf_no_error());
|
||||
}
|
||||
--- sys/contrib/libnv/nv_impl.h.orig
|
||||
+++ sys/contrib/libnv/nv_impl.h
|
||||
@@ -42,6 +42,14 @@
|
||||
typedef struct nvpair nvpair_t;
|
||||
#endif
|
||||
|
||||
+struct nvlist_header {
|
||||
+ uint8_t nvlh_magic;
|
||||
+ uint8_t nvlh_version;
|
||||
+ uint8_t nvlh_flags;
|
||||
+ uint64_t nvlh_descriptors;
|
||||
+ uint64_t nvlh_size;
|
||||
+} __packed;
|
||||
+
|
||||
#define NV_TYPE_NVLIST_ARRAY_NEXT 254
|
||||
#define NV_TYPE_NVLIST_UP 255
|
||||
|
||||
--- sys/contrib/libnv/nvlist.c.orig
|
||||
+++ sys/contrib/libnv/nvlist.c
|
||||
@@ -118,13 +118,6 @@
|
||||
|
||||
#define NVLIST_HEADER_MAGIC 0x6c
|
||||
#define NVLIST_HEADER_VERSION 0x00
|
||||
-struct nvlist_header {
|
||||
- uint8_t nvlh_magic;
|
||||
- uint8_t nvlh_version;
|
||||
- uint8_t nvlh_flags;
|
||||
- uint64_t nvlh_descriptors;
|
||||
- uint64_t nvlh_size;
|
||||
-} __packed;
|
||||
|
||||
nvlist_t *
|
||||
nvlist_create(int flags)
|
||||
@@ -0,0 +1,17 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xikbFIAAAAAABAAO
|
||||
bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvXoIQAMu1Z+MW43UPDQ7tLgn2
|
||||
4aVfe0l+NqdQS3t9diugP8SdwmSXuCgs6nnXFgp0s6iBRyDqWyHtc3w6eaf24QSD
|
||||
Iho64XCvcZrik5QkLCE0agDZ4JutaPFy2Tkv1CWgeBmQyZl09LyYgILqtqIgK5qm
|
||||
WZXhxDdPK+d16QRvHr06AhOWHqQzDo7/Exk5U82LrwuEbJCu9Szy5yTT5tBJrmIq
|
||||
fvQYVYf2RLyNad2LA13xRLLCF0K/Tdpaj6TnkBLJragNwjCExBtnXyi+c4FCnqTF
|
||||
7d+FzOAF2sgMSFxFh075FPXAlItfcMOIxUXjbH03vmXgxOV20izwQP0i3PRR3lPl
|
||||
eGZobqaO7Oe7vhCJ1vgY2OPRuOr2VHrKQMcTAeQCCLYkN7MMjx1mWspRSWRTbIv5
|
||||
3KzZfy89v+NWO5vbXQ6zVqsknNUjeYbqbHS6Hlk5xr9kwYkxA0HBm/6RVwmVg5bm
|
||||
dthtj7jtZcuiYQwgNuGp908SuZkU0g+MzzGijOvZ60nckfvx+CX/tAEWecDKn8zZ
|
||||
V4UiEggNR5tSkqnNIfFtelAYtNGKX5lia/3lb/FijxM8mFgVjLC3IAyR5z8OSYDQ
|
||||
zdYrC5aYsWUCFyBENN4VElz2RnJgIGFMRWFCfb4vpbHFC7Zo6ce6Rln1TnsuH0bE
|
||||
MJH+dVpEzdrjYOq74oc0fHgA
|
||||
=/8Ff
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -0,0 +1,487 @@
|
||||
--- lib/libnv/tests/Makefile.orig
|
||||
+++ lib/libnv/tests/Makefile
|
||||
@@ -1,6 +1,15 @@
|
||||
+.include <src.opts.mk>
|
||||
|
||||
ATF_TESTS_C= \
|
||||
nvlist_send_recv_test
|
||||
+
|
||||
+.PATH: ${SRCTOP}/lib/libnv
|
||||
+SRCS.nvlist_send_recv_test= msgio.c nvlist_send_recv_test.c
|
||||
+CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/sys/contrib/libnv
|
||||
+CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/lib/libnv
|
||||
+.if ${MK_ASAN} != "yes"
|
||||
+CFLAGS.nvlist_send_recv_test+=-DNO_ASAN
|
||||
+.endif
|
||||
|
||||
ATF_TESTS_CXX= \
|
||||
cnv_tests \
|
||||
--- lib/libnv/tests/nv_array_tests.cc.orig
|
||||
+++ lib/libnv/tests/nv_array_tests.cc
|
||||
@@ -1,6 +1,5 @@
|
||||
/*-
|
||||
- * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
- * All rights reserved.
|
||||
+ * Copyright (c) 2015-2024 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -28,6 +27,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/nv.h>
|
||||
+#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
@@ -1162,6 +1162,58 @@
|
||||
free(packed);
|
||||
}
|
||||
|
||||
+
|
||||
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array_nonull__pack);
|
||||
+ATF_TEST_CASE_BODY(nvlist_string_array_nonull__pack)
|
||||
+{
|
||||
+ nvlist_t *testnvl, *unpacked;
|
||||
+ const char *somestr[3] = { "a", "b", "XXX" };
|
||||
+ uint8_t *packed, *twopages, *dataptr, *secondpage;
|
||||
+ size_t packed_size, page_size;
|
||||
+ bool found;
|
||||
+
|
||||
+ page_size = sysconf(_SC_PAGESIZE);
|
||||
+ testnvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(testnvl != NULL);
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0);
|
||||
+ nvlist_add_string_array(testnvl, "nvl/string", somestr,
|
||||
+ nitems(somestr));
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0);
|
||||
+
|
||||
+ packed = (uint8_t *)nvlist_pack(testnvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+
|
||||
+ twopages = (uint8_t *)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,
|
||||
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
+ ATF_REQUIRE(twopages != MAP_FAILED);
|
||||
+ dataptr = &twopages[page_size - packed_size];
|
||||
+ secondpage = &twopages[page_size];
|
||||
+
|
||||
+ memset(twopages, 'A', page_size * 2);
|
||||
+
|
||||
+ mprotect(secondpage, page_size, PROT_NONE);
|
||||
+ memcpy(dataptr, packed, packed_size);
|
||||
+
|
||||
+ found = false;
|
||||
+ for (size_t i = 0; i < packed_size - 3; i++) {
|
||||
+ if (dataptr[i] == 'X' && dataptr[i + 1] == 'X' &&
|
||||
+ dataptr[i + 2] == 'X' && dataptr[i + 3] == '\0') {
|
||||
+ dataptr[i + 3] = 'X';
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ ATF_REQUIRE(found == true);
|
||||
+
|
||||
+ unpacked = nvlist_unpack(dataptr, packed_size, 0);
|
||||
+ ATF_REQUIRE(unpacked == NULL);
|
||||
+
|
||||
+ nvlist_destroy(testnvl);
|
||||
+ free(packed);
|
||||
+ munmap(twopages, page_size * 2);
|
||||
+}
|
||||
+
|
||||
+
|
||||
ATF_INIT_TEST_CASES(tp)
|
||||
{
|
||||
|
||||
@@ -1191,5 +1243,7 @@
|
||||
ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__pack)
|
||||
ATF_ADD_TEST_CASE(tp, nvlist_string_array__pack)
|
||||
ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__pack)
|
||||
+
|
||||
+ ATF_ADD_TEST_CASE(tp, nvlist_string_array_nonull__pack)
|
||||
}
|
||||
|
||||
--- lib/libnv/tests/nvlist_send_recv_test.c.orig
|
||||
+++ lib/libnv/tests/nvlist_send_recv_test.c
|
||||
@@ -1,5 +1,8 @@
|
||||
/*-
|
||||
+ * SPDX-License-Identifier: BSD-2-Clause
|
||||
+ *
|
||||
* Copyright (c) 2013 The FreeBSD Foundation
|
||||
+ * Copyright (c) 2024-2026 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
*
|
||||
* This software was developed by Pawel Jakub Dawidek under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
@@ -28,6 +31,8 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
+#include <sys/resource.h>
|
||||
+#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -44,6 +49,9 @@
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
+#include <nv_impl.h>
|
||||
+#include <msgio.h>
|
||||
+
|
||||
#define ALPHABET "abcdefghijklmnopqrstuvwxyz"
|
||||
#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
|
||||
|
||||
@@ -531,6 +539,59 @@
|
||||
nvlist_send_recv__send_nvlist(SOCK_STREAM);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Regression test for fd_wait(): the previous select(2)-based implementation
|
||||
+ * called FD_SET() unconditionally, which is an out-of-bounds stack write when
|
||||
+ * the socket fd is >= FD_SETSIZE. Force the socketpair fds above FD_SETSIZE
|
||||
+ * and verify a full nvlist round-trip still works.
|
||||
+ */
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__highfd);
|
||||
+ATF_TC_BODY(nvlist_send_recv__highfd, tc)
|
||||
+{
|
||||
+ struct rlimit rl;
|
||||
+ nvlist_t *nvl;
|
||||
+ int socks[2], hi_send, hi_recv, status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ hi_send = FD_SETSIZE + 5;
|
||||
+ hi_recv = FD_SETSIZE + 6;
|
||||
+
|
||||
+ rl.rlim_cur = rl.rlim_max = hi_recv + 1;
|
||||
+ if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
|
||||
+ atf_tc_skip("cannot raise RLIMIT_NOFILE: %s", strerror(errno));
|
||||
+
|
||||
+ ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0);
|
||||
+ ATF_REQUIRE(dup2(socks[0], hi_recv) == hi_recv);
|
||||
+ ATF_REQUIRE(dup2(socks[1], hi_send) == hi_send);
|
||||
+ (void)close(socks[0]);
|
||||
+ (void)close(socks[1]);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+ if (pid == 0) {
|
||||
+ /* Child: send. */
|
||||
+ (void)close(hi_recv);
|
||||
+ nvl = nvlist_create(0);
|
||||
+ nvlist_add_string(nvl, "key", "value");
|
||||
+ if (nvlist_send(hi_send, nvl) != 0)
|
||||
+ err(EXIT_FAILURE, "nvlist_send");
|
||||
+ nvlist_destroy(nvl);
|
||||
+ _exit(0);
|
||||
+ }
|
||||
+
|
||||
+ (void)close(hi_send);
|
||||
+ nvl = nvlist_recv(hi_recv, 0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
|
||||
+ ATF_REQUIRE(nvlist_exists_string(nvl, "key"));
|
||||
+ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "key"), "value") == 0);
|
||||
+ nvlist_destroy(nvl);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+ (void)close(hi_recv);
|
||||
+}
|
||||
+
|
||||
ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram);
|
||||
ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc)
|
||||
{
|
||||
@@ -543,15 +604,260 @@
|
||||
nvlist_send_recv__send_closed_fd(SOCK_STREAM);
|
||||
}
|
||||
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc)
|
||||
+{
|
||||
+ nvlist_t *nvl;
|
||||
+ void *packed;
|
||||
+ size_t packed_size;
|
||||
+ struct nvlist_header *header;
|
||||
+ int fd, socks[2], status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+#ifdef NO_ASAN
|
||||
+ atf_tc_skip("This test requires ASAN");
|
||||
+#endif
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ /* Child. */
|
||||
+ fd = socks[0];
|
||||
+ close(socks[1]);
|
||||
+
|
||||
+ nvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_empty(nvl));
|
||||
+
|
||||
+ packed = nvlist_pack(nvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
|
||||
+
|
||||
+ header = (struct nvlist_header *)packed;
|
||||
+ header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
|
||||
+ (ssize_t)sizeof(struct nvlist_header));
|
||||
+
|
||||
+ nvlist_destroy(nvl);
|
||||
+ free(packed);
|
||||
+
|
||||
+ exit(0);
|
||||
+ } else {
|
||||
+ /* Parent */
|
||||
+ fd = socks[1];
|
||||
+ close(socks[0]);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(fd, 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure it has failed on EINVAL, and not on
|
||||
+ * errors returned by malloc or recv.
|
||||
+ */
|
||||
+ ATF_REQUIRE(errno == EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+ close(fd);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_big_endian_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_big_endian_size, tc)
|
||||
+{
|
||||
+ static const unsigned char payload[] = {
|
||||
+ 0x6c, /* magic */
|
||||
+ 0x00, /* version */
|
||||
+ 0x80, /* flags: NV_FLAG_BIG_ENDIAN */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5,
|
||||
+ };
|
||||
+ nvlist_t *nvl;
|
||||
+ int sv[2];
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
+ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)),
|
||||
+ (ssize_t)sizeof(payload));
|
||||
+ ATF_REQUIRE_EQ(close(sv[1]), 0);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(sv[0], 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+ ATF_REQUIRE_EQ(errno, EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(close(sv[0]), 0);
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_little_endian_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_little_endian_size, tc)
|
||||
+{
|
||||
+ static const unsigned char payload[] = {
|
||||
+ 0x6c, /* magic */
|
||||
+ 0x00, /* version */
|
||||
+ 0x00, /* flags */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ };
|
||||
+ nvlist_t *nvl;
|
||||
+ int sv[2];
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
+ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)),
|
||||
+ (ssize_t)sizeof(payload));
|
||||
+ ATF_REQUIRE_EQ(close(sv[1]), 0);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(sv[0], 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+ ATF_REQUIRE_EQ(errno, EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(close(sv[0]), 0);
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc)
|
||||
+{
|
||||
+ nvlist_t *nvl;
|
||||
+ void *packed;
|
||||
+ size_t packed_size;
|
||||
+ struct nvlist_header *header;
|
||||
+ int fd, socks[2], status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ /* Child. */
|
||||
+ fd = socks[0];
|
||||
+ close(socks[1]);
|
||||
+
|
||||
+ nvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_empty(nvl));
|
||||
+
|
||||
+ nvlist_add_string(nvl, "nvl/string", "test");
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
|
||||
+
|
||||
+ packed = nvlist_pack(nvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
|
||||
+
|
||||
+ header = (struct nvlist_header *)packed;
|
||||
+ header->nvlh_descriptors = 0x20;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
|
||||
+ (ssize_t)packed_size);
|
||||
+
|
||||
+ nvlist_destroy(nvl);
|
||||
+ free(packed);
|
||||
+
|
||||
+ exit(0);
|
||||
+ } else {
|
||||
+ /* Parent */
|
||||
+ fd = socks[1];
|
||||
+ close(socks[0]);
|
||||
+
|
||||
+ nvl = nvlist_recv(fd, 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+ }
|
||||
+
|
||||
+ close(fd);
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc)
|
||||
+{
|
||||
+ nvlist_t *nvl;
|
||||
+ void *packed;
|
||||
+ size_t packed_size;
|
||||
+ struct nvlist_header *header;
|
||||
+ int fd, socks[2], fds[1], status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ /* Child. */
|
||||
+ fd = socks[0];
|
||||
+ close(socks[1]);
|
||||
+
|
||||
+ nvl = nvlist_create(0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_empty(nvl));
|
||||
+
|
||||
+ nvlist_add_string(nvl, "nvl/string", "test");
|
||||
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
|
||||
+
|
||||
+ packed = nvlist_pack(nvl, &packed_size);
|
||||
+ ATF_REQUIRE(packed != NULL);
|
||||
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
|
||||
+
|
||||
+ header = (struct nvlist_header *)packed;
|
||||
+ header->nvlh_descriptors = 0x4000000000000002;
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
|
||||
+ (ssize_t)packed_size);
|
||||
+
|
||||
+ fds[0] = dup(STDERR_FILENO);
|
||||
+ ATF_REQUIRE(fds[0] >= 0);
|
||||
+ ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0);
|
||||
+
|
||||
+ nvlist_destroy(nvl);
|
||||
+ free(packed);
|
||||
+
|
||||
+ close(fds[0]);
|
||||
+ close(fd);
|
||||
+
|
||||
+ exit(0);
|
||||
+ } else {
|
||||
+ /* Parent */
|
||||
+ fd = socks[1];
|
||||
+ close(socks[0]);
|
||||
+
|
||||
+ nvl = nvlist_recv(fd, 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+
|
||||
+ /* Make sure that fd was not parsed by nvlist */
|
||||
+ ATF_REQUIRE(fd_recv(fd, fds, 1) == 0);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+
|
||||
+ close(fds[0]);
|
||||
+ close(fd);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__highfd);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream);
|
||||
+
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_big_endian_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_little_endian_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size);
|
||||
|
||||
return (atf_no_error());
|
||||
}
|
||||
--- sys/contrib/libnv/nv_impl.h.orig
|
||||
+++ sys/contrib/libnv/nv_impl.h
|
||||
@@ -42,6 +42,14 @@
|
||||
typedef struct nvpair nvpair_t;
|
||||
#endif
|
||||
|
||||
+struct nvlist_header {
|
||||
+ uint8_t nvlh_magic;
|
||||
+ uint8_t nvlh_version;
|
||||
+ uint8_t nvlh_flags;
|
||||
+ uint64_t nvlh_descriptors;
|
||||
+ uint64_t nvlh_size;
|
||||
+} __packed;
|
||||
+
|
||||
#define NV_TYPE_NVLIST_ARRAY_NEXT 254
|
||||
#define NV_TYPE_NVLIST_UP 255
|
||||
|
||||
--- sys/contrib/libnv/nvlist.c.orig
|
||||
+++ sys/contrib/libnv/nvlist.c
|
||||
@@ -118,13 +118,6 @@
|
||||
|
||||
#define NVLIST_HEADER_MAGIC 0x6c
|
||||
#define NVLIST_HEADER_VERSION 0x00
|
||||
-struct nvlist_header {
|
||||
- uint8_t nvlh_magic;
|
||||
- uint8_t nvlh_version;
|
||||
- uint8_t nvlh_flags;
|
||||
- uint64_t nvlh_descriptors;
|
||||
- uint64_t nvlh_size;
|
||||
-} __packed;
|
||||
|
||||
nvlist_t *
|
||||
nvlist_create(int flags)
|
||||
@@ -0,0 +1,17 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xiobFIAAAAAABAAO
|
||||
bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvsj4QAKU6z5Bwr7Mz1EuIurfY
|
||||
KWC8nPyOciXn+b0pITMGZKKmYOOk3uhjcVwuQa3BRL0XGFEVm2b1GSO7exvSHTjo
|
||||
TUD/w80wyzjiqUV3T7LfXZD2hZKnIL3erCDKwgmXX3D5cSOjjKQPaDgb/ax0Jk+G
|
||||
/mccSWKg+4oMrISwcD2urimU5OZcvrgTNNksRnFtVlKb1bKttdTIERtcB40fb3G9
|
||||
6CAI6Gwpg/OzARHICC9GgMrrSvnaknL5peMLfTpwNBwdYJJLJLXuGVlugKnH46/3
|
||||
py5e1zdbR6Y/ieEhJpZ3bhHV38UZBgstVGCmtpMPVFXo7N6ustrBM+861CeLGez4
|
||||
ct9d8LcHMNoOGtFkzDsWL/Pp99TV8wYEVoVVZkx0dJv/awzmmasAN8q9KN4tlTzB
|
||||
+4DHYIToTRdhghpp9aRm7ZCoShKARpbSp4XH1sOdj6t82MR/mIDQnvl+t7uw69oY
|
||||
Y3Ch+atdUuZAU+2RcxGPlcQJ4bhQ2UlXG1fZnyD6HeizkTCZaOlLn2aSmPtpv+bH
|
||||
nihTiuLFCPcpmdrNsj6ukVBBftpojF9Jufo4d95sKgOr1mImYWBJUjCIZjc3bHFL
|
||||
Qk/GnOSKgsD9UQjgtoQoQlZRmjTBlX04HqMgE4TBfjrnfb/5jezIlxE/TPpA4wrU
|
||||
/eawpZgNuXq1uaBn/w1aNBkE
|
||||
=rZUQ
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -0,0 +1,166 @@
|
||||
--- lib/libnv/tests/nvlist_send_recv_test.c.orig
|
||||
+++ lib/libnv/tests/nvlist_send_recv_test.c
|
||||
@@ -1,5 +1,8 @@
|
||||
/*-
|
||||
+ * SPDX-License-Identifier: BSD-2-Clause
|
||||
+ *
|
||||
* Copyright (c) 2013 The FreeBSD Foundation
|
||||
+ * Copyright (c) 2024-2026 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
*
|
||||
* This software was developed by Pawel Jakub Dawidek under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
@@ -27,6 +30,8 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
+#include <sys/resource.h>
|
||||
+#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -533,6 +538,59 @@
|
||||
nvlist_send_recv__send_nvlist(SOCK_STREAM);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Regression test for fd_wait(): the previous select(2)-based implementation
|
||||
+ * called FD_SET() unconditionally, which is an out-of-bounds stack write when
|
||||
+ * the socket fd is >= FD_SETSIZE. Force the socketpair fds above FD_SETSIZE
|
||||
+ * and verify a full nvlist round-trip still works.
|
||||
+ */
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__highfd);
|
||||
+ATF_TC_BODY(nvlist_send_recv__highfd, tc)
|
||||
+{
|
||||
+ struct rlimit rl;
|
||||
+ nvlist_t *nvl;
|
||||
+ int socks[2], hi_send, hi_recv, status;
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ hi_send = FD_SETSIZE + 5;
|
||||
+ hi_recv = FD_SETSIZE + 6;
|
||||
+
|
||||
+ rl.rlim_cur = rl.rlim_max = hi_recv + 1;
|
||||
+ if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
|
||||
+ atf_tc_skip("cannot raise RLIMIT_NOFILE: %s", strerror(errno));
|
||||
+
|
||||
+ ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0);
|
||||
+ ATF_REQUIRE(dup2(socks[0], hi_recv) == hi_recv);
|
||||
+ ATF_REQUIRE(dup2(socks[1], hi_send) == hi_send);
|
||||
+ (void)close(socks[0]);
|
||||
+ (void)close(socks[1]);
|
||||
+
|
||||
+ pid = fork();
|
||||
+ ATF_REQUIRE(pid >= 0);
|
||||
+ if (pid == 0) {
|
||||
+ /* Child: send. */
|
||||
+ (void)close(hi_recv);
|
||||
+ nvl = nvlist_create(0);
|
||||
+ nvlist_add_string(nvl, "key", "value");
|
||||
+ if (nvlist_send(hi_send, nvl) != 0)
|
||||
+ err(EXIT_FAILURE, "nvlist_send");
|
||||
+ nvlist_destroy(nvl);
|
||||
+ _exit(0);
|
||||
+ }
|
||||
+
|
||||
+ (void)close(hi_send);
|
||||
+ nvl = nvlist_recv(hi_recv, 0);
|
||||
+ ATF_REQUIRE(nvl != NULL);
|
||||
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
|
||||
+ ATF_REQUIRE(nvlist_exists_string(nvl, "key"));
|
||||
+ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "key"), "value") == 0);
|
||||
+ nvlist_destroy(nvl);
|
||||
+
|
||||
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
|
||||
+ ATF_REQUIRE(status == 0);
|
||||
+ (void)close(hi_recv);
|
||||
+}
|
||||
+
|
||||
ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram);
|
||||
ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc)
|
||||
{
|
||||
@@ -608,6 +666,58 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_big_endian_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_big_endian_size, tc)
|
||||
+{
|
||||
+ static const unsigned char payload[] = {
|
||||
+ 0x6c, /* magic */
|
||||
+ 0x00, /* version */
|
||||
+ 0x80, /* flags: NV_FLAG_BIG_ENDIAN */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5,
|
||||
+ };
|
||||
+ nvlist_t *nvl;
|
||||
+ int sv[2];
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
+ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)),
|
||||
+ (ssize_t)sizeof(payload));
|
||||
+ ATF_REQUIRE_EQ(close(sv[1]), 0);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(sv[0], 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+ ATF_REQUIRE_EQ(errno, EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(close(sv[0]), 0);
|
||||
+}
|
||||
+
|
||||
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_little_endian_size);
|
||||
+ATF_TC_BODY(nvlist_send_recv__overflow_little_endian_size, tc)
|
||||
+{
|
||||
+ static const unsigned char payload[] = {
|
||||
+ 0x6c, /* magic */
|
||||
+ 0x00, /* version */
|
||||
+ 0x00, /* flags */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ };
|
||||
+ nvlist_t *nvl;
|
||||
+ int sv[2];
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
+ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)),
|
||||
+ (ssize_t)sizeof(payload));
|
||||
+ ATF_REQUIRE_EQ(close(sv[1]), 0);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ nvl = nvlist_recv(sv[0], 0);
|
||||
+ ATF_REQUIRE(nvl == NULL);
|
||||
+ ATF_REQUIRE_EQ(errno, EINVAL);
|
||||
+
|
||||
+ ATF_REQUIRE_EQ(close(sv[0]), 0);
|
||||
+}
|
||||
+
|
||||
ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size);
|
||||
ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc)
|
||||
{
|
||||
@@ -736,12 +846,15 @@
|
||||
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__highfd);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream);
|
||||
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_big_endian_size);
|
||||
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_little_endian_size);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size);
|
||||
ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size);
|
||||
|
||||
--- tests/sys/posixshm/posixshm_test.c.orig
|
||||
+++ tests/sys/posixshm/posixshm_test.c
|
||||
@@ -1986,7 +1986,7 @@
|
||||
error = sigaction(SIGSEGV, &sa, NULL);
|
||||
ATF_REQUIRE(error == 0);
|
||||
|
||||
- pscnt = pagesizes(ps, true);
|
||||
+ pscnt = pagesizes(ps);
|
||||
|
||||
for (int i = 1; i < pscnt; i++) {
|
||||
uint64_t val;
|
||||
@@ -0,0 +1,17 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xisbFIAAAAAABAAO
|
||||
bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvZdYQAIY0794gvo9DtJHT/h1Z
|
||||
y5ezNg6C3axx4X1Ug1dVGQoH/+isH/hvMzHM/826SaGFBlD65SM+pQeZb9sUeeA9
|
||||
N65cW1m3dt+k+SNfpZ583adcwQBGQuC1NvNUDyJJmEnozCWmmqXXBtciPEIQEZ9c
|
||||
AmsSlL/TBVw1ruWPQ8nA/5xpPUEjAEw5CoMej9KG7/xziaYr5wC1e27FiDA8Z3Ar
|
||||
LiA/NM+4FmgZQvUIRWCrzBhesdKFFYOl8QMriOrxucqCcp6bqzQGRi5izfnvFCYH
|
||||
aWvN1FFe99+EYiVH3aQ1SoEBJ8etVPSrlhuOfic0WIhWlwKeL9Yvx9Be04LpJcu6
|
||||
3KY8Yr1O7mxQv8Jtwd7OeXUha2mDBLIxMtYs70SKgo+m1vfvLPoUckIDDszgIgCk
|
||||
swZEWhuGKSQ1aAMx5+6eRESKnOqATLWV04MHuC+TTD2v5kQvI4lb/bna87wUDlbl
|
||||
zSQn7FCv5KITrkhuFSF7vmoTUmB6EBDmfDvI2LSUKiHPAOwh8WJE4L0JoF9xgP2d
|
||||
G8SsONb5gb8YghWtF1KbPQlobGLy44vqZ/o1QvAxs7wZxPDx2Rw66PpEVWHXZKjN
|
||||
iXTAxheUwEYqMykzp7AQXuGvxeXrxfc6SoMLib1VsiRC4SGnVGaincF0jjqbeWeG
|
||||
r7Nd/REiFerNNNgKJGLXa5N0
|
||||
=U/vY
|
||||
-----END PGP SIGNATURE-----
|
||||
Reference in New Issue
Block a user