aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-12-05 09:37:56 -0500
committerDavid Howells <dhowells@warthog.cambridge.redhat.com>2006-12-05 09:37:56 -0500
commit4c1ac1b49122b805adfa4efc620592f68dccf5db (patch)
tree87557f4bc2fd4fe65b7570489c2f610c45c0adcd /net/bridge
parentc4028958b6ecad064b1a6303a6a5906d4fe48d73 (diff)
parentd916faace3efc0bf19fe9a615a1ab8fa1a24cd93 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/infiniband/core/iwcm.c drivers/net/chelsio/cxgb2.c drivers/net/wireless/bcm43xx/bcm43xx_main.c drivers/net/wireless/prism54/islpci_eth.c drivers/usb/core/hub.h drivers/usb/input/hid-core.c net/core/netpoll.c Fix up merge failures with Linus's head and fix new compilation failures. Signed-Off-By: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_ioctl.c9
-rw-r--r--net/bridge/br_netfilter.c3
-rw-r--r--net/bridge/br_netlink.c113
-rw-r--r--net/bridge/netfilter/ebt_802_3.c2
-rw-r--r--net/bridge/netfilter/ebt_among.c22
-rw-r--r--net/bridge/netfilter/ebt_arp.c6
-rw-r--r--net/bridge/netfilter/ebt_ip.c4
-rw-r--r--net/bridge/netfilter/ebt_log.c6
-rw-r--r--net/bridge/netfilter/ebt_mark.c14
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c4
-rw-r--r--net/bridge/netfilter/ebt_snat.c27
-rw-r--r--net/bridge/netfilter/ebt_ulog.c2
-rw-r--r--net/bridge/netfilter/ebt_vlan.c2
-rw-r--r--net/bridge/netfilter/ebtable_broute.c2
-rw-r--r--net/bridge/netfilter/ebtable_filter.c2
-rw-r--r--net/bridge/netfilter/ebtable_nat.c2
-rw-r--r--net/bridge/netfilter/ebtables.c222
17 files changed, 250 insertions, 192 deletions
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 4e4119a12139..4c61a7e0a86e 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -58,12 +58,13 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
58{ 58{
59 int num; 59 int num;
60 void *buf; 60 void *buf;
61 size_t size = maxnum * sizeof(struct __fdb_entry); 61 size_t size;
62 62
63 if (size > PAGE_SIZE) { 63 /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
64 size = PAGE_SIZE; 64 if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
65 maxnum = PAGE_SIZE/sizeof(struct __fdb_entry); 65 maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
66 } 66
67 size = maxnum * sizeof(struct __fdb_entry);
67 68
68 buf = kmalloc(size, GFP_USER); 69 buf = kmalloc(size, GFP_USER);
69 if (!buf) 70 if (!buf)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index ac181be13d83..ac47ba2ba028 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -40,7 +40,6 @@
40#include <net/route.h> 40#include <net/route.h>
41 41
42#include <asm/uaccess.h> 42#include <asm/uaccess.h>
43#include <asm/checksum.h>
44#include "br_private.h" 43#include "br_private.h"
45#ifdef CONFIG_SYSCTL 44#ifdef CONFIG_SYSCTL
46#include <linux/sysctl.h> 45#include <linux/sysctl.h>
@@ -381,7 +380,7 @@ static int check_hbh_len(struct sk_buff *skb)
381 case IPV6_TLV_JUMBO: 380 case IPV6_TLV_JUMBO:
382 if (skb->nh.raw[off + 1] != 4 || (off & 3) != 2) 381 if (skb->nh.raw[off + 1] != 4 || (off & 3) != 2)
383 goto bad; 382 goto bad;
384 pkt_len = ntohl(*(u32 *) (skb->nh.raw + off + 2)); 383 pkt_len = ntohl(*(__be32 *) (skb->nh.raw + off + 2));
385 if (pkt_len <= IPV6_MAXPLEN || 384 if (pkt_len <= IPV6_MAXPLEN ||
386 skb->nh.ipv6h->payload_len) 385 skb->nh.ipv6h->payload_len)
387 goto bad; 386 goto bad;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 8f661195d09d..a9139682c49b 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -15,6 +15,18 @@
15#include <net/netlink.h> 15#include <net/netlink.h>
16#include "br_private.h" 16#include "br_private.h"
17 17
18static inline size_t br_nlmsg_size(void)
19{
20 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
21 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
22 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
23 + nla_total_size(4) /* IFLA_MASTER */
24 + nla_total_size(4) /* IFLA_MTU */
25 + nla_total_size(4) /* IFLA_LINK */
26 + nla_total_size(1) /* IFLA_OPERSTATE */
27 + nla_total_size(1); /* IFLA_PROTINFO */
28}
29
18/* 30/*
19 * Create one netlink message for one interface 31 * Create one netlink message for one interface
20 * Contains port and master info as well as carrier and bridge state. 32 * Contains port and master info as well as carrier and bridge state.
@@ -24,51 +36,43 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
24{ 36{
25 const struct net_bridge *br = port->br; 37 const struct net_bridge *br = port->br;
26 const struct net_device *dev = port->dev; 38 const struct net_device *dev = port->dev;
27 struct ifinfomsg *r; 39 struct ifinfomsg *hdr;
28 struct nlmsghdr *nlh; 40 struct nlmsghdr *nlh;
29 unsigned char *b = skb->tail;
30 u32 mtu = dev->mtu;
31 u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; 41 u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
32 u8 portstate = port->state;
33 42
34 pr_debug("br_fill_info event %d port %s master %s\n", 43 pr_debug("br_fill_info event %d port %s master %s\n",
35 event, dev->name, br->dev->name); 44 event, dev->name, br->dev->name);
36 45
37 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); 46 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
38 r = NLMSG_DATA(nlh); 47 if (nlh == NULL)
39 r->ifi_family = AF_BRIDGE; 48 return -ENOBUFS;
40 r->__ifi_pad = 0;
41 r->ifi_type = dev->type;
42 r->ifi_index = dev->ifindex;
43 r->ifi_flags = dev_get_flags(dev);
44 r->ifi_change = 0;
45 49
46 RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); 50 hdr = nlmsg_data(nlh);
51 hdr->ifi_family = AF_BRIDGE;
52 hdr->__ifi_pad = 0;
53 hdr->ifi_type = dev->type;
54 hdr->ifi_index = dev->ifindex;
55 hdr->ifi_flags = dev_get_flags(dev);
56 hdr->ifi_change = 0;
47 57
48 RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex); 58 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
59 NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex);
60 NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
61 NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate);
49 62
50 if (dev->addr_len) 63 if (dev->addr_len)
51 RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); 64 NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
52 65
53 RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
54 if (dev->ifindex != dev->iflink) 66 if (dev->ifindex != dev->iflink)
55 RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); 67 NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
56
57
58 RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
59 68
60 if (event == RTM_NEWLINK) 69 if (event == RTM_NEWLINK)
61 RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate); 70 NLA_PUT_U8(skb, IFLA_PROTINFO, port->state);
62
63 nlh->nlmsg_len = skb->tail - b;
64
65 return skb->len;
66 71
67nlmsg_failure: 72 return nlmsg_end(skb, nlh);
68rtattr_failure:
69 73
70 skb_trim(skb, b - skb->data); 74nla_put_failure:
71 return -EINVAL; 75 return nlmsg_cancel(skb, nlh);
72} 76}
73 77
74/* 78/*
@@ -77,19 +81,16 @@ rtattr_failure:
77void br_ifinfo_notify(int event, struct net_bridge_port *port) 81void br_ifinfo_notify(int event, struct net_bridge_port *port)
78{ 82{
79 struct sk_buff *skb; 83 struct sk_buff *skb;
80 int payload = sizeof(struct ifinfomsg) + 128;
81 int err = -ENOBUFS; 84 int err = -ENOBUFS;
82 85
83 pr_debug("bridge notify event=%d\n", event); 86 pr_debug("bridge notify event=%d\n", event);
84 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); 87 skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC);
85 if (skb == NULL) 88 if (skb == NULL)
86 goto errout; 89 goto errout;
87 90
88 err = br_fill_ifinfo(skb, port, 0, 0, event, 0); 91 err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
89 if (err < 0) { 92 /* failure implies BUG in br_nlmsg_size() */
90 kfree_skb(skb); 93 BUG_ON(err < 0);
91 goto errout;
92 }
93 94
94 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 95 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
95errout: 96errout:
@@ -104,25 +105,18 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
104{ 105{
105 struct net_device *dev; 106 struct net_device *dev;
106 int idx; 107 int idx;
107 int s_idx = cb->args[0];
108 int err = 0;
109 108
110 read_lock(&dev_base_lock); 109 read_lock(&dev_base_lock);
111 for (dev = dev_base, idx = 0; dev; dev = dev->next) { 110 for (dev = dev_base, idx = 0; dev; dev = dev->next) {
112 struct net_bridge_port *p = dev->br_port;
113
114 /* not a bridge port */ 111 /* not a bridge port */
115 if (!p) 112 if (dev->br_port == NULL || idx < cb->args[0])
116 continue; 113 goto skip;
117
118 if (idx < s_idx)
119 goto cont;
120 114
121 err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid, 115 if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid,
122 cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI); 116 cb->nlh->nlmsg_seq, RTM_NEWLINK,
123 if (err <= 0) 117 NLM_F_MULTI) < 0)
124 break; 118 break;
125cont: 119skip:
126 ++idx; 120 ++idx;
127 } 121 }
128 read_unlock(&dev_base_lock); 122 read_unlock(&dev_base_lock);
@@ -138,26 +132,27 @@ cont:
138 */ 132 */
139static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 133static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
140{ 134{
141 struct rtattr **rta = arg; 135 struct ifinfomsg *ifm;
142 struct ifinfomsg *ifm = NLMSG_DATA(nlh); 136 struct nlattr *protinfo;
143 struct net_device *dev; 137 struct net_device *dev;
144 struct net_bridge_port *p; 138 struct net_bridge_port *p;
145 u8 new_state; 139 u8 new_state;
146 140
141 if (nlmsg_len(nlh) < sizeof(*ifm))
142 return -EINVAL;
143
144 ifm = nlmsg_data(nlh);
147 if (ifm->ifi_family != AF_BRIDGE) 145 if (ifm->ifi_family != AF_BRIDGE)
148 return -EPFNOSUPPORT; 146 return -EPFNOSUPPORT;
149 147
150 /* Must pass valid state as PROTINFO */ 148 protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
151 if (rta[IFLA_PROTINFO-1]) { 149 if (!protinfo || nla_len(protinfo) < sizeof(u8))
152 u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
153 new_state = *pstate;
154 } else
155 return -EINVAL; 150 return -EINVAL;
156 151
152 new_state = nla_get_u8(protinfo);
157 if (new_state > BR_STATE_BLOCKING) 153 if (new_state > BR_STATE_BLOCKING)
158 return -EINVAL; 154 return -EINVAL;
159 155
160 /* Find bridge port */
161 dev = __dev_get_by_index(ifm->ifi_index); 156 dev = __dev_get_by_index(ifm->ifi_index);
162 if (!dev) 157 if (!dev)
163 return -ENODEV; 158 return -ENODEV;
@@ -170,10 +165,8 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
170 if (p->br->stp_enabled) 165 if (p->br->stp_enabled)
171 return -EBUSY; 166 return -EBUSY;
172 167
173 if (!netif_running(dev)) 168 if (!netif_running(dev) ||
174 return -ENETDOWN; 169 (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED))
175
176 if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
177 return -ENETDOWN; 170 return -ENETDOWN;
178 171
179 p->state = new_state; 172 p->state = new_state;
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index d42f63f5e9f8..9abbc09ccdc3 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -17,7 +17,7 @@ static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *
17{ 17{
18 struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; 18 struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
19 struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb); 19 struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
20 uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; 20 __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
21 21
22 if (info->bitmask & EBT_802_3_SAP) { 22 if (info->bitmask & EBT_802_3_SAP) {
23 if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP)) 23 if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP))
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index a614485828af..ce97c4285f9a 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -15,7 +15,7 @@
15#include <linux/module.h> 15#include <linux/module.h>
16 16
17static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh, 17static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
18 const char *mac, uint32_t ip) 18 const char *mac, __be32 ip)
19{ 19{
20 /* You may be puzzled as to how this code works. 20 /* You may be puzzled as to how this code works.
21 * Some tricks were used, refer to 21 * Some tricks were used, refer to
@@ -70,7 +70,7 @@ static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
70 return 0; 70 return 0;
71} 71}
72 72
73static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr) 73static int get_ip_dst(const struct sk_buff *skb, __be32 *addr)
74{ 74{
75 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { 75 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
76 struct iphdr _iph, *ih; 76 struct iphdr _iph, *ih;
@@ -81,16 +81,16 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
81 *addr = ih->daddr; 81 *addr = ih->daddr;
82 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { 82 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
83 struct arphdr _arph, *ah; 83 struct arphdr _arph, *ah;
84 uint32_t buf, *bp; 84 __be32 buf, *bp;
85 85
86 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); 86 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
87 if (ah == NULL || 87 if (ah == NULL ||
88 ah->ar_pln != sizeof(uint32_t) || 88 ah->ar_pln != sizeof(__be32) ||
89 ah->ar_hln != ETH_ALEN) 89 ah->ar_hln != ETH_ALEN)
90 return -1; 90 return -1;
91 bp = skb_header_pointer(skb, sizeof(struct arphdr) + 91 bp = skb_header_pointer(skb, sizeof(struct arphdr) +
92 2 * ETH_ALEN + sizeof(uint32_t), 92 2 * ETH_ALEN + sizeof(__be32),
93 sizeof(uint32_t), &buf); 93 sizeof(__be32), &buf);
94 if (bp == NULL) 94 if (bp == NULL)
95 return -1; 95 return -1;
96 *addr = *bp; 96 *addr = *bp;
@@ -98,7 +98,7 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
98 return 0; 98 return 0;
99} 99}
100 100
101static int get_ip_src(const struct sk_buff *skb, uint32_t *addr) 101static int get_ip_src(const struct sk_buff *skb, __be32 *addr)
102{ 102{
103 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { 103 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
104 struct iphdr _iph, *ih; 104 struct iphdr _iph, *ih;
@@ -109,15 +109,15 @@ static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
109 *addr = ih->saddr; 109 *addr = ih->saddr;
110 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { 110 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
111 struct arphdr _arph, *ah; 111 struct arphdr _arph, *ah;
112 uint32_t buf, *bp; 112 __be32 buf, *bp;
113 113
114 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); 114 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
115 if (ah == NULL || 115 if (ah == NULL ||
116 ah->ar_pln != sizeof(uint32_t) || 116 ah->ar_pln != sizeof(__be32) ||
117 ah->ar_hln != ETH_ALEN) 117 ah->ar_hln != ETH_ALEN)
118 return -1; 118 return -1;
119 bp = skb_header_pointer(skb, sizeof(struct arphdr) + 119 bp = skb_header_pointer(skb, sizeof(struct arphdr) +
120 ETH_ALEN, sizeof(uint32_t), &buf); 120 ETH_ALEN, sizeof(__be32), &buf);
121 if (bp == NULL) 121 if (bp == NULL)
122 return -1; 122 return -1;
123 *addr = *bp; 123 *addr = *bp;
@@ -133,7 +133,7 @@ static int ebt_filter_among(const struct sk_buff *skb,
133 struct ebt_among_info *info = (struct ebt_among_info *) data; 133 struct ebt_among_info *info = (struct ebt_among_info *) data;
134 const char *dmac, *smac; 134 const char *dmac, *smac;
135 const struct ebt_mac_wormhash *wh_dst, *wh_src; 135 const struct ebt_mac_wormhash *wh_dst, *wh_src;
136 uint32_t dip = 0, sip = 0; 136 __be32 dip = 0, sip = 0;
137 137
138 wh_dst = ebt_among_wh_dst(info); 138 wh_dst = ebt_among_wh_dst(info);
139 wh_src = ebt_among_wh_src(info); 139 wh_src = ebt_among_wh_src(info);
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index a6c81d9f73b8..9c599800a900 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -35,10 +35,10 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
35 return EBT_NOMATCH; 35 return EBT_NOMATCH;
36 36
37 if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) { 37 if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
38 uint32_t _addr, *ap; 38 __be32 _addr, *ap;
39 39
40 /* IPv4 addresses are always 4 bytes */ 40 /* IPv4 addresses are always 4 bytes */
41 if (ah->ar_pln != sizeof(uint32_t)) 41 if (ah->ar_pln != sizeof(__be32))
42 return EBT_NOMATCH; 42 return EBT_NOMATCH;
43 if (info->bitmask & EBT_ARP_SRC_IP) { 43 if (info->bitmask & EBT_ARP_SRC_IP) {
44 ap = skb_header_pointer(skb, sizeof(struct arphdr) + 44 ap = skb_header_pointer(skb, sizeof(struct arphdr) +
@@ -53,7 +53,7 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
53 53
54 if (info->bitmask & EBT_ARP_DST_IP) { 54 if (info->bitmask & EBT_ARP_DST_IP) {
55 ap = skb_header_pointer(skb, sizeof(struct arphdr) + 55 ap = skb_header_pointer(skb, sizeof(struct arphdr) +
56 2*ah->ar_hln+sizeof(uint32_t), 56 2*ah->ar_hln+sizeof(__be32),
57 sizeof(_addr), &_addr); 57 sizeof(_addr), &_addr);
58 if (ap == NULL) 58 if (ap == NULL)
59 return EBT_NOMATCH; 59 return EBT_NOMATCH;
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index 65b665ce57b5..e4c642448e1b 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -20,8 +20,8 @@
20#include <linux/module.h> 20#include <linux/module.h>
21 21
22struct tcpudphdr { 22struct tcpudphdr {
23 uint16_t src; 23 __be16 src;
24 uint16_t dst; 24 __be16 dst;
25}; 25};
26 26
27static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, 27static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 466ed3440b74..a184f879f253 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -38,8 +38,8 @@ static int ebt_log_check(const char *tablename, unsigned int hookmask,
38 38
39struct tcpudphdr 39struct tcpudphdr
40{ 40{
41 uint16_t src; 41 __be16 src;
42 uint16_t dst; 42 __be16 dst;
43}; 43};
44 44
45struct arppayload 45struct arppayload
@@ -130,7 +130,7 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum,
130 * then log the ARP payload */ 130 * then log the ARP payload */
131 if (ah->ar_hrd == htons(1) && 131 if (ah->ar_hrd == htons(1) &&
132 ah->ar_hln == ETH_ALEN && 132 ah->ar_hln == ETH_ALEN &&
133 ah->ar_pln == sizeof(uint32_t)) { 133 ah->ar_pln == sizeof(__be32)) {
134 struct arppayload _arpp, *ap; 134 struct arppayload _arpp, *ap;
135 135
136 ap = skb_header_pointer(skb, sizeof(_arph), 136 ap = skb_header_pointer(skb, sizeof(_arph),
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index b54306a934e5..62d23c7b25e6 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -25,15 +25,15 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
25 int action = info->target & -16; 25 int action = info->target & -16;
26 26
27 if (action == MARK_SET_VALUE) 27 if (action == MARK_SET_VALUE)
28 (*pskb)->nfmark = info->mark; 28 (*pskb)->mark = info->mark;
29 else if (action == MARK_OR_VALUE) 29 else if (action == MARK_OR_VALUE)
30 (*pskb)->nfmark |= info->mark; 30 (*pskb)->mark |= info->mark;
31 else if (action == MARK_AND_VALUE) 31 else if (action == MARK_AND_VALUE)
32 (*pskb)->nfmark &= info->mark; 32 (*pskb)->mark &= info->mark;
33 else 33 else
34 (*pskb)->nfmark ^= info->mark; 34 (*pskb)->mark ^= info->mark;
35 35
36 return info->target | -16; 36 return info->target | ~EBT_VERDICT_BITS;
37} 37}
38 38
39static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, 39static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
@@ -44,13 +44,13 @@ static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
44 44
45 if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) 45 if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
46 return -EINVAL; 46 return -EINVAL;
47 tmp = info->target | -16; 47 tmp = info->target | ~EBT_VERDICT_BITS;
48 if (BASE_CHAIN && tmp == EBT_RETURN) 48 if (BASE_CHAIN && tmp == EBT_RETURN)
49 return -EINVAL; 49 return -EINVAL;
50 CLEAR_BASE_CHAIN_BIT; 50 CLEAR_BASE_CHAIN_BIT;
51 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 51 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
52 return -EINVAL; 52 return -EINVAL;
53 tmp = info->target & -16; 53 tmp = info->target & ~EBT_VERDICT_BITS;
54 if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && 54 if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
55 tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) 55 tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
56 return -EINVAL; 56 return -EINVAL;
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index a6413e4b4982..025869ee0b68 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -19,8 +19,8 @@ static int ebt_filter_mark(const struct sk_buff *skb,
19 struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; 19 struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
20 20
21 if (info->bitmask & EBT_MARK_OR) 21 if (info->bitmask & EBT_MARK_OR)
22 return !(!!(skb->nfmark & info->mask) ^ info->invert); 22 return !(!!(skb->mark & info->mask) ^ info->invert);
23 return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert); 23 return !(((skb->mark & info->mask) == info->mark) ^ info->invert);
24} 24}
25 25
26static int ebt_mark_check(const char *tablename, unsigned int hookmask, 26static int ebt_mark_check(const char *tablename, unsigned int hookmask,
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index cbb33e24ca8a..a50722182bfe 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -12,6 +12,8 @@
12#include <linux/netfilter_bridge/ebt_nat.h> 12#include <linux/netfilter_bridge/ebt_nat.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <net/sock.h> 14#include <net/sock.h>
15#include <linux/if_arp.h>
16#include <net/arp.h>
15 17
16static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, 18static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
17 const struct net_device *in, const struct net_device *out, 19 const struct net_device *in, const struct net_device *out,
@@ -31,24 +33,43 @@ static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
31 *pskb = nskb; 33 *pskb = nskb;
32 } 34 }
33 memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN); 35 memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
34 return info->target; 36 if (!(info->target & NAT_ARP_BIT) &&
37 eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
38 struct arphdr _ah, *ap;
39
40 ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
41 if (ap == NULL)
42 return EBT_DROP;
43 if (ap->ar_hln != ETH_ALEN)
44 goto out;
45 if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
46 return EBT_DROP;
47 }
48out:
49 return info->target | ~EBT_VERDICT_BITS;
35} 50}
36 51
37static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, 52static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
38 const struct ebt_entry *e, void *data, unsigned int datalen) 53 const struct ebt_entry *e, void *data, unsigned int datalen)
39{ 54{
40 struct ebt_nat_info *info = (struct ebt_nat_info *) data; 55 struct ebt_nat_info *info = (struct ebt_nat_info *) data;
56 int tmp;
41 57
42 if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) 58 if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
43 return -EINVAL; 59 return -EINVAL;
44 if (BASE_CHAIN && info->target == EBT_RETURN) 60 tmp = info->target | ~EBT_VERDICT_BITS;
61 if (BASE_CHAIN && tmp == EBT_RETURN)
45 return -EINVAL; 62 return -EINVAL;
46 CLEAR_BASE_CHAIN_BIT; 63 CLEAR_BASE_CHAIN_BIT;
47 if (strcmp(tablename, "nat")) 64 if (strcmp(tablename, "nat"))
48 return -EINVAL; 65 return -EINVAL;
49 if (hookmask & ~(1 << NF_BR_POST_ROUTING)) 66 if (hookmask & ~(1 << NF_BR_POST_ROUTING))
50 return -EINVAL; 67 return -EINVAL;
51 if (INVALID_TARGET) 68
69 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
70 return -EINVAL;
71 tmp = info->target | EBT_VERDICT_BITS;
72 if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
52 return -EINVAL; 73 return -EINVAL;
53 return 0; 74 return 0;
54} 75}
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 9f950db3b76f..c1af68b5a29c 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -168,7 +168,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
168 if (ub->qlen == 1) 168 if (ub->qlen == 1)
169 skb_set_timestamp(ub->skb, &pm->stamp); 169 skb_set_timestamp(ub->skb, &pm->stamp);
170 pm->data_len = copy_len; 170 pm->data_len = copy_len;
171 pm->mark = skb->nfmark; 171 pm->mark = skb->mark;
172 pm->hook = hooknr; 172 pm->hook = hooknr;
173 if (uloginfo->prefix != NULL) 173 if (uloginfo->prefix != NULL)
174 strcpy(pm->prefix, uloginfo->prefix); 174 strcpy(pm->prefix, uloginfo->prefix);
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index a2b452862b73..7ee377622964 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -55,7 +55,7 @@ ebt_filter_vlan(const struct sk_buff *skb,
55 unsigned short id; /* VLAN ID, given from frame TCI */ 55 unsigned short id; /* VLAN ID, given from frame TCI */
56 unsigned char prio; /* user_priority, given from frame TCI */ 56 unsigned char prio; /* user_priority, given from frame TCI */
57 /* VLAN encapsulated Type/Length field, given from orig frame */ 57 /* VLAN encapsulated Type/Length field, given from orig frame */
58 unsigned short encap; 58 __be16 encap;
59 59
60 fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame); 60 fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
61 if (fp == NULL) 61 if (fp == NULL)
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 9a6e548e148b..d37ce0478938 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -23,7 +23,7 @@ static struct ebt_entries initial_chain = {
23 .policy = EBT_ACCEPT, 23 .policy = EBT_ACCEPT,
24}; 24};
25 25
26static struct ebt_replace initial_table = 26static struct ebt_replace_kernel initial_table =
27{ 27{
28 .name = "broute", 28 .name = "broute",
29 .valid_hooks = 1 << NF_BR_BROUTING, 29 .valid_hooks = 1 << NF_BR_BROUTING,
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 3d5bd44f2395..127135ead2d5 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] =
30 }, 30 },
31}; 31};
32 32
33static struct ebt_replace initial_table = 33static struct ebt_replace_kernel initial_table =
34{ 34{
35 .name = "filter", 35 .name = "filter",
36 .valid_hooks = FILTER_VALID_HOOKS, 36 .valid_hooks = FILTER_VALID_HOOKS,
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 04dd42efda1d..9c50488b62eb 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] =
30 } 30 }
31}; 31};
32 32
33static struct ebt_replace initial_table = 33static struct ebt_replace_kernel initial_table =
34{ 34{
35 .name = "nat", 35 .name = "nat",
36 .valid_hooks = NAT_VALID_HOOKS, 36 .valid_hooks = NAT_VALID_HOOKS,
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 9f85666f29f7..bee558a41800 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -338,10 +338,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
338 const char *name, unsigned int hookmask, unsigned int *cnt) 338 const char *name, unsigned int hookmask, unsigned int *cnt)
339{ 339{
340 struct ebt_match *match; 340 struct ebt_match *match;
341 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
341 int ret; 342 int ret;
342 343
343 if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) > 344 if (left < sizeof(struct ebt_entry_match) ||
344 ((char *)e) + e->watchers_offset) 345 left - sizeof(struct ebt_entry_match) < m->match_size)
345 return -EINVAL; 346 return -EINVAL;
346 match = find_match_lock(m->u.name, &ret, &ebt_mutex); 347 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
347 if (!match) 348 if (!match)
@@ -367,10 +368,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
367 const char *name, unsigned int hookmask, unsigned int *cnt) 368 const char *name, unsigned int hookmask, unsigned int *cnt)
368{ 369{
369 struct ebt_watcher *watcher; 370 struct ebt_watcher *watcher;
371 size_t left = ((char *)e + e->target_offset) - (char *)w;
370 int ret; 372 int ret;
371 373
372 if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) > 374 if (left < sizeof(struct ebt_entry_watcher) ||
373 ((char *)e) + e->target_offset) 375 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
374 return -EINVAL; 376 return -EINVAL;
375 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex); 377 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
376 if (!watcher) 378 if (!watcher)
@@ -391,35 +393,91 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
391 return 0; 393 return 0;
392} 394}
393 395
396static int ebt_verify_pointers(struct ebt_replace *repl,
397 struct ebt_table_info *newinfo)
398{
399 unsigned int limit = repl->entries_size;
400 unsigned int valid_hooks = repl->valid_hooks;
401 unsigned int offset = 0;
402 int i;
403
404 for (i = 0; i < NF_BR_NUMHOOKS; i++)
405 newinfo->hook_entry[i] = NULL;
406
407 newinfo->entries_size = repl->entries_size;
408 newinfo->nentries = repl->nentries;
409
410 while (offset < limit) {
411 size_t left = limit - offset;
412 struct ebt_entry *e = (void *)newinfo->entries + offset;
413
414 if (left < sizeof(unsigned int))
415 break;
416
417 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
418 if ((valid_hooks & (1 << i)) == 0)
419 continue;
420 if ((char __user *)repl->hook_entry[i] ==
421 repl->entries + offset)
422 break;
423 }
424
425 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
426 if (e->bitmask != 0) {
427 /* we make userspace set this right,
428 so there is no misunderstanding */
429 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
430 "in distinguisher\n");
431 return -EINVAL;
432 }
433 if (i != NF_BR_NUMHOOKS)
434 newinfo->hook_entry[i] = (struct ebt_entries *)e;
435 if (left < sizeof(struct ebt_entries))
436 break;
437 offset += sizeof(struct ebt_entries);
438 } else {
439 if (left < sizeof(struct ebt_entry))
440 break;
441 if (left < e->next_offset)
442 break;
443 offset += e->next_offset;
444 }
445 }
446 if (offset != limit) {
447 BUGPRINT("entries_size too small\n");
448 return -EINVAL;
449 }
450
451 /* check if all valid hooks have a chain */
452 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
453 if (!newinfo->hook_entry[i] &&
454 (valid_hooks & (1 << i))) {
455 BUGPRINT("Valid hook without chain\n");
456 return -EINVAL;
457 }
458 }
459 return 0;
460}
461
394/* 462/*
395 * this one is very careful, as it is the first function 463 * this one is very careful, as it is the first function
396 * to parse the userspace data 464 * to parse the userspace data
397 */ 465 */
398static inline int 466static inline int
399ebt_check_entry_size_and_hooks(struct ebt_entry *e, 467ebt_check_entry_size_and_hooks(struct ebt_entry *e,
400 struct ebt_table_info *newinfo, char *base, char *limit, 468 struct ebt_table_info *newinfo,
401 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt, 469 unsigned int *n, unsigned int *cnt,
402 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks) 470 unsigned int *totalcnt, unsigned int *udc_cnt)
403{ 471{
404 int i; 472 int i;
405 473
406 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 474 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
407 if ((valid_hooks & (1 << i)) == 0) 475 if ((void *)e == (void *)newinfo->hook_entry[i])
408 continue;
409 if ( (char *)hook_entries[i] - base ==
410 (char *)e - newinfo->entries)
411 break; 476 break;
412 } 477 }
413 /* beginning of a new chain 478 /* beginning of a new chain
414 if i == NF_BR_NUMHOOKS it must be a user defined chain */ 479 if i == NF_BR_NUMHOOKS it must be a user defined chain */
415 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { 480 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
416 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
417 /* we make userspace set this right,
418 so there is no misunderstanding */
419 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
420 "in distinguisher\n");
421 return -EINVAL;
422 }
423 /* this checks if the previous chain has as many entries 481 /* this checks if the previous chain has as many entries
424 as it said it has */ 482 as it said it has */
425 if (*n != *cnt) { 483 if (*n != *cnt) {
@@ -427,12 +485,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
427 "in the chain\n"); 485 "in the chain\n");
428 return -EINVAL; 486 return -EINVAL;
429 } 487 }
430 /* before we look at the struct, be sure it is not too big */
431 if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
432 > limit) {
433 BUGPRINT("entries_size too small\n");
434 return -EINVAL;
435 }
436 if (((struct ebt_entries *)e)->policy != EBT_DROP && 488 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
437 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) { 489 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
438 /* only RETURN from udc */ 490 /* only RETURN from udc */
@@ -444,8 +496,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
444 } 496 }
445 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */ 497 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
446 (*udc_cnt)++; 498 (*udc_cnt)++;
447 else
448 newinfo->hook_entry[i] = (struct ebt_entries *)e;
449 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) { 499 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
450 BUGPRINT("counter_offset != totalcnt"); 500 BUGPRINT("counter_offset != totalcnt");
451 return -EINVAL; 501 return -EINVAL;
@@ -466,7 +516,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
466 BUGPRINT("target size too small\n"); 516 BUGPRINT("target size too small\n");
467 return -EINVAL; 517 return -EINVAL;
468 } 518 }
469
470 (*cnt)++; 519 (*cnt)++;
471 (*totalcnt)++; 520 (*totalcnt)++;
472 return 0; 521 return 0;
@@ -485,17 +534,14 @@ struct ebt_cl_stack
485 */ 534 */
486static inline int 535static inline int
487ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, 536ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
488 struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks, 537 unsigned int *n, struct ebt_cl_stack *udc)
489 struct ebt_cl_stack *udc)
490{ 538{
491 int i; 539 int i;
492 540
493 /* we're only interested in chain starts */ 541 /* we're only interested in chain starts */
494 if (e->bitmask & EBT_ENTRY_OR_ENTRIES) 542 if (e->bitmask)
495 return 0; 543 return 0;
496 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 544 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
497 if ((valid_hooks & (1 << i)) == 0)
498 continue;
499 if (newinfo->hook_entry[i] == (struct ebt_entries *)e) 545 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
500 break; 546 break;
501 } 547 }
@@ -541,7 +587,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
541{ 587{
542 struct ebt_entry_target *t; 588 struct ebt_entry_target *t;
543 589
544 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) 590 if (e->bitmask == 0)
545 return 0; 591 return 0;
546 /* we're done */ 592 /* we're done */
547 if (cnt && (*cnt)-- == 0) 593 if (cnt && (*cnt)-- == 0)
@@ -558,16 +604,17 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
558 604
559static inline int 605static inline int
560ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, 606ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
561 const char *name, unsigned int *cnt, unsigned int valid_hooks, 607 const char *name, unsigned int *cnt,
562 struct ebt_cl_stack *cl_s, unsigned int udc_cnt) 608 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
563{ 609{
564 struct ebt_entry_target *t; 610 struct ebt_entry_target *t;
565 struct ebt_target *target; 611 struct ebt_target *target;
566 unsigned int i, j, hook = 0, hookmask = 0; 612 unsigned int i, j, hook = 0, hookmask = 0;
613 size_t gap = e->next_offset - e->target_offset;
567 int ret; 614 int ret;
568 615
569 /* don't mess with the struct ebt_entries */ 616 /* don't mess with the struct ebt_entries */
570 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) 617 if (e->bitmask == 0)
571 return 0; 618 return 0;
572 619
573 if (e->bitmask & ~EBT_F_MASK) { 620 if (e->bitmask & ~EBT_F_MASK) {
@@ -584,7 +631,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
584 } 631 }
585 /* what hook do we belong to? */ 632 /* what hook do we belong to? */
586 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 633 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
587 if ((valid_hooks & (1 << i)) == 0) 634 if (!newinfo->hook_entry[i])
588 continue; 635 continue;
589 if ((char *)newinfo->hook_entry[i] < (char *)e) 636 if ((char *)newinfo->hook_entry[i] < (char *)e)
590 hook = i; 637 hook = i;
@@ -625,8 +672,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
625 672
626 t->u.target = target; 673 t->u.target = target;
627 if (t->u.target == &ebt_standard_target) { 674 if (t->u.target == &ebt_standard_target) {
628 if (e->target_offset + sizeof(struct ebt_standard_target) > 675 if (gap < sizeof(struct ebt_standard_target)) {
629 e->next_offset) {
630 BUGPRINT("Standard target size too big\n"); 676 BUGPRINT("Standard target size too big\n");
631 ret = -EFAULT; 677 ret = -EFAULT;
632 goto cleanup_watchers; 678 goto cleanup_watchers;
@@ -637,8 +683,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
637 ret = -EFAULT; 683 ret = -EFAULT;
638 goto cleanup_watchers; 684 goto cleanup_watchers;
639 } 685 }
640 } else if ((e->target_offset + t->target_size + 686 } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
641 sizeof(struct ebt_entry_target) > e->next_offset) ||
642 (t->u.target->check && 687 (t->u.target->check &&
643 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){ 688 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
644 module_put(t->u.target->me); 689 module_put(t->u.target->me);
@@ -708,7 +753,9 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s
708 BUGPRINT("loop\n"); 753 BUGPRINT("loop\n");
709 return -1; 754 return -1;
710 } 755 }
711 /* this can't be 0, so the above test is correct */ 756 if (cl_s[i].hookmask & (1 << hooknr))
757 goto letscontinue;
758 /* this can't be 0, so the loop test is correct */
712 cl_s[i].cs.n = pos + 1; 759 cl_s[i].cs.n = pos + 1;
713 pos = 0; 760 pos = 0;
714 cl_s[i].cs.e = ((void *)e + e->next_offset); 761 cl_s[i].cs.e = ((void *)e + e->next_offset);
@@ -728,42 +775,35 @@ letscontinue:
728} 775}
729 776
730/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */ 777/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
731static int translate_table(struct ebt_replace *repl, 778static int translate_table(char *name, struct ebt_table_info *newinfo)
732 struct ebt_table_info *newinfo)
733{ 779{
734 unsigned int i, j, k, udc_cnt; 780 unsigned int i, j, k, udc_cnt;
735 int ret; 781 int ret;
736 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */ 782 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
737 783
738 i = 0; 784 i = 0;
739 while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i))) 785 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
740 i++; 786 i++;
741 if (i == NF_BR_NUMHOOKS) { 787 if (i == NF_BR_NUMHOOKS) {
742 BUGPRINT("No valid hooks specified\n"); 788 BUGPRINT("No valid hooks specified\n");
743 return -EINVAL; 789 return -EINVAL;
744 } 790 }
745 if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) { 791 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
746 BUGPRINT("Chains don't start at beginning\n"); 792 BUGPRINT("Chains don't start at beginning\n");
747 return -EINVAL; 793 return -EINVAL;
748 } 794 }
749 /* make sure chains are ordered after each other in same order 795 /* make sure chains are ordered after each other in same order
750 as their corresponding hooks */ 796 as their corresponding hooks */
751 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) { 797 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
752 if (!(repl->valid_hooks & (1 << j))) 798 if (!newinfo->hook_entry[j])
753 continue; 799 continue;
754 if ( repl->hook_entry[j] <= repl->hook_entry[i] ) { 800 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
755 BUGPRINT("Hook order must be followed\n"); 801 BUGPRINT("Hook order must be followed\n");
756 return -EINVAL; 802 return -EINVAL;
757 } 803 }
758 i = j; 804 i = j;
759 } 805 }
760 806
761 for (i = 0; i < NF_BR_NUMHOOKS; i++)
762 newinfo->hook_entry[i] = NULL;
763
764 newinfo->entries_size = repl->entries_size;
765 newinfo->nentries = repl->nentries;
766
767 /* do some early checkings and initialize some things */ 807 /* do some early checkings and initialize some things */
768 i = 0; /* holds the expected nr. of entries for the chain */ 808 i = 0; /* holds the expected nr. of entries for the chain */
769 j = 0; /* holds the up to now counted entries for the chain */ 809 j = 0; /* holds the up to now counted entries for the chain */
@@ -771,9 +811,8 @@ static int translate_table(struct ebt_replace *repl,
771 newinfo->nentries afterwards */ 811 newinfo->nentries afterwards */
772 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */ 812 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
773 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 813 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
774 ebt_check_entry_size_and_hooks, newinfo, repl->entries, 814 ebt_check_entry_size_and_hooks, newinfo,
775 repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k, 815 &i, &j, &k, &udc_cnt);
776 &udc_cnt, repl->valid_hooks);
777 816
778 if (ret != 0) 817 if (ret != 0)
779 return ret; 818 return ret;
@@ -788,15 +827,6 @@ static int translate_table(struct ebt_replace *repl,
788 return -EINVAL; 827 return -EINVAL;
789 } 828 }
790 829
791 /* check if all valid hooks have a chain */
792 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
793 if (newinfo->hook_entry[i] == NULL &&
794 (repl->valid_hooks & (1 << i))) {
795 BUGPRINT("Valid hook without chain\n");
796 return -EINVAL;
797 }
798 }
799
800 /* get the location of the udc, put them in an array 830 /* get the location of the udc, put them in an array
801 while we're at it, allocate the chainstack */ 831 while we're at it, allocate the chainstack */
802 if (udc_cnt) { 832 if (udc_cnt) {
@@ -824,8 +854,7 @@ static int translate_table(struct ebt_replace *repl,
824 return -ENOMEM; 854 return -ENOMEM;
825 i = 0; /* the i'th udc */ 855 i = 0; /* the i'th udc */
826 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 856 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
827 ebt_get_udc_positions, newinfo, repl->hook_entry, &i, 857 ebt_get_udc_positions, newinfo, &i, cl_s);
828 repl->valid_hooks, cl_s);
829 /* sanity check */ 858 /* sanity check */
830 if (i != udc_cnt) { 859 if (i != udc_cnt) {
831 BUGPRINT("i != udc_cnt\n"); 860 BUGPRINT("i != udc_cnt\n");
@@ -836,7 +865,7 @@ static int translate_table(struct ebt_replace *repl,
836 865
837 /* Check for loops */ 866 /* Check for loops */
838 for (i = 0; i < NF_BR_NUMHOOKS; i++) 867 for (i = 0; i < NF_BR_NUMHOOKS; i++)
839 if (repl->valid_hooks & (1 << i)) 868 if (newinfo->hook_entry[i])
840 if (check_chainloops(newinfo->hook_entry[i], 869 if (check_chainloops(newinfo->hook_entry[i],
841 cl_s, udc_cnt, i, newinfo->entries)) { 870 cl_s, udc_cnt, i, newinfo->entries)) {
842 vfree(cl_s); 871 vfree(cl_s);
@@ -856,8 +885,7 @@ static int translate_table(struct ebt_replace *repl,
856 /* used to know what we need to clean up if something goes wrong */ 885 /* used to know what we need to clean up if something goes wrong */
857 i = 0; 886 i = 0;
858 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 887 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
859 ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks, 888 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
860 cl_s, udc_cnt);
861 if (ret != 0) { 889 if (ret != 0) {
862 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 890 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
863 ebt_cleanup_entry, &i); 891 ebt_cleanup_entry, &i);
@@ -954,7 +982,11 @@ static int do_replace(void __user *user, unsigned int len)
954 982
955 /* this can get initialized by translate_table() */ 983 /* this can get initialized by translate_table() */
956 newinfo->chainstack = NULL; 984 newinfo->chainstack = NULL;
957 ret = translate_table(&tmp, newinfo); 985 ret = ebt_verify_pointers(&tmp, newinfo);
986 if (ret != 0)
987 goto free_counterstmp;
988
989 ret = translate_table(tmp.name, newinfo);
958 990
959 if (ret != 0) 991 if (ret != 0)
960 goto free_counterstmp; 992 goto free_counterstmp;
@@ -1125,35 +1157,47 @@ int ebt_register_table(struct ebt_table *table)
1125{ 1157{
1126 struct ebt_table_info *newinfo; 1158 struct ebt_table_info *newinfo;
1127 struct ebt_table *t; 1159 struct ebt_table *t;
1160 struct ebt_replace_kernel *repl;
1128 int ret, i, countersize; 1161 int ret, i, countersize;
1162 void *p;
1129 1163
1130 if (!table || !table->table ||!table->table->entries || 1164 if (!table || !(repl = table->table) || !repl->entries ||
1131 table->table->entries_size == 0 || 1165 repl->entries_size == 0 ||
1132 table->table->counters || table->private) { 1166 repl->counters || table->private) {
1133 BUGPRINT("Bad table data for ebt_register_table!!!\n"); 1167 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1134 return -EINVAL; 1168 return -EINVAL;
1135 } 1169 }
1136 1170
1137 countersize = COUNTER_OFFSET(table->table->nentries) * 1171 countersize = COUNTER_OFFSET(repl->nentries) *
1138 (highest_possible_processor_id()+1); 1172 (highest_possible_processor_id()+1);
1139 newinfo = vmalloc(sizeof(*newinfo) + countersize); 1173 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1140 ret = -ENOMEM; 1174 ret = -ENOMEM;
1141 if (!newinfo) 1175 if (!newinfo)
1142 return -ENOMEM; 1176 return -ENOMEM;
1143 1177
1144 newinfo->entries = vmalloc(table->table->entries_size); 1178 p = vmalloc(repl->entries_size);
1145 if (!(newinfo->entries)) 1179 if (!p)
1146 goto free_newinfo; 1180 goto free_newinfo;
1147 1181
1148 memcpy(newinfo->entries, table->table->entries, 1182 memcpy(p, repl->entries, repl->entries_size);
1149 table->table->entries_size); 1183 newinfo->entries = p;
1184
1185 newinfo->entries_size = repl->entries_size;
1186 newinfo->nentries = repl->nentries;
1150 1187
1151 if (countersize) 1188 if (countersize)
1152 memset(newinfo->counters, 0, countersize); 1189 memset(newinfo->counters, 0, countersize);
1153 1190
1154 /* fill in newinfo and parse the entries */ 1191 /* fill in newinfo and parse the entries */
1155 newinfo->chainstack = NULL; 1192 newinfo->chainstack = NULL;
1156 ret = translate_table(table->table, newinfo); 1193 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1194 if ((repl->valid_hooks & (1 << i)) == 0)
1195 newinfo->hook_entry[i] = NULL;
1196 else
1197 newinfo->hook_entry[i] = p +
1198 ((char *)repl->hook_entry[i] - repl->entries);
1199 }
1200 ret = translate_table(repl->name, newinfo);
1157 if (ret != 0) { 1201 if (ret != 0) {
1158 BUGPRINT("Translate_table failed\n"); 1202 BUGPRINT("Translate_table failed\n");
1159 goto free_chainstack; 1203 goto free_chainstack;
@@ -1277,33 +1321,33 @@ free_tmp:
1277} 1321}
1278 1322
1279static inline int ebt_make_matchname(struct ebt_entry_match *m, 1323static inline int ebt_make_matchname(struct ebt_entry_match *m,
1280 char *base, char *ubase) 1324 char *base, char __user *ubase)
1281{ 1325{
1282 char *hlp = ubase - base + (char *)m; 1326 char __user *hlp = ubase + ((char *)m - base);
1283 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN)) 1327 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1284 return -EFAULT; 1328 return -EFAULT;
1285 return 0; 1329 return 0;
1286} 1330}
1287 1331
1288static inline int ebt_make_watchername(struct ebt_entry_watcher *w, 1332static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1289 char *base, char *ubase) 1333 char *base, char __user *ubase)
1290{ 1334{
1291 char *hlp = ubase - base + (char *)w; 1335 char __user *hlp = ubase + ((char *)w - base);
1292 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN)) 1336 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1293 return -EFAULT; 1337 return -EFAULT;
1294 return 0; 1338 return 0;
1295} 1339}
1296 1340
1297static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase) 1341static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
1298{ 1342{
1299 int ret; 1343 int ret;
1300 char *hlp; 1344 char __user *hlp;
1301 struct ebt_entry_target *t; 1345 struct ebt_entry_target *t;
1302 1346
1303 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) 1347 if (e->bitmask == 0)
1304 return 0; 1348 return 0;
1305 1349
1306 hlp = ubase - base + (char *)e + e->target_offset; 1350 hlp = ubase + (((char *)e + e->target_offset) - base);
1307 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); 1351 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1308 1352
1309 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase); 1353 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);