File Index
Files and directories
Sign in
FILE

bpf_lsm.c

File preview with syntax highlighting.

linux-6.19.14/kernel/bpf/bpf_lsm.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3/*
  4 * Copyright (C) 2020 Google LLC.
  5 */
  6
  7#include <linux/filter.h>
  8#include <linux/bpf.h>
  9#include <linux/btf.h>
 10#include <linux/binfmts.h>
 11#include <linux/lsm_hooks.h>
 12#include <linux/bpf_lsm.h>
 13#include <linux/kallsyms.h>
 14#include <net/bpf_sk_storage.h>
 15#include <linux/bpf_local_storage.h>
 16#include <linux/btf_ids.h>
 17#include <linux/ima.h>
 18#include <linux/bpf-cgroup.h>
 19
 20/* For every LSM hook that allows attachment of BPF programs, declare a nop
 21 * function where a BPF program can be attached.
 22 */
 23#define LSM_HOOK(RET, DEFAULT, NAME, ...)	\
 24noinline RET bpf_lsm_##NAME(__VA_ARGS__)	\
 25{						\
 26	return DEFAULT;				\
 27}
 28
 29#include <linux/lsm_hook_defs.h>
 30#undef LSM_HOOK
 31
 32#define LSM_HOOK(RET, DEFAULT, NAME, ...) BTF_ID(func, bpf_lsm_##NAME)
 33BTF_SET_START(bpf_lsm_hooks)
 34#include <linux/lsm_hook_defs.h>
 35#undef LSM_HOOK
 36BTF_SET_END(bpf_lsm_hooks)
 37
 38BTF_SET_START(bpf_lsm_disabled_hooks)
 39BTF_ID(func, bpf_lsm_vm_enough_memory)
 40BTF_ID(func, bpf_lsm_inode_need_killpriv)
 41BTF_ID(func, bpf_lsm_inode_getsecurity)
 42BTF_ID(func, bpf_lsm_inode_listsecurity)
 43BTF_ID(func, bpf_lsm_inode_copy_up_xattr)
 44BTF_ID(func, bpf_lsm_getselfattr)
 45BTF_ID(func, bpf_lsm_getprocattr)
 46BTF_ID(func, bpf_lsm_setprocattr)
 47#ifdef CONFIG_KEYS
 48BTF_ID(func, bpf_lsm_key_getsecurity)
 49#endif
 50#ifdef CONFIG_AUDIT
 51BTF_ID(func, bpf_lsm_audit_rule_match)
 52#endif
 53BTF_ID(func, bpf_lsm_ismaclabel)
 54BTF_ID(func, bpf_lsm_file_alloc_security)
 55BTF_SET_END(bpf_lsm_disabled_hooks)
 56
 57/* List of LSM hooks that should operate on 'current' cgroup regardless
 58 * of function signature.
 59 */
 60BTF_SET_START(bpf_lsm_current_hooks)
 61/* operate on freshly allocated sk without any cgroup association */
 62#ifdef CONFIG_SECURITY_NETWORK
 63BTF_ID(func, bpf_lsm_sk_alloc_security)
 64BTF_ID(func, bpf_lsm_sk_free_security)
 65#endif
 66BTF_SET_END(bpf_lsm_current_hooks)
 67
 68/* List of LSM hooks that trigger while the socket is properly locked.
 69 */
 70BTF_SET_START(bpf_lsm_locked_sockopt_hooks)
 71#ifdef CONFIG_SECURITY_NETWORK
 72BTF_ID(func, bpf_lsm_sock_graft)
 73BTF_ID(func, bpf_lsm_inet_csk_clone)
 74BTF_ID(func, bpf_lsm_inet_conn_established)
 75#endif
 76BTF_SET_END(bpf_lsm_locked_sockopt_hooks)
 77
 78/* List of LSM hooks that trigger while the socket is _not_ locked,
 79 * but it's ok to call bpf_{g,s}etsockopt because the socket is still
 80 * in the early init phase.
 81 */
 82BTF_SET_START(bpf_lsm_unlocked_sockopt_hooks)
 83#ifdef CONFIG_SECURITY_NETWORK
 84BTF_ID(func, bpf_lsm_socket_post_create)
 85BTF_ID(func, bpf_lsm_socket_socketpair)
 86#endif
 87BTF_SET_END(bpf_lsm_unlocked_sockopt_hooks)
 88
 89#ifdef CONFIG_CGROUP_BPF
 90void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog,
 91			     bpf_func_t *bpf_func)
 92{
 93	const struct btf_param *args __maybe_unused;
 94
 95	if (btf_type_vlen(prog->aux->attach_func_proto) < 1 ||
 96	    btf_id_set_contains(&bpf_lsm_current_hooks,
 97				prog->aux->attach_btf_id)) {
 98		*bpf_func = __cgroup_bpf_run_lsm_current;
 99		return;
100	}
101
102#ifdef CONFIG_NET
103	args = btf_params(prog->aux->attach_func_proto);
104
105	if (args[0].type == btf_sock_ids[BTF_SOCK_TYPE_SOCKET])
106		*bpf_func = __cgroup_bpf_run_lsm_socket;
107	else if (args[0].type == btf_sock_ids[BTF_SOCK_TYPE_SOCK])
108		*bpf_func = __cgroup_bpf_run_lsm_sock;
109	else
110#endif
111		*bpf_func = __cgroup_bpf_run_lsm_current;
112}
113#endif
114
115int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog,
116			const struct bpf_prog *prog)
117{
118	u32 btf_id = prog->aux->attach_btf_id;
119	const char *func_name = prog->aux->attach_func_name;
120
121	if (!prog->gpl_compatible) {
122		bpf_log(vlog,
123			"LSM programs must have a GPL compatible license\n");
124		return -EINVAL;
125	}
126
127	if (btf_id_set_contains(&bpf_lsm_disabled_hooks, btf_id)) {
128		bpf_log(vlog, "attach_btf_id %u points to disabled hook %s\n",
129			btf_id, func_name);
130		return -EINVAL;
131	}
132
133	if (!btf_id_set_contains(&bpf_lsm_hooks, btf_id)) {
134		bpf_log(vlog, "attach_btf_id %u points to wrong type name %s\n",
135			btf_id, func_name);
136		return -EINVAL;
137	}
138
139	return 0;
140}
141
142/* Mask for all the currently supported BPRM option flags */
143#define BPF_F_BRPM_OPTS_MASK	BPF_F_BPRM_SECUREEXEC
144
145BPF_CALL_2(bpf_bprm_opts_set, struct linux_binprm *, bprm, u64, flags)
146{
147	if (flags & ~BPF_F_BRPM_OPTS_MASK)
148		return -EINVAL;
149
150	bprm->secureexec = (flags & BPF_F_BPRM_SECUREEXEC);
151	return 0;
152}
153
154BTF_ID_LIST_SINGLE(bpf_bprm_opts_set_btf_ids, struct, linux_binprm)
155
156static const struct bpf_func_proto bpf_bprm_opts_set_proto = {
157	.func		= bpf_bprm_opts_set,
158	.gpl_only	= false,
159	.ret_type	= RET_INTEGER,
160	.arg1_type	= ARG_PTR_TO_BTF_ID,
161	.arg1_btf_id	= &bpf_bprm_opts_set_btf_ids[0],
162	.arg2_type	= ARG_ANYTHING,
163};
164
165BPF_CALL_3(bpf_ima_inode_hash, struct inode *, inode, void *, dst, u32, size)
166{
167	return ima_inode_hash(inode, dst, size);
168}
169
170static bool bpf_ima_inode_hash_allowed(const struct bpf_prog *prog)
171{
172	return bpf_lsm_is_sleepable_hook(prog->aux->attach_btf_id);
173}
174
175BTF_ID_LIST_SINGLE(bpf_ima_inode_hash_btf_ids, struct, inode)
176
177static const struct bpf_func_proto bpf_ima_inode_hash_proto = {
178	.func		= bpf_ima_inode_hash,
179	.gpl_only	= false,
180	.might_sleep	= true,
181	.ret_type	= RET_INTEGER,
182	.arg1_type	= ARG_PTR_TO_BTF_ID,
183	.arg1_btf_id	= &bpf_ima_inode_hash_btf_ids[0],
184	.arg2_type	= ARG_PTR_TO_UNINIT_MEM,
185	.arg3_type	= ARG_CONST_SIZE,
186	.allowed	= bpf_ima_inode_hash_allowed,
187};
188
189BPF_CALL_3(bpf_ima_file_hash, struct file *, file, void *, dst, u32, size)
190{
191	return ima_file_hash(file, dst, size);
192}
193
194BTF_ID_LIST_SINGLE(bpf_ima_file_hash_btf_ids, struct, file)
195
196static const struct bpf_func_proto bpf_ima_file_hash_proto = {
197	.func		= bpf_ima_file_hash,
198	.gpl_only	= false,
199	.might_sleep	= true,
200	.ret_type	= RET_INTEGER,
201	.arg1_type	= ARG_PTR_TO_BTF_ID,
202	.arg1_btf_id	= &bpf_ima_file_hash_btf_ids[0],
203	.arg2_type	= ARG_PTR_TO_UNINIT_MEM,
204	.arg3_type	= ARG_CONST_SIZE,
205	.allowed	= bpf_ima_inode_hash_allowed,
206};
207
208BPF_CALL_1(bpf_get_attach_cookie, void *, ctx)
209{
210	struct bpf_trace_run_ctx *run_ctx;
211
212	run_ctx = container_of(current->bpf_ctx, struct bpf_trace_run_ctx, run_ctx);
213	return run_ctx->bpf_cookie;
214}
215
216static const struct bpf_func_proto bpf_get_attach_cookie_proto = {
217	.func		= bpf_get_attach_cookie,
218	.gpl_only	= false,
219	.ret_type	= RET_INTEGER,
220	.arg1_type	= ARG_PTR_TO_CTX,
221};
222
223static const struct bpf_func_proto *
224bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
225{
226	const struct bpf_func_proto *func_proto;
227
228	if (prog->expected_attach_type == BPF_LSM_CGROUP) {
229		func_proto = cgroup_common_func_proto(func_id, prog);
230		if (func_proto)
231			return func_proto;
232	}
233
234	switch (func_id) {
235	case BPF_FUNC_inode_storage_get:
236		return &bpf_inode_storage_get_proto;
237	case BPF_FUNC_inode_storage_delete:
238		return &bpf_inode_storage_delete_proto;
239#ifdef CONFIG_NET
240	case BPF_FUNC_sk_storage_get:
241		return &bpf_sk_storage_get_proto;
242	case BPF_FUNC_sk_storage_delete:
243		return &bpf_sk_storage_delete_proto;
244#endif /* CONFIG_NET */
245	case BPF_FUNC_spin_lock:
246		return &bpf_spin_lock_proto;
247	case BPF_FUNC_spin_unlock:
248		return &bpf_spin_unlock_proto;
249	case BPF_FUNC_bprm_opts_set:
250		return &bpf_bprm_opts_set_proto;
251	case BPF_FUNC_ima_inode_hash:
252		return &bpf_ima_inode_hash_proto;
253	case BPF_FUNC_ima_file_hash:
254		return &bpf_ima_file_hash_proto;
255	case BPF_FUNC_get_attach_cookie:
256		return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto : NULL;
257#ifdef CONFIG_NET
258	case BPF_FUNC_setsockopt:
259		if (prog->expected_attach_type != BPF_LSM_CGROUP)
260			return NULL;
261		if (btf_id_set_contains(&bpf_lsm_locked_sockopt_hooks,
262					prog->aux->attach_btf_id))
263			return &bpf_sk_setsockopt_proto;
264		if (btf_id_set_contains(&bpf_lsm_unlocked_sockopt_hooks,
265					prog->aux->attach_btf_id))
266			return &bpf_unlocked_sk_setsockopt_proto;
267		return NULL;
268	case BPF_FUNC_getsockopt:
269		if (prog->expected_attach_type != BPF_LSM_CGROUP)
270			return NULL;
271		if (btf_id_set_contains(&bpf_lsm_locked_sockopt_hooks,
272					prog->aux->attach_btf_id))
273			return &bpf_sk_getsockopt_proto;
274		if (btf_id_set_contains(&bpf_lsm_unlocked_sockopt_hooks,
275					prog->aux->attach_btf_id))
276			return &bpf_unlocked_sk_getsockopt_proto;
277		return NULL;
278#endif
279	default:
280		return tracing_prog_func_proto(func_id, prog);
281	}
282}
283
284/* The set of hooks which are called without pagefaults disabled and are allowed
285 * to "sleep" and thus can be used for sleepable BPF programs.
286 */
287BTF_SET_START(sleepable_lsm_hooks)
288BTF_ID(func, bpf_lsm_bpf)
289BTF_ID(func, bpf_lsm_bpf_map)
290BTF_ID(func, bpf_lsm_bpf_map_create)
291BTF_ID(func, bpf_lsm_bpf_map_free)
292BTF_ID(func, bpf_lsm_bpf_prog)
293BTF_ID(func, bpf_lsm_bpf_prog_load)
294BTF_ID(func, bpf_lsm_bpf_prog_free)
295BTF_ID(func, bpf_lsm_bpf_token_create)
296BTF_ID(func, bpf_lsm_bpf_token_free)
297BTF_ID(func, bpf_lsm_bpf_token_cmd)
298BTF_ID(func, bpf_lsm_bpf_token_capable)
299BTF_ID(func, bpf_lsm_bprm_check_security)
300BTF_ID(func, bpf_lsm_bprm_committed_creds)
301BTF_ID(func, bpf_lsm_bprm_committing_creds)
302BTF_ID(func, bpf_lsm_bprm_creds_for_exec)
303BTF_ID(func, bpf_lsm_bprm_creds_from_file)
304BTF_ID(func, bpf_lsm_capget)
305BTF_ID(func, bpf_lsm_capset)
306BTF_ID(func, bpf_lsm_cred_prepare)
307BTF_ID(func, bpf_lsm_file_ioctl)
308BTF_ID(func, bpf_lsm_file_lock)
309BTF_ID(func, bpf_lsm_file_open)
310BTF_ID(func, bpf_lsm_file_post_open)
311BTF_ID(func, bpf_lsm_file_receive)
312
313BTF_ID(func, bpf_lsm_inode_create)
314BTF_ID(func, bpf_lsm_inode_free_security)
315BTF_ID(func, bpf_lsm_inode_getattr)
316BTF_ID(func, bpf_lsm_inode_getxattr)
317BTF_ID(func, bpf_lsm_inode_mknod)
318BTF_ID(func, bpf_lsm_inode_need_killpriv)
319BTF_ID(func, bpf_lsm_inode_post_setxattr)
320BTF_ID(func, bpf_lsm_inode_post_removexattr)
321BTF_ID(func, bpf_lsm_inode_readlink)
322BTF_ID(func, bpf_lsm_inode_removexattr)
323BTF_ID(func, bpf_lsm_inode_rename)
324BTF_ID(func, bpf_lsm_inode_rmdir)
325BTF_ID(func, bpf_lsm_inode_setattr)
326BTF_ID(func, bpf_lsm_inode_setxattr)
327BTF_ID(func, bpf_lsm_inode_symlink)
328BTF_ID(func, bpf_lsm_inode_unlink)
329BTF_ID(func, bpf_lsm_kernel_module_request)
330BTF_ID(func, bpf_lsm_kernel_read_file)
331BTF_ID(func, bpf_lsm_kernfs_init_security)
332
333#ifdef CONFIG_SECURITY_PATH
334BTF_ID(func, bpf_lsm_path_unlink)
335BTF_ID(func, bpf_lsm_path_mkdir)
336BTF_ID(func, bpf_lsm_path_rmdir)
337BTF_ID(func, bpf_lsm_path_truncate)
338BTF_ID(func, bpf_lsm_path_symlink)
339BTF_ID(func, bpf_lsm_path_link)
340BTF_ID(func, bpf_lsm_path_rename)
341BTF_ID(func, bpf_lsm_path_chmod)
342BTF_ID(func, bpf_lsm_path_chown)
343#endif /* CONFIG_SECURITY_PATH */
344
345BTF_ID(func, bpf_lsm_mmap_file)
346BTF_ID(func, bpf_lsm_netlink_send)
347BTF_ID(func, bpf_lsm_path_notify)
348BTF_ID(func, bpf_lsm_release_secctx)
349BTF_ID(func, bpf_lsm_sb_alloc_security)
350BTF_ID(func, bpf_lsm_sb_eat_lsm_opts)
351BTF_ID(func, bpf_lsm_sb_kern_mount)
352BTF_ID(func, bpf_lsm_sb_mount)
353BTF_ID(func, bpf_lsm_sb_remount)
354BTF_ID(func, bpf_lsm_sb_set_mnt_opts)
355BTF_ID(func, bpf_lsm_sb_show_options)
356BTF_ID(func, bpf_lsm_sb_statfs)
357BTF_ID(func, bpf_lsm_sb_umount)
358BTF_ID(func, bpf_lsm_settime)
359
360#ifdef CONFIG_SECURITY_NETWORK
361BTF_ID(func, bpf_lsm_inet_conn_established)
362
363BTF_ID(func, bpf_lsm_socket_accept)
364BTF_ID(func, bpf_lsm_socket_bind)
365BTF_ID(func, bpf_lsm_socket_connect)
366BTF_ID(func, bpf_lsm_socket_create)
367BTF_ID(func, bpf_lsm_socket_getpeername)
368BTF_ID(func, bpf_lsm_socket_getpeersec_dgram)
369BTF_ID(func, bpf_lsm_socket_getsockname)
370BTF_ID(func, bpf_lsm_socket_getsockopt)
371BTF_ID(func, bpf_lsm_socket_listen)
372BTF_ID(func, bpf_lsm_socket_post_create)
373BTF_ID(func, bpf_lsm_socket_recvmsg)
374BTF_ID(func, bpf_lsm_socket_sendmsg)
375BTF_ID(func, bpf_lsm_socket_shutdown)
376BTF_ID(func, bpf_lsm_socket_socketpair)
377#endif /* CONFIG_SECURITY_NETWORK */
378
379BTF_ID(func, bpf_lsm_syslog)
380BTF_ID(func, bpf_lsm_task_alloc)
381BTF_ID(func, bpf_lsm_task_prctl)
382BTF_ID(func, bpf_lsm_task_setscheduler)
383BTF_ID(func, bpf_lsm_task_to_inode)
384BTF_ID(func, bpf_lsm_userns_create)
385BTF_SET_END(sleepable_lsm_hooks)
386
387BTF_SET_START(untrusted_lsm_hooks)
388BTF_ID(func, bpf_lsm_bpf_map_free)
389BTF_ID(func, bpf_lsm_bpf_prog_free)
390BTF_ID(func, bpf_lsm_file_alloc_security)
391BTF_ID(func, bpf_lsm_file_free_security)
392#ifdef CONFIG_SECURITY_NETWORK
393BTF_ID(func, bpf_lsm_sk_alloc_security)
394BTF_ID(func, bpf_lsm_sk_free_security)
395#endif /* CONFIG_SECURITY_NETWORK */
396BTF_ID(func, bpf_lsm_task_free)
397BTF_SET_END(untrusted_lsm_hooks)
398
399bool bpf_lsm_is_sleepable_hook(u32 btf_id)
400{
401	return btf_id_set_contains(&sleepable_lsm_hooks, btf_id);
402}
403
404bool bpf_lsm_is_trusted(const struct bpf_prog *prog)
405{
406	return !btf_id_set_contains(&untrusted_lsm_hooks, prog->aux->attach_btf_id);
407}
408
409const struct bpf_prog_ops lsm_prog_ops = {
410};
411
412const struct bpf_verifier_ops lsm_verifier_ops = {
413	.get_func_proto = bpf_lsm_func_proto,
414	.is_valid_access = btf_ctx_access,
415};
416
417/* hooks return 0 or 1 */
418BTF_SET_START(bool_lsm_hooks)
419#ifdef CONFIG_SECURITY_NETWORK_XFRM
420BTF_ID(func, bpf_lsm_xfrm_state_pol_flow_match)
421#endif
422#ifdef CONFIG_AUDIT
423BTF_ID(func, bpf_lsm_audit_rule_known)
424#endif
425BTF_ID(func, bpf_lsm_inode_xattr_skipcap)
426BTF_SET_END(bool_lsm_hooks)
427
428int bpf_lsm_get_retval_range(const struct bpf_prog *prog,
429			     struct bpf_retval_range *retval_range)
430{
431	/* no return value range for void hooks */
432	if (!prog->aux->attach_func_proto->type)
433		return -EINVAL;
434
435	if (btf_id_set_contains(&bool_lsm_hooks, prog->aux->attach_btf_id)) {
436		retval_range->minval = 0;
437		retval_range->maxval = 1;
438	} else {
439		/* All other available LSM hooks, except task_prctl, return 0
440		 * on success and negative error code on failure.
441		 * To keep things simple, we only allow bpf progs to return 0
442		 * or negative errno for task_prctl too.
443		 */
444		retval_range->minval = -MAX_ERRNO;
445		retval_range->maxval = 0;
446	}
447	return 0;
448}
~/ Read-only file preview.