提交 a73fda3c 编写于 作者: J Jens Axboe 提交者: Shile Zhang

net: add __sys_accept4_file() helper

commit de2ea4b64b75a79ed9cdf9bf30e0e197901084e4 upstream.

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: NDavid S. Miller <davem@davemloft.net>
Signed-off-by: NJens Axboe <axboe@kernel.dk>
Signed-off-by: NJoseph Qi <joseph.qi@linux.alibaba.com>
Reviewed-by: NXiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
上级 44b96780
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
struct pid; struct pid;
struct cred; struct cred;
struct socket; struct socket;
struct file;
#define __sockaddr_check_size(size) \ #define __sockaddr_check_size(size) \
BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage))) BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
...@@ -377,6 +378,9 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, ...@@ -377,6 +378,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, extern int __sys_sendto(int fd, void __user *buff, size_t len,
unsigned int flags, struct sockaddr __user *addr, unsigned int flags, struct sockaddr __user *addr,
int addr_len); 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, extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags); int __user *upeer_addrlen, int flags);
extern int __sys_socket(int family, int type, int protocol); extern int __sys_socket(int family, int type, int protocol);
......
...@@ -1525,24 +1525,13 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog) ...@@ -1525,24 +1525,13 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
return __sys_listen(fd, backlog); return __sys_listen(fd, backlog);
} }
/* int __sys_accept4_file(struct file *file, unsigned file_flags,
* For accept, we attempt to create a new socket, set up the link struct sockaddr __user *upeer_sockaddr,
* 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 __user *upeer_addrlen, int flags)
{ {
struct socket *sock, *newsock; struct socket *sock, *newsock;
struct file *newfile; struct file *newfile;
int err, len, newfd, fput_needed; int err, len, newfd;
struct sockaddr_storage address; struct sockaddr_storage address;
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
...@@ -1551,14 +1540,14 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, ...@@ -1551,14 +1540,14 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sock_from_file(file, &err);
if (!sock) if (!sock)
goto out; goto out;
err = -ENFILE; err = -ENFILE;
newsock = sock_alloc(); newsock = sock_alloc();
if (!newsock) if (!newsock)
goto out_put; goto out;
newsock->type = sock->type; newsock->type = sock->type;
newsock->ops = sock->ops; newsock->ops = sock->ops;
...@@ -1573,20 +1562,21 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, ...@@ -1573,20 +1562,21 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
if (unlikely(newfd < 0)) { if (unlikely(newfd < 0)) {
err = newfd; err = newfd;
sock_release(newsock); sock_release(newsock);
goto out_put; goto out;
} }
newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
if (IS_ERR(newfile)) { if (IS_ERR(newfile)) {
err = PTR_ERR(newfile); err = PTR_ERR(newfile);
put_unused_fd(newfd); put_unused_fd(newfd);
goto out_put; goto out;
} }
err = security_socket_accept(sock, newsock); err = security_socket_accept(sock, newsock);
if (err) if (err)
goto out_fd; 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) if (err < 0)
goto out_fd; goto out_fd;
...@@ -1607,15 +1597,42 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, ...@@ -1607,15 +1597,42 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
fd_install(newfd, newfile); fd_install(newfd, newfile);
err = newfd; err = newfd;
out_put:
fput_light(sock->file, fput_needed);
out: out:
return err; return err;
out_fd: out_fd:
fput(newfile); fput(newfile);
put_unused_fd(newfd); 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, SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册