diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 71 | 
1 files changed, 37 insertions, 34 deletions
diff --git a/net/socket.c b/net/socket.c index 0b2dad3bdf7f..532fff5a3684 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1722,32 +1722,22 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)  	return __sys_listen(fd, backlog);  } -int __sys_accept4_file(struct file *file, unsigned file_flags, +struct file *do_accept(struct file *file, unsigned file_flags,  		       struct sockaddr __user *upeer_sockaddr, -		       int __user *upeer_addrlen, int flags, -		       unsigned long nofile) +		       int __user *upeer_addrlen, int flags)  {  	struct socket *sock, *newsock;  	struct file *newfile; -	int err, len, newfd; +	int err, len;  	struct sockaddr_storage address; -	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) -		return -EINVAL; - -	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) -		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; -  	sock = sock_from_file(file); -	if (!sock) { -		err = -ENOTSOCK; -		goto out; -	} +	if (!sock) +		return ERR_PTR(-ENOTSOCK); -	err = -ENFILE;  	newsock = sock_alloc();  	if (!newsock) -		goto out; +		return ERR_PTR(-ENFILE);  	newsock->type = sock->type;  	newsock->ops = sock->ops; @@ -1758,18 +1748,9 @@ int __sys_accept4_file(struct file *file, unsigned file_flags,  	 */  	__module_get(newsock->ops->owner); -	newfd = __get_unused_fd_flags(flags, nofile); -	if (unlikely(newfd < 0)) { -		err = newfd; -		sock_release(newsock); -		goto out; -	}  	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); -	if (IS_ERR(newfile)) { -		err = PTR_ERR(newfile); -		put_unused_fd(newfd); -		goto out; -	} +	if (IS_ERR(newfile)) +		return newfile;  	err = security_socket_accept(sock, newsock);  	if (err) @@ -1794,16 +1775,38 @@ int __sys_accept4_file(struct file *file, unsigned file_flags,  	}  	/* File flags are not inherited via accept() unlike another OSes. */ - -	fd_install(newfd, newfile); -	err = newfd; -out: -	return err; +	return newfile;  out_fd:  	fput(newfile); -	put_unused_fd(newfd); -	goto out; +	return ERR_PTR(err); +} + +int __sys_accept4_file(struct file *file, unsigned file_flags, +		       struct sockaddr __user *upeer_sockaddr, +		       int __user *upeer_addrlen, int flags, +		       unsigned long nofile) +{ +	struct file *newfile; +	int newfd; +	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) +		return -EINVAL; + +	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) +		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; + +	newfd = __get_unused_fd_flags(flags, nofile); +	if (unlikely(newfd < 0)) +		return newfd; + +	newfile = do_accept(file, file_flags, upeer_sockaddr, upeer_addrlen, +			    flags); +	if (IS_ERR(newfile)) { +		put_unused_fd(newfd); +		return PTR_ERR(newfile); +	} +	fd_install(newfd, newfile); +	return newfd;  }  /*  |