Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp962809ybi; Fri, 31 May 2019 11:27:42 -0700 (PDT) X-Google-Smtp-Source: APXvYqxlSjSReNh62xr4/ihB/i196hzehdWcUSX18NAOiSRPIZFl64aiI5qEvQIJbrwOz46YToIf X-Received: by 2002:a62:f245:: with SMTP id y5mr11477117pfl.12.1559327261921; Fri, 31 May 2019 11:27:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559327261; cv=none; d=google.com; s=arc-20160816; b=aJPcu4bXq01yeExQNEYY2ErM3I6SbfW2UA/p+cc786FzE0H2x+KIZfDv0KL4iSsx49 x7AeC5SwW/MCSzHVd1MTGx8e3tvnQ/6uFnLQeUM6PIeLX31EbGJqyxNIoTTeS+n8DDg+ 4T710JOnCNoyIOT4QHfUQtHIBlAzMt2BECwjvXRMyyEfDWEO+TivFzIjRzNSE0lo98nx nbhWk07sEJZEoDDGydA2zOe+6FcjNCCVl2cwpl/TtKdPgczRbbeggc7d/jbYX2qHgetA WiIXKRXweixk9WDMCUXN4gcuqy2eb2JlzOs3BCAfWfi2/S2Znebg9JUm5yzWAm/Bn1VF Lnkw== 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=LDA2pDvq/qNvw7N7uaZJss460mNoNVu4VrvzxbecA4k=; b=LFHMtKZsMeUBBdQc5Hx/ImIveoktOndMBKW0Ilb4aIvaC14bxEtk21IHA868MwEW5r DLfKIDDjBGo14hp8wLZ/lYTSgA1UkTpa4vWR2KnHvNHbmknQNGNws89kmjmOydRcfzvs 0liAx9cYAq89g8ru7RD77na4mRQvPaFHTE3Rj04XL2bJaCUKjIbUdP2q8x4lQuxJxaNf LtbGOhlWbbBvm8z0wliZEzI+7MnsQt10IzUUZ2aSoJlXu412WKQbBLGm/k1VaDg4afb8 NN3DiARrITdgj4F4mvunBXj+CEj0SG3xCqaAHCquX8TxzcE0wPzwhCE56+drJgAd2/6l KnfA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=tZefdfI0; 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 d21si2954637pjr.17.2019.05.31.11.27.25; Fri, 31 May 2019 11:27:41 -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=tZefdfI0; 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 S1727072AbfEaSZ6 (ORCPT + 99 others); Fri, 31 May 2019 14:25:58 -0400 Received: from mail-yw1-f73.google.com ([209.85.161.73]:46364 "EHLO mail-yw1-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726869AbfEaSZ5 (ORCPT ); Fri, 31 May 2019 14:25:57 -0400 Received: by mail-yw1-f73.google.com with SMTP id w139so9503114ywd.13 for ; Fri, 31 May 2019 11:25:56 -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=LDA2pDvq/qNvw7N7uaZJss460mNoNVu4VrvzxbecA4k=; b=tZefdfI09ZiYnm5bSY61vRh6qtHxrGgKsfd8fdJtygF24iXXrRcac0NtIAtgJe/VSH Xsmc6PhCVT4QusVNYvrVzTdULKnXH+5lsmO03krr/QsEZcZgpymnTXrGt3veGmbDz1vI 4OlW2FZZafEuSbDzxpRvk18jasR2DJCvYLEaFU6+x1CApvfnL9CMWkLMrHo/u9QlYlgO uAZ7/HUwvJ0Lxzv7Qo2mmm3dIDRyY/GrKBHs2svtv1p4o/snjj5Ot52MpixQXSr6FGUG 0JU745xRfLe2As+UVfjbUM829gyjsS2WVJpC0/+f8ZmpaqQWk4EGxhgf5ub5tmGWqjjc 9mBg== 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=LDA2pDvq/qNvw7N7uaZJss460mNoNVu4VrvzxbecA4k=; b=sz2dgV+3M9BRgDWaFsv+tys5iebhYNLERLORxnVijXIKmi5ZdFY51RjqQxyiY8V/n0 uwwVwRWZblR6kPY+gQPfho9HrCs3cIMJkywby6sfOOe02vZohodsWTd0gDsJizIXgZRP Sno/8H63cH09VmaBR+d6jvLI5ThLk/zqUC1tAJSmuHmchGH54npT0PoP1QBByGmtCBob rB7wLT8mT/6B0HSuXBZRJAfR+aYIWzMvL0NCyfHS1FNpl9OjHheNP3hQOHLgXoV9w0pV 9lBkNqAtQ6ZuBe3HKkDGNwjtfYfMvnVdhLRngD5IUwvZmwNn4/hzDfedpAgBRA2JBHHp EI5Q== X-Gm-Message-State: APjAAAVns9gBeXSRXqhkhOnPmFaEUTk+XazM0jdhzpyWEEREKXfMzoGX IesJpi6dhZYuoLw8FnK9Vo3taLqtHek= X-Received: by 2002:a0d:d7cc:: with SMTP id z195mr6425678ywd.454.1559327156131; Fri, 31 May 2019 11:25:56 -0700 (PDT) Date: Fri, 31 May 2019 11:25:53 -0700 In-Reply-To: <20190529224350.6460-1-mikewu@google.com> Message-Id: <20190531182553.51721-1-mikewu@google.com> Mime-Version: 1.0 References: <20190529224350.6460-1-mikewu@google.com> X-Mailer: git-send-email 2.22.0.rc1.257.g3120a18244-goog Subject: [PATCH v3] Allow to exclude specific file types in LoadPin From: Ke Wu To: Kees Cook , Jonathan Corbet , James Morris , "Serge E. Hallyn" Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, Ke Wu 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 Linux kernel already provide MODULE_SIG and KEXEC_VERIFY_SIG to make sure loaded kernel module and kernel image are trusted. This patch adds a kernel command line option "loadpin.exclude" which allows to exclude specific file types from LoadPin. This is useful when people want to use different mechanisms to verify module and kernel image while still use LoadPin to protect the integrity of other files kernel loads. Signed-off-by: Ke Wu --- Changelog since v2: - Make size of exclude_read_files and ignore_read_file_id to be equal to the size of kernel_read_file_str. Changelog since v1: - Mark ignore_read_file_id with __ro_after_init. - Mark parse_exclude() with __init. - Use ARRAY_SIZE(ignore_read_file_id) instead of READING_MAX_ID. Documentation/admin-guide/LSM/LoadPin.rst | 10 ++++++ security/loadpin/loadpin.c | 42 +++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/Documentation/admin-guide/LSM/LoadPin.rst b/Documentation/admin-guide/LSM/LoadPin.rst index 32070762d24c..716ad9b23c9a 100644 --- a/Documentation/admin-guide/LSM/LoadPin.rst +++ b/Documentation/admin-guide/LSM/LoadPin.rst @@ -19,3 +19,13 @@ block device backing the filesystem is not read-only, a sysctl is created to toggle pinning: ``/proc/sys/kernel/loadpin/enabled``. (Having a mutable filesystem means pinning is mutable too, but having the sysctl allows for easy testing on systems with a mutable filesystem.) + +It's also possible to exclude specific file types from LoadPin using kernel +command line option "``loadpin.exclude``". By default, all files are +included, but they can be excluded using kernel command line option such +as "``loadpin.exclude=kernel-module,kexec-image``". This allows to use +different mechanisms such as ``CONFIG_MODULE_SIG`` and +``CONFIG_KEXEC_VERIFY_SIG`` to verify kernel module and kernel image while +still use LoadPin to protect the integrity of other files kernel loads. The +full list of valid file types can be found in ``kernel_read_file_str`` +defined in ``include/linux/fs.h``. diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index 055fb0a64169..baa8a5b08c53 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -45,6 +45,12 @@ static void report_load(const char *origin, struct file *file, char *operation) } static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE); +/* + * The size should be READING_MAX_ID + 1 to be equal to the size of + * kernel_read_file_str. + */ +static char *exclude_read_files[READING_MAX_ID + 1]; +static int ignore_read_file_id[READING_MAX_ID + 1] __ro_after_init; static struct super_block *pinned_root; static DEFINE_SPINLOCK(pinned_root_spinlock); @@ -129,6 +135,13 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id) struct super_block *load_root; const char *origin = kernel_read_file_id_str(id); + /* If the file id is excluded, ignore the pinning. */ + if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) && + ignore_read_file_id[id]) { + report_load(origin, file, "pinning-excluded"); + return 0; + } + /* This handles the older init_module API that has a NULL file. */ if (!file) { if (!enforce) { @@ -187,10 +200,37 @@ static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), }; +static void __init parse_exclude(void) +{ + int i, j; + char *cur; + + for (i = 0; i < ARRAY_SIZE(exclude_read_files); i++) { + cur = exclude_read_files[i]; + if (!cur) + break; + if (*cur == '\0') + continue; + + for (j = 0; j < ARRAY_SIZE(kernel_read_file_str); j++) { + if (strcmp(cur, kernel_read_file_str[j]) == 0) { + pr_info("excluding: %s\n", + kernel_read_file_str[j]); + ignore_read_file_id[j] = 1; + /* + * Can not break, because one read_file_str + * may map to more than on read_file_id. + */ + } + } + } +} + static int __init loadpin_init(void) { pr_info("ready to pin (currently %senforcing)\n", enforce ? "" : "not "); + parse_exclude(); security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); return 0; } @@ -203,3 +243,5 @@ DEFINE_LSM(loadpin) = { /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ module_param(enforce, int, 0); MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning"); +module_param_array_named(exclude, exclude_read_files, charp, NULL, 0); +MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types"); -- 2.22.0.rc1.257.g3120a18244-goog