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 | extern int __sys_sendto(int fd, void __user *buff, size_t len, | 392 | extern int __sys_sendto(int fd, void __user *buff, size_t len, |
| 393 | unsigned int flags, struct sockaddr __user *addr, | 393 | unsigned int flags, struct sockaddr __user *addr, |
| 394 | int addr_len); | 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 | extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, | 398 | extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, |
| 396 | int __user *upeer_addrlen, int flags); | 399 | int __user *upeer_addrlen, int flags); |
| 397 | extern int __sys_socket(int family, int type, int protocol); | 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 | return __sys_listen(fd, backlog); | 1690 | return __sys_listen(fd, backlog); |
| 1691 | } | 1691 | } |
| 1692 | 1692 | ||
| 1693 | /* | 1693 | int __sys_accept4_file(struct file *file, unsigned file_flags, |
| 1694 | * For accept, we attempt to create a new socket, set up the link | 1694 | struct sockaddr __user *upeer_sockaddr, |
| 1695 | * with the client, wake up the client, then return the new | 1695 | int __user *upeer_addrlen, int flags) |
| 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) | ||
| 1707 | { | 1696 | { |
| 1708 | struct socket *sock, *newsock; | 1697 | struct socket *sock, *newsock; |
| 1709 | struct file *newfile; | 1698 | struct file *newfile; |
| 1710 | int err, len, newfd, fput_needed; | 1699 | int err, len, newfd; |
| 1711 | struct sockaddr_storage address; | 1700 | struct sockaddr_storage address; |
| 1712 | 1701 | ||
| 1713 | if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) | 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 | if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) | 1705 | if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) |
| 1717 | flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; | 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 | if (!sock) | 1709 | if (!sock) |
| 1721 | goto out; | 1710 | goto out; |
| 1722 | 1711 | ||
| 1723 | err = -ENFILE; | 1712 | err = -ENFILE; |
| 1724 | newsock = sock_alloc(); | 1713 | newsock = sock_alloc(); |
| 1725 | if (!newsock) | 1714 | if (!newsock) |
| 1726 | goto out_put; | 1715 | goto out; |
| 1727 | 1716 | ||
| 1728 | newsock->type = sock->type; | 1717 | newsock->type = sock->type; |
| 1729 | newsock->ops = sock->ops; | 1718 | newsock->ops = sock->ops; |
| @@ -1738,20 +1727,21 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 8 unmodified lines | |||
| 1738 | if (unlikely(newfd < 0)) { | 1727 | if (unlikely(newfd < 0)) { |
| 1739 | err = newfd; | 1728 | err = newfd; |
| 1740 | sock_release(newsock); | 1729 | sock_release(newsock); |
| 1741 | goto out_put; | 1730 | goto out; |
| 1742 | } | 1731 | } |
| 1743 | newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); | 1732 | newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); |
| 1744 | if (IS_ERR(newfile)) { | 1733 | if (IS_ERR(newfile)) { |
| 1745 | err = PTR_ERR(newfile); | 1734 | err = PTR_ERR(newfile); |
| 1746 | put_unused_fd(newfd); | 1735 | put_unused_fd(newfd); |
| 1747 | goto out_put; | 1736 | goto out; |
| 1748 | } | 1737 | } |
| 1749 | 1738 | ||
| 1750 | err = security_socket_accept(sock, newsock); | 1739 | err = security_socket_accept(sock, newsock); |
| 1751 | if (err) | 1740 | if (err) |
| 1752 | goto out_fd; | 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 | if (err < 0) | 1745 | if (err < 0) |
| 1756 | goto out_fd; | 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 | fd_install(newfd, newfile); | 1763 | fd_install(newfd, newfile); |
| 1774 | err = newfd; | 1764 | err = newfd; |
| 1775 | |||
| 1776 | out_put: | ||
| 1777 | fput_light(sock->file, fput_needed); | ||
| 1778 | out: | 1765 | out: |
| 1779 | return err; | 1766 | return err; |
| 1780 | out_fd: | 1767 | out_fd: |
| 1781 | fput(newfile); | 1768 | fput(newfile); |
| 1782 | put_unused_fd(newfd); | 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 | SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | 1803 | SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, |