[PATCH] Fix for iptables non-x86 + ipchains oops.

From: Rusty Russell (rusty@linuxcare.com.au)
Date: Fri May 12 2000 - 08:33:40 EST


Linus, please apply.

WARNING: this breaks the userland iptables tool. You need to 1.1.0
release (or CVS). This is neccessary for non-Intel, and it's better
to break cleanly NOW.

This also fixes the running ipchains on 2.4 kernel OOPS (check length
of structure).

Rusty.
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/Documentation/Changes working-pre7/Documentation/Changes
--- linux-2.3.99-pre7-official/Documentation/Changes Fri May 12 12:52:10 2000
+++ working-pre7/Documentation/Changes Fri May 12 15:56:07 2000
@@ -245,8 +245,7 @@
 features like IPv6.
 
    The IP firewalling and NAT code has been replaced again. The
-actual modules (including ipfwadm and ipchains backwards-compatibility
-modules) are currently distributed separately: see
+userspace tool `iptables' is distributed at:
         http://antarctica.penguincomputing.com/~netfilter/
         http://www.samba.org/netfilter/
         http://netfilter.kernelnotes.org
@@ -737,12 +736,13 @@
 The 2.4.0b1 release:
 ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0b1.tar.gz
 
-IP Chains
+iptables
 =========
 
-The 1.3.8 release:
-ftp://ftp.rustcorp.com/ipchains/ipchains-1.3.8.tar.gz
-ftp://ftp.rustcorp.com/ipchains/ipchains-1.3.8.tar.bz2
+The 1.1.0 release:
+http://antarctica.penguincomputing.com/~netfilter/iptables-1.1.0.tar.bz2
+http://www.samba.org/netfilter/iptables-1.1.0.tar.bz2
+http://netfilter.kernelnotes.org/iptables-1.1.0.tar.bz2
 
 IP Masq Adm
 ===========
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/include/linux/netfilter_ipv4/ip_tables.h working-pre7/include/linux/netfilter_ipv4/ip_tables.h
--- linux-2.3.99-pre7-official/include/linux/netfilter_ipv4/ip_tables.h Fri May 12 13:15:02 2000
+++ working-pre7/include/linux/netfilter_ipv4/ip_tables.h Fri May 12 15:56:07 2000
@@ -24,7 +24,7 @@
 #endif
 #include <linux/netfilter_ipv4.h>
 
-#define IPT_FUNCTION_MAXNAMELEN 32
+#define IPT_FUNCTION_MAXNAMELEN 30
 #define IPT_TABLE_MAXNAMELEN 32
 
 /* Yes, Virginia, you have to zero the padding. */
@@ -47,13 +47,22 @@
 
 struct ipt_entry_match
 {
- /* Total length */
- u_int16_t match_size;
         union {
- /* Used by userspace */
- char name[IPT_FUNCTION_MAXNAMELEN];
- /* Used inside the kernel */
- struct ipt_match *match;
+ struct {
+ u_int16_t match_size;
+
+ /* Used by userspace */
+ char name[IPT_FUNCTION_MAXNAMELEN];
+ } user;
+ struct {
+ u_int16_t match_size;
+
+ /* Used inside the kernel */
+ struct ipt_match *match;
+ } kernel;
+
+ /* Total length */
+ u_int16_t match_size;
         } u;
 
         unsigned char data[0];
@@ -61,13 +70,22 @@
 
 struct ipt_entry_target
 {
- /* Total length */
- u_int16_t target_size;
         union {
- /* Used by userspace */
- char name[IPT_FUNCTION_MAXNAMELEN];
- /* Used inside the kernel */
- struct ipt_target *target;
+ struct {
+ u_int16_t target_size;
+
+ /* Used by userspace */
+ char name[IPT_FUNCTION_MAXNAMELEN];
+ } user;
+ struct {
+ u_int16_t target_size;
+
+ /* Used inside the kernel */
+ struct ipt_target *target;
+ } kernel;
+
+ /* Total length */
+ u_int16_t target_size;
         } u;
 
         unsigned char data[0];
@@ -286,7 +304,7 @@
                                                 \
         for (__i = sizeof(struct ipt_entry); \
              __i < (e)->target_offset; \
- __i += __m->match_size) { \
+ __i += __m->u.match_size) { \
                 __m = (void *)(e) + __i; \
                                                 \
                 __ret = fn(__m , ## args); \
@@ -421,6 +439,6 @@
                                  struct ipt_table *table,
                                  void *userdata);
 
-#define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_match)-1)) & ~(__alignof__(struct ipt_match)-1))
+#define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1))
 #endif /*__KERNEL__*/
 #endif /* _IPTABLES_H */
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/net/ipv4/netfilter/ip_nat_rule.c working-pre7/net/ipv4/netfilter/ip_nat_rule.c
--- linux-2.3.99-pre7-official/net/ipv4/netfilter/ip_nat_rule.c Wed Apr 5 18:44:00 2000
+++ working-pre7/net/ipv4/netfilter/ip_nat_rule.c Fri May 12 15:56:07 2000
@@ -70,7 +70,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
                 -NF_ACCEPT - 1 } },
             /* POST_ROUTING */
             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
@@ -78,7 +78,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
                 -NF_ACCEPT - 1 } },
             /* LOCAL_OUT */
             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
@@ -86,7 +86,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
                 -NF_ACCEPT - 1 } }
     },
     /* ERROR */
@@ -95,7 +95,7 @@
         sizeof(struct ipt_entry),
         sizeof(struct ipt_error),
         0, { 0, 0 }, { } },
- { { sizeof(struct ipt_error_target), { IPT_ERROR_TARGET },
+ { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
           { } },
         "ERROR"
       }
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/net/ipv4/netfilter/ip_tables.c working-pre7/net/ipv4/netfilter/ip_tables.c
--- linux-2.3.99-pre7-official/net/ipv4/netfilter/ip_tables.c Fri May 12 12:52:38 2000
+++ working-pre7/net/ipv4/netfilter/ip_tables.c Fri May 12 15:58:20 2000
@@ -232,8 +232,8 @@
              int *hotdrop)
 {
         /* Stop iteration if it doesn't match */
- if (!m->u.match->match(skb, in, out, m->data,
- offset, hdr, datalen, hotdrop))
+ if (!m->u.kernel.match->match(skb, in, out, m->data,
+ offset, hdr, datalen, hotdrop))
                 return 1;
         else
                 return 0;
@@ -318,9 +318,9 @@
                         ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
 
                         t = ipt_get_target(e);
- IP_NF_ASSERT(t->u.target);
+ IP_NF_ASSERT(t->u.kernel.target);
                         /* Standard target? */
- if (!t->u.target->target) {
+ if (!t->u.kernel.target->target) {
                                 int v;
 
                                 v = ((struct ipt_standard_target *)t)->verdict;
@@ -354,17 +354,18 @@
                                 ((struct ipt_entry *)table_base)->comefrom
                                         = 0xeeeeeeec;
 #endif
- verdict = t->u.target->target(pskb, hook,
- in, out,
- t->data,
- userdata);
+ verdict = t->u.kernel.target->target(pskb,
+ hook,
+ in, out,
+ t->data,
+ userdata);
 
 #ifdef CONFIG_NETFILTER_DEBUG
                                 if (((struct ipt_entry *)table_base)->comefrom
                                     != 0xeeeeeeec
                                     && verdict == IPT_CONTINUE) {
                                         printk("Target %s reentered!\n",
- t->u.target->name);
+ t->u.kernel.target->name);
                                         verdict = NF_DROP;
                                 }
                                 ((struct ipt_entry *)table_base)->comefrom
@@ -521,8 +522,8 @@
 
                         /* Unconditional return/END. */
                         if (e->target_offset == sizeof(struct ipt_entry)
- && (strcmp(t->target.u.name, IPT_STANDARD_TARGET)
- == 0)
+ && (strcmp(t->target.u.user.name,
+ IPT_STANDARD_TARGET) == 0)
                             && t->verdict < 0
                             && unconditional(&e->ip)) {
                                 unsigned int oldpos, size;
@@ -561,7 +562,7 @@
                         } else {
                                 int newpos = t->verdict;
 
- if (strcmp(t->target.u.name,
+ if (strcmp(t->target.u.user.name,
                                            IPT_STANDARD_TARGET) == 0
                                     && newpos >= 0) {
                                         /* This a jump; chase it. */
@@ -589,11 +590,12 @@
         if (i && (*i)-- == 0)
                 return 1;
 
- if (m->u.match->destroy)
- m->u.match->destroy(m->data, m->match_size - sizeof(*m));
+ if (m->u.kernel.match->destroy)
+ m->u.kernel.match->destroy(m->data,
+ m->u.match_size - sizeof(*m));
 
- if (m->u.match->me)
- __MOD_DEC_USE_COUNT(m->u.match->me);
+ if (m->u.kernel.match->me)
+ __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
 
         return 0;
 }
@@ -605,9 +607,11 @@
         struct ipt_standard_target *targ = (void *)t;
 
         /* Check standard info. */
- if (t->target_size != sizeof(struct ipt_standard_target)) {
+ if (t->u.target_size
+ != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
                 duprintf("standard_check: target size %u != %u\n",
- t->target_size, sizeof(struct ipt_standard_target));
+ t->u.target_size,
+ IPT_ALIGN(sizeof(struct ipt_standard_target)));
                 return 0;
         }
 
@@ -636,24 +640,24 @@
         int ret;
         struct ipt_match *match;
 
- match = find_match_lock(m->u.name, &ret, &ipt_mutex);
+ match = find_match_lock(m->u.user.name, &ret, &ipt_mutex);
         if (!match) {
                 duprintf("check_match: `%s' not found\n", m->u.name);
                 return ret;
         }
         if (match->me)
                 __MOD_INC_USE_COUNT(match->me);
