hastd: Fix nv data size check

The data size check, as currently written, can be defeated by providing
a very large number that rounds up to 0, which will pass the check
(because zero plus the size of the header and name is smaller than the
size of the message) but cause a segfault later when used to index the
data array.

Rewrite the data size check to take rounding into account, and add a
cast to ensure the name size can't round up to zero.

MFC after:	1 week
PR:		266827
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D51615
This commit is contained in:
Dag-Erling Smørgrav 2025-08-06 15:49:37 +02:00
parent 3456a0de94
commit 3caee2a93f

View file

@ -97,7 +97,7 @@ struct nvhdr {
} __packed;
#define NVH_DATA(nvh) ((unsigned char *)nvh + NVH_HSIZE(nvh))
#define NVH_HSIZE(nvh) \
(sizeof(struct nvhdr) + roundup2((nvh)->nvh_namesize, 8))
(sizeof(struct nvhdr) + roundup2((size_t)(nvh)->nvh_namesize, 8))
#define NVH_DSIZE(nvh) \
(((nvh)->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST ? \
(nvh)->nvh_dsize : \
@ -247,11 +247,8 @@ nv_validate(struct nv *nv, size_t *extrap)
break;
}
dsize = NVH_DSIZE(nvh);
if (dsize == 0) {
error = EINVAL;
break;
}
if (size < NVH_SIZE(nvh)) {
if (roundup2(dsize, 8) == 0 ||
roundup2(dsize, 8) > size - NVH_HSIZE(nvh)) {
error = EINVAL;
break;
}