forked from mirrors/linux
		
	unix_diag: Dumping exact socket core
The socket inode is used as a key for lookup. This is effectively the only really unique ID of a unix socket, but using this for search currently has one problem -- it is O(number of sockets) :( Does it worth fixing this lookup or inventing some other ID for unix sockets? Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									45a96b9be6
								
							
						
					
					
						commit
						5d3cae8bc3
					
				
					 1 changed files with 66 additions and 1 deletions
				
			
		|  | @ -89,11 +89,76 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 	return skb->len; | ||||
| } | ||||
| 
 | ||||
| static struct sock *unix_lookup_by_ino(int ino) | ||||
| { | ||||
| 	int i; | ||||
| 	struct sock *sk; | ||||
| 
 | ||||
| 	spin_lock(&unix_table_lock); | ||||
| 	for (i = 0; i <= UNIX_HASH_SIZE; i++) { | ||||
| 		struct hlist_node *node; | ||||
| 
 | ||||
| 		sk_for_each(sk, node, &unix_socket_table[i]) | ||||
| 			if (ino == sock_i_ino(sk)) { | ||||
| 				sock_hold(sk); | ||||
| 				spin_unlock(&unix_table_lock); | ||||
| 
 | ||||
| 				return sk; | ||||
| 			} | ||||
| 	} | ||||
| 
 | ||||
| 	spin_unlock(&unix_table_lock); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static int unix_diag_get_exact(struct sk_buff *in_skb, | ||||
| 			       const struct nlmsghdr *nlh, | ||||
| 			       struct unix_diag_req *req) | ||||
| { | ||||
| 	return -EAFNOSUPPORT; | ||||
| 	int err = -EINVAL; | ||||
| 	struct sock *sk; | ||||
| 	struct sk_buff *rep; | ||||
| 	unsigned int extra_len; | ||||
| 
 | ||||
| 	if (req->udiag_ino == 0) | ||||
| 		goto out_nosk; | ||||
| 
 | ||||
| 	sk = unix_lookup_by_ino(req->udiag_ino); | ||||
| 	err = -ENOENT; | ||||
| 	if (sk == NULL) | ||||
| 		goto out_nosk; | ||||
| 
 | ||||
| 	err = sock_diag_check_cookie(sk, req->udiag_cookie); | ||||
| 	if (err) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	extra_len = 256; | ||||
| again: | ||||
| 	err = -ENOMEM; | ||||
| 	rep = alloc_skb(NLMSG_SPACE((sizeof(struct unix_diag_msg) + extra_len)), | ||||
| 			GFP_KERNEL); | ||||
| 	if (!rep) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	err = sk_diag_fill(sk, rep, req, NETLINK_CB(in_skb).pid, | ||||
| 			   nlh->nlmsg_seq, 0, req->udiag_ino); | ||||
| 	if (err < 0) { | ||||
| 		kfree_skb(rep); | ||||
| 		extra_len += 256; | ||||
| 		if (extra_len >= PAGE_SIZE) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		goto again; | ||||
| 	} | ||||
| 	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, | ||||
| 			      MSG_DONTWAIT); | ||||
| 	if (err > 0) | ||||
| 		err = 0; | ||||
| out: | ||||
| 	if (sk) | ||||
| 		sock_put(sk); | ||||
| out_nosk: | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Pavel Emelyanov
						Pavel Emelyanov