- m->u.match = match;
+ m->u.kernel.match = match;
         up(&ipt_mutex);
 
- if (m->u.match->checkentry
- && !m->u.match->checkentry(name, ip, m->data,
- m->match_size - sizeof(*m),
- hookmask)) {
- if (m->u.match->me)
- __MOD_DEC_USE_COUNT(m->u.match->me);
+ if (m->u.kernel.match->checkentry
+ && !m->u.kernel.match->checkentry(name, ip, m->data,
+ m->u.match_size - sizeof(*m),
+ hookmask)) {
+ if (m->u.kernel.match->me)
+ __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
                 duprintf("ip_tables: check failed for `%s'.\n",
- m->u.match->name);
+ m->u.kernel.match->name);
                 return -EINVAL;
         }
 
@@ -683,29 +687,30 @@
                 goto cleanup_matches;
 
         t = ipt_get_target(e);
- target = find_target_lock(t->u.name, &ret, &ipt_mutex);
+ target = find_target_lock(t->u.user.name, &ret, &ipt_mutex);
         if (!target) {
                 duprintf("check_entry: `%s' not found\n", t->u.name);
                 return ret;
         }
         if (target->me)
                 __MOD_INC_USE_COUNT(target->me);
- t->u.target = target;
+ t->u.kernel.target = target;
         up(&ipt_mutex);
 
