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

Commit a898def2 authored by Paul E. McKenney's avatar Paul E. McKenney Committed by Ingo Molnar
Browse files

net: Add checking to rcu_dereference() primitives



Update rcu_dereference() primitives to use new lockdep-based
checking. The rcu_dereference() in __in6_dev_get() may be
protected either by rcu_read_lock() or RTNL, per Eric Dumazet.
The rcu_dereference() in __sk_free() is protected by the fact
that it is never reached if an update could change it.  Check
for this by using rcu_dereference_check() to verify that the
struct sock's ->sk_wmem_alloc counter is zero.

Acked-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: mathieu.desnoyers@polymtl.ca
Cc: josh@joshtriplett.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: rostedt@goodmis.org
Cc: Valdis.Kletnieks@vt.edu
Cc: dhowells@redhat.com
LKML-Reference: <1266887105-1528-5-git-send-email-paulmck@linux.vnet.ibm.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 3120438a
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -735,6 +735,9 @@ extern void rtnl_lock(void);
extern void rtnl_unlock(void);
extern void rtnl_unlock(void);
extern int rtnl_trylock(void);
extern int rtnl_trylock(void);
extern int rtnl_is_locked(void);
extern int rtnl_is_locked(void);
#ifdef CONFIG_PROVE_LOCKING
extern int lockdep_rtnl_is_held(void);
#endif /* #ifdef CONFIG_PROVE_LOCKING */


extern void rtnetlink_init(void);
extern void rtnetlink_init(void);
extern void __rtnl_unlock(void);
extern void __rtnl_unlock(void);
+3 −1
Original line number Original line Diff line number Diff line
@@ -177,7 +177,9 @@ extern int unregister_inet6addr_notifier(struct notifier_block *nb);
static inline struct inet6_dev *
static inline struct inet6_dev *
__in6_dev_get(struct net_device *dev)
__in6_dev_get(struct net_device *dev)
{
{
	return rcu_dereference(dev->ip6_ptr);
	return rcu_dereference_check(dev->ip6_ptr,
				     rcu_read_lock_held() ||
				     lockdep_rtnl_is_held());
}
}


static inline struct inet6_dev *
static inline struct inet6_dev *
+1 −1
Original line number Original line Diff line number Diff line
@@ -2041,7 +2041,7 @@ int dev_queue_xmit(struct sk_buff *skb)
	rcu_read_lock_bh();
	rcu_read_lock_bh();


	txq = dev_pick_tx(dev, skb);
	txq = dev_pick_tx(dev, skb);
	q = rcu_dereference(txq->qdisc);
	q = rcu_dereference_bh(txq->qdisc);


#ifdef CONFIG_NET_CLS_ACT
#ifdef CONFIG_NET_CLS_ACT
	skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
	skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
+3 −3
Original line number Original line Diff line number Diff line
@@ -86,7 +86,7 @@ int sk_filter(struct sock *sk, struct sk_buff *skb)
		return err;
		return err;


	rcu_read_lock_bh();
	rcu_read_lock_bh();
	filter = rcu_dereference(sk->sk_filter);
	filter = rcu_dereference_bh(sk->sk_filter);
	if (filter) {
	if (filter) {
		unsigned int pkt_len = sk_run_filter(skb, filter->insns,
		unsigned int pkt_len = sk_run_filter(skb, filter->insns,
				filter->len);
				filter->len);
@@ -521,7 +521,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
	}
	}


	rcu_read_lock_bh();
	rcu_read_lock_bh();
	old_fp = rcu_dereference(sk->sk_filter);
	old_fp = rcu_dereference_bh(sk->sk_filter);
	rcu_assign_pointer(sk->sk_filter, fp);
	rcu_assign_pointer(sk->sk_filter, fp);
	rcu_read_unlock_bh();
	rcu_read_unlock_bh();


@@ -536,7 +536,7 @@ int sk_detach_filter(struct sock *sk)
	struct sk_filter *filter;
	struct sk_filter *filter;


	rcu_read_lock_bh();
	rcu_read_lock_bh();
	filter = rcu_dereference(sk->sk_filter);
	filter = rcu_dereference_bh(sk->sk_filter);
	if (filter) {
	if (filter) {
		rcu_assign_pointer(sk->sk_filter, NULL);
		rcu_assign_pointer(sk->sk_filter, NULL);
		sk_filter_delayed_uncharge(sk, filter);
		sk_filter_delayed_uncharge(sk, filter);
+8 −0
Original line number Original line Diff line number Diff line
@@ -89,6 +89,14 @@ int rtnl_is_locked(void)
}
}
EXPORT_SYMBOL(rtnl_is_locked);
EXPORT_SYMBOL(rtnl_is_locked);


#ifdef CONFIG_PROVE_LOCKING
int lockdep_rtnl_is_held(void)
{
	return lockdep_is_held(&rtnl_mutex);
}
EXPORT_SYMBOL(lockdep_rtnl_is_held);
#endif /* #ifdef CONFIG_PROVE_LOCKING */

static struct rtnl_link *rtnl_msg_handlers[NPROTO];
static struct rtnl_link *rtnl_msg_handlers[NPROTO];


static inline int rtm_msgindex(int msgtype)
static inline int rtm_msgindex(int msgtype)
Loading