Skip to content

Commit 4aa624b

Browse files
committed
netmap: harden nmreq option size and overflow checks (defensive)\n\n- Enforce exact option body size equality per option type\n- Add explicit overflow guards to size arithmetic (sum)\n- Return EINVAL for invalid sizes; keep behavior for valid requests\n- Defensive hardening; no API break; reduces potential DoS/OOB surfaces
1 parent 716acd9 commit 4aa624b

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

sys/dev/netmap/netmap.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3497,16 +3497,19 @@ nmreq_copyin(struct nmreq_header *hdr, int nr_body_is_user)
34973497
}
34983498
opt_tab[opt->nro_reqtype] = opt;
34993499

3500-
/* copy the option body */
3501-
optsz = nmreq_opt_size_by_type(opt->nro_reqtype,
3502-
opt->nro_size);
3503-
/* check optsz and nro_size to avoid for possible integer overflows of rqsz */
3504-
if ((optsz > NETMAP_REQ_MAXSIZE) || (opt->nro_size > NETMAP_REQ_MAXSIZE)
3505-
|| (rqsz + optsz > NETMAP_REQ_MAXSIZE)
3506-
|| (optsz > 0 && rqsz + optsz <= rqsz)) {
3507-
error = EMSGSIZE;
3508-
goto out_restore;
3509-
}
3500+
/* copy the option body */
3501+
optsz = nmreq_opt_size_by_type(opt->nro_reqtype,
3502+
opt->nro_size);
3503+
/* enforce exact option body size and overflow guards */
3504+
if ((optsz == 0 && opt->nro_size != 0) || (opt->nro_size != optsz)) {
3505+
error = EINVAL;
3506+
goto out_restore;
3507+
}
3508+
if ((optsz > NETMAP_REQ_MAXSIZE) || (opt->nro_size > NETMAP_REQ_MAXSIZE)
3509+
|| (rqsz > NETMAP_REQ_MAXSIZE - optsz)) {
3510+
error = EMSGSIZE;
3511+
goto out_restore;
3512+
}
35103513
rqsz += optsz;
35113514
if (optsz) {
35123515
/* the option body follows the option header */
@@ -3584,10 +3587,15 @@ nmreq_copyout(struct nmreq_header *hdr, int rerror)
35843587
goto out;
35853588
}
35863589

3587-
/* copy the option body only if there was no error */
3588-
if (!rerror && !src->nro_status) {
3589-
optsz = nmreq_opt_size_by_type(src->nro_reqtype,
3590-
src->nro_size);
3590+
/* copy the option body only if there was no error */
3591+
if (!rerror && !src->nro_status) {
3592+
optsz = nmreq_opt_size_by_type(src->nro_reqtype,
3593+
src->nro_size);
3594+
/* enforce symmetry for copyout */
3595+
if ((optsz == 0 && src->nro_size != 0) || (src->nro_size != optsz)) {
3596+
rerror = EINVAL;
3597+
goto out;
3598+
}
35913599
if (optsz) {
35923600
error = copyout(src + 1, dst + 1, optsz);
35933601
if (error) {

0 commit comments

Comments
 (0)