[PATCH] Fix oops on bad entry list

Andrew Church achurch@achurch.org
Wed, 19 Jun 2002 09:57:31 JST


[Note: I am not subscribed to netfilter-devel; please CC me on any replies]

     The patch below fixes an oops that occurs in Linux kernels
<= 2.4.19-pre10 if an entry list passed to IPT_SO_SET_REPLACE contains an
entry with a jump to an invalid position (into the middle of another entry
or outside the list).

  --Andrew Church
    achurch@achurch.org
    http://achurch.org/

--- net/ipv4/netfilter/ip_tables.c.old	Fri Jun  7 11:50:39 2002
+++ net/ipv4/netfilter/ip_tables.c	Wed Jun 19 09:49:01 2002
@@ -739,6 +739,7 @@
 			   unsigned int *i)
 {
 	unsigned int h;
+	struct ipt_standard_target *t;
 
 	if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
 	    || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
@@ -751,6 +752,35 @@
 		duprintf("checking: element %p size %u\n",
 			 e, e->next_offset);
 		return -EINVAL;
+	}
+
+	if (e->target_offset + sizeof(struct ipt_entry_target)
+	    >= e->next_offset) {
+		duprintf("checking: element %p size %u target %u\n",
+			 e, e->next_offset, e->target_offset);
+		return -EINVAL;
+	}
+
+	/* If the target is another chain, make sure the pointer is valid */
+	t = (void *)ipt_get_target(e);
+	if (strcmp(t->target.u.user.name, IPT_STANDARD_TARGET) == 0
+	    && t->verdict >= 0) {
+		int checkpos = 0;
+		if (t->verdict >= newinfo->size) {
+			duprintf("checking: element %p: jump target %u"
+				 " out of range", e, t->verdict);
+			return -EINVAL;
+		}
+		while (checkpos < t->verdict) {
+			struct ipt_entry *e2;
+			e2 = (void *)newinfo->entries + checkpos;
+			checkpos += e2->next_offset;
+		}
+		if (checkpos > t->verdict) {
+			duprintf("checking: element %p: jump target %u"
+				 " invalid", e, t->verdict);
+			return -EINVAL;
+		}
 	}
 
 	/* Check hooks & underflows */