diff --git a/sys/net/ipfw3/ip_fw3.c b/sys/net/ipfw3/ip_fw3.c --- a/sys/net/ipfw3/ip_fw3.c +++ b/sys/net/ipfw3/ip_fw3.c @@ -1039,6 +1039,16 @@ ip_fw3_ctl_x(struct sockopt *sopt) { ip_fw_x_header *x_header; + + /* + * DF-0471: sopt_valsize is size_t (unsigned). If it is smaller than + * the 4-byte ip_fw_x_header, the subtraction below wraps to ~SIZE_MAX + * and the following bcopy walks off the end of the option buffer, + * corrupting kernel memory. Reject short payloads up front. + */ + if (sopt->sopt_valsize < sizeof(ip_fw_x_header)) + return EINVAL; + x_header = (ip_fw_x_header *)(sopt->sopt_val); sopt->sopt_name = x_header->opcode; sopt->sopt_valsize -= sizeof(ip_fw_x_header);