blob: 86d825349f31139252cf9a88ee361d81f2e5c5ba [file] [log] [blame] [raw]
Fix rules comparison code compares volatile pointers and index numbers.
Reported in bug 238796.
Fixed in r350880.
diff -ru --exclude-from freebsd-src-diff-exclude-names /usr/src/sys/contrib/ipfilter/netinet/fil.c freebsd-11.1/sys/contrib/ipfilter/netinet/fil.c
--- /usr/src/sys/contrib/ipfilter/netinet/fil.c 2017-07-21 07:41:56.000000000 +0800
+++ freebsd-11.1/sys/contrib/ipfilter/netinet/fil.c 2020-01-26 00:06:12.922137000 +0800
@@ -4468,6 +4468,40 @@
return 0;
}
+static int
+ipf_ifnames_compare(const int *ifnames1, const int *ifnames2,
+ const char *base1, const char *base2)
+{
+ int i;
+ for(i = 0; i < 4; i++) {
+ if (ifnames1[i] != -1 && ifnames2[i] == -1)
+ return 1;
+ if (ifnames1[i] == -1 && ifnames2[i] != -1)
+ return 1;
+ if (ifnames1[i] == -1 && ifnames2[i] == -1 &&
+ strcmp(base1 + ifnames1[i], base2 + ifnames2[i]))
+ return 1;
+ }
+ return 0;
+}
+
+static int
+ipf_dest_compare(const frdest_t *d1, const frdest_t *d2,
+ const char *base1, const char *base2)
+{
+ if (memcmp(&d1->fd_addr, &d2->fd_addr,
+ offsetof(frdest_t, fd_name) - offsetof(frdest_t, fd_addr)) != 0)
+ return 1;
+ if (d1->fd_name != -1 && d2->fd_name == -1)
+ return 2;
+ if (d1->fd_name == -1 && d2->fd_name != -1)
+ return 3;
+ if (d1->fd_name != -1 && d2->fd_name != -1 &&
+ d1->fd_type == FRD_NORMAL &&
+ strcmp(base1 + d1->fd_name, base2 + d2->fd_name))
+ return 4;
+ return 0;
+}
/* ------------------------------------------------------------------------ */
/* Function: ipf_rule_compare */
@@ -4487,8 +4521,25 @@
return 2;
if (fr1->fr_dsize != fr2->fr_dsize)
return 3;
- if (bcmp((char *)&fr1->fr_func, (char *)&fr2->fr_func,
- fr1->fr_size - offsetof(struct frentry, fr_func)) != 0)
+ if (memcmp(&fr1->fr_func, &fr2->fr_func,
+ offsetof(struct frentry, fr_ifnames) -
+ offsetof(struct frentry, fr_func)) != 0)
+ return 4;
+ if (ipf_ifnames_compare(fr1->fr_ifnames, fr2->fr_ifnames,
+ fr1->fr_names, fr2->fr_names))
+ return 4;
+ if (memcmp(&fr1->fr_func, &fr2->fr_func,
+ offsetof(struct frentry, fr_tifs) -
+ offsetof(struct frentry, fr_isctag)) != 0)
+ return 4;
+ if (ipf_dest_compare(&fr1->fr_tifs[0], &fr2->fr_tifs[0],
+ fr1->fr_names, fr2->fr_names))
+ return 4;
+ if (ipf_dest_compare(&fr1->fr_tifs[1], &fr2->fr_tifs[1],
+ fr1->fr_names, fr2->fr_names))
+ return 4;
+ if (ipf_dest_compare(&fr1->fr_dif, &fr2->fr_dif,
+ fr1->fr_names, fr2->fr_names))
return 4;
if (fr1->fr_data && !fr2->fr_data)
return 5;
@@ -4971,12 +5022,25 @@
* the constant part of the filter rule to make comparisons quicker
* (this meaning no pointers are included).
*/
- for (fp->fr_cksum = 0, p = (u_int *)&fp->fr_func, pp = &fp->fr_cksum;
- p < pp; p++)
- fp->fr_cksum += *p;
+ fp->fr_cksum = 0;
+ p = (u_int *)&fp->fr_func;
+ pp = (u_int *)fp->fr_ifnames;
+ while(p < pp) fp->fr_cksum += *p++;
+ p = (u_int *)&fp->fr_isctag;
+ pp = (u_int *)fp->fr_tifs;
+ while(p < pp) fp->fr_cksum += *p++;
+ p = (u_int *)&fp->fr_tifs[0].fd_addr;
+ pp = (u_int *)&fp->fr_tifs[0].fd_name;
+ while(p < pp) fp->fr_cksum += *p++;
+ p = (u_int *)&fp->fr_tifs[1].fd_addr;
+ pp = (u_int *)&fp->fr_tifs[1].fd_name;
+ while(p < pp) fp->fr_cksum += *p++;
+ p = (u_int *)&fp->fr_dif.fd_addr;
+ pp = (u_int *)&fp->fr_dif.fd_name;
+ while(p < pp) fp->fr_cksum += *p++;
+ p = (u_int *)fp->fr_data;
pp = (u_int *)(fp->fr_caddr + fp->fr_dsize);
- for (p = (u_int *)fp->fr_data; p < pp; p++)
- fp->fr_cksum += *p;
+ while(p < pp) fp->fr_cksum += *p++;
WRITE_ENTER(&softc->ipf_mutex);