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.
Unified · Split
| @@ -392,6 +392,9 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, · 391 unmodified lines | ||
| 392 | 392 | extern int __sys_sendto(int fd, void __user *buff, size_t len, |
| 393 | 393 | unsigned int flags, struct sockaddr __user *addr, |
| 394 | 394 | 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); | |
| 395 | 398 | extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, |
| 396 | 399 | int __user *upeer_addrlen, int flags); |
| 397 | 400 | extern int __sys_socket(int family, int type, int protocol); |
| @@ -1690,24 +1690,13 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog) · 1689 unmodified lines | ||
| 1690 | 1690 | return __sys_listen(fd, backlog); |
| 1691 | 1691 | } |
| 1692 | 1692 | |
| 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) | |
| 1707 | 1696 | { |
| 1708 | 1697 | struct socket *sock, *newsock; |
| 1709 | 1698 | struct file *newfile; |
| 1710 | − int err, len, newfd, fput_needed; | |
| 1699 | + int err, len, newfd; | |
| 1711 | 1700 | struct sockaddr_storage address; |
| 1712 | 1701 | |
| 1713 | 1702 | if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) |
| @@ -1716,14 +1705,14 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 2 unmodified lines | ||
| 1716 | 1705 | if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) |
| 1717 | 1706 | flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; |
| 1718 | 1707 | |
| 1719 | − sock = sockfd_lookup_light(fd, &err, &fput_needed); | |
| 1708 | + sock = sock_from_file(file, &err); | |
| 1720 | 1709 | if (!sock) |
| 1721 | 1710 | goto out; |
| 1722 | 1711 | |
| 1723 | 1712 | err = -ENFILE; |
| 1724 | 1713 | newsock = sock_alloc(); |
| 1725 | 1714 | if (!newsock) |
| 1726 | − goto out_put; | |
| 1715 | + goto out; | |
| 1727 | 1716 | |
| 1728 | 1717 | newsock->type = sock->type; |
| 1729 | 1718 | newsock->ops = sock->ops; |
| @@ -1738,20 +1727,21 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 8 unmodified lines | ||
| 1738 | 1727 | if (unlikely(newfd < 0)) { |
| 1739 | 1728 | err = newfd; |
| 1740 | 1729 | sock_release(newsock); |
| 1741 | − goto out_put; | |
| 1730 | + goto out; | |
| 1742 | 1731 | } |
| 1743 | 1732 | newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); |
| 1744 | 1733 | if (IS_ERR(newfile)) { |
| 1745 | 1734 | err = PTR_ERR(newfile); |
| 1746 | 1735 | put_unused_fd(newfd); |
| 1747 | − goto out_put; | |
| 1736 | + goto out; | |
| 1748 | 1737 | } |
| 1749 | 1738 | |
| 1750 | 1739 | err = security_socket_accept(sock, newsock); |
| 1751 | 1740 | if (err) |
| 1752 | 1741 | goto out_fd; |
| 1753 | 1742 | |
| 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); | |
| 1755 | 1745 | if (err < 0) |
| 1756 | 1746 | goto out_fd; |
| 1757 | 1747 | |
| @@ -1772,15 +1762,42 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 14 unmodified lines | ||
| 1772 | 1762 | |
| 1773 | 1763 | fd_install(newfd, newfile); |
| 1774 | 1764 | err = newfd; |
| 1775 | − | |
| 1776 | −out_put: | |
| 1777 | − fput_light(sock->file, fput_needed); | |
| 1778 | 1765 | out: |
| 1779 | 1766 | return err; |
| 1780 | 1767 | out_fd: |
| 1781 | 1768 | fput(newfile); |
| 1782 | 1769 | 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; | |
| 1784 | 1801 | } |
| 1785 | 1802 | |
| 1786 | 1803 | SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, |