af_unix: Factorise unix_find_other() based on address types.

As done in the commit fa42d910a3 ("unix_bind(): take BSD and abstract
address cases into new helpers"), this patch moves BSD and abstract address
cases from unix_find_other() into unix_find_bsd() and unix_find_abstract().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Kuniyuki Iwashima 2021-11-24 11:14:21 +09:00 committed by Jakub Kicinski
parent f7ed31f461
commit fa39ef0e47
1 changed files with 81 additions and 55 deletions

View File

@ -950,6 +950,87 @@ static int unix_release(struct socket *sock)
return 0;
}
static struct sock *unix_find_bsd(struct net *net, struct sockaddr_un *sunaddr,
int type, int *error)
{
struct inode *inode;
struct path path;
struct sock *sk;
int err;
err = kern_path(sunaddr->sun_path, LOOKUP_FOLLOW, &path);
if (err)
goto fail;
err = path_permission(&path, MAY_WRITE);
if (err)
goto path_put;
err = -ECONNREFUSED;
inode = d_backing_inode(path.dentry);
if (!S_ISSOCK(inode->i_mode))
goto path_put;
sk = unix_find_socket_byinode(inode);
if (!sk)
goto path_put;
err = -EPROTOTYPE;
if (sk->sk_type == type)
touch_atime(&path);
else
goto sock_put;
path_put(&path);
return sk;
sock_put:
sock_put(sk);
path_put:
path_put(&path);
fail:
*error = err;
return NULL;
}
static struct sock *unix_find_abstract(struct net *net,
struct sockaddr_un *sunaddr,
int addr_len, int type,
unsigned int hash, int *error)
{
struct dentry *dentry;
struct sock *sk;
sk = unix_find_socket_byname(net, sunaddr, addr_len, type ^ hash);
if (!sk) {
*error = -ECONNREFUSED;
return NULL;
}
dentry = unix_sk(sk)->path.dentry;
if (dentry)
touch_atime(&unix_sk(sk)->path);
return sk;
}
static struct sock *unix_find_other(struct net *net,
struct sockaddr_un *sunaddr,
int addr_len, int type,
unsigned int hash, int *error)
{
struct sock *sk;
if (sunaddr->sun_path[0])
sk = unix_find_bsd(net, sunaddr, type, error);
else
sk = unix_find_abstract(net, sunaddr, addr_len, type, hash,
error);
return sk;
}
static int unix_autobind(struct sock *sk)
{
struct unix_sock *u = unix_sk(sk);
@ -1008,61 +1089,6 @@ out: mutex_unlock(&u->bindlock);
return err;
}
static struct sock *unix_find_other(struct net *net,
struct sockaddr_un *sunname, int len,
int type, unsigned int hash, int *error)
{
struct sock *u;
struct path path;
int err = 0;
if (sunname->sun_path[0]) {
struct inode *inode;
err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
if (err)
goto fail;
inode = d_backing_inode(path.dentry);
err = path_permission(&path, MAY_WRITE);
if (err)
goto put_fail;
err = -ECONNREFUSED;
if (!S_ISSOCK(inode->i_mode))
goto put_fail;
u = unix_find_socket_byinode(inode);
if (!u)
goto put_fail;
if (u->sk_type == type)
touch_atime(&path);
path_put(&path);
err = -EPROTOTYPE;
if (u->sk_type != type) {
sock_put(u);
goto fail;
}
} else {
err = -ECONNREFUSED;
u = unix_find_socket_byname(net, sunname, len, type ^ hash);
if (u) {
struct dentry *dentry;
dentry = unix_sk(u)->path.dentry;
if (dentry)
touch_atime(&unix_sk(u)->path);
} else
goto fail;
}
return u;
put_fail:
path_put(&path);
fail:
*error = err;
return NULL;
}
static int unix_bind_bsd(struct sock *sk, struct unix_address *addr)
{
struct unix_sock *u = unix_sk(sk);