[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 [EMAIL PROTECTED] 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 */