]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
net: add __sys_accept4_file() helper
authorJens Axboe <axboe@kernel.dk>
Thu, 17 Oct 2019 20:41:29 +0000 (14:41 -0600)
committerJens Axboe <axboe@kernel.dk>
Tue, 29 Oct 2019 18:43:06 +0000 (12:43 -0600)
This is identical to __sys_accept4(), except it takes a struct file
instead of an fd, and it also allows passing in extra file->f_flags
flags. The latter is done to support masking in O_NONBLOCK without
manipulating the original file flags.

No functional changes in this patch.

Cc: netdev@vger.kernel.org
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/socket.h
net/socket.c

index fc0bed59fc84ef8e6631d3c275853d52a46f84aa..dd061f741bc1880f040acaffa68438466e2f9963 100644 (file)
@@ -392,6 +392,9 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
 extern int __sys_sendto(int fd, void __user *buff, size_t len,
                        unsigned int flags, struct sockaddr __user *addr,
                        int addr_len);
+extern int __sys_accept4_file(struct file *file, unsigned file_flags,
+                       struct sockaddr __user *upeer_sockaddr,
+                        int __user *upeer_addrlen, int flags);
 extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
                         int __user *upeer_addrlen, int flags);
 extern int __sys_socket(int family, int type, int protocol);
index 6a9ab7a8b1d2c5059752a9147c2f0fd1aea4f44d..40ab39f6c5d8bfa9fc0aa2fd793b85371e719d52 100644 (file)
@@ -1690,24 +1690,13 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
        return __sys_listen(fd, backlog);
 }
 
-/*
- *     For accept, we attempt to create a new socket, set up the link
- *     with the client, wake up the client, then return the new
- *     connected fd. We collect the address of the connector in kernel
- *     space and move it to user at the very end. This is unclean because
- *     we open the socket then return an error.
- *
- *     1003.1g adds the ability to recvmsg() to query connection pending
- *     status to recvmsg. We need to add that support in a way thats
- *     clean when we restructure accept also.
- */
-
-int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
-                 int __user *upeer_addrlen, int flags)
+int __sys_accept4_file(struct file *file, unsigned file_flags,
+                      struct sockaddr __user *upeer_sockaddr,
+                      int __user *upeer_addrlen, int flags)
 {
        struct socket *sock, *newsock;
        struct file *newfile;
-       int err, len, newfd, fput_needed;
+       int err, len, newfd;
        struct sockaddr_storage address;
 
        if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
@@ -1716,14 +1705,14 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
        if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
                flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
 
-       sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       sock = sock_from_file(file, &err);
        if (!sock)
                goto out;
 
        err = -ENFILE;
        newsock = sock_alloc();
        if (!newsock)
-               goto out_put;
+               goto out;
 
        newsock->type = sock->type;
        newsock->ops = sock->ops;
@@ -1738,20 +1727,21 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
        if (unlikely(newfd < 0)) {
                err = newfd;
                sock_release(newsock);
-               goto out_put;
+               goto out;
        }
        newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
        if (IS_ERR(newfile)) {
                err = PTR_ERR(newfile);
                put_unused_fd(newfd);
-               goto out_put;
+               goto out;
        }
 
        err = security_socket_accept(sock, newsock);
        if (err)
                goto out_fd;
 
-       err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
+       err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags,
+                                       false);
        if (err < 0)
                goto out_fd;
 
@@ -1772,15 +1762,42 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
 
        fd_install(newfd, newfile);
        err = newfd;
-
-out_put:
-       fput_light(sock->file, fput_needed);
 out:
        return err;
 out_fd:
        fput(newfile);
        put_unused_fd(newfd);
-       goto out_put;
+       goto out;
+
+}
+
+/*
+ *     For accept, we attempt to create a new socket, set up the link
+ *     with the client, wake up the client, then return the new
+ *     connected fd. We collect the address of the connector in kernel
+ *     space and move it to user at the very end. This is unclean because
+ *     we open the socket then return an error.
+ *
+ *     1003.1g adds the ability to recvmsg() to query connection pending
+ *     status to recvmsg. We need to add that support in a way thats
+ *     clean when we restructure accept also.
+ */
+
+int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
+                 int __user *upeer_addrlen, int flags)
+{
+       int ret = -EBADF;
+       struct fd f;
+
+       f = fdget(fd);
+       if (f.file) {
+               ret = __sys_accept4_file(f.file, 0, upeer_sockaddr,
+                                               upeer_addrlen, flags);
+               if (f.flags)
+                       fput(f.file);
+       }
+
+       return ret;
 }
 
 SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,