diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-19 18:37:29 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-29 13:24:15 -0400 |
commit | faf02010290e202e275c1bf94ca9dd808bf85607 (patch) | |
tree | 987d42740c98a37577adb31d0a432a19068ccf44 /net/unix | |
parent | a8104a9fcdeb82e22d7acd55fca20746581067d3 (diff) |
clean unix_bind() up a bit
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/unix')
-rw-r--r-- | net/unix/af_unix.c | 88 |
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 | ||
817 | static 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 | ||
818 | static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | 846 | static 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; |
883 | out_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); |
919 | out: | 925 | out: |
920 | return err; | 926 | return err; |
921 | |||
922 | out_mknod_dput: | ||
923 | done_path_create(&path, dentry); | ||
924 | out_mknod_parent: | ||
925 | if (err == -EEXIST) | ||
926 | err = -EADDRINUSE; | ||
927 | unix_release_addr(addr); | ||
928 | goto out_up; | ||
929 | } | 927 | } |
930 | 928 | ||
931 | static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) | 929 | static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) |