Commit aee51517 authored by Al Viro's avatar Al Viro Committed by David S. Miller

unix_bind(): separate BSD and abstract cases

We do get some duplication that way, but it's minor compared to
parts that are different.  What we get is an ability to change
locking in BSD case without making failure exits very hard to
follow.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c34d4582
...@@ -1024,7 +1024,6 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -1024,7 +1024,6 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
int err; int err;
unsigned int hash; unsigned int hash;
struct unix_address *addr; struct unix_address *addr;
struct path path = { };
err = -EINVAL; err = -EINVAL;
if (addr_len < offsetofend(struct sockaddr_un, sun_family) || if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
...@@ -1051,6 +1050,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -1051,6 +1050,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
refcount_set(&addr->refcnt, 1); refcount_set(&addr->refcnt, 1);
if (sun_path[0]) { if (sun_path[0]) {
struct path path = { };
umode_t mode = S_IFSOCK | umode_t mode = S_IFSOCK |
(SOCK_INODE(sock)->i_mode & ~current_umask()); (SOCK_INODE(sock)->i_mode & ~current_umask());
err = unix_mknod(sun_path, mode, &path); err = unix_mknod(sun_path, mode, &path);
...@@ -1059,41 +1059,54 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -1059,41 +1059,54 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
err = -EADDRINUSE; err = -EADDRINUSE;
goto out_addr; goto out_addr;
} }
}
err = mutex_lock_interruptible(&u->bindlock); err = mutex_lock_interruptible(&u->bindlock);
if (err) if (err) {
goto out_put; path_put(&path);
goto out_addr;
}
err = -EINVAL; err = -EINVAL;
if (u->addr) if (u->addr) {
goto out_up; mutex_unlock(&u->bindlock);
path_put(&path);
goto out_addr;
}
if (sun_path[0]) {
addr->hash = UNIX_HASH_SIZE; addr->hash = UNIX_HASH_SIZE;
hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1); hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
spin_lock(&unix_table_lock); spin_lock(&unix_table_lock);
u->path = path; u->path = path;
__unix_set_addr(sk, addr, hash);
spin_unlock(&unix_table_lock);
mutex_unlock(&u->bindlock);
addr = NULL;
err = 0;
} else { } else {
err = mutex_lock_interruptible(&u->bindlock);
if (err)
goto out_addr;
err = -EINVAL;
if (u->addr) {
mutex_unlock(&u->bindlock);
goto out_addr;
}
spin_lock(&unix_table_lock); spin_lock(&unix_table_lock);
err = -EADDRINUSE; err = -EADDRINUSE;
if (__unix_find_socket_byname(net, sunaddr, addr_len, if (__unix_find_socket_byname(net, sunaddr, addr_len,
sk->sk_type, hash)) { sk->sk_type, hash)) {
spin_unlock(&unix_table_lock); spin_unlock(&unix_table_lock);
goto out_up; mutex_unlock(&u->bindlock);
} goto out_addr;
hash = addr->hash;
} }
__unix_set_addr(sk, addr, addr->hash);
__unix_set_addr(sk, addr, hash);
spin_unlock(&unix_table_lock); spin_unlock(&unix_table_lock);
mutex_unlock(&u->bindlock);
addr = NULL; addr = NULL;
err = 0; err = 0;
out_up: }
mutex_unlock(&u->bindlock);
out_put:
if (err)
path_put(&path);
out_addr: out_addr:
if (addr) if (addr)
unix_release_addr(addr); unix_release_addr(addr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment