Skip to content

Commit 082f1db

Browse files
Blaise BoscaccyAlexei Starovoitov
authored andcommitted
security: Propagate caller information in bpf hooks
Certain bpf syscall subcommands are available for usage from both userspace and the kernel. LSM modules or eBPF gatekeeper programs may need to take a different course of action depending on whether or not a BPF syscall originated from the kernel or userspace. Additionally, some of the bpf_attr struct fields contain pointers to arbitrary memory. Currently the functionality to determine whether or not a pointer refers to kernel memory or userspace memory is exposed to the bpf verifier, but that information is missing from various LSM hooks. Here we augment the LSM hooks to provide this data, by simply passing a boolean flag indicating whether or not the call originated in the kernel, in any hook that contains a bpf_attr struct that corresponds to a subcommand that may be called from the kernel. Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com> Acked-by: Song Liu <song@kernel.org> Acked-by: Paul Moore <paul@paul-moore.com> Link: https://lore.kernel.org/r/20250310221737.821889-2-bboscaccy@linux.microsoft.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent a03d375 commit 082f1db

File tree

12 files changed

+37
-33
lines changed

12 files changed

+37
-33
lines changed

include/linux/lsm_hook_defs.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,14 +426,14 @@ LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule)
426426
#endif /* CONFIG_AUDIT */
427427

428428
#ifdef CONFIG_BPF_SYSCALL
429-
LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size)
429+
LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
430430
LSM_HOOK(int, 0, bpf_map, struct bpf_map *map, fmode_t fmode)
431431
LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog)
432432
LSM_HOOK(int, 0, bpf_map_create, struct bpf_map *map, union bpf_attr *attr,
433-
struct bpf_token *token)
433+
struct bpf_token *token, bool kernel)
434434
LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map)
435435
LSM_HOOK(int, 0, bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr,
436-
struct bpf_token *token)
436+
struct bpf_token *token, bool kernel)
437437
LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog)
438438
LSM_HOOK(int, 0, bpf_token_create, struct bpf_token *token, union bpf_attr *attr,
439439
const struct path *path)

include/linux/security.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,14 +2249,14 @@ struct bpf_map;
22492249
struct bpf_prog;
22502250
struct bpf_token;
22512251
#ifdef CONFIG_SECURITY
2252-
extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size);
2252+
extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size, bool kernel);
22532253
extern int security_bpf_map(struct bpf_map *map, fmode_t fmode);
22542254
extern int security_bpf_prog(struct bpf_prog *prog);
22552255
extern int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
2256-
struct bpf_token *token);
2256+
struct bpf_token *token, bool kernel);
22572257
extern void security_bpf_map_free(struct bpf_map *map);
22582258
extern int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
2259-
struct bpf_token *token);
2259+
struct bpf_token *token, bool kernel);
22602260
extern void security_bpf_prog_free(struct bpf_prog *prog);
22612261
extern int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
22622262
const struct path *path);
@@ -2265,7 +2265,7 @@ extern int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cm
22652265
extern int security_bpf_token_capable(const struct bpf_token *token, int cap);
22662266
#else
22672267
static inline int security_bpf(int cmd, union bpf_attr *attr,
2268-
unsigned int size)
2268+
unsigned int size, bool kernel)
22692269
{
22702270
return 0;
22712271
}
@@ -2281,7 +2281,7 @@ static inline int security_bpf_prog(struct bpf_prog *prog)
22812281
}
22822282

22832283
static inline int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
2284-
struct bpf_token *token)
2284+
struct bpf_token *token, bool kernel)
22852285
{
22862286
return 0;
22872287
}
@@ -2290,7 +2290,7 @@ static inline void security_bpf_map_free(struct bpf_map *map)
22902290
{ }
22912291

22922292
static inline int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
2293-
struct bpf_token *token)
2293+
struct bpf_token *token, bool kernel)
22942294
{
22952295
return 0;
22962296
}

kernel/bpf/syscall.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,7 @@ static bool bpf_net_capable(void)
13151315

13161316
#define BPF_MAP_CREATE_LAST_FIELD map_token_fd
13171317
/* called via syscall */
1318-
static int map_create(union bpf_attr *attr)
1318+
static int map_create(union bpf_attr *attr, bool kernel)
13191319
{
13201320
const struct bpf_map_ops *ops;
13211321
struct bpf_token *token = NULL;
@@ -1505,7 +1505,7 @@ static int map_create(union bpf_attr *attr)
15051505
attr->btf_vmlinux_value_type_id;
15061506
}
15071507

1508-
err = security_bpf_map_create(map, attr, token);
1508+
err = security_bpf_map_create(map, attr, token, kernel);
15091509
if (err)
15101510
goto free_map_sec;
15111511

@@ -2942,7 +2942,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
29422942
if (err < 0)
29432943
goto free_prog;
29442944

2945-
err = security_bpf_prog_load(prog, attr, token);
2945+
err = security_bpf_prog_load(prog, attr, token, uattr.is_kernel);
29462946
if (err)
29472947
goto free_prog_sec;
29482948

@@ -5767,13 +5767,13 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
57675767
if (copy_from_bpfptr(&attr, uattr, size) != 0)
57685768
return -EFAULT;
57695769

5770-
err = security_bpf(cmd, &attr, size);
5770+
err = security_bpf(cmd, &attr, size, uattr.is_kernel);
57715771
if (err < 0)
57725772
return err;
57735773

57745774
switch (cmd) {
57755775
case BPF_MAP_CREATE:
5776-
err = map_create(&attr);
5776+
err = map_create(&attr, uattr.is_kernel);
57775777
break;
57785778
case BPF_MAP_LOOKUP_ELEM:
57795779
err = map_lookup_elem(&attr);

security/security.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5627,16 +5627,17 @@ int security_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op,
56275627
* @cmd: command
56285628
* @attr: bpf attribute
56295629
* @size: size
5630+
* @kernel: whether or not call originated from kernel
56305631
*
56315632
* Do a initial check for all bpf syscalls after the attribute is copied into
56325633
* the kernel. The actual security module can implement their own rules to
56335634
* check the specific cmd they need.
56345635
*
56355636
* Return: Returns 0 if permission is granted.
56365637
*/
5637-
int security_bpf(int cmd, union bpf_attr *attr, unsigned int size)
5638+
int security_bpf(int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
56385639
{
5639-
return call_int_hook(bpf, cmd, attr, size);
5640+
return call_int_hook(bpf, cmd, attr, size, kernel);
56405641
}
56415642

56425643
/**
@@ -5673,23 +5674,25 @@ int security_bpf_prog(struct bpf_prog *prog)
56735674
* @map: BPF map object
56745675
* @attr: BPF syscall attributes used to create BPF map
56755676
* @token: BPF token used to grant user access
5677+
* @kernel: whether or not call originated from kernel
56765678
*
56775679
* Do a check when the kernel creates a new BPF map. This is also the
56785680
* point where LSM blob is allocated for LSMs that need them.
56795681
*
56805682
* Return: Returns 0 on success, error on failure.
56815683
*/
56825684
int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
5683-
struct bpf_token *token)
5685+
struct bpf_token *token, bool kernel)
56845686
{
5685-
return call_int_hook(bpf_map_create, map, attr, token);
5687+
return call_int_hook(bpf_map_create, map, attr, token, kernel);
56865688
}
56875689

56885690
/**
56895691
* security_bpf_prog_load() - Check if loading of BPF program is allowed
56905692
* @prog: BPF program object
56915693
* @attr: BPF syscall attributes used to create BPF program
56925694
* @token: BPF token used to grant user access to BPF subsystem
5695+
* @kernel: whether or not call originated from kernel
56935696
*
56945697
* Perform an access control check when the kernel loads a BPF program and
56955698
* allocates associated BPF program object. This hook is also responsible for
@@ -5698,9 +5701,9 @@ int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
56985701
* Return: Returns 0 on success, error on failure.
56995702
*/
57005703
int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
5701-
struct bpf_token *token)
5704+
struct bpf_token *token, bool kernel)
57025705
{
5703-
return call_int_hook(bpf_prog_load, prog, attr, token);
5706+
return call_int_hook(bpf_prog_load, prog, attr, token, kernel);
57045707
}
57055708

57065709
/**

security/selinux/hooks.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6866,7 +6866,7 @@ static int selinux_ib_alloc_security(void *ib_sec)
68666866

68676867
#ifdef CONFIG_BPF_SYSCALL
68686868
static int selinux_bpf(int cmd, union bpf_attr *attr,
6869-
unsigned int size)
6869+
unsigned int size, bool kernel)
68706870
{
68716871
u32 sid = current_sid();
68726872
int ret;
@@ -6953,7 +6953,7 @@ static int selinux_bpf_prog(struct bpf_prog *prog)
69536953
}
69546954

69556955
static int selinux_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
6956-
struct bpf_token *token)
6956+
struct bpf_token *token, bool kernel)
69576957
{
69586958
struct bpf_security_struct *bpfsec;
69596959

@@ -6976,7 +6976,7 @@ static void selinux_bpf_map_free(struct bpf_map *map)
69766976
}
69776977

69786978
static int selinux_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
6979-
struct bpf_token *token)
6979+
struct bpf_token *token, bool kernel)
69806980
{
69816981
struct bpf_security_struct *bpfsec;
69826982

tools/testing/selftests/bpf/progs/rcu_read_lock.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ int inproper_sleepable_helper(void *ctx)
242242
}
243243

244244
SEC("?lsm.s/bpf")
245-
int BPF_PROG(inproper_sleepable_kfunc, int cmd, union bpf_attr *attr, unsigned int size)
245+
int BPF_PROG(inproper_sleepable_kfunc, int cmd, union bpf_attr *attr, unsigned int size,
246+
bool kernel)
246247
{
247248
struct bpf_key *bkey;
248249

tools/testing/selftests/bpf/progs/test_cgroup1_hierarchy.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ static int bpf_link_create_verify(int cmd)
5151
}
5252

5353
SEC("lsm/bpf")
54-
int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size)
54+
int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
5555
{
5656
return bpf_link_create_verify(cmd);
5757
}
5858

5959
SEC("lsm.s/bpf")
60-
int BPF_PROG(lsm_s_run, int cmd, union bpf_attr *attr, unsigned int size)
60+
int BPF_PROG(lsm_s_run, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
6161
{
6262
return bpf_link_create_verify(cmd);
6363
}

tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ char _license[] SEC("license") = "GPL";
3636

3737
SEC("?lsm.s/bpf")
3838
__failure __msg("cannot pass in dynptr at an offset=-8")
39-
int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size)
39+
int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
4040
{
4141
unsigned long val;
4242

@@ -46,7 +46,7 @@ int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size)
4646

4747
SEC("?lsm.s/bpf")
4848
__failure __msg("arg#0 expected pointer to stack or const struct bpf_dynptr")
49-
int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size)
49+
int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
5050
{
5151
unsigned long val = 0;
5252

@@ -55,7 +55,7 @@ int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size)
5555
}
5656

5757
SEC("lsm.s/bpf")
58-
int BPF_PROG(dynptr_data_null, int cmd, union bpf_attr *attr, unsigned int size)
58+
int BPF_PROG(dynptr_data_null, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
5959
{
6060
struct bpf_key *trusted_keyring;
6161
struct bpf_dynptr ptr;

tools/testing/selftests/bpf/progs/test_lookup_key.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ extern struct bpf_key *bpf_lookup_system_key(__u64 id) __ksym;
2323
extern void bpf_key_put(struct bpf_key *key) __ksym;
2424

2525
SEC("lsm.s/bpf")
26-
int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size)
26+
int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
2727
{
2828
struct bpf_key *bkey;
2929
__u32 pid;

tools/testing/selftests/bpf/progs/test_ptr_untrusted.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
char tp_name[128];
88

99
SEC("lsm.s/bpf")
10-
int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size)
10+
int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
1111
{
1212
switch (cmd) {
1313
case BPF_RAW_TRACEPOINT_OPEN:

0 commit comments

Comments
 (0)