diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 123 | 
1 files changed, 56 insertions, 67 deletions
diff --git a/net/socket.c b/net/socket.c index 42d8e9c9ccd5..6f05d5c4bf30 100644 --- a/net/socket.c +++ b/net/socket.c @@ -406,8 +406,10 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)  		name.len = strlen(name.name);  	}  	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); -	if (unlikely(!path.dentry)) +	if (unlikely(!path.dentry)) { +		sock_release(sock);  		return ERR_PTR(-ENOMEM); +	}  	path.mnt = mntget(sock_mnt);  	d_instantiate(path.dentry, SOCK_INODE(sock)); @@ -415,9 +417,11 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)  	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,  		  &socket_file_ops);  	if (IS_ERR(file)) { -		/* drop dentry, keep inode */ +		/* drop dentry, keep inode for a bit */  		ihold(d_inode(path.dentry));  		path_put(&path); +		/* ... and now kill it properly */ +		sock_release(sock);  		return file;  	} @@ -432,8 +436,10 @@ static int sock_map_fd(struct socket *sock, int flags)  {  	struct file *newfile;  	int fd = get_unused_fd_flags(flags); -	if (unlikely(fd < 0)) +	if (unlikely(fd < 0)) { +		sock_release(sock);  		return fd; +	}  	newfile = sock_alloc_file(sock, flags, NULL);  	if (likely(!IS_ERR(newfile))) { @@ -1330,19 +1336,9 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)  	retval = sock_create(family, type, protocol, &sock);  	if (retval < 0) -		goto out; - -	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); -	if (retval < 0) -		goto out_release; - -out: -	/* It may be already another descriptor 8) Not kernel problem. */ -	return retval; +		return retval; -out_release: -	sock_release(sock); -	return retval; +	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));  }  /* @@ -1366,87 +1362,72 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;  	/* +	 * reserve descriptors and make sure we won't fail +	 * to return them to userland. +	 */ +	fd1 = get_unused_fd_flags(flags); +	if (unlikely(fd1 < 0)) +		return fd1; + +	fd2 = get_unused_fd_flags(flags); +	if (unlikely(fd2 < 0)) { +		put_unused_fd(fd1); +		return fd2; +	} + +	err = put_user(fd1, &usockvec[0]); +	if (err) +		goto out; + +	err = put_user(fd2, &usockvec[1]); +	if (err) +		goto out; + +	/*  	 * Obtain the first socket and check if the underlying protocol  	 * supports the socketpair call.  	 */  	err = sock_create(family, type, protocol, &sock1); -	if (err < 0) +	if (unlikely(err < 0))  		goto out;  	err = sock_create(family, type, protocol, &sock2); -	if (err < 0) -		goto out_release_1; - -	err = sock1->ops->socketpair(sock1, sock2); -	if (err < 0) -		goto out_release_both; - -	fd1 = get_unused_fd_flags(flags); -	if (unlikely(fd1 < 0)) { -		err = fd1; -		goto out_release_both; +	if (unlikely(err < 0)) { +		sock_release(sock1); +		goto out;  	} -	fd2 = get_unused_fd_flags(flags); -	if (unlikely(fd2 < 0)) { -		err = fd2; -		goto out_put_unused_1; +	err = sock1->ops->socketpair(sock1, sock2); +	if (unlikely(err < 0)) { +		sock_release(sock2); +		sock_release(sock1); +		goto out;  	}  	newfile1 = sock_alloc_file(sock1, flags, NULL);  	if (IS_ERR(newfile1)) {  		err = PTR_ERR(newfile1); -		goto out_put_unused_both; +		sock_release(sock2); +		goto out;  	}  	newfile2 = sock_alloc_file(sock2, flags, NULL);  	if (IS_ERR(newfile2)) {  		err = PTR_ERR(newfile2); -		goto out_fput_1; +		fput(newfile1); +		goto out;  	} -	err = put_user(fd1, &usockvec[0]); -	if (err) -		goto out_fput_both; - -	err = put_user(fd2, &usockvec[1]); -	if (err) -		goto out_fput_both; -  	audit_fd_pair(fd1, fd2);  	fd_install(fd1, newfile1);  	fd_install(fd2, newfile2); -	/* fd1 and fd2 may be already another descriptors. -	 * Not kernel problem. -	 */ -  	return 0; -out_fput_both: -	fput(newfile2); -	fput(newfile1); -	put_unused_fd(fd2); -	put_unused_fd(fd1); -	goto out; - -out_fput_1: -	fput(newfile1); -	put_unused_fd(fd2); -	put_unused_fd(fd1); -	sock_release(sock2); -	goto out; - -out_put_unused_both: +out:  	put_unused_fd(fd2); -out_put_unused_1:  	put_unused_fd(fd1); -out_release_both: -	sock_release(sock2); -out_release_1: -	sock_release(sock1); -out:  	return err;  } @@ -1562,7 +1543,6 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,  	if (IS_ERR(newfile)) {  		err = PTR_ERR(newfile);  		put_unused_fd(newfd); -		sock_release(newsock);  		goto out_put;  	} @@ -2641,6 +2621,15 @@ out_fs:  core_initcall(sock_init);	/* early initcall */ +static int __init jit_init(void) +{ +#ifdef CONFIG_BPF_JIT_ALWAYS_ON +	bpf_jit_enable = 1; +#endif +	return 0; +} +pure_initcall(jit_init); +  #ifdef CONFIG_PROC_FS  void socket_seq_show(struct seq_file *seq)  {  | 
