diff options
author | Eric Dumazet <edumazet@google.com> | 2012-07-17 16:42:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-17 16:47:33 -0400 |
commit | 5abf7f7e0f6bdbfcac737f636497d7016d9507eb (patch) | |
tree | c52a21ed83a306c6626a00378934a28a6daa8db0 /net/ipv4 | |
parent | d3a25c980fc231238256f8d80816367674e5caaf (diff) |
ipv4: fix rcu splat
free_nh_exceptions() should use rcu_dereference_protected(..., 1)
since its called after one RCU grace period.
Also add some const-ification in recent code.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/fib_semantics.c | 4 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 4 | ||||
-rw-r--r-- | net/ipv4/route.c | 13 |
3 files changed, 11 insertions, 10 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 1e09852df512..2b57d768240d 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -148,11 +148,11 @@ static void free_nh_exceptions(struct fib_nh *nh) | |||
148 | for (i = 0; i < FNHE_HASH_SIZE; i++) { | 148 | for (i = 0; i < FNHE_HASH_SIZE; i++) { |
149 | struct fib_nh_exception *fnhe; | 149 | struct fib_nh_exception *fnhe; |
150 | 150 | ||
151 | fnhe = rcu_dereference(hash[i].chain); | 151 | fnhe = rcu_dereference_protected(hash[i].chain, 1); |
152 | while (fnhe) { | 152 | while (fnhe) { |
153 | struct fib_nh_exception *next; | 153 | struct fib_nh_exception *next; |
154 | 154 | ||
155 | next = rcu_dereference(fnhe->fnhe_next); | 155 | next = rcu_dereference_protected(fnhe->fnhe_next, 1); |
156 | kfree(fnhe); | 156 | kfree(fnhe); |
157 | 157 | ||
158 | fnhe = next; | 158 | fnhe = next; |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 3ea465286a39..c7a4de05ca04 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -806,8 +806,8 @@ EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt); | |||
806 | 806 | ||
807 | static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl) | 807 | static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl) |
808 | { | 808 | { |
809 | struct inet_sock *inet = inet_sk(sk); | 809 | const struct inet_sock *inet = inet_sk(sk); |
810 | struct ip_options_rcu *inet_opt; | 810 | const struct ip_options_rcu *inet_opt; |
811 | __be32 daddr = inet->inet_daddr; | 811 | __be32 daddr = inet->inet_daddr; |
812 | struct flowi4 *fl4; | 812 | struct flowi4 *fl4; |
813 | struct rtable *rt; | 813 | struct rtable *rt; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 812e4447a223..f67e70236728 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1275,7 +1275,7 @@ static void rt_del(unsigned int hash, struct rtable *rt) | |||
1275 | spin_unlock_bh(rt_hash_lock_addr(hash)); | 1275 | spin_unlock_bh(rt_hash_lock_addr(hash)); |
1276 | } | 1276 | } |
1277 | 1277 | ||
1278 | static void __build_flow_key(struct flowi4 *fl4, struct sock *sk, | 1278 | static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk, |
1279 | const struct iphdr *iph, | 1279 | const struct iphdr *iph, |
1280 | int oif, u8 tos, | 1280 | int oif, u8 tos, |
1281 | u8 prot, u32 mark, int flow_flags) | 1281 | u8 prot, u32 mark, int flow_flags) |
@@ -1294,7 +1294,8 @@ static void __build_flow_key(struct flowi4 *fl4, struct sock *sk, | |||
1294 | iph->daddr, iph->saddr, 0, 0); | 1294 | iph->daddr, iph->saddr, 0, 0); |
1295 | } | 1295 | } |
1296 | 1296 | ||
1297 | static void build_skb_flow_key(struct flowi4 *fl4, struct sk_buff *skb, struct sock *sk) | 1297 | static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb, |
1298 | const struct sock *sk) | ||
1298 | { | 1299 | { |
1299 | const struct iphdr *iph = ip_hdr(skb); | 1300 | const struct iphdr *iph = ip_hdr(skb); |
1300 | int oif = skb->dev->ifindex; | 1301 | int oif = skb->dev->ifindex; |
@@ -1305,10 +1306,10 @@ static void build_skb_flow_key(struct flowi4 *fl4, struct sk_buff *skb, struct s | |||
1305 | __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0); | 1306 | __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0); |
1306 | } | 1307 | } |
1307 | 1308 | ||
1308 | static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk) | 1309 | static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk) |
1309 | { | 1310 | { |
1310 | const struct inet_sock *inet = inet_sk(sk); | 1311 | const struct inet_sock *inet = inet_sk(sk); |
1311 | struct ip_options_rcu *inet_opt; | 1312 | const struct ip_options_rcu *inet_opt; |
1312 | __be32 daddr = inet->inet_daddr; | 1313 | __be32 daddr = inet->inet_daddr; |
1313 | 1314 | ||
1314 | rcu_read_lock(); | 1315 | rcu_read_lock(); |
@@ -1323,8 +1324,8 @@ static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk) | |||
1323 | rcu_read_unlock(); | 1324 | rcu_read_unlock(); |
1324 | } | 1325 | } |
1325 | 1326 | ||
1326 | static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk, | 1327 | static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk, |
1327 | struct sk_buff *skb) | 1328 | const struct sk_buff *skb) |
1328 | { | 1329 | { |
1329 | if (skb) | 1330 | if (skb) |
1330 | build_skb_flow_key(fl4, skb, sk); | 1331 | build_skb_flow_key(fl4, skb, sk); |