Skip to content

Commit

Permalink
selinux: bpf: Add selinux check for eBPF syscall operations
Browse files Browse the repository at this point in the history
Implement the actual checks introduced to eBPF related syscalls. This
implementation use the security field inside bpf object to store a sid that
identify the bpf object. And when processes try to access the object,
selinux will check if processes have the right privileges. The creation
of eBPF object are also checked at the general bpf check hook and new
cmd introduced to eBPF domain can also be checked there.

Signed-off-by: Chenbo Feng <[email protected]>
Acked-by: Alexei Starovoitov <[email protected]>
Reviewed-by: James Morris <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Chenbo Feng authored and davem330 committed Oct 20, 2017
1 parent afdb09c commit ec27c35
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
111 changes: 111 additions & 0 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
#include <linux/export.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/bpf.h>

#include "avc.h"
#include "objsec.h"
Expand Down Expand Up @@ -6252,6 +6253,106 @@ static void selinux_ib_free_security(void *ib_sec)
}
#endif

#ifdef CONFIG_BPF_SYSCALL
static int selinux_bpf(int cmd, union bpf_attr *attr,
unsigned int size)
{
u32 sid = current_sid();
int ret;

switch (cmd) {
case BPF_MAP_CREATE:
ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
NULL);
break;
case BPF_PROG_LOAD:
ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
NULL);
break;
default:
ret = 0;
break;
}

return ret;
}

static u32 bpf_map_fmode_to_av(fmode_t fmode)
{
u32 av = 0;

if (fmode & FMODE_READ)
av |= BPF__MAP_READ;
if (fmode & FMODE_WRITE)
av |= BPF__MAP_WRITE;
return av;
}

static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
{
u32 sid = current_sid();
struct bpf_security_struct *bpfsec;

bpfsec = map->security;
return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
bpf_map_fmode_to_av(fmode), NULL);
}

static int selinux_bpf_prog(struct bpf_prog *prog)
{
u32 sid = current_sid();
struct bpf_security_struct *bpfsec;

bpfsec = prog->aux->security;
return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
BPF__PROG_RUN, NULL);
}

static int selinux_bpf_map_alloc(struct bpf_map *map)
{
struct bpf_security_struct *bpfsec;

bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
if (!bpfsec)
return -ENOMEM;

bpfsec->sid = current_sid();
map->security = bpfsec;

return 0;
}

static void selinux_bpf_map_free(struct bpf_map *map)
{
struct bpf_security_struct *bpfsec = map->security;

map->security = NULL;
kfree(bpfsec);
}

static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
{
struct bpf_security_struct *bpfsec;

bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
if (!bpfsec)
return -ENOMEM;

bpfsec->sid = current_sid();
aux->security = bpfsec;

return 0;
}

static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
{
struct bpf_security_struct *bpfsec = aux->security;

aux->security = NULL;
kfree(bpfsec);
}
#endif

static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
Expand Down Expand Up @@ -6471,6 +6572,16 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
#endif

#ifdef CONFIG_BPF_SYSCALL
LSM_HOOK_INIT(bpf, selinux_bpf),
LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
#endif
};

static __init int selinux_init(void)
Expand Down
2 changes: 2 additions & 0 deletions security/selinux/include/classmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ struct security_class_mapping secclass_map[] = {
{ "access", NULL } },
{ "infiniband_endport",
{ "manage_subnet", NULL } },
{ "bpf",
{"map_create", "map_read", "map_write", "prog_load", "prog_run"} },
{ NULL }
};

Expand Down
4 changes: 4 additions & 0 deletions security/selinux/include/objsec.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ struct pkey_security_struct {
u32 sid; /* SID of pkey */
};

struct bpf_security_struct {
u32 sid; /*SID of bpf obj creater*/
};

extern unsigned int selinux_checkreqprot;

#endif /* _SELINUX_OBJSEC_H_ */

0 comments on commit ec27c35

Please sign in to comment.