From patchwork Mon May 10 14:14:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitri John Ledkov X-Patchwork-Id: 1476462 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Ff33S6Mhbz9rx6; Tue, 11 May 2021 00:15:00 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1lg6gR-0001c8-65; Mon, 10 May 2021 14:14:55 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lg6gO-0001bO-Cm for kernel-team@lists.ubuntu.com; Mon, 10 May 2021 14:14:52 +0000 Received: from mail-wr1-f71.google.com ([209.85.221.71]) by youngberry.canonical.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1lg6gO-0004I0-4P for kernel-team@lists.ubuntu.com; Mon, 10 May 2021 14:14:52 +0000 Received: by mail-wr1-f71.google.com with SMTP id l2-20020adf9f020000b029010d6bb7f1cbso7533964wrf.7 for ; Mon, 10 May 2021 07:14:52 -0700 (PDT) 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:mime-version :content-transfer-encoding; bh=kqzq17Hk0IRFE+yiTIkq9n8Y+KPYCnybiuhf1DGlsYM=; b=PmLCWQ0mPRK+3B3jTvx2W3wPF9lc11BEDjfkLlVSDjiCraKlgTriAX3tKfp7rTJXdF BYoTRHLPmWHbCOQGoqFIH8Kd1LaOItwQyRRuAyriKHMH4ygtn/ozvNMj22lI/HvdE2Lj 74aKCgYw7vQaINVITEJ2KNBsph1fw1JS63KIW3Wr8GGaXSnM97L1YH5lJDv/K1M0Qxyh /FyuxMoavtIJA11YJjTq/xF00dvj8hmuDbIDm3ja3ya1h2pyty5TLW5+1SQ8KPi9aWjl +N25bzBvlCAoGhQfGZ8E8V1qwc9bMITsn1HoJu9EUByaDhTrs1wJXD77J+kTtQqUWnDe chWQ== X-Gm-Message-State: AOAM532BJOsslZphVqwkjJv/7gGAZd4kUJxf4uoqAjVKbDNelh903db2 ytSii07wQ/CteEDP2ff0/FFltKE+RTjBH3LzaVI7o+vuBgHVYEbZWkPwLRSVLl9VzA3lDvhmVJI FUH0ILfQvWyQG6gikFx34KEwnV78ZtlSQWoDRzmU6RA== X-Received: by 2002:adf:d4ca:: with SMTP id w10mr32402979wrk.244.1620656091492; Mon, 10 May 2021 07:14:51 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwxRSaij3Yw8t+8tHBwJgFN90OIZDzrYME9Z5gZx5JmFbmxGyY8E1EAJyRYVHnNR8/GidkoOA== X-Received: by 2002:adf:d4ca:: with SMTP id w10mr32402926wrk.244.1620656091109; Mon, 10 May 2021 07:14:51 -0700 (PDT) Received: from localhost ([2a01:4b00:85fd:d700:5dd:29d:3e2a:7420]) by smtp.gmail.com with ESMTPSA id n7sm22789441wri.14.2021.05.10.07.14.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 May 2021 07:14:50 -0700 (PDT) From: Dimitri John Ledkov To: kernel-team@lists.ubuntu.com Subject: [UPSTREAM][RFC PATCH] integrity: Load mokx certs from the EFI MOK config table Date: Mon, 10 May 2021 15:14:48 +0100 Message-Id: <20210510141448.45341-1-dimitri.ledkov@canonical.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: security@ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" Refactor load_moklist_certs() to load either MokListRT into db, or MokListXRT into dbx. Call load_moklist_certs() twice - first to load mokx certs into dbx, then mok certs into db. This thus now attempts to load mokx certs via the EFI MOKvar config table first, and if that fails, via the EFI variable. Previously mokx certs were only loaded via the EFI variable. Which fails when MokListXRT is large and instead of MokListXRT is only available as MokListXRT{1,2,3}. This is the case with Ubuntu's 15.4 based shim. This patch is required to address CVE-2020-26541 when certificates are revoked via MokListXRT. Fixes: ebd9c2ae369a45bdd9f8615484db09be58fc242b Signed-off-by: Dimitri John Ledkov --- @Ubuntu kernel-team / security-team Presubmitting this patch internally, to see if it's ok to submit upstream. Intention is to send this to keyrings@ linux-security-module@ linux-kernel@ Eric Snowberg etc that have introduced the referenced feature into v5.13-rc1 which on ubuntu is buggy and doesn't address the CVE in question. security/integrity/platform_certs/load_uefi.c | 73 ++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c index f290f78c3f301..e1f4ebb71abe0 100644 --- a/security/integrity/platform_certs/load_uefi.c +++ b/security/integrity/platform_certs/load_uefi.c @@ -66,17 +66,18 @@ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, } /* - * load_moklist_certs() - Load MokList certs + * load_moklist_certs() - Load Mok(X)List certs + * @load_db: Load MokListRT into db when true; MokListXRT into dbx when false * - * Load the certs contained in the UEFI MokListRT database into the - * platform trusted keyring. + * Load the certs contained in the UEFI MokList(X)RT database into the + * platform trusted/denied keyring. * * This routine checks the EFI MOK config table first. If and only if - * that fails, this routine uses the MokListRT ordinary UEFI variable. + * that fails, this routine uses the MokList(X)RT ordinary UEFI variable. * * Return: Status */ -static int __init load_moklist_certs(void) +static int __init load_moklist_certs(const bool load_db) { struct efi_mokvar_table_entry *mokvar_entry; efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; @@ -84,41 +85,54 @@ static int __init load_moklist_certs(void) unsigned long moksize; efi_status_t status; int rc; + char *mokvar_name = "MokListRT"; + efi_char16_t *efivar_name = L"MokListRT"; + char *parse_mokvar_name = "UEFI:MokListRT (MOKvar table)"; + char *parse_efivar_name = "UEFI:MokListRT"; + efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *) = get_handler_for_db; + + if (!load_db) { + mokvar_name = "MokListXRT"; + efivar_name = L"MokListXRT"; + parse_mokvar_name = "UEFI:MokListXRT (MOKvar table)"; + parse_efivar_name = "UEFI:MokListXRT"; + get_handler_for_guid = get_handler_for_dbx; + } /* First try to load certs from the EFI MOKvar config table. * It's not an error if the MOKvar config table doesn't exist * or the MokListRT entry is not found in it. */ - mokvar_entry = efi_mokvar_entry_find("MokListRT"); + mokvar_entry = efi_mokvar_entry_find(mokvar_name); if (mokvar_entry) { - rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)", + rc = parse_efi_signature_list(parse_mokvar_name, mokvar_entry->data, mokvar_entry->data_size, - get_handler_for_db); + get_handler_for_guid); /* All done if that worked. */ if (!rc) return rc; - pr_err("Couldn't parse MokListRT signatures from EFI MOKvar config table: %d\n", - rc); + pr_err("Couldn't parse %s signatures from EFI MOKvar config table: %d\n", + mokvar_name, rc); } /* Get MokListRT. It might not exist, so it isn't an error * if we can't get it. */ - mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status); + mok = get_cert_list(efivar_name, &mok_var, &moksize, &status); if (mok) { - rc = parse_efi_signature_list("UEFI:MokListRT", - mok, moksize, get_handler_for_db); + rc = parse_efi_signature_list(parse_efivar_name, + mok, moksize, get_handler_for_guid); kfree(mok); if (rc) - pr_err("Couldn't parse MokListRT signatures: %d\n", rc); + pr_err("Couldn't parse %s signatures: %d\n", mokvar_name, rc); return rc; } if (status == EFI_NOT_FOUND) - pr_debug("MokListRT variable wasn't found\n"); + pr_debug("%s variable wasn't found\n", mokvar_name); else - pr_info("Couldn't get UEFI MokListRT\n"); + pr_info("Couldn't get UEFI %s\n", mokvar_name); return 0; } @@ -132,9 +146,8 @@ static int __init load_moklist_certs(void) static int __init load_uefi_certs(void) { efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; - efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; - void *db = NULL, *dbx = NULL, *mokx = NULL; - unsigned long dbsize = 0, dbxsize = 0, mokxsize = 0; + void *db = NULL, *dbx = NULL; + unsigned long dbsize = 0, dbxsize = 0; efi_status_t status; int rc = 0; @@ -176,23 +189,15 @@ static int __init load_uefi_certs(void) kfree(dbx); } - mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status); - if (!mokx) { - if (status == EFI_NOT_FOUND) - pr_debug("mokx variable wasn't found\n"); - else - pr_info("Couldn't get mokx list\n"); - } else { - rc = parse_efi_signature_list("UEFI:MokListXRT", - mokx, mokxsize, - get_handler_for_dbx); - if (rc) - pr_err("Couldn't parse mokx signatures %d\n", rc); - kfree(mokx); - } + /* Load the MokListXRT certs */ + rc = load_moklist_certs(false); + if (rc) + pr_err("Couldn't parse mokx signatures: %d\n", rc); /* Load the MokListRT certs */ - rc = load_moklist_certs(); + rc = load_moklist_certs(true); + if (rc) + pr_err("Couldn't parse mok signatures: %d\n", rc); return rc; }