diff options
Diffstat (limited to 'net/unix/diag.c')
| -rw-r--r-- | net/unix/diag.c | 47 | 
1 files changed, 13 insertions, 34 deletions
| diff --git a/net/unix/diag.c b/net/unix/diag.c index 937edf4afed4..9138af8b465e 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -47,9 +47,7 @@ static int sk_diag_dump_peer(struct sock *sk, struct sk_buff *nlskb)  	peer = unix_peer_get(sk);  	if (peer) { -		unix_state_lock(peer);  		ino = sock_i_ino(peer); -		unix_state_unlock(peer);  		sock_put(peer);  		return nla_put_u32(nlskb, UNIX_DIAG_PEER, ino); @@ -75,20 +73,9 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)  		buf = nla_data(attr);  		i = 0; -		skb_queue_walk(&sk->sk_receive_queue, skb) { -			struct sock *req, *peer; - -			req = skb->sk; -			/* -			 * The state lock is outer for the same sk's -			 * queue lock. With the other's queue locked it's -			 * OK to lock the state. -			 */ -			unix_state_lock_nested(req, U_LOCK_DIAG); -			peer = unix_sk(req)->peer; -			buf[i++] = (peer ? sock_i_ino(peer) : 0); -			unix_state_unlock(req); -		} +		skb_queue_walk(&sk->sk_receive_queue, skb) +			buf[i++] = sock_i_ino(unix_peer(skb->sk)); +  		spin_unlock(&sk->sk_receive_queue.lock);  	} @@ -180,22 +167,6 @@ out_nlmsg_trim:  	return -EMSGSIZE;  } -static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, -			struct user_namespace *user_ns, -			u32 portid, u32 seq, u32 flags) -{ -	int sk_ino; - -	unix_state_lock(sk); -	sk_ino = sock_i_ino(sk); -	unix_state_unlock(sk); - -	if (!sk_ino) -		return 0; - -	return sk_diag_fill(sk, skb, req, user_ns, portid, seq, flags, sk_ino); -} -  static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)  {  	struct net *net = sock_net(skb->sk); @@ -213,14 +184,22 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)  		num = 0;  		spin_lock(&net->unx.table.locks[slot]);  		sk_for_each(sk, &net->unx.table.buckets[slot]) { +			int sk_ino; +  			if (num < s_num)  				goto next; +  			if (!(req->udiag_states & (1 << READ_ONCE(sk->sk_state))))  				goto next; -			if (sk_diag_dump(sk, skb, req, sk_user_ns(skb->sk), + +			sk_ino = sock_i_ino(sk); +			if (!sk_ino) +				goto next; + +			if (sk_diag_fill(sk, skb, req, sk_user_ns(skb->sk),  					 NETLINK_CB(cb->skb).portid,  					 cb->nlh->nlmsg_seq, -					 NLM_F_MULTI) < 0) { +					 NLM_F_MULTI, sk_ino) < 0) {  				spin_unlock(&net->unx.table.locks[slot]);  				goto done;  			} |