From patchwork Tue Aug 29 19:04:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 9927965 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3DD836022E for ; Tue, 29 Aug 2017 19:04:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F67428402 for ; Tue, 29 Aug 2017 19:04:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 23A47283BD; Tue, 29 Aug 2017 19:04:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 91E3D283BD for ; Tue, 29 Aug 2017 19:04:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751270AbdH2TEO (ORCPT ); Tue, 29 Aug 2017 15:04:14 -0400 Received: from mail-pg0-f74.google.com ([74.125.83.74]:50158 "EHLO mail-pg0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751186AbdH2TEM (ORCPT ); Tue, 29 Aug 2017 15:04:12 -0400 Received: by mail-pg0-f74.google.com with SMTP id n126so11657509pgn.4 for ; Tue, 29 Aug 2017 12:04:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:date:message-id:subject:from:to:cc; bh=r5d3c+P+bldISvi876lk98xyIGgCV7iZvhruTugLyUM=; b=wChbTf2QvIsI16ibmvxD89yqLdg/xGUE99Ma/1wGfV9aFxRxlHHsTPaFSR2JZhE2/B 6Cy7RQublhm8tpMXrA/ugaa7kGfGhfDoHbaeZRXqCL3/0sTWJUwILs3QsW5GKuts7AHT m+6MZ/7V95W4EyMfRaG6wzpDXNN4yJ3nVqWyfyGvaDJrig1qUiF/6g+VeJznrxfKUxMA NkMqeQOXV/mBIkGNsXHPoPT5TlsXXxs4e9yYMLOakk9DhhpyKGxwt9zIBk1jZwWvWIBQ ZpvK3QS7BNrBHndFShqX/1aPH3/xzMjESJfXHQR/LzCZ9KhMf3wcIKCVmqj8uwovyrpX zPow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:date:message-id:subject:from:to:cc; bh=r5d3c+P+bldISvi876lk98xyIGgCV7iZvhruTugLyUM=; b=F42OcIR1mOn9fOmvu8/XIUdofaXeX9tdALYpzaUvk6tKBYxVJoqGth+n5v90je362W LlonLoyD0tms7OD//KG1fVeXR3mDuplU3crG1XDeHFQsCyHL3zMKh9gXwcDq9fsVULu7 7/4rV82Pn6gz+eDlj5TIm/aSSsoIiViUak7qVbAq9n4498Sff2pCinPRC9Q1S8UsfxZL NNkg/PRglaKQsUI/uuJx30wCUjqfHXSlumPohKK07FHV7f2Jr1O3k2MmsJzfGC+YLdf3 mk4ZKavKU5+81F63rKjRe7O9xDBaE8/UljCyCCTMs9h3WoM+fGnQ4ZjiTQ2n73uH5rsa BnWQ== X-Gm-Message-State: AHYfb5hBZBPrhb29+6djxaIzvk67LcLmAHmiKwDFXw4HSBY7ySu7uXig HgCdcX96P30xDmnlTTajF+DVLSIA+QRB X-Google-Smtp-Source: ADKCNb4mbDJ1zH+8zTLfk8JR5xYJDO42NcfL5+rebLMPTKaK/9WejM1u51gSi+Ew6+ffDpjAh9lzqM9DEKOTZ1KR2dhfBg== MIME-Version: 1.0 X-Received: by 10.99.6.200 with SMTP id 191mr969547pgg.192.1504033451516; Tue, 29 Aug 2017 12:04:11 -0700 (PDT) Date: Tue, 29 Aug 2017 12:04:01 -0700 Message-Id: <20170829190401.18056-1-mjg59@google.com> X-Mailer: git-send-email 2.14.1.342.g6490525c54-goog Subject: [PATCH] RFC: Add Apparmor policy matching to IMA From: Matthew Garrett To: linux-ima-devel@lists.sourceforge.net Cc: linux-security-module@vger.kernel.org, apparmor@lists.ubuntu.com, Matthew Garrett Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP IMA has support for matching based on security context, but this is currently limited to modules that implement the audit_rule_match hook. The infrastructure around this seems to depend on having 32 bit security IDs to reference the policy associated with tasks or files, which doesn't seem to be a concept that Apparmor really has. So, this implementation ignores the abstraction and calls through to Apparmor directly. This seems ugly, so is there a better way to achieve this? --- include/linux/apparmor.h | 16 ++++++++++++++++ security/apparmor/lib.c | 32 ++++++++++++++++++++++++++++++++ security/integrity/ima/ima_policy.c | 24 +++++++++++++++++++++--- 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 include/linux/apparmor.h diff --git a/include/linux/apparmor.h b/include/linux/apparmor.h new file mode 100644 index 000000000000..d8ac3f706437 --- /dev/null +++ b/include/linux/apparmor.h @@ -0,0 +1,16 @@ +#ifndef _APPARMOR_H_ + +struct linux_binprm; + +#ifdef CONFIG_SECURITY_APPARMOR +int aa_task_profile_match(struct linux_binprm *bprm, struct task_struct *tsk, + const char *profile); +#else +static int aa_task_profile_match(struct linux_binprm *bprm, + struct task_struct *tsk, const char *profile) +{ + return 0; +} +#endif + +#endif diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 08ca26bcca77..04d087e4a1a3 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -17,9 +17,11 @@ #include #include #include +#include #include "include/audit.h" #include "include/apparmor.h" +#include "include/context.h" #include "include/lib.h" #include "include/perms.h" #include "include/policy.h" @@ -385,6 +387,36 @@ void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, aa_label_match(profile, label, state, false, request, perms); } +/** + * aa_task_profile_match - check whether a task is using the specified profile + * @bprm - bprm structure to extract creds from. + * @tsk - task to verify. Ignored if @bprm is not NULL. + * @name - name of the profile to search for. + */ +int aa_task_profile_match(struct linux_binprm *bprm, struct task_struct *tsk, + const char *name) +{ + struct aa_label *label; + struct aa_profile *profile; + struct aa_task_ctx *ctx; + struct label_it i; + const struct cred *cred; + + if (bprm) { + ctx = cred_ctx(bprm->cred); + label = aa_get_newest_label(ctx->label); + } else { + cred = __task_cred(tsk); + label = aa_get_newest_cred_label(cred); + } + + label_for_each(i, label, profile) { + if (strcmp(name, profile->base.name) == 0) + return 1; + } + + return 0; +} /* currently unused */ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 93f6af4e3a20..556a1292734c 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "ima.h" @@ -47,9 +48,9 @@ int ima_policy_flag; static int temp_ima_appraise; -#define MAX_LSM_RULES 6 +#define MAX_LSM_RULES 7 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, - LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE + LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE, LSM_AA_PROFILE }; enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB }; @@ -313,6 +314,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, Audit_equal, rule->lsm[i].rule, NULL); + break; + case LSM_AA_PROFILE: + rc = aa_task_profile_match(bprm, tsk, + rule->lsm[i].args_p); + break; default: break; } @@ -527,7 +533,7 @@ enum { Opt_audit, Opt_obj_user, Opt_obj_role, Opt_obj_type, Opt_subj_user, Opt_subj_role, Opt_subj_type, - Opt_func, Opt_mask, Opt_fsmagic, + Opt_aa_profile, Opt_func, Opt_mask, Opt_fsmagic, Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq, Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt, Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, @@ -547,6 +553,7 @@ static match_table_t policy_tokens = { {Opt_subj_user, "subj_user=%s"}, {Opt_subj_role, "subj_role=%s"}, {Opt_subj_type, "subj_type=%s"}, + {Opt_aa_profile, "aa_profile=%s"}, {Opt_func, "func=%s"}, {Opt_mask, "mask=%s"}, {Opt_fsmagic, "fsmagic=%s"}, @@ -847,6 +854,13 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) LSM_SUBJ_TYPE, AUDIT_SUBJ_TYPE); break; + case Opt_aa_profile: + ima_log_string(ab, "aa_profile", args[0].from); + entry->lsm[LSM_AA_PROFILE].args_p = match_strdup(args); + entry->lsm[LSM_AA_PROFILE].rule = 1; + if (!entry->lsm[LSM_AA_PROFILE].args_p) + result = -ENOMEM; + break; case Opt_appraise_type: if (entry->action != APPRAISE) { result = -EINVAL; @@ -1138,6 +1152,10 @@ int ima_policy_show(struct seq_file *m, void *v) seq_printf(m, pt(Opt_subj_type), (char *)entry->lsm[i].args_p); break; + case LSM_AA_PROFILE: + seq_printf(m, pt(Opt_aa_profile), + (char *)entry->lsm[i].args_p); + break; } } }