[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 */

Reply via email to