- if (t->u.target == &ipt_standard_target) {
+ if (t->u.kernel.target == &ipt_standard_target) {
                 if (!standard_check(t, size)) {
                         ret = -EINVAL;
                         goto cleanup_matches;
                 }
- } else if (t->u.target->checkentry
- && !t->u.target->checkentry(name, e, t->data,
- t->target_size - sizeof(*t),
- e->comefrom)) {
- if (t->u.target->me)
- __MOD_DEC_USE_COUNT(t->u.target->me);
+ } else if (t->u.kernel.target->checkentry
+ && !t->u.kernel.target->checkentry(name, e, t->data,
+ t->u.target_size
+ - sizeof(*t),
+ e->comefrom)) {
+ if (t->u.kernel.target->me)
+ __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
                 duprintf("ip_tables: check failed for `%s'.\n",
- t->u.target->name);
+ t->u.kernel.target->name);
                 ret = -EINVAL;
                 goto cleanup_matches;
         }
@@ -772,10 +777,11 @@
         /* Cleanup all matches */
         IPT_MATCH_ITERATE(e, cleanup_match, NULL);
         t = ipt_get_target(e);
- if (t->u.target->destroy)
- t->u.target->destroy(t->data, t->target_size - sizeof(*t));
- if (t->u.target->me)
- __MOD_DEC_USE_COUNT(t->u.target->me);
+ if (t->u.kernel.target->destroy)
+ t->u.kernel.target->destroy(t->data,
+ t->u.target_size - sizeof(*t));
+ if (t->u.kernel.target->me)
+ __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
 
         return 0;
 }
@@ -980,14 +986,15 @@
 
                 for (i = sizeof(struct ipt_entry);
                      i < e->target_offset;
- i += m->match_size) {
+ i += m->u.match_size) {
                         m = (void *)e + i;
 
                         if (copy_to_user(userptr + off + i
                                          + offsetof(struct ipt_entry_match,
- u.name),
- m->u.match->name,
- strlen(m->u.match->name)+1) != 0) {
+ u.user.name),
+ m->u.kernel.match->name,
+ strlen(m->u.kernel.match->name)+1)
+ != 0) {
                                 ret = -EFAULT;
                                 goto free_counters;
                         }
@@ -996,9 +1003,9 @@
                 t = ipt_get_target(e);
                 if (copy_to_user(userptr + off + e->target_offset
                                  + offsetof(struct ipt_entry_target,
- u.name),
- t->u.target->name,
- strlen(t->u.target->name)+1) != 0) {
+ u.user.name),
+ t->u.kernel.target->name,
+ strlen(t->u.kernel.target->name)+1) != 0) {
                         ret = -EFAULT;
                         goto free_counters;
                 }
@@ -1048,6 +1055,10 @@
 
         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
                 return -EFAULT;
