]> Pileus Git - ~andy/linux/blobdiff - net/socket.c
ip6tnl: advertise tunnel param via rtnl
[~andy/linux] / net / socket.c
index 80dc7e84b046358581f454ec87993d4195e6edc3..2ca51c719ef984cdadef749008456cf7bd5e1ae4 100644 (file)
@@ -347,17 +347,11 @@ static struct file_system_type sock_fs_type = {
  *     but we take care of internal coherence yet.
  */
 
-static int sock_alloc_file(struct socket *sock, struct file **f, int flags,
-                          const char *dname)
+struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
 {
        struct qstr name = { .name = "" };
        struct path path;
        struct file *file;
-       int fd;
-
-       fd = get_unused_fd_flags(flags);
-       if (unlikely(fd < 0))
-               return fd;
 
        if (dname) {
                name.name = dname;
@@ -367,10 +361,8 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags,
                name.len = strlen(name.name);
        }
        path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
-       if (unlikely(!path.dentry)) {
-               put_unused_fd(fd);
-               return -ENOMEM;
-       }
+       if (unlikely(!path.dentry))
+               return ERR_PTR(-ENOMEM);
        path.mnt = mntget(sock_mnt);
 
        d_instantiate(path.dentry, SOCK_INODE(sock));
@@ -382,30 +374,33 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags,
                /* drop dentry, keep inode */
                ihold(path.dentry->d_inode);
                path_put(&path);
-               put_unused_fd(fd);
-               return -ENFILE;
+               return ERR_PTR(-ENFILE);
        }
 
        sock->file = file;
        file->f_flags = O_RDWR | (flags & O_NONBLOCK);
        file->f_pos = 0;
        file->private_data = sock;
-
-       *f = file;
-       return fd;
+       return file;
 }
+EXPORT_SYMBOL(sock_alloc_file);
 
-int sock_map_fd(struct socket *sock, int flags)
+static int sock_map_fd(struct socket *sock, int flags)
 {
        struct file *newfile;
-       int fd = sock_alloc_file(sock, &newfile, flags, NULL);
+       int fd = get_unused_fd_flags(flags);
+       if (unlikely(fd < 0))
+               return fd;
 
-       if (likely(fd >= 0))
+       newfile = sock_alloc_file(sock, flags, NULL);
+       if (likely(!IS_ERR(newfile))) {
                fd_install(fd, newfile);
+               return fd;
+       }
 
-       return fd;
+       put_unused_fd(fd);
+       return PTR_ERR(newfile);
 }
-EXPORT_SYMBOL(sock_map_fd);
 
 struct socket *sock_from_file(struct file *file, int *err)
 {
@@ -625,8 +620,6 @@ static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
 {
        struct sock_iocb *si = kiocb_to_siocb(iocb);
 
-       sock_update_classid(sock->sk);
-
        si->sock = sock;
        si->scm = NULL;
        si->msg = msg;
@@ -789,8 +782,6 @@ static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
 {
        struct sock_iocb *si = kiocb_to_siocb(iocb);
 
-       sock_update_classid(sock->sk);
-
        si->sock = sock;
        si->scm = NULL;
        si->msg = msg;
@@ -901,8 +892,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
        if (unlikely(!sock->ops->splice_read))
                return -EINVAL;
 
-       sock_update_classid(sock->sk);
-
        return sock->ops->splice_read(sock, ppos, pipe, len, flags);
 }
 
@@ -1466,17 +1455,32 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
        if (err < 0)
                goto out_release_both;
 
-       fd1 = sock_alloc_file(sock1, &newfile1, flags, NULL);
+       fd1 = get_unused_fd_flags(flags);
        if (unlikely(fd1 < 0)) {
                err = fd1;
                goto out_release_both;
        }
-
-       fd2 = sock_alloc_file(sock2, &newfile2, flags, NULL);
+       fd2 = get_unused_fd_flags(flags);
        if (unlikely(fd2 < 0)) {
                err = fd2;
+               put_unused_fd(fd1);
+               goto out_release_both;
+       }
+
+       newfile1 = sock_alloc_file(sock1, flags, NULL);
+       if (unlikely(IS_ERR(newfile1))) {
+               err = PTR_ERR(newfile1);
+               put_unused_fd(fd1);
+               put_unused_fd(fd2);
+               goto out_release_both;
+       }
+
+       newfile2 = sock_alloc_file(sock2, flags, NULL);
+       if (IS_ERR(newfile2)) {
+               err = PTR_ERR(newfile2);
                fput(newfile1);
                put_unused_fd(fd1);
+               put_unused_fd(fd2);
                sock_release(sock2);
                goto out;
        }
@@ -1608,13 +1612,19 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
         */
        __module_get(newsock->ops->owner);
 
-       newfd = sock_alloc_file(newsock, &newfile, flags,
-                               sock->sk->sk_prot_creator->name);
+       newfd = get_unused_fd_flags(flags);
        if (unlikely(newfd < 0)) {
                err = newfd;
                sock_release(newsock);
                goto out_put;
        }
+       newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
+       if (unlikely(IS_ERR(newfile))) {
+               err = PTR_ERR(newfile);
+               put_unused_fd(newfd);
+               sock_release(newsock);
+               goto out_put;
+       }
 
        err = security_socket_accept(sock, newsock);
        if (err)
@@ -3421,8 +3431,6 @@ EXPORT_SYMBOL(kernel_setsockopt);
 int kernel_sendpage(struct socket *sock, struct page *page, int offset,
                    size_t size, int flags)
 {
-       sock_update_classid(sock->sk);
-
        if (sock->ops->sendpage)
                return sock->ops->sendpage(sock, page, offset, size, flags);