diff --git a/sys/netpfil/ipfilter/netinet/ip_nat.c b/sys/netpfil/ipfilter/netinet/ip_nat.c --- a/sys/netpfil/ipfilter/netinet/ip_nat.c +++ b/sys/netpfil/ipfilter/netinet/ip_nat.c @@ -956,6 +956,34 @@ *(sp) = htons(sumshort); } +/* + * Make sure that the string at the specified offset lies within the bounds of + * the structure. + */ +static int +check_ipnat_string(ipf_main_softc_t *softc, ipnat_t *nat, int offset) +{ + const char *name; + size_t len; + + if (offset == -1) + return (0); + if (offset < 0) { + IPFERROR(60077); + return (EINVAL); + } + if (offset > nat->in_namelen) { + IPFERROR(60081); + return (EINVAL); + } + name = &nat->in_names[offset]; + len = strnlen(name, nat->in_namelen - offset); + if (len == nat->in_namelen - offset) { + IPFERROR(60078); + return (EINVAL); + } + return (0); +} /* ------------------------------------------------------------------------ */ /* Function: ipf_nat_ioctl */ @@ -1027,6 +1055,11 @@ error = EINVAL; goto done; } + if (natd.in_namelen < 0 || + sizeof(natd) + natd.in_namelen != natd.in_size) { + error = EINVAL; + goto done; + } KMALLOCS(nt, ipnat_t *, natd.in_size); if (nt == NULL) { IPFERROR(60070); @@ -1041,6 +1074,20 @@ nat = nt; } + /* + * Validate string offsets. + */ + error = check_ipnat_string(softc, nat, nat->in_ifnames[0]); + if (error == 0) + error = check_ipnat_string(softc, nat, + nat->in_ifnames[1]); + if (error == 0) + error = check_ipnat_string(softc, nat, nat->in_plabel); + if (error == 0) + error = check_ipnat_string(softc, nat, nat->in_pconfig); + if (error != 0) + goto done; + /* * For add/delete, look to see if the NAT entry is * already present