1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2026 Isovalent */ 3 4 #include <linux/bpf.h> 5 #include <linux/bpf_ksock.h> 6 #include <linux/btf.h> 7 #include <linux/btf_ids.h> 8 #include <linux/in.h> 9 #include <linux/in6.h> 10 #include <linux/net.h> 11 #include <linux/refcount.h> 12 #include <linux/sched.h> 13 #include <linux/slab.h> 14 #include <linux/socket.h> 15 #include <linux/unaligned.h> 16 #include <linux/workqueue.h> 17 #include <net/sock.h> 18 19 /** 20 * struct bpf_ksock - refcounted BPF kernel socket context 21 * @sock: The underlying kernel socket. 22 * @usage: Reference counter. 23 * @rwork: RCU work for deferred cleanup (sock_release may sleep). 24 */ 25 struct bpf_ksock { 26 struct socket *sock; 27 refcount_t usage; 28 struct rcu_work rwork; 29 }; 30 31 static void ksock_release_work_fn(struct work_struct *work) 32 { 33 struct bpf_ksock *ks; 34 35 ks = container_of(to_rcu_work(work), struct bpf_ksock, rwork); 36 sock_release(ks->sock); 37 kfree(ks); 38 } 39 40 static bool bpf_ksock_has_user_task_context(void) 41 { 42 /* 43 * Task work can run from do_exit() after exit_nsproxy_namespaces() 44 * cleared current->nsproxy, while current is still not a kthread. 45 */ 46 return !(current->flags & PF_KTHREAD) && current->nsproxy; 47 } 48 49 __bpf_kfunc_start_defs(); 50 51 /** 52 * bpf_ksock_create() - Create a BPF kernel socket. 53 * 54 * Allocates and creates a kernel socket. 55 * 56 * The returned context must either be stored in a map as a kptr, or 57 * freed with bpf_ksock_release(). 58 * 59 * This function may sleep (sock_create), so it can only be used 60 * in sleepable BPF programs (SYSCALL). 61 * It cannot be called from a BPF workqueue callback because that callback 62 * does not retain the invoking task's namespace or security context. 63 * 64 * @opts: Pointer to struct bpf_ksock_create_opts with socket parameters. 65 * @opts__sz: Size of the opts struct. 66 * @err__uninit: Integer to store error code when NULL is returned. 67 */ 68 __bpf_kfunc struct bpf_ksock * 69 bpf_ksock_create(const struct bpf_ksock_create_opts *opts, u32 opts__sz, 70 int *err__uninit) 71 { 72 struct bpf_ksock_create_opts opts_copy; 73 struct bpf_ksock *ks; 74 int err; 75 76 /* 77 * sock_create() derives the network namespace, credentials, and cgroup 78 * from current. Kernel threads, including BPF workqueue callbacks, do 79 * not carry the context of the task that invoked the BPF program. 80 */ 81 if (!bpf_ksock_has_user_task_context()) { 82 err = -EOPNOTSUPP; 83 goto err_out; 84 } 85 86 if (!opts || opts__sz != sizeof(struct bpf_ksock_create_opts)) { 87 err = -EINVAL; 88 goto err_out; 89 } 90 91 opts_copy = (struct bpf_ksock_create_opts){ 92 .family = READ_ONCE(opts->family), 93 .type = READ_ONCE(opts->type), 94 .protocol = READ_ONCE(opts->protocol), 95 .reserved = READ_ONCE(opts->reserved), 96 }; 97 98 if (opts_copy.reserved) { 99 err = -EINVAL; 100 goto err_out; 101 } 102 103 if (opts_copy.family != AF_INET && opts_copy.family != AF_INET6) { 104 err = -EAFNOSUPPORT; 105 goto err_out; 106 } 107 108 if (opts_copy.type != SOCK_DGRAM) { 109 err = -EPROTONOSUPPORT; 110 goto err_out; 111 } 112 113 if (opts_copy.protocol != IPPROTO_UDP && opts_copy.protocol != 0) { 114 err = -EPROTONOSUPPORT; 115 goto err_out; 116 } 117 118 ks = kzalloc_obj(*ks); 119 if (!ks) { 120 err = -ENOMEM; 121 goto err_out; 122 } 123 124 /* 125 * Use the normal current-task socket path so LSM/cgroup policy, 126 * socket labels, and the active netns reference match a socket(2) 127 * created by the BPF program's caller. 128 */ 129 err = sock_create(opts_copy.family, opts_copy.type, opts_copy.protocol, 130 &ks->sock); 131 if (err) 132 goto err_free; 133 134 ks->sock->sk->sk_rcvbuf = SOCK_MIN_RCVBUF; 135 ks->sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK; 136 137 refcount_set(&ks->usage, 1); 138 put_unaligned(0, err__uninit); 139 return ks; 140 141 err_free: 142 kfree(ks); 143 err_out: 144 put_unaligned(err, err__uninit); 145 return NULL; 146 } 147 148 /** 149 * bpf_ksock_connect() - Connect a BPF kernel socket to a remote address. 150 * @ks: The BPF kernel socket context. 151 * @addr: Pointer to an IPv4 or IPv6 socket address. 152 * @addr__sz: Size of the address union. 153 * 154 * Connects the socket to the specified remote address and port. 155 * 156 * This function may sleep while connecting the socket, so it can only be used 157 * in sleepable BPF programs (SYSCALL). 158 * 159 * Return: 0 on success, negative errno on error. 160 */ 161 __bpf_kfunc int bpf_ksock_connect(struct bpf_ksock *ks, 162 const union bpf_ksock_addr *addr, 163 u32 addr__sz) 164 { 165 struct sockaddr_storage sa; 166 int addrlen; 167 168 if (!bpf_ksock_has_user_task_context()) 169 return -EOPNOTSUPP; 170 171 if (!addr || addr__sz != sizeof(*addr)) 172 return -EINVAL; 173 174 /* Kfunc memory arguments may be unaligned. */ 175 memcpy(&sa, addr, sizeof(*addr)); 176 177 switch (sa.ss_family) { 178 case AF_INET: 179 addrlen = sizeof(struct sockaddr_in); 180 break; 181 case AF_INET6: 182 addrlen = sizeof(struct sockaddr_in6); 183 break; 184 default: 185 return -EAFNOSUPPORT; 186 } 187 188 return connect_socket(ks->sock, &sa, addrlen, 0); 189 } 190 191 /** 192 * bpf_ksock_acquire() - Acquire a reference to a BPF kernel socket. 193 * @ks: The BPF kernel socket context to acquire. Must be a 194 * trusted pointer (e.g. RCU-protected kptr from a map). 195 * 196 * The acquired context must either be stored in a map as a kptr, or 197 * freed with bpf_ksock_release(). 198 */ 199 __bpf_kfunc struct bpf_ksock *bpf_ksock_acquire(struct bpf_ksock *ks) 200 { 201 if (!refcount_inc_not_zero(&ks->usage)) 202 return NULL; 203 return ks; 204 } 205 206 /** 207 * bpf_ksock_release() - Release a BPF kernel socket. 208 * @ks: The BPF kernel socket context to release. 209 * 210 * When the final reference is released, the socket is cleaned up via 211 * queue_rcu_work() (since sock_release may sleep). 212 */ 213 __bpf_kfunc void bpf_ksock_release(struct bpf_ksock *ks) 214 { 215 if (refcount_dec_and_test(&ks->usage)) { 216 INIT_RCU_WORK(&ks->rwork, ksock_release_work_fn); 217 queue_rcu_work(system_dfl_wq, &ks->rwork); 218 } 219 } 220 221 __bpf_kfunc void bpf_ksock_release_dtor(void *ks) 222 { 223 bpf_ksock_release(ks); 224 } 225 CFI_NOSEAL(bpf_ksock_release_dtor); 226 227 /** 228 * bpf_ksock_send() - Send data through a BPF kernel socket. 229 * @ks: The BPF kernel socket context. Must be an acquired reference. 230 * @data: Pointer to the data to send. 231 * @data__sz: Size of the data to send. 232 * 233 * Sends data on a connected socket, best-effort and nonblocking. This may sleep 234 * (kernel_sendmsg), so it can only be called from sleepable BPF programs. 235 * 236 * Return: Number of bytes sent on success, negative errno on error. 237 */ 238 __bpf_kfunc int bpf_ksock_send(struct bpf_ksock *ks, const void *data, 239 u32 data__sz) 240 { 241 struct msghdr msg = { 242 .msg_flags = MSG_DONTWAIT, 243 }; 244 struct kvec iov = { 245 .iov_base = (void *)data, 246 .iov_len = data__sz, 247 }; 248 int ret; 249 250 if (!bpf_ksock_has_user_task_context()) 251 return -EOPNOTSUPP; 252 253 ret = kernel_sendmsg(ks->sock, &msg, &iov, 1, data__sz); 254 255 return ret; 256 } 257 258 __bpf_kfunc_end_defs(); 259 260 BTF_KFUNCS_START(ksock_init_kfunc_btf_ids) 261 BTF_ID_FLAGS(func, bpf_ksock_create, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE) 262 BTF_ID_FLAGS(func, bpf_ksock_connect, KF_SLEEPABLE) 263 BTF_KFUNCS_END(ksock_init_kfunc_btf_ids) 264 265 static const struct btf_kfunc_id_set ksock_init_kfunc_set = { 266 .owner = THIS_MODULE, 267 .set = &ksock_init_kfunc_btf_ids, 268 }; 269 270 BTF_KFUNCS_START(ksock_kfunc_btf_ids) 271 BTF_ID_FLAGS(func, bpf_ksock_release, KF_RELEASE) 272 BTF_ID_FLAGS(func, bpf_ksock_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL) 273 BTF_ID_FLAGS(func, bpf_ksock_send, KF_SLEEPABLE) 274 BTF_KFUNCS_END(ksock_kfunc_btf_ids) 275 276 #ifdef CONFIG_BPF_LSM 277 BTF_ID_LIST_SINGLE(bpf_lsm_socket_sendmsg_id, func, bpf_lsm_socket_sendmsg) 278 #endif 279 280 static int bpf_ksock_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id) 281 { 282 if (!btf_id_set8_contains(&ksock_kfunc_btf_ids, kfunc_id)) 283 return 0; 284 285 if (prog->type == BPF_PROG_TYPE_SYSCALL) 286 return 0; 287 288 #ifdef CONFIG_BPF_LSM 289 if (prog->type == BPF_PROG_TYPE_LSM && 290 prog->aux->attach_btf_id != bpf_lsm_socket_sendmsg_id[0]) 291 return 0; 292 #endif 293 294 return -EACCES; 295 } 296 297 static const struct btf_kfunc_id_set ksock_kfunc_set = { 298 .owner = THIS_MODULE, 299 .set = &ksock_kfunc_btf_ids, 300 .filter = bpf_ksock_kfunc_filter, 301 }; 302 303 BTF_ID_LIST(bpf_ksock_dtor_ids) 304 BTF_ID(struct, bpf_ksock) 305 BTF_ID(func, bpf_ksock_release_dtor) 306 307 static int __init bpf_ksock_kfunc_init(void) 308 { 309 int ret; 310 const struct btf_id_dtor_kfunc bpf_ksock_dtors[] = { 311 { 312 .btf_id = bpf_ksock_dtor_ids[0], 313 .kfunc_btf_id = bpf_ksock_dtor_ids[1], 314 }, 315 }; 316 317 ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, 318 &ksock_init_kfunc_set); 319 ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, 320 &ksock_kfunc_set); 321 ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, 322 &ksock_kfunc_set); 323 return ret ?: register_btf_id_dtor_kfuncs(bpf_ksock_dtors, 324 ARRAY_SIZE(bpf_ksock_dtors), 325 THIS_MODULE); 326 } 327 328 late_initcall(bpf_ksock_kfunc_init); 329