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