diff options
author | David Howells <dhowells@redhat.com> | 2006-12-05 09:37:56 -0500 |
---|---|---|
committer | David Howells <dhowells@warthog.cambridge.redhat.com> | 2006-12-05 09:37:56 -0500 |
commit | 4c1ac1b49122b805adfa4efc620592f68dccf5db (patch) | |
tree | 87557f4bc2fd4fe65b7570489c2f610c45c0adcd /net/bridge | |
parent | c4028958b6ecad064b1a6303a6a5906d4fe48d73 (diff) | |
parent | d916faace3efc0bf19fe9a615a1ab8fa1a24cd93 (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.c | 9 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 3 | ||||
-rw-r--r-- | net/bridge/br_netlink.c | 113 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_802_3.c | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_among.c | 22 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_arp.c | 6 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_ip.c | 4 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_log.c | 6 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_mark.c | 14 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_mark_m.c | 4 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_snat.c | 27 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_ulog.c | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_vlan.c | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_broute.c | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_filter.c | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_nat.c | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 222 |
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 | ||
18 | static 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 | ||
67 | nlmsg_failure: | 72 | return nlmsg_end(skb, nlh); |
68 | rtattr_failure: | ||
69 | 73 | ||
70 | skb_trim(skb, b - skb->data); | 74 | nla_put_failure: |
71 | return -EINVAL; | 75 | return nlmsg_cancel(skb, nlh); |
72 | } | 76 | } |
73 | 77 | ||
74 | /* | 78 | /* |
@@ -77,19 +81,16 @@ rtattr_failure: | |||
77 | void br_ifinfo_notify(int event, struct net_bridge_port *port) | 81 | void 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); |
95 | errout: | 96 | errout: |
@@ -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; |
125 | cont: | 119 | skip: |
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 | */ |
139 | static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 133 | static 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 | ||
17 | static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh, | 17 | static 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 | ||
73 | static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr) | 73 | static 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 | ||
101 | static int get_ip_src(const struct sk_buff *skb, uint32_t *addr) | 101 | static 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 | ||
22 | struct tcpudphdr { | 22 | struct tcpudphdr { |
23 | uint16_t src; | 23 | __be16 src; |
24 | uint16_t dst; | 24 | __be16 dst; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, | 27 | static 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 | ||
39 | struct tcpudphdr | 39 | struct tcpudphdr |
40 | { | 40 | { |
41 | uint16_t src; | 41 | __be16 src; |
42 | uint16_t dst; | 42 | __be16 dst; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct arppayload | 45 | struct 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 | ||
39 | static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, | 39 | static 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 | ||
26 | static int ebt_mark_check(const char *tablename, unsigned int hookmask, | 26 | static 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 | ||
16 | static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, | 18 | static 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 | } | ||
48 | out: | ||
49 | return info->target | ~EBT_VERDICT_BITS; | ||
35 | } | 50 | } |
36 | 51 | ||
37 | static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, | 52 | static 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 | ||
26 | static struct ebt_replace initial_table = | 26 | static 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 | ||
33 | static struct ebt_replace initial_table = | 33 | static 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 | ||
33 | static struct ebt_replace initial_table = | 33 | static 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 | ||
396 | static 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 | */ |
398 | static inline int | 466 | static inline int |
399 | ebt_check_entry_size_and_hooks(struct ebt_entry *e, | 467 | ebt_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 | */ |
486 | static inline int | 535 | static inline int |
487 | ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, | 536 | ebt_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 | ||
559 | static inline int | 605 | static inline int |
560 | ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, | 606 | ebt_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 */ |
731 | static int translate_table(struct ebt_replace *repl, | 778 | static 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 | ||
1279 | static inline int ebt_make_matchname(struct ebt_entry_match *m, | 1323 | static 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 | ||
1288 | static inline int ebt_make_watchername(struct ebt_entry_watcher *w, | 1332 | static 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 | ||
1297 | static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase) | 1341 | static 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); |