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