Re: [PATCH net-next v7 4/5] selinux: bpf: Add selinux check for eBPF syscall operations

2017-10-23 Thread Paul Moore
On Wed, Oct 18, 2017 at 4:00 PM, 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(+)

Not sure if DaveM has merged this into net-next yet, but it looks
reasonable to me.

Acked-by: Paul Moore 

> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index f5d304736852..12cf7de8cbed 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, 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),
> @@ -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, 

Re: [PATCH net-next v7 4/5] selinux: bpf: Add selinux check for eBPF syscall operations

2017-10-19 Thread James Morris
On Wed, 18 Oct 2017, 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 


Reviewed-by: James Morris 

-- 
James Morris




[PATCH net-next v7 4/5] selinux: bpf: Add selinux check for eBPF syscall operations

2017-10-18 Thread Chenbo Feng
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..12cf7de8cbed 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, 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),
@@ -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..0a7023b5f000 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", "map_read",