diff options
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br.c | 3 | ||||
-rw-r--r-- | net/bridge/br_device.c | 4 | ||||
-rw-r--r-- | net/bridge/br_if.c | 49 | ||||
-rw-r--r-- | net/bridge/br_netfilter_hooks.c | 1 | ||||
-rw-r--r-- | net/bridge/br_private.h | 3 | ||||
-rw-r--r-- | net/bridge/br_sysfs_br.c | 2 | ||||
-rw-r--r-- | net/bridge/br_sysfs_if.c | 36 | ||||
-rw-r--r-- | net/bridge/netfilter/Kconfig | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_ip.c | 58 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_stp.c | 6 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_broute.c | 1 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_filter.c | 1 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_nat.c | 1 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 74 | ||||
-rw-r--r-- | net/bridge/netfilter/nf_log_bridge.c | 1 | ||||
-rw-r--r-- | net/bridge/netfilter/nf_tables_bridge.c | 79 |
17 files changed, 138 insertions, 184 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c index a3f95ab9d6a3..671d13c10f6f 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -52,7 +52,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v switch (event) { case NETDEV_CHANGEMTU: - dev_set_mtu(br->dev, br_mtu(br)); + br_mtu_auto_adjust(br); break; case NETDEV_CHANGEADDR: @@ -188,7 +188,6 @@ static void __net_exit br_net_exit(struct net *net) static struct pernet_operations br_net_ops = { .exit = br_net_exit, - .async = true, }; static const struct stp_proto br_stp_proto = { diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 278fc999d355..e682a668ce57 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -224,11 +224,11 @@ static void br_get_stats64(struct net_device *dev, static int br_change_mtu(struct net_device *dev, int new_mtu) { struct net_bridge *br = netdev_priv(dev); - if (new_mtu > br_mtu(br)) - return -EINVAL; dev->mtu = new_mtu; + /* this flag will be cleared if the MTU was automatically adjusted */ + br->mtu_set_by_user = true; #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) /* remember the MTU in the rtable for PMTU */ dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 48dc4d2e2be3..82c1a6f430b3 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -424,41 +424,32 @@ int br_del_bridge(struct net *net, const char *name) return ret; } -static bool min_mtu(int a, int b) -{ - return a < b ? 1 : 0; -} - -static bool max_mtu(int a, int b) -{ - return a > b ? 1 : 0; -} - /* MTU of the bridge pseudo-device: ETH_DATA_LEN or the minimum of the ports */ -static int __br_mtu(const struct net_bridge *br, bool (compare_fn)(int, int)) +static int br_mtu_min(const struct net_bridge *br) { const struct net_bridge_port *p; - int mtu = 0; + int ret_mtu = 0; - ASSERT_RTNL(); + list_for_each_entry(p, &br->port_list, list) + if (!ret_mtu || ret_mtu > p->dev->mtu) + ret_mtu = p->dev->mtu; - if (list_empty(&br->port_list)) - mtu = ETH_DATA_LEN; - else { - list_for_each_entry(p, &br->port_list, list) { - if (!mtu || compare_fn(p->dev->mtu, mtu)) - mtu = p->dev->mtu; - } - } - return mtu; + return ret_mtu ? ret_mtu : ETH_DATA_LEN; } -int br_mtu(const struct net_bridge *br) +void br_mtu_auto_adjust(struct net_bridge *br) { - if (br->vlan_enabled) - return __br_mtu(br, max_mtu); - else - return __br_mtu(br, min_mtu); + ASSERT_RTNL(); + + /* if the bridge MTU was manually configured don't mess with it */ + if (br->mtu_set_by_user) + return; + + /* change to the minimum MTU and clear the flag which was set by + * the bridge ndo_change_mtu callback + */ + dev_set_mtu(br->dev, br_mtu_min(br)); + br->mtu_set_by_user = false; } static void br_set_gso_limits(struct net_bridge *br) @@ -612,7 +603,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, if (changed_addr) call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); - dev_set_mtu(br->dev, br_mtu(br)); + br_mtu_auto_adjust(br); br_set_gso_limits(br); kobject_uevent(&p->kobj, KOBJ_ADD); @@ -659,7 +650,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) */ del_nbp(p); - dev_set_mtu(br->dev, br_mtu(br)); + br_mtu_auto_adjust(br); br_set_gso_limits(br); spin_lock_bh(&br->lock); diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index c2120eb889a9..9b16eaf33819 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -969,7 +969,6 @@ static struct pernet_operations brnf_net_ops __read_mostly = { .exit = brnf_exit_net, .id = &brnf_net_id, .size = sizeof(struct brnf_net), - .async = true, }; static struct notifier_block brnf_notifier __read_mostly = { diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 048d5b51813b..a7cb3ece5031 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -410,6 +410,7 @@ struct net_bridge { int offload_fwd_mark; #endif bool neigh_suppress_enabled; + bool mtu_set_by_user; struct hlist_head fdb_list; }; @@ -578,7 +579,7 @@ int br_del_bridge(struct net *net, const char *name); int br_add_if(struct net_bridge *br, struct net_device *dev, struct netlink_ext_ack *extack); int br_del_if(struct net_bridge *br, struct net_device *dev); -int br_mtu(const struct net_bridge *br); +void br_mtu_auto_adjust(struct net_bridge *br); netdev_features_t br_features_recompute(struct net_bridge *br, netdev_features_t features); void br_port_flags_change(struct net_bridge_port *port, unsigned long mask); diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index b1be0dcfba6b..0318a69888d4 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -893,7 +893,7 @@ static ssize_t brforward_read(struct file *filp, struct kobject *kobj, static struct bin_attribute bridge_forward = { .attr = { .name = SYSFS_BRIDGE_FDB, - .mode = S_IRUGO, }, + .mode = 0444, }, .read = brforward_read, }; diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 126a8ea73c96..fd31ad83ec7b 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -44,7 +44,7 @@ static int store_##_name(struct net_bridge_port *p, unsigned long v) \ { \ return store_flag(p, v, _mask); \ } \ -static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR, \ +static BRPORT_ATTR(_name, 0644, \ show_##_name, store_##_name) static int store_flag(struct net_bridge_port *p, unsigned long v, @@ -71,7 +71,7 @@ static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) return sprintf(buf, "%d\n", p->path_cost); } -static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, +static BRPORT_ATTR(path_cost, 0644, show_path_cost, br_stp_set_path_cost); static ssize_t show_priority(struct net_bridge_port *p, char *buf) @@ -79,91 +79,91 @@ static ssize_t show_priority(struct net_bridge_port *p, char *buf) return sprintf(buf, "%d\n", p->priority); } -static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, +static BRPORT_ATTR(priority, 0644, show_priority, br_stp_set_port_priority); static ssize_t show_designated_root(struct net_bridge_port *p, char *buf) { return br_show_bridge_id(buf, &p->designated_root); } -static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL); +static BRPORT_ATTR(designated_root, 0444, show_designated_root, NULL); static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf) { return br_show_bridge_id(buf, &p->designated_bridge); } -static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL); +static BRPORT_ATTR(designated_bridge, 0444, show_designated_bridge, NULL); static ssize_t show_designated_port(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%d\n", p->designated_port); } -static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL); +static BRPORT_ATTR(designated_port, 0444, show_designated_port, NULL); static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%d\n", p->designated_cost); } -static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL); +static BRPORT_ATTR(designated_cost, 0444, show_designated_cost, NULL); static ssize_t show_port_id(struct net_bridge_port *p, char *buf) { return sprintf(buf, "0x%x\n", p->port_id); } -static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL); +static BRPORT_ATTR(port_id, 0444, show_port_id, NULL); static ssize_t show_port_no(struct net_bridge_port *p, char *buf) { return sprintf(buf, "0x%x\n", p->port_no); } -static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL); +static BRPORT_ATTR(port_no, 0444, show_port_no, NULL); static ssize_t show_change_ack(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%d\n", p->topology_change_ack); } -static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL); +static BRPORT_ATTR(change_ack, 0444, show_change_ack, NULL); static ssize_t show_config_pending(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%d\n", p->config_pending); } -static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL); +static BRPORT_ATTR(config_pending, 0444, show_config_pending, NULL); static ssize_t show_port_state(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%d\n", p->state); } -static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL); +static BRPORT_ATTR(state, 0444, show_port_state, NULL); static ssize_t show_message_age_timer(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%ld\n", br_timer_value(&p->message_age_timer)); } -static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL); +static BRPORT_ATTR(message_age_timer, 0444, show_message_age_timer, NULL); static ssize_t show_forward_delay_timer(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%ld\n", br_timer_value(&p->forward_delay_timer)); } -static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL); +static BRPORT_ATTR(forward_delay_timer, 0444, show_forward_delay_timer, NULL); static ssize_t show_hold_timer(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%ld\n", br_timer_value(&p->hold_timer)); } -static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); +static BRPORT_ATTR(hold_timer, 0444, show_hold_timer, NULL); static int store_flush(struct net_bridge_port *p, unsigned long v) { br_fdb_delete_by_port(p->br, p, 0, 0); // Don't delete local entry return 0; } -static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); +static BRPORT_ATTR(flush, 0200, NULL, store_flush); static ssize_t show_group_fwd_mask(struct net_bridge_port *p, char *buf) { @@ -179,7 +179,7 @@ static int store_group_fwd_mask(struct net_bridge_port *p, return 0; } -static BRPORT_ATTR(group_fwd_mask, S_IRUGO | S_IWUSR, show_group_fwd_mask, +static BRPORT_ATTR(group_fwd_mask, 0644, show_group_fwd_mask, store_group_fwd_mask); BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); @@ -204,7 +204,7 @@ static int store_multicast_router(struct net_bridge_port *p, { return br_multicast_set_port_router(p, v); } -static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, +static BRPORT_ATTR(multicast_router, 0644, show_multicast_router, store_multicast_router); BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE); diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig index 225d1668dfdd..f212447794bd 100644 --- a/net/bridge/netfilter/Kconfig +++ b/net/bridge/netfilter/Kconfig @@ -5,7 +5,7 @@ menuconfig NF_TABLES_BRIDGE depends on BRIDGE && NETFILTER && NF_TABLES select NETFILTER_FAMILY_BRIDGE - tristate "Ethernet Bridge nf_tables support" + bool "Ethernet Bridge nf_tables support" if NF_TABLES_BRIDGE diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile index 2f28e16de6c7..4bc758dd4a8c 100644 --- a/net/bridge/netfilter/Makefile +++ b/net/bridge/netfilter/Makefile @@ -3,7 +3,6 @@ # Makefile for the netfilter modules for Link Layer filtering on a bridge. # -obj-$(CONFIG_NF_TABLES_BRIDGE) += nf_tables_bridge.o obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o obj-$(CONFIG_NFT_BRIDGE_REJECT) += nft_reject_bridge.o diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index 2b46c50abce0..ffaa8ce2e724 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c @@ -19,9 +19,18 @@ #include <linux/netfilter_bridge/ebtables.h> #include <linux/netfilter_bridge/ebt_ip.h> -struct tcpudphdr { - __be16 src; - __be16 dst; +union pkthdr { + struct { + __be16 src; + __be16 dst; + } tcpudphdr; + struct { + u8 type; + u8 code; + } icmphdr; + struct { + u8 type; + } igmphdr; }; static bool @@ -30,8 +39,8 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) const struct ebt_ip_info *info = par->matchinfo; const struct iphdr *ih; struct iphdr _iph; - const struct tcpudphdr *pptr; - struct tcpudphdr _ports; + const union pkthdr *pptr; + union pkthdr _pkthdr; ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); if (ih == NULL) @@ -50,29 +59,43 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) if (info->bitmask & EBT_IP_PROTO) { if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol)) return false; - if (!(info->bitmask & EBT_IP_DPORT) && - !(info->bitmask & EBT_IP_SPORT)) + if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT | + EBT_IP_ICMP | EBT_IP_IGMP))) return true; if (ntohs(ih->frag_off) & IP_OFFSET) return false; + + /* min icmp/igmp headersize is 4, so sizeof(_pkthdr) is ok. */ pptr = skb_header_pointer(skb, ih->ihl*4, - sizeof(_ports), &_ports); + sizeof(_pkthdr), &_pkthdr); if (pptr == NULL) return false; if (info->bitmask & EBT_IP_DPORT) { - u32 dst = ntohs(pptr->dst); + u32 dst = ntohs(pptr->tcpudphdr.dst); if (NF_INVF(info, EBT_IP_DPORT, dst < info->dport[0] || dst > info->dport[1])) return false; } if (info->bitmask & EBT_IP_SPORT) { - u32 src = ntohs(pptr->src); + u32 src = ntohs(pptr->tcpudphdr.src); if (NF_INVF(info, EBT_IP_SPORT, src < info->sport[0] || src > info->sport[1])) return false; } + if ((info->bitmask & EBT_IP_ICMP) && + NF_INVF(info, EBT_IP_ICMP, + pptr->icmphdr.type < info->icmp_type[0] || + pptr->icmphdr.type > info->icmp_type[1] || + pptr->icmphdr.code < info->icmp_code[0] || + pptr->icmphdr.code > info->icmp_code[1])) + return false; + if ((info->bitmask & EBT_IP_IGMP) && + NF_INVF(info, EBT_IP_IGMP, + pptr->igmphdr.type < info->igmp_type[0] || + pptr->igmphdr.type > info->igmp_type[1])) + return false; } return true; } @@ -101,6 +124,21 @@ static int ebt_ip_mt_check(const struct xt_mtchk_param *par) return -EINVAL; if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) return -EINVAL; + if (info->bitmask & EBT_IP_ICMP) { + if ((info->invflags & EBT_IP_PROTO) || + info->protocol != IPPROTO_ICMP) + return -EINVAL; + if (info->icmp_type[0] > info->icmp_type[1] || + info->icmp_code[0] > info->icmp_code[1]) + return -EINVAL; + } + if (info->bitmask & EBT_IP_IGMP) { + if ((info->invflags & EBT_IP_PROTO) || + info->protocol != IPPROTO_IGMP) + return -EINVAL; + if (info->igmp_type[0] > info->igmp_type[1]) + return -EINVAL; + } return 0; } diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c index 3140eb912d7e..47ba98db145d 100644 --- a/net/bridge/netfilter/ebt_stp.c +++ b/net/bridge/netfilter/ebt_stp.c @@ -153,8 +153,6 @@ ebt_stp_mt(const struct sk_buff *skb, struct xt_action_param *par) static int ebt_stp_mt_check(const struct xt_mtchk_param *par) { const struct ebt_stp_info *info = par->matchinfo; - const u8 bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; - const u8 msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const struct ebt_entry *e = par->entryinfo; if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK || @@ -162,8 +160,8 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par) return -EINVAL; /* Make sure the match only receives stp frames */ if (!par->nft_compat && - (!ether_addr_equal(e->destmac, bridge_ula) || - !ether_addr_equal(e->destmsk, msk) || + (!ether_addr_equal(e->destmac, eth_stp_addr) || + !is_broadcast_ether_addr(e->destmsk) || !(e->bitmask & EBT_DESTMAC))) return -EINVAL; diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index f070b5e5b9dd..276b60262981 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -77,7 +77,6 @@ static void __net_exit broute_net_exit(struct net *net) static struct pernet_operations broute_net_ops = { .init = broute_net_init, .exit = broute_net_exit, - .async = true, }; static int __init ebtable_broute_init(void) diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 4151afc8efcc..c41da5fac84f 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -105,7 +105,6 @@ static void __net_exit frame_filter_net_exit(struct net *net) static struct pernet_operations frame_filter_net_ops = { .init = frame_filter_net_init, .exit = frame_filter_net_exit, - .async = true, }; static int __init ebtable_filter_init(void) diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index b8da2dfe2ec5..08df7406ecb3 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -105,7 +105,6 @@ static void __net_exit frame_nat_net_exit(struct net *net) static struct pernet_operations frame_nat_net_ops = { .init = frame_nat_net_init, .exit = frame_nat_net_exit, - .async = true, }; static int __init ebtable_nat_init(void) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index a94d23b0a9af..032e0fe45940 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -223,9 +223,7 @@ unsigned int ebt_do_table(struct sk_buff *skb, return NF_DROP; } - /* increase counter */ - (*(counter_base + i)).pcnt++; - (*(counter_base + i)).bcnt += skb->len; + ADD_COUNTER(*(counter_base + i), 1, skb->len); /* these should only watch: not modify, nor tell us * what to do with the packet @@ -358,12 +356,12 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par, left - sizeof(struct ebt_entry_match) < m->match_size) return -EINVAL; - match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0); + match = xt_find_match(NFPROTO_BRIDGE, m->u.name, m->u.revision); if (IS_ERR(match) || match->family != NFPROTO_BRIDGE) { if (!IS_ERR(match)) module_put(match->me); request_module("ebt_%s", m->u.name); - match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0); + match = xt_find_match(NFPROTO_BRIDGE, m->u.name, m->u.revision); } if (IS_ERR(match)) return PTR_ERR(match); @@ -968,10 +966,9 @@ static void get_counters(const struct ebt_counter *oldcounters, if (cpu == 0) continue; counter_base = COUNTER_BASE(oldcounters, nentries, cpu); - for (i = 0; i < nentries; i++) { - counters[i].pcnt += counter_base[i].pcnt; - counters[i].bcnt += counter_base[i].bcnt; - } + for (i = 0; i < nentries; i++) + ADD_COUNTER(counters[i], counter_base[i].pcnt, + counter_base[i].bcnt); } } @@ -1324,10 +1321,8 @@ static int do_update_counters(struct net *net, const char *name, write_lock_bh(&t->lock); /* we add to the counters of the first cpu */ - for (i = 0; i < num_counters; i++) { - t->private->counters[i].pcnt += tmp[i].pcnt; - t->private->counters[i].bcnt += tmp[i].bcnt; - } + for (i = 0; i < num_counters; i++) + ADD_COUNTER(t->private->counters[i], tmp[i].pcnt, tmp[i].bcnt); write_unlock_bh(&t->lock); ret = 0; @@ -1355,16 +1350,17 @@ static int update_counters(struct net *net, const void __user *user, static inline int ebt_obj_to_user(char __user *um, const char *_name, const char *data, int entrysize, - int usersize, int datasize) + int usersize, int datasize, u8 revision) { - char name[EBT_FUNCTION_MAXNAMELEN] = {0}; + char name[EBT_EXTENSION_MAXNAMELEN] = {0}; - /* ebtables expects 32 bytes long names but xt_match names are 29 bytes + /* ebtables expects 31 bytes long names but xt_match names are 29 bytes * long. Copy 29 bytes and fill remaining bytes with zeroes. */ strlcpy(name, _name, sizeof(name)); - if (copy_to_user(um, name, EBT_FUNCTION_MAXNAMELEN) || - put_user(datasize, (int __user *)(um + EBT_FUNCTION_MAXNAMELEN)) || + if (copy_to_user(um, name, EBT_EXTENSION_MAXNAMELEN) || + put_user(revision, (u8 __user *)(um + EBT_EXTENSION_MAXNAMELEN)) || + put_user(datasize, (int __user *)(um + EBT_EXTENSION_MAXNAMELEN + 1)) || xt_data_to_user(um + entrysize, data, usersize, datasize, XT_ALIGN(datasize))) return -EFAULT; @@ -1377,7 +1373,8 @@ static inline int ebt_match_to_user(const struct ebt_entry_match *m, { return ebt_obj_to_user(ubase + ((char *)m - base), m->u.match->name, m->data, sizeof(*m), - m->u.match->usersize, m->match_size); + m->u.match->usersize, m->match_size, + m->u.match->revision); } static inline int ebt_watcher_to_user(const struct ebt_entry_watcher *w, @@ -1385,7 +1382,8 @@ static inline int ebt_watcher_to_user(const struct ebt_entry_watcher *w, { return ebt_obj_to_user(ubase + ((char *)w - base), w->u.watcher->name, w->data, sizeof(*w), - w->u.watcher->usersize, w->watcher_size); + w->u.watcher->usersize, w->watcher_size, + w->u.watcher->revision); } static inline int ebt_entry_to_user(struct ebt_entry *e, const char *base, @@ -1416,7 +1414,8 @@ static inline int ebt_entry_to_user(struct ebt_entry *e, const char *base, if (ret != 0) return ret; ret = ebt_obj_to_user(hlp, t->u.target->name, t->data, sizeof(*t), - t->u.target->usersize, t->target_size); + t->u.target->usersize, t->target_size, + t->u.target->revision); if (ret != 0) return ret; @@ -1604,7 +1603,10 @@ struct compat_ebt_replace { /* struct ebt_entry_match, _target and _watcher have same layout */ struct compat_ebt_entry_mwt { union { - char name[EBT_FUNCTION_MAXNAMELEN]; + struct { + char name[EBT_EXTENSION_MAXNAMELEN]; + u8 revision; + }; compat_uptr_t ptr; } u; compat_uint_t match_size; @@ -1644,8 +1646,9 @@ static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr, if (WARN_ON(off >= m->match_size)) return -EINVAL; - if (copy_to_user(cm->u.name, match->name, - strlen(match->name) + 1) || put_user(msize, &cm->match_size)) + if (copy_to_user(cm->u.name, match->name, strlen(match->name) + 1) || + put_user(match->revision, &cm->u.revision) || + put_user(msize, &cm->match_size)) return -EFAULT; if (match->compat_to_user) { @@ -1675,8 +1678,9 @@ static int compat_target_to_user(struct ebt_entry_target *t, if (WARN_ON(off >= t->target_size)) return -EINVAL; - if (copy_to_user(cm->u.name, target->name, - strlen(target->name) + 1) || put_user(tsize, &cm->match_size)) + if (copy_to_user(cm->u.name, target->name, strlen(target->name) + 1) || + put_user(target->revision, &cm->u.revision) || + put_user(tsize, &cm->match_size)) return -EFAULT; if (target->compat_to_user) { @@ -1821,10 +1825,14 @@ static int compat_table_info(const struct ebt_table_info *info, { unsigned int size = info->entries_size; const void *entries = info->entries; + int ret; newinfo->entries_size = size; - xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); + ret = xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); + if (ret) + return ret; + return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, entries, newinfo); } @@ -1938,7 +1946,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, struct ebt_entries_buf_state *state, const unsigned char *base) { - char name[EBT_FUNCTION_MAXNAMELEN]; + char name[EBT_EXTENSION_MAXNAMELEN]; struct xt_match *match; struct xt_target *wt; void *dst = NULL; @@ -1952,7 +1960,8 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, switch (compat_mwt) { case EBT_COMPAT_MATCH: - match = xt_request_find_match(NFPROTO_BRIDGE, name, 0); + match = xt_request_find_match(NFPROTO_BRIDGE, name, + mwt->u.revision); if (IS_ERR(match)) return PTR_ERR(match); @@ -1971,7 +1980,8 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, break; case EBT_COMPAT_WATCHER: /* fallthrough */ case EBT_COMPAT_TARGET: - wt = xt_request_find_target(NFPROTO_BRIDGE, name, 0); + wt = xt_request_find_target(NFPROTO_BRIDGE, name, + mwt->u.revision); if (IS_ERR(wt)) return PTR_ERR(wt); off = xt_compat_target_offset(wt); @@ -2268,7 +2278,9 @@ static int compat_do_replace(struct net *net, void __user *user, xt_compat_lock(NFPROTO_BRIDGE); - xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); + ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); + if (ret < 0) + goto out_unlock; ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); if (ret < 0) goto out_unlock; diff --git a/net/bridge/netfilter/nf_log_bridge.c b/net/bridge/netfilter/nf_log_bridge.c index 91bfc2ac055a..bd2b3c78f59b 100644 --- a/net/bridge/netfilter/nf_log_bridge.c +++ b/net/bridge/netfilter/nf_log_bridge.c @@ -48,7 +48,6 @@ static void __net_exit nf_log_bridge_net_exit(struct net *net) static struct pernet_operations nf_log_bridge_net_ops = { .init = nf_log_bridge_net_init, .exit = nf_log_bridge_net_exit, - .async = true, }; static int __init nf_log_bridge_init(void) diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c deleted file mode 100644 index 5160cf614176..000000000000 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2008 Patrick McHardy <kaber@trash.net> - * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Development of this code funded by Astaro AG (http://www.astaro.com/) - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/netfilter_bridge.h> -#include <net/netfilter/nf_tables.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <net/netfilter/nf_tables_ipv4.h> -#include <net/netfilter/nf_tables_ipv6.h> - -static unsigned int -nft_do_chain_bridge(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -{ - struct nft_pktinfo pkt; - - nft_set_pktinfo(&pkt, skb, state); - - switch (eth_hdr(skb)->h_proto) { - case htons(ETH_P_IP): - nft_set_pktinfo_ipv4_validate(&pkt, skb); - break; - case htons(ETH_P_IPV6): - nft_set_pktinfo_ipv6_validate(&pkt, skb); - break; - default: - nft_set_pktinfo_unspec(&pkt, skb); - break; - } - - return nft_do_chain(&pkt, priv); -} - -static const struct nf_chain_type filter_bridge = { - .name = "filter", - .type = NFT_CHAIN_T_DEFAULT, - .family = NFPROTO_BRIDGE, - .owner = THIS_MODULE, - .hook_mask = (1 << NF_BR_PRE_ROUTING) | - (1 << NF_BR_LOCAL_IN) | - (1 << NF_BR_FORWARD) | - (1 << NF_BR_LOCAL_OUT) | - (1 << NF_BR_POST_ROUTING), - .hooks = { - [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, - [NF_BR_LOCAL_IN] = nft_do_chain_bridge, - [NF_BR_FORWARD] = nft_do_chain_bridge, - [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, - [NF_BR_POST_ROUTING] = nft_do_chain_bridge, - }, -}; - -static int __init nf_tables_bridge_init(void) -{ - return nft_register_chain_type(&filter_bridge); -} - -static void __exit nf_tables_bridge_exit(void) -{ - nft_unregister_chain_type(&filter_bridge); -} - -module_init(nf_tables_bridge_init); -module_exit(nf_tables_bridge_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); -MODULE_ALIAS_NFT_CHAIN(AF_BRIDGE, "filter"); |