+
+ /* Hack: Causes ipchains to give correct error msg --RR */
+ if (len != sizeof(tmp) + tmp.size)
+ return -ENOPROTOOPT;
 
         newinfo = vmalloc(sizeof(struct ipt_table_info)
                           + SMP_ALIGN(tmp.size) * smp_num_cpus);
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/net/ipv4/netfilter/ipt_REJECT.c working-pre7/net/ipv4/netfilter/ipt_REJECT.c
--- linux-2.3.99-pre7-official/net/ipv4/netfilter/ipt_REJECT.c Fri May 12 12:52:38 2000
+++ working-pre7/net/ipv4/netfilter/ipt_REJECT.c Fri May 12 15:56:07 2000
@@ -73,7 +73,7 @@
 {
         const struct ipt_icmp *icmpinfo = (const struct ipt_icmp *)m->data;
 
- if (strcmp(m->u.match->name, "icmp") == 0
+ if (strcmp(m->u.kernel.match->name, "icmp") == 0
             && icmpinfo->type == ICMP_ECHO
             && !(icmpinfo->invflags & IPT_ICMP_INV))
                 return 1;
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/net/ipv4/netfilter/ipt_owner.c working-pre7/net/ipv4/netfilter/ipt_owner.c
--- linux-2.3.99-pre7-official/net/ipv4/netfilter/ipt_owner.c Fri May 12 12:52:38 2000
+++ working-pre7/net/ipv4/netfilter/ipt_owner.c Fri May 12 15:51:33 2000
@@ -21,7 +21,8 @@
         p = find_task_by_pid(pid);
         if(p && p->files) {
                 for (i=0; i < p->files->max_fds; i++) {
- if (fcheck_task(p, i) == skb->sk->socket->file) {
+ if (fcheck_files(p->files, i)
+ == skb->sk->socket->file) {
                                 read_unlock(&tasklist_lock);
                                 return 1;
                         }
@@ -43,7 +44,8 @@
                         continue;
 
                 for (i=0; i < p->files->max_fds; i++) {
- if (fcheck_task(p, i) == skb->sk->socket->file) {
+ if (fcheck_files(p->files, i)
+ == skb->sk->socket->file) {
                                 found = 1;
                                 break;
                         }
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/net/ipv4/netfilter/iptable_filter.c working-pre7/net/ipv4/netfilter/iptable_filter.c
--- linux-2.3.99-pre7-official/net/ipv4/netfilter/iptable_filter.c Fri May 12 12:52:38 2000
+++ working-pre7/net/ipv4/netfilter/iptable_filter.c Fri May 12 15:56:07 2000
@@ -49,7 +49,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
                 -NF_ACCEPT - 1 } },
             /* FORWARD */
             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
@@ -57,7 +57,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
                 -NF_ACCEPT - 1 } },
             /* LOCAL_OUT */
             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
@@ -65,7 +65,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
                 -NF_ACCEPT - 1 } }
     },
     /* ERROR */
@@ -74,7 +74,7 @@
         sizeof(struct ipt_entry),
         sizeof(struct ipt_error),
         0, { 0, 0 }, { } },
- { { sizeof(struct ipt_error_target), { IPT_ERROR_TARGET },
+ { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
           { } },
         "ERROR"
       }
diff -urN -X /tmp/fileQlnund --minimal linux-2.3.99-pre7-official/net/ipv4/netfilter/iptable_mangle.c working-pre7/net/ipv4/netfilter/iptable_mangle.c
--- linux-2.3.99-pre7-official/net/ipv4/netfilter/iptable_mangle.c Wed Apr 5 18:44:00 2000
+++ working-pre7/net/ipv4/netfilter/iptable_mangle.c Fri May 12 15:56:07 2000
@@ -47,7 +47,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { sizeof(struct ipt_standard_target), "" } }, { } },
                 -NF_ACCEPT - 1 } },
             /* LOCAL_OUT */
             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
@@ -55,7 +55,7 @@
                 sizeof(struct ipt_entry),
                 sizeof(struct ipt_standard),
                 0, { 0, 0 }, { } },
- { { sizeof(struct ipt_standard_target), { "" }, { } },
+ { { { { sizeof(struct ipt_standard_target), "" } }, { } },
                 -NF_ACCEPT - 1 } }
     },
     /* ERROR */
@@ -64,7 +64,7 @@
         sizeof(struct ipt_entry),
         sizeof(struct ipt_error),
         0, { 0, 0 }, { } },
- { { sizeof(struct ipt_error_target), { IPT_ERROR_TARGET },
+ { { { { sizeof(struct ipt_error_target), IPT_ERROR_TARGET } },
           { } },
         "ERROR"
       }

--
Hacking time.

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon May 15 2000 - 21:00:20 EST