Re: [PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
On Tue, 2017-10-10 at 10:54 -0700, Chenbo Feng via Selinux wrote: > On Tue, Oct 10, 2017 at 7:52 AM, Stephen Smalley> wrote: > > On Tue, 2017-10-10 at 10:18 -0400, Stephen Smalley wrote: > > > On Mon, 2017-10-09 at 15:20 -0700, Chenbo Feng wrote: > > > > From: Chenbo Feng > > > > > > > > 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 > > > > Acked-by: Alexei Starovoitov > > > > --- > > > > security/selinux/hooks.c| 111 > > > > > > > > security/selinux/include/classmap.h | 2 + > > > > security/selinux/include/objsec.h | 4 ++ > > > > 3 files changed, 117 insertions(+) > > > > > > > > diff --git a/security/selinux/hooks.c > > > > b/security/selinux/hooks.c > > > > index f5d304736852..41aba4e3d57c 100644 > > > > --- a/security/selinux/hooks.c > > > > +++ b/security/selinux/hooks.c > > > > @@ -85,6 +85,7 @@ > > > > #include > > > > #include > > > > #include > > > > +#include > > > > > > > > #include "avc.h" > > > > #include "objsec.h" > > > > @@ -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_MAP, > > > > BPF_MAP__CREATE, > > > > + NULL); > > > > + break; > > > > + case BPF_PROG_LOAD: > > > > + ret = avc_has_perm(sid, sid, SECCLASS_BPF_PROG, > > > > 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 (f_mode & FMODE_READ) > > > > + av |= BPF_MAP__READ; > > > > + if (f_mode & 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_MAP, > > > > + 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_PROG, > > > > + BPF_PROG__USE, 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, > > >
Re: [PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
Hi Chenbo, [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/Chenbo-Feng/bpf-security-New-file-mode-and-LSM-hooks-for-eBPF-object-permission-control/20171011-010349 config: x86_64-randconfig-u0-10110310 (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All warnings (new ones prefixed by >>): In file included from include/linux/init.h:4:0, from security/selinux/hooks.c:27: security/selinux/hooks.c: In function 'bpf_map_fmode_to_av': security/selinux/hooks.c:6284:6: error: 'f_mode' undeclared (first use in this function) if (f_mode & FMODE_READ) ^ include/linux/compiler.h:156:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> security/selinux/hooks.c:6284:2: note: in expansion of macro 'if' if (f_mode & FMODE_READ) ^~ security/selinux/hooks.c:6284:6: note: each undeclared identifier is reported only once for each function it appears in if (f_mode & FMODE_READ) ^ include/linux/compiler.h:156:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> security/selinux/hooks.c:6284:2: note: in expansion of macro 'if' if (f_mode & FMODE_READ) ^~ vim +/if +6284 security/selinux/hooks.c 6279 6280 static u32 bpf_map_fmode_to_av(fmode_t fmode) 6281 { 6282 u32 av = 0; 6283 > 6284 if (f_mode & FMODE_READ) 6285 av |= BPF_MAP__READ; 6286 if (f_mode & FMODE_WRITE) 6287 av |= BPF_MAP__WRITE; 6288 return av; 6289 } 6290 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
Hi Chenbo, [auto build test ERROR on net-next/master] url: https://github.com/0day-ci/linux/commits/Chenbo-Feng/bpf-security-New-file-mode-and-LSM-hooks-for-eBPF-object-permission-control/20171011-010349 config: xtensa-allyesconfig (attached as .config) compiler: xtensa-linux-gcc (GCC) 4.9.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=xtensa All errors (new ones prefixed by >>): security//selinux/hooks.c: In function 'bpf_map_fmode_to_av': >> security//selinux/hooks.c:6284:6: error: 'f_mode' undeclared (first use in >> this function) if (f_mode & FMODE_READ) ^ security//selinux/hooks.c:6284:6: note: each undeclared identifier is reported only once for each function it appears in vim +/f_mode +6284 security//selinux/hooks.c 6279 6280 static u32 bpf_map_fmode_to_av(fmode_t fmode) 6281 { 6282 u32 av = 0; 6283 > 6284 if (f_mode & FMODE_READ) 6285 av |= BPF_MAP__READ; 6286 if (f_mode & FMODE_WRITE) 6287 av |= BPF_MAP__WRITE; 6288 return av; 6289 } 6290 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
On Tue, Oct 10, 2017 at 7:52 AM, Stephen Smalleywrote: > On Tue, 2017-10-10 at 10:18 -0400, Stephen Smalley wrote: >> On Mon, 2017-10-09 at 15:20 -0700, Chenbo Feng wrote: >> > From: Chenbo Feng >> > >> > 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 >> > Acked-by: Alexei Starovoitov >> > --- >> > security/selinux/hooks.c| 111 >> > >> > security/selinux/include/classmap.h | 2 + >> > security/selinux/include/objsec.h | 4 ++ >> > 3 files changed, 117 insertions(+) >> > >> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c >> > index f5d304736852..41aba4e3d57c 100644 >> > --- a/security/selinux/hooks.c >> > +++ b/security/selinux/hooks.c >> > @@ -85,6 +85,7 @@ >> > #include >> > #include >> > #include >> > +#include >> > >> > #include "avc.h" >> > #include "objsec.h" >> > @@ -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_MAP, >> > BPF_MAP__CREATE, >> > + NULL); >> > + break; >> > + case BPF_PROG_LOAD: >> > + ret = avc_has_perm(sid, sid, SECCLASS_BPF_PROG, >> > 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 (f_mode & FMODE_READ) >> > + av |= BPF_MAP__READ; >> > + if (f_mode & 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_MAP, >> > + 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_PROG, >> > + BPF_PROG__USE, 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), >> > @@ -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), >> > +
Re: [PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
On Tue, 2017-10-10 at 10:18 -0400, Stephen Smalley wrote: > On Mon, 2017-10-09 at 15:20 -0700, Chenbo Feng wrote: > > From: Chenbo Feng> > > > 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 > > Acked-by: Alexei Starovoitov > > --- > > security/selinux/hooks.c| 111 > > > > security/selinux/include/classmap.h | 2 + > > security/selinux/include/objsec.h | 4 ++ > > 3 files changed, 117 insertions(+) > > > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > > index f5d304736852..41aba4e3d57c 100644 > > --- a/security/selinux/hooks.c > > +++ b/security/selinux/hooks.c > > @@ -85,6 +85,7 @@ > > #include > > #include > > #include > > +#include > > > > #include "avc.h" > > #include "objsec.h" > > @@ -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_MAP, > > BPF_MAP__CREATE, > > + NULL); > > + break; > > + case BPF_PROG_LOAD: > > + ret = avc_has_perm(sid, sid, SECCLASS_BPF_PROG, > > 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 (f_mode & FMODE_READ) > > + av |= BPF_MAP__READ; > > + if (f_mode & 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_MAP, > > + 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_PROG, > > + BPF_PROG__USE, 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), > > @@ -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), > > +
Re: [PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
On Mon, 2017-10-09 at 15:20 -0700, Chenbo Feng wrote: > From: Chenbo Feng> > 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 > Acked-by: Alexei Starovoitov > --- > security/selinux/hooks.c| 111 > > security/selinux/include/classmap.h | 2 + > security/selinux/include/objsec.h | 4 ++ > 3 files changed, 117 insertions(+) > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > index f5d304736852..41aba4e3d57c 100644 > --- a/security/selinux/hooks.c > +++ b/security/selinux/hooks.c > @@ -85,6 +85,7 @@ > #include > #include > #include > +#include > > #include "avc.h" > #include "objsec.h" > @@ -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_MAP, > BPF_MAP__CREATE, > + NULL); > + break; > + case BPF_PROG_LOAD: > + ret = avc_has_perm(sid, sid, SECCLASS_BPF_PROG, > 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 (f_mode & FMODE_READ) > + av |= BPF_MAP__READ; > + if (f_mode & 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_MAP, > + 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_PROG, > + BPF_PROG__USE, 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), > @@ -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) > diff --git a/security/selinux/include/classmap.h > b/security/selinux/include/classmap.h > index 35ffb29a69cb..7253c5eea59c 100644 > ---
[PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
From: Chenbo FengImplement 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 Acked-by: Alexei Starovoitov --- security/selinux/hooks.c| 111 security/selinux/include/classmap.h | 2 + security/selinux/include/objsec.h | 4 ++ 3 files changed, 117 insertions(+) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f5d304736852..41aba4e3d57c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -85,6 +85,7 @@ #include #include #include +#include #include "avc.h" #include "objsec.h" @@ -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_MAP, BPF_MAP__CREATE, + NULL); + break; + case BPF_PROG_LOAD: + ret = avc_has_perm(sid, sid, SECCLASS_BPF_PROG, 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 (f_mode & FMODE_READ) + av |= BPF_MAP__READ; + if (f_mode & 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_MAP, + 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_PROG, + BPF_PROG__USE, 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), @@ -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) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 35ffb29a69cb..7253c5eea59c 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -237,6 +237,8 @@ struct security_class_mapping secclass_map[] = { { "access", NULL } }, { "infiniband_endport", { "manage_subnet", NULL } }, + { "bpf_map", {"create",