Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter updates for your net-next tree,
they are:

1) Remove useless debug message when deleting IPVS service, from
Yannick Brosseau.

2) Get rid of compilation warning when CONFIG_PROC_FS is unset in
several spots of the IPVS code, from Arnd Bergmann.

3) Add prandom_u32 support to nft_meta, from Florian Westphal.

4) Remove unused variable in xt_osf, from Sudip Mukherjee.

5) Don't calculate IP checksum twice from netfilter ipv4 defrag hook
since fixing af_packet defragmentation issues, from Joe Stringer.

6) On-demand hook registration for iptables from netns. Instead of
registering the hooks for every available netns whenever we need
one of the support tables, we register this on the specific netns
that needs it, patchset from Florian Westphal.

7) Add missing port range selection to nf_tables masquerading support.

BTW, just for the record, there is a typo in the description of
5f6c253ebe93b0 ("netfilter: bridge: register hooks only when bridge
interface is added") that refers to the cluster match as deprecated, but
it is actually the CLUSTERIP target (which registers hooks
inconditionally) the one that is scheduled for removal.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+670 -397
+11 -18
include/linux/netfilter.h
··· 141 141 142 142 #ifdef HAVE_JUMP_LABEL 143 143 extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; 144 - 145 - static inline bool nf_hook_list_active(struct list_head *hook_list, 146 - u_int8_t pf, unsigned int hook) 147 - { 148 - if (__builtin_constant_p(pf) && 149 - __builtin_constant_p(hook)) 150 - return static_key_false(&nf_hooks_needed[pf][hook]); 151 - 152 - return !list_empty(hook_list); 153 - } 154 - #else 155 - static inline bool nf_hook_list_active(struct list_head *hook_list, 156 - u_int8_t pf, unsigned int hook) 157 - { 158 - return !list_empty(hook_list); 159 - } 160 144 #endif 161 145 162 146 int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state); ··· 161 177 int (*okfn)(struct net *, struct sock *, struct sk_buff *), 162 178 int thresh) 163 179 { 164 - struct list_head *hook_list = &net->nf.hooks[pf][hook]; 180 + struct list_head *hook_list; 165 181 166 - if (nf_hook_list_active(hook_list, pf, hook)) { 182 + #ifdef HAVE_JUMP_LABEL 183 + if (__builtin_constant_p(pf) && 184 + __builtin_constant_p(hook) && 185 + !static_key_false(&nf_hooks_needed[pf][hook])) 186 + return 1; 187 + #endif 188 + 189 + hook_list = &net->nf.hooks[pf][hook]; 190 + 191 + if (!list_empty(hook_list)) { 167 192 struct nf_hook_state state; 168 193 169 194 nf_hook_state_init(&state, hook_list, hook, thresh,
+4 -2
include/linux/netfilter/x_tables.h
··· 200 200 u_int8_t af; /* address/protocol family */ 201 201 int priority; /* hook order */ 202 202 203 + /* called when table is needed in the given netns */ 204 + int (*table_init)(struct net *net); 205 + 203 206 /* A unique name... */ 204 207 const char name[XT_TABLE_MAXNAMELEN]; 205 208 }; ··· 411 408 return cnt; 412 409 } 413 410 414 - struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *); 415 - void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *); 411 + struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *); 416 412 417 413 #ifdef CONFIG_COMPAT 418 414 #include <net/compat.h>
+5 -4
include/linux/netfilter_arp/arp_tables.h
··· 48 48 } 49 49 50 50 extern void *arpt_alloc_initial_table(const struct xt_table *); 51 - extern struct xt_table *arpt_register_table(struct net *net, 52 - const struct xt_table *table, 53 - const struct arpt_replace *repl); 54 - extern void arpt_unregister_table(struct xt_table *table); 51 + int arpt_register_table(struct net *net, const struct xt_table *table, 52 + const struct arpt_replace *repl, 53 + const struct nf_hook_ops *ops, struct xt_table **res); 54 + void arpt_unregister_table(struct net *net, struct xt_table *table, 55 + const struct nf_hook_ops *ops); 55 56 extern unsigned int arpt_do_table(struct sk_buff *skb, 56 57 const struct nf_hook_state *state, 57 58 struct xt_table *table);
+5 -4
include/linux/netfilter_ipv4/ip_tables.h
··· 24 24 25 25 extern void ipt_init(void) __init; 26 26 27 - extern struct xt_table *ipt_register_table(struct net *net, 28 - const struct xt_table *table, 29 - const struct ipt_replace *repl); 30 - extern void ipt_unregister_table(struct net *net, struct xt_table *table); 27 + int ipt_register_table(struct net *net, const struct xt_table *table, 28 + const struct ipt_replace *repl, 29 + const struct nf_hook_ops *ops, struct xt_table **res); 30 + void ipt_unregister_table(struct net *net, struct xt_table *table, 31 + const struct nf_hook_ops *ops); 31 32 32 33 /* Standard entry. */ 33 34 struct ipt_standard {
+5 -4
include/linux/netfilter_ipv6/ip6_tables.h
··· 25 25 extern void ip6t_init(void) __init; 26 26 27 27 extern void *ip6t_alloc_initial_table(const struct xt_table *); 28 - extern struct xt_table *ip6t_register_table(struct net *net, 29 - const struct xt_table *table, 30 - const struct ip6t_replace *repl); 31 - extern void ip6t_unregister_table(struct net *net, struct xt_table *table); 28 + int ip6t_register_table(struct net *net, const struct xt_table *table, 29 + const struct ip6t_replace *repl, 30 + const struct nf_hook_ops *ops, struct xt_table **res); 31 + void ip6t_unregister_table(struct net *net, struct xt_table *table, 32 + const struct nf_hook_ops *ops); 32 33 extern unsigned int ip6t_do_table(struct sk_buff *skb, 33 34 const struct nf_hook_state *state, 34 35 struct xt_table *table);
+3 -1
include/net/netfilter/nft_masq.h
··· 2 2 #define _NFT_MASQ_H_ 3 3 4 4 struct nft_masq { 5 - u32 flags; 5 + u32 flags; 6 + enum nft_registers sreg_proto_min:8; 7 + enum nft_registers sreg_proto_max:8; 6 8 }; 7 9 8 10 extern const struct nla_policy nft_masq_policy[];
+6
include/uapi/linux/netfilter/nf_tables.h
··· 681 681 * @NFT_META_IIFGROUP: packet input interface group 682 682 * @NFT_META_OIFGROUP: packet output interface group 683 683 * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid) 684 + * @NFT_META_PRANDOM: a 32bit pseudo-random number 684 685 */ 685 686 enum nft_meta_keys { 686 687 NFT_META_LEN, ··· 708 707 NFT_META_IIFGROUP, 709 708 NFT_META_OIFGROUP, 710 709 NFT_META_CGROUP, 710 + NFT_META_PRANDOM, 711 711 }; 712 712 713 713 /** ··· 951 949 * enum nft_masq_attributes - nf_tables masquerade expression attributes 952 950 * 953 951 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32) 952 + * @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers) 953 + * @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers) 954 954 */ 955 955 enum nft_masq_attributes { 956 956 NFTA_MASQ_UNSPEC, 957 957 NFTA_MASQ_FLAGS, 958 + NFTA_MASQ_REG_PROTO_MIN, 959 + NFTA_MASQ_REG_PROTO_MAX, 958 960 __NFTA_MASQ_MAX 959 961 }; 960 962 #define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
+1
lib/random32.c
··· 255 255 prandom_warmup(state); 256 256 } 257 257 } 258 + EXPORT_SYMBOL(prandom_seed_full_state); 258 259 259 260 /* 260 261 * Generate better values after random number generator
+65 -3
net/bridge/br_netfilter_hooks.c
··· 37 37 #include <net/addrconf.h> 38 38 #include <net/route.h> 39 39 #include <net/netfilter/br_netfilter.h> 40 + #include <net/netns/generic.h> 40 41 41 42 #include <asm/uaccess.h> 42 43 #include "br_private.h" 43 44 #ifdef CONFIG_SYSCTL 44 45 #include <linux/sysctl.h> 45 46 #endif 47 + 48 + static int brnf_net_id __read_mostly; 49 + 50 + struct brnf_net { 51 + bool enabled; 52 + }; 46 53 47 54 #ifdef CONFIG_SYSCTL 48 55 static struct ctl_table_header *brnf_sysctl_header; ··· 945 938 }, 946 939 }; 947 940 941 + static int brnf_device_event(struct notifier_block *unused, unsigned long event, 942 + void *ptr) 943 + { 944 + struct net_device *dev = netdev_notifier_info_to_dev(ptr); 945 + struct brnf_net *brnet; 946 + struct net *net; 947 + int ret; 948 + 949 + if (event != NETDEV_REGISTER || !(dev->priv_flags & IFF_EBRIDGE)) 950 + return NOTIFY_DONE; 951 + 952 + ASSERT_RTNL(); 953 + 954 + net = dev_net(dev); 955 + brnet = net_generic(net, brnf_net_id); 956 + if (brnet->enabled) 957 + return NOTIFY_OK; 958 + 959 + ret = nf_register_net_hooks(net, br_nf_ops, ARRAY_SIZE(br_nf_ops)); 960 + if (ret) 961 + return NOTIFY_BAD; 962 + 963 + brnet->enabled = true; 964 + return NOTIFY_OK; 965 + } 966 + 967 + static void __net_exit brnf_exit_net(struct net *net) 968 + { 969 + struct brnf_net *brnet = net_generic(net, brnf_net_id); 970 + 971 + if (!brnet->enabled) 972 + return; 973 + 974 + nf_unregister_net_hooks(net, br_nf_ops, ARRAY_SIZE(br_nf_ops)); 975 + brnet->enabled = false; 976 + } 977 + 978 + static struct pernet_operations brnf_net_ops __read_mostly = { 979 + .exit = brnf_exit_net, 980 + .id = &brnf_net_id, 981 + .size = sizeof(struct brnf_net), 982 + }; 983 + 984 + static struct notifier_block brnf_notifier __read_mostly = { 985 + .notifier_call = brnf_device_event, 986 + }; 987 + 948 988 #ifdef CONFIG_SYSCTL 949 989 static 950 990 int brnf_sysctl_call_tables(struct ctl_table *ctl, int write, ··· 1057 1003 { 1058 1004 int ret; 1059 1005 1060 - ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 1006 + ret = register_pernet_subsys(&brnf_net_ops); 1061 1007 if (ret < 0) 1062 1008 return ret; 1009 + 1010 + ret = register_netdevice_notifier(&brnf_notifier); 1011 + if (ret < 0) { 1012 + unregister_pernet_subsys(&brnf_net_ops); 1013 + return ret; 1014 + } 1063 1015 1064 1016 #ifdef CONFIG_SYSCTL 1065 1017 brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table); 1066 1018 if (brnf_sysctl_header == NULL) { 1067 1019 printk(KERN_WARNING 1068 1020 "br_netfilter: can't register to sysctl.\n"); 1069 - nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 1021 + unregister_netdevice_notifier(&brnf_notifier); 1022 + unregister_pernet_subsys(&brnf_net_ops); 1070 1023 return -ENOMEM; 1071 1024 } 1072 1025 #endif ··· 1085 1024 static void __exit br_netfilter_fini(void) 1086 1025 { 1087 1026 RCU_INIT_POINTER(nf_br_ops, NULL); 1088 - nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 1027 + unregister_netdevice_notifier(&brnf_notifier); 1028 + unregister_pernet_subsys(&brnf_net_ops); 1089 1029 #ifdef CONFIG_SYSCTL 1090 1030 unregister_net_sysctl_table(brnf_sysctl_header); 1091 1031 #endif
+54 -38
net/ipv4/netfilter/arp_tables.c
··· 1780 1780 return ret; 1781 1781 } 1782 1782 1783 - struct xt_table *arpt_register_table(struct net *net, 1784 - const struct xt_table *table, 1785 - const struct arpt_replace *repl) 1786 - { 1787 - int ret; 1788 - struct xt_table_info *newinfo; 1789 - struct xt_table_info bootstrap = {0}; 1790 - void *loc_cpu_entry; 1791 - struct xt_table *new_table; 1792 - 1793 - newinfo = xt_alloc_table_info(repl->size); 1794 - if (!newinfo) { 1795 - ret = -ENOMEM; 1796 - goto out; 1797 - } 1798 - 1799 - loc_cpu_entry = newinfo->entries; 1800 - memcpy(loc_cpu_entry, repl->entries, repl->size); 1801 - 1802 - ret = translate_table(newinfo, loc_cpu_entry, repl); 1803 - duprintf("arpt_register_table: translate table gives %d\n", ret); 1804 - if (ret != 0) 1805 - goto out_free; 1806 - 1807 - new_table = xt_register_table(net, table, &bootstrap, newinfo); 1808 - if (IS_ERR(new_table)) { 1809 - ret = PTR_ERR(new_table); 1810 - goto out_free; 1811 - } 1812 - return new_table; 1813 - 1814 - out_free: 1815 - xt_free_table_info(newinfo); 1816 - out: 1817 - return ERR_PTR(ret); 1818 - } 1819 - 1820 - void arpt_unregister_table(struct xt_table *table) 1783 + static void __arpt_unregister_table(struct xt_table *table) 1821 1784 { 1822 1785 struct xt_table_info *private; 1823 1786 void *loc_cpu_entry; ··· 1796 1833 if (private->number > private->initial_entries) 1797 1834 module_put(table_owner); 1798 1835 xt_free_table_info(private); 1836 + } 1837 + 1838 + int arpt_register_table(struct net *net, 1839 + const struct xt_table *table, 1840 + const struct arpt_replace *repl, 1841 + const struct nf_hook_ops *ops, 1842 + struct xt_table **res) 1843 + { 1844 + int ret; 1845 + struct xt_table_info *newinfo; 1846 + struct xt_table_info bootstrap = {0}; 1847 + void *loc_cpu_entry; 1848 + struct xt_table *new_table; 1849 + 1850 + newinfo = xt_alloc_table_info(repl->size); 1851 + if (!newinfo) 1852 + return -ENOMEM; 1853 + 1854 + loc_cpu_entry = newinfo->entries; 1855 + memcpy(loc_cpu_entry, repl->entries, repl->size); 1856 + 1857 + ret = translate_table(newinfo, loc_cpu_entry, repl); 1858 + duprintf("arpt_register_table: translate table gives %d\n", ret); 1859 + if (ret != 0) 1860 + goto out_free; 1861 + 1862 + new_table = xt_register_table(net, table, &bootstrap, newinfo); 1863 + if (IS_ERR(new_table)) { 1864 + ret = PTR_ERR(new_table); 1865 + goto out_free; 1866 + } 1867 + 1868 + /* set res now, will see skbs right after nf_register_net_hooks */ 1869 + WRITE_ONCE(*res, new_table); 1870 + 1871 + ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks)); 1872 + if (ret != 0) { 1873 + __arpt_unregister_table(new_table); 1874 + *res = NULL; 1875 + } 1876 + 1877 + return ret; 1878 + 1879 + out_free: 1880 + xt_free_table_info(newinfo); 1881 + return ret; 1882 + } 1883 + 1884 + void arpt_unregister_table(struct net *net, struct xt_table *table, 1885 + const struct nf_hook_ops *ops) 1886 + { 1887 + nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); 1888 + __arpt_unregister_table(table); 1799 1889 } 1800 1890 1801 1891 /* The built-in targets: standard (NULL) and error. */
+23 -17
net/ipv4/netfilter/arptable_filter.c
··· 17 17 #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ 18 18 (1 << NF_ARP_FORWARD)) 19 19 20 + static int __net_init arptable_filter_table_init(struct net *net); 21 + 20 22 static const struct xt_table packet_filter = { 21 23 .name = "filter", 22 24 .valid_hooks = FILTER_VALID_HOOKS, 23 25 .me = THIS_MODULE, 24 26 .af = NFPROTO_ARP, 25 27 .priority = NF_IP_PRI_FILTER, 28 + .table_init = arptable_filter_table_init, 26 29 }; 27 30 28 31 /* The work comes in here from netfilter.c */ ··· 38 35 39 36 static struct nf_hook_ops *arpfilter_ops __read_mostly; 40 37 41 - static int __net_init arptable_filter_net_init(struct net *net) 38 + static int __net_init arptable_filter_table_init(struct net *net) 42 39 { 43 40 struct arpt_replace *repl; 44 - 41 + int err; 42 + 43 + if (net->ipv4.arptable_filter) 44 + return 0; 45 + 45 46 repl = arpt_alloc_initial_table(&packet_filter); 46 47 if (repl == NULL) 47 48 return -ENOMEM; 48 - net->ipv4.arptable_filter = 49 - arpt_register_table(net, &packet_filter, repl); 49 + err = arpt_register_table(net, &packet_filter, repl, arpfilter_ops, 50 + &net->ipv4.arptable_filter); 50 51 kfree(repl); 51 - return PTR_ERR_OR_ZERO(net->ipv4.arptable_filter); 52 + return err; 52 53 } 53 54 54 55 static void __net_exit arptable_filter_net_exit(struct net *net) 55 56 { 56 - arpt_unregister_table(net->ipv4.arptable_filter); 57 + if (!net->ipv4.arptable_filter) 58 + return; 59 + arpt_unregister_table(net, net->ipv4.arptable_filter, arpfilter_ops); 60 + net->ipv4.arptable_filter = NULL; 57 61 } 58 62 59 63 static struct pernet_operations arptable_filter_net_ops = { 60 - .init = arptable_filter_net_init, 61 64 .exit = arptable_filter_net_exit, 62 65 }; 63 66 ··· 71 62 { 72 63 int ret; 73 64 65 + arpfilter_ops = xt_hook_ops_alloc(&packet_filter, arptable_filter_hook); 66 + if (IS_ERR(arpfilter_ops)) 67 + return PTR_ERR(arpfilter_ops); 68 + 74 69 ret = register_pernet_subsys(&arptable_filter_net_ops); 75 - if (ret < 0) 70 + if (ret < 0) { 71 + kfree(arpfilter_ops); 76 72 return ret; 77 - 78 - arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook); 79 - if (IS_ERR(arpfilter_ops)) { 80 - ret = PTR_ERR(arpfilter_ops); 81 - goto cleanup_table; 82 73 } 83 - return ret; 84 74 85 - cleanup_table: 86 - unregister_pernet_subsys(&arptable_filter_net_ops); 87 75 return ret; 88 76 } 89 77 90 78 static void __exit arptable_filter_fini(void) 91 79 { 92 - xt_hook_unlink(&packet_filter, arpfilter_ops); 93 80 unregister_pernet_subsys(&arptable_filter_net_ops); 81 + kfree(arpfilter_ops); 94 82 } 95 83 96 84 module_init(arptable_filter_init);
+51 -38
net/ipv4/netfilter/ip_tables.c
··· 2062 2062 return ret; 2063 2063 } 2064 2064 2065 - struct xt_table *ipt_register_table(struct net *net, 2066 - const struct xt_table *table, 2067 - const struct ipt_replace *repl) 2068 - { 2069 - int ret; 2070 - struct xt_table_info *newinfo; 2071 - struct xt_table_info bootstrap = {0}; 2072 - void *loc_cpu_entry; 2073 - struct xt_table *new_table; 2074 - 2075 - newinfo = xt_alloc_table_info(repl->size); 2076 - if (!newinfo) { 2077 - ret = -ENOMEM; 2078 - goto out; 2079 - } 2080 - 2081 - loc_cpu_entry = newinfo->entries; 2082 - memcpy(loc_cpu_entry, repl->entries, repl->size); 2083 - 2084 - ret = translate_table(net, newinfo, loc_cpu_entry, repl); 2085 - if (ret != 0) 2086 - goto out_free; 2087 - 2088 - new_table = xt_register_table(net, table, &bootstrap, newinfo); 2089 - if (IS_ERR(new_table)) { 2090 - ret = PTR_ERR(new_table); 2091 - goto out_free; 2092 - } 2093 - 2094 - return new_table; 2095 - 2096 - out_free: 2097 - xt_free_table_info(newinfo); 2098 - out: 2099 - return ERR_PTR(ret); 2100 - } 2101 - 2102 - void ipt_unregister_table(struct net *net, struct xt_table *table) 2065 + static void __ipt_unregister_table(struct net *net, struct xt_table *table) 2103 2066 { 2104 2067 struct xt_table_info *private; 2105 2068 void *loc_cpu_entry; ··· 2078 2115 if (private->number > private->initial_entries) 2079 2116 module_put(table_owner); 2080 2117 xt_free_table_info(private); 2118 + } 2119 + 2120 + int ipt_register_table(struct net *net, const struct xt_table *table, 2121 + const struct ipt_replace *repl, 2122 + const struct nf_hook_ops *ops, struct xt_table **res) 2123 + { 2124 + int ret; 2125 + struct xt_table_info *newinfo; 2126 + struct xt_table_info bootstrap = {0}; 2127 + void *loc_cpu_entry; 2128 + struct xt_table *new_table; 2129 + 2130 + newinfo = xt_alloc_table_info(repl->size); 2131 + if (!newinfo) 2132 + return -ENOMEM; 2133 + 2134 + loc_cpu_entry = newinfo->entries; 2135 + memcpy(loc_cpu_entry, repl->entries, repl->size); 2136 + 2137 + ret = translate_table(net, newinfo, loc_cpu_entry, repl); 2138 + if (ret != 0) 2139 + goto out_free; 2140 + 2141 + new_table = xt_register_table(net, table, &bootstrap, newinfo); 2142 + if (IS_ERR(new_table)) { 2143 + ret = PTR_ERR(new_table); 2144 + goto out_free; 2145 + } 2146 + 2147 + /* set res now, will see skbs right after nf_register_net_hooks */ 2148 + WRITE_ONCE(*res, new_table); 2149 + 2150 + ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks)); 2151 + if (ret != 0) { 2152 + __ipt_unregister_table(net, new_table); 2153 + *res = NULL; 2154 + } 2155 + 2156 + return ret; 2157 + 2158 + out_free: 2159 + xt_free_table_info(newinfo); 2160 + return ret; 2161 + } 2162 + 2163 + void ipt_unregister_table(struct net *net, struct xt_table *table, 2164 + const struct nf_hook_ops *ops) 2165 + { 2166 + nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); 2167 + __ipt_unregister_table(net, table); 2081 2168 } 2082 2169 2083 2170 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
+29 -15
net/ipv4/netfilter/iptable_filter.c
··· 23 23 #define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \ 24 24 (1 << NF_INET_FORWARD) | \ 25 25 (1 << NF_INET_LOCAL_OUT)) 26 + static int __net_init iptable_filter_table_init(struct net *net); 26 27 27 28 static const struct xt_table packet_filter = { 28 29 .name = "filter", ··· 31 30 .me = THIS_MODULE, 32 31 .af = NFPROTO_IPV4, 33 32 .priority = NF_IP_PRI_FILTER, 33 + .table_init = iptable_filter_table_init, 34 34 }; 35 35 36 36 static unsigned int ··· 50 48 static struct nf_hook_ops *filter_ops __read_mostly; 51 49 52 50 /* Default to forward because I got too much mail already. */ 53 - static bool forward = true; 51 + static bool forward __read_mostly = true; 54 52 module_param(forward, bool, 0000); 55 53 56 - static int __net_init iptable_filter_net_init(struct net *net) 54 + static int __net_init iptable_filter_table_init(struct net *net) 57 55 { 58 56 struct ipt_replace *repl; 57 + int err; 58 + 59 + if (net->ipv4.iptable_filter) 60 + return 0; 59 61 60 62 repl = ipt_alloc_initial_table(&packet_filter); 61 63 if (repl == NULL) ··· 68 62 ((struct ipt_standard *)repl->entries)[1].target.verdict = 69 63 forward ? -NF_ACCEPT - 1 : -NF_DROP - 1; 70 64 71 - net->ipv4.iptable_filter = 72 - ipt_register_table(net, &packet_filter, repl); 65 + err = ipt_register_table(net, &packet_filter, repl, filter_ops, 66 + &net->ipv4.iptable_filter); 73 67 kfree(repl); 74 - return PTR_ERR_OR_ZERO(net->ipv4.iptable_filter); 68 + return err; 69 + } 70 + 71 + static int __net_init iptable_filter_net_init(struct net *net) 72 + { 73 + if (net == &init_net || !forward) 74 + return iptable_filter_table_init(net); 75 + 76 + return 0; 75 77 } 76 78 77 79 static void __net_exit iptable_filter_net_exit(struct net *net) 78 80 { 79 - ipt_unregister_table(net, net->ipv4.iptable_filter); 81 + if (!net->ipv4.iptable_filter) 82 + return; 83 + ipt_unregister_table(net, net->ipv4.iptable_filter, filter_ops); 84 + net->ipv4.iptable_filter = NULL; 80 85 } 81 86 82 87 static struct pernet_operations iptable_filter_net_ops = { ··· 99 82 { 100 83 int ret; 101 84 85 + filter_ops = xt_hook_ops_alloc(&packet_filter, iptable_filter_hook); 86 + if (IS_ERR(filter_ops)) 87 + return PTR_ERR(filter_ops); 88 + 102 89 ret = register_pernet_subsys(&iptable_filter_net_ops); 103 90 if (ret < 0) 104 - return ret; 105 - 106 - /* Register hooks */ 107 - filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); 108 - if (IS_ERR(filter_ops)) { 109 - ret = PTR_ERR(filter_ops); 110 - unregister_pernet_subsys(&iptable_filter_net_ops); 111 - } 91 + kfree(filter_ops); 112 92 113 93 return ret; 114 94 } 115 95 116 96 static void __exit iptable_filter_fini(void) 117 97 { 118 - xt_hook_unlink(&packet_filter, filter_ops); 119 98 unregister_pernet_subsys(&iptable_filter_net_ops); 99 + kfree(filter_ops); 120 100 } 121 101 122 102 module_init(iptable_filter_init);
+29 -14
net/ipv4/netfilter/iptable_mangle.c
··· 28 28 (1 << NF_INET_LOCAL_OUT) | \ 29 29 (1 << NF_INET_POST_ROUTING)) 30 30 31 + static int __net_init iptable_mangle_table_init(struct net *net); 32 + 31 33 static const struct xt_table packet_mangler = { 32 34 .name = "mangle", 33 35 .valid_hooks = MANGLE_VALID_HOOKS, 34 36 .me = THIS_MODULE, 35 37 .af = NFPROTO_IPV4, 36 38 .priority = NF_IP_PRI_MANGLE, 39 + .table_init = iptable_mangle_table_init, 37 40 }; 38 41 39 42 static unsigned int ··· 95 92 } 96 93 97 94 static struct nf_hook_ops *mangle_ops __read_mostly; 98 - 99 - static int __net_init iptable_mangle_net_init(struct net *net) 95 + static int __net_init iptable_mangle_table_init(struct net *net) 100 96 { 101 97 struct ipt_replace *repl; 98 + int ret; 99 + 100 + if (net->ipv4.iptable_mangle) 101 + return 0; 102 102 103 103 repl = ipt_alloc_initial_table(&packet_mangler); 104 104 if (repl == NULL) 105 105 return -ENOMEM; 106 - net->ipv4.iptable_mangle = 107 - ipt_register_table(net, &packet_mangler, repl); 106 + ret = ipt_register_table(net, &packet_mangler, repl, mangle_ops, 107 + &net->ipv4.iptable_mangle); 108 108 kfree(repl); 109 - return PTR_ERR_OR_ZERO(net->ipv4.iptable_mangle); 109 + return ret; 110 110 } 111 111 112 112 static void __net_exit iptable_mangle_net_exit(struct net *net) 113 113 { 114 - ipt_unregister_table(net, net->ipv4.iptable_mangle); 114 + if (!net->ipv4.iptable_mangle) 115 + return; 116 + ipt_unregister_table(net, net->ipv4.iptable_mangle, mangle_ops); 117 + net->ipv4.iptable_mangle = NULL; 115 118 } 116 119 117 120 static struct pernet_operations iptable_mangle_net_ops = { 118 - .init = iptable_mangle_net_init, 119 121 .exit = iptable_mangle_net_exit, 120 122 }; 121 123 ··· 128 120 { 129 121 int ret; 130 122 131 - ret = register_pernet_subsys(&iptable_mangle_net_ops); 132 - if (ret < 0) 133 - return ret; 134 - 135 - /* Register hooks */ 136 - mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); 123 + mangle_ops = xt_hook_ops_alloc(&packet_mangler, iptable_mangle_hook); 137 124 if (IS_ERR(mangle_ops)) { 138 125 ret = PTR_ERR(mangle_ops); 126 + return ret; 127 + } 128 + 129 + ret = register_pernet_subsys(&iptable_mangle_net_ops); 130 + if (ret < 0) { 131 + kfree(mangle_ops); 132 + return ret; 133 + } 134 + 135 + ret = iptable_mangle_table_init(&init_net); 136 + if (ret) { 139 137 unregister_pernet_subsys(&iptable_mangle_net_ops); 138 + kfree(mangle_ops); 140 139 } 141 140 142 141 return ret; ··· 151 136 152 137 static void __exit iptable_mangle_fini(void) 153 138 { 154 - xt_hook_unlink(&packet_mangler, mangle_ops); 155 139 unregister_pernet_subsys(&iptable_mangle_net_ops); 140 + kfree(mangle_ops); 156 141 } 157 142 158 143 module_init(iptable_mangle_init);
+22 -19
net/ipv4/netfilter/iptable_nat.c
··· 18 18 #include <net/netfilter/nf_nat_core.h> 19 19 #include <net/netfilter/nf_nat_l3proto.h> 20 20 21 + static int __net_init iptable_nat_table_init(struct net *net); 22 + 21 23 static const struct xt_table nf_nat_ipv4_table = { 22 24 .name = "nat", 23 25 .valid_hooks = (1 << NF_INET_PRE_ROUTING) | ··· 28 26 (1 << NF_INET_LOCAL_IN), 29 27 .me = THIS_MODULE, 30 28 .af = NFPROTO_IPV4, 29 + .table_init = iptable_nat_table_init, 31 30 }; 32 31 33 32 static unsigned int iptable_nat_do_chain(void *priv, ··· 98 95 }, 99 96 }; 100 97 101 - static int __net_init iptable_nat_net_init(struct net *net) 98 + static int __net_init iptable_nat_table_init(struct net *net) 102 99 { 103 100 struct ipt_replace *repl; 101 + int ret; 102 + 103 + if (net->ipv4.nat_table) 104 + return 0; 104 105 105 106 repl = ipt_alloc_initial_table(&nf_nat_ipv4_table); 106 107 if (repl == NULL) 107 108 return -ENOMEM; 108 - net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl); 109 + ret = ipt_register_table(net, &nf_nat_ipv4_table, repl, 110 + nf_nat_ipv4_ops, &net->ipv4.nat_table); 109 111 kfree(repl); 110 - return PTR_ERR_OR_ZERO(net->ipv4.nat_table); 112 + return ret; 111 113 } 112 114 113 115 static void __net_exit iptable_nat_net_exit(struct net *net) 114 116 { 115 - ipt_unregister_table(net, net->ipv4.nat_table); 117 + if (!net->ipv4.nat_table) 118 + return; 119 + ipt_unregister_table(net, net->ipv4.nat_table, nf_nat_ipv4_ops); 120 + net->ipv4.nat_table = NULL; 116 121 } 117 122 118 123 static struct pernet_operations iptable_nat_net_ops = { 119 - .init = iptable_nat_net_init, 120 124 .exit = iptable_nat_net_exit, 121 125 }; 122 126 123 127 static int __init iptable_nat_init(void) 124 128 { 125 - int err; 129 + int ret = register_pernet_subsys(&iptable_nat_net_ops); 126 130 127 - err = register_pernet_subsys(&iptable_nat_net_ops); 128 - if (err < 0) 129 - goto err1; 131 + if (ret) 132 + return ret; 130 133 131 - err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 132 - if (err < 0) 133 - goto err2; 134 - return 0; 135 - 136 - err2: 137 - unregister_pernet_subsys(&iptable_nat_net_ops); 138 - err1: 139 - return err; 134 + ret = iptable_nat_table_init(&init_net); 135 + if (ret) 136 + unregister_pernet_subsys(&iptable_nat_net_ops); 137 + return ret; 140 138 } 141 139 142 140 static void __exit iptable_nat_exit(void) 143 141 { 144 - nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 145 142 unregister_pernet_subsys(&iptable_nat_net_ops); 146 143 } 147 144
+28 -14
net/ipv4/netfilter/iptable_raw.c
··· 10 10 11 11 #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) 12 12 13 + static int __net_init iptable_raw_table_init(struct net *net); 14 + 13 15 static const struct xt_table packet_raw = { 14 16 .name = "raw", 15 17 .valid_hooks = RAW_VALID_HOOKS, 16 18 .me = THIS_MODULE, 17 19 .af = NFPROTO_IPV4, 18 20 .priority = NF_IP_PRI_RAW, 21 + .table_init = iptable_raw_table_init, 19 22 }; 20 23 21 24 /* The work comes in here from netfilter.c. */ ··· 37 34 38 35 static struct nf_hook_ops *rawtable_ops __read_mostly; 39 36 40 - static int __net_init iptable_raw_net_init(struct net *net) 37 + static int __net_init iptable_raw_table_init(struct net *net) 41 38 { 42 39 struct ipt_replace *repl; 40 + int ret; 41 + 42 + if (net->ipv4.iptable_raw) 43 + return 0; 43 44 44 45 repl = ipt_alloc_initial_table(&packet_raw); 45 46 if (repl == NULL) 46 47 return -ENOMEM; 47 - net->ipv4.iptable_raw = 48 - ipt_register_table(net, &packet_raw, repl); 48 + ret = ipt_register_table(net, &packet_raw, repl, rawtable_ops, 49 + &net->ipv4.iptable_raw); 49 50 kfree(repl); 50 - return PTR_ERR_OR_ZERO(net->ipv4.iptable_raw); 51 + return ret; 51 52 } 52 53 53 54 static void __net_exit iptable_raw_net_exit(struct net *net) 54 55 { 55 - ipt_unregister_table(net, net->ipv4.iptable_raw); 56 + if (!net->ipv4.iptable_raw) 57 + return; 58 + ipt_unregister_table(net, net->ipv4.iptable_raw, rawtable_ops); 59 + net->ipv4.iptable_raw = NULL; 56 60 } 57 61 58 62 static struct pernet_operations iptable_raw_net_ops = { 59 - .init = iptable_raw_net_init, 60 63 .exit = iptable_raw_net_exit, 61 64 }; 62 65 ··· 70 61 { 71 62 int ret; 72 63 73 - ret = register_pernet_subsys(&iptable_raw_net_ops); 74 - if (ret < 0) 75 - return ret; 64 + rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook); 65 + if (IS_ERR(rawtable_ops)) 66 + return PTR_ERR(rawtable_ops); 76 67 77 - /* Register hooks */ 78 - rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); 79 - if (IS_ERR(rawtable_ops)) { 80 - ret = PTR_ERR(rawtable_ops); 68 + ret = register_pernet_subsys(&iptable_raw_net_ops); 69 + if (ret < 0) { 70 + kfree(rawtable_ops); 71 + return ret; 72 + } 73 + 74 + ret = iptable_raw_table_init(&init_net); 75 + if (ret) { 81 76 unregister_pernet_subsys(&iptable_raw_net_ops); 77 + kfree(rawtable_ops); 82 78 } 83 79 84 80 return ret; ··· 91 77 92 78 static void __exit iptable_raw_fini(void) 93 79 { 94 - xt_hook_unlink(&packet_raw, rawtable_ops); 95 80 unregister_pernet_subsys(&iptable_raw_net_ops); 81 + kfree(rawtable_ops); 96 82 } 97 83 98 84 module_init(iptable_raw_init);
+29 -17
net/ipv4/netfilter/iptable_security.c
··· 28 28 (1 << NF_INET_FORWARD) | \ 29 29 (1 << NF_INET_LOCAL_OUT) 30 30 31 + static int __net_init iptable_security_table_init(struct net *net); 32 + 31 33 static const struct xt_table security_table = { 32 34 .name = "security", 33 35 .valid_hooks = SECURITY_VALID_HOOKS, 34 36 .me = THIS_MODULE, 35 37 .af = NFPROTO_IPV4, 36 38 .priority = NF_IP_PRI_SECURITY, 39 + .table_init = iptable_security_table_init, 37 40 }; 38 41 39 42 static unsigned int ··· 54 51 55 52 static struct nf_hook_ops *sectbl_ops __read_mostly; 56 53 57 - static int __net_init iptable_security_net_init(struct net *net) 54 + static int __net_init iptable_security_table_init(struct net *net) 58 55 { 59 56 struct ipt_replace *repl; 57 + int ret; 58 + 59 + if (net->ipv4.iptable_security) 60 + return 0; 60 61 61 62 repl = ipt_alloc_initial_table(&security_table); 62 63 if (repl == NULL) 63 64 return -ENOMEM; 64 - net->ipv4.iptable_security = 65 - ipt_register_table(net, &security_table, repl); 65 + ret = ipt_register_table(net, &security_table, repl, sectbl_ops, 66 + &net->ipv4.iptable_security); 66 67 kfree(repl); 67 - return PTR_ERR_OR_ZERO(net->ipv4.iptable_security); 68 + return ret; 68 69 } 69 70 70 71 static void __net_exit iptable_security_net_exit(struct net *net) 71 72 { 72 - ipt_unregister_table(net, net->ipv4.iptable_security); 73 + if (!net->ipv4.iptable_security) 74 + return; 75 + 76 + ipt_unregister_table(net, net->ipv4.iptable_security, sectbl_ops); 77 + net->ipv4.iptable_security = NULL; 73 78 } 74 79 75 80 static struct pernet_operations iptable_security_net_ops = { 76 - .init = iptable_security_net_init, 77 81 .exit = iptable_security_net_exit, 78 82 }; 79 83 ··· 88 78 { 89 79 int ret; 90 80 91 - ret = register_pernet_subsys(&iptable_security_net_ops); 92 - if (ret < 0) 93 - return ret; 81 + sectbl_ops = xt_hook_ops_alloc(&security_table, iptable_security_hook); 82 + if (IS_ERR(sectbl_ops)) 83 + return PTR_ERR(sectbl_ops); 94 84 95 - sectbl_ops = xt_hook_link(&security_table, iptable_security_hook); 96 - if (IS_ERR(sectbl_ops)) { 97 - ret = PTR_ERR(sectbl_ops); 98 - goto cleanup_table; 85 + ret = register_pernet_subsys(&iptable_security_net_ops); 86 + if (ret < 0) { 87 + kfree(sectbl_ops); 88 + return ret; 99 89 } 100 90 101 - return ret; 91 + ret = iptable_security_table_init(&init_net); 92 + if (ret) { 93 + unregister_pernet_subsys(&iptable_security_net_ops); 94 + kfree(sectbl_ops); 95 + } 102 96 103 - cleanup_table: 104 - unregister_pernet_subsys(&iptable_security_net_ops); 105 97 return ret; 106 98 } 107 99 108 100 static void __exit iptable_security_fini(void) 109 101 { 110 - xt_hook_unlink(&security_table, sectbl_ops); 111 102 unregister_pernet_subsys(&iptable_security_net_ops); 103 + kfree(sectbl_ops); 112 104 } 113 105 114 106 module_init(iptable_security_init);
+1 -3
net/ipv4/netfilter/nf_defrag_ipv4.c
··· 31 31 err = ip_defrag(net, skb, user); 32 32 local_bh_enable(); 33 33 34 - if (!err) { 35 - ip_send_check(ip_hdr(skb)); 34 + if (!err) 36 35 skb->ignore_df = 1; 37 - } 38 36 39 37 return err; 40 38 }
+6 -1
net/ipv4/netfilter/nft_masq_ipv4.c
··· 25 25 26 26 memset(&range, 0, sizeof(range)); 27 27 range.flags = priv->flags; 28 - 28 + if (priv->sreg_proto_min) { 29 + range.min_proto.all = 30 + *(__be16 *)&regs->data[priv->sreg_proto_min]; 31 + range.max_proto.all = 32 + *(__be16 *)&regs->data[priv->sreg_proto_max]; 33 + } 29 34 regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook, 30 35 &range, pkt->out); 31 36 }
+52 -37
net/ipv6/netfilter/ip6_tables.c
··· 2071 2071 return ret; 2072 2072 } 2073 2073 2074 - struct xt_table *ip6t_register_table(struct net *net, 2075 - const struct xt_table *table, 2076 - const struct ip6t_replace *repl) 2077 - { 2078 - int ret; 2079 - struct xt_table_info *newinfo; 2080 - struct xt_table_info bootstrap = {0}; 2081 - void *loc_cpu_entry; 2082 - struct xt_table *new_table; 2083 - 2084 - newinfo = xt_alloc_table_info(repl->size); 2085 - if (!newinfo) { 2086 - ret = -ENOMEM; 2087 - goto out; 2088 - } 2089 - 2090 - loc_cpu_entry = newinfo->entries; 2091 - memcpy(loc_cpu_entry, repl->entries, repl->size); 2092 - 2093 - ret = translate_table(net, newinfo, loc_cpu_entry, repl); 2094 - if (ret != 0) 2095 - goto out_free; 2096 - 2097 - new_table = xt_register_table(net, table, &bootstrap, newinfo); 2098 - if (IS_ERR(new_table)) { 2099 - ret = PTR_ERR(new_table); 2100 - goto out_free; 2101 - } 2102 - return new_table; 2103 - 2104 - out_free: 2105 - xt_free_table_info(newinfo); 2106 - out: 2107 - return ERR_PTR(ret); 2108 - } 2109 - 2110 - void ip6t_unregister_table(struct net *net, struct xt_table *table) 2074 + static void __ip6t_unregister_table(struct net *net, struct xt_table *table) 2111 2075 { 2112 2076 struct xt_table_info *private; 2113 2077 void *loc_cpu_entry; ··· 2087 2123 if (private->number > private->initial_entries) 2088 2124 module_put(table_owner); 2089 2125 xt_free_table_info(private); 2126 + } 2127 + 2128 + int ip6t_register_table(struct net *net, const struct xt_table *table, 2129 + const struct ip6t_replace *repl, 2130 + const struct nf_hook_ops *ops, 2131 + struct xt_table **res) 2132 + { 2133 + int ret; 2134 + struct xt_table_info *newinfo; 2135 + struct xt_table_info bootstrap = {0}; 2136 + void *loc_cpu_entry; 2137 + struct xt_table *new_table; 2138 + 2139 + newinfo = xt_alloc_table_info(repl->size); 2140 + if (!newinfo) 2141 + return -ENOMEM; 2142 + 2143 + loc_cpu_entry = newinfo->entries; 2144 + memcpy(loc_cpu_entry, repl->entries, repl->size); 2145 + 2146 + ret = translate_table(net, newinfo, loc_cpu_entry, repl); 2147 + if (ret != 0) 2148 + goto out_free; 2149 + 2150 + new_table = xt_register_table(net, table, &bootstrap, newinfo); 2151 + if (IS_ERR(new_table)) { 2152 + ret = PTR_ERR(new_table); 2153 + goto out_free; 2154 + } 2155 + 2156 + /* set res now, will see skbs right after nf_register_net_hooks */ 2157 + WRITE_ONCE(*res, new_table); 2158 + 2159 + ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks)); 2160 + if (ret != 0) { 2161 + __ip6t_unregister_table(net, new_table); 2162 + *res = NULL; 2163 + } 2164 + 2165 + return ret; 2166 + 2167 + out_free: 2168 + xt_free_table_info(newinfo); 2169 + return ret; 2170 + } 2171 + 2172 + void ip6t_unregister_table(struct net *net, struct xt_table *table, 2173 + const struct nf_hook_ops *ops) 2174 + { 2175 + nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); 2176 + __ip6t_unregister_table(net, table); 2090 2177 } 2091 2178 2092 2179 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
+29 -18
net/ipv6/netfilter/ip6table_filter.c
··· 22 22 (1 << NF_INET_FORWARD) | \ 23 23 (1 << NF_INET_LOCAL_OUT)) 24 24 25 + static int __net_init ip6table_filter_table_init(struct net *net); 26 + 25 27 static const struct xt_table packet_filter = { 26 28 .name = "filter", 27 29 .valid_hooks = FILTER_VALID_HOOKS, 28 30 .me = THIS_MODULE, 29 31 .af = NFPROTO_IPV6, 30 32 .priority = NF_IP6_PRI_FILTER, 33 + .table_init = ip6table_filter_table_init, 31 34 }; 32 35 33 36 /* The work comes in here from netfilter.c. */ ··· 47 44 static bool forward = true; 48 45 module_param(forward, bool, 0000); 49 46 50 - static int __net_init ip6table_filter_net_init(struct net *net) 47 + static int __net_init ip6table_filter_table_init(struct net *net) 51 48 { 52 49 struct ip6t_replace *repl; 50 + int err; 51 + 52 + if (net->ipv6.ip6table_filter) 53 + return 0; 53 54 54 55 repl = ip6t_alloc_initial_table(&packet_filter); 55 56 if (repl == NULL) ··· 62 55 ((struct ip6t_standard *)repl->entries)[1].target.verdict = 63 56 forward ? -NF_ACCEPT - 1 : -NF_DROP - 1; 64 57 65 - net->ipv6.ip6table_filter = 66 - ip6t_register_table(net, &packet_filter, repl); 58 + err = ip6t_register_table(net, &packet_filter, repl, filter_ops, 59 + &net->ipv6.ip6table_filter); 67 60 kfree(repl); 68 - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_filter); 61 + return err; 62 + } 63 + 64 + static int __net_init ip6table_filter_net_init(struct net *net) 65 + { 66 + if (net == &init_net || !forward) 67 + return ip6table_filter_table_init(net); 68 + 69 + return 0; 69 70 } 70 71 71 72 static void __net_exit ip6table_filter_net_exit(struct net *net) 72 73 { 73 - ip6t_unregister_table(net, net->ipv6.ip6table_filter); 74 + if (!net->ipv6.ip6table_filter) 75 + return; 76 + ip6t_unregister_table(net, net->ipv6.ip6table_filter, filter_ops); 77 + net->ipv6.ip6table_filter = NULL; 74 78 } 75 79 76 80 static struct pernet_operations ip6table_filter_net_ops = { ··· 93 75 { 94 76 int ret; 95 77 78 + filter_ops = xt_hook_ops_alloc(&packet_filter, ip6table_filter_hook); 79 + if (IS_ERR(filter_ops)) 80 + return PTR_ERR(filter_ops); 81 + 96 82 ret = register_pernet_subsys(&ip6table_filter_net_ops); 97 83 if (ret < 0) 98 - return ret; 84 + kfree(filter_ops); 99 85 100 - /* Register hooks */ 101 - filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook); 102 - if (IS_ERR(filter_ops)) { 103 - ret = PTR_ERR(filter_ops); 104 - goto cleanup_table; 105 - } 106 - 107 - return ret; 108 - 109 - cleanup_table: 110 - unregister_pernet_subsys(&ip6table_filter_net_ops); 111 86 return ret; 112 87 } 113 88 114 89 static void __exit ip6table_filter_fini(void) 115 90 { 116 - xt_hook_unlink(&packet_filter, filter_ops); 117 91 unregister_pernet_subsys(&ip6table_filter_net_ops); 92 + kfree(filter_ops); 118 93 } 119 94 120 95 module_init(ip6table_filter_init);
+29 -19
net/ipv6/netfilter/ip6table_mangle.c
··· 23 23 (1 << NF_INET_LOCAL_OUT) | \ 24 24 (1 << NF_INET_POST_ROUTING)) 25 25 26 + static int __net_init ip6table_mangle_table_init(struct net *net); 27 + 26 28 static const struct xt_table packet_mangler = { 27 29 .name = "mangle", 28 30 .valid_hooks = MANGLE_VALID_HOOKS, 29 31 .me = THIS_MODULE, 30 32 .af = NFPROTO_IPV6, 31 33 .priority = NF_IP6_PRI_MANGLE, 34 + .table_init = ip6table_mangle_table_init, 32 35 }; 33 36 34 37 static unsigned int ··· 91 88 } 92 89 93 90 static struct nf_hook_ops *mangle_ops __read_mostly; 94 - static int __net_init ip6table_mangle_net_init(struct net *net) 91 + static int __net_init ip6table_mangle_table_init(struct net *net) 95 92 { 96 93 struct ip6t_replace *repl; 94 + int ret; 95 + 96 + if (net->ipv6.ip6table_mangle) 97 + return 0; 97 98 98 99 repl = ip6t_alloc_initial_table(&packet_mangler); 99 100 if (repl == NULL) 100 101 return -ENOMEM; 101 - net->ipv6.ip6table_mangle = 102 - ip6t_register_table(net, &packet_mangler, repl); 102 + ret = ip6t_register_table(net, &packet_mangler, repl, mangle_ops, 103 + &net->ipv6.ip6table_mangle); 103 104 kfree(repl); 104 - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_mangle); 105 + return ret; 105 106 } 106 107 107 108 static void __net_exit ip6table_mangle_net_exit(struct net *net) 108 109 { 109 - ip6t_unregister_table(net, net->ipv6.ip6table_mangle); 110 + if (!net->ipv6.ip6table_mangle) 111 + return; 112 + 113 + ip6t_unregister_table(net, net->ipv6.ip6table_mangle, mangle_ops); 114 + net->ipv6.ip6table_mangle = NULL; 110 115 } 111 116 112 117 static struct pernet_operations ip6table_mangle_net_ops = { 113 - .init = ip6table_mangle_net_init, 114 118 .exit = ip6table_mangle_net_exit, 115 119 }; 116 120 ··· 125 115 { 126 116 int ret; 127 117 128 - ret = register_pernet_subsys(&ip6table_mangle_net_ops); 129 - if (ret < 0) 130 - return ret; 118 + mangle_ops = xt_hook_ops_alloc(&packet_mangler, ip6table_mangle_hook); 119 + if (IS_ERR(mangle_ops)) 120 + return PTR_ERR(mangle_ops); 131 121 132 - /* Register hooks */ 133 - mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook); 134 - if (IS_ERR(mangle_ops)) { 135 - ret = PTR_ERR(mangle_ops); 136 - goto cleanup_table; 122 + ret = register_pernet_subsys(&ip6table_mangle_net_ops); 123 + if (ret < 0) { 124 + kfree(mangle_ops); 125 + return ret; 137 126 } 138 127 139 - return ret; 140 - 141 - cleanup_table: 142 - unregister_pernet_subsys(&ip6table_mangle_net_ops); 128 + ret = ip6table_mangle_table_init(&init_net); 129 + if (ret) { 130 + unregister_pernet_subsys(&ip6table_mangle_net_ops); 131 + kfree(mangle_ops); 132 + } 143 133 return ret; 144 134 } 145 135 146 136 static void __exit ip6table_mangle_fini(void) 147 137 { 148 - xt_hook_unlink(&packet_mangler, mangle_ops); 149 138 unregister_pernet_subsys(&ip6table_mangle_net_ops); 139 + kfree(mangle_ops); 150 140 } 151 141 152 142 module_init(ip6table_mangle_init);
+22 -19
net/ipv6/netfilter/ip6table_nat.c
··· 20 20 #include <net/netfilter/nf_nat_core.h> 21 21 #include <net/netfilter/nf_nat_l3proto.h> 22 22 23 + static int __net_init ip6table_nat_table_init(struct net *net); 24 + 23 25 static const struct xt_table nf_nat_ipv6_table = { 24 26 .name = "nat", 25 27 .valid_hooks = (1 << NF_INET_PRE_ROUTING) | ··· 30 28 (1 << NF_INET_LOCAL_IN), 31 29 .me = THIS_MODULE, 32 30 .af = NFPROTO_IPV6, 31 + .table_init = ip6table_nat_table_init, 33 32 }; 34 33 35 34 static unsigned int ip6table_nat_do_chain(void *priv, ··· 100 97 }, 101 98 }; 102 99 103 - static int __net_init ip6table_nat_net_init(struct net *net) 100 + static int __net_init ip6table_nat_table_init(struct net *net) 104 101 { 105 102 struct ip6t_replace *repl; 103 + int ret; 104 + 105 + if (net->ipv6.ip6table_nat) 106 + return 0; 106 107 107 108 repl = ip6t_alloc_initial_table(&nf_nat_ipv6_table); 108 109 if (repl == NULL) 109 110 return -ENOMEM; 110 - net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl); 111 + ret = ip6t_register_table(net, &nf_nat_ipv6_table, repl, 112 + nf_nat_ipv6_ops, &net->ipv6.ip6table_nat); 111 113 kfree(repl); 112 - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_nat); 114 + return ret; 113 115 } 114 116 115 117 static void __net_exit ip6table_nat_net_exit(struct net *net) 116 118 { 117 - ip6t_unregister_table(net, net->ipv6.ip6table_nat); 119 + if (!net->ipv6.ip6table_nat) 120 + return; 121 + ip6t_unregister_table(net, net->ipv6.ip6table_nat, nf_nat_ipv6_ops); 122 + net->ipv6.ip6table_nat = NULL; 118 123 } 119 124 120 125 static struct pernet_operations ip6table_nat_net_ops = { 121 - .init = ip6table_nat_net_init, 122 126 .exit = ip6table_nat_net_exit, 123 127 }; 124 128 125 129 static int __init ip6table_nat_init(void) 126 130 { 127 - int err; 131 + int ret = register_pernet_subsys(&ip6table_nat_net_ops); 128 132 129 - err = register_pernet_subsys(&ip6table_nat_net_ops); 130 - if (err < 0) 131 - goto err1; 133 + if (ret) 134 + return ret; 132 135 133 - err = nf_register_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops)); 134 - if (err < 0) 135 - goto err2; 136 - return 0; 137 - 138 - err2: 139 - unregister_pernet_subsys(&ip6table_nat_net_ops); 140 - err1: 141 - return err; 136 + ret = ip6table_nat_table_init(&init_net); 137 + if (ret) 138 + unregister_pernet_subsys(&ip6table_nat_net_ops); 139 + return ret; 142 140 } 143 141 144 142 static void __exit ip6table_nat_exit(void) 145 143 { 146 - nf_unregister_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops)); 147 144 unregister_pernet_subsys(&ip6table_nat_net_ops); 148 145 } 149 146
+29 -19
net/ipv6/netfilter/ip6table_raw.c
··· 9 9 10 10 #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) 11 11 12 + static int __net_init ip6table_raw_table_init(struct net *net); 13 + 12 14 static const struct xt_table packet_raw = { 13 15 .name = "raw", 14 16 .valid_hooks = RAW_VALID_HOOKS, 15 17 .me = THIS_MODULE, 16 18 .af = NFPROTO_IPV6, 17 19 .priority = NF_IP6_PRI_RAW, 20 + .table_init = ip6table_raw_table_init, 18 21 }; 19 22 20 23 /* The work comes in here from netfilter.c. */ ··· 30 27 31 28 static struct nf_hook_ops *rawtable_ops __read_mostly; 32 29 33 - static int __net_init ip6table_raw_net_init(struct net *net) 30 + static int __net_init ip6table_raw_table_init(struct net *net) 34 31 { 35 32 struct ip6t_replace *repl; 33 + int ret; 34 + 35 + if (net->ipv6.ip6table_raw) 36 + return 0; 36 37 37 38 repl = ip6t_alloc_initial_table(&packet_raw); 38 39 if (repl == NULL) 39 40 return -ENOMEM; 40 - net->ipv6.ip6table_raw = 41 - ip6t_register_table(net, &packet_raw, repl); 41 + ret = ip6t_register_table(net, &packet_raw, repl, rawtable_ops, 42 + &net->ipv6.ip6table_raw); 42 43 kfree(repl); 43 - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_raw); 44 + return ret; 44 45 } 45 46 46 47 static void __net_exit ip6table_raw_net_exit(struct net *net) 47 48 { 48 - ip6t_unregister_table(net, net->ipv6.ip6table_raw); 49 + if (!net->ipv6.ip6table_raw) 50 + return; 51 + ip6t_unregister_table(net, net->ipv6.ip6table_raw, rawtable_ops); 52 + net->ipv6.ip6table_raw = NULL; 49 53 } 50 54 51 55 static struct pernet_operations ip6table_raw_net_ops = { 52 - .init = ip6table_raw_net_init, 53 56 .exit = ip6table_raw_net_exit, 54 57 }; 55 58 ··· 63 54 { 64 55 int ret; 65 56 66 - ret = register_pernet_subsys(&ip6table_raw_net_ops); 67 - if (ret < 0) 68 - return ret; 69 - 70 57 /* Register hooks */ 71 - rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook); 72 - if (IS_ERR(rawtable_ops)) { 73 - ret = PTR_ERR(rawtable_ops); 74 - goto cleanup_table; 58 + rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook); 59 + if (IS_ERR(rawtable_ops)) 60 + return PTR_ERR(rawtable_ops); 61 + 62 + ret = register_pernet_subsys(&ip6table_raw_net_ops); 63 + if (ret < 0) { 64 + kfree(rawtable_ops); 65 + return ret; 75 66 } 76 67 77 - return ret; 78 - 79 - cleanup_table: 80 - unregister_pernet_subsys(&ip6table_raw_net_ops); 68 + ret = ip6table_raw_table_init(&init_net); 69 + if (ret) { 70 + unregister_pernet_subsys(&ip6table_raw_net_ops); 71 + kfree(rawtable_ops); 72 + } 81 73 return ret; 82 74 } 83 75 84 76 static void __exit ip6table_raw_fini(void) 85 77 { 86 - xt_hook_unlink(&packet_raw, rawtable_ops); 87 78 unregister_pernet_subsys(&ip6table_raw_net_ops); 79 + kfree(rawtable_ops); 88 80 } 89 81 90 82 module_init(ip6table_raw_init);
+28 -18
net/ipv6/netfilter/ip6table_security.c
··· 27 27 (1 << NF_INET_FORWARD) | \ 28 28 (1 << NF_INET_LOCAL_OUT) 29 29 30 + static int __net_init ip6table_security_table_init(struct net *net); 31 + 30 32 static const struct xt_table security_table = { 31 33 .name = "security", 32 34 .valid_hooks = SECURITY_VALID_HOOKS, 33 35 .me = THIS_MODULE, 34 36 .af = NFPROTO_IPV6, 35 37 .priority = NF_IP6_PRI_SECURITY, 38 + .table_init = ip6table_security_table_init, 36 39 }; 37 40 38 41 static unsigned int ··· 47 44 48 45 static struct nf_hook_ops *sectbl_ops __read_mostly; 49 46 50 - static int __net_init ip6table_security_net_init(struct net *net) 47 + static int __net_init ip6table_security_table_init(struct net *net) 51 48 { 52 49 struct ip6t_replace *repl; 50 + int ret; 51 + 52 + if (net->ipv6.ip6table_security) 53 + return 0; 53 54 54 55 repl = ip6t_alloc_initial_table(&security_table); 55 56 if (repl == NULL) 56 57 return -ENOMEM; 57 - net->ipv6.ip6table_security = 58 - ip6t_register_table(net, &security_table, repl); 58 + ret = ip6t_register_table(net, &security_table, repl, sectbl_ops, 59 + &net->ipv6.ip6table_security); 59 60 kfree(repl); 60 - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_security); 61 + return ret; 61 62 } 62 63 63 64 static void __net_exit ip6table_security_net_exit(struct net *net) 64 65 { 65 - ip6t_unregister_table(net, net->ipv6.ip6table_security); 66 + if (!net->ipv6.ip6table_security) 67 + return; 68 + ip6t_unregister_table(net, net->ipv6.ip6table_security, sectbl_ops); 69 + net->ipv6.ip6table_security = NULL; 66 70 } 67 71 68 72 static struct pernet_operations ip6table_security_net_ops = { 69 - .init = ip6table_security_net_init, 70 73 .exit = ip6table_security_net_exit, 71 74 }; 72 75 ··· 80 71 { 81 72 int ret; 82 73 83 - ret = register_pernet_subsys(&ip6table_security_net_ops); 84 - if (ret < 0) 85 - return ret; 74 + sectbl_ops = xt_hook_ops_alloc(&security_table, ip6table_security_hook); 75 + if (IS_ERR(sectbl_ops)) 76 + return PTR_ERR(sectbl_ops); 86 77 87 - sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook); 88 - if (IS_ERR(sectbl_ops)) { 89 - ret = PTR_ERR(sectbl_ops); 90 - goto cleanup_table; 78 + ret = register_pernet_subsys(&ip6table_security_net_ops); 79 + if (ret < 0) { 80 + kfree(sectbl_ops); 81 + return ret; 91 82 } 92 83 93 - return ret; 94 - 95 - cleanup_table: 96 - unregister_pernet_subsys(&ip6table_security_net_ops); 84 + ret = ip6table_security_table_init(&init_net); 85 + if (ret) { 86 + unregister_pernet_subsys(&ip6table_security_net_ops); 87 + kfree(sectbl_ops); 88 + } 97 89 return ret; 98 90 } 99 91 100 92 static void __exit ip6table_security_fini(void) 101 93 { 102 - xt_hook_unlink(&security_table, sectbl_ops); 103 94 unregister_pernet_subsys(&ip6table_security_net_ops); 95 + kfree(sectbl_ops); 104 96 } 105 97 106 98 module_init(ip6table_security_init);
+6 -1
net/ipv6/netfilter/nft_masq_ipv6.c
··· 26 26 27 27 memset(&range, 0, sizeof(range)); 28 28 range.flags = priv->flags; 29 - 29 + if (priv->sreg_proto_min) { 30 + range.min_proto.all = 31 + *(__be16 *)&regs->data[priv->sreg_proto_min]; 32 + range.max_proto.all = 33 + *(__be16 *)&regs->data[priv->sreg_proto_max]; 34 + } 30 35 regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); 31 36 } 32 37
+2 -6
net/netfilter/ipvs/ip_vs_app.c
··· 605 605 606 606 int __net_init ip_vs_app_net_init(struct netns_ipvs *ipvs) 607 607 { 608 - struct net *net = ipvs->net; 609 - 610 608 INIT_LIST_HEAD(&ipvs->app_list); 611 - proc_create("ip_vs_app", 0, net->proc_net, &ip_vs_app_fops); 609 + proc_create("ip_vs_app", 0, ipvs->net->proc_net, &ip_vs_app_fops); 612 610 return 0; 613 611 } 614 612 615 613 void __net_exit ip_vs_app_net_cleanup(struct netns_ipvs *ipvs) 616 614 { 617 - struct net *net = ipvs->net; 618 - 619 615 unregister_ip_vs_app(ipvs, NULL /* all */); 620 - remove_proc_entry("ip_vs_app", net->proc_net); 616 + remove_proc_entry("ip_vs_app", ipvs->net->proc_net); 621 617 }
+6 -11
net/netfilter/ipvs/ip_vs_ctl.c
··· 1376 1376 struct ip_vs_pe *old_pe; 1377 1377 struct netns_ipvs *ipvs = svc->ipvs; 1378 1378 1379 - pr_info("%s: enter\n", __func__); 1380 - 1381 1379 /* Count only IPv4 services for old get/setsockopt interface */ 1382 1380 if (svc->af == AF_INET) 1383 1381 ipvs->num_services--; ··· 3945 3947 3946 3948 int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs) 3947 3949 { 3948 - struct net *net = ipvs->net; 3949 3950 int i, idx; 3950 3951 3951 3952 /* Initialize rs_table */ ··· 3971 3974 3972 3975 spin_lock_init(&ipvs->tot_stats.lock); 3973 3976 3974 - proc_create("ip_vs", 0, net->proc_net, &ip_vs_info_fops); 3975 - proc_create("ip_vs_stats", 0, net->proc_net, &ip_vs_stats_fops); 3976 - proc_create("ip_vs_stats_percpu", 0, net->proc_net, 3977 + proc_create("ip_vs", 0, ipvs->net->proc_net, &ip_vs_info_fops); 3978 + proc_create("ip_vs_stats", 0, ipvs->net->proc_net, &ip_vs_stats_fops); 3979 + proc_create("ip_vs_stats_percpu", 0, ipvs->net->proc_net, 3977 3980 &ip_vs_stats_percpu_fops); 3978 3981 3979 3982 if (ip_vs_control_net_init_sysctl(ipvs)) ··· 3988 3991 3989 3992 void __net_exit ip_vs_control_net_cleanup(struct netns_ipvs *ipvs) 3990 3993 { 3991 - struct net *net = ipvs->net; 3992 - 3993 3994 ip_vs_trash_cleanup(ipvs); 3994 3995 ip_vs_control_net_cleanup_sysctl(ipvs); 3995 - remove_proc_entry("ip_vs_stats_percpu", net->proc_net); 3996 - remove_proc_entry("ip_vs_stats", net->proc_net); 3997 - remove_proc_entry("ip_vs", net->proc_net); 3996 + remove_proc_entry("ip_vs_stats_percpu", ipvs->net->proc_net); 3997 + remove_proc_entry("ip_vs_stats", ipvs->net->proc_net); 3998 + remove_proc_entry("ip_vs", ipvs->net->proc_net); 3998 3999 free_percpu(ipvs->tot_stats.cpustats); 3999 4000 } 4000 4001
+39 -10
net/netfilter/nft_masq.c
··· 17 17 #include <net/netfilter/nft_masq.h> 18 18 19 19 const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = { 20 - [NFTA_MASQ_FLAGS] = { .type = NLA_U32 }, 20 + [NFTA_MASQ_FLAGS] = { .type = NLA_U32 }, 21 + [NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 }, 22 + [NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 }, 21 23 }; 22 24 EXPORT_SYMBOL_GPL(nft_masq_policy); 23 25 ··· 42 40 const struct nft_expr *expr, 43 41 const struct nlattr * const tb[]) 44 42 { 43 + u32 plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); 45 44 struct nft_masq *priv = nft_expr_priv(expr); 46 45 int err; 47 46 ··· 50 47 if (err) 51 48 return err; 52 49 53 - if (tb[NFTA_MASQ_FLAGS] == NULL) 54 - return 0; 50 + if (tb[NFTA_MASQ_FLAGS]) { 51 + priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS])); 52 + if (priv->flags & ~NF_NAT_RANGE_MASK) 53 + return -EINVAL; 54 + } 55 55 56 - priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS])); 57 - if (priv->flags & ~NF_NAT_RANGE_MASK) 58 - return -EINVAL; 56 + if (tb[NFTA_MASQ_REG_PROTO_MIN]) { 57 + priv->sreg_proto_min = 58 + nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MIN]); 59 + 60 + err = nft_validate_register_load(priv->sreg_proto_min, plen); 61 + if (err < 0) 62 + return err; 63 + 64 + if (tb[NFTA_MASQ_REG_PROTO_MAX]) { 65 + priv->sreg_proto_max = 66 + nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MAX]); 67 + 68 + err = nft_validate_register_load(priv->sreg_proto_max, 69 + plen); 70 + if (err < 0) 71 + return err; 72 + } else { 73 + priv->sreg_proto_max = priv->sreg_proto_min; 74 + } 75 + } 59 76 60 77 return 0; 61 78 } ··· 85 62 { 86 63 const struct nft_masq *priv = nft_expr_priv(expr); 87 64 88 - if (priv->flags == 0) 89 - return 0; 90 - 91 - if (nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags))) 65 + if (priv->flags != 0 && 66 + nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags))) 92 67 goto nla_put_failure; 68 + 69 + if (priv->sreg_proto_min) { 70 + if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN, 71 + priv->sreg_proto_min) || 72 + nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MAX, 73 + priv->sreg_proto_max)) 74 + goto nla_put_failure; 75 + } 93 76 94 77 return 0; 95 78
+11
net/netfilter/nft_meta.c
··· 28 28 29 29 #include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */ 30 30 31 + static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state); 32 + 31 33 void nft_meta_get_eval(const struct nft_expr *expr, 32 34 struct nft_regs *regs, 33 35 const struct nft_pktinfo *pkt) ··· 183 181 *dest = sock_cgroup_classid(&sk->sk_cgrp_data); 184 182 break; 185 183 #endif 184 + case NFT_META_PRANDOM: { 185 + struct rnd_state *state = this_cpu_ptr(&nft_prandom_state); 186 + *dest = prandom_u32_state(state); 187 + break; 188 + } 186 189 default: 187 190 WARN_ON(1); 188 191 goto err; ··· 283 276 case NFT_META_IIFNAME: 284 277 case NFT_META_OIFNAME: 285 278 len = IFNAMSIZ; 279 + break; 280 + case NFT_META_PRANDOM: 281 + prandom_init_once(&nft_prandom_state); 282 + len = sizeof(u32); 286 283 break; 287 284 default: 288 285 return -EOPNOTSUPP;
+40 -25
net/netfilter/x_tables.c
··· 694 694 struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, 695 695 const char *name) 696 696 { 697 - struct xt_table *t; 697 + struct xt_table *t, *found = NULL; 698 698 699 699 mutex_lock(&xt[af].mutex); 700 700 list_for_each_entry(t, &net->xt.tables[af], list) 701 701 if (strcmp(t->name, name) == 0 && try_module_get(t->me)) 702 702 return t; 703 + 704 + if (net == &init_net) 705 + goto out; 706 + 707 + /* Table doesn't exist in this netns, re-try init */ 708 + list_for_each_entry(t, &init_net.xt.tables[af], list) { 709 + if (strcmp(t->name, name)) 710 + continue; 711 + if (!try_module_get(t->me)) 712 + return NULL; 713 + 714 + mutex_unlock(&xt[af].mutex); 715 + if (t->table_init(net) != 0) { 716 + module_put(t->me); 717 + return NULL; 718 + } 719 + 720 + found = t; 721 + 722 + mutex_lock(&xt[af].mutex); 723 + break; 724 + } 725 + 726 + if (!found) 727 + goto out; 728 + 729 + /* and once again: */ 730 + list_for_each_entry(t, &net->xt.tables[af], list) 731 + if (strcmp(t->name, name) == 0) 732 + return t; 733 + 734 + module_put(found->me); 735 + out: 703 736 mutex_unlock(&xt[af].mutex); 704 737 return NULL; 705 738 } ··· 1203 1170 #endif /* CONFIG_PROC_FS */ 1204 1171 1205 1172 /** 1206 - * xt_hook_link - set up hooks for a new table 1173 + * xt_hook_ops_alloc - set up hooks for a new table 1207 1174 * @table: table with metadata needed to set up hooks 1208 1175 * @fn: Hook function 1209 1176 * 1210 - * This function will take care of creating and registering the necessary 1211 - * Netfilter hooks for XT tables. 1177 + * This function will create the nf_hook_ops that the x_table needs 1178 + * to hand to xt_hook_link_net(). 1212 1179 */ 1213 - struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn) 1180 + struct nf_hook_ops * 1181 + xt_hook_ops_alloc(const struct xt_table *table, nf_hookfn *fn) 1214 1182 { 1215 1183 unsigned int hook_mask = table->valid_hooks; 1216 1184 uint8_t i, num_hooks = hweight32(hook_mask); 1217 1185 uint8_t hooknum; 1218 1186 struct nf_hook_ops *ops; 1219 - int ret; 1220 1187 1221 1188 ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL); 1222 1189 if (ops == NULL) ··· 1233 1200 ++i; 1234 1201 } 1235 1202 1236 - ret = nf_register_hooks(ops, num_hooks); 1237 - if (ret < 0) { 1238 - kfree(ops); 1239 - return ERR_PTR(ret); 1240 - } 1241 - 1242 1203 return ops; 1243 1204 } 1244 - EXPORT_SYMBOL_GPL(xt_hook_link); 1245 - 1246 - /** 1247 - * xt_hook_unlink - remove hooks for a table 1248 - * @ops: nf_hook_ops array as returned by nf_hook_link 1249 - * @hook_mask: the very same mask that was passed to nf_hook_link 1250 - */ 1251 - void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops) 1252 - { 1253 - nf_unregister_hooks(ops, hweight32(table->valid_hooks)); 1254 - kfree(ops); 1255 - } 1256 - EXPORT_SYMBOL_GPL(xt_hook_unlink); 1205 + EXPORT_SYMBOL_GPL(xt_hook_ops_alloc); 1257 1206 1258 1207 int xt_proto_init(struct net *net, u_int8_t af) 1259 1208 {
-2
net/netfilter/xt_osf.c
··· 262 262 if (f->opt[optnum].kind == (*optp)) { 263 263 __u32 len = f->opt[optnum].length; 264 264 const __u8 *optend = optp + len; 265 - int loop_cont = 0; 266 265 267 266 fmatch = FMATCH_OK; 268 267 ··· 274 275 mss = ntohs((__force __be16)mss); 275 276 break; 276 277 case OSFOPT_TS: 277 - loop_cont = 1; 278 278 break; 279 279 } 280 280