This is identical to __sys_connect(), 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
| @@ -399,6 +399,9 @@ extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 398 unmodified lines | |||
| 399 | int __user *upeer_addrlen, int flags); | 399 | int __user *upeer_addrlen, int flags); |
| 400 | extern int __sys_socket(int family, int type, int protocol); | 400 | extern int __sys_socket(int family, int type, int protocol); |
| 401 | extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); | 401 | extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); |
| 402 | extern int __sys_connect_file(struct file *file, | ||
| 403 | struct sockaddr __user *uservaddr, int addrlen, | ||
| 404 | int file_flags); | ||
| 402 | extern int __sys_connect(int fd, struct sockaddr __user *uservaddr, | 405 | extern int __sys_connect(int fd, struct sockaddr __user *uservaddr, |
| 403 | int addrlen); | 406 | int addrlen); |
| 404 | extern int __sys_listen(int fd, int backlog); | 407 | extern int __sys_listen(int fd, int backlog); |
| @@ -1825,32 +1825,46 @@ SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, · 1824 unmodified lines | |||
| 1825 | * include the -EINPROGRESS status for such sockets. | 1825 | * include the -EINPROGRESS status for such sockets. |
| 1826 | */ | 1826 | */ |
| 1827 | 1827 | ||
| 1828 | int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) | 1828 | int __sys_connect_file(struct file *file, struct sockaddr __user *uservaddr, |
| 1829 | int addrlen, int file_flags) | ||
| 1829 | { | 1830 | { |
| 1830 | struct socket *sock; | 1831 | struct socket *sock; |
| 1831 | struct sockaddr_storage address; | 1832 | struct sockaddr_storage address; |
| 1832 | int err, fput_needed; | 1833 | int err; |
| 1833 | 1834 | ||
| 1834 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1835 | sock = sock_from_file(file, &err); |
| 1835 | if (!sock) | 1836 | if (!sock) |
| 1836 | goto out; | 1837 | goto out; |
| 1837 | err = move_addr_to_kernel(uservaddr, addrlen, &address); | 1838 | err = move_addr_to_kernel(uservaddr, addrlen, &address); |
| 1838 | if (err < 0) | 1839 | if (err < 0) |
| 1839 | goto out_put; | 1840 | goto out; |
| 1840 | 1841 | ||
| 1841 | err = | 1842 | err = |
| 1842 | security_socket_connect(sock, (struct sockaddr *)&address, addrlen); | 1843 | security_socket_connect(sock, (struct sockaddr *)&address, addrlen); |
| 1843 | if (err) | 1844 | if (err) |
| 1844 | goto out_put; | 1845 | goto out; |
| 1845 | 1846 | ||
| 1846 | err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, | 1847 | err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, |
| 1847 | sock->file->f_flags); | 1848 | sock->file->f_flags | file_flags); |
| 1848 | out_put: | ||
| 1849 | fput_light(sock->file, fput_needed); | ||
| 1850 | out: | 1849 | out: |
| 1851 | return err; | 1850 | return err; |
| 1852 | } | 1851 | } |
| 1853 | 1852 | ||
| 1853 | int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) | ||
| 1854 | { | ||
| 1855 | int ret = -EBADF; | ||
| 1856 | struct fd f; | ||
| 1857 | |||
| 1858 | f = fdget(fd); | ||
| 1859 | if (f.file) { | ||
| 1860 | ret = __sys_connect_file(f.file, uservaddr, addrlen, 0); | ||
| 1861 | if (f.flags) | ||
| 1862 | fput(f.file); | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | return ret; | ||
| 1866 | } | ||
| 1867 | |||
| 1854 | SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, | 1868 | SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, |
| 1855 | int, addrlen) | 1869 | int, addrlen) |
| 1856 | { | 1870 | { |