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