Received: by 2002:a25:b794:0:0:0:0:0 with SMTP id n20csp6088479ybh; Wed, 7 Aug 2019 17:08:27 -0700 (PDT) X-Google-Smtp-Source: APXvYqz0DrfviNNvCvUD+V5eKzdbQgAVN33gAN+cmBIcGeuqMUhDZ9cXFuKxTTODpDRLVCSgnEHJ X-Received: by 2002:a62:8c81:: with SMTP id m123mr12072153pfd.240.1565222907618; Wed, 07 Aug 2019 17:08:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565222907; cv=none; d=google.com; s=arc-20160816; b=bBNzVmxIOLaNDH3rOGZ95Qpu6XfibEYYS+TwE3fbITUqwpZKV6em/W7OhBKpp1HMDI o70UFJohJSEksBGCa6Yv2kQ4rjXAxnDLHEuiapYRVgfke3UVkbJW9PNTf3vsw7LlApka Tc5cc8gP9Si3OL+KqZ2Edg5imATeCc3JpTYuAZ9ta/X/eR04yR5NCfvvIbBV8/ruZV1W IxwdASZS+R6hjApa3PqJMinZRtvvu5BfeR/t5ooZjs4I9/qT8A6UrTqvcs47AKoJkeYN GduTdzApr+5LlCuKAmePGWEjZoU8Uf78agSuxGD44qiDuSNRhwHIHRFTpL3hnRwV9LTP SMEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=51dHsz2VCo9w+VP1Zvpve034pgyEZM98AQeW9IXg4Ow=; b=EL1boTEOPBB7lfi4aUHThem9L8OosswN7ggU0MW2QyLq8sos4Yas4BH7PQEmIxdAbh ZLyShBsfbJenNyBjKoxjv9zicow/VbRzBa25TroxpzEPdTrb4PZAuSQIox03EgVk6ze0 adR8e71q/NdL+/cHStkEmK/nvG2YIYh30nyGbmbg7qDTNqFnaVrP7NNW2Tn1Mba7TWvu lF/zT1uREIA2/4UDOmZ0sgbJxvW87FwPS3tRcnz+9eQ52v5lg0oZ7h00FIKYvWf+SsDl pjuDbmxSWZX0XXkgfZcvlEAguqOgLvb8Cy7/cB6dbRnqhDucqgHyL0Z9TM18mt+rGFrU Oa6A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=qaPMZFsx; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id bc8si44434522plb.322.2019.08.07.17.08.12; Wed, 07 Aug 2019 17:08:27 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=qaPMZFsx; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730552AbfHHAH3 (ORCPT + 99 others); Wed, 7 Aug 2019 20:07:29 -0400 Received: from mail-pg1-f201.google.com ([209.85.215.201]:37988 "EHLO mail-pg1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730505AbfHHAH2 (ORCPT ); Wed, 7 Aug 2019 20:07:28 -0400 Received: by mail-pg1-f201.google.com with SMTP id w5so56579866pgs.5 for ; Wed, 07 Aug 2019 17:07:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=51dHsz2VCo9w+VP1Zvpve034pgyEZM98AQeW9IXg4Ow=; b=qaPMZFsxPYlh8hN7E8ZioYbLyoR2pnDjpUUdmvY82bDBN4zqlIczR0U1yBwpU333HZ aSch76HNl1DW8kctots8Mrj8L3EbKtrh9q4nuhBYvc0Z1EOR/JIfl3aZpyWr+C23mn72 g9HOt17EpcIbJ7QlgWlERG14acM/xEk9FLARVuCHKSudxWmSL5xub/4seyB3pD+D3Va5 DVqZ6FgAeJwHubIPsuex5xOBBNoVqePDedbxGWuOHDJNcURe/7+XlN/ThGoh9NoRdDTI wPFHD2qhLBeMr4Yw29yn97s9LTZi5I4xogrV35LxyTlNL3QoHVm+JfRun+A3NQUgNb5z L03g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=51dHsz2VCo9w+VP1Zvpve034pgyEZM98AQeW9IXg4Ow=; b=Pd0UaG4+kjQnh0kzIQCfFFobO3ZODrutmb5hbiv7y02jvx20uEDh0pBkuP9Ve5HFUx PAAWr+P8PGHq8Hi4hNdSxh39B5xFE63VlS3UQPhuY+u6BC/7KjAs1KCw9UwpjwVrI4Bl 8dL1fX2fFihbuIrVLGQIEyKQAN5D1ngRO7jQgz29d3VtpXVuLF55rl3mM2H1/7xFF47r ODzvnMKNBpu8+wJGsQpMWabxIf0txNs1iUVmIW9zVoGOT0YnOOqTilw204PahcbIpzQO 6t/3l+VRmWyk6A16zGsMja5kEPhrSwmMfz+s7fsH8hmFtvfAravo3ssIzeCGdQjL1vHK Vtpw== X-Gm-Message-State: APjAAAVFbBaYhO3nXMXPyU4GoKIRJRwRYzyVm/9vZ5KKTeJQWnEyKsoc qbHFa/WjkuJh/Jx9+Ar1vjJY4nYVnQoqszOniI4kqw== X-Received: by 2002:a65:52ca:: with SMTP id z10mr10274165pgp.424.1565222847365; Wed, 07 Aug 2019 17:07:27 -0700 (PDT) Date: Wed, 7 Aug 2019 17:06:53 -0700 In-Reply-To: <20190808000721.124691-1-matthewgarrett@google.com> Message-Id: <20190808000721.124691-2-matthewgarrett@google.com> Mime-Version: 1.0 References: <20190808000721.124691-1-matthewgarrett@google.com> X-Mailer: git-send-email 2.22.0.770.g0f2c4a37fd-goog Subject: [PATCH V38 01/29] security: Support early LSMs From: Matthew Garrett To: jmorris@namei.org Cc: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, Matthew Garrett , Matthew Garrett , Kees Cook , Casey Schaufler Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The lockdown module is intended to allow for kernels to be locked down early in boot - sufficiently early that we don't have the ability to kmalloc() yet. Add support for early initialisation of some LSMs, and then add them to the list of names when we do full initialisation later. Early LSMs are initialised in link order and cannot be overridden via boot parameters, and cannot make use of kmalloc() (since the allocator isn't initialised yet). Signed-off-by: Matthew Garrett Acked-by: Kees Cook Acked-by: Casey Schaufler --- include/asm-generic/vmlinux.lds.h | 8 ++++- include/linux/lsm_hooks.h | 6 ++++ include/linux/security.h | 1 + init/main.c | 1 + security/security.c | 50 ++++++++++++++++++++++++++----- 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index cd28f63bfbc7..dae64600ccbf 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -215,8 +215,13 @@ __start_lsm_info = .; \ KEEP(*(.lsm_info.init)) \ __end_lsm_info = .; +#define EARLY_LSM_TABLE() . = ALIGN(8); \ + __start_early_lsm_info = .; \ + KEEP(*(.early_lsm_info.init)) \ + __end_early_lsm_info = .; #else #define LSM_TABLE() +#define EARLY_LSM_TABLE() #endif #define ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name) @@ -627,7 +632,8 @@ ACPI_PROBE_TABLE(timer) \ THERMAL_TABLE(governor) \ EARLYCON_TABLE() \ - LSM_TABLE() + LSM_TABLE() \ + EARLY_LSM_TABLE() #define INIT_TEXT \ *(.init.text .init.text.*) \ diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index df1318d85f7d..aebb0e032072 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2104,12 +2104,18 @@ struct lsm_info { }; extern struct lsm_info __start_lsm_info[], __end_lsm_info[]; +extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[]; #define DEFINE_LSM(lsm) \ static struct lsm_info __lsm_##lsm \ __used __section(.lsm_info.init) \ __aligned(sizeof(unsigned long)) +#define DEFINE_EARLY_LSM(lsm) \ + static struct lsm_info __early_lsm_##lsm \ + __used __section(.early_lsm_info.init) \ + __aligned(sizeof(unsigned long)) + #ifdef CONFIG_SECURITY_SELINUX_DISABLE /* * Assuring the safety of deleting a security module is up to diff --git a/include/linux/security.h b/include/linux/security.h index 5f7441abbf42..66a2fcbe6ab0 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -195,6 +195,7 @@ int unregister_blocking_lsm_notifier(struct notifier_block *nb); /* prototypes */ extern int security_init(void); +extern int early_security_init(void); /* Security operations */ int security_binder_set_context_mgr(struct task_struct *mgr); diff --git a/init/main.c b/init/main.c index 96f8d5af52d6..565af7b963e1 100644 --- a/init/main.c +++ b/init/main.c @@ -593,6 +593,7 @@ asmlinkage __visible void __init start_kernel(void) boot_cpu_init(); page_address_init(); pr_notice("%s", linux_banner); + early_security_init(); setup_arch(&command_line); mm_init_cpumask(&init_mm); setup_command_line(command_line); diff --git a/security/security.c b/security/security.c index 250ee2d76406..90f1e291c800 100644 --- a/security/security.c +++ b/security/security.c @@ -33,6 +33,7 @@ /* How many LSMs were built into the kernel? */ #define LSM_COUNT (__end_lsm_info - __start_lsm_info) +#define EARLY_LSM_COUNT (__end_early_lsm_info - __start_early_lsm_info) struct security_hook_heads security_hook_heads __lsm_ro_after_init; static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain); @@ -277,6 +278,8 @@ static void __init ordered_lsm_parse(const char *order, const char *origin) static void __init lsm_early_cred(struct cred *cred); static void __init lsm_early_task(struct task_struct *task); +static int lsm_append(const char *new, char **result); + static void __init ordered_lsm_init(void) { struct lsm_info **lsm; @@ -323,6 +326,26 @@ static void __init ordered_lsm_init(void) kfree(ordered_lsms); } +int __init early_security_init(void) +{ + int i; + struct hlist_head *list = (struct hlist_head *) &security_hook_heads; + struct lsm_info *lsm; + + for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head); + i++) + INIT_HLIST_HEAD(&list[i]); + + for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) { + if (!lsm->enabled) + lsm->enabled = &lsm_enabled_true; + prepare_lsm(lsm); + initialize_lsm(lsm); + } + + return 0; +} + /** * security_init - initializes the security framework * @@ -330,14 +353,18 @@ static void __init ordered_lsm_init(void) */ int __init security_init(void) { - int i; - struct hlist_head *list = (struct hlist_head *) &security_hook_heads; + struct lsm_info *lsm; pr_info("Security Framework initializing\n"); - for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head); - i++) - INIT_HLIST_HEAD(&list[i]); + /* + * Append the names of the early LSM modules now that kmalloc() is + * available + */ + for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) { + if (lsm->enabled) + lsm_append(lsm->name, &lsm_names); + } /* Load LSMs in specified order. */ ordered_lsm_init(); @@ -384,7 +411,7 @@ static bool match_last_lsm(const char *list, const char *lsm) return !strcmp(last, lsm); } -static int lsm_append(char *new, char **result) +static int lsm_append(const char *new, char **result) { char *cp; @@ -422,8 +449,15 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, hooks[i].lsm = lsm; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); } - if (lsm_append(lsm, &lsm_names) < 0) - panic("%s - Cannot get early memory.\n", __func__); + + /* + * Don't try to append during early_security_init(), we'll come back + * and fix this up afterwards. + */ + if (slab_is_available()) { + if (lsm_append(lsm, &lsm_names) < 0) + panic("%s - Cannot get early memory.\n", __func__); + } } int call_blocking_lsm_notifier(enum lsm_event event, void *data) -- 2.22.0.770.g0f2c4a37fd-goog