aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix')
-rw-r--r--net/unix/af_unix.c88
1 files changed, 43 insertions, 45 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 88ab72820b9f..b7667f81c49c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -814,6 +814,34 @@ fail:
814 return NULL; 814 return NULL;
815} 815}
816 816
817static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
818{
819 struct dentry *dentry;
820 struct path path;
821 int err = 0;
822 /*
823 * Get the parent directory, calculate the hash for last
824 * component.
825 */
826 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
827 err = PTR_ERR(dentry);
828 if (IS_ERR(dentry))
829 return err;
830
831 /*
832 * All right, let's create it.
833 */
834 err = security_path_mknod(&path, dentry, mode, 0);
835 if (!err) {
836 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
837 if (!err) {
838 res->mnt = mntget(path.mnt);
839 res->dentry = dget(dentry);
840 }
841 }
842 done_path_create(&path, dentry);
843 return err;
844}
817 845
818static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 846static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
819{ 847{
@@ -822,8 +850,6 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
822 struct unix_sock *u = unix_sk(sk); 850 struct unix_sock *u = unix_sk(sk);
823 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; 851 struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
824 char *sun_path = sunaddr->sun_path; 852 char *sun_path = sunaddr->sun_path;
825 struct dentry *dentry = NULL;
826 struct path path;
827 int err; 853 int err;
828 unsigned int hash; 854 unsigned int hash;
829 struct unix_address *addr; 855 struct unix_address *addr;
@@ -860,40 +886,23 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
860 atomic_set(&addr->refcnt, 1); 886 atomic_set(&addr->refcnt, 1);
861 887
862 if (sun_path[0]) { 888 if (sun_path[0]) {
863 umode_t mode; 889 struct path path;
864 err = 0; 890 umode_t mode = S_IFSOCK |
865 /*
866 * Get the parent directory, calculate the hash for last
867 * component.
868 */
869 dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
870 err = PTR_ERR(dentry);
871 if (IS_ERR(dentry))
872 goto out_mknod_parent;
873
874 /*
875 * All right, let's create it.
876 */
877 mode = S_IFSOCK |
878 (SOCK_INODE(sock)->i_mode & ~current_umask()); 891 (SOCK_INODE(sock)->i_mode & ~current_umask());
879 err = security_path_mknod(&path, dentry, mode, 0); 892 err = unix_mknod(sun_path, mode, &path);
880 if (err) 893 if (err) {
881 goto out_mknod_drop_write; 894 if (err == -EEXIST)
882 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); 895 err = -EADDRINUSE;
883out_mknod_drop_write: 896 unix_release_addr(addr);
884 if (err) 897 goto out_up;
885 goto out_mknod_dput; 898 }
886 mntget(path.mnt);
887 dget(dentry);
888 done_path_create(&path, dentry);
889 path.dentry = dentry;
890
891 addr->hash = UNIX_HASH_SIZE; 899 addr->hash = UNIX_HASH_SIZE;
892 } 900 hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1);
893 901 spin_lock(&unix_table_lock);
894 spin_lock(&unix_table_lock); 902 u->path = path;
895 903 list = &unix_socket_table[hash];
896 if (!sun_path[0]) { 904 } else {
905 spin_lock(&unix_table_lock);
897 err = -EADDRINUSE; 906 err = -EADDRINUSE;
898 if (__unix_find_socket_byname(net, sunaddr, addr_len, 907 if (__unix_find_socket_byname(net, sunaddr, addr_len,
899 sk->sk_type, hash)) { 908 sk->sk_type, hash)) {
@@ -902,9 +911,6 @@ out_mknod_drop_write:
902 } 911 }
903 912
904 list = &unix_socket_table[addr->hash]; 913 list = &unix_socket_table[addr->hash];
905 } else {
906 list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
907 u->path = path;
908 } 914 }
909 915
910 err = 0; 916 err = 0;
@@ -918,14 +924,6 @@ out_up:
918 mutex_unlock(&u->readlock); 924 mutex_unlock(&u->readlock);
919out: 925out:
920 return err; 926 return err;
921
922out_mknod_dput:
923 done_path_create(&path, dentry);
924out_mknod_parent:
925 if (err == -EEXIST)
926 err = -EADDRINUSE;
927 unix_release_addr(addr);
928 goto out_up;
929} 927}
930 928
931static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) 929static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)