Loading net/unix/af_unix.c +74 −73 Original line number Diff line number Diff line Loading @@ -1014,63 +1014,29 @@ static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) return err; } static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) static int unix_bind_bsd(struct sock *sk, struct unix_address *addr) { struct sock *sk = sock->sk; struct net *net = sock_net(sk); struct unix_sock *u = unix_sk(sk); struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; char *sun_path = sunaddr->sun_path; int err; unsigned int hash; struct unix_address *addr; err = -EINVAL; if (addr_len < offsetofend(struct sockaddr_un, sun_family) || sunaddr->sun_family != AF_UNIX) goto out; if (addr_len == sizeof(short)) { err = unix_autobind(sock); goto out; } err = unix_mkname(sunaddr, addr_len, &hash); if (err < 0) goto out; addr_len = err; err = -ENOMEM; addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); if (!addr) goto out; memcpy(addr->name, sunaddr, addr_len); addr->len = addr_len; addr->hash = hash ^ sk->sk_type; refcount_set(&addr->refcnt, 1); if (sun_path[0]) { struct path path = { }; umode_t mode = S_IFSOCK | (SOCK_INODE(sock)->i_mode & ~current_umask()); err = unix_mknod(sun_path, mode, &path); if (err) { if (err == -EEXIST) err = -EADDRINUSE; goto out_addr; } (SOCK_INODE(sk->sk_socket)->i_mode & ~current_umask()); unsigned int hash; int err; err = unix_mknod(addr->name->sun_path, mode, &path); if (err) return err; err = mutex_lock_interruptible(&u->bindlock); if (err) { path_put(&path); goto out_addr; return err; } err = -EINVAL; if (u->addr) { mutex_unlock(&u->bindlock); path_put(&path); goto out_addr; return -EINVAL; } addr->hash = UNIX_HASH_SIZE; Loading @@ -1080,38 +1046,73 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) __unix_set_addr(sk, addr, hash); spin_unlock(&unix_table_lock); mutex_unlock(&u->bindlock); addr = NULL; err = 0; } else { return 0; } static int unix_bind_abstract(struct sock *sk, unsigned hash, struct unix_address *addr) { struct unix_sock *u = unix_sk(sk); int err; err = mutex_lock_interruptible(&u->bindlock); if (err) goto out_addr; return err; err = -EINVAL; if (u->addr) { mutex_unlock(&u->bindlock); goto out_addr; return -EINVAL; } spin_lock(&unix_table_lock); err = -EADDRINUSE; if (__unix_find_socket_byname(net, sunaddr, addr_len, if (__unix_find_socket_byname(sock_net(sk), addr->name, addr->len, sk->sk_type, hash)) { spin_unlock(&unix_table_lock); mutex_unlock(&u->bindlock); goto out_addr; return -EADDRINUSE; } __unix_set_addr(sk, addr, addr->hash); spin_unlock(&unix_table_lock); mutex_unlock(&u->bindlock); addr = NULL; err = 0; return 0; } out_addr: if (addr) unix_release_addr(addr); out: static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; char *sun_path = sunaddr->sun_path; int err; unsigned int hash; struct unix_address *addr; if (addr_len < offsetofend(struct sockaddr_un, sun_family) || sunaddr->sun_family != AF_UNIX) return -EINVAL; if (addr_len == sizeof(short)) return unix_autobind(sock); err = unix_mkname(sunaddr, addr_len, &hash); if (err < 0) return err; addr_len = err; addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); if (!addr) return -ENOMEM; memcpy(addr->name, sunaddr, addr_len); addr->len = addr_len; addr->hash = hash ^ sk->sk_type; refcount_set(&addr->refcnt, 1); if (sun_path[0]) err = unix_bind_bsd(sk, addr); else err = unix_bind_abstract(sk, hash, addr); if (err) unix_release_addr(addr); return err == -EEXIST ? -EADDRINUSE : err; } static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) Loading Loading
net/unix/af_unix.c +74 −73 Original line number Diff line number Diff line Loading @@ -1014,63 +1014,29 @@ static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) return err; } static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) static int unix_bind_bsd(struct sock *sk, struct unix_address *addr) { struct sock *sk = sock->sk; struct net *net = sock_net(sk); struct unix_sock *u = unix_sk(sk); struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; char *sun_path = sunaddr->sun_path; int err; unsigned int hash; struct unix_address *addr; err = -EINVAL; if (addr_len < offsetofend(struct sockaddr_un, sun_family) || sunaddr->sun_family != AF_UNIX) goto out; if (addr_len == sizeof(short)) { err = unix_autobind(sock); goto out; } err = unix_mkname(sunaddr, addr_len, &hash); if (err < 0) goto out; addr_len = err; err = -ENOMEM; addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); if (!addr) goto out; memcpy(addr->name, sunaddr, addr_len); addr->len = addr_len; addr->hash = hash ^ sk->sk_type; refcount_set(&addr->refcnt, 1); if (sun_path[0]) { struct path path = { }; umode_t mode = S_IFSOCK | (SOCK_INODE(sock)->i_mode & ~current_umask()); err = unix_mknod(sun_path, mode, &path); if (err) { if (err == -EEXIST) err = -EADDRINUSE; goto out_addr; } (SOCK_INODE(sk->sk_socket)->i_mode & ~current_umask()); unsigned int hash; int err; err = unix_mknod(addr->name->sun_path, mode, &path); if (err) return err; err = mutex_lock_interruptible(&u->bindlock); if (err) { path_put(&path); goto out_addr; return err; } err = -EINVAL; if (u->addr) { mutex_unlock(&u->bindlock); path_put(&path); goto out_addr; return -EINVAL; } addr->hash = UNIX_HASH_SIZE; Loading @@ -1080,38 +1046,73 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) __unix_set_addr(sk, addr, hash); spin_unlock(&unix_table_lock); mutex_unlock(&u->bindlock); addr = NULL; err = 0; } else { return 0; } static int unix_bind_abstract(struct sock *sk, unsigned hash, struct unix_address *addr) { struct unix_sock *u = unix_sk(sk); int err; err = mutex_lock_interruptible(&u->bindlock); if (err) goto out_addr; return err; err = -EINVAL; if (u->addr) { mutex_unlock(&u->bindlock); goto out_addr; return -EINVAL; } spin_lock(&unix_table_lock); err = -EADDRINUSE; if (__unix_find_socket_byname(net, sunaddr, addr_len, if (__unix_find_socket_byname(sock_net(sk), addr->name, addr->len, sk->sk_type, hash)) { spin_unlock(&unix_table_lock); mutex_unlock(&u->bindlock); goto out_addr; return -EADDRINUSE; } __unix_set_addr(sk, addr, addr->hash); spin_unlock(&unix_table_lock); mutex_unlock(&u->bindlock); addr = NULL; err = 0; return 0; } out_addr: if (addr) unix_release_addr(addr); out: static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; char *sun_path = sunaddr->sun_path; int err; unsigned int hash; struct unix_address *addr; if (addr_len < offsetofend(struct sockaddr_un, sun_family) || sunaddr->sun_family != AF_UNIX) return -EINVAL; if (addr_len == sizeof(short)) return unix_autobind(sock); err = unix_mkname(sunaddr, addr_len, &hash); if (err < 0) return err; addr_len = err; addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); if (!addr) return -ENOMEM; memcpy(addr->name, sunaddr, addr_len); addr->len = addr_len; addr->hash = hash ^ sk->sk_type; refcount_set(&addr->refcnt, 1); if (sun_path[0]) err = unix_bind_bsd(sk, addr); else err = unix_bind_abstract(sk, hash, addr); if (err) unix_release_addr(addr); return err == -EEXIST ? -EADDRINUSE : err; } static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) Loading