forked from pool/grub2
8c3cd1e56a
- Fix unattended boot with TPM2 allows downgrading kernel and rootfs, also enhancing the overall security posture (bsc#1216680) * 0001-Improve-TPM-key-protection-on-boot-interruptions.patch * 0002-Restrict-file-access-on-cryptodisk-print.patch * 0003-Restrict-ls-and-auto-file-completion-on-cryptodisk-p.patch * 0004-Key-revocation-on-out-of-bound-file-access.patch OBS-URL: https://build.opensuse.org/request/show/1128487 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=477
198 lines
5.6 KiB
Diff
198 lines
5.6 KiB
Diff
From 912384e63c1e3b6aa9d90effb71cd535a17da1e2 Mon Sep 17 00:00:00 2001
|
|
From: Michael Chang <mchang@suse.com>
|
|
Date: Sat, 18 Nov 2023 19:02:31 +0800
|
|
Subject: [PATCH 2/4] Restrict file access on cryptodisk print
|
|
|
|
When the encrypted partition is automatically unlocked by TPM, granting
|
|
access to the system upon validation of its known good state, there's a
|
|
potential vulnerability. Grub gains access to file systems that were
|
|
previously inaccessible to the public, enabling certain commands from
|
|
the grub console to print content. This arises due to grub lacking
|
|
restrictions similar to those imposed by password authentication, which
|
|
typically occurs before privileged access is granted.
|
|
|
|
Although the automatic unlocking process ensures system integrity and a
|
|
secure environment for grub to operate in, it doesn't directly address
|
|
the issue of authentication for viewing encrypted partition content.
|
|
|
|
This commit addresses this security loophole by implementing a file
|
|
filter upon adding a TPM key. The newly added file filter will
|
|
specifically verify if the disk is encrypted, denying access and
|
|
returning an "Access Denied: prohibited to view encrypted data" error
|
|
message to alert the user.
|
|
|
|
Since the policy to filter out unwanted commands from leaking encrypted
|
|
content is irreversible, it is advisable to make the loaded module
|
|
persistent to prevent its removal.
|
|
|
|
This enhancement aims to bolster security measures and prevent
|
|
unauthorized access to encrypted data.
|
|
|
|
Signed-Off-by Michael Chang <mchang@suse.com>
|
|
---
|
|
grub-core/commands/crypttab.c | 35 ++++++++++++++++++++++++++++++++++-
|
|
grub-core/disk/diskfilter.c | 35 +++++++++++++++++++++++++++++++++++
|
|
include/grub/disk.h | 10 ++++++++++
|
|
include/grub/file.h | 1 +
|
|
4 files changed, 80 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
|
|
index 9397bede9..d3acc4b59 100644
|
|
--- a/grub-core/commands/crypttab.c
|
|
+++ b/grub-core/commands/crypttab.c
|
|
@@ -6,11 +6,39 @@
|
|
#include <grub/mm.h>
|
|
#include <grub/list.h>
|
|
#include <grub/crypttab.h>
|
|
+#include <grub/file.h>
|
|
|
|
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
|
grub_crypto_key_list_t *cryptokey_lst;
|
|
|
|
+static grub_file_t
|
|
+grub_nocat_open (grub_file_t io, enum grub_file_type type)
|
|
+{
|
|
+ grub_disk_t disk;
|
|
+
|
|
+ /* Network device */
|
|
+ if (!io->device->disk)
|
|
+ return io;
|
|
+
|
|
+ disk = io->device->disk;
|
|
+
|
|
+ if (grub_disk_is_crypto (disk))
|
|
+ {
|
|
+ switch (type & GRUB_FILE_TYPE_MASK)
|
|
+ {
|
|
+ case GRUB_FILE_TYPE_CAT:
|
|
+ case GRUB_FILE_TYPE_HEXCAT:
|
|
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to view encrypted data"));
|
|
+ return NULL;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return io;
|
|
+}
|
|
+
|
|
grub_err_t
|
|
grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey)
|
|
{
|
|
@@ -48,7 +76,11 @@ grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key
|
|
}
|
|
|
|
if (is_tpmkey >= 0)
|
|
- cur->is_tpmkey = is_tpmkey;
|
|
+ {
|
|
+ cur->is_tpmkey = is_tpmkey;
|
|
+ if (is_tpmkey)
|
|
+ grub_file_filter_register (GRUB_FILE_FILTER_NOCAT, grub_nocat_open);
|
|
+ }
|
|
|
|
if (!cur->name)
|
|
{
|
|
@@ -121,6 +153,7 @@ GRUB_MOD_INIT(crypttab)
|
|
{
|
|
cmd = grub_register_command ("crypttab_entry", grub_cmd_crypttab_entry,
|
|
N_("VOLUME-NAME ENCRYPTED-DEVICE KEY-FILE") , N_("No description"));
|
|
+ grub_dl_set_persistent (mod);
|
|
}
|
|
|
|
GRUB_MOD_FINI(crypttab)
|
|
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
|
|
index 5c5fabe1a..b0c1c880d 100644
|
|
--- a/grub-core/disk/diskfilter.c
|
|
+++ b/grub-core/disk/diskfilter.c
|
|
@@ -558,6 +558,39 @@ find_lv (const char *name)
|
|
return NULL;
|
|
}
|
|
|
|
+static int
|
|
+grub_diskfilter_has_cryptodisk (const struct grub_diskfilter_lv *lv)
|
|
+{
|
|
+ struct grub_diskfilter_pv *pv;
|
|
+
|
|
+ if (!lv)
|
|
+ return 0;
|
|
+
|
|
+ if (lv->vg->pvs)
|
|
+ for (pv = lv->vg->pvs; pv; pv = pv->next)
|
|
+ {
|
|
+ if (!pv->disk)
|
|
+ {
|
|
+ grub_dprintf ("diskfilter", _("Couldn't find physical volume `%s'."
|
|
+ " Some modules may be missing from core image."),
|
|
+ pv->name);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ switch (pv->disk->dev->id)
|
|
+ {
|
|
+ case GRUB_DISK_DEVICE_CRYPTODISK_ID:
|
|
+ return 1;
|
|
+ case GRUB_DISK_DEVICE_DISKFILTER_ID:
|
|
+ return grub_diskfilter_has_cryptodisk (pv->disk->data);
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static grub_err_t
|
|
grub_diskfilter_open (const char *name, grub_disk_t disk)
|
|
{
|
|
@@ -589,6 +622,8 @@ grub_diskfilter_open (const char *name, grub_disk_t disk)
|
|
|
|
disk->total_sectors = lv->size;
|
|
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
|
|
+ disk->is_crypto_diskfilter = grub_diskfilter_has_cryptodisk (lv);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/include/grub/disk.h b/include/grub/disk.h
|
|
index 3b3db6222..63982f16c 100644
|
|
--- a/include/grub/disk.h
|
|
+++ b/include/grub/disk.h
|
|
@@ -147,6 +147,8 @@ struct grub_disk
|
|
|
|
/* Device-specific data. */
|
|
void *data;
|
|
+
|
|
+ int is_crypto_diskfilter;
|
|
};
|
|
typedef struct grub_disk *grub_disk_t;
|
|
|
|
@@ -314,4 +316,12 @@ void grub_mdraid1x_fini (void);
|
|
void grub_diskfilter_fini (void);
|
|
#endif
|
|
|
|
+static inline int
|
|
+grub_disk_is_crypto (grub_disk_t disk)
|
|
+{
|
|
+ return ((disk->is_crypto_diskfilter ||
|
|
+ disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) ?
|
|
+ 1 : 0);
|
|
+}
|
|
+
|
|
#endif /* ! GRUB_DISK_HEADER */
|
|
diff --git a/include/grub/file.h b/include/grub/file.h
|
|
index fde58f0fa..fcfd32ce2 100644
|
|
--- a/include/grub/file.h
|
|
+++ b/include/grub/file.h
|
|
@@ -185,6 +185,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
|
|
/* Filters with lower ID are executed first. */
|
|
typedef enum grub_file_filter_id
|
|
{
|
|
+ GRUB_FILE_FILTER_NOCAT,
|
|
GRUB_FILE_FILTER_VERIFY,
|
|
GRUB_FILE_FILTER_GZIO,
|
|
GRUB_FILE_FILTER_XZIO,
|
|
--
|
|
2.42.1
|
|
|