Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5abf7f7e authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d3a25c98
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -148,11 +148,11 @@ static void free_nh_exceptions(struct fib_nh *nh)
	for (i = 0; i < FNHE_HASH_SIZE; i++) {
		struct fib_nh_exception *fnhe;

		fnhe = rcu_dereference(hash[i].chain);
		fnhe = rcu_dereference_protected(hash[i].chain, 1);
		while (fnhe) {
			struct fib_nh_exception *next;
			
			next = rcu_dereference(fnhe->fnhe_next);
			next = rcu_dereference_protected(fnhe->fnhe_next, 1);
			kfree(fnhe);

			fnhe = next;
+2 −2
Original line number Diff line number Diff line
@@ -806,8 +806,8 @@ EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt);

static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl)
{
	struct inet_sock *inet = inet_sk(sk);
	struct ip_options_rcu *inet_opt;
	const struct inet_sock *inet = inet_sk(sk);
	const struct ip_options_rcu *inet_opt;
	__be32 daddr = inet->inet_daddr;
	struct flowi4 *fl4;
	struct rtable *rt;
+7 −6
Original line number Diff line number Diff line
@@ -1275,7 +1275,7 @@ static void rt_del(unsigned int hash, struct rtable *rt)
	spin_unlock_bh(rt_hash_lock_addr(hash));
}

static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,
static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
			     const struct iphdr *iph,
			     int oif, u8 tos,
			     u8 prot, u32 mark, int flow_flags)
@@ -1294,7 +1294,8 @@ static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,
			   iph->daddr, iph->saddr, 0, 0);
}

static void build_skb_flow_key(struct flowi4 *fl4, struct sk_buff *skb, struct sock *sk)
static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
			       const struct sock *sk)
{
	const struct iphdr *iph = ip_hdr(skb);
	int oif = skb->dev->ifindex;
@@ -1305,10 +1306,10 @@ static void build_skb_flow_key(struct flowi4 *fl4, struct sk_buff *skb, struct s
	__build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
}

static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)
static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
{
	const struct inet_sock *inet = inet_sk(sk);
	struct ip_options_rcu *inet_opt;
	const struct ip_options_rcu *inet_opt;
	__be32 daddr = inet->inet_daddr;

	rcu_read_lock();
@@ -1323,8 +1324,8 @@ static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)
	rcu_read_unlock();
}

static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk,
				 struct sk_buff *skb)
static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk,
				 const struct sk_buff *skb)
{
	if (skb)
		build_skb_flow_key(fl4, skb, sk);