From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9B595C5516F for ; Fri, 31 Jul 2026 16:28:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=6RJPYbBdKyVevokLLvrFaLY6IOxzeT8FvabNtZpBPjM=; b=cYV5SDMD+OIyfR4/qi+cfouVBW vQUfuzat7kDBwqHWv0m6j33WXArJLYLASoysktdMDBJZNJfbOEAxu0rAw8M+h5y47UM3Jt1Vy6G19 EvrWWQqMVLPrPWx4nRlzHJKkACyol1NCMeDwj5lERZHZ75Ijn6WTeqj9epsMIuqkf3KaDQ0Ul2wzr gQYV79cI9s17d3QZ9cBNjHvuD3mJzcq9bRT3FptScIcUKKZNfJQiiw6h0BxuaBXhy7y2b+SF1wzx0 3b9d6TZL711Se4qT1+bqNTaQqz4Trm+pW8K3+T5/aNFS0pKo+/E+gzTfHGjgpBcYJUwftqiWMVONS 0tRZlHHA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wpq5X-0000000D7Ru-265b; Fri, 31 Jul 2026 16:27:59 +0000 Received: from fhigh-b3-smtp.messagingengine.com ([202.12.124.154]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wpq5T-0000000D7P4-3Wh8 for kexec@lists.infradead.org; Fri, 31 Jul 2026 16:27:57 +0000 Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfhigh.stl.internal (Postfix) with ESMTP id 230AA7A0112; Fri, 31 Jul 2026 12:27:55 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Fri, 31 Jul 2026 12:27:55 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jaseg.de; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm2; t=1785515274; x=1785601674; bh=6RJPYbBdKyVevokLLvrFaLY6IOxzeT8FvabNtZpBPjM=; b= YUz5MR510i+WmXGI7a4kC5uqawHagcWlThX/znOeuRjkIJrcn2zxv0EsYGbM20lb i5yjscraNBNQfufT3LtYFRxnI0PCj5X76beHrvcmSIEU1d2fHZrUWO6XIAi7OWDU rpE2w0joPx55gGeemOiiqSM0bOSu6EgZj9K2NvJ0uJI8fg0aS8KZhGS1sXhk9EeU Xn3a0nNO7LYe5vFb9ipY8TccSzGCc1jNGae7Ncb+VoA+eEMurDBLCM1RyDXi/jwi Bl1clFSRw9/MyZyGuTc3fleqXsSSmVHhcMZQUkkwkNP7Myvg7pMS4n7PX8M9XHTS KeJ2d49aUOJSd3kt7vIPeg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1785515274; x= 1785601674; bh=6RJPYbBdKyVevokLLvrFaLY6IOxzeT8FvabNtZpBPjM=; b=c E7SOqoa3Otd7WsGDI1EXvQLZ5uj79zcwLoXFNNZ3ZhmOiWo8vcAxHQw5MA8dqUYd 7DQvxudJBbVDkploQoBg1qu3X/W/4umdXLFrwfFlzY9Gf//CeCIvl0yiml7ROhqK Qb2QCGMeNGxi351dOwLvEtDB3+vChBbKO2cVaF4xTLljSb95UrLr61C3cvwvbfaq yV2E5czozC/kxvDeddrTSmn9PJhduC5uBwqKjjcfB0L8sEZ5+HD/gFVbI7SZmjQd HKX+jX74c1FBv7HDt74zfE5RrnOw/PFTwFKQ6yAlkc64gKUEGtkzrLebYsnfwT0l HKxWtXy94CSDS2JuLZp7A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFK/nfZ71g8ktujuuoyrF9Ty3Awc1kurrPu2o1v6nhgMM6NL3zj5ESd/fiJ+lq6Fq Z3OuJgsO9Fs2GPtTwEyFZyDKihsNiiEsnOWMvsOfBTFOP9roQM0mTP8MtpTOtxDCDWThhp R6cquw+SMl49Oku+QQXCkKW+TrFunMbAzDZTMwRiMkrGaoNe0GLi6W90Q6fubhxR5onr5q JMP4yfob1UtqZ4XCQdoJfvSelSRy/3zTBtxj7H4AUAz0Xtt/lL1/4chym5iL4gRXLFaWSQ TqzwgVHkZuxaKP3mHZdHzlPw99hzi3gU4xKCX1rRjxCDxKjnlHRIs9asJOBHpx9Xtx82Wu KfYE0fXzVTV12FAmSzQyjawktIBVNf4pTw9FSHRBmhVSjR/DfddoxPl4utqYB4lxLjouzt oXC5NAFahcYIV6iVTmqO7YcRb0qN1Q5SAf4H5gLw4tfLgIBe6suNECZv0viYMaX8RmL/Z0 mWD0jSZEDPOu6r2LNzYFAaUhaglPqA+u4ArkGHwvjPud20jbUikr0ul60+KyV5NudeSHon KHKewFBLzNSRafof6rP0ltLpAIe7339yDePtxqrF1sw2mIchka9xTpJ9ZDEige5ZTrIo+b 18pexHS4+MVejnDnuk3GvyPN1lshEFrhRooCzfsWwDeVqxpuffogHi3ECxTA X-ME-Proxy: Feedback-ID: i60a14417:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 31 Jul 2026 12:27:53 -0400 (EDT) From: =?UTF-8?q?Jan=20Sebastian=20G=C3=B6tte?= To: =?UTF-8?q?Jan=20Sebastian=20G=C3=B6tte?= Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, kexec@lists.infradead.org, keyrings@vger.kernel.org, linux-mm@kvack.org, linux-security-module@vger.kernel.org, linux-integrity@vger.kernel.org Subject: [PATCH 4/4] security/keys: zeroize key payloads before kdump Date: Fri, 31 Jul 2026 18:27:39 +0200 Message-ID: <20260731162739.158320-5-linux@jaseg.de> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260731162739.158320-1-linux@jaseg.de> References: <20260731162739.158320-1-linux@jaseg.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260731_092756_416658_64896450 X-CRM114-Status: GOOD ( 19.78 ) X-BeenThere: kexec@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "kexec" Errors-To: kexec-bounces+kexec=archiver.kernel.org@lists.infradead.org When CONFIG_CRASH_ZEROIZE is set, try to erase key payloads on panic before jumping to the kdump kernel. CRASH_ZEROIZE notifiers run during panic() with other CPUs stopped and preemption disabled. In this state, we can't rely on free()'ing being safe, so we define a new zeroize key op. Implement the zeroize op for the user/logon, encrypted, trusted, and big_key types. Signed-off-by: Jan Sebastian Götte --- include/linux/key-type.h | 9 +++++ security/keys/big_key.c | 15 ++++++++ security/keys/encrypted-keys/encrypted.c | 12 +++++++ security/keys/key.c | 44 +++++++++++++++++++++++ security/keys/trusted-keys/trusted_core.c | 14 ++++++++ security/keys/user_defined.c | 11 ++++++ 6 files changed, 105 insertions(+) diff --git a/include/linux/key-type.h b/include/linux/key-type.h index bb97bd3e5af4..ff0944ce368f 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -122,6 +122,15 @@ struct key_type { /* clear the data from a key (optional) */ void (*destroy)(struct key *key); + /* scrub the key material without free'ing (optional) + * - used from CONFIG_CRASH_ZEROIZE during panic to keep keys out of + * crash dumps + * - called from the panic path with other CPUs stopped and preemption + * disabled + * - must not sleep, allocate, free or take locks + */ + void (*zeroize)(struct key *key); + /* describe a key */ void (*describe)(const struct key *key, struct seq_file *p); diff --git a/security/keys/big_key.c b/security/keys/big_key.c index 268f702df380..ad8537dda70f 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c @@ -35,6 +35,8 @@ struct big_key_payload { */ #define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry)) +static void big_key_zeroize(struct key *key); + /* * big_key defined keys take an arbitrary string as the description and an * arbitrary blob of data as the payload @@ -46,6 +48,7 @@ struct key_type key_type_big_key = { .instantiate = generic_key_instantiate, .revoke = big_key_revoke, .destroy = big_key_destroy, + .zeroize = big_key_zeroize, .describe = big_key_describe, .read = big_key_read, .update = big_key_update, @@ -279,6 +282,18 @@ long big_key_read(const struct key *key, char *buffer, size_t buflen) return ret; } +static void big_key_zeroize(struct key *key) +{ + struct big_key_payload *payload = to_big_key_payload(key->payload); + + if (payload->data) { + if (payload->length > BIG_KEY_FILE_THRESHOLD) + memzero_explicit(payload->data, CHACHA20POLY1305_KEY_SIZE); + else + memzero_explicit(payload->data, payload->length); + } +} + /* * Register key type */ diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 59cb77b237b3..9f56fa9b4aaf 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -970,11 +970,23 @@ static void encrypted_destroy(struct key *key) kfree_sensitive(key->payload.data[0]); } +static void encrypted_zeroize(struct key *key) +{ + struct encrypted_key_payload *epayload = key->payload.data[0]; + + if (!epayload) + return; + + memzero_explicit(epayload->payload_data, + epayload->payload_datalen + epayload->datablob_len); +} + struct key_type key_type_encrypted = { .name = "encrypted", .instantiate = encrypted_instantiate, .update = encrypted_update, .destroy = encrypted_destroy, + .zeroize = encrypted_zeroize, .describe = user_describe, .read = encrypted_read, }; diff --git a/security/keys/key.c b/security/keys/key.c index b34a64d81d47..5673dcc8c5d2 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "internal.h" @@ -1268,6 +1269,44 @@ void unregister_key_type(struct key_type *ktype) } EXPORT_SYMBOL(unregister_key_type); +#ifdef CONFIG_CRASH_ZEROIZE +/* Called far into vpanic from crash_core.c with other CPUs stopped and + * preemption disabled + */ +static int key_crash_zeroize(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct rb_node *node; + + /* If we can't acquire the lock, the rbtree might be in an inconsistent + * state. That's all we can do then, as there's no point to waiting + * at this stage. + */ + if (!spin_trylock(&key_serial_lock)) { + pr_crit("crash_zeroize: can't acquire key_serial_lock. skipping keyrings.\n"); + return NOTIFY_DONE; + } + + for (node = rb_first(&key_serial_tree); node; node = rb_next(node)) { + struct key *key = rb_entry(node, struct key, serial_node); + + if (key->type == &key_type_keyring || + key->state == KEY_IS_UNINSTANTIATED) + continue; + + /* custom zeroize since free'ing isn't safe at this point */ + if (key->type->zeroize) + key->type->zeroize(key); + } + /* off to kexec()! */ + return NOTIFY_DONE; +} + +static struct notifier_block key_crash_zeroize_nb = { + .notifier_call = key_crash_zeroize +}; +#endif /* CONFIG_CRASH_ZEROIZE */ + /* * Initialise the key management state. */ @@ -1290,4 +1329,9 @@ void __init key_init(void) rb_insert_color(&root_key_user.node, &key_user_tree); + +#ifdef CONFIG_CRASH_ZEROIZE + atomic_notifier_chain_register(&crash_zeroize_notifier_list, + &key_crash_zeroize_nb); +#endif } diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c index 0509d9955f2a..f159faeafe23 100644 --- a/security/keys/trusted-keys/trusted_core.c +++ b/security/keys/trusted-keys/trusted_core.c @@ -325,11 +325,25 @@ static void trusted_destroy(struct key *key) kfree_sensitive(key->payload.data[0]); } +static void trusted_zeroize(struct key *key) +{ + struct trusted_key_payload *p = key->payload.data[0]; + + if (!p) + return; + + memzero_explicit(p->key, sizeof(p->key)); + memzero_explicit(p->blob, sizeof(p->blob)); + p->key_len = 0; + p->blob_len = 0; +} + struct key_type key_type_trusted = { .name = "trusted", .instantiate = trusted_instantiate, .update = trusted_update, .destroy = trusted_destroy, + .zeroize = trusted_zeroize, .describe = user_describe, .read = trusted_read, }; diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 6f88b507f927..ade95dc2481d 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -15,6 +15,7 @@ #include "internal.h" static int logon_vet_description(const char *desc); +static void user_zeroize(struct key *key); /* * user defined keys take an arbitrary string as the description and an @@ -28,6 +29,7 @@ struct key_type key_type_user = { .update = user_update, .revoke = user_revoke, .destroy = user_destroy, + .zeroize = user_zeroize, .describe = user_describe, .read = user_read, }; @@ -48,6 +50,7 @@ struct key_type key_type_logon = { .update = user_update, .revoke = user_revoke, .destroy = user_destroy, + .zeroize = user_zeroize, .describe = user_describe, .vet_description = logon_vet_description, }; @@ -152,6 +155,14 @@ void user_destroy(struct key *key) EXPORT_SYMBOL_GPL(user_destroy); +static void user_zeroize(struct key *key) +{ + struct user_key_payload *upayload = key->payload.data[0]; + + if (upayload) + memzero_explicit(upayload->data, upayload->datalen); +} + /* * describe the user key */ -- 2.53.0