diff options
| author | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2022-04-05 23:26:02 +0000 |
|---|---|---|
| committer | Ed Maste <emaste@FreeBSD.org> | 2022-04-05 23:26:02 +0000 |
| commit | 00ca345e83ada8b68e302f5406f9799209872c90 (patch) | |
| tree | be40643fcbe6c4d8c96c98b450b6d59db77d1245 /sys/dev/netmap | |
| parent | 5b789e0c92a7c363b36111b1f75519f2acd21f97 (diff) | |
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)
(cherry picked from commit 9df8dd3ea36c8b3abe8fc182647472ca9cd83efd)
Approved by: so
Security: FreeBSD-SA-22:04.netmap
Diffstat (limited to 'sys/dev/netmap')
| -rw-r--r-- | sys/dev/netmap/netmap.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c index 0bc723f6963d..c635c3d66314 100644 --- a/sys/dev/netmap/netmap.c +++ b/sys/dev/netmap/netmap.c @@ -3096,7 +3096,7 @@ 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; + size_t rqsz, optsz, bufsz, optbodysz; int error = 0; char *ker = NULL, *p; struct nmreq_option **next, *src, **opt_tab; @@ -3144,8 +3144,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; |
