git: 606f528decc3 - stable/11 - netmap: Fix integer overflow in nmreq_copyin
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 20 Mar 2022 09:02:53 UTC
The branch stable/11 has been updated by vmaffione:
URL: https://cgit.FreeBSD.org/src/commit/?id=606f528decc334d9a56ef760b0815c6d56060dbe
commit 606f528decc334d9a56ef760b0815c6d56060dbe
Author: Vincenzo Maffione <vmaffione@FreeBSD.org>
AuthorDate: 2022-03-16 06:57:54 +0000
Commit: Vincenzo Maffione <vmaffione@FreeBSD.org>
CommitDate: 2022-03-20 09:01:58 +0000
netmap: Fix integer overflow in nmreq_copyin
An unsanitized field in an option could be abused, causing an integer
overflow followed by kernel memory corruption. This might be used
to escape jails/containers.
Reported by: Reno Robert and Lucas Leong (@_wmliang_) of Trend Micro
Zero Day Initiative
Security: CVE-2022-23085
(cherry picked from commit 694ea59c7021c25417e6d516362d2f59b4e2c343)
---
sys/dev/netmap/netmap.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c
index 420287516aa6..0c060219ff23 100644
--- a/sys/dev/netmap/netmap.c
+++ b/sys/dev/netmap/netmap.c
@@ -2987,8 +2987,8 @@ nmreq_opt_size_by_type(uint32_t nro_reqtype, uint64_t nro_size)
int
nmreq_copyin(struct nmreq_header *hdr, int nr_body_is_user)
{
- size_t rqsz, optsz, bufsz;
- int error;
+ size_t rqsz, optsz, bufsz, optbodysz;
+ int error = 0;
char *ker = NULL, *p;
struct nmreq_option **next, *src;
struct nmreq_option buf;
@@ -3029,8 +3029,18 @@ nmreq_copyin(struct nmreq_header *hdr, int nr_body_is_user)
error = copyin(src, &buf, sizeof(*src));
if (error)
goto out_err;
+ /* Validate nro_size to avoid integer overflow of optsz and bufsz. */
+ if (buf.nro_size > NETMAP_REQ_MAXSIZE) {
+ error = EMSGSIZE;
+ goto out_err;
+ }
optsz += sizeof(*src);
- optsz += nmreq_opt_size_by_type(buf.nro_reqtype, buf.nro_size);
+ optbodysz = nmreq_opt_size_by_type(buf.nro_reqtype, buf.nro_size);
+ if (optbodysz > NETMAP_REQ_MAXSIZE) {
+ error = EMSGSIZE;
+ goto out_err;
+ }
+ optsz += optbodysz;
if (rqsz + optsz > NETMAP_REQ_MAXSIZE) {
error = EMSGSIZE;
goto out_err;