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>
This commit is contained in:
@@ -58,12 +58,13 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
|
||||
{
|
||||
int num;
|
||||
void *buf;
|
||||
size_t size = maxnum * sizeof(struct __fdb_entry);
|
||||
size_t size;
|
||||
|
||||
if (size > PAGE_SIZE) {
|
||||
size = PAGE_SIZE;
|
||||
/* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
|
||||
if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
|
||||
maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
|
||||
}
|
||||
|
||||
size = maxnum * sizeof(struct __fdb_entry);
|
||||
|
||||
buf = kmalloc(size, GFP_USER);
|
||||
if (!buf)
|
||||
|
@@ -40,7 +40,6 @@
|
||||
#include <net/route.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/checksum.h>
|
||||
#include "br_private.h"
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#include <linux/sysctl.h>
|
||||
@@ -381,7 +380,7 @@ static int check_hbh_len(struct sk_buff *skb)
|
||||
case IPV6_TLV_JUMBO:
|
||||
if (skb->nh.raw[off + 1] != 4 || (off & 3) != 2)
|
||||
goto bad;
|
||||
pkt_len = ntohl(*(u32 *) (skb->nh.raw + off + 2));
|
||||
pkt_len = ntohl(*(__be32 *) (skb->nh.raw + off + 2));
|
||||
if (pkt_len <= IPV6_MAXPLEN ||
|
||||
skb->nh.ipv6h->payload_len)
|
||||
goto bad;
|
||||
|
@@ -15,6 +15,18 @@
|
||||
#include <net/netlink.h>
|
||||
#include "br_private.h"
|
||||
|
||||
static inline size_t br_nlmsg_size(void)
|
||||
{
|
||||
return NLMSG_ALIGN(sizeof(struct ifinfomsg))
|
||||
+ nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
|
||||
+ nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
|
||||
+ nla_total_size(4) /* IFLA_MASTER */
|
||||
+ nla_total_size(4) /* IFLA_MTU */
|
||||
+ nla_total_size(4) /* IFLA_LINK */
|
||||
+ nla_total_size(1) /* IFLA_OPERSTATE */
|
||||
+ nla_total_size(1); /* IFLA_PROTINFO */
|
||||
}
|
||||
|
||||
/*
|
||||
* Create one netlink message for one interface
|
||||
* 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
|
||||
{
|
||||
const struct net_bridge *br = port->br;
|
||||
const struct net_device *dev = port->dev;
|
||||
struct ifinfomsg *r;
|
||||
struct ifinfomsg *hdr;
|
||||
struct nlmsghdr *nlh;
|
||||
unsigned char *b = skb->tail;
|
||||
u32 mtu = dev->mtu;
|
||||
u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
|
||||
u8 portstate = port->state;
|
||||
|
||||
pr_debug("br_fill_info event %d port %s master %s\n",
|
||||
event, dev->name, br->dev->name);
|
||||
|
||||
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
|
||||
r = NLMSG_DATA(nlh);
|
||||
r->ifi_family = AF_BRIDGE;
|
||||
r->__ifi_pad = 0;
|
||||
r->ifi_type = dev->type;
|
||||
r->ifi_index = dev->ifindex;
|
||||
r->ifi_flags = dev_get_flags(dev);
|
||||
r->ifi_change = 0;
|
||||
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
|
||||
if (nlh == NULL)
|
||||
return -ENOBUFS;
|
||||
|
||||
RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
|
||||
hdr = nlmsg_data(nlh);
|
||||
hdr->ifi_family = AF_BRIDGE;
|
||||
hdr->__ifi_pad = 0;
|
||||
hdr->ifi_type = dev->type;
|
||||
hdr->ifi_index = dev->ifindex;
|
||||
hdr->ifi_flags = dev_get_flags(dev);
|
||||
hdr->ifi_change = 0;
|
||||
|
||||
RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);
|
||||
NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
|
||||
NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex);
|
||||
NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
|
||||
NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate);
|
||||
|
||||
if (dev->addr_len)
|
||||
RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
|
||||
NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
|
||||
|
||||
RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
|
||||
if (dev->ifindex != dev->iflink)
|
||||
RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
|
||||
|
||||
|
||||
RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
|
||||
NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
|
||||
|
||||
if (event == RTM_NEWLINK)
|
||||
RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);
|
||||
NLA_PUT_U8(skb, IFLA_PROTINFO, port->state);
|
||||
|
||||
nlh->nlmsg_len = skb->tail - b;
|
||||
return nlmsg_end(skb, nlh);
|
||||
|
||||
return skb->len;
|
||||
|
||||
nlmsg_failure:
|
||||
rtattr_failure:
|
||||
|
||||
skb_trim(skb, b - skb->data);
|
||||
return -EINVAL;
|
||||
nla_put_failure:
|
||||
return nlmsg_cancel(skb, nlh);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -77,19 +81,16 @@ rtattr_failure:
|
||||
void br_ifinfo_notify(int event, struct net_bridge_port *port)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int payload = sizeof(struct ifinfomsg) + 128;
|
||||
int err = -ENOBUFS;
|
||||
|
||||
pr_debug("bridge notify event=%d\n", event);
|
||||
skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
|
||||
skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC);
|
||||
if (skb == NULL)
|
||||
goto errout;
|
||||
|
||||
err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
goto errout;
|
||||
}
|
||||
/* failure implies BUG in br_nlmsg_size() */
|
||||
BUG_ON(err < 0);
|
||||
|
||||
err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
|
||||
errout:
|
||||
@@ -104,25 +105,18 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct net_device *dev;
|
||||
int idx;
|
||||
int s_idx = cb->args[0];
|
||||
int err = 0;
|
||||
|
||||
read_lock(&dev_base_lock);
|
||||
for (dev = dev_base, idx = 0; dev; dev = dev->next) {
|
||||
struct net_bridge_port *p = dev->br_port;
|
||||
|
||||
/* not a bridge port */
|
||||
if (!p)
|
||||
continue;
|
||||
if (dev->br_port == NULL || idx < cb->args[0])
|
||||
goto skip;
|
||||
|
||||
if (idx < s_idx)
|
||||
goto cont;
|
||||
|
||||
err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid,
|
||||
cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
|
||||
if (err <= 0)
|
||||
if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid,
|
||||
cb->nlh->nlmsg_seq, RTM_NEWLINK,
|
||||
NLM_F_MULTI) < 0)
|
||||
break;
|
||||
cont:
|
||||
skip:
|
||||
++idx;
|
||||
}
|
||||
read_unlock(&dev_base_lock);
|
||||
@@ -138,26 +132,27 @@ cont:
|
||||
*/
|
||||
static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
||||
{
|
||||
struct rtattr **rta = arg;
|
||||
struct ifinfomsg *ifm = NLMSG_DATA(nlh);
|
||||
struct ifinfomsg *ifm;
|
||||
struct nlattr *protinfo;
|
||||
struct net_device *dev;
|
||||
struct net_bridge_port *p;
|
||||
u8 new_state;
|
||||
|
||||
if (nlmsg_len(nlh) < sizeof(*ifm))
|
||||
return -EINVAL;
|
||||
|
||||
ifm = nlmsg_data(nlh);
|
||||
if (ifm->ifi_family != AF_BRIDGE)
|
||||
return -EPFNOSUPPORT;
|
||||
|
||||
/* Must pass valid state as PROTINFO */
|
||||
if (rta[IFLA_PROTINFO-1]) {
|
||||
u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
|
||||
new_state = *pstate;
|
||||
} else
|
||||
protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
|
||||
if (!protinfo || nla_len(protinfo) < sizeof(u8))
|
||||
return -EINVAL;
|
||||
|
||||
new_state = nla_get_u8(protinfo);
|
||||
if (new_state > BR_STATE_BLOCKING)
|
||||
return -EINVAL;
|
||||
|
||||
/* Find bridge port */
|
||||
dev = __dev_get_by_index(ifm->ifi_index);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
@@ -170,10 +165,8 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
||||
if (p->br->stp_enabled)
|
||||
return -EBUSY;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return -ENETDOWN;
|
||||
|
||||
if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
|
||||
if (!netif_running(dev) ||
|
||||
(!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED))
|
||||
return -ENETDOWN;
|
||||
|
||||
p->state = new_state;
|
||||
|
@@ -17,7 +17,7 @@ static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *
|
||||
{
|
||||
struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
|
||||
struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
|
||||
uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
|
||||
__be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
|
||||
|
||||
if (info->bitmask & EBT_802_3_SAP) {
|
||||
if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP))
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
|
||||
const char *mac, uint32_t ip)
|
||||
const char *mac, __be32 ip)
|
||||
{
|
||||
/* You may be puzzled as to how this code works.
|
||||
* Some tricks were used, refer to
|
||||
@@ -70,7 +70,7 @@ static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
|
||||
static int get_ip_dst(const struct sk_buff *skb, __be32 *addr)
|
||||
{
|
||||
if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
|
||||
struct iphdr _iph, *ih;
|
||||
@@ -81,16 +81,16 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
|
||||
*addr = ih->daddr;
|
||||
} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
|
||||
struct arphdr _arph, *ah;
|
||||
uint32_t buf, *bp;
|
||||
__be32 buf, *bp;
|
||||
|
||||
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
|
||||
if (ah == NULL ||
|
||||
ah->ar_pln != sizeof(uint32_t) ||
|
||||
ah->ar_pln != sizeof(__be32) ||
|
||||
ah->ar_hln != ETH_ALEN)
|
||||
return -1;
|
||||
bp = skb_header_pointer(skb, sizeof(struct arphdr) +
|
||||
2 * ETH_ALEN + sizeof(uint32_t),
|
||||
sizeof(uint32_t), &buf);
|
||||
2 * ETH_ALEN + sizeof(__be32),
|
||||
sizeof(__be32), &buf);
|
||||
if (bp == NULL)
|
||||
return -1;
|
||||
*addr = *bp;
|
||||
@@ -98,7 +98,7 @@ static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
|
||||
static int get_ip_src(const struct sk_buff *skb, __be32 *addr)
|
||||
{
|
||||
if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
|
||||
struct iphdr _iph, *ih;
|
||||
@@ -109,15 +109,15 @@ static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
|
||||
*addr = ih->saddr;
|
||||
} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
|
||||
struct arphdr _arph, *ah;
|
||||
uint32_t buf, *bp;
|
||||
__be32 buf, *bp;
|
||||
|
||||
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
|
||||
if (ah == NULL ||
|
||||
ah->ar_pln != sizeof(uint32_t) ||
|
||||
ah->ar_pln != sizeof(__be32) ||
|
||||
ah->ar_hln != ETH_ALEN)
|
||||
return -1;
|
||||
bp = skb_header_pointer(skb, sizeof(struct arphdr) +
|
||||
ETH_ALEN, sizeof(uint32_t), &buf);
|
||||
ETH_ALEN, sizeof(__be32), &buf);
|
||||
if (bp == NULL)
|
||||
return -1;
|
||||
*addr = *bp;
|
||||
@@ -133,7 +133,7 @@ static int ebt_filter_among(const struct sk_buff *skb,
|
||||
struct ebt_among_info *info = (struct ebt_among_info *) data;
|
||||
const char *dmac, *smac;
|
||||
const struct ebt_mac_wormhash *wh_dst, *wh_src;
|
||||
uint32_t dip = 0, sip = 0;
|
||||
__be32 dip = 0, sip = 0;
|
||||
|
||||
wh_dst = ebt_among_wh_dst(info);
|
||||
wh_src = ebt_among_wh_src(info);
|
||||
|
@@ -35,10 +35,10 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
|
||||
return EBT_NOMATCH;
|
||||
|
||||
if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
|
||||
uint32_t _addr, *ap;
|
||||
__be32 _addr, *ap;
|
||||
|
||||
/* IPv4 addresses are always 4 bytes */
|
||||
if (ah->ar_pln != sizeof(uint32_t))
|
||||
if (ah->ar_pln != sizeof(__be32))
|
||||
return EBT_NOMATCH;
|
||||
if (info->bitmask & EBT_ARP_SRC_IP) {
|
||||
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
|
||||
|
||||
if (info->bitmask & EBT_ARP_DST_IP) {
|
||||
ap = skb_header_pointer(skb, sizeof(struct arphdr) +
|
||||
2*ah->ar_hln+sizeof(uint32_t),
|
||||
2*ah->ar_hln+sizeof(__be32),
|
||||
sizeof(_addr), &_addr);
|
||||
if (ap == NULL)
|
||||
return EBT_NOMATCH;
|
||||
|
@@ -20,8 +20,8 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
struct tcpudphdr {
|
||||
uint16_t src;
|
||||
uint16_t dst;
|
||||
__be16 src;
|
||||
__be16 dst;
|
||||
};
|
||||
|
||||
static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
|
||||
|
@@ -38,8 +38,8 @@ static int ebt_log_check(const char *tablename, unsigned int hookmask,
|
||||
|
||||
struct tcpudphdr
|
||||
{
|
||||
uint16_t src;
|
||||
uint16_t dst;
|
||||
__be16 src;
|
||||
__be16 dst;
|
||||
};
|
||||
|
||||
struct arppayload
|
||||
@@ -130,7 +130,7 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum,
|
||||
* then log the ARP payload */
|
||||
if (ah->ar_hrd == htons(1) &&
|
||||
ah->ar_hln == ETH_ALEN &&
|
||||
ah->ar_pln == sizeof(uint32_t)) {
|
||||
ah->ar_pln == sizeof(__be32)) {
|
||||
struct arppayload _arpp, *ap;
|
||||
|
||||
ap = skb_header_pointer(skb, sizeof(_arph),
|
||||
|
@@ -25,15 +25,15 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
|
||||
int action = info->target & -16;
|
||||
|
||||
if (action == MARK_SET_VALUE)
|
||||
(*pskb)->nfmark = info->mark;
|
||||
(*pskb)->mark = info->mark;
|
||||
else if (action == MARK_OR_VALUE)
|
||||
(*pskb)->nfmark |= info->mark;
|
||||
(*pskb)->mark |= info->mark;
|
||||
else if (action == MARK_AND_VALUE)
|
||||
(*pskb)->nfmark &= info->mark;
|
||||
(*pskb)->mark &= info->mark;
|
||||
else
|
||||
(*pskb)->nfmark ^= info->mark;
|
||||
(*pskb)->mark ^= info->mark;
|
||||
|
||||
return info->target | -16;
|
||||
return info->target | ~EBT_VERDICT_BITS;
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
|
||||
return -EINVAL;
|
||||
tmp = info->target | -16;
|
||||
tmp = info->target | ~EBT_VERDICT_BITS;
|
||||
if (BASE_CHAIN && tmp == EBT_RETURN)
|
||||
return -EINVAL;
|
||||
CLEAR_BASE_CHAIN_BIT;
|
||||
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
|
||||
return -EINVAL;
|
||||
tmp = info->target & -16;
|
||||
tmp = info->target & ~EBT_VERDICT_BITS;
|
||||
if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
|
||||
tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
|
||||
return -EINVAL;
|
||||
|
@@ -19,8 +19,8 @@ static int ebt_filter_mark(const struct sk_buff *skb,
|
||||
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
|
||||
|
||||
if (info->bitmask & EBT_MARK_OR)
|
||||
return !(!!(skb->nfmark & info->mask) ^ info->invert);
|
||||
return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert);
|
||||
return !(!!(skb->mark & info->mask) ^ info->invert);
|
||||
return !(((skb->mark & info->mask) == info->mark) ^ info->invert);
|
||||
}
|
||||
|
||||
static int ebt_mark_check(const char *tablename, unsigned int hookmask,
|
||||
|
@@ -12,6 +12,8 @@
|
||||
#include <linux/netfilter_bridge/ebt_nat.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <net/arp.h>
|
||||
|
||||
static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
|
||||
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,
|
||||
*pskb = nskb;
|
||||
}
|
||||
memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
|
||||
return info->target;
|
||||
if (!(info->target & NAT_ARP_BIT) &&
|
||||
eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
|
||||
struct arphdr _ah, *ap;
|
||||
|
||||
ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
|
||||
if (ap == NULL)
|
||||
return EBT_DROP;
|
||||
if (ap->ar_hln != ETH_ALEN)
|
||||
goto out;
|
||||
if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
|
||||
return EBT_DROP;
|
||||
}
|
||||
out:
|
||||
return info->target | ~EBT_VERDICT_BITS;
|
||||
}
|
||||
|
||||
static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
|
||||
const struct ebt_entry *e, void *data, unsigned int datalen)
|
||||
{
|
||||
struct ebt_nat_info *info = (struct ebt_nat_info *) data;
|
||||
int tmp;
|
||||
|
||||
if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
|
||||
return -EINVAL;
|
||||
if (BASE_CHAIN && info->target == EBT_RETURN)
|
||||
tmp = info->target | ~EBT_VERDICT_BITS;
|
||||
if (BASE_CHAIN && tmp == EBT_RETURN)
|
||||
return -EINVAL;
|
||||
CLEAR_BASE_CHAIN_BIT;
|
||||
if (strcmp(tablename, "nat"))
|
||||
return -EINVAL;
|
||||
if (hookmask & ~(1 << NF_BR_POST_ROUTING))
|
||||
return -EINVAL;
|
||||
if (INVALID_TARGET)
|
||||
|
||||
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
|
||||
return -EINVAL;
|
||||
tmp = info->target | EBT_VERDICT_BITS;
|
||||
if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -168,7 +168,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
|
||||
if (ub->qlen == 1)
|
||||
skb_set_timestamp(ub->skb, &pm->stamp);
|
||||
pm->data_len = copy_len;
|
||||
pm->mark = skb->nfmark;
|
||||
pm->mark = skb->mark;
|
||||
pm->hook = hooknr;
|
||||
if (uloginfo->prefix != NULL)
|
||||
strcpy(pm->prefix, uloginfo->prefix);
|
||||
|
@@ -55,7 +55,7 @@ ebt_filter_vlan(const struct sk_buff *skb,
|
||||
unsigned short id; /* VLAN ID, given from frame TCI */
|
||||
unsigned char prio; /* user_priority, given from frame TCI */
|
||||
/* VLAN encapsulated Type/Length field, given from orig frame */
|
||||
unsigned short encap;
|
||||
__be16 encap;
|
||||
|
||||
fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
|
||||
if (fp == NULL)
|
||||
|
@@ -23,7 +23,7 @@ static struct ebt_entries initial_chain = {
|
||||
.policy = EBT_ACCEPT,
|
||||
};
|
||||
|
||||
static struct ebt_replace initial_table =
|
||||
static struct ebt_replace_kernel initial_table =
|
||||
{
|
||||
.name = "broute",
|
||||
.valid_hooks = 1 << NF_BR_BROUTING,
|
||||
|
@@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] =
|
||||
},
|
||||
};
|
||||
|
||||
static struct ebt_replace initial_table =
|
||||
static struct ebt_replace_kernel initial_table =
|
||||
{
|
||||
.name = "filter",
|
||||
.valid_hooks = FILTER_VALID_HOOKS,
|
||||
|
@@ -30,7 +30,7 @@ static struct ebt_entries initial_chains[] =
|
||||
}
|
||||
};
|
||||
|
||||
static struct ebt_replace initial_table =
|
||||
static struct ebt_replace_kernel initial_table =
|
||||
{
|
||||
.name = "nat",
|
||||
.valid_hooks = NAT_VALID_HOOKS,
|
||||
|
@@ -338,10 +338,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
|
||||
const char *name, unsigned int hookmask, unsigned int *cnt)
|
||||
{
|
||||
struct ebt_match *match;
|
||||
size_t left = ((char *)e + e->watchers_offset) - (char *)m;
|
||||
int ret;
|
||||
|
||||
if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
|
||||
((char *)e) + e->watchers_offset)
|
||||
if (left < sizeof(struct ebt_entry_match) ||
|
||||
left - sizeof(struct ebt_entry_match) < m->match_size)
|
||||
return -EINVAL;
|
||||
match = find_match_lock(m->u.name, &ret, &ebt_mutex);
|
||||
if (!match)
|
||||
@@ -367,10 +368,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
|
||||
const char *name, unsigned int hookmask, unsigned int *cnt)
|
||||
{
|
||||
struct ebt_watcher *watcher;
|
||||
size_t left = ((char *)e + e->target_offset) - (char *)w;
|
||||
int ret;
|
||||
|
||||
if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
|
||||
((char *)e) + e->target_offset)
|
||||
if (left < sizeof(struct ebt_entry_watcher) ||
|
||||
left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
|
||||
return -EINVAL;
|
||||
watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
|
||||
if (!watcher)
|
||||
@@ -391,35 +393,91 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ebt_verify_pointers(struct ebt_replace *repl,
|
||||
struct ebt_table_info *newinfo)
|
||||
{
|
||||
unsigned int limit = repl->entries_size;
|
||||
unsigned int valid_hooks = repl->valid_hooks;
|
||||
unsigned int offset = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++)
|
||||
newinfo->hook_entry[i] = NULL;
|
||||
|
||||
newinfo->entries_size = repl->entries_size;
|
||||
newinfo->nentries = repl->nentries;
|
||||
|
||||
while (offset < limit) {
|
||||
size_t left = limit - offset;
|
||||
struct ebt_entry *e = (void *)newinfo->entries + offset;
|
||||
|
||||
if (left < sizeof(unsigned int))
|
||||
break;
|
||||
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
|
||||
if ((valid_hooks & (1 << i)) == 0)
|
||||
continue;
|
||||
if ((char __user *)repl->hook_entry[i] ==
|
||||
repl->entries + offset)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
|
||||
if (e->bitmask != 0) {
|
||||
/* we make userspace set this right,
|
||||
so there is no misunderstanding */
|
||||
BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
|
||||
"in distinguisher\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (i != NF_BR_NUMHOOKS)
|
||||
newinfo->hook_entry[i] = (struct ebt_entries *)e;
|
||||
if (left < sizeof(struct ebt_entries))
|
||||
break;
|
||||
offset += sizeof(struct ebt_entries);
|
||||
} else {
|
||||
if (left < sizeof(struct ebt_entry))
|
||||
break;
|
||||
if (left < e->next_offset)
|
||||
break;
|
||||
offset += e->next_offset;
|
||||
}
|
||||
}
|
||||
if (offset != limit) {
|
||||
BUGPRINT("entries_size too small\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check if all valid hooks have a chain */
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
|
||||
if (!newinfo->hook_entry[i] &&
|
||||
(valid_hooks & (1 << i))) {
|
||||
BUGPRINT("Valid hook without chain\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this one is very careful, as it is the first function
|
||||
* to parse the userspace data
|
||||
*/
|
||||
static inline int
|
||||
ebt_check_entry_size_and_hooks(struct ebt_entry *e,
|
||||
struct ebt_table_info *newinfo, char *base, char *limit,
|
||||
struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
|
||||
unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
|
||||
struct ebt_table_info *newinfo,
|
||||
unsigned int *n, unsigned int *cnt,
|
||||
unsigned int *totalcnt, unsigned int *udc_cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
|
||||
if ((valid_hooks & (1 << i)) == 0)
|
||||
continue;
|
||||
if ( (char *)hook_entries[i] - base ==
|
||||
(char *)e - newinfo->entries)
|
||||
if ((void *)e == (void *)newinfo->hook_entry[i])
|
||||
break;
|
||||
}
|
||||
/* beginning of a new chain
|
||||
if i == NF_BR_NUMHOOKS it must be a user defined chain */
|
||||
if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
|
||||
if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
|
||||
/* we make userspace set this right,
|
||||
so there is no misunderstanding */
|
||||
BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
|
||||
"in distinguisher\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (i != NF_BR_NUMHOOKS || !e->bitmask) {
|
||||
/* this checks if the previous chain has as many entries
|
||||
as it said it has */
|
||||
if (*n != *cnt) {
|
||||
@@ -427,12 +485,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
|
||||
"in the chain\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* before we look at the struct, be sure it is not too big */
|
||||
if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
|
||||
> limit) {
|
||||
BUGPRINT("entries_size too small\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (((struct ebt_entries *)e)->policy != EBT_DROP &&
|
||||
((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
|
||||
/* only RETURN from udc */
|
||||
@@ -444,8 +496,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
|
||||
}
|
||||
if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
|
||||
(*udc_cnt)++;
|
||||
else
|
||||
newinfo->hook_entry[i] = (struct ebt_entries *)e;
|
||||
if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
|
||||
BUGPRINT("counter_offset != totalcnt");
|
||||
return -EINVAL;
|
||||
@@ -466,7 +516,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
|
||||
BUGPRINT("target size too small\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
(*cnt)++;
|
||||
(*totalcnt)++;
|
||||
return 0;
|
||||
@@ -485,17 +534,14 @@ struct ebt_cl_stack
|
||||
*/
|
||||
static inline int
|
||||
ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
||||
struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
|
||||
struct ebt_cl_stack *udc)
|
||||
unsigned int *n, struct ebt_cl_stack *udc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* we're only interested in chain starts */
|
||||
if (e->bitmask & EBT_ENTRY_OR_ENTRIES)
|
||||
if (e->bitmask)
|
||||
return 0;
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
|
||||
if ((valid_hooks & (1 << i)) == 0)
|
||||
continue;
|
||||
if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
|
||||
break;
|
||||
}
|
||||
@@ -541,7 +587,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
|
||||
{
|
||||
struct ebt_entry_target *t;
|
||||
|
||||
if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
|
||||
if (e->bitmask == 0)
|
||||
return 0;
|
||||
/* we're done */
|
||||
if (cnt && (*cnt)-- == 0)
|
||||
@@ -558,16 +604,17 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
|
||||
|
||||
static inline int
|
||||
ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
||||
const char *name, unsigned int *cnt, unsigned int valid_hooks,
|
||||
const char *name, unsigned int *cnt,
|
||||
struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
|
||||
{
|
||||
struct ebt_entry_target *t;
|
||||
struct ebt_target *target;
|
||||
unsigned int i, j, hook = 0, hookmask = 0;
|
||||
size_t gap = e->next_offset - e->target_offset;
|
||||
int ret;
|
||||
|
||||
/* don't mess with the struct ebt_entries */
|
||||
if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
|
||||
if (e->bitmask == 0)
|
||||
return 0;
|
||||
|
||||
if (e->bitmask & ~EBT_F_MASK) {
|
||||
@@ -584,7 +631,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
||||
}
|
||||
/* what hook do we belong to? */
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
|
||||
if ((valid_hooks & (1 << i)) == 0)
|
||||
if (!newinfo->hook_entry[i])
|
||||
continue;
|
||||
if ((char *)newinfo->hook_entry[i] < (char *)e)
|
||||
hook = i;
|
||||
@@ -625,8 +672,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
||||
|
||||
t->u.target = target;
|
||||
if (t->u.target == &ebt_standard_target) {
|
||||
if (e->target_offset + sizeof(struct ebt_standard_target) >
|
||||
e->next_offset) {
|
||||
if (gap < sizeof(struct ebt_standard_target)) {
|
||||
BUGPRINT("Standard target size too big\n");
|
||||
ret = -EFAULT;
|
||||
goto cleanup_watchers;
|
||||
@@ -637,8 +683,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
||||
ret = -EFAULT;
|
||||
goto cleanup_watchers;
|
||||
}
|
||||
} else if ((e->target_offset + t->target_size +
|
||||
sizeof(struct ebt_entry_target) > e->next_offset) ||
|
||||
} else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
|
||||
(t->u.target->check &&
|
||||
t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
|
||||
module_put(t->u.target->me);
|
||||
@@ -708,7 +753,9 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s
|
||||
BUGPRINT("loop\n");
|
||||
return -1;
|
||||
}
|
||||
/* this can't be 0, so the above test is correct */
|
||||
if (cl_s[i].hookmask & (1 << hooknr))
|
||||
goto letscontinue;
|
||||
/* this can't be 0, so the loop test is correct */
|
||||
cl_s[i].cs.n = pos + 1;
|
||||
pos = 0;
|
||||
cl_s[i].cs.e = ((void *)e + e->next_offset);
|
||||
@@ -728,42 +775,35 @@ letscontinue:
|
||||
}
|
||||
|
||||
/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
|
||||
static int translate_table(struct ebt_replace *repl,
|
||||
struct ebt_table_info *newinfo)
|
||||
static int translate_table(char *name, struct ebt_table_info *newinfo)
|
||||
{
|
||||
unsigned int i, j, k, udc_cnt;
|
||||
int ret;
|
||||
struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
|
||||
|
||||
i = 0;
|
||||
while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
|
||||
while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
|
||||
i++;
|
||||
if (i == NF_BR_NUMHOOKS) {
|
||||
BUGPRINT("No valid hooks specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {
|
||||
if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
|
||||
BUGPRINT("Chains don't start at beginning\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* make sure chains are ordered after each other in same order
|
||||
as their corresponding hooks */
|
||||
for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
|
||||
if (!(repl->valid_hooks & (1 << j)))
|
||||
if (!newinfo->hook_entry[j])
|
||||
continue;
|
||||
if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {
|
||||
if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
|
||||
BUGPRINT("Hook order must be followed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
i = j;
|
||||
}
|
||||
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++)
|
||||
newinfo->hook_entry[i] = NULL;
|
||||
|
||||
newinfo->entries_size = repl->entries_size;
|
||||
newinfo->nentries = repl->nentries;
|
||||
|
||||
/* do some early checkings and initialize some things */
|
||||
i = 0; /* holds the expected nr. of entries for the chain */
|
||||
j = 0; /* holds the up to now counted entries for the chain */
|
||||
@@ -771,9 +811,8 @@ static int translate_table(struct ebt_replace *repl,
|
||||
newinfo->nentries afterwards */
|
||||
udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
|
||||
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
|
||||
ebt_check_entry_size_and_hooks, newinfo, repl->entries,
|
||||
repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
|
||||
&udc_cnt, repl->valid_hooks);
|
||||
ebt_check_entry_size_and_hooks, newinfo,
|
||||
&i, &j, &k, &udc_cnt);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@@ -788,15 +827,6 @@ static int translate_table(struct ebt_replace *repl,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check if all valid hooks have a chain */
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
|
||||
if (newinfo->hook_entry[i] == NULL &&
|
||||
(repl->valid_hooks & (1 << i))) {
|
||||
BUGPRINT("Valid hook without chain\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the location of the udc, put them in an array
|
||||
while we're at it, allocate the chainstack */
|
||||
if (udc_cnt) {
|
||||
@@ -824,8 +854,7 @@ static int translate_table(struct ebt_replace *repl,
|
||||
return -ENOMEM;
|
||||
i = 0; /* the i'th udc */
|
||||
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
|
||||
ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
|
||||
repl->valid_hooks, cl_s);
|
||||
ebt_get_udc_positions, newinfo, &i, cl_s);
|
||||
/* sanity check */
|
||||
if (i != udc_cnt) {
|
||||
BUGPRINT("i != udc_cnt\n");
|
||||
@@ -836,7 +865,7 @@ static int translate_table(struct ebt_replace *repl,
|
||||
|
||||
/* Check for loops */
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++)
|
||||
if (repl->valid_hooks & (1 << i))
|
||||
if (newinfo->hook_entry[i])
|
||||
if (check_chainloops(newinfo->hook_entry[i],
|
||||
cl_s, udc_cnt, i, newinfo->entries)) {
|
||||
vfree(cl_s);
|
||||
@@ -856,8 +885,7 @@ static int translate_table(struct ebt_replace *repl,
|
||||
/* used to know what we need to clean up if something goes wrong */
|
||||
i = 0;
|
||||
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
|
||||
ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
|
||||
cl_s, udc_cnt);
|
||||
ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
|
||||
if (ret != 0) {
|
||||
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
|
||||
ebt_cleanup_entry, &i);
|
||||
@@ -954,7 +982,11 @@ static int do_replace(void __user *user, unsigned int len)
|
||||
|
||||
/* this can get initialized by translate_table() */
|
||||
newinfo->chainstack = NULL;
|
||||
ret = translate_table(&tmp, newinfo);
|
||||
ret = ebt_verify_pointers(&tmp, newinfo);
|
||||
if (ret != 0)
|
||||
goto free_counterstmp;
|
||||
|
||||
ret = translate_table(tmp.name, newinfo);
|
||||
|
||||
if (ret != 0)
|
||||
goto free_counterstmp;
|
||||
@@ -1125,35 +1157,47 @@ int ebt_register_table(struct ebt_table *table)
|
||||
{
|
||||
struct ebt_table_info *newinfo;
|
||||
struct ebt_table *t;
|
||||
struct ebt_replace_kernel *repl;
|
||||
int ret, i, countersize;
|
||||
void *p;
|
||||
|
||||
if (!table || !table->table ||!table->table->entries ||
|
||||
table->table->entries_size == 0 ||
|
||||
table->table->counters || table->private) {
|
||||
if (!table || !(repl = table->table) || !repl->entries ||
|
||||
repl->entries_size == 0 ||
|
||||
repl->counters || table->private) {
|
||||
BUGPRINT("Bad table data for ebt_register_table!!!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
countersize = COUNTER_OFFSET(table->table->nentries) *
|
||||
countersize = COUNTER_OFFSET(repl->nentries) *
|
||||
(highest_possible_processor_id()+1);
|
||||
newinfo = vmalloc(sizeof(*newinfo) + countersize);
|
||||
ret = -ENOMEM;
|
||||
if (!newinfo)
|
||||
return -ENOMEM;
|
||||
|
||||
newinfo->entries = vmalloc(table->table->entries_size);
|
||||
if (!(newinfo->entries))
|
||||
p = vmalloc(repl->entries_size);
|
||||
if (!p)
|
||||
goto free_newinfo;
|
||||
|
||||
memcpy(newinfo->entries, table->table->entries,
|
||||
table->table->entries_size);
|
||||
memcpy(p, repl->entries, repl->entries_size);
|
||||
newinfo->entries = p;
|
||||
|
||||
newinfo->entries_size = repl->entries_size;
|
||||
newinfo->nentries = repl->nentries;
|
||||
|
||||
if (countersize)
|
||||
memset(newinfo->counters, 0, countersize);
|
||||
|
||||
/* fill in newinfo and parse the entries */
|
||||
newinfo->chainstack = NULL;
|
||||
ret = translate_table(table->table, newinfo);
|
||||
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
|
||||
if ((repl->valid_hooks & (1 << i)) == 0)
|
||||
newinfo->hook_entry[i] = NULL;
|
||||
else
|
||||
newinfo->hook_entry[i] = p +
|
||||
((char *)repl->hook_entry[i] - repl->entries);
|
||||
}
|
||||
ret = translate_table(repl->name, newinfo);
|
||||
if (ret != 0) {
|
||||
BUGPRINT("Translate_table failed\n");
|
||||
goto free_chainstack;
|
||||
@@ -1277,33 +1321,33 @@ free_tmp:
|
||||
}
|
||||
|
||||
static inline int ebt_make_matchname(struct ebt_entry_match *m,
|
||||
char *base, char *ubase)
|
||||
char *base, char __user *ubase)
|
||||
{
|
||||
char *hlp = ubase - base + (char *)m;
|
||||
char __user *hlp = ubase + ((char *)m - base);
|
||||
if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
|
||||
char *base, char *ubase)
|
||||
char *base, char __user *ubase)
|
||||
{
|
||||
char *hlp = ubase - base + (char *)w;
|
||||
char __user *hlp = ubase + ((char *)w - base);
|
||||
if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
|
||||
static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
|
||||
{
|
||||
int ret;
|
||||
char *hlp;
|
||||
char __user *hlp;
|
||||
struct ebt_entry_target *t;
|
||||
|
||||
if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
|
||||
if (e->bitmask == 0)
|
||||
return 0;
|
||||
|
||||
hlp = ubase - base + (char *)e + e->target_offset;
|
||||
hlp = ubase + (((char *)e + e->target_offset) - base);
|
||||
t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
|
||||
|
||||
ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
|
||||
|
Reference in New Issue
Block a user