Page MenuHomeFreeBSD

D53475.diff
No OneTemporary

D53475.diff

diff --git a/sbin/ipf/libipf/interror.c b/sbin/ipf/libipf/interror.c
--- a/sbin/ipf/libipf/interror.c
+++ b/sbin/ipf/libipf/interror.c
@@ -177,6 +177,11 @@
{ 149, "object size validation failed for kernel copyout" },
{ 150, "error copying data out for kernel copyout" },
{ 151, "version mismatch for kernel copyout" },
+ { 152, "fr_names offset is wrapped negative" },
+ { 153, "fr_names larger than fr_namelen" },
+ { 154, "frentry larger than fr_size" },
+ { 155, "frentry and fr_namelen mismatch fr_size" },
+ { 156, "fr_namelen too large" },
/* -------------------------------------------------------------------------- */
{ 10001, "could not find token for auth iterator" },
{ 10002, "write permissions require to add/remove auth rule" },
diff --git a/sys/netpfil/ipfilter/netinet/fil.c b/sys/netpfil/ipfilter/netinet/fil.c
--- a/sys/netpfil/ipfilter/netinet/fil.c
+++ b/sys/netpfil/ipfilter/netinet/fil.c
@@ -363,6 +363,10 @@
"ip_timeout", 1, 0x7fffffff,
stsizeof(ipf_main_softc_t, ipf_iptimeout),
0, NULL, ipf_settimeout },
+ { { (void *)offsetof(ipf_main_softc_t, ipf_max_namelen) },
+ "max_namelen", 0, 0x7fffffff,
+ stsizeof(ipf_main_softc_t, ipf_max_namelen),
+ 0, NULL, NULL },
#if defined(INSTANCES) && defined(_KERNEL)
{ { (void *)offsetof(ipf_main_softc_t, ipf_get_loopback) },
"intercept_loopback", 0, 1,
@@ -4408,7 +4412,9 @@
void *ptr, *uptr;
u_int *p, *pp;
frgroup_t *fg;
- char *group;
+ char *group, *name;
+ size_t v_fr_size, v_element_size;
+ int v_rem_namelen, v_fr_toend;
ptr = NULL;
fg = NULL;
@@ -4423,6 +4429,17 @@
IPFERROR(6);
return (EINVAL);
}
+ if (fp->fr_size < sizeof(frd)) {
+ return (EINVAL);
+ }
+ if (sizeof(frd) + fp->fr_namelen != fp->fr_size ) {
+ IPFERROR(155);
+ return (EINVAL);
+ }
+ if (fp->fr_namelen > softc->ipf_max_namelen) {
+ IPFERROR(156);
+ return (EINVAL);
+ }
KMALLOCS(f, frentry_t *, fp->fr_size);
if (f == NULL) {
IPFERROR(131);
@@ -4449,6 +4466,51 @@
fp->fr_ptr = NULL;
fp->fr_ref = 0;
fp->fr_flags |= FR_COPIED;
+ /*
+ * Validate the incoming frentry_t.
+ */
+#define VFY_FR_NAME(_a, _b) \
+ if (_a->_b != -1) { \
+ if (_a->_b < -1) { \
+ IPFERROR(152); \
+ error = EINVAL; \
+ goto donenolock; \
+ } \
+ name = FR_NAME(_a, _b); \
+ v_fr_toend = _a->fr_namelen - _a->_b; \
+ if (v_fr_toend < 0) { \
+ IPFERROR(156); \
+ error = EINVAL; \
+ goto donenolock; \
+ } \
+ v_element_size = strnlen(name, v_fr_toend) + 1; \
+ v_fr_size += v_element_size; \
+ v_rem_namelen -= v_element_size; \
+ if (v_rem_namelen < 0 || v_fr_size > fp->fr_size) { \
+ IPFERROR(153); \
+ error = EINVAL; \
+ goto donenolock; \
+ } \
+ }
+
+ v_fr_size = sizeof(*fp);
+ v_rem_namelen = fp->fr_namelen;
+ VFY_FR_NAME(fp, fr_comment);
+ VFY_FR_NAME(fp, fr_group);
+ VFY_FR_NAME(fp, fr_grhead);
+ VFY_FR_NAME(fp, fr_grhead);
+ VFY_FR_NAME(fp, fr_ifnames[0]);
+ VFY_FR_NAME(fp, fr_ifnames[1]);
+ VFY_FR_NAME(fp, fr_ifnames[2]);
+ VFY_FR_NAME(fp, fr_ifnames[3]);
+ VFY_FR_NAME(fp, fr_tif.fd_name);
+ VFY_FR_NAME(fp, fr_rif.fd_name);
+ VFY_FR_NAME(fp, fr_dif.fd_name);
+ if (v_fr_size > fp->fr_size) {
+ IPFERROR(154);
+ error = EINVAL;
+ goto donenolock;
+ }
} else {
fp = (frentry_t *)data;
if ((fp->fr_type & FR_T_BUILTIN) == 0) {
@@ -9040,6 +9102,7 @@
#endif
softc->ipf_minttl = 4;
softc->ipf_icmpminfragmtu = 68;
+ softc->ipf_max_namelen = 128;
softc->ipf_flags = IPF_LOGGING;
#ifdef LARGE_NAT
diff --git a/sys/netpfil/ipfilter/netinet/ip_fil.h b/sys/netpfil/ipfilter/netinet/ip_fil.h
--- a/sys/netpfil/ipfilter/netinet/ip_fil.h
+++ b/sys/netpfil/ipfilter/netinet/ip_fil.h
@@ -1529,6 +1529,7 @@
int ipf_pass;
int ipf_minttl;
int ipf_icmpminfragmtu;
+ int ipf_max_namelen;
int ipf_interror; /* Should be in a struct that is per */
/* thread or process. Does not belong */
/* here but there's a lot more work */
diff --git a/sys/netpfil/ipfilter/netinet/mlfk_ipl.c b/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
--- a/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
+++ b/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
@@ -135,6 +135,7 @@
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_chksrc), 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_minttl), 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, large_nat, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &VNET_NAME(ipfmain.ipf_large_nat), 0, "large_nat");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_max_namelen, CTLFLAG_RWTUN, &VNET_NAME(ipfmain.ipf_max_namelen), 0, "max_namelen");
#define CDEV_MAJOR 79
#include <sys/poll.h>

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 1, 1:19 PM (4 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29114894
Default Alt Text
D53475.diff (4 KB)

Event Timeline