Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/kernel/bpf/bpf_lsm.c
49884 views
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, ...) \
24
noinline 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)
33
BTF_SET_START(bpf_lsm_hooks)
34
#include <linux/lsm_hook_defs.h>
35
#undef LSM_HOOK
36
BTF_SET_END(bpf_lsm_hooks)
37
38
BTF_SET_START(bpf_lsm_disabled_hooks)
39
BTF_ID(func, bpf_lsm_vm_enough_memory)
40
BTF_ID(func, bpf_lsm_inode_need_killpriv)
41
BTF_ID(func, bpf_lsm_inode_getsecurity)
42
BTF_ID(func, bpf_lsm_inode_listsecurity)
43
BTF_ID(func, bpf_lsm_inode_copy_up_xattr)
44
BTF_ID(func, bpf_lsm_getselfattr)
45
BTF_ID(func, bpf_lsm_getprocattr)
46
BTF_ID(func, bpf_lsm_setprocattr)
47
#ifdef CONFIG_KEYS
48
BTF_ID(func, bpf_lsm_key_getsecurity)
49
#endif
50
#ifdef CONFIG_AUDIT
51
BTF_ID(func, bpf_lsm_audit_rule_match)
52
#endif
53
BTF_ID(func, bpf_lsm_ismaclabel)
54
BTF_ID(func, bpf_lsm_file_alloc_security)
55
BTF_SET_END(bpf_lsm_disabled_hooks)
56
57
/* List of LSM hooks that should operate on 'current' cgroup regardless
58
* of function signature.
59
*/
60
BTF_SET_START(bpf_lsm_current_hooks)
61
/* operate on freshly allocated sk without any cgroup association */
62
#ifdef CONFIG_SECURITY_NETWORK
63
BTF_ID(func, bpf_lsm_sk_alloc_security)
64
BTF_ID(func, bpf_lsm_sk_free_security)
65
#endif
66
BTF_SET_END(bpf_lsm_current_hooks)
67
68
/* List of LSM hooks that trigger while the socket is properly locked.
69
*/
70
BTF_SET_START(bpf_lsm_locked_sockopt_hooks)
71
#ifdef CONFIG_SECURITY_NETWORK
72
BTF_ID(func, bpf_lsm_sock_graft)
73
BTF_ID(func, bpf_lsm_inet_csk_clone)
74
BTF_ID(func, bpf_lsm_inet_conn_established)
75
#endif
76
BTF_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
*/
82
BTF_SET_START(bpf_lsm_unlocked_sockopt_hooks)
83
#ifdef CONFIG_SECURITY_NETWORK
84
BTF_ID(func, bpf_lsm_socket_post_create)
85
BTF_ID(func, bpf_lsm_socket_socketpair)
86
#endif
87
BTF_SET_END(bpf_lsm_unlocked_sockopt_hooks)
88
89
#ifdef CONFIG_CGROUP_BPF
90
void 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
115
int 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
145
BPF_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
154
BTF_ID_LIST_SINGLE(bpf_bprm_opts_set_btf_ids, struct, linux_binprm)
155
156
static 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
165
BPF_CALL_3(bpf_ima_inode_hash, struct inode *, inode, void *, dst, u32, size)
166
{
167
return ima_inode_hash(inode, dst, size);
168
}
169
170
static 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
175
BTF_ID_LIST_SINGLE(bpf_ima_inode_hash_btf_ids, struct, inode)
176
177
static 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
189
BPF_CALL_3(bpf_ima_file_hash, struct file *, file, void *, dst, u32, size)
190
{
191
return ima_file_hash(file, dst, size);
192
}
193
194
BTF_ID_LIST_SINGLE(bpf_ima_file_hash_btf_ids, struct, file)
195
196
static 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
208
BPF_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
216
static 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
223
static const struct bpf_func_proto *
224
bpf_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
*/
287
BTF_SET_START(sleepable_lsm_hooks)
288
BTF_ID(func, bpf_lsm_bpf)
289
BTF_ID(func, bpf_lsm_bpf_map)
290
BTF_ID(func, bpf_lsm_bpf_map_create)
291
BTF_ID(func, bpf_lsm_bpf_map_free)
292
BTF_ID(func, bpf_lsm_bpf_prog)
293
BTF_ID(func, bpf_lsm_bpf_prog_load)
294
BTF_ID(func, bpf_lsm_bpf_prog_free)
295
BTF_ID(func, bpf_lsm_bpf_token_create)
296
BTF_ID(func, bpf_lsm_bpf_token_free)
297
BTF_ID(func, bpf_lsm_bpf_token_cmd)
298
BTF_ID(func, bpf_lsm_bpf_token_capable)
299
BTF_ID(func, bpf_lsm_bprm_check_security)
300
BTF_ID(func, bpf_lsm_bprm_committed_creds)
301
BTF_ID(func, bpf_lsm_bprm_committing_creds)
302
BTF_ID(func, bpf_lsm_bprm_creds_for_exec)
303
BTF_ID(func, bpf_lsm_bprm_creds_from_file)
304
BTF_ID(func, bpf_lsm_capget)
305
BTF_ID(func, bpf_lsm_capset)
306
BTF_ID(func, bpf_lsm_cred_prepare)
307
BTF_ID(func, bpf_lsm_file_ioctl)
308
BTF_ID(func, bpf_lsm_file_lock)
309
BTF_ID(func, bpf_lsm_file_open)
310
BTF_ID(func, bpf_lsm_file_post_open)
311
BTF_ID(func, bpf_lsm_file_receive)
312
313
BTF_ID(func, bpf_lsm_inode_create)
314
BTF_ID(func, bpf_lsm_inode_free_security)
315
BTF_ID(func, bpf_lsm_inode_getattr)
316
BTF_ID(func, bpf_lsm_inode_getxattr)
317
BTF_ID(func, bpf_lsm_inode_mknod)
318
BTF_ID(func, bpf_lsm_inode_need_killpriv)
319
BTF_ID(func, bpf_lsm_inode_post_setxattr)
320
BTF_ID(func, bpf_lsm_inode_post_removexattr)
321
BTF_ID(func, bpf_lsm_inode_readlink)
322
BTF_ID(func, bpf_lsm_inode_removexattr)
323
BTF_ID(func, bpf_lsm_inode_rename)
324
BTF_ID(func, bpf_lsm_inode_rmdir)
325
BTF_ID(func, bpf_lsm_inode_setattr)
326
BTF_ID(func, bpf_lsm_inode_setxattr)
327
BTF_ID(func, bpf_lsm_inode_symlink)
328
BTF_ID(func, bpf_lsm_inode_unlink)
329
BTF_ID(func, bpf_lsm_kernel_module_request)
330
BTF_ID(func, bpf_lsm_kernel_read_file)
331
BTF_ID(func, bpf_lsm_kernfs_init_security)
332
333
#ifdef CONFIG_SECURITY_PATH
334
BTF_ID(func, bpf_lsm_path_unlink)
335
BTF_ID(func, bpf_lsm_path_mkdir)
336
BTF_ID(func, bpf_lsm_path_rmdir)
337
BTF_ID(func, bpf_lsm_path_truncate)
338
BTF_ID(func, bpf_lsm_path_symlink)
339
BTF_ID(func, bpf_lsm_path_link)
340
BTF_ID(func, bpf_lsm_path_rename)
341
BTF_ID(func, bpf_lsm_path_chmod)
342
BTF_ID(func, bpf_lsm_path_chown)
343
#endif /* CONFIG_SECURITY_PATH */
344
345
BTF_ID(func, bpf_lsm_mmap_file)
346
BTF_ID(func, bpf_lsm_netlink_send)
347
BTF_ID(func, bpf_lsm_path_notify)
348
BTF_ID(func, bpf_lsm_release_secctx)
349
BTF_ID(func, bpf_lsm_sb_alloc_security)
350
BTF_ID(func, bpf_lsm_sb_eat_lsm_opts)
351
BTF_ID(func, bpf_lsm_sb_kern_mount)
352
BTF_ID(func, bpf_lsm_sb_mount)
353
BTF_ID(func, bpf_lsm_sb_remount)
354
BTF_ID(func, bpf_lsm_sb_set_mnt_opts)
355
BTF_ID(func, bpf_lsm_sb_show_options)
356
BTF_ID(func, bpf_lsm_sb_statfs)
357
BTF_ID(func, bpf_lsm_sb_umount)
358
BTF_ID(func, bpf_lsm_settime)
359
360
#ifdef CONFIG_SECURITY_NETWORK
361
BTF_ID(func, bpf_lsm_inet_conn_established)
362
363
BTF_ID(func, bpf_lsm_socket_accept)
364
BTF_ID(func, bpf_lsm_socket_bind)
365
BTF_ID(func, bpf_lsm_socket_connect)
366
BTF_ID(func, bpf_lsm_socket_create)
367
BTF_ID(func, bpf_lsm_socket_getpeername)
368
BTF_ID(func, bpf_lsm_socket_getpeersec_dgram)
369
BTF_ID(func, bpf_lsm_socket_getsockname)
370
BTF_ID(func, bpf_lsm_socket_getsockopt)
371
BTF_ID(func, bpf_lsm_socket_listen)
372
BTF_ID(func, bpf_lsm_socket_post_create)
373
BTF_ID(func, bpf_lsm_socket_recvmsg)
374
BTF_ID(func, bpf_lsm_socket_sendmsg)
375
BTF_ID(func, bpf_lsm_socket_shutdown)
376
BTF_ID(func, bpf_lsm_socket_socketpair)
377
#endif /* CONFIG_SECURITY_NETWORK */
378
379
BTF_ID(func, bpf_lsm_syslog)
380
BTF_ID(func, bpf_lsm_task_alloc)
381
BTF_ID(func, bpf_lsm_task_prctl)
382
BTF_ID(func, bpf_lsm_task_setscheduler)
383
BTF_ID(func, bpf_lsm_task_to_inode)
384
BTF_ID(func, bpf_lsm_userns_create)
385
BTF_SET_END(sleepable_lsm_hooks)
386
387
BTF_SET_START(untrusted_lsm_hooks)
388
BTF_ID(func, bpf_lsm_bpf_map_free)
389
BTF_ID(func, bpf_lsm_bpf_prog_free)
390
BTF_ID(func, bpf_lsm_file_alloc_security)
391
BTF_ID(func, bpf_lsm_file_free_security)
392
#ifdef CONFIG_SECURITY_NETWORK
393
BTF_ID(func, bpf_lsm_sk_alloc_security)
394
BTF_ID(func, bpf_lsm_sk_free_security)
395
#endif /* CONFIG_SECURITY_NETWORK */
396
BTF_ID(func, bpf_lsm_task_free)
397
BTF_SET_END(untrusted_lsm_hooks)
398
399
bool bpf_lsm_is_sleepable_hook(u32 btf_id)
400
{
401
return btf_id_set_contains(&sleepable_lsm_hooks, btf_id);
402
}
403
404
bool 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
409
const struct bpf_prog_ops lsm_prog_ops = {
410
};
411
412
const 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 */
418
BTF_SET_START(bool_lsm_hooks)
419
#ifdef CONFIG_SECURITY_NETWORK_XFRM
420
BTF_ID(func, bpf_lsm_xfrm_state_pol_flow_match)
421
#endif
422
#ifdef CONFIG_AUDIT
423
BTF_ID(func, bpf_lsm_audit_rule_known)
424
#endif
425
BTF_ID(func, bpf_lsm_inode_xattr_skipcap)
426
BTF_SET_END(bool_lsm_hooks)
427
428
int 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
}
449
450