From patchwork Wed Oct 18 20:00:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenbo Feng X-Patchwork-Id: 827797 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="qVMMCFkg"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yHNGh2sZlz9sBd for ; Thu, 19 Oct 2017 07:01:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751577AbdJRUA6 (ORCPT ); Wed, 18 Oct 2017 16:00:58 -0400 Received: from mail-io0-f196.google.com ([209.85.223.196]:55671 "EHLO mail-io0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751504AbdJRUAw (ORCPT ); Wed, 18 Oct 2017 16:00:52 -0400 Received: by mail-io0-f196.google.com with SMTP id p186so7505377ioe.12; Wed, 18 Oct 2017 13:00:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xGmstFmirsJRkbpE+6/KzifbhLe8ppo41yh8uS/SIIY=; b=qVMMCFkgLBTLqOv3wj4sCjhDsgv9Q1BelPGVfzQUg1WrOrt9+WwxOqhBOd1OD9DWLa E0zvcyyI6CJKlHX5VZYyonGBzdVaAEEIO4h5XBAbIeV9IDYV7NiuRjHsdZPfBzAQEinH YEKyNMoAi/4DkQRPXioXPKPmCTfxcyXIbrBl1dLhz/s1yPqeQh85dhaWjhoergoq6enR 6BgUNvaGborJbK7HfJSG7OpHuH85pP1V5UUJD9hed/YfUi5gKDoQrRijvRCvAD25e74K H3Qa8R3c4gwy3oWhurxV38g9RWNGqHjAzKWHr+KXQwE9W22zg1f1WYvtUvDqjgVim9OQ HSGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xGmstFmirsJRkbpE+6/KzifbhLe8ppo41yh8uS/SIIY=; b=Phjb4Sn+HI9x3ZqP4bcVi24fXZSoC+ews2TWAH43D6IK31gVjZED2iLUx3/WmG2JzQ iIItG1Yun+Ayjai59D9HCIz1FpUU5LDoghBRZTxhLC+/i+KFKXURzP2izu3LoOvU/Y0G cvd5R8faWgFTR+FHU4d3BXoKQ93QSn47JYrNoFv6fqVWExU06L/n1/pc1/I8pdkOygFn Ek4Z7N0IA5U5WqyE+48O4JTDvR3Th6OaK9yYrBwEcxUA6m4AyyIocIFd4Q5y/cwVj6QU GPtE4k4PdrAZCjEZkB3SOf0tMGOPGzHFlTAJ2gfhUHm/q1i41C4Xki7khse5FZU61gor nVHw== X-Gm-Message-State: AMCzsaVgM/r+5JbQQ7764WanDA1dcGXCVBtulNM4egMsVXOkcAxVROIE s/CVYFYh7L9S0Wx6NsLPI0hTK/ZZ/tg= X-Google-Smtp-Source: AOwi7QAtMSVJGMMno2AlqhA5KfFkb8CjZtRZaodsOxRMn1LXG+3C+36839u2Kx+1AC9N1UP91nQYYA== X-Received: by 10.107.42.10 with SMTP id q10mr24563526ioq.196.1508356851378; Wed, 18 Oct 2017 13:00:51 -0700 (PDT) Received: from fengc.mtv.corp.google.com ([100.98.120.50]) by smtp.gmail.com with ESMTPSA id 78sm3550047ioo.37.2017.10.18.13.00.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Oct 2017 13:00:50 -0700 (PDT) From: Chenbo Feng To: netdev@vger.kernel.org, SELinux , linux-security-module@vger.kernel.org Cc: Jeffrey Vander Stoep , Alexei Starovoitov , lorenzo@google.com, Daniel Borkmann , Stephen Smalley , James Morris , Paul Moore , Chenbo Feng Subject: [PATCH net-next v7 4/5] selinux: bpf: Add selinux check for eBPF syscall operations Date: Wed, 18 Oct 2017 13:00:25 -0700 Message-Id: <20171018200026.146093-5-chenbofeng.kernel@gmail.com> X-Mailer: git-send-email 2.15.0.rc1.287.g2b38de12cc-goog In-Reply-To: <20171018200026.146093-1-chenbofeng.kernel@gmail.com> References: <20171018200026.146093-1-chenbofeng.kernel@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 Acked-by: Paul Moore --- 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", "map_write", "prog_load", "prog_run"} }, { NULL } }; diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 1649cd18eb0b..3d54468ce334 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -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_ */