193 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include "vmlinux.h"4#include "bpf_tracing_net.h"5#include <bpf/bpf_helpers.h>6#include <bpf/bpf_tracing.h>7 8char _license[] SEC("license") = "GPL";9 10extern bool CONFIG_SECURITY_SELINUX __kconfig __weak;11extern bool CONFIG_SECURITY_SMACK __kconfig __weak;12extern bool CONFIG_SECURITY_APPARMOR __kconfig __weak;13 14#ifndef AF_PACKET15#define AF_PACKET 1716#endif17 18#ifndef AF_UNIX19#define AF_UNIX 120#endif21 22#ifndef EPERM23#define EPERM 124#endif25 26struct {27 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);28 __type(key, __u64);29 __type(value, __u64);30} cgroup_storage SEC(".maps");31 32int called_socket_post_create;33int called_socket_post_create2;34int called_socket_bind;35int called_socket_bind2;36int called_socket_alloc;37int called_socket_clone;38 39static __always_inline int test_local_storage(void)40{41 __u64 *val;42 43 val = bpf_get_local_storage(&cgroup_storage, 0);44 if (!val)45 return 0;46 *val += 1;47 48 return 1;49}50 51static __always_inline int real_create(struct socket *sock, int family,52 int protocol)53{54 struct sock *sk;55 int prio = 123;56 57 /* Reject non-tx-only AF_PACKET. */58 if (family == AF_PACKET && protocol != 0)59 return 0; /* EPERM */60 61 sk = sock->sk;62 if (!sk)63 return 1;64 65 /* The rest of the sockets get default policy. */66 if (bpf_setsockopt(sk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))67 return 0; /* EPERM */68 69 /* Make sure bpf_getsockopt is allowed and works. */70 prio = 0;71 if (bpf_getsockopt(sk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))72 return 0; /* EPERM */73 if (prio != 123)74 return 0; /* EPERM */75 76 /* Can access cgroup local storage. */77 if (!test_local_storage())78 return 0; /* EPERM */79 80 return 1;81}82 83/* __cgroup_bpf_run_lsm_socket */84SEC("lsm_cgroup/socket_post_create")85int BPF_PROG(socket_post_create, struct socket *sock, int family,86 int type, int protocol, int kern)87{88 called_socket_post_create++;89 return real_create(sock, family, protocol);90}91 92/* __cgroup_bpf_run_lsm_socket */93SEC("lsm_cgroup/socket_post_create")94int BPF_PROG(socket_post_create2, struct socket *sock, int family,95 int type, int protocol, int kern)96{97 called_socket_post_create2++;98 return real_create(sock, family, protocol);99}100 101static __always_inline int real_bind(struct socket *sock,102 struct sockaddr *address,103 int addrlen)104{105 struct sockaddr_ll sa = {};106 struct sock *sk = sock->sk;107 108 if (!sk)109 return 1;110 111 if (sk->__sk_common.skc_family != AF_PACKET)112 return 1;113 114 if (sk->sk_kern_sock)115 return 1;116 117 bpf_probe_read_kernel(&sa, sizeof(sa), address);118 if (sa.sll_protocol)119 return 0; /* EPERM */120 121 /* Can access cgroup local storage. */122 if (!test_local_storage())123 return 0; /* EPERM */124 125 return 1;126}127 128/* __cgroup_bpf_run_lsm_socket */129SEC("lsm_cgroup/socket_bind")130int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,131 int addrlen)132{133 called_socket_bind++;134 return real_bind(sock, address, addrlen);135}136 137/* __cgroup_bpf_run_lsm_socket */138SEC("lsm_cgroup/socket_bind")139int BPF_PROG(socket_bind2, struct socket *sock, struct sockaddr *address,140 int addrlen)141{142 called_socket_bind2++;143 return real_bind(sock, address, addrlen);144}145 146/* __cgroup_bpf_run_lsm_current (via bpf_lsm_current_hooks) */147SEC("lsm_cgroup/sk_alloc_security")148int BPF_PROG(socket_alloc, struct sock *sk, int family, gfp_t priority)149{150 called_socket_alloc++;151 /* if already have non-bpf lsms installed, EPERM will cause memory leak of non-bpf lsms */152 if (CONFIG_SECURITY_SELINUX || CONFIG_SECURITY_SMACK || CONFIG_SECURITY_APPARMOR)153 return 1;154 155 if (family == AF_UNIX)156 return 0; /* EPERM */157 158 /* Can access cgroup local storage. */159 if (!test_local_storage())160 return 0; /* EPERM */161 162 return 1;163}164 165/* __cgroup_bpf_run_lsm_sock */166SEC("lsm_cgroup/inet_csk_clone")167int BPF_PROG(socket_clone, struct sock *newsk, const struct request_sock *req)168{169 int prio = 234;170 171 if (!newsk)172 return 1;173 174 /* Accepted request sockets get a different priority. */175 if (bpf_setsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))176 return 1;177 178 /* Make sure bpf_getsockopt is allowed and works. */179 prio = 0;180 if (bpf_getsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))181 return 1;182 if (prio != 234)183 return 1;184 185 /* Can access cgroup local storage. */186 if (!test_local_storage())187 return 1;188 189 called_socket_clone++;190 191 return 1;192}193