History

net: add __sys_accept4_file() helper

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.

Jens Axboe committed 7 years ago

Commit de2ea4b1 parent fcb323c2 files · +44 −24Browse files

Unified · Split

2 files
  1. include/linux/socket.h +3 −0
  2. net/socket.c +41 −24
include/linux/socket.h+3−0
@@ -392,6 +392,9 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, · 391 unmodified lines
392392 extern int __sys_sendto(int fd, void __user *buff, size_t len,
393393 unsigned int flags, struct sockaddr __user *addr,
394394 int addr_len);
395+extern int __sys_accept4_file(struct file *file, unsigned file_flags,
396+ struct sockaddr __user *upeer_sockaddr,
397+ int __user *upeer_addrlen, int flags);
395398 extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
396399 int __user *upeer_addrlen, int flags);
397400 extern int __sys_socket(int family, int type, int protocol);
net/socket.c+41−24
@@ -1690,24 +1690,13 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog) · 1689 unmodified lines
16901690 return __sys_listen(fd, backlog);
16911691 }
16921692
1693−/*
1694− * For accept, we attempt to create a new socket, set up the link
1695− * with the client, wake up the client, then return the new
1696− * connected fd. We collect the address of the connector in kernel
1697− * space and move it to user at the very end. This is unclean because
1698− * we open the socket then return an error.
1699− *
1700− * 1003.1g adds the ability to recvmsg() to query connection pending
1701− * status to recvmsg. We need to add that support in a way thats
1702− * clean when we restructure accept also.
1703− */
1704−
1705−int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
1706− int __user *upeer_addrlen, int flags)
1693+int __sys_accept4_file(struct file *file, unsigned file_flags,
1694+ struct sockaddr __user *upeer_sockaddr,
1695+ int __user *upeer_addrlen, int flags)
17071696 {
17081697 struct socket *sock, *newsock;
17091698 struct file *newfile;
1710− int err, len, newfd, fput_needed;
1699+ int err, len, newfd;
17111700 struct sockaddr_storage address;
17121701
17131702 if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
@@ -1716,14 +1705,14 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 2 unmodified lines
17161705 if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
17171706 flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
17181707
1719− sock = sockfd_lookup_light(fd, &err, &fput_needed);
1708+ sock = sock_from_file(file, &err);
17201709 if (!sock)
17211710 goto out;
17221711
17231712 err = -ENFILE;
17241713 newsock = sock_alloc();
17251714 if (!newsock)
1726− goto out_put;
1715+ goto out;
17271716
17281717 newsock->type = sock->type;
17291718 newsock->ops = sock->ops;
@@ -1738,20 +1727,21 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 8 unmodified lines
17381727 if (unlikely(newfd < 0)) {
17391728 err = newfd;
17401729 sock_release(newsock);
1741− goto out_put;
1730+ goto out;
17421731 }
17431732 newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
17441733 if (IS_ERR(newfile)) {
17451734 err = PTR_ERR(newfile);
17461735 put_unused_fd(newfd);
1747− goto out_put;
1736+ goto out;
17481737 }
17491738
17501739 err = security_socket_accept(sock, newsock);
17511740 if (err)
17521741 goto out_fd;
17531742
1754− err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
1743+ err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags,
1744+ false);
17551745 if (err < 0)
17561746 goto out_fd;
17571747
@@ -1772,15 +1762,42 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 14 unmodified lines
17721762
17731763 fd_install(newfd, newfile);
17741764 err = newfd;
1775−
1776−out_put:
1777− fput_light(sock->file, fput_needed);
17781765 out:
17791766 return err;
17801767 out_fd:
17811768 fput(newfile);
17821769 put_unused_fd(newfd);
1783− goto out_put;
1770+ goto out;
1771+
1772+}
1773+
1774+/*
1775+ * For accept, we attempt to create a new socket, set up the link
1776+ * with the client, wake up the client, then return the new
1777+ * connected fd. We collect the address of the connector in kernel
1778+ * space and move it to user at the very end. This is unclean because
1779+ * we open the socket then return an error.
1780+ *
1781+ * 1003.1g adds the ability to recvmsg() to query connection pending
1782+ * status to recvmsg. We need to add that support in a way thats
1783+ * clean when we restructure accept also.
1784+ */
1785+
1786+int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
1787+ int __user *upeer_addrlen, int flags)
1788+{
1789+ int ret = -EBADF;
1790+ struct fd f;
1791+
1792+ f = fdget(fd);
1793+ if (f.file) {
1794+ ret = __sys_accept4_file(f.file, 0, upeer_sockaddr,
1795+ upeer_addrlen, flags);
1796+ if (f.flags)
1797+ fput(f.file);
1798+ }
1799+
1800+ return ret;
17841801 }
17851802
17861803 SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t