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 | 399 | int __user *upeer_addrlen, int flags); |
| 400 | 400 | extern int __sys_socket(int family, int type, int protocol); |
| 401 | 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 | 405 | extern int __sys_connect(int fd, struct sockaddr __user *uservaddr, |
| 403 | 406 | int addrlen); |
| 404 | 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 | 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 | 1831 | struct socket *sock; |
| 1831 | 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 | 1836 | if (!sock) |
| 1836 | 1837 | goto out; |
| 1837 | 1838 | err = move_addr_to_kernel(uservaddr, addrlen, &address); |
| 1838 | 1839 | if (err < 0) |
| 1839 | − goto out_put; | |
| 1840 | + goto out; | |
| 1840 | 1841 | |
| 1841 | 1842 | err = |
| 1842 | 1843 | security_socket_connect(sock, (struct sockaddr *)&address, addrlen); |
| 1843 | 1844 | if (err) |
| 1844 | − goto out_put; | |
| 1845 | + goto out; | |
| 1845 | 1846 | |
| 1846 | 1847 | err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, |
| 1847 | − sock->file->f_flags); | |
| 1848 | −out_put: | |
| 1849 | − fput_light(sock->file, fput_needed); | |
| 1848 | + sock->file->f_flags | file_flags); | |
| 1850 | 1849 | out: |
| 1851 | 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 | 1868 | SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, |
| 1855 | 1869 | int, addrlen) |
| 1856 | 1870 | { |