aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/diag.c
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@amazon.com>2022-06-21 10:19:11 -0700
committerDavid S. Miller <davem@davemloft.net>2022-06-22 12:59:43 +0100
commit79b05beaa5c340e1649dc7462e056ae33b916131 (patch)
treeb6a8cd6babb1b98c4fdee205471d5bb01c63cd0b /net/unix/diag.c
parentaf_unix: Define a per-netns hash table. (diff)
downloadlinux-dev-79b05beaa5c340e1649dc7462e056ae33b916131.tar.xz
linux-dev-79b05beaa5c340e1649dc7462e056ae33b916131.zip
af_unix: Acquire/Release per-netns hash table's locks.
This commit adds extra spin_lock/spin_unlock() for a per-netns hash table inside the existing ones for unix_table_locks. As of this commit, sockets are still linked in the global hash table. After putting sockets in a per-netns hash table and removing the old one in the next patch, we remove the global locks in the last patch. Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/unix/diag.c')
-rw-r--r--net/unix/diag.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/net/unix/diag.c b/net/unix/diag.c
index c5d1cca72aa5..7fc377435114 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -195,9 +195,9 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct unix_diag_req *req;
- int num, s_num, slot, s_slot;
struct net *net = sock_net(skb->sk);
+ int num, s_num, slot, s_slot;
+ struct unix_diag_req *req;
req = nlmsg_data(cb->nlh);
@@ -209,6 +209,7 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
num = 0;
spin_lock(&unix_table_locks[slot]);
+ spin_lock(&net->unx.table.locks[slot]);
sk_for_each(sk, &unix_socket_table[slot]) {
if (!net_eq(sock_net(sk), net))
continue;
@@ -220,12 +221,14 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
NLM_F_MULTI) < 0) {
+ spin_unlock(&net->unx.table.locks[slot]);
spin_unlock(&unix_table_locks[slot]);
goto done;
}
next:
num++;
}
+ spin_unlock(&net->unx.table.locks[slot]);
spin_unlock(&unix_table_locks[slot]);
}
done:
@@ -235,19 +238,22 @@ done:
return skb->len;
}
-static struct sock *unix_lookup_by_ino(unsigned int ino)
+static struct sock *unix_lookup_by_ino(struct net *net, unsigned int ino)
{
struct sock *sk;
int i;
for (i = 0; i < UNIX_HASH_SIZE; i++) {
spin_lock(&unix_table_locks[i]);
+ spin_lock(&net->unx.table.locks[i]);
sk_for_each(sk, &unix_socket_table[i])
if (ino == sock_i_ino(sk)) {
sock_hold(sk);
+ spin_unlock(&net->unx.table.locks[i]);
spin_unlock(&unix_table_locks[i]);
return sk;
}
+ spin_unlock(&net->unx.table.locks[i]);
spin_unlock(&unix_table_locks[i]);
}
return NULL;
@@ -257,16 +263,17 @@ static int unix_diag_get_exact(struct sk_buff *in_skb,
const struct nlmsghdr *nlh,
struct unix_diag_req *req)
{
- int err = -EINVAL;
- struct sock *sk;
- struct sk_buff *rep;
- unsigned int extra_len;
struct net *net = sock_net(in_skb->sk);
+ unsigned int extra_len;
+ struct sk_buff *rep;
+ struct sock *sk;
+ int err;
+ err = -EINVAL;
if (req->udiag_ino == 0)
goto out_nosk;
- sk = unix_lookup_by_ino(req->udiag_ino);
+ sk = unix_lookup_by_ino(net, req->udiag_ino);
err = -ENOENT;
if (sk == NULL)
goto out_nosk;