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

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6

+416 -210
+23
include/linux/netfilter/x_tables.h
··· 437 437 extern void xt_table_entry_swap_rcu(struct xt_table_info *old, 438 438 struct xt_table_info *new); 439 439 440 + /* 441 + * This helper is performance critical and must be inlined 442 + */ 443 + static inline unsigned long ifname_compare_aligned(const char *_a, 444 + const char *_b, 445 + const char *_mask) 446 + { 447 + const unsigned long *a = (const unsigned long *)_a; 448 + const unsigned long *b = (const unsigned long *)_b; 449 + const unsigned long *mask = (const unsigned long *)_mask; 450 + unsigned long ret; 451 + 452 + ret = (a[0] ^ b[0]) & mask[0]; 453 + if (IFNAMSIZ > sizeof(unsigned long)) 454 + ret |= (a[1] ^ b[1]) & mask[1]; 455 + if (IFNAMSIZ > 2 * sizeof(unsigned long)) 456 + ret |= (a[2] ^ b[2]) & mask[2]; 457 + if (IFNAMSIZ > 3 * sizeof(unsigned long)) 458 + ret |= (a[3] ^ b[3]) & mask[3]; 459 + BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); 460 + return ret; 461 + } 462 + 440 463 #ifdef CONFIG_COMPAT 441 464 #include <net/compat.h> 442 465
+8 -6
include/net/netfilter/nf_conntrack.h
··· 91 91 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 92 92 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 93 93 94 - struct nf_conn 95 - { 94 + struct nf_conn { 96 95 /* Usage count in here is 1 for hash table/destruct timer, 1 per skb, 97 96 plus 1 for any connection(s) we are `master' for */ 98 97 struct nf_conntrack ct_general; ··· 125 126 #ifdef CONFIG_NET_NS 126 127 struct net *ct_net; 127 128 #endif 128 - struct rcu_head rcu; 129 129 }; 130 130 131 131 static inline struct nf_conn * ··· 188 190 extern int nf_ct_l3proto_try_module_get(unsigned short l3proto); 189 191 extern void nf_ct_l3proto_module_put(unsigned short l3proto); 190 192 191 - extern struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced); 192 - extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, 193 - unsigned int size); 193 + /* 194 + * Allocate a hashtable of hlist_head (if nulls == 0), 195 + * or hlist_nulls_head (if nulls == 1) 196 + */ 197 + extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls); 198 + 199 + extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size); 194 200 195 201 extern struct nf_conntrack_tuple_hash * 196 202 __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple);
+2
include/net/netfilter/nf_conntrack_helper.h
··· 14 14 15 15 struct module; 16 16 17 + #define NF_CT_HELPER_NAME_LEN 16 18 + 17 19 struct nf_conntrack_helper 18 20 { 19 21 struct hlist_node hnode; /* Internal use. */
+7
include/net/netfilter/nf_conntrack_l3proto.h
··· 53 53 int (*tuple_to_nlattr)(struct sk_buff *skb, 54 54 const struct nf_conntrack_tuple *t); 55 55 56 + /* 57 + * Calculate size of tuple nlattr 58 + */ 59 + int (*nlattr_tuple_size)(void); 60 + 56 61 int (*nlattr_to_tuple)(struct nlattr *tb[], 57 62 struct nf_conntrack_tuple *t); 58 63 const struct nla_policy *nla_policy; 64 + 65 + size_t nla_size; 59 66 60 67 #ifdef CONFIG_SYSCTL 61 68 struct ctl_table_header *ctl_table_header;
+7
include/net/netfilter/nf_conntrack_l4proto.h
··· 64 64 /* convert protoinfo to nfnetink attributes */ 65 65 int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, 66 66 const struct nf_conn *ct); 67 + /* Calculate protoinfo nlattr size */ 68 + int (*nlattr_size)(void); 67 69 68 70 /* convert nfnetlink attributes to protoinfo */ 69 71 int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct); 70 72 71 73 int (*tuple_to_nlattr)(struct sk_buff *skb, 72 74 const struct nf_conntrack_tuple *t); 75 + /* Calculate tuple nlattr size */ 76 + int (*nlattr_tuple_size)(void); 73 77 int (*nlattr_to_tuple)(struct nlattr *tb[], 74 78 struct nf_conntrack_tuple *t); 75 79 const struct nla_policy *nla_policy; 80 + 81 + size_t nla_size; 76 82 77 83 #ifdef CONFIG_SYSCTL 78 84 struct ctl_table_header **ctl_table_header; ··· 113 107 const struct nf_conntrack_tuple *tuple); 114 108 extern int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[], 115 109 struct nf_conntrack_tuple *t); 110 + extern int nf_ct_port_nlattr_tuple_size(void); 116 111 extern const struct nla_policy nf_ct_port_nla_policy[]; 117 112 118 113 #ifdef CONFIG_SYSCTL
+3 -3
include/net/netfilter/nf_conntrack_tuple.h
··· 12 12 13 13 #include <linux/netfilter/x_tables.h> 14 14 #include <linux/netfilter/nf_conntrack_tuple_common.h> 15 + #include <linux/list_nulls.h> 15 16 16 17 /* A `tuple' is a structure containing the information to uniquely 17 18 identify a connection. ie. if two packets have the same tuple, they ··· 147 146 ((enum ip_conntrack_dir)(h)->tuple.dst.dir) 148 147 149 148 /* Connections have two entries in the hash table: one for each way */ 150 - struct nf_conntrack_tuple_hash 151 - { 152 - struct hlist_node hnode; 149 + struct nf_conntrack_tuple_hash { 150 + struct hlist_nulls_node hnnode; 153 151 struct nf_conntrack_tuple tuple; 154 152 }; 155 153
+1
include/net/netlink.h
··· 230 230 extern int nla_parse(struct nlattr *tb[], int maxtype, 231 231 struct nlattr *head, int len, 232 232 const struct nla_policy *policy); 233 + extern int nla_policy_len(const struct nla_policy *, int); 233 234 extern struct nlattr * nla_find(struct nlattr *head, int len, int attrtype); 234 235 extern size_t nla_strlcpy(char *dst, const struct nlattr *nla, 235 236 size_t dstsize);
+3 -2
include/net/netns/conntrack.h
··· 2 2 #define __NETNS_CONNTRACK_H 3 3 4 4 #include <linux/list.h> 5 + #include <linux/list_nulls.h> 5 6 #include <asm/atomic.h> 6 7 7 8 struct ctl_table_header; ··· 11 10 struct netns_ct { 12 11 atomic_t count; 13 12 unsigned int expect_count; 14 - struct hlist_head *hash; 13 + struct hlist_nulls_head *hash; 15 14 struct hlist_head *expect_hash; 16 - struct hlist_head unconfirmed; 15 + struct hlist_nulls_head unconfirmed; 17 16 struct ip_conntrack_stat *stat; 18 17 #ifdef CONFIG_NF_CONNTRACK_EVENTS 19 18 struct nf_conntrack_ecache *ecache;
+27
lib/nlattr.c
··· 133 133 } 134 134 135 135 /** 136 + * nla_policy_len - Determin the max. length of a policy 137 + * @policy: policy to use 138 + * @n: number of policies 139 + * 140 + * Determines the max. length of the policy. It is currently used 141 + * to allocated Netlink buffers roughly the size of the actual 142 + * message. 143 + * 144 + * Returns 0 on success or a negative error code. 145 + */ 146 + int 147 + nla_policy_len(const struct nla_policy *p, int n) 148 + { 149 + int i, len = 0; 150 + 151 + for (i = 0; i < n; i++) { 152 + if (p->len) 153 + len += nla_total_size(p->len); 154 + else if (nla_attr_minlen[p->type]) 155 + len += nla_total_size(nla_attr_minlen[p->type]); 156 + } 157 + 158 + return len; 159 + } 160 + 161 + /** 136 162 * nla_parse - Parse a stream of attributes into a tb buffer 137 163 * @tb: destination array with maxtype+1 elements 138 164 * @maxtype: maximum attribute type to be expected ··· 493 467 #endif 494 468 495 469 EXPORT_SYMBOL(nla_validate); 470 + EXPORT_SYMBOL(nla_policy_len); 496 471 EXPORT_SYMBOL(nla_parse); 497 472 EXPORT_SYMBOL(nla_find); 498 473 EXPORT_SYMBOL(nla_strlcpy);
+4 -14
net/ipv4/netfilter/arp_tables.c
··· 81 81 static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) 82 82 { 83 83 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 84 - const unsigned long *a = (const unsigned long *)_a; 85 - const unsigned long *b = (const unsigned long *)_b; 86 - const unsigned long *mask = (const unsigned long *)_mask; 87 - unsigned long ret; 88 - 89 - ret = (a[0] ^ b[0]) & mask[0]; 90 - if (IFNAMSIZ > sizeof(unsigned long)) 91 - ret |= (a[1] ^ b[1]) & mask[1]; 92 - if (IFNAMSIZ > 2 * sizeof(unsigned long)) 93 - ret |= (a[2] ^ b[2]) & mask[2]; 94 - if (IFNAMSIZ > 3 * sizeof(unsigned long)) 95 - ret |= (a[3] ^ b[3]) & mask[3]; 96 - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); 84 + unsigned long ret = ifname_compare_aligned(_a, _b, _mask); 97 85 #else 98 86 unsigned long ret = 0; 99 87 const u16 *a = (const u16 *)_a; ··· 392 404 && unconditional(&e->arp)) || visited) { 393 405 unsigned int oldpos, size; 394 406 395 - if (t->verdict < -NF_MAX_VERDICT - 1) { 407 + if ((strcmp(t->target.u.user.name, 408 + ARPT_STANDARD_TARGET) == 0) && 409 + t->verdict < -NF_MAX_VERDICT - 1) { 396 410 duprintf("mark_source_chains: bad " 397 411 "negative verdict (%i)\n", 398 412 t->verdict);
+5 -22
net/ipv4/netfilter/ip_tables.c
··· 74 74 75 75 Hence the start of any table is given by get_table() below. */ 76 76 77 - static unsigned long ifname_compare(const char *_a, const char *_b, 78 - const unsigned char *_mask) 79 - { 80 - const unsigned long *a = (const unsigned long *)_a; 81 - const unsigned long *b = (const unsigned long *)_b; 82 - const unsigned long *mask = (const unsigned long *)_mask; 83 - unsigned long ret; 84 - 85 - ret = (a[0] ^ b[0]) & mask[0]; 86 - if (IFNAMSIZ > sizeof(unsigned long)) 87 - ret |= (a[1] ^ b[1]) & mask[1]; 88 - if (IFNAMSIZ > 2 * sizeof(unsigned long)) 89 - ret |= (a[2] ^ b[2]) & mask[2]; 90 - if (IFNAMSIZ > 3 * sizeof(unsigned long)) 91 - ret |= (a[3] ^ b[3]) & mask[3]; 92 - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); 93 - return ret; 94 - } 95 - 96 77 /* Returns whether matches rule or not. */ 97 78 /* Performance critical - called for every packet */ 98 79 static inline bool ··· 102 121 return false; 103 122 } 104 123 105 - ret = ifname_compare(indev, ipinfo->iniface, ipinfo->iniface_mask); 124 + ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask); 106 125 107 126 if (FWINV(ret != 0, IPT_INV_VIA_IN)) { 108 127 dprintf("VIA in mismatch (%s vs %s).%s\n", ··· 111 130 return false; 112 131 } 113 132 114 - ret = ifname_compare(outdev, ipinfo->outiface, ipinfo->outiface_mask); 133 + ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask); 115 134 116 135 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { 117 136 dprintf("VIA out mismatch (%s vs %s).%s\n", ··· 488 507 && unconditional(&e->ip)) || visited) { 489 508 unsigned int oldpos, size; 490 509 491 - if (t->verdict < -NF_MAX_VERDICT - 1) { 510 + if ((strcmp(t->target.u.user.name, 511 + IPT_STANDARD_TARGET) == 0) && 512 + t->verdict < -NF_MAX_VERDICT - 1) { 492 513 duprintf("mark_source_chains: bad " 493 514 "negative verdict (%i)\n", 494 515 t->verdict);
+6
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
··· 328 328 329 329 return 0; 330 330 } 331 + 332 + static int ipv4_nlattr_tuple_size(void) 333 + { 334 + return nla_policy_len(ipv4_nla_policy, CTA_IP_MAX + 1); 335 + } 331 336 #endif 332 337 333 338 static struct nf_sockopt_ops so_getorigdst = { ··· 352 347 .get_l4proto = ipv4_get_l4proto, 353 348 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 354 349 .tuple_to_nlattr = ipv4_tuple_to_nlattr, 350 + .nlattr_tuple_size = ipv4_nlattr_tuple_size, 355 351 .nlattr_to_tuple = ipv4_nlattr_to_tuple, 356 352 .nla_policy = ipv4_nla_policy, 357 353 #endif
+36 -27
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
··· 25 25 unsigned int bucket; 26 26 }; 27 27 28 - static struct hlist_node *ct_get_first(struct seq_file *seq) 28 + static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) 29 29 { 30 30 struct net *net = seq_file_net(seq); 31 31 struct ct_iter_state *st = seq->private; 32 - struct hlist_node *n; 32 + struct hlist_nulls_node *n; 33 33 34 34 for (st->bucket = 0; 35 35 st->bucket < nf_conntrack_htable_size; 36 36 st->bucket++) { 37 37 n = rcu_dereference(net->ct.hash[st->bucket].first); 38 - if (n) 38 + if (!is_a_nulls(n)) 39 39 return n; 40 40 } 41 41 return NULL; 42 42 } 43 43 44 - static struct hlist_node *ct_get_next(struct seq_file *seq, 45 - struct hlist_node *head) 44 + static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, 45 + struct hlist_nulls_node *head) 46 46 { 47 47 struct net *net = seq_file_net(seq); 48 48 struct ct_iter_state *st = seq->private; 49 49 50 50 head = rcu_dereference(head->next); 51 - while (head == NULL) { 52 - if (++st->bucket >= nf_conntrack_htable_size) 53 - return NULL; 51 + while (is_a_nulls(head)) { 52 + if (likely(get_nulls_value(head) == st->bucket)) { 53 + if (++st->bucket >= nf_conntrack_htable_size) 54 + return NULL; 55 + } 54 56 head = rcu_dereference(net->ct.hash[st->bucket].first); 55 57 } 56 58 return head; 57 59 } 58 60 59 - static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) 61 + static struct hlist_nulls_node *ct_get_idx(struct seq_file *seq, loff_t pos) 60 62 { 61 - struct hlist_node *head = ct_get_first(seq); 63 + struct hlist_nulls_node *head = ct_get_first(seq); 62 64 63 65 if (head) 64 66 while (pos && (head = ct_get_next(seq, head))) ··· 89 87 90 88 static int ct_seq_show(struct seq_file *s, void *v) 91 89 { 92 - const struct nf_conntrack_tuple_hash *hash = v; 93 - const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); 90 + struct nf_conntrack_tuple_hash *hash = v; 91 + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); 94 92 const struct nf_conntrack_l3proto *l3proto; 95 93 const struct nf_conntrack_l4proto *l4proto; 94 + int ret = 0; 96 95 97 96 NF_CT_ASSERT(ct); 97 + if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) 98 + return 0; 99 + 98 100 99 101 /* we only want to print DIR_ORIGINAL */ 100 102 if (NF_CT_DIRECTION(hash)) 101 - return 0; 103 + goto release; 102 104 if (nf_ct_l3num(ct) != AF_INET) 103 - return 0; 105 + goto release; 104 106 105 107 l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); 106 108 NF_CT_ASSERT(l3proto); 107 109 l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); 108 110 NF_CT_ASSERT(l4proto); 109 111 112 + ret = -ENOSPC; 110 113 if (seq_printf(s, "%-8s %u %ld ", 111 114 l4proto->name, nf_ct_protonum(ct), 112 115 timer_pending(&ct->timeout) 113 116 ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) 114 - return -ENOSPC; 117 + goto release; 115 118 116 119 if (l4proto->print_conntrack && l4proto->print_conntrack(s, ct)) 117 - return -ENOSPC; 120 + goto release; 118 121 119 122 if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 120 123 l3proto, l4proto)) 121 - return -ENOSPC; 124 + goto release; 122 125 123 126 if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL)) 124 - return -ENOSPC; 127 + goto release; 125 128 126 129 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 127 130 if (seq_printf(s, "[UNREPLIED] ")) 128 - return -ENOSPC; 131 + goto release; 129 132 130 133 if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, 131 134 l3proto, l4proto)) 132 - return -ENOSPC; 135 + goto release; 133 136 134 137 if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) 135 - return -ENOSPC; 138 + goto release; 136 139 137 140 if (test_bit(IPS_ASSURED_BIT, &ct->status)) 138 141 if (seq_printf(s, "[ASSURED] ")) 139 - return -ENOSPC; 142 + goto release; 140 143 141 144 #ifdef CONFIG_NF_CONNTRACK_MARK 142 145 if (seq_printf(s, "mark=%u ", ct->mark)) 143 - return -ENOSPC; 146 + goto release; 144 147 #endif 145 148 146 149 #ifdef CONFIG_NF_CONNTRACK_SECMARK 147 150 if (seq_printf(s, "secmark=%u ", ct->secmark)) 148 - return -ENOSPC; 151 + goto release; 149 152 #endif 150 153 151 154 if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 152 - return -ENOSPC; 153 - 154 - return 0; 155 + goto release; 156 + ret = 0; 157 + release: 158 + nf_ct_put(ct); 159 + return ret; 155 160 } 156 161 157 162 static const struct seq_operations ct_seq_ops = {
+6
net/ipv4/netfilter/nf_conntrack_proto_icmp.c
··· 262 262 263 263 return 0; 264 264 } 265 + 266 + static int icmp_nlattr_tuple_size(void) 267 + { 268 + return nla_policy_len(icmp_nla_policy, CTA_PROTO_MAX + 1); 269 + } 265 270 #endif 266 271 267 272 #ifdef CONFIG_SYSCTL ··· 314 309 .me = NULL, 315 310 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 316 311 .tuple_to_nlattr = icmp_tuple_to_nlattr, 312 + .nlattr_tuple_size = icmp_nlattr_tuple_size, 317 313 .nlattr_to_tuple = icmp_nlattr_to_tuple, 318 314 .nla_policy = icmp_nla_policy, 319 315 #endif
+1 -1
net/ipv4/netfilter/nf_nat_core.c
··· 679 679 static int __net_init nf_nat_net_init(struct net *net) 680 680 { 681 681 net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, 682 - &net->ipv4.nat_vmalloced); 682 + &net->ipv4.nat_vmalloced, 0); 683 683 if (!net->ipv4.nat_bysource) 684 684 return -ENOMEM; 685 685 return 0;
+5 -22
net/ipv6/netfilter/ip6_tables.c
··· 89 89 (nexthdr == IPPROTO_DSTOPTS) ); 90 90 } 91 91 92 - static unsigned long ifname_compare(const char *_a, const char *_b, 93 - const unsigned char *_mask) 94 - { 95 - const unsigned long *a = (const unsigned long *)_a; 96 - const unsigned long *b = (const unsigned long *)_b; 97 - const unsigned long *mask = (const unsigned long *)_mask; 98 - unsigned long ret; 99 - 100 - ret = (a[0] ^ b[0]) & mask[0]; 101 - if (IFNAMSIZ > sizeof(unsigned long)) 102 - ret |= (a[1] ^ b[1]) & mask[1]; 103 - if (IFNAMSIZ > 2 * sizeof(unsigned long)) 104 - ret |= (a[2] ^ b[2]) & mask[2]; 105 - if (IFNAMSIZ > 3 * sizeof(unsigned long)) 106 - ret |= (a[3] ^ b[3]) & mask[3]; 107 - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); 108 - return ret; 109 - } 110 - 111 92 /* Returns whether matches rule or not. */ 112 93 /* Performance critical - called for every packet */ 113 94 static inline bool ··· 119 138 return false; 120 139 } 121 140 122 - ret = ifname_compare(indev, ip6info->iniface, ip6info->iniface_mask); 141 + ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask); 123 142 124 143 if (FWINV(ret != 0, IP6T_INV_VIA_IN)) { 125 144 dprintf("VIA in mismatch (%s vs %s).%s\n", ··· 128 147 return false; 129 148 } 130 149 131 - ret = ifname_compare(outdev, ip6info->outiface, ip6info->outiface_mask); 150 + ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask); 132 151 133 152 if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) { 134 153 dprintf("VIA out mismatch (%s vs %s).%s\n", ··· 517 536 && unconditional(&e->ipv6)) || visited) { 518 537 unsigned int oldpos, size; 519 538 520 - if (t->verdict < -NF_MAX_VERDICT - 1) { 539 + if ((strcmp(t->target.u.user.name, 540 + IP6T_STANDARD_TARGET) == 0) && 541 + t->verdict < -NF_MAX_VERDICT - 1) { 521 542 duprintf("mark_source_chains: bad " 522 543 "negative verdict (%i)\n", 523 544 t->verdict);
+6
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
··· 342 342 343 343 return 0; 344 344 } 345 + 346 + static int ipv6_nlattr_tuple_size(void) 347 + { 348 + return nla_policy_len(ipv6_nla_policy, CTA_IP_MAX + 1); 349 + } 345 350 #endif 346 351 347 352 struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { ··· 358 353 .get_l4proto = ipv6_get_l4proto, 359 354 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 360 355 .tuple_to_nlattr = ipv6_tuple_to_nlattr, 356 + .nlattr_tuple_size = ipv6_nlattr_tuple_size, 361 357 .nlattr_to_tuple = ipv6_nlattr_to_tuple, 362 358 .nla_policy = ipv6_nla_policy, 363 359 #endif
+6
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
··· 269 269 270 270 return 0; 271 271 } 272 + 273 + static int icmpv6_nlattr_tuple_size(void) 274 + { 275 + return nla_policy_len(icmpv6_nla_policy, CTA_PROTO_MAX + 1); 276 + } 272 277 #endif 273 278 274 279 #ifdef CONFIG_SYSCTL ··· 305 300 .error = icmpv6_error, 306 301 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 307 302 .tuple_to_nlattr = icmpv6_tuple_to_nlattr, 303 + .nlattr_tuple_size = icmpv6_nlattr_tuple_size, 308 304 .nlattr_to_tuple = icmpv6_nlattr_to_tuple, 309 305 .nla_policy = icmpv6_nla_policy, 310 306 #endif
+1 -1
net/netfilter/Kconfig
··· 374 374 375 375 config NETFILTER_XT_TARGET_LED 376 376 tristate '"LED" target support' 377 - depends on LEDS_CLASS 377 + depends on LEDS_CLASS && LED_TRIGGERS 378 378 depends on NETFILTER_ADVANCED 379 379 help 380 380 This option adds a `LED' target, which allows you to blink LEDs in
+76 -53
net/netfilter/nf_conntrack_core.c
··· 29 29 #include <linux/netdevice.h> 30 30 #include <linux/socket.h> 31 31 #include <linux/mm.h> 32 + #include <linux/rculist_nulls.h> 32 33 33 34 #include <net/netfilter/nf_conntrack.h> 34 35 #include <net/netfilter/nf_conntrack_l3proto.h> ··· 164 163 clean_from_lists(struct nf_conn *ct) 165 164 { 166 165 pr_debug("clean_from_lists(%p)\n", ct); 167 - hlist_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); 168 - hlist_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnode); 166 + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); 167 + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode); 169 168 170 169 /* Destroy all pending expectations */ 171 170 nf_ct_remove_expectations(ct); ··· 205 204 206 205 /* We overload first tuple to link into unconfirmed list. */ 207 206 if (!nf_ct_is_confirmed(ct)) { 208 - BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode)); 209 - hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); 207 + BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); 208 + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); 210 209 } 211 210 212 211 NF_CT_STAT_INC(net, delete); ··· 243 242 nf_ct_put(ct); 244 243 } 245 244 245 + /* 246 + * Warning : 247 + * - Caller must take a reference on returned object 248 + * and recheck nf_ct_tuple_equal(tuple, &h->tuple) 249 + * OR 250 + * - Caller must lock nf_conntrack_lock before calling this function 251 + */ 246 252 struct nf_conntrack_tuple_hash * 247 253 __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) 248 254 { 249 255 struct nf_conntrack_tuple_hash *h; 250 - struct hlist_node *n; 256 + struct hlist_nulls_node *n; 251 257 unsigned int hash = hash_conntrack(tuple); 252 258 253 259 /* Disable BHs the entire time since we normally need to disable them 254 260 * at least once for the stats anyway. 255 261 */ 256 262 local_bh_disable(); 257 - hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { 263 + begin: 264 + hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { 258 265 if (nf_ct_tuple_equal(tuple, &h->tuple)) { 259 266 NF_CT_STAT_INC(net, found); 260 267 local_bh_enable(); ··· 270 261 } 271 262 NF_CT_STAT_INC(net, searched); 272 263 } 264 + /* 265 + * if the nulls value we got at the end of this lookup is 266 + * not the expected one, we must restart lookup. 267 + * We probably met an item that was moved to another chain. 268 + */ 269 + if (get_nulls_value(n) != hash) 270 + goto begin; 273 271 local_bh_enable(); 274 272 275 273 return NULL; ··· 291 275 struct nf_conn *ct; 292 276 293 277 rcu_read_lock(); 278 + begin: 294 279 h = __nf_conntrack_find(net, tuple); 295 280 if (h) { 296 281 ct = nf_ct_tuplehash_to_ctrack(h); 297 282 if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) 298 283 h = NULL; 284 + else { 285 + if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) { 286 + nf_ct_put(ct); 287 + goto begin; 288 + } 289 + } 299 290 } 300 291 rcu_read_unlock(); 301 292 ··· 316 293 { 317 294 struct net *net = nf_ct_net(ct); 318 295 319 - hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, 296 + hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, 320 297 &net->ct.hash[hash]); 321 - hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnode, 298 + hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode, 322 299 &net->ct.hash[repl_hash]); 323 300 } 324 301 ··· 341 318 struct nf_conntrack_tuple_hash *h; 342 319 struct nf_conn *ct; 343 320 struct nf_conn_help *help; 344 - struct hlist_node *n; 321 + struct hlist_nulls_node *n; 345 322 enum ip_conntrack_info ctinfo; 346 323 struct net *net; 347 324 ··· 373 350 /* See if there's one in the list already, including reverse: 374 351 NAT could have grabbed it without realizing, since we're 375 352 not in the hash. If there is, we lost race. */ 376 - hlist_for_each_entry(h, n, &net->ct.hash[hash], hnode) 353 + hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) 377 354 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 378 355 &h->tuple)) 379 356 goto out; 380 - hlist_for_each_entry(h, n, &net->ct.hash[repl_hash], hnode) 357 + hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) 381 358 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, 382 359 &h->tuple)) 383 360 goto out; 384 361 385 362 /* Remove from unconfirmed list */ 386 - hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); 363 + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); 387 364 388 365 __nf_conntrack_hash_insert(ct, hash, repl_hash); 389 366 /* Timer relative to confirmation time, not original ··· 422 399 { 423 400 struct net *net = nf_ct_net(ignored_conntrack); 424 401 struct nf_conntrack_tuple_hash *h; 425 - struct hlist_node *n; 402 + struct hlist_nulls_node *n; 426 403 unsigned int hash = hash_conntrack(tuple); 427 404 428 405 /* Disable BHs the entire time since we need to disable them at 429 406 * least once for the stats anyway. 430 407 */ 431 408 rcu_read_lock_bh(); 432 - hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { 409 + hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { 433 410 if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && 434 411 nf_ct_tuple_equal(tuple, &h->tuple)) { 435 412 NF_CT_STAT_INC(net, found); ··· 453 430 /* Use oldest entry, which is roughly LRU */ 454 431 struct nf_conntrack_tuple_hash *h; 455 432 struct nf_conn *ct = NULL, *tmp; 456 - struct hlist_node *n; 433 + struct hlist_nulls_node *n; 457 434 unsigned int i, cnt = 0; 458 435 int dropped = 0; 459 436 460 437 rcu_read_lock(); 461 438 for (i = 0; i < nf_conntrack_htable_size; i++) { 462 - hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], 463 - hnode) { 439 + hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], 440 + hnnode) { 464 441 tmp = nf_ct_tuplehash_to_ctrack(h); 465 442 if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) 466 443 ct = tmp; ··· 531 508 #ifdef CONFIG_NET_NS 532 509 ct->ct_net = net; 533 510 #endif 534 - INIT_RCU_HEAD(&ct->rcu); 535 511 536 512 return ct; 537 513 } 538 514 EXPORT_SYMBOL_GPL(nf_conntrack_alloc); 539 - 540 - static void nf_conntrack_free_rcu(struct rcu_head *head) 541 - { 542 - struct nf_conn *ct = container_of(head, struct nf_conn, rcu); 543 - 544 - nf_ct_ext_free(ct); 545 - kmem_cache_free(nf_conntrack_cachep, ct); 546 - } 547 515 548 516 void nf_conntrack_free(struct nf_conn *ct) 549 517 { ··· 542 528 543 529 nf_ct_ext_destroy(ct); 544 530 atomic_dec(&net->ct.count); 545 - call_rcu(&ct->rcu, nf_conntrack_free_rcu); 531 + nf_ct_ext_free(ct); 532 + kmem_cache_free(nf_conntrack_cachep, ct); 546 533 } 547 534 EXPORT_SYMBOL_GPL(nf_conntrack_free); 548 535 ··· 609 594 } 610 595 611 596 /* Overload tuple linked list to put us in unconfirmed list. */ 612 - hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, 597 + hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, 613 598 &net->ct.unconfirmed); 614 599 615 600 spin_unlock_bh(&nf_conntrack_lock); ··· 921 906 return 0; 922 907 } 923 908 EXPORT_SYMBOL_GPL(nf_ct_port_nlattr_to_tuple); 909 + 910 + int nf_ct_port_nlattr_tuple_size(void) 911 + { 912 + return nla_policy_len(nf_ct_port_nla_policy, CTA_PROTO_MAX + 1); 913 + } 914 + EXPORT_SYMBOL_GPL(nf_ct_port_nlattr_tuple_size); 924 915 #endif 925 916 926 917 /* Used by ipt_REJECT and ip6t_REJECT. */ ··· 955 934 { 956 935 struct nf_conntrack_tuple_hash *h; 957 936 struct nf_conn *ct; 958 - struct hlist_node *n; 937 + struct hlist_nulls_node *n; 959 938 960 939 spin_lock_bh(&nf_conntrack_lock); 961 940 for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { 962 - hlist_for_each_entry(h, n, &net->ct.hash[*bucket], hnode) { 941 + hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { 963 942 ct = nf_ct_tuplehash_to_ctrack(h); 964 943 if (iter(ct, data)) 965 944 goto found; 966 945 } 967 946 } 968 - hlist_for_each_entry(h, n, &net->ct.unconfirmed, hnode) { 947 + hlist_nulls_for_each_entry(h, n, &net->ct.unconfirmed, hnnode) { 969 948 ct = nf_ct_tuplehash_to_ctrack(h); 970 949 if (iter(ct, data)) 971 950 set_bit(IPS_DYING_BIT, &ct->status); ··· 1013 992 return 1; 1014 993 } 1015 994 1016 - void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, unsigned int size) 995 + void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size) 1017 996 { 1018 997 if (vmalloced) 1019 998 vfree(hash); ··· 1081 1060 } 1082 1061 } 1083 1062 1084 - struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) 1063 + void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls) 1085 1064 { 1086 - struct hlist_head *hash; 1087 - unsigned int size, i; 1065 + struct hlist_nulls_head *hash; 1066 + unsigned int nr_slots, i; 1067 + size_t sz; 1088 1068 1089 1069 *vmalloced = 0; 1090 1070 1091 - size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head)); 1092 - hash = (void*)__get_free_pages(GFP_KERNEL|__GFP_NOWARN, 1093 - get_order(sizeof(struct hlist_head) 1094 - * size)); 1071 + BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head)); 1072 + nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head)); 1073 + sz = nr_slots * sizeof(struct hlist_nulls_head); 1074 + hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 1075 + get_order(sz)); 1095 1076 if (!hash) { 1096 1077 *vmalloced = 1; 1097 1078 printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); 1098 - hash = vmalloc(sizeof(struct hlist_head) * size); 1079 + hash = __vmalloc(sz, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); 1099 1080 } 1100 1081 1101 - if (hash) 1102 - for (i = 0; i < size; i++) 1103 - INIT_HLIST_HEAD(&hash[i]); 1082 + if (hash && nulls) 1083 + for (i = 0; i < nr_slots; i++) 1084 + INIT_HLIST_NULLS_HEAD(&hash[i], i); 1104 1085 1105 1086 return hash; 1106 1087 } ··· 1113 1090 int i, bucket, vmalloced, old_vmalloced; 1114 1091 unsigned int hashsize, old_size; 1115 1092 int rnd; 1116 - struct hlist_head *hash, *old_hash; 1093 + struct hlist_nulls_head *hash, *old_hash; 1117 1094 struct nf_conntrack_tuple_hash *h; 1118 1095 1119 1096 /* On boot, we can set this without any fancy locking. */ ··· 1124 1101 if (!hashsize) 1125 1102 return -EINVAL; 1126 1103 1127 - hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced); 1104 + hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced, 1); 1128 1105 if (!hash) 1129 1106 return -ENOMEM; 1130 1107 ··· 1139 1116 */ 1140 1117 spin_lock_bh(&nf_conntrack_lock); 1141 1118 for (i = 0; i < nf_conntrack_htable_size; i++) { 1142 - while (!hlist_empty(&init_net.ct.hash[i])) { 1143 - h = hlist_entry(init_net.ct.hash[i].first, 1144 - struct nf_conntrack_tuple_hash, hnode); 1145 - hlist_del_rcu(&h->hnode); 1119 + while (!hlist_nulls_empty(&init_net.ct.hash[i])) { 1120 + h = hlist_nulls_entry(init_net.ct.hash[i].first, 1121 + struct nf_conntrack_tuple_hash, hnnode); 1122 + hlist_nulls_del_rcu(&h->hnnode); 1146 1123 bucket = __hash_conntrack(&h->tuple, hashsize, rnd); 1147 - hlist_add_head(&h->hnode, &hash[bucket]); 1124 + hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); 1148 1125 } 1149 1126 } 1150 1127 old_size = nf_conntrack_htable_size; ··· 1195 1172 1196 1173 nf_conntrack_cachep = kmem_cache_create("nf_conntrack", 1197 1174 sizeof(struct nf_conn), 1198 - 0, 0, NULL); 1175 + 0, SLAB_DESTROY_BY_RCU, NULL); 1199 1176 if (!nf_conntrack_cachep) { 1200 1177 printk(KERN_ERR "Unable to create nf_conn slab cache\n"); 1201 1178 ret = -ENOMEM; ··· 1225 1202 int ret; 1226 1203 1227 1204 atomic_set(&net->ct.count, 0); 1228 - INIT_HLIST_HEAD(&net->ct.unconfirmed); 1205 + INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, 0); 1229 1206 net->ct.stat = alloc_percpu(struct ip_conntrack_stat); 1230 1207 if (!net->ct.stat) { 1231 1208 ret = -ENOMEM; ··· 1235 1212 if (ret < 0) 1236 1213 goto err_ecache; 1237 1214 net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, 1238 - &net->ct.hash_vmalloc); 1215 + &net->ct.hash_vmalloc, 1); 1239 1216 if (!net->ct.hash) { 1240 1217 ret = -ENOMEM; 1241 1218 printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
+1 -1
net/netfilter/nf_conntrack_expect.c
··· 604 604 605 605 net->ct.expect_count = 0; 606 606 net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 607 - &net->ct.expect_vmalloc); 607 + &net->ct.expect_vmalloc, 0); 608 608 if (net->ct.expect_hash == NULL) 609 609 goto err1; 610 610
+5 -3
net/netfilter/nf_conntrack_helper.c
··· 142 142 143 143 BUG_ON(me->expect_policy == NULL); 144 144 BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); 145 + BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1); 145 146 146 147 mutex_lock(&nf_ct_helper_mutex); 147 148 hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); ··· 159 158 struct nf_conntrack_tuple_hash *h; 160 159 struct nf_conntrack_expect *exp; 161 160 const struct hlist_node *n, *next; 161 + const struct hlist_nulls_node *nn; 162 162 unsigned int i; 163 163 164 164 /* Get rid of expectations */ ··· 176 174 } 177 175 178 176 /* Get rid of expecteds, set helpers to NULL. */ 179 - hlist_for_each_entry(h, n, &net->ct.unconfirmed, hnode) 177 + hlist_for_each_entry(h, nn, &net->ct.unconfirmed, hnnode) 180 178 unhelp(h, me); 181 179 for (i = 0; i < nf_conntrack_htable_size; i++) { 182 - hlist_for_each_entry(h, n, &net->ct.hash[i], hnode) 180 + hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) 183 181 unhelp(h, me); 184 182 } 185 183 } ··· 219 217 220 218 nf_ct_helper_hsize = 1; /* gets rounded up to use one page */ 221 219 nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 222 - &nf_ct_helper_vmalloc); 220 + &nf_ct_helper_vmalloc, 0); 223 221 if (!nf_ct_helper_hash) 224 222 return -ENOMEM; 225 223
+84 -10
net/netfilter/nf_conntrack_netlink.c
··· 19 19 #include <linux/module.h> 20 20 #include <linux/kernel.h> 21 21 #include <linux/rculist.h> 22 + #include <linux/rculist_nulls.h> 22 23 #include <linux/types.h> 23 24 #include <linux/timer.h> 24 25 #include <linux/skbuff.h> ··· 405 404 } 406 405 407 406 #ifdef CONFIG_NF_CONNTRACK_EVENTS 407 + /* 408 + * The general structure of a ctnetlink event is 409 + * 410 + * CTA_TUPLE_ORIG 411 + * <l3/l4-proto-attributes> 412 + * CTA_TUPLE_REPLY 413 + * <l3/l4-proto-attributes> 414 + * CTA_ID 415 + * ... 416 + * CTA_PROTOINFO 417 + * <l4-proto-attributes> 418 + * CTA_TUPLE_MASTER 419 + * <l3/l4-proto-attributes> 420 + * 421 + * Therefore the formular is 422 + * 423 + * size = sizeof(headers) + sizeof(generic_nlas) + 3 * sizeof(tuple_nlas) 424 + * + sizeof(protoinfo_nlas) 425 + */ 426 + static struct sk_buff * 427 + ctnetlink_alloc_skb(const struct nf_conntrack_tuple *tuple, gfp_t gfp) 428 + { 429 + struct nf_conntrack_l3proto *l3proto; 430 + struct nf_conntrack_l4proto *l4proto; 431 + int len; 432 + 433 + #define NLA_TYPE_SIZE(type) nla_total_size(sizeof(type)) 434 + 435 + /* proto independant part */ 436 + len = NLMSG_SPACE(sizeof(struct nfgenmsg)) 437 + + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ 438 + + 3 * nla_total_size(0) /* CTA_TUPLE_IP */ 439 + + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */ 440 + + 3 * NLA_TYPE_SIZE(u_int8_t) /* CTA_PROTO_NUM */ 441 + + NLA_TYPE_SIZE(u_int32_t) /* CTA_ID */ 442 + + NLA_TYPE_SIZE(u_int32_t) /* CTA_STATUS */ 443 + #ifdef CONFIG_NF_CT_ACCT 444 + + 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ 445 + + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_PACKETS */ 446 + + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_BYTES */ 447 + #endif 448 + + NLA_TYPE_SIZE(u_int32_t) /* CTA_TIMEOUT */ 449 + + nla_total_size(0) /* CTA_PROTOINFO */ 450 + + nla_total_size(0) /* CTA_HELP */ 451 + + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ 452 + #ifdef CONFIG_NF_CONNTRACK_SECMARK 453 + + NLA_TYPE_SIZE(u_int32_t) /* CTA_SECMARK */ 454 + #endif 455 + #ifdef CONFIG_NF_NAT_NEEDED 456 + + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ 457 + + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_POS */ 458 + + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_BEFORE */ 459 + + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_AFTER */ 460 + #endif 461 + #ifdef CONFIG_NF_CONNTRACK_MARK 462 + + NLA_TYPE_SIZE(u_int32_t) /* CTA_MARK */ 463 + #endif 464 + ; 465 + 466 + #undef NLA_TYPE_SIZE 467 + 468 + rcu_read_lock(); 469 + l3proto = __nf_ct_l3proto_find(tuple->src.l3num); 470 + len += l3proto->nla_size; 471 + 472 + l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum); 473 + len += l4proto->nla_size; 474 + rcu_read_unlock(); 475 + 476 + return alloc_skb(len, gfp); 477 + } 478 + 408 479 static int ctnetlink_conntrack_event(struct notifier_block *this, 409 480 unsigned long events, void *ptr) 410 481 { ··· 510 437 if (!item->report && !nfnetlink_has_listeners(group)) 511 438 return NOTIFY_DONE; 512 439 513 - skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 440 + skb = ctnetlink_alloc_skb(tuple(ct, IP_CT_DIR_ORIGINAL), GFP_ATOMIC); 514 441 if (!skb) 515 442 return NOTIFY_DONE; 516 443 ··· 609 536 { 610 537 struct nf_conn *ct, *last; 611 538 struct nf_conntrack_tuple_hash *h; 612 - struct hlist_node *n; 539 + struct hlist_nulls_node *n; 613 540 struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); 614 541 u_int8_t l3proto = nfmsg->nfgen_family; 615 542 ··· 617 544 last = (struct nf_conn *)cb->args[1]; 618 545 for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { 619 546 restart: 620 - hlist_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]], 621 - hnode) { 547 + hlist_nulls_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]], 548 + hnnode) { 622 549 if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) 623 550 continue; 624 551 ct = nf_ct_tuplehash_to_ctrack(h); 552 + if (!atomic_inc_not_zero(&ct->ct_general.use)) 553 + continue; 625 554 /* Dump entries of a given L3 protocol number. 626 555 * If it is not specified, ie. l3proto == 0, 627 556 * then dump everything. */ 628 557 if (l3proto && nf_ct_l3num(ct) != l3proto) 629 - continue; 558 + goto releasect; 630 559 if (cb->args[1]) { 631 560 if (ct != last) 632 - continue; 561 + goto releasect; 633 562 cb->args[1] = 0; 634 563 } 635 564 if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, 636 565 cb->nlh->nlmsg_seq, 637 566 IPCTNL_MSG_CT_NEW, 638 567 1, ct) < 0) { 639 - if (!atomic_inc_not_zero(&ct->ct_general.use)) 640 - continue; 641 568 cb->args[1] = (unsigned long)ct; 642 569 goto out; 643 570 } ··· 650 577 if (acct) 651 578 memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX])); 652 579 } 580 + releasect: 581 + nf_ct_put(ct); 653 582 } 654 583 if (cb->args[1]) { 655 584 cb->args[1] = 0; ··· 1317 1242 if (err < 0) 1318 1243 goto err2; 1319 1244 1320 - master_h = __nf_conntrack_find(&init_net, &master); 1245 + master_h = nf_conntrack_find_get(&init_net, &master); 1321 1246 if (master_h == NULL) { 1322 1247 err = -ENOENT; 1323 1248 goto err2; 1324 1249 } 1325 1250 master_ct = nf_ct_tuplehash_to_ctrack(master_h); 1326 - nf_conntrack_get(&master_ct->ct_general); 1327 1251 __set_bit(IPS_EXPECTED_BIT, &ct->status); 1328 1252 ct->master = master_ct; 1329 1253 }
+16
net/netfilter/nf_conntrack_proto.c
··· 167 167 if (proto->l3proto >= AF_MAX) 168 168 return -EBUSY; 169 169 170 + if (proto->tuple_to_nlattr && !proto->nlattr_tuple_size) 171 + return -EINVAL; 172 + 170 173 mutex_lock(&nf_ct_proto_mutex); 171 174 if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { 172 175 ret = -EBUSY; ··· 179 176 ret = nf_ct_l3proto_register_sysctl(proto); 180 177 if (ret < 0) 181 178 goto out_unlock; 179 + 180 + if (proto->nlattr_tuple_size) 181 + proto->nla_size = 3 * proto->nlattr_tuple_size(); 182 182 183 183 rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); 184 184 ··· 269 263 if (l4proto->l3proto >= PF_MAX) 270 264 return -EBUSY; 271 265 266 + if ((l4proto->to_nlattr && !l4proto->nlattr_size) 267 + || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size)) 268 + return -EINVAL; 269 + 272 270 mutex_lock(&nf_ct_proto_mutex); 273 271 if (!nf_ct_protos[l4proto->l3proto]) { 274 272 /* l3proto may be loaded latter. */ ··· 299 289 ret = nf_ct_l4proto_register_sysctl(l4proto); 300 290 if (ret < 0) 301 291 goto out_unlock; 292 + 293 + l4proto->nla_size = 0; 294 + if (l4proto->nlattr_size) 295 + l4proto->nla_size += l4proto->nlattr_size(); 296 + if (l4proto->nlattr_tuple_size) 297 + l4proto->nla_size += 3 * l4proto->nlattr_tuple_size(); 302 298 303 299 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], 304 300 l4proto);
+9
net/netfilter/nf_conntrack_proto_dccp.c
··· 669 669 write_unlock_bh(&dccp_lock); 670 670 return 0; 671 671 } 672 + 673 + static int dccp_nlattr_size(void) 674 + { 675 + return nla_total_size(0) /* CTA_PROTOINFO_DCCP */ 676 + + nla_policy_len(dccp_nla_policy, CTA_PROTOINFO_DCCP_MAX + 1); 677 + } 672 678 #endif 673 679 674 680 #ifdef CONFIG_SYSCTL ··· 755 749 .print_conntrack = dccp_print_conntrack, 756 750 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 757 751 .to_nlattr = dccp_to_nlattr, 752 + .nlattr_size = dccp_nlattr_size, 758 753 .from_nlattr = nlattr_to_dccp, 759 754 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 755 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 760 756 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 761 757 .nla_policy = nf_ct_port_nla_policy, 762 758 #endif ··· 779 771 .to_nlattr = dccp_to_nlattr, 780 772 .from_nlattr = nlattr_to_dccp, 781 773 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 774 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 782 775 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 783 776 .nla_policy = nf_ct_port_nla_policy, 784 777 #endif
+1
net/netfilter/nf_conntrack_proto_gre.c
··· 293 293 .me = THIS_MODULE, 294 294 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 295 295 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 296 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 296 297 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 297 298 .nla_policy = nf_ct_port_nla_policy, 298 299 #endif
+10
net/netfilter/nf_conntrack_proto_sctp.c
··· 537 537 538 538 return 0; 539 539 } 540 + 541 + static int sctp_nlattr_size(void) 542 + { 543 + return nla_total_size(0) /* CTA_PROTOINFO_SCTP */ 544 + + nla_policy_len(sctp_nla_policy, CTA_PROTOINFO_SCTP_MAX + 1); 545 + } 540 546 #endif 541 547 542 548 #ifdef CONFIG_SYSCTL ··· 674 668 .me = THIS_MODULE, 675 669 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 676 670 .to_nlattr = sctp_to_nlattr, 671 + .nlattr_size = sctp_nlattr_size, 677 672 .from_nlattr = nlattr_to_sctp, 678 673 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 674 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 679 675 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 680 676 .nla_policy = nf_ct_port_nla_policy, 681 677 #endif ··· 704 696 .me = THIS_MODULE, 705 697 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 706 698 .to_nlattr = sctp_to_nlattr, 699 + .nlattr_size = sctp_nlattr_size, 707 700 .from_nlattr = nlattr_to_sctp, 708 701 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 702 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 709 703 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 710 704 .nla_policy = nf_ct_port_nla_policy, 711 705 #endif
+15
net/netfilter/nf_conntrack_proto_tcp.c
··· 1184 1184 1185 1185 return 0; 1186 1186 } 1187 + 1188 + static int tcp_nlattr_size(void) 1189 + { 1190 + return nla_total_size(0) /* CTA_PROTOINFO_TCP */ 1191 + + nla_policy_len(tcp_nla_policy, CTA_PROTOINFO_TCP_MAX + 1); 1192 + } 1193 + 1194 + static int tcp_nlattr_tuple_size(void) 1195 + { 1196 + return nla_policy_len(nf_ct_port_nla_policy, CTA_PROTO_MAX + 1); 1197 + } 1187 1198 #endif 1188 1199 1189 1200 #ifdef CONFIG_SYSCTL ··· 1410 1399 .error = tcp_error, 1411 1400 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 1412 1401 .to_nlattr = tcp_to_nlattr, 1402 + .nlattr_size = tcp_nlattr_size, 1413 1403 .from_nlattr = nlattr_to_tcp, 1414 1404 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 1415 1405 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 1406 + .nlattr_tuple_size = tcp_nlattr_tuple_size, 1416 1407 .nla_policy = nf_ct_port_nla_policy, 1417 1408 #endif 1418 1409 #ifdef CONFIG_SYSCTL ··· 1442 1429 .error = tcp_error, 1443 1430 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 1444 1431 .to_nlattr = tcp_to_nlattr, 1432 + .nlattr_size = tcp_nlattr_size, 1445 1433 .from_nlattr = nlattr_to_tcp, 1446 1434 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 1447 1435 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 1436 + .nlattr_tuple_size = tcp_nlattr_tuple_size, 1448 1437 .nla_policy = nf_ct_port_nla_policy, 1449 1438 #endif 1450 1439 #ifdef CONFIG_SYSCTL
+2
net/netfilter/nf_conntrack_proto_udp.c
··· 195 195 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 196 196 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 197 197 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 198 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 198 199 .nla_policy = nf_ct_port_nla_policy, 199 200 #endif 200 201 #ifdef CONFIG_SYSCTL ··· 223 222 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 224 223 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 225 224 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 225 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 226 226 .nla_policy = nf_ct_port_nla_policy, 227 227 #endif 228 228 #ifdef CONFIG_SYSCTL
+1
net/netfilter/nf_conntrack_proto_udplite.c
··· 180 180 .error = udplite_error, 181 181 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 182 182 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 183 + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 183 184 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 184 185 .nla_policy = nf_ct_port_nla_policy, 185 186 #endif
+33 -24
net/netfilter/nf_conntrack_standalone.c
··· 44 44 unsigned int bucket; 45 45 }; 46 46 47 - static struct hlist_node *ct_get_first(struct seq_file *seq) 47 + static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) 48 48 { 49 49 struct net *net = seq_file_net(seq); 50 50 struct ct_iter_state *st = seq->private; 51 - struct hlist_node *n; 51 + struct hlist_nulls_node *n; 52 52 53 53 for (st->bucket = 0; 54 54 st->bucket < nf_conntrack_htable_size; 55 55 st->bucket++) { 56 56 n = rcu_dereference(net->ct.hash[st->bucket].first); 57 - if (n) 57 + if (!is_a_nulls(n)) 58 58 return n; 59 59 } 60 60 return NULL; 61 61 } 62 62 63 - static struct hlist_node *ct_get_next(struct seq_file *seq, 64 - struct hlist_node *head) 63 + static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, 64 + struct hlist_nulls_node *head) 65 65 { 66 66 struct net *net = seq_file_net(seq); 67 67 struct ct_iter_state *st = seq->private; 68 68 69 69 head = rcu_dereference(head->next); 70 - while (head == NULL) { 71 - if (++st->bucket >= nf_conntrack_htable_size) 72 - return NULL; 70 + while (is_a_nulls(head)) { 71 + if (likely(get_nulls_value(head) == st->bucket)) { 72 + if (++st->bucket >= nf_conntrack_htable_size) 73 + return NULL; 74 + } 73 75 head = rcu_dereference(net->ct.hash[st->bucket].first); 74 76 } 75 77 return head; 76 78 } 77 79 78 - static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) 80 + static struct hlist_nulls_node *ct_get_idx(struct seq_file *seq, loff_t pos) 79 81 { 80 - struct hlist_node *head = ct_get_first(seq); 82 + struct hlist_nulls_node *head = ct_get_first(seq); 81 83 82 84 if (head) 83 85 while (pos && (head = ct_get_next(seq, head))) ··· 109 107 /* return 0 on success, 1 in case of error */ 110 108 static int ct_seq_show(struct seq_file *s, void *v) 111 109 { 112 - const struct nf_conntrack_tuple_hash *hash = v; 113 - const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); 110 + struct nf_conntrack_tuple_hash *hash = v; 111 + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); 114 112 const struct nf_conntrack_l3proto *l3proto; 115 113 const struct nf_conntrack_l4proto *l4proto; 114 + int ret = 0; 116 115 117 116 NF_CT_ASSERT(ct); 117 + if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) 118 + return 0; 118 119 119 120 /* we only want to print DIR_ORIGINAL */ 120 121 if (NF_CT_DIRECTION(hash)) 121 - return 0; 122 + goto release; 122 123 123 124 l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); 124 125 NF_CT_ASSERT(l3proto); 125 126 l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); 126 127 NF_CT_ASSERT(l4proto); 127 128 129 + ret = -ENOSPC; 128 130 if (seq_printf(s, "%-8s %u %-8s %u %ld ", 129 131 l3proto->name, nf_ct_l3num(ct), 130 132 l4proto->name, nf_ct_protonum(ct), 131 133 timer_pending(&ct->timeout) 132 134 ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) 133 - return -ENOSPC; 135 + goto release; 134 136 135 137 if (l4proto->print_conntrack && l4proto->print_conntrack(s, ct)) 136 - return -ENOSPC; 138 + goto release; 137 139 138 140 if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 139 141 l3proto, l4proto)) 140 - return -ENOSPC; 142 + goto release; 141 143 142 144 if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL)) 143 - return -ENOSPC; 145 + goto release; 144 146 145 147 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) 146 148 if (seq_printf(s, "[UNREPLIED] ")) 147 - return -ENOSPC; 149 + goto release; 148 150 149 151 if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, 150 152 l3proto, l4proto)) 151 - return -ENOSPC; 153 + goto release; 152 154 153 155 if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) 154 - return -ENOSPC; 156 + goto release; 155 157 156 158 if (test_bit(IPS_ASSURED_BIT, &ct->status)) 157 159 if (seq_printf(s, "[ASSURED] ")) 158 - return -ENOSPC; 160 + goto release; 159 161 160 162 #if defined(CONFIG_NF_CONNTRACK_MARK) 161 163 if (seq_printf(s, "mark=%u ", ct->mark)) 162 - return -ENOSPC; 164 + goto release; 163 165 #endif 164 166 165 167 #ifdef CONFIG_NF_CONNTRACK_SECMARK 166 168 if (seq_printf(s, "secmark=%u ", ct->secmark)) 167 - return -ENOSPC; 169 + goto release; 168 170 #endif 169 171 170 172 if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 171 - return -ENOSPC; 173 + goto release; 172 174 175 + ret = 0; 176 + release: 177 + nf_ct_put(ct); 173 178 return 0; 174 179 } 175 180
+4 -2
net/netfilter/xt_connlimit.c
··· 108 108 const struct nf_conntrack_tuple_hash *found; 109 109 struct xt_connlimit_conn *conn; 110 110 struct xt_connlimit_conn *tmp; 111 - const struct nf_conn *found_ct; 111 + struct nf_conn *found_ct; 112 112 struct list_head *hash; 113 113 bool addit = true; 114 114 int matches = 0; ··· 123 123 124 124 /* check the saved connections */ 125 125 list_for_each_entry_safe(conn, tmp, hash, list) { 126 - found = __nf_conntrack_find(&init_net, &conn->tuple); 126 + found = nf_conntrack_find_get(&init_net, &conn->tuple); 127 127 found_ct = NULL; 128 128 129 129 if (found != NULL) ··· 151 151 * we do not care about connections which are 152 152 * closed already -> ditch it 153 153 */ 154 + nf_ct_put(found_ct); 154 155 list_del(&conn->list); 155 156 kfree(conn); 156 157 continue; ··· 161 160 match->family)) 162 161 /* same source network -> be counted! */ 163 162 ++matches; 163 + nf_ct_put(found_ct); 164 164 } 165 165 166 166 rcu_read_unlock();
+2 -19
net/netfilter/xt_physdev.c
··· 20 20 MODULE_ALIAS("ipt_physdev"); 21 21 MODULE_ALIAS("ip6t_physdev"); 22 22 23 - static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) 24 - { 25 - const unsigned long *a = (const unsigned long *)_a; 26 - const unsigned long *b = (const unsigned long *)_b; 27 - const unsigned long *mask = (const unsigned long *)_mask; 28 - unsigned long ret; 29 - 30 - ret = (a[0] ^ b[0]) & mask[0]; 31 - if (IFNAMSIZ > sizeof(unsigned long)) 32 - ret |= (a[1] ^ b[1]) & mask[1]; 33 - if (IFNAMSIZ > 2 * sizeof(unsigned long)) 34 - ret |= (a[2] ^ b[2]) & mask[2]; 35 - if (IFNAMSIZ > 3 * sizeof(unsigned long)) 36 - ret |= (a[3] ^ b[3]) & mask[3]; 37 - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); 38 - return ret; 39 - } 40 23 41 24 static bool 42 25 physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par) ··· 68 85 if (!(info->bitmask & XT_PHYSDEV_OP_IN)) 69 86 goto match_outdev; 70 87 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; 71 - ret = ifname_compare(indev, info->physindev, info->in_mask); 88 + ret = ifname_compare_aligned(indev, info->physindev, info->in_mask); 72 89 73 90 if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN)) 74 91 return false; ··· 78 95 return true; 79 96 outdev = nf_bridge->physoutdev ? 80 97 nf_bridge->physoutdev->name : nulldevname; 81 - ret = ifname_compare(outdev, info->physoutdev, info->out_mask); 98 + ret = ifname_compare_aligned(outdev, info->physoutdev, info->out_mask); 82 99 83 100 return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT)); 84 101 }