Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp4481368ybi; Mon, 3 Jun 2019 11:38:17 -0700 (PDT) X-Google-Smtp-Source: APXvYqyEm5FjIBDTY3TmpuP/BI963VggGv81MnHZAh/cW+zMpgruPPaThlZ79oF/t9F6P84Se5fK X-Received: by 2002:a17:902:d701:: with SMTP id w1mr25742100ply.12.1559587097754; Mon, 03 Jun 2019 11:38:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559587097; cv=none; d=google.com; s=arc-20160816; b=WATX5T6ZrboK9p2K7mArUgbPuF9jmNHSOCCLsUdD35q42kFE98yHXYEO5oXmQikriy E4dtRd/pWtQ0lM4y1hCraSyk+pZYg6zm8KIHAfyYfehGhPHyYPdm68V4UVMs2Q3zmNE5 Ip4+W2hwl260pJlNgXEkAIPnsCqplTxmdp/WYzHk8U0WrtdruUPsU0yKkCJdPUBleyrv 8GCHGPFBOSt3ftrDGmb7V6qT1fAzQi+n3lx5uDHNnFrPD2T+jNWRUbkJtpv9vHiRioOT EBJfxjakm3ED2dF8pL2baiXXoPKkGtksnUzh0avMWsdnyO2l867Glc99L93K7PC1x8vR nlwA== 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=eZitS+dbekPKdSNKv5e4dRxz7q7psKdXco7JWUyUMYI=; b=QT1T5Hqm5Q9q9cv1IMJgjTb99ELFY2KcWSsxSKgwDYHt1BSnc/8ffpAwhxoxUCvofu JWFi91u/q0JFlfXLg3xYRuIUV6zMuCalaqMdUjvnDun8gZPoPL8BlOWsOKZ2lDXpB8Bn bV7YHYJ0UeHUl0Su4hcTa0R19TqtMqOJzWPGk6usMoVonG4Zn48Vb6ueY9d0O5XC5nEx uPA12lggXroweBTLWtlzCY6lmMJw4XRPnqtNEDj3VoAoo3GcA3Yrdq5NjpMlAdQpfWfV d6anCXM6tLrL9cVE5P4Z0cZDIhsPFpSRX+Ikj9pLRJH1GFLEB4qVNf476qVrUBLtUFwA s+2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=uINysbsp; 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 d23si18916636pgd.198.2019.06.03.11.38.01; Mon, 03 Jun 2019 11:38:17 -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=uINysbsp; 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 S1727204AbfFCSgT (ORCPT + 99 others); Mon, 3 Jun 2019 14:36:19 -0400 Received: from mail-oi1-f201.google.com ([209.85.167.201]:37614 "EHLO mail-oi1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726875AbfFCSgQ (ORCPT ); Mon, 3 Jun 2019 14:36:16 -0400 Received: by mail-oi1-f201.google.com with SMTP id 5so5567072oix.4 for ; Mon, 03 Jun 2019 11:36:16 -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=eZitS+dbekPKdSNKv5e4dRxz7q7psKdXco7JWUyUMYI=; b=uINysbsp98/V5G2kBWYHoIhT/rBsJepOwPJSjBVEQppBYNRWnvqVwAApBvYTW84bEJ tzMyyXoKwN4rqiWZvrGMNzC+qf5fkucrR0NzYetxglwxXgUTMns5m26CdQijOasEi1g+ Hlqhd3qZhx1UTY5M0mOwhadaipDfE7owhYN9ym9VYoblRb2e/RPpaiGrNqNEGh/wDzVl PKKT8k7dnNbYCPMxODos/8GERZ6DBGH0nuhWTal6oC+WXtflYyNJ5zdsFLLJYelg/otc Y4Y5VddFnoFFBILsWu2w4SiGvxMorSWDUn032trwlFJD8hSaDWgMeZ3jyTnuH8nmK4MH rg3g== 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=eZitS+dbekPKdSNKv5e4dRxz7q7psKdXco7JWUyUMYI=; b=kLioJqiCEJDbHpB7iYjn3QwZSqANeRPH+BBactrz2So4HkWj99WJ4p7Qna5/gJIhUN XZTT7ocDelzy8+N4YDha/L/93GD/r7yAOkTsMOT2F1vJxMBWqby9CGj9+vesNRkAK84q tC2tIg7T0fCKJ0VRfI6fE3T0fM/w8O7ruj3w9+sy/3B739aqEH5AgWAUnJTSqDDuNB2g ijYphUAro1yaRCJGzU9/Hga8YF8blfMGY/gljcRzT5cecGGWu2FcgsXWt6yipGGWeSWi uvF6pp4sALps56RWrg1ldfPBhFqfCCOsBXSgmQhhpnknHn70xtiDRR3XoT//6DVvem1X WLdQ== X-Gm-Message-State: APjAAAU+6IhsSW4lzJFH6KlOrEq/HcYls7en8QmabxJNd1R14dRaG5sA vECtNrfdwDjl8Q0LGoEC104p66fPUOc= X-Received: by 2002:a9d:4d04:: with SMTP id n4mr937988otf.234.1559586975858; Mon, 03 Jun 2019 11:36:15 -0700 (PDT) Date: Mon, 3 Jun 2019 11:36:10 -0700 In-Reply-To: <20190529224350.6460-1-mikewu@google.com> Message-Id: <20190603183610.241026-1-mikewu@google.com> Mime-Version: 1.0 References: <20190529224350.6460-1-mikewu@google.com> X-Mailer: git-send-email 2.22.0.rc1.311.g5d7573a151-goog Subject: [PATCH v4] 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 v3: - Undo patch v3 change. - Use ignore_read_file_id rahther than kernel_read_file_str when iterating to prevent out-of-bounds write. 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 | 44 +++++++++++++++++++++++ 2 files changed, 54 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..ae59b812f4c8 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -45,6 +45,8 @@ static void report_load(const char *origin, struct file *file, char *operation) } static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE); +static char *exclude_read_files[READING_MAX_ID]; +static int ignore_read_file_id[READING_MAX_ID] __ro_after_init; static struct super_block *pinned_root; static DEFINE_SPINLOCK(pinned_root_spinlock); @@ -129,6 +131,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 +196,43 @@ 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; + + /* Robustness check: size of kernel_read_file_str should be size of + * ignore_read_file_id + 1. + */ + BUILD_BUG_ON(ARRAY_SIZE(kernel_read_file_str) < + ARRAY_SIZE(ignore_read_file_id)); + + 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(ignore_read_file_id); 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 +245,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.311.g5d7573a151-goog