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

inetpeer: add namespace support for inetpeer

now inetpeer doesn't support namespace,the information will
be leaking across namespace.

this patch move the global vars v4_peers and v6_peers to
netns_ipv4 and netns_ipv6 as a field peers.

add struct pernet_operations inetpeer_ops to initial pernet
inetpeer data.

and change family_to_base and inet_getpeer to support namespace.

Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Gao feng and committed by
David S. Miller
c8a627ed 1578e777

+59 -24
+6 -4
include/net/inetpeer.h
··· 75 75 } 76 76 77 77 /* can be called with or without local BH being disabled */ 78 - struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create); 78 + struct inet_peer *inet_getpeer(struct net *net, 79 + const struct inetpeer_addr *daddr, 80 + int create); 79 81 80 82 static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) 81 83 { ··· 85 83 86 84 daddr.addr.a4 = v4daddr; 87 85 daddr.family = AF_INET; 88 - return inet_getpeer(&daddr, create); 86 + return inet_getpeer(&init_net, &daddr, create); 89 87 } 90 88 91 89 static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create) ··· 94 92 95 93 *(struct in6_addr *)daddr.addr.a6 = *v6daddr; 96 94 daddr.family = AF_INET6; 97 - return inet_getpeer(&daddr, create); 95 + return inet_getpeer(&init_net, &daddr, create); 98 96 } 99 97 100 98 /* can be called from BH context or outside */ 101 99 extern void inet_putpeer(struct inet_peer *p); 102 100 extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); 103 101 104 - extern void inetpeer_invalidate_tree(int family); 102 + extern void inetpeer_invalidate_tree(struct net *net, int family); 105 103 106 104 /* 107 105 * temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
+1 -1
include/net/netns/ipv4.h
··· 30 30 31 31 struct sock **icmp_sk; 32 32 struct sock *tcp_sock; 33 - 33 + struct inet_peer_base *peers; 34 34 struct netns_frags frags; 35 35 #ifdef CONFIG_NETFILTER 36 36 struct xt_table *iptable_filter;
+1
include/net/netns/ipv6.h
··· 33 33 struct netns_sysctl_ipv6 sysctl; 34 34 struct ipv6_devconf *devconf_all; 35 35 struct ipv6_devconf *devconf_dflt; 36 + struct inet_peer_base *peers; 36 37 struct netns_frags frags; 37 38 #ifdef CONFIG_NETFILTER 38 39 struct xt_table *ip6table_filter;
+50 -18
net/ipv4/inetpeer.c
··· 88 88 int total; 89 89 }; 90 90 91 - static struct inet_peer_base v4_peers = { 92 - .root = peer_avl_empty_rcu, 93 - .lock = __SEQLOCK_UNLOCKED(v4_peers.lock), 94 - .total = 0, 95 - }; 96 - 97 - static struct inet_peer_base v6_peers = { 98 - .root = peer_avl_empty_rcu, 99 - .lock = __SEQLOCK_UNLOCKED(v6_peers.lock), 100 - .total = 0, 101 - }; 102 - 103 91 #define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */ 104 92 105 93 /* Exported for sysctl_net_ipv4. */ ··· 141 153 schedule_delayed_work(&gc_work, gc_delay); 142 154 } 143 155 156 + static int __net_init inetpeer_net_init(struct net *net) 157 + { 158 + net->ipv4.peers = kzalloc(sizeof(struct inet_peer_base), 159 + GFP_KERNEL); 160 + if (net->ipv4.peers == NULL) 161 + return -ENOMEM; 162 + 163 + net->ipv4.peers->root = peer_avl_empty_rcu; 164 + seqlock_init(&net->ipv4.peers->lock); 165 + 166 + net->ipv6.peers = kzalloc(sizeof(struct inet_peer_base), 167 + GFP_KERNEL); 168 + if (net->ipv6.peers == NULL) 169 + goto out_ipv6; 170 + 171 + net->ipv6.peers->root = peer_avl_empty_rcu; 172 + seqlock_init(&net->ipv6.peers->lock); 173 + 174 + return 0; 175 + out_ipv6: 176 + kfree(net->ipv4.peers); 177 + return -ENOMEM; 178 + } 179 + 180 + static void __net_exit inetpeer_net_exit(struct net *net) 181 + { 182 + inetpeer_invalidate_tree(net, AF_INET); 183 + kfree(net->ipv4.peers); 184 + net->ipv4.peers = NULL; 185 + 186 + inetpeer_invalidate_tree(net, AF_INET6); 187 + kfree(net->ipv6.peers); 188 + net->ipv6.peers = NULL; 189 + } 190 + 191 + static struct pernet_operations inetpeer_ops = { 192 + .init = inetpeer_net_init, 193 + .exit = inetpeer_net_exit, 194 + }; 195 + 144 196 /* Called from ip_output.c:ip_init */ 145 197 void __init inet_initpeers(void) 146 198 { ··· 205 177 NULL); 206 178 207 179 INIT_DELAYED_WORK_DEFERRABLE(&gc_work, inetpeer_gc_worker); 180 + register_pernet_subsys(&inetpeer_ops); 208 181 } 209 182 210 183 static int addr_compare(const struct inetpeer_addr *a, ··· 430 401 call_rcu(&p->rcu, inetpeer_free_rcu); 431 402 } 432 403 433 - static struct inet_peer_base *family_to_base(int family) 404 + static struct inet_peer_base *family_to_base(struct net *net, 405 + int family) 434 406 { 435 - return family == AF_INET ? &v4_peers : &v6_peers; 407 + return family == AF_INET ? net->ipv4.peers : net->ipv6.peers; 436 408 } 437 409 438 410 /* perform garbage collect on all items stacked during a lookup */ ··· 473 443 return cnt; 474 444 } 475 445 476 - struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create) 446 + struct inet_peer *inet_getpeer(struct net *net, 447 + const struct inetpeer_addr *daddr, 448 + int create) 477 449 { 478 450 struct inet_peer __rcu **stack[PEER_MAXDEPTH], ***stackptr; 479 - struct inet_peer_base *base = family_to_base(daddr->family); 451 + struct inet_peer_base *base = family_to_base(net, daddr->family); 480 452 struct inet_peer *p; 481 453 unsigned int sequence; 482 454 int invalidated, gccnt = 0; ··· 603 571 schedule_delayed_work(&gc_work, gc_delay); 604 572 } 605 573 606 - void inetpeer_invalidate_tree(int family) 574 + void inetpeer_invalidate_tree(struct net *net, int family) 607 575 { 608 576 struct inet_peer *old, *new, *prev; 609 - struct inet_peer_base *base = family_to_base(family); 577 + struct inet_peer_base *base = family_to_base(net, family); 610 578 611 579 write_seqlock_bh(&base->lock); 612 580
+1 -1
net/ipv4/route.c
··· 938 938 939 939 get_random_bytes(&shuffle, sizeof(shuffle)); 940 940 atomic_add(shuffle + 1U, &net->ipv4.rt_genid); 941 - inetpeer_invalidate_tree(AF_INET); 941 + inetpeer_invalidate_tree(net, AF_INET); 942 942 } 943 943 944 944 /*