xref: /linux/net/core/bpf_ksock.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
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 
ksock_release_work_fn(struct work_struct * work)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 
bpf_ksock_has_user_task_context(void)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 *
bpf_ksock_create(const struct bpf_ksock_create_opts * opts,u32 opts__sz,int * err__uninit)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  */
bpf_ksock_connect(struct bpf_ksock * ks,const union bpf_ksock_addr * addr,u32 addr__sz)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  */
bpf_ksock_acquire(struct bpf_ksock * ks)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  */
bpf_ksock_release(struct bpf_ksock * ks)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 
bpf_ksock_release_dtor(void * ks)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  */
bpf_ksock_send(struct bpf_ksock * ks,const void * data,u32 data__sz)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)
BTF_ID_FLAGS(func,bpf_ksock_release,KF_RELEASE)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)
BTF_ID(struct,bpf_ksock)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