diff options
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 67 | 
1 files changed, 43 insertions, 24 deletions
| diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 3e8a04a13668..a357dc5f2404 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -116,6 +116,7 @@  #include <linux/freezer.h>  #include <linux/file.h>  #include <linux/btf_ids.h> +#include <linux/bpf-cgroup.h>  #include "scm.h" @@ -1381,6 +1382,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,  		if (err)  			goto out; +		err = BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, addr, &alen); +		if (err) +			goto out; +  		if ((test_bit(SOCK_PASSCRED, &sock->flags) ||  		     test_bit(SOCK_PASSPIDFD, &sock->flags)) &&  		    !unix_sk(sk)->addr) { @@ -1490,6 +1495,10 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,  	if (err)  		goto out; +	err = BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, uaddr, &addr_len); +	if (err) +		goto out; +  	if ((test_bit(SOCK_PASSCRED, &sock->flags) ||  	     test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {  		err = unix_autobind(sk); @@ -1770,6 +1779,13 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)  	} else {  		err = addr->len;  		memcpy(sunaddr, addr->name, addr->len); + +		if (peer) +			BPF_CGROUP_RUN_SA_PROG(sk, uaddr, &err, +					       CGROUP_UNIX_GETPEERNAME); +		else +			BPF_CGROUP_RUN_SA_PROG(sk, uaddr, &err, +					       CGROUP_UNIX_GETSOCKNAME);  	}  	sock_put(sk);  out: @@ -1922,6 +1938,13 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,  		err = unix_validate_addr(sunaddr, msg->msg_namelen);  		if (err)  			goto out; + +		err = BPF_CGROUP_RUN_PROG_UNIX_SENDMSG_LOCK(sk, +							    msg->msg_name, +							    &msg->msg_namelen, +							    NULL); +		if (err) +			goto out;  	} else {  		sunaddr = NULL;  		err = -ENOTCONN; @@ -2390,9 +2413,14 @@ int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,  						EPOLLOUT | EPOLLWRNORM |  						EPOLLWRBAND); -	if (msg->msg_name) +	if (msg->msg_name) {  		unix_copy_addr(msg, skb->sk); +		BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk, +						      msg->msg_name, +						      &msg->msg_namelen); +	} +  	if (size > skb->len - skip)  		size = skb->len - skip;  	else if (size < skb->len - skip) @@ -2553,15 +2581,16 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)  	if (!(state->flags & MSG_PEEK))  		WRITE_ONCE(u->oob_skb, NULL); - +	else +		skb_get(oob_skb);  	unix_state_unlock(sk);  	chunk = state->recv_actor(oob_skb, 0, chunk, state); -	if (!(state->flags & MSG_PEEK)) { +	if (!(state->flags & MSG_PEEK))  		UNIXCB(oob_skb).consumed += 1; -		kfree_skb(oob_skb); -	} + +	consume_skb(oob_skb);  	mutex_unlock(&u->iolock); @@ -2744,6 +2773,11 @@ unlock:  			DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr,  					 state->msg->msg_name);  			unix_copy_addr(state->msg, skb->sk); + +			BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk, +							      state->msg->msg_name, +							      &state->msg->msg_namelen); +  			sunaddr = NULL;  		} @@ -3311,7 +3345,7 @@ static const struct seq_operations unix_seq_ops = {  	.show   = unix_seq_show,  }; -#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) +#ifdef CONFIG_BPF_SYSCALL  struct bpf_unix_iter_state {  	struct seq_net_private p;  	unsigned int cur_sk; @@ -3573,7 +3607,7 @@ static struct pernet_operations unix_net_ops = {  	.exit = unix_net_exit,  }; -#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)  DEFINE_BPF_ITER_FUNC(unix, struct bpf_iter_meta *meta,  		     struct unix_sock *unix_sk, uid_t uid) @@ -3673,7 +3707,7 @@ static int __init af_unix_init(void)  	register_pernet_subsys(&unix_net_ops);  	unix_bpf_build_proto(); -#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)  	bpf_iter_register();  #endif @@ -3681,20 +3715,5 @@ out:  	return rc;  } -static void __exit af_unix_exit(void) -{ -	sock_unregister(PF_UNIX); -	proto_unregister(&unix_dgram_proto); -	proto_unregister(&unix_stream_proto); -	unregister_pernet_subsys(&unix_net_ops); -} - -/* Earlier than device_initcall() so that other drivers invoking -   request_module() don't end up in a loop when modprobe tries -   to use a UNIX socket. But later than subsys_initcall() because -   we depend on stuff initialised there */ +/* Later than subsys_initcall() because we depend on stuff initialised there */  fs_initcall(af_unix_init); -module_exit(af_unix_exit); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS_NETPROTO(PF_UNIX); | 
