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
<osho...@freebsd.org>.

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++) {

Reply via email to