mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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;
 | 
						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,
 | 
					static int unix_diag_get_exact(struct sk_buff *in_skb,
 | 
				
			||||||
			       const struct nlmsghdr *nlh,
 | 
								       const struct nlmsghdr *nlh,
 | 
				
			||||||
			       struct unix_diag_req *req)
 | 
								       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)
 | 
					static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue