Module Name: src
Committed By: riastradh
Date: Wed Sep 4 12:57:00 UTC 2024
Modified Files:
src/sys/external/bsd/libnv/dist: nv_kern_netbsd.c nvlist.c nvpair.c
Log Message:
libnv: Avoid arithmetic overflow in array allocation.
1. Teach nv_calloc and nv_strdup to detect arithmetic overflow.
2. Convert nv_malloc(sizeof(...) * N) to nv_calloc(N, sizeof(...)).
I reviewed all the remaining nv_malloc calls, because some of them
have the multiplication separated from the nv_malloc call. Of the
remaining callers:
- nv_calloc (now) checks for overflow
- nv_strdup (now) checks for overflow
- nvlist_create uses a fixed sizeof(...) without arithmetic
- nvlist_xpack doesn't directly check bounds, but as long as the wire
format is smaller than the in-memory size, that's not a problem
- nvlist_recv checks for sizeof(nvlhdr) + nvlhdr.nvlh_size overflow
- nvpair_unpack_binary uses nvp->nvp_datasize without arithmetic
- nvpair_unpack_bool_array checks for unsigned overflow
- nvpair_unpack_number_array checks for unsigned overflow
- nvpair_unpack_descriptor_array checks for unsigned overflow
- nvpair_create_binary uses caller-supplied size without arithmetic
Matches upstream FreeBSD change by Mariusz Zaborski
<[email protected]>.
CVE-2024-45287
PR security/58652: libnv: Integer overflow and buffer overrun
vulnerabilities
To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/external/bsd/libnv/dist/nv_kern_netbsd.c
cvs rdiff -u -r1.9 -r1.10 src/sys/external/bsd/libnv/dist/nvlist.c
cvs rdiff -u -r1.11 -r1.12 src/sys/external/bsd/libnv/dist/nvpair.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/external/bsd/libnv/dist/nv_kern_netbsd.c
diff -u src/sys/external/bsd/libnv/dist/nv_kern_netbsd.c:1.6 src/sys/external/bsd/libnv/dist/nv_kern_netbsd.c:1.7
--- src/sys/external/bsd/libnv/dist/nv_kern_netbsd.c:1.6 Tue Oct 16 13:18:25 2018
+++ src/sys/external/bsd/libnv/dist/nv_kern_netbsd.c Wed Sep 4 12:57:00 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: nv_kern_netbsd.c,v 1.6 2018/10/16 13:18:25 maxv Exp $ */
+/* $NetBSD: nv_kern_netbsd.c,v 1.7 2024/09/04 12:57:00 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: nv_kern_netbsd.c,v 1.6 2018/10/16 13:18:25 maxv Exp $");
+__RCSID("$NetBSD: nv_kern_netbsd.c,v 1.7 2024/09/04 12:57:00 riastradh Exp $");
#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <sys/mman.h>
@@ -209,10 +209,14 @@ nvlist_recv_ioctl(int fd, unsigned long
#endif
void *
-nv_calloc(size_t n, size_t s)
+nv_calloc(size_t nelem, size_t elemsize)
{
- const size_t len = n * s;
- void *buf = nv_malloc(len);
+
+ if (nelem > SIZE_MAX/elemsize)
+ return NULL;
+
+ const size_t len = nelem * elemsize;
+ void *const buf = nv_malloc(len);
if (buf == NULL)
return NULL;
memset(buf, 0, len);
@@ -222,9 +226,13 @@ nv_calloc(size_t n, size_t s)
char *
nv_strdup(const char *s1)
{
- size_t len = strlen(s1) + 1;
+ size_t len = strlen(s1);
char *s2;
+ if (len == SIZE_MAX)
+ return NULL;
+ len += 1; /* NUL terminator */
+
s2 = nv_malloc(len);
if (s2) {
memcpy(s2, s1, len);
Index: src/sys/external/bsd/libnv/dist/nvlist.c
diff -u src/sys/external/bsd/libnv/dist/nvlist.c:1.9 src/sys/external/bsd/libnv/dist/nvlist.c:1.10
--- src/sys/external/bsd/libnv/dist/nvlist.c:1.9 Wed Sep 4 12:56:47 2024
+++ src/sys/external/bsd/libnv/dist/nvlist.c Wed Sep 4 12:57:00 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: nvlist.c,v 1.9 2024/09/04 12:56:47 riastradh Exp $ */
+/* $NetBSD: nvlist.c,v 1.10 2024/09/04 12:57:00 riastradh Exp $ */
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
@@ -36,7 +36,7 @@
#ifdef __FreeBSD__
__FBSDID("$FreeBSD: head/sys/contrib/libnv/nvlist.c 335347 2018-06-18 22:57:32Z oshogbo $");
#else
-__RCSID("$NetBSD: nvlist.c,v 1.9 2024/09/04 12:56:47 riastradh Exp $");
+__RCSID("$NetBSD: nvlist.c,v 1.10 2024/09/04 12:57:00 riastradh Exp $");
#endif
#include <sys/param.h>
@@ -803,7 +803,7 @@ nvlist_descriptors(const nvlist_t *nvl,
int *fds;
nitems = nvlist_ndescriptors(nvl);
- fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
+ fds = nv_calloc(nitems + 1, sizeof(fds[0]));
if (fds == NULL)
return (NULL);
if (nitems > 0)
@@ -1351,7 +1351,7 @@ nvlist_recv(int sock, int flags)
goto out;
if (nfds > 0) {
- fds = nv_malloc(nfds * sizeof(fds[0]));
+ fds = nv_calloc(nfds, sizeof(fds[0]));
if (fds == NULL)
goto out;
if (fd_recv(sock, fds, nfds) == -1)
Index: src/sys/external/bsd/libnv/dist/nvpair.c
diff -u src/sys/external/bsd/libnv/dist/nvpair.c:1.11 src/sys/external/bsd/libnv/dist/nvpair.c:1.12
--- src/sys/external/bsd/libnv/dist/nvpair.c:1.11 Wed Jul 24 14:25:56 2019
+++ src/sys/external/bsd/libnv/dist/nvpair.c Wed Sep 4 12:57:00 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: nvpair.c,v 1.11 2019/07/24 14:25:56 martin Exp $ */
+/* $NetBSD: nvpair.c,v 1.12 2024/09/04 12:57:00 riastradh Exp $ */
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
@@ -36,7 +36,7 @@
#ifdef __FreeBSD__
__FBSDID("$FreeBSD: head/sys/contrib/libnv/nvpair.c 335382 2018-06-19 18:43:02Z lwhsu $");
#else
-__RCSID("$NetBSD: nvpair.c,v 1.11 2019/07/24 14:25:56 martin Exp $");
+__RCSID("$NetBSD: nvpair.c,v 1.12 2024/09/04 12:57:00 riastradh Exp $");
#endif
#include <sys/param.h>
@@ -1019,7 +1019,7 @@ nvpair_unpack_string_array(bool isbe __u
return (NULL);
}
- value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
+ value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
if (value == NULL)
return (NULL);
@@ -1112,7 +1112,7 @@ nvpair_unpack_nvlist_array(bool isbe __u
return (NULL);
}
- value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
+ value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
if (value == NULL)
return (NULL);
@@ -1357,10 +1357,10 @@ nvpair_create_bool_array(const char *nam
return (NULL);
}
- size = sizeof(value[0]) * nitems;
- data = nv_malloc(size);
+ data = nv_calloc(nitems, sizeof(value[0]));
if (data == NULL)
return (NULL);
+ size = sizeof(value[0]) * nitems;
memcpy(data, value, size);
nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
@@ -1387,10 +1387,10 @@ nvpair_create_number_array(const char *n
return (NULL);
}
- size = sizeof(value[0]) * nitems;
- data = nv_malloc(size);
+ data = nv_calloc(nitems, sizeof(value[0]));
if (data == NULL)
return (NULL);
+ size = sizeof(value[0]) * nitems;
memcpy(data, value, size);
nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
@@ -1420,7 +1420,7 @@ nvpair_create_string_array(const char *n
nvp = NULL;
datasize = 0;
- data = nv_malloc(sizeof(value[0]) * nitems);
+ data = nv_calloc(nitems, sizeof(value[0]));
if (data == NULL)
return (NULL);
@@ -1467,7 +1467,7 @@ nvpair_create_nvlist_array(const char *n
return (NULL);
}
- nvls = nv_malloc(sizeof(value[0]) * nitems);
+ nvls = nv_calloc(nitems, sizeof(value[0]));
if (nvls == NULL)
return (NULL);
@@ -1534,7 +1534,7 @@ nvpair_create_descriptor_array(const cha
nvp = NULL;
- fds = nv_malloc(sizeof(value[0]) * nitems);
+ fds = nv_calloc(nitems, sizeof(value[0]));
if (fds == NULL)
return (NULL);
for (ii = 0; ii < nitems; ii++) {