aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
commita0e881b7c189fa2bd76c024dbff91e79511c971d (patch)
tree0c801918565b08921d21aceee5b326f64d998f5f /net/unix/af_unix.c
parenteff0d13f3823f35d70228cd151d2a2c89288ff32 (diff)
parentdbc6e0222d79e78925fe20733844a796a4b72cf9 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull second vfs pile from Al Viro: "The stuff in there: fsfreeze deadlock fixes by Jan (essentially, the deadlock reproduced by xfstests 068), symlink and hardlink restriction patches, plus assorted cleanups and fixes. Note that another fsfreeze deadlock (emergency thaw one) is *not* dealt with - the series by Fernando conflicts a lot with Jan's, breaks userland ABI (FIFREEZE semantics gets changed) and trades the deadlock for massive vfsmount leak; this is going to be handled next cycle. There probably will be another pull request, but that stuff won't be in it." Fix up trivial conflicts due to unrelated changes next to each other in drivers/{staging/gdm72xx/usb_boot.c, usb/gadget/storage_common.c} * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (54 commits) delousing target_core_file a bit Documentation: Correct s_umount state for freeze_fs/unfreeze_fs fs: Remove old freezing mechanism ext2: Implement freezing btrfs: Convert to new freezing mechanism nilfs2: Convert to new freezing mechanism ntfs: Convert to new freezing mechanism fuse: Convert to new freezing mechanism gfs2: Convert to new freezing mechanism ocfs2: Convert to new freezing mechanism xfs: Convert to new freezing code ext4: Convert to new freezing mechanism fs: Protect write paths by sb_start_write - sb_end_write fs: Skip atime update on frozen filesystem fs: Add freezing handling to mnt_want_write() / mnt_drop_write() fs: Improve filesystem freezing handling switch the protection of percpu_counter list to spinlock nfsd: Push mnt_want_write() outside of i_mutex btrfs: Push mnt_want_write() outside of i_mutex fat: Push mnt_want_write() outside of i_mutex ...
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)