Debrand for AlmaLinux
This commit is contained in:
commit
1c1e46c10e
1684
SOURCES/0458-fs-Remove-trailing-whitespaces.patch
Normal file
1684
SOURCES/0458-fs-Remove-trailing-whitespaces.patch
Normal file
File diff suppressed because it is too large
Load Diff
50
SOURCES/0459-fs-xfs-Fix-memory-leaks-in-XFS-module.patch
Normal file
50
SOURCES/0459-fs-xfs-Fix-memory-leaks-in-XFS-module.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 1ff9d36ec874d5702be3815e74a71db7764c56ee Mon Sep 17 00:00:00 2001
|
||||
From: "t.feng" <fengtao40@huawei.com>
|
||||
Date: Tue, 29 Nov 2022 17:14:15 +0800
|
||||
Subject: [PATCH 459/464] fs/xfs: Fix memory leaks in XFS module
|
||||
|
||||
Signed-off-by: t.feng <fengtao40@huawei.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/xfs.c | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index 17bf01f31ddb..8cf41d07c2ee 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -599,7 +599,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
if (grub_disk_read (node->data->disk,
|
||||
GRUB_XFS_FSB_TO_BLOCK (node->data, get_fsb (keys, i - 1 + recoffset)) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS),
|
||||
0, node->data->bsize, leaf))
|
||||
- return 0;
|
||||
+ {
|
||||
+ grub_free (leaf);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
if ((!node->data->hascrc &&
|
||||
grub_strncmp ((char *) leaf->magic, "BMAP", 4)) ||
|
||||
@@ -790,6 +793,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
+ grub_free (fdiro);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -907,7 +911,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
blk << dirblk_log2,
|
||||
dirblk_size, dirblock, 0);
|
||||
if (numread != dirblk_size)
|
||||
- return 0;
|
||||
+ {
|
||||
+ grub_free (dirblock);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
entries = (grub_be_to_cpu32 (tail->leaf_count)
|
||||
- grub_be_to_cpu32 (tail->leaf_stale));
|
||||
--
|
||||
2.46.1
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
From 270099a784d7dc0d251a8be1fed57e55f4dd4f8f Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Thu, 28 Sep 2023 22:33:44 +0000
|
||||
Subject: [PATCH 460/464] fs/xfs: Incorrect short form directory data boundary
|
||||
check
|
||||
|
||||
After parsing of the current entry, the entry pointer is advanced
|
||||
to the next entry at the end of the "for" loop. In case where the
|
||||
last entry is at the end of the data boundary, the advanced entry
|
||||
pointer can point off the data boundary. The subsequent boundary
|
||||
check for the advanced entry pointer can cause a failure.
|
||||
|
||||
The fix is to include the boundary check into the "for" loop
|
||||
condition.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
|
||||
Tested-by: Marta Lewandowska <mlewando@redhat.com>
|
||||
---
|
||||
grub-core/fs/xfs.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index 8cf41d07c2ee..a779eb6b8334 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -836,7 +836,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
if (iterate_dir_call_hook (parent, "..", &ctx))
|
||||
return 1;
|
||||
|
||||
- for (i = 0; i < head->count; i++)
|
||||
+ for (i = 0; i < head->count &&
|
||||
+ (grub_uint8_t *) de < ((grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)); i++)
|
||||
{
|
||||
grub_uint64_t ino;
|
||||
grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de);
|
||||
@@ -871,10 +872,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
de->name[de->len] = c;
|
||||
|
||||
de = grub_xfs_inline_next_de(dir->data, head, de);
|
||||
-
|
||||
- if ((grub_uint8_t *) de >= (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data))
|
||||
- return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
|
||||
-
|
||||
}
|
||||
break;
|
||||
}
|
||||
--
|
||||
2.46.1
|
||||
|
||||
171
SOURCES/0461-fs-xfs-Fix-XFS-directory-extent-parsing.patch
Normal file
171
SOURCES/0461-fs-xfs-Fix-XFS-directory-extent-parsing.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From e5d18ae1b2b0ff58ce720dad90b3539aa2f28ee1 Mon Sep 17 00:00:00 2001
|
||||
From: Jon DeVree <nuxi@vault24.org>
|
||||
Date: Tue, 17 Oct 2023 23:03:47 -0400
|
||||
Subject: [PATCH 461/464] fs/xfs: Fix XFS directory extent parsing
|
||||
|
||||
The XFS directory entry parsing code has never been completely correct
|
||||
for extent based directories. The parser correctly handles the case
|
||||
where the directory is contained in a single extent, but then mistakenly
|
||||
assumes the data blocks for the multiple extent case are each identical
|
||||
to the single extent case. The difference in the format of the data
|
||||
blocks between the two cases is tiny enough that its gone unnoticed for
|
||||
a very long time.
|
||||
|
||||
A recent change introduced some additional bounds checking into the XFS
|
||||
parser. Like GRUB's existing parser, it is correct for the single extent
|
||||
case but incorrect for the multiple extent case. When parsing a directory
|
||||
with multiple extents, this new bounds checking is sometimes (but not
|
||||
always) tripped and triggers an "invalid XFS directory entry" error. This
|
||||
probably would have continued to go unnoticed but the /boot/grub/<arch>
|
||||
directory is large enough that it often has multiple extents.
|
||||
|
||||
The difference between the two cases is that when there are multiple
|
||||
extents, the data blocks do not contain a trailer nor do they contain
|
||||
any leaf information. That information is stored in a separate set of
|
||||
extents dedicated to just the leaf information. These extents come after
|
||||
the directory entry extents and are not included in the inode size. So
|
||||
the existing parser already ignores the leaf extents.
|
||||
|
||||
The only reason to read the trailer/leaf information at all is so that
|
||||
the parser can avoid misinterpreting that data as directory entries. So
|
||||
this updates the parser as follows:
|
||||
|
||||
For the single extent case the parser doesn't change much:
|
||||
1. Read the size of the leaf information from the trailer
|
||||
2. Set the end pointer for the parser to the start of the leaf
|
||||
information. (The previous bounds checking set the end pointer to the
|
||||
start of the trailer, so this is actually a small improvement.)
|
||||
3. Set the entries variable to the expected number of directory entries.
|
||||
|
||||
For the multiple extent case:
|
||||
1. Set the end pointer to the end of the block.
|
||||
2. Do not set up the entries variable. Figuring out how many entries are
|
||||
in each individual block is complex and does not seem worth it when
|
||||
it appears to be safe to just iterate over the entire block.
|
||||
|
||||
The bounds check itself was also dependent upon the faulty XFS parser
|
||||
because it accidentally used "filename + length - 1". Presumably this
|
||||
was able to pass the fuzzer because in the old parser there was always
|
||||
8 bytes of slack space between the tail pointer and the actual end of
|
||||
the block. Since this is no longer the case the bounds check needs to be
|
||||
updated to "filename + length + 1" in order to prevent a regression in
|
||||
the handling of corrupt fliesystems.
|
||||
|
||||
Notes:
|
||||
* When there is only one extent there will only ever be one block. If
|
||||
more than one block is required then XFS will always switch to holding
|
||||
leaf information in a separate extent.
|
||||
* B-tree based directories seems to be parsed properly by the same code
|
||||
that handles multiple extents. This is unlikely to ever occur within
|
||||
/boot though because its only used when there are an extremely large
|
||||
number of directory entries.
|
||||
|
||||
Fixes: ef7850c75 (fs/xfs: Fix issues found while fuzzing the XFS filesystem)
|
||||
Fixes: b2499b29c (Adds support for the XFS filesystem.)
|
||||
Fixes: https://savannah.gnu.org/bugs/?64376
|
||||
|
||||
Signed-off-by: Jon DeVree <nuxi@vault24.org>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
|
||||
Tested-by: Marta Lewandowska <mlewando@redhat.com>
|
||||
---
|
||||
grub-core/fs/xfs.c | 52 +++++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 38 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index a779eb6b8334..e178ffcdc290 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -223,6 +223,12 @@ struct grub_xfs_inode
|
||||
/* Size of struct grub_xfs_inode v2, up to unused4 member included. */
|
||||
#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76)
|
||||
|
||||
+struct grub_xfs_dir_leaf_entry
|
||||
+{
|
||||
+ grub_uint32_t hashval;
|
||||
+ grub_uint32_t address;
|
||||
+} GRUB_PACKED;
|
||||
+
|
||||
struct grub_xfs_dirblock_tail
|
||||
{
|
||||
grub_uint32_t leaf_count;
|
||||
@@ -900,9 +906,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
{
|
||||
struct grub_xfs_dir2_entry *direntry =
|
||||
grub_xfs_first_de(dir->data, dirblock);
|
||||
- int entries;
|
||||
- struct grub_xfs_dirblock_tail *tail =
|
||||
- grub_xfs_dir_tail(dir->data, dirblock);
|
||||
+ int entries = -1;
|
||||
+ char *end = dirblock + dirblk_size;
|
||||
|
||||
numread = grub_xfs_read_file (dir, 0, 0,
|
||||
blk << dirblk_log2,
|
||||
@@ -913,14 +918,27 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- entries = (grub_be_to_cpu32 (tail->leaf_count)
|
||||
- - grub_be_to_cpu32 (tail->leaf_stale));
|
||||
+ /*
|
||||
+ * Leaf and tail information are only in the data block if the number
|
||||
+ * of extents is 1.
|
||||
+ */
|
||||
+ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
|
||||
+ {
|
||||
+ struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock);
|
||||
+
|
||||
+ end = (char *) tail;
|
||||
+
|
||||
+ /* Subtract the space used by leaf nodes. */
|
||||
+ end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry);
|
||||
|
||||
- if (!entries)
|
||||
- continue;
|
||||
+ entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale);
|
||||
+
|
||||
+ if (!entries)
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
/* Iterate over all entries within this block. */
|
||||
- while ((char *)direntry < (char *)tail)
|
||||
+ while ((char *) direntry < (char *) end)
|
||||
{
|
||||
grub_uint8_t *freetag;
|
||||
char *filename;
|
||||
@@ -940,7 +958,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
}
|
||||
|
||||
filename = (char *)(direntry + 1);
|
||||
- if (filename + direntry->len - 1 > (char *) tail)
|
||||
+ if (filename + direntry->len + 1 > (char *) end)
|
||||
return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
|
||||
|
||||
/* The byte after the filename is for the filetype, padding, or
|
||||
@@ -954,11 +972,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
return 1;
|
||||
}
|
||||
|
||||
- /* Check if last direntry in this block is
|
||||
- reached. */
|
||||
- entries--;
|
||||
- if (!entries)
|
||||
- break;
|
||||
+ /*
|
||||
+ * The expected number of directory entries is only tracked for the
|
||||
+ * single extent case.
|
||||
+ */
|
||||
+ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
|
||||
+ {
|
||||
+ /* Check if last direntry in this block is reached. */
|
||||
+ entries--;
|
||||
+ if (!entries)
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
/* Select the next directory entry. */
|
||||
direntry = grub_xfs_next_de(dir->data, direntry);
|
||||
--
|
||||
2.46.1
|
||||
|
||||
@ -0,0 +1,119 @@
|
||||
From 16ff7f17e65503ed53758ccc0245c1fabd444fb2 Mon Sep 17 00:00:00 2001
|
||||
From: Anthony Iliopoulos <ailiop@suse.com>
|
||||
Date: Thu, 26 Oct 2023 11:53:39 +0200
|
||||
Subject: [PATCH 462/464] fs/xfs: Add large extent counters incompat feature
|
||||
support
|
||||
|
||||
XFS introduced 64-bit extent counters for inodes via a series of
|
||||
upstream commits and the feature was marked as stable in v6.5 via
|
||||
commit 61d7e8274cd8 (xfs: drop EXPERIMENTAL tag for large extent
|
||||
counts).
|
||||
|
||||
Further, xfsprogs release v6.5.0 switched this feature on by default
|
||||
in mkfs.xfs via commit e5b18d7d1d96 (mkfs: enable large extent counts
|
||||
by default).
|
||||
|
||||
Filesystems formatted with large extent count support, nrext64=1, are
|
||||
thus currently not recognizable by GRUB, since this is an incompat
|
||||
feature. Add the required support so that those filesystems and inodes
|
||||
with large extent counters can be read by GRUB.
|
||||
|
||||
Signed-off-by: Anthony Iliopoulos <ailiop@suse.com>
|
||||
Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Marta Lewandowska <mlewando@redhat.com>
|
||||
Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
|
||||
---
|
||||
grub-core/fs/xfs.c | 30 +++++++++++++++++++++++++-----
|
||||
1 file changed, 25 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index e178ffcdc290..70c9f449b133 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -79,6 +79,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
/* Inode flags2 flags */
|
||||
#define XFS_DIFLAG2_BIGTIME_BIT 3
|
||||
#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT)
|
||||
+#define XFS_DIFLAG2_NREXT64_BIT 4
|
||||
+#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT)
|
||||
|
||||
/* incompat feature flags */
|
||||
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
|
||||
@@ -86,6 +88,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
|
||||
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
|
||||
#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */
|
||||
+#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */
|
||||
|
||||
/*
|
||||
* Directory entries with ftype are explicitly handled by GRUB code.
|
||||
@@ -101,7 +104,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
XFS_SB_FEAT_INCOMPAT_SPINODES | \
|
||||
XFS_SB_FEAT_INCOMPAT_META_UUID | \
|
||||
XFS_SB_FEAT_INCOMPAT_BIGTIME | \
|
||||
- XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR)
|
||||
+ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \
|
||||
+ XFS_SB_FEAT_INCOMPAT_NREXT64)
|
||||
|
||||
struct grub_xfs_sblock
|
||||
{
|
||||
@@ -203,7 +207,8 @@ struct grub_xfs_inode
|
||||
grub_uint16_t mode;
|
||||
grub_uint8_t version;
|
||||
grub_uint8_t format;
|
||||
- grub_uint8_t unused2[26];
|
||||
+ grub_uint8_t unused2[18];
|
||||
+ grub_uint64_t nextents_big;
|
||||
grub_uint64_t atime;
|
||||
grub_uint64_t mtime;
|
||||
grub_uint64_t ctime;
|
||||
@@ -547,11 +552,26 @@ get_fsb (const void *keys, int idx)
|
||||
return grub_be_to_cpu64 (grub_get_unaligned64 (p));
|
||||
}
|
||||
|
||||
+static int
|
||||
+grub_xfs_inode_has_large_extent_counts (const struct grub_xfs_inode *inode)
|
||||
+{
|
||||
+ return inode->version >= 3 &&
|
||||
+ (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_NREXT64));
|
||||
+}
|
||||
+
|
||||
+static grub_uint64_t
|
||||
+grub_xfs_get_inode_nextents (struct grub_xfs_inode *inode)
|
||||
+{
|
||||
+ return (grub_xfs_inode_has_large_extent_counts (inode)) ?
|
||||
+ grub_be_to_cpu64 (inode->nextents_big) :
|
||||
+ grub_be_to_cpu32 (inode->nextents);
|
||||
+}
|
||||
+
|
||||
static grub_disk_addr_t
|
||||
grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
{
|
||||
struct grub_xfs_btree_node *leaf = 0;
|
||||
- int ex, nrec;
|
||||
+ grub_uint64_t ex, nrec;
|
||||
struct grub_xfs_extent *exts;
|
||||
grub_uint64_t ret = 0;
|
||||
|
||||
@@ -576,7 +596,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
/ (2 * sizeof (grub_uint64_t));
|
||||
do
|
||||
{
|
||||
- int i;
|
||||
+ grub_uint64_t i;
|
||||
grub_addr_t keys_end, data_end;
|
||||
|
||||
if (grub_mul (sizeof (grub_uint64_t), nrec, &keys_end) ||
|
||||
@@ -634,7 +654,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
grub_addr_t exts_end = 0;
|
||||
grub_addr_t data_end = 0;
|
||||
|
||||
- nrec = grub_be_to_cpu32 (node->inode.nextents);
|
||||
+ nrec = grub_xfs_get_inode_nextents (&node->inode);
|
||||
exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode);
|
||||
|
||||
if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) ||
|
||||
--
|
||||
2.46.1
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
From 300b38fdf7036bf3b2f6244456e1adb3f9c1c359 Mon Sep 17 00:00:00 2001
|
||||
From: Jon DeVree <nuxi@vault24.org>
|
||||
Date: Sun, 11 Feb 2024 10:34:58 -0500
|
||||
Subject: [PATCH 463/464] fs/xfs: Handle non-continuous data blocks in
|
||||
directory extents
|
||||
|
||||
The directory extent list does not have to be a continuous list of data
|
||||
blocks. When GRUB tries to read a non-existant member of the list,
|
||||
grub_xfs_read_file() will return a block of zero'ed memory. Checking for
|
||||
a zero'ed magic number is sufficient to skip this non-existant data block.
|
||||
|
||||
Prior to commit 07318ee7e (fs/xfs: Fix XFS directory extent parsing)
|
||||
this was handled as a subtle side effect of reading the (non-existant)
|
||||
tail data structure. Since the block was zero'ed the computation of the
|
||||
number of directory entries in the block would return 0 as well.
|
||||
|
||||
Fixes: 07318ee7e (fs/xfs: Fix XFS directory extent parsing)
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2254370
|
||||
|
||||
Signed-off-by: Jon DeVree <nuxi@vault24.org>
|
||||
Reviewed-By: Vladimir Serbinenko <phcoder@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/xfs.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index 70c9f449b133..ab1281497472 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -928,6 +928,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
grub_xfs_first_de(dir->data, dirblock);
|
||||
int entries = -1;
|
||||
char *end = dirblock + dirblk_size;
|
||||
+ grub_uint32_t magic;
|
||||
|
||||
numread = grub_xfs_read_file (dir, 0, 0,
|
||||
blk << dirblk_log2,
|
||||
@@ -938,6 +939,15 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * If this data block isn't actually part of the extent list then
|
||||
+ * grub_xfs_read_file() returns a block of zeros. So, if the magic
|
||||
+ * number field is all zeros then this block should be skipped.
|
||||
+ */
|
||||
+ magic = *(grub_uint32_t *)(void *) dirblock;
|
||||
+ if (!magic)
|
||||
+ continue;
|
||||
+
|
||||
/*
|
||||
* Leaf and tail information are only in the data block if the number
|
||||
* of extents is 1.
|
||||
--
|
||||
2.46.1
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
From 6c6b8bebde2261aac2fbe7abd6d03008a5e06ce9 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Sandeen <sandeen@redhat.com>
|
||||
Date: Wed, 4 Dec 2024 07:50:28 -0600
|
||||
Subject: [PATCH 464/464] fs/xfs: fix large extent counters incompat feature
|
||||
support
|
||||
|
||||
When large extent counter / NREXT64 support was added to grub, it missed
|
||||
a couple of direct reads of nextents which need to be changed to the new
|
||||
NREXT64-aware helper as well. Without this, we'll have mis-reads of some
|
||||
directories with this feature enabled.
|
||||
|
||||
(The large extent counter fix likely raced on merge with
|
||||
07318ee7e ("fs/xfs: Fix XFS directory extent parsing") which added the new
|
||||
direct nextents reads just prior, causing this issue.)
|
||||
|
||||
Fixes: aa7c1322671e ("fs/xfs: Add large extent counters incompat feature support")
|
||||
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||
Reviewed-by: Anthony Iliopoulos <ailiop@suse.com>
|
||||
Reviewed-by: Jon DeVree <nuxi@vault24.org>
|
||||
---
|
||||
grub-core/fs/xfs.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index ab1281497472..c60db73613c5 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -952,7 +952,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
* Leaf and tail information are only in the data block if the number
|
||||
* of extents is 1.
|
||||
*/
|
||||
- if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
|
||||
+ if (grub_xfs_get_inode_nextents(&dir->inode) == 1)
|
||||
{
|
||||
struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock);
|
||||
|
||||
@@ -1006,7 +1006,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
* The expected number of directory entries is only tracked for the
|
||||
* single extent case.
|
||||
*/
|
||||
- if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
|
||||
+ if (grub_xfs_get_inode_nextents(&dir->inode) == 1)
|
||||
{
|
||||
/* Check if last direntry in this block is reached. */
|
||||
entries--;
|
||||
--
|
||||
2.46.1
|
||||
|
||||
167
SOURCES/0465-grub-mkimage-Create-new-ELF-note-for-SBAT.patch
Normal file
167
SOURCES/0465-grub-mkimage-Create-new-ELF-note-for-SBAT.patch
Normal file
@ -0,0 +1,167 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Wed, 23 Oct 2024 17:54:32 +0530
|
||||
Subject: [PATCH] grub-mkimage: Create new ELF note for SBAT
|
||||
|
||||
In order to store the SBAT data we create a new ELF note. The string
|
||||
".sbat", zero-padded to 4 byte alignment, shall be entered in the name
|
||||
field. The string "SBAT"'s ASCII values, 0x53424154, should be entered
|
||||
in the type field.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
include/grub/util/mkimage.h | 4 ++--
|
||||
util/grub-mkimagexx.c | 48 +++++++++++++++++++++++++++++++++++++++++++--
|
||||
util/mkimage.c | 5 +++--
|
||||
3 files changed, 51 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
|
||||
index 6f1da89b9b65..881e3031f41f 100644
|
||||
--- a/include/grub/util/mkimage.h
|
||||
+++ b/include/grub/util/mkimage.h
|
||||
@@ -51,12 +51,12 @@ grub_mkimage_load_image64 (const char *kernel_path,
|
||||
const struct grub_install_image_target_desc *image_target);
|
||||
void
|
||||
grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
|
||||
- int note, size_t appsig_size, char **core_img, size_t *core_size,
|
||||
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
||||
Elf32_Addr target_addr,
|
||||
struct grub_mkimage_layout *layout);
|
||||
void
|
||||
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
|
||||
- int note, size_t appsig_size, char **core_img, size_t *core_size,
|
||||
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
||||
Elf64_Addr target_addr,
|
||||
struct grub_mkimage_layout *layout);
|
||||
|
||||
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
|
||||
index 393119486d3f..3609015673ec 100644
|
||||
--- a/util/grub-mkimagexx.c
|
||||
+++ b/util/grub-mkimagexx.c
|
||||
@@ -115,6 +115,14 @@ struct section_metadata
|
||||
const char *strtab;
|
||||
};
|
||||
|
||||
+#define GRUB_SBAT_NOTE_NAME ".sbat"
|
||||
+#define GRUB_SBAT_NOTE_TYPE 0x53424154 /* "SBAT" */
|
||||
+
|
||||
+struct grub_sbat_note {
|
||||
+ Elf32_Nhdr header;
|
||||
+ char name[ALIGN_UP(sizeof(GRUB_SBAT_NOTE_NAME), 4)];
|
||||
+};
|
||||
+
|
||||
static int
|
||||
is_relocatable (const struct grub_install_image_target_desc *image_target)
|
||||
{
|
||||
@@ -216,7 +224,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
|
||||
|
||||
void
|
||||
SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
|
||||
- int note, size_t appsig_size, char **core_img, size_t *core_size,
|
||||
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
||||
Elf_Addr target_addr,
|
||||
struct grub_mkimage_layout *layout)
|
||||
{
|
||||
@@ -225,10 +233,17 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
||||
Elf_Ehdr *ehdr;
|
||||
Elf_Phdr *phdr;
|
||||
Elf_Shdr *shdr;
|
||||
- int header_size, footer_size = 0;
|
||||
+ int header_size, footer_size = 0, footer_offset = 0;
|
||||
int phnum = 1;
|
||||
int shnum = 4;
|
||||
int string_size = sizeof (".text") + sizeof ("mods") + 1;
|
||||
+ char *footer;
|
||||
+
|
||||
+ if (sbat)
|
||||
+ {
|
||||
+ phnum++;
|
||||
+ footer_size += ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
|
||||
+ }
|
||||
|
||||
if (appsig_size)
|
||||
{
|
||||
@@ -262,6 +277,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
||||
ehdr = (void *) elf_img;
|
||||
phdr = (void *) (elf_img + sizeof (*ehdr));
|
||||
shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
|
||||
+ footer = elf_img + program_size + header_size;
|
||||
memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
|
||||
ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
|
||||
if (!image_target->bigendian)
|
||||
@@ -434,6 +450,8 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
||||
phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
|
||||
phdr->p_memsz = 0;
|
||||
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
|
||||
+ footer = ptr;
|
||||
+ footer_offset = XEN_NOTE_SIZE;
|
||||
}
|
||||
|
||||
if (image_target->id == IMAGE_XEN_PVH)
|
||||
@@ -467,6 +485,8 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
||||
phdr->p_filesz = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
|
||||
phdr->p_memsz = 0;
|
||||
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
|
||||
+ footer = ptr;
|
||||
+ footer_offset = XEN_PVH_NOTE_SIZE;
|
||||
}
|
||||
|
||||
if (note)
|
||||
@@ -497,6 +517,30 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
||||
phdr->p_filesz = grub_host_to_target32 (note_size);
|
||||
phdr->p_memsz = 0;
|
||||
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
|
||||
+ footer = (elf_img + program_size + header_size + note_size);
|
||||
+ footer_offset += note_size;
|
||||
+ }
|
||||
+
|
||||
+ if (sbat)
|
||||
+ {
|
||||
+ int note_size = ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
|
||||
+ struct grub_sbat_note *note_ptr = (struct grub_sbat_note *) footer;
|
||||
+
|
||||
+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_SBAT_NOTE_NAME));
|
||||
+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(layout->sbat_size, 4));
|
||||
+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_SBAT_NOTE_TYPE);
|
||||
+ memcpy (note_ptr->name, GRUB_SBAT_NOTE_NAME, sizeof (GRUB_SBAT_NOTE_NAME));
|
||||
+ memcpy ((char *)(note_ptr + 1), sbat, layout->sbat_size);
|
||||
+
|
||||
+ phdr++;
|
||||
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
|
||||
+ phdr->p_flags = grub_host_to_target32 (PF_R);
|
||||
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
|
||||
+ phdr->p_vaddr = 0;
|
||||
+ phdr->p_paddr = 0;
|
||||
+ phdr->p_filesz = grub_host_to_target32 (note_size);
|
||||
+ phdr->p_memsz = 0;
|
||||
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
|
||||
}
|
||||
|
||||
if (appsig_size) {
|
||||
diff --git a/util/mkimage.c b/util/mkimage.c
|
||||
index 9ba1a8988f19..358db8378422 100644
|
||||
--- a/util/mkimage.c
|
||||
+++ b/util/mkimage.c
|
||||
@@ -1811,6 +1811,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
case IMAGE_I386_IEEE1275:
|
||||
{
|
||||
grub_uint64_t target_addr;
|
||||
+ char *sbat = NULL;
|
||||
if (image_target->id == IMAGE_LOONGSON_ELF)
|
||||
{
|
||||
if (comp == GRUB_COMPRESSION_NONE)
|
||||
@@ -1822,10 +1823,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
else
|
||||
target_addr = image_target->link_addr;
|
||||
if (image_target->voidp_sizeof == 4)
|
||||
- grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
|
||||
+ grub_mkimage_generate_elf32 (image_target, note, appsig_size, sbat, &core_img,
|
||||
&core_size, target_addr, &layout);
|
||||
else
|
||||
- grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
|
||||
+ grub_mkimage_generate_elf64 (image_target, note, appsig_size, sbat, &core_img,
|
||||
&core_size, target_addr, &layout);
|
||||
}
|
||||
break;
|
||||
@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Wed, 23 Oct 2024 17:54:33 +0530
|
||||
Subject: [PATCH] grub-mkimage: Add SBAT metadata into ELF note for PowerPC
|
||||
targets
|
||||
|
||||
The SBAT metadata is read from CSV file and transformed into an ELF note
|
||||
with the -s option.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
util/mkimage.c | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/util/mkimage.c b/util/mkimage.c
|
||||
index 358db8378422..eaa382b2a120 100644
|
||||
--- a/util/mkimage.c
|
||||
+++ b/util/mkimage.c
|
||||
@@ -941,8 +941,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
total_module_size += dtb_size + sizeof (struct grub_module_header);
|
||||
}
|
||||
|
||||
- if (sbat_path != NULL && image_target->id != IMAGE_EFI)
|
||||
- grub_util_error (_(".sbat section can be embedded into EFI images only"));
|
||||
+ if (sbat_path != NULL && (image_target->id != IMAGE_EFI && image_target->id != IMAGE_PPC))
|
||||
+ grub_util_error (_("SBAT data can be added only to EFI or powerpc-ieee1275 images"));
|
||||
|
||||
if (disable_shim_lock)
|
||||
total_module_size += sizeof (struct grub_module_header);
|
||||
@@ -1812,6 +1812,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
{
|
||||
grub_uint64_t target_addr;
|
||||
char *sbat = NULL;
|
||||
+ if (sbat_path != NULL)
|
||||
+ {
|
||||
+ sbat_size = grub_util_get_image_size (sbat_path);
|
||||
+ sbat = xmalloc (sbat_size);
|
||||
+ grub_util_load_image (sbat_path, sbat);
|
||||
+ layout.sbat_size = sbat_size;
|
||||
+ }
|
||||
if (image_target->id == IMAGE_LOONGSON_ELF)
|
||||
{
|
||||
if (comp == GRUB_COMPRESSION_NONE)
|
||||
2720
SOURCES/0467-appended-sig-sync-d-with-upstream-code.patch
Normal file
2720
SOURCES/0467-appended-sig-sync-d-with-upstream-code.patch
Normal file
File diff suppressed because it is too large
Load Diff
200
SOURCES/0468-ieee1275-Platform-Keystore-PKS-Support.patch
Normal file
200
SOURCES/0468-ieee1275-Platform-Keystore-PKS-Support.patch
Normal file
@ -0,0 +1,200 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:35 +0530
|
||||
Subject: [PATCH] ieee1275: Platform Keystore (PKS) Support
|
||||
|
||||
enhancing the infrastructure to enable the Platform Keystore (PKS) feature,
|
||||
which provides access to the SB VERSION, DB, and DBX secure boot variables
|
||||
from PKS.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
grub-core/Makefile.core.def | 1 +
|
||||
grub-core/kern/powerpc/ieee1275/ieee1275.c | 140 +++++++++++++++++++++++++++++
|
||||
include/grub/powerpc/ieee1275/ieee1275.h | 14 +++
|
||||
3 files changed, 155 insertions(+)
|
||||
create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 3740330..05b9c8d 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -320,6 +320,7 @@ kernel = {
|
||||
extra_dist = video/sis315_init.c;
|
||||
mips_loongson = commands/keylayouts.c;
|
||||
|
||||
+ powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c;
|
||||
powerpc_ieee1275 = kern/powerpc/cache.S;
|
||||
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||||
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
|
||||
diff --git a/grub-core/kern/powerpc/ieee1275/ieee1275.c b/grub-core/kern/powerpc/ieee1275/ieee1275.c
|
||||
new file mode 100644
|
||||
index 0000000..f685afc
|
||||
--- /dev/null
|
||||
+++ b/grub-core/kern/powerpc/ieee1275/ieee1275.c
|
||||
@@ -0,0 +1,140 @@
|
||||
+/* of.c - Access the Open Firmware client interface. */
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
+ *
|
||||
+ * GRUB is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * GRUB is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+#include <grub/ieee1275/ieee1275.h>
|
||||
+#include <grub/powerpc/ieee1275/ieee1275.h>
|
||||
+#include <grub/misc.h>
|
||||
+
|
||||
+#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) - 1)
|
||||
+
|
||||
+int
|
||||
+grub_ieee1275_test (const char *name, grub_ieee1275_cell_t *missing)
|
||||
+{
|
||||
+ struct test_args
|
||||
+ {
|
||||
+ struct grub_ieee1275_common_hdr common;
|
||||
+ grub_ieee1275_cell_t name;
|
||||
+ grub_ieee1275_cell_t missing;
|
||||
+ } args;
|
||||
+
|
||||
+ INIT_IEEE1275_COMMON (&args.common, "test", 1, 1);
|
||||
+ args.name = (grub_ieee1275_cell_t) name;
|
||||
+
|
||||
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (args.missing == IEEE1275_CELL_INVALID)
|
||||
+ return -1;
|
||||
+
|
||||
+ *missing = args.missing;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+grub_ieee1275_pks_max_object_size (grub_size_t *result)
|
||||
+{
|
||||
+ struct mos_args
|
||||
+ {
|
||||
+ struct grub_ieee1275_common_hdr common;
|
||||
+ grub_ieee1275_cell_t size;
|
||||
+ } args;
|
||||
+
|
||||
+ INIT_IEEE1275_COMMON (&args.common, "pks-max-object-size", 0, 1);
|
||||
+
|
||||
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (args.size == IEEE1275_CELL_INVALID)
|
||||
+ return -1;
|
||||
+
|
||||
+ *result = args.size;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+grub_ieee1275_pks_read_object (grub_uint8_t consumer, grub_uint8_t *label,
|
||||
+ grub_size_t label_len, grub_uint8_t *buffer,
|
||||
+ grub_size_t buffer_len, grub_size_t *data_len,
|
||||
+ grub_uint32_t *policies)
|
||||
+{
|
||||
+ struct pks_read_args
|
||||
+ {
|
||||
+ struct grub_ieee1275_common_hdr common;
|
||||
+ grub_ieee1275_cell_t consumer;
|
||||
+ grub_ieee1275_cell_t label;
|
||||
+ grub_ieee1275_cell_t label_len;
|
||||
+ grub_ieee1275_cell_t buffer;
|
||||
+ grub_ieee1275_cell_t buffer_len;
|
||||
+ grub_ieee1275_cell_t data_len;
|
||||
+ grub_ieee1275_cell_t policies;
|
||||
+ grub_ieee1275_cell_t rc;
|
||||
+ } args;
|
||||
+
|
||||
+ INIT_IEEE1275_COMMON (&args.common, "pks-read-object", 5, 3);
|
||||
+ args.consumer = (grub_ieee1275_cell_t) consumer;
|
||||
+ args.label = (grub_ieee1275_cell_t) label;
|
||||
+ args.label_len = (grub_ieee1275_cell_t) label_len;
|
||||
+ args.buffer = (grub_ieee1275_cell_t) buffer;
|
||||
+ args.buffer_len = (grub_ieee1275_cell_t) buffer_len;
|
||||
+
|
||||
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (args.data_len == IEEE1275_CELL_INVALID)
|
||||
+ return -1;
|
||||
+
|
||||
+ *data_len = args.data_len;
|
||||
+ *policies = args.policies;
|
||||
+
|
||||
+ return (int) args.rc;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+grub_ieee1275_pks_read_sbvar (grub_uint8_t sbvarflags, grub_uint8_t sbvartype,
|
||||
+ grub_uint8_t *buffer, grub_size_t buffer_len,
|
||||
+ grub_size_t *data_len)
|
||||
+{
|
||||
+ struct pks_read_sbvar_args
|
||||
+ {
|
||||
+ struct grub_ieee1275_common_hdr common;
|
||||
+ grub_ieee1275_cell_t sbvarflags;
|
||||
+ grub_ieee1275_cell_t sbvartype;
|
||||
+ grub_ieee1275_cell_t buffer;
|
||||
+ grub_ieee1275_cell_t buffer_len;
|
||||
+ grub_ieee1275_cell_t data_len;
|
||||
+ grub_ieee1275_cell_t rc;
|
||||
+ } args;
|
||||
+
|
||||
+ INIT_IEEE1275_COMMON (&args.common, "pks-read-sbvar", 4, 2);
|
||||
+ args.sbvarflags = (grub_ieee1275_cell_t) sbvarflags;
|
||||
+ args.sbvartype = (grub_ieee1275_cell_t) sbvartype;
|
||||
+ args.buffer = (grub_ieee1275_cell_t) buffer;
|
||||
+ args.buffer_len = (grub_ieee1275_cell_t) buffer_len;
|
||||
+
|
||||
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (args.data_len == IEEE1275_CELL_INVALID)
|
||||
+ return -1;
|
||||
+
|
||||
+ *data_len = args.data_len;
|
||||
+
|
||||
+ return (int) args.rc;
|
||||
+}
|
||||
diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h
|
||||
index 3c7683f..45c7b16 100644
|
||||
--- a/include/grub/powerpc/ieee1275/ieee1275.h
|
||||
+++ b/include/grub/powerpc/ieee1275/ieee1275.h
|
||||
@@ -25,4 +25,18 @@
|
||||
#define GRUB_IEEE1275_CELL_SIZEOF 4
|
||||
typedef grub_uint32_t grub_ieee1275_cell_t;
|
||||
|
||||
+int EXPORT_FUNC (grub_ieee1275_test) (const char *name,
|
||||
+ grub_ieee1275_cell_t *missing);
|
||||
+
|
||||
+int grub_ieee1275_pks_max_object_size (grub_size_t *result);
|
||||
+
|
||||
+int grub_ieee1275_pks_read_object (grub_uint8_t consumer, grub_uint8_t *label,
|
||||
+ grub_size_t label_len, grub_uint8_t *buffer,
|
||||
+ grub_size_t buffer_len, grub_size_t *data_len,
|
||||
+ grub_uint32_t *policies);
|
||||
+
|
||||
+int grub_ieee1275_pks_read_sbvar (grub_uint8_t sbvarflags, grub_uint8_t sbvartype,
|
||||
+ grub_uint8_t *buffer, grub_size_t buffer_len,
|
||||
+ grub_size_t *data_len);
|
||||
+
|
||||
#endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
|
||||
@ -0,0 +1,686 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:36 +0530
|
||||
Subject: [PATCH] ieee1275: Read the DB and DBX secure boot variables
|
||||
|
||||
If secure boot is enabled with PKS, it will read secure boot variables
|
||||
such as db and dbx from PKS and extract ESL's from it.
|
||||
The ESL's would be saved in the platform keystore buffer, and
|
||||
the appendedsig (module) would read it later to extract
|
||||
the certificate's details from ESL.
|
||||
|
||||
In the following scenarios, static key mode will be activated:
|
||||
1. When Secure Boot is enabled with static keys
|
||||
2. When SB Version is unavailable but Secure Boot is enabled
|
||||
3. When PKS support is unavailable but Secure Boot is enabled
|
||||
|
||||
Note:-
|
||||
|
||||
SB Version - Secure Boot mode
|
||||
1 - PKS
|
||||
0 - static key (embeded key)
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
grub-core/Makefile.am | 1 +
|
||||
grub-core/Makefile.core.def | 1 +
|
||||
grub-core/kern/ieee1275/init.c | 15 +-
|
||||
.../kern/powerpc/ieee1275/platform_keystore.c | 332 +++++++++++++++++++++
|
||||
include/grub/powerpc/ieee1275/platform_keystore.h | 225 ++++++++++++++
|
||||
include/grub/types.h | 8 +
|
||||
6 files changed, 580 insertions(+), 2 deletions(-)
|
||||
create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||
create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h
|
||||
|
||||
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
|
||||
index dd49939..a398a04 100644
|
||||
--- a/grub-core/Makefile.am
|
||||
+++ b/grub-core/Makefile.am
|
||||
@@ -245,6 +245,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||
endif
|
||||
|
||||
if COND_sparc64_ieee1275
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 05b9c8d..218068b 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -325,6 +325,7 @@ kernel = {
|
||||
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||||
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
|
||||
powerpc_ieee1275 = kern/lockdown.c;
|
||||
+ powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c;
|
||||
|
||||
sparc64_ieee1275 = kern/sparc64/cache.S;
|
||||
sparc64_ieee1275 = kern/sparc64/dl.c;
|
||||
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
|
||||
index bb791f8..b853f04 100644
|
||||
--- a/grub-core/kern/ieee1275/init.c
|
||||
+++ b/grub-core/kern/ieee1275/init.c
|
||||
@@ -47,6 +47,8 @@
|
||||
#include <grub/machine/kernel.h>
|
||||
#endif
|
||||
#include <grub/lockdown.h>
|
||||
+#include <grub/powerpc/ieee1275/ieee1275.h>
|
||||
+#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||
|
||||
/* The maximum heap size we're going to claim at boot. Not used by sparc. */
|
||||
#ifdef __i386__
|
||||
@@ -956,7 +958,7 @@ grub_get_ieee1275_secure_boot (void)
|
||||
{
|
||||
grub_ieee1275_phandle_t root;
|
||||
int rc;
|
||||
- grub_uint32_t is_sb;
|
||||
+ grub_uint32_t is_sb = 0;
|
||||
|
||||
grub_ieee1275_finddevice ("/", &root);
|
||||
|
||||
@@ -972,7 +974,16 @@ grub_get_ieee1275_secure_boot (void)
|
||||
* We only support enforce.
|
||||
*/
|
||||
if (rc >= 0 && is_sb >= 2)
|
||||
- grub_lockdown ();
|
||||
+ {
|
||||
+ grub_dprintf ("ieee1275", "Secure Boot Enabled\n");
|
||||
+ rc = grub_pks_keystore_init ();
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ grub_error (rc, "Initialization of the Platform Keystore failed!\n");
|
||||
+
|
||||
+ grub_lockdown ();
|
||||
+ }
|
||||
+ else
|
||||
+ grub_dprintf ("ieee1275", "Secure Boot Disabled\n");
|
||||
}
|
||||
|
||||
grub_addr_t grub_modbase;
|
||||
diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||
new file mode 100644
|
||||
index 0000000..cf1d055
|
||||
--- /dev/null
|
||||
+++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||
@@ -0,0 +1,332 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
+ * Copyright (C) 2024 IBM Corporation
|
||||
+ *
|
||||
+ * GRUB is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * GRUB is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include <grub/mm.h>
|
||||
+#include <grub/powerpc/ieee1275/ieee1275.h>
|
||||
+#include <grub/types.h>
|
||||
+#include <grub/misc.h>
|
||||
+#include <grub/lockdown.h>
|
||||
+#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||
+
|
||||
+#define PKS_CONSUMER_FW 1
|
||||
+#define SB_VERSION_KEY_NAME ((grub_uint8_t *) "SB_VERSION")
|
||||
+#define SB_VERSION_KEY_LEN 10
|
||||
+#define DB 1
|
||||
+#define DBX 2
|
||||
+#define PKS_OBJECT_NOT_FOUND ((grub_err_t) - 7)
|
||||
+
|
||||
+/* Platform Keystore */
|
||||
+static grub_size_t pks_max_object_size;
|
||||
+grub_uint8_t grub_pks_use_keystore = 0;
|
||||
+grub_pks_t grub_pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, .dbx_entries = 0 };
|
||||
+
|
||||
+/* Convert the esl data into the ESL */
|
||||
+static grub_esl_t *
|
||||
+convert_to_esl (const grub_uint8_t *esl_data, const grub_size_t esl_data_size)
|
||||
+{
|
||||
+ grub_esl_t *esl = NULL;
|
||||
+
|
||||
+ if (esl_data_size < sizeof (grub_esl_t) || esl_data == NULL)
|
||||
+ return esl;
|
||||
+
|
||||
+ esl = (grub_esl_t *) esl_data;
|
||||
+
|
||||
+ return esl;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Import the GUID, esd, and its size into the pks sd buffer and
|
||||
+ * pks sd entries from the EFI signature list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+esd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
|
||||
+ const grub_size_t signature_size, const grub_uuid_t *guid,
|
||||
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
|
||||
+{
|
||||
+ grub_esd_t *esd = NULL;
|
||||
+ grub_pks_sd_t *signature = *pks_sd;
|
||||
+ grub_size_t entries = *pks_sd_entries;
|
||||
+ grub_size_t data_size = 0, offset = 0;
|
||||
+
|
||||
+ /* reads the esd from esl */
|
||||
+ while (esl_size > 0)
|
||||
+ {
|
||||
+ esd = (grub_esd_t *) (esl_data + offset);
|
||||
+ data_size = signature_size - sizeof (grub_esd_t);
|
||||
+
|
||||
+ signature = grub_realloc (signature, (entries + 1) * sizeof (grub_pks_sd_t));
|
||||
+ if (signature == NULL)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+
|
||||
+ signature[entries].data = grub_malloc (data_size * sizeof (grub_uint8_t));
|
||||
+ if (signature[entries].data == NULL)
|
||||
+ {
|
||||
+ /*
|
||||
+ * allocated memory will be freed by
|
||||
+ * grub_free_platform_keystore
|
||||
+ */
|
||||
+ *pks_sd = signature;
|
||||
+ *pks_sd_entries = entries + 1;
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+ }
|
||||
+
|
||||
+ grub_memcpy (signature[entries].data, esd->signaturedata, data_size);
|
||||
+ signature[entries].data_size = data_size;
|
||||
+ signature[entries].guid = *guid;
|
||||
+ entries++;
|
||||
+ esl_size -= signature_size;
|
||||
+ offset += signature_size;
|
||||
+ }
|
||||
+
|
||||
+ *pks_sd = signature;
|
||||
+ *pks_sd_entries = entries;
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Extract the esd after removing the esl header from esl.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+esl_to_esd (const grub_uint8_t *esl_data, grub_size_t *next_esl,
|
||||
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
|
||||
+{
|
||||
+ grub_uuid_t guid = { 0 };
|
||||
+ grub_esl_t *esl = NULL;
|
||||
+ grub_size_t offset = 0, esl_size = 0,
|
||||
+ signature_size = 0, signature_header_size = 0;
|
||||
+
|
||||
+ esl = convert_to_esl (esl_data, *next_esl);
|
||||
+ if (esl == NULL)
|
||||
+ return grub_error (GRUB_ERR_BUG, "invalid ESL");
|
||||
+
|
||||
+ esl_size = grub_le_to_cpu32 (esl->signaturelistsize);
|
||||
+ signature_header_size = grub_le_to_cpu32 (esl->signatureheadersize);
|
||||
+ signature_size = grub_le_to_cpu32 (esl->signaturesize);
|
||||
+ guid = esl->signaturetype;
|
||||
+
|
||||
+ if (esl_size < sizeof (grub_esl_t) || esl_size > *next_esl)
|
||||
+ return grub_error (GRUB_ERR_BUG, "invalid ESL size (%u)\n", esl_size);
|
||||
+
|
||||
+ *next_esl = esl_size;
|
||||
+ offset = sizeof (grub_esl_t) + signature_header_size;
|
||||
+ esl_size = esl_size - offset;
|
||||
+
|
||||
+ return esd_from_esl (esl_data + offset, esl_size, signature_size, &guid,
|
||||
+ pks_sd, pks_sd_entries);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Import the EFI signature data and the number of esd from the esl
|
||||
+ * into the pks sd buffer and pks sd entries.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+pks_sd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
|
||||
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_size_t next_esl = esl_size;
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ rc = esl_to_esd (esl_data, &next_esl, pks_sd, pks_sd_entries);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ break;
|
||||
+
|
||||
+ esl_data += next_esl;
|
||||
+ esl_size -= next_esl;
|
||||
+ next_esl = esl_size;
|
||||
+ }
|
||||
+ while (esl_size > 0);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Read the secure boot version from PKS as an object.
|
||||
+ * caller must free result
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+read_sbversion_from_pks (grub_uint8_t **out, grub_size_t *outlen, grub_size_t *policy)
|
||||
+{
|
||||
+ *out = grub_malloc (pks_max_object_size);
|
||||
+ if (*out == NULL)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+
|
||||
+ return grub_ieee1275_pks_read_object (PKS_CONSUMER_FW, SB_VERSION_KEY_NAME,
|
||||
+ SB_VERSION_KEY_LEN, *out, pks_max_object_size,
|
||||
+ outlen, policy);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * reads the secure boot variable from PKS.
|
||||
+ * caller must free result
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+read_sbvar_from_pks (const grub_uint8_t sbvarflags, const grub_uint8_t sbvartype,
|
||||
+ grub_uint8_t **out, grub_size_t *outlen)
|
||||
+{
|
||||
+ *out = grub_malloc (pks_max_object_size);
|
||||
+ if (*out == NULL)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+
|
||||
+ return grub_ieee1275_pks_read_sbvar (sbvarflags, sbvartype, *out,
|
||||
+ pks_max_object_size, outlen);
|
||||
+}
|
||||
+
|
||||
+/* Test the availability of PKS support. */
|
||||
+static grub_err_t
|
||||
+is_support_pks (void)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_ieee1275_cell_t missing = 0;
|
||||
+
|
||||
+ rc = grub_ieee1275_test ("pks-max-object-size", &missing);
|
||||
+ if (rc != GRUB_ERR_NONE || (int) missing == -1)
|
||||
+ rc = grub_error (GRUB_ERR_BAD_FIRMWARE, "Firmware doesn't have PKS support!\n");
|
||||
+ else
|
||||
+ {
|
||||
+ rc = grub_ieee1275_pks_max_object_size (&pks_max_object_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ rc = grub_error (GRUB_ERR_BAD_NUMBER, "PKS support is there but it has zero objects!\n");
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Retrieve the secure boot variable from PKS, unpacks it, read the esd
|
||||
+ * from ESL, and store the information in the pks sd buffer.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+read_secure_boot_variables (const grub_uint8_t sbvarflags, const grub_uint8_t sbvartype,
|
||||
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_uint8_t *esl_data = NULL;
|
||||
+ grub_size_t esl_data_size = 0;
|
||||
+
|
||||
+ rc = read_sbvar_from_pks (sbvarflags, sbvartype, &esl_data, &esl_data_size);
|
||||
+ /*
|
||||
+ * at this point we have SB_VERSION, so any error is worth
|
||||
+ * at least some user-visible info
|
||||
+ */
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ rc = grub_error (rc, "secure boot variable %s reading (%d)",
|
||||
+ (sbvartype == DB ? "db" : "dbx"), rc);
|
||||
+ else if (esl_data_size != 0)
|
||||
+ rc = pks_sd_from_esl ((const grub_uint8_t *) esl_data, esl_data_size,
|
||||
+ pks_sd, pks_sd_entries);
|
||||
+ grub_free (esl_data);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/* reads secure boot version (SB_VERSION) and it supports following
|
||||
+ * SB_VERSION
|
||||
+ * 1 - PKS
|
||||
+ * 0 - static key (embeded key)
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+get_secure_boot_version (void)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_uint8_t *data = NULL;
|
||||
+ grub_size_t len = 0, policy = 0;
|
||||
+
|
||||
+ rc = read_sbversion_from_pks (&data, &len, &policy);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ rc = grub_error (GRUB_ERR_READ_ERROR, "SB version read failed! (%d)\n", rc);
|
||||
+ else if (len != 1 || (*data >= 2))
|
||||
+ rc = grub_error (GRUB_ERR_BAD_NUMBER, "found unexpected SB version! (%d)\n", *data);
|
||||
+
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_printf ("Switch to Static Key!\n");
|
||||
+ if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
|
||||
+ grub_fatal ("Secure Boot locked down");
|
||||
+ }
|
||||
+ else
|
||||
+ grub_pks_use_keystore = *data;
|
||||
+
|
||||
+ grub_free (data);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/* Free allocated memory */
|
||||
+void
|
||||
+grub_pks_free_keystore (void)
|
||||
+{
|
||||
+ grub_size_t i = 0;
|
||||
+
|
||||
+ for (i = 0; i < grub_pks_keystore.db_entries; i++)
|
||||
+ grub_free (grub_pks_keystore.db[i].data);
|
||||
+
|
||||
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
|
||||
+ grub_free (grub_pks_keystore.dbx[i].data);
|
||||
+
|
||||
+ grub_free (grub_pks_keystore.db);
|
||||
+ grub_free (grub_pks_keystore.dbx);
|
||||
+ grub_memset (&grub_pks_keystore, 0, sizeof (grub_pks_t));
|
||||
+}
|
||||
+
|
||||
+/* Initialization of the Platform Keystore */
|
||||
+grub_err_t
|
||||
+grub_pks_keystore_init (void)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+
|
||||
+ grub_dprintf ("ieee1275", "trying to load Platform Keystore\n");
|
||||
+
|
||||
+ rc = is_support_pks ();
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_printf ("Switch to Static Key!\n");
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ /* SB_VERSION */
|
||||
+ rc = get_secure_boot_version ();
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ return rc;
|
||||
+
|
||||
+ if (grub_pks_use_keystore)
|
||||
+ {
|
||||
+ grub_memset (&grub_pks_keystore, 0, sizeof (grub_pks_t));
|
||||
+ /* DB */
|
||||
+ rc = read_secure_boot_variables (0, DB, &grub_pks_keystore.db, &grub_pks_keystore.db_entries);
|
||||
+ if (rc == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ /* DBX */
|
||||
+ rc = read_secure_boot_variables (0, DBX, &grub_pks_keystore.dbx, &grub_pks_keystore.dbx_entries);
|
||||
+ if (rc == PKS_OBJECT_NOT_FOUND)
|
||||
+ {
|
||||
+ grub_dprintf ("ieee1275", "dbx is not found in PKS\n");
|
||||
+ rc = GRUB_ERR_NONE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ grub_pks_free_keystore ();
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
diff --git a/include/grub/powerpc/ieee1275/platform_keystore.h b/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||
new file mode 100644
|
||||
index 0000000..0641adb
|
||||
--- /dev/null
|
||||
+++ b/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||
@@ -0,0 +1,225 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. This
|
||||
+ * program and the accompanying materials are licensed and made available
|
||||
+ * under the terms and conditions of the 2-Clause BSD License which
|
||||
+ * accompanies this distribution.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright notice,
|
||||
+ * this list of conditions and the following disclaimer.
|
||||
+ *
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ *
|
||||
+ *
|
||||
+ * https://github.com/tianocore/edk2-staging (edk2-staging repo of tianocore),
|
||||
+ * the ImageAuthentication.h file under it, and here's the copyright and license.
|
||||
+ *
|
||||
+ * MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ *
|
||||
+ * Copyright 2024 IBM Corp.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __PLATFORM_KEYSTORE_H__
|
||||
+#define __PLATFORM_KEYSTORE_H__
|
||||
+
|
||||
+#include <grub/symbol.h>
|
||||
+#include <grub/mm.h>
|
||||
+#include <grub/types.h>
|
||||
+
|
||||
+#if __GNUC__ >= 9
|
||||
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
||||
+#endif
|
||||
+
|
||||
+#define GRUB_MAX_HASH_SIZE 64
|
||||
+
|
||||
+typedef struct grub_esd grub_esd_t;
|
||||
+typedef struct grub_esl grub_esl_t;
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_SIGNATURE_DATA
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ *
|
||||
+ * The structure of an EFI signature database (ESD).*/
|
||||
+struct grub_esd
|
||||
+{
|
||||
+ /*
|
||||
+ * An identifier which identifies the agent which added
|
||||
+ * the signature to the list.
|
||||
+ */
|
||||
+ grub_uuid_t signatureowner;
|
||||
+ /* The format of the signature is defined by the SignatureType.*/
|
||||
+ grub_uint8_t signaturedata[];
|
||||
+} GRUB_PACKED;
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_SIGNATURE_LIST
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ *
|
||||
+ * The structure of an EFI signature list (ESL).*/
|
||||
+struct grub_esl
|
||||
+{
|
||||
+ /* Type of the signature. GUID signature types are defined in below.*/
|
||||
+ grub_uuid_t signaturetype;
|
||||
+ /* Total size of the signature list, including this header.*/
|
||||
+ grub_uint32_t signaturelistsize;
|
||||
+ /*
|
||||
+ * Size of the signature header which precedes
|
||||
+ * the array of signatures.
|
||||
+ */
|
||||
+ grub_uint32_t signatureheadersize;
|
||||
+ /* Size of each signature.*/
|
||||
+ grub_uint32_t signaturesize;
|
||||
+} GRUB_PACKED;
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_CERT_X509_GUID
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ */
|
||||
+#define GRUB_PKS_CERT_X509_GUID \
|
||||
+ (grub_uuid_t) \
|
||||
+ { \
|
||||
+ { \
|
||||
+ 0xa1, 0x59, 0xc0, 0xa5, 0xe4, 0x94, \
|
||||
+ 0xa7, 0x4a, 0x87, 0xb5, 0xab, 0x15, \
|
||||
+ 0x5c, 0x2b, 0xf0, 0x72 \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_CERT_SHA256_GUID
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ */
|
||||
+#define GRUB_PKS_CERT_SHA256_GUID \
|
||||
+ (grub_uuid_t) \
|
||||
+ { \
|
||||
+ { \
|
||||
+ 0x26, 0x16, 0xc4, 0xc1, 0x4c, 0x50, \
|
||||
+ 0x92, 0x40, 0xac, 0xa9, 0x41, 0xf9, \
|
||||
+ 0x36, 0x93, 0x43, 0x28 \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_CERT_SHA384_GUID
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ */
|
||||
+#define GRUB_PKS_CERT_SHA384_GUID \
|
||||
+ (grub_uuid_t) \
|
||||
+ { \
|
||||
+ { \
|
||||
+ 0x07, 0x53, 0x3e, 0xff, 0xd0, 0x9f, \
|
||||
+ 0xc9, 0x48, 0x85, 0xf1, 0x8a, 0xd5, \
|
||||
+ 0x6c, 0x70, 0x1e, 0x1 \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_CERT_SHA512_GUID
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ */
|
||||
+#define GRUB_PKS_CERT_SHA512_GUID \
|
||||
+ (grub_uuid_t) \
|
||||
+ { \
|
||||
+ { \
|
||||
+ 0xae, 0x0f, 0x3e, 0x09, 0xc4, 0xa6, \
|
||||
+ 0x50, 0x4f, 0x9f, 0x1b, 0xd4, 0x1e, \
|
||||
+ 0x2b, 0x89, 0xc1, 0x9a \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_CERT_X509_SHA256_GUID
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ */
|
||||
+#define GRUB_PKS_CERT_X509_SHA256_GUID \
|
||||
+ (grub_uuid_t) \
|
||||
+ { \
|
||||
+ { \
|
||||
+ 0x92, 0xa4, 0xd2, 0x3b, 0xc0, 0x96, \
|
||||
+ 0x79, 0x40, 0xb4, 0x20, 0xfc, 0xf9, \
|
||||
+ 0x8e, 0xf1, 0x03, 0xed \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_CERT_X509_SHA384_GUID
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ */
|
||||
+#define GRUB_PKS_CERT_X509_SHA384_GUID \
|
||||
+ (grub_uuid_t) \
|
||||
+ { \
|
||||
+ { \
|
||||
+ 0x6e, 0x87, 0x76, 0x70, 0xc2, 0x80, \
|
||||
+ 0xe6, 0x4e, 0xaa, 0xd2, 0x28, 0xb3, \
|
||||
+ 0x49, 0xa6, 0x86, 0x5b \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+/*
|
||||
+ * It is derived from EFI_CERT_X509_SHA512_GUID
|
||||
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||
+ */
|
||||
+#define GRUB_PKS_CERT_X509_SHA512_GUID \
|
||||
+ (grub_uuid_t) \
|
||||
+ { \
|
||||
+ { \
|
||||
+ 0x63, 0xbf, 0x6d, 0x44, 0x02, 0x25, \
|
||||
+ 0xda, 0x4c, 0xbc, 0xfa, 0x24, 0x65, \
|
||||
+ 0xd2, 0xb0, 0xfe, 0x9d \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+typedef struct grub_pks_sd grub_pks_sd_t;
|
||||
+typedef struct grub_pks grub_pks_t;
|
||||
+
|
||||
+/* The structure of a PKS signature data.*/
|
||||
+struct grub_pks_sd
|
||||
+{
|
||||
+ grub_uuid_t guid; /* signature type */
|
||||
+ grub_uint8_t *data; /* signature data */
|
||||
+ grub_size_t data_size; /* size of signature data */
|
||||
+} GRUB_PACKED;
|
||||
+
|
||||
+/* The structure of a PKS.*/
|
||||
+struct grub_pks
|
||||
+{
|
||||
+ grub_pks_sd_t *db; /* signature database */
|
||||
+ grub_pks_sd_t *dbx; /* forbidden signature database */
|
||||
+ grub_size_t db_entries; /* size of signature database */
|
||||
+ grub_size_t dbx_entries; /* size of forbidden signature database */
|
||||
+} GRUB_PACKED;
|
||||
+
|
||||
+#ifdef __powerpc__
|
||||
+
|
||||
+/* Initialization of the Platform Keystore */
|
||||
+grub_err_t grub_pks_keystore_init (void);
|
||||
+/* Free allocated memory */
|
||||
+void EXPORT_FUNC(grub_pks_free_keystore) (void);
|
||||
+extern grub_uint8_t EXPORT_VAR(grub_pks_use_keystore);
|
||||
+extern grub_pks_t EXPORT_VAR(grub_pks_keystore);
|
||||
+
|
||||
+#else
|
||||
+
|
||||
+#define grub_pks_use_keystore 0
|
||||
+grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0};
|
||||
+void grub_pks_free_keystore (void);
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
diff --git a/include/grub/types.h b/include/grub/types.h
|
||||
index 1587ff4..bfa7af9 100644
|
||||
--- a/include/grub/types.h
|
||||
+++ b/include/grub/types.h
|
||||
@@ -345,4 +345,12 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
|
||||
dd->d = val;
|
||||
}
|
||||
|
||||
+#define GRUB_UUID_SIZE 16
|
||||
+typedef struct grub_uuid grub_uuid_t;
|
||||
+/* The structure of a UUID.*/
|
||||
+struct grub_uuid
|
||||
+{
|
||||
+ grub_uint8_t b[GRUB_UUID_SIZE];
|
||||
+};
|
||||
+
|
||||
#endif /* ! GRUB_TYPES_HEADER */
|
||||
@ -0,0 +1,764 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:37 +0530
|
||||
Subject: [PATCH] appendedsig: The creation of trusted and distrusted lists
|
||||
|
||||
The trusted certificates and binary hashes, distrusted certificates and
|
||||
binary/certificate hashes will be extracted from the platform keystore buffer
|
||||
if Secure Boot is enabled with PKS.
|
||||
|
||||
In order to verify the integrity of the kernel, the extracted data
|
||||
needs to be stored stored in the buffer db and dbx.
|
||||
|
||||
The trusted certificates will be extracted from the grub ELFNOTE if Secure Boot is
|
||||
enabled with static key. In order to verify the integerity of the kernel,
|
||||
the extracted data needs to be stored in the buffer db.
|
||||
|
||||
Note:-
|
||||
|
||||
If neither the trusted certificate nor binary hash exists in the distrusted list (dbx),
|
||||
rejects it while extracting certificate/binary hash from the platform keystore buffer.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
grub-core/commands/appendedsig/appendedsig.c | 584 +++++++++++++++++++++++++--
|
||||
grub-core/kern/file.c | 34 ++
|
||||
include/grub/file.h | 1 +
|
||||
3 files changed, 577 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||
index f4eefe5..994852f 100644
|
||||
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <grub/libtasn1.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/lockdown.h>
|
||||
-
|
||||
+#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||
#include "appendedsig.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
@@ -64,8 +64,23 @@ struct grub_appended_signature
|
||||
struct pkcs7_signedData pkcs7; /* Parsed PKCS#7 data */
|
||||
};
|
||||
|
||||
-/* Trusted certificates for verifying appended signatures */
|
||||
-struct x509_certificate *grub_trusted_key;
|
||||
+/* This represents a trusted/distrusted list*/
|
||||
+struct grub_database
|
||||
+{
|
||||
+ struct x509_certificate *keys; /* Certificates */
|
||||
+ grub_size_t key_entries; /* Number of certificates */
|
||||
+ grub_uint8_t **signatures; /* Certificate/binary hashes */
|
||||
+ grub_size_t *signature_size; /* Size of certificate/binary hashes */
|
||||
+ grub_size_t signature_entries; /* Number of certificate/binary hashes */
|
||||
+};
|
||||
+
|
||||
+/* Trusted list */
|
||||
+struct grub_database db = {.keys = NULL, .key_entries = 0, .signatures = NULL,
|
||||
+ .signature_size = NULL, .signature_entries = 0};
|
||||
+
|
||||
+/* Distrusted list */
|
||||
+struct grub_database dbx = {.signatures = NULL, .signature_size = NULL,
|
||||
+ .signature_entries = 0};
|
||||
|
||||
/*
|
||||
* Force gcry_rsa to be a module dependency.
|
||||
@@ -87,6 +102,13 @@ struct x509_certificate *grub_trusted_key;
|
||||
* also resolves our concerns about loading from the filesystem.
|
||||
*/
|
||||
extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
|
||||
+extern gcry_md_spec_t _gcry_digest_spec_sha224;
|
||||
+extern gcry_md_spec_t _gcry_digest_spec_sha384;
|
||||
+
|
||||
+/* Free trusted list memory */
|
||||
+static void free_trusted_list (void);
|
||||
+/* Free distrusted list memory */
|
||||
+static void free_distrusted_list (void);
|
||||
|
||||
static enum
|
||||
{
|
||||
@@ -95,6 +117,204 @@ static enum
|
||||
check_sigs_forced = 2
|
||||
} check_sigs = check_sigs_no;
|
||||
|
||||
+/*
|
||||
+ * GUID can be used to determine the hashing function and
|
||||
+ * generate the hash using determined hashing function.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+get_hash (const grub_uuid_t *guid, const grub_uint8_t *data, const grub_size_t data_size,
|
||||
+ grub_uint8_t *hash, grub_size_t *hash_size)
|
||||
+{
|
||||
+ gcry_md_spec_t *hash_func = NULL;
|
||||
+
|
||||
+ if (guid == NULL)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "GUID is null");
|
||||
+
|
||||
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
|
||||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) == 0)
|
||||
+ hash_func = &_gcry_digest_spec_sha256;
|
||||
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
|
||||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) == 0)
|
||||
+ hash_func = &_gcry_digest_spec_sha384;
|
||||
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0 ||
|
||||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) == 0)
|
||||
+ hash_func = &_gcry_digest_spec_sha512;
|
||||
+ else
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "Unsupported GUID for hash");
|
||||
+
|
||||
+ grub_memset (hash, 0, GRUB_MAX_HASH_SIZE);
|
||||
+ grub_crypto_hash (hash_func, hash, data, data_size);
|
||||
+ *hash_size = hash_func->mdlen;
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/* Add the certificate/binary hash into the trusted/distrusted list */
|
||||
+static grub_err_t
|
||||
+add_hash (const grub_uint8_t **data, const grub_size_t data_size,
|
||||
+ grub_uint8_t ***signature_list, grub_size_t **signature_size_list,
|
||||
+ grub_size_t *signature_list_entries)
|
||||
+{
|
||||
+ grub_uint8_t **signatures = *signature_list;
|
||||
+ grub_size_t *signature_size = *signature_size_list;
|
||||
+ grub_size_t signature_entries = *signature_list_entries;
|
||||
+
|
||||
+ if (*data == NULL || data_size == 0)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate/binary hash data/size is null");
|
||||
+
|
||||
+ signatures = grub_realloc (signatures, sizeof (grub_uint8_t *) * (signature_entries + 1));
|
||||
+ signature_size = grub_realloc (signature_size,
|
||||
+ sizeof (grub_size_t) * (signature_entries + 1));
|
||||
+
|
||||
+ if (signatures == NULL || signature_size == NULL)
|
||||
+ {
|
||||
+ /*
|
||||
+ * allocated memory will be freed by
|
||||
+ * free_trusted_list/free_distrusted_list
|
||||
+ */
|
||||
+ if (signatures != NULL)
|
||||
+ {
|
||||
+ *signature_list = signatures;
|
||||
+ *signature_list_entries = signature_entries + 1;
|
||||
+ }
|
||||
+
|
||||
+ if (signature_size != NULL)
|
||||
+ *signature_size_list = signature_size;
|
||||
+
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+ }
|
||||
+
|
||||
+ signatures[signature_entries] = (grub_uint8_t *) *data;
|
||||
+ signature_size[signature_entries] = data_size;
|
||||
+ signature_entries++;
|
||||
+ *data = NULL;
|
||||
+
|
||||
+ *signature_list = signatures;
|
||||
+ *signature_size_list = signature_size;
|
||||
+ *signature_list_entries = signature_entries;
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+is_x509 (const grub_uuid_t *guid)
|
||||
+{
|
||||
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_GUID, GRUB_UUID_SIZE) == 0)
|
||||
+ return GRUB_ERR_NONE;
|
||||
+
|
||||
+ return GRUB_ERR_UNKNOWN_COMMAND;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+is_cert_match (const struct x509_certificate *distrusted_cert,
|
||||
+ const struct x509_certificate *db_cert)
|
||||
+{
|
||||
+
|
||||
+ if (grub_memcmp (distrusted_cert->subject, db_cert->subject, db_cert->subject_len) == 0
|
||||
+ && grub_memcmp (distrusted_cert->serial, db_cert->serial, db_cert->serial_len) == 0
|
||||
+ && grub_memcmp (distrusted_cert->mpis[0], db_cert->mpis[0], sizeof (db_cert->mpis[0])) == 0
|
||||
+ && grub_memcmp (distrusted_cert->mpis[1], db_cert->mpis[1], sizeof (db_cert->mpis[1])) == 0)
|
||||
+ return GRUB_ERR_NONE;
|
||||
+
|
||||
+ return GRUB_ERR_UNKNOWN_COMMAND;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Verify the certificate against the certificate from platform keystore buffer's
|
||||
+ * distrusted list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+is_distrusted_cert (const struct x509_certificate *db_cert)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_size_t i = 0;
|
||||
+ struct x509_certificate *distrusted_cert = NULL;
|
||||
+
|
||||
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
|
||||
+ {
|
||||
+ if (grub_pks_keystore.dbx[i].data == NULL)
|
||||
+ continue;
|
||||
+
|
||||
+ if (is_x509 (&grub_pks_keystore.dbx[i].guid) == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ distrusted_cert = grub_zalloc (sizeof (struct x509_certificate));
|
||||
+ if (distrusted_cert == NULL)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+
|
||||
+ rc = parse_x509_certificate (grub_pks_keystore.dbx[i].data,
|
||||
+ grub_pks_keystore.dbx[i].data_size, distrusted_cert);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_free (distrusted_cert);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (is_cert_match (distrusted_cert, db_cert) == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_printf ("Warning: a trusted certificate CN='%s' is ignored "
|
||||
+ "because it is on the distrusted list (dbx).\n", db_cert->subject);
|
||||
+ grub_free (grub_pks_keystore.dbx[i].data);
|
||||
+ grub_memset (&grub_pks_keystore.dbx[i], 0, sizeof (grub_pks_sd_t));
|
||||
+ certificate_release (distrusted_cert);
|
||||
+ grub_free (distrusted_cert);
|
||||
+ return GRUB_ERR_ACCESS_DENIED;
|
||||
+ }
|
||||
+
|
||||
+ certificate_release (distrusted_cert);
|
||||
+ grub_free (distrusted_cert);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/* Add the certificate into the trusted/distrusted list */
|
||||
+static grub_err_t
|
||||
+add_certificate (const grub_uint8_t *data, const grub_size_t data_size,
|
||||
+ struct grub_database *database, const grub_size_t is_db)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_size_t key_entries = database->key_entries;
|
||||
+ struct x509_certificate *cert = NULL;
|
||||
+
|
||||
+ if (data == NULL || data_size == 0)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data/size is null");
|
||||
+
|
||||
+ cert = grub_zalloc (sizeof (struct x509_certificate));
|
||||
+ if (cert == NULL)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+
|
||||
+ rc = parse_x509_certificate (data, data_size, cert);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_dprintf ("appendedsig", "skipping %s certificate (%d)\n",
|
||||
+ (is_db ? "trusted":"distrusted"), rc);
|
||||
+ grub_free (cert);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ if (is_db)
|
||||
+ {
|
||||
+ rc = is_distrusted_cert (cert);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ certificate_release (cert);
|
||||
+ grub_free (cert);
|
||||
+ return rc;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ grub_dprintf ("appendedsig", "add a %s certificate CN='%s'\n",
|
||||
+ (is_db ? "trusted":"distrusted"), cert->subject);
|
||||
+
|
||||
+ key_entries++;
|
||||
+ cert->next = database->keys;
|
||||
+ database->keys = cert;
|
||||
+ database->key_entries = key_entries;
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
static const char *
|
||||
grub_env_read_sec (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val __attribute__ ((unused)))
|
||||
@@ -248,7 +468,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||
struct pkcs7_signerInfo *si;
|
||||
int i;
|
||||
|
||||
- if (!grub_trusted_key)
|
||||
+ if (!db.key_entries)
|
||||
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify against"));
|
||||
|
||||
err = extract_appended_signature (buf, bufsize, &sig);
|
||||
@@ -279,7 +499,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||
datasize, i, hash[0], hash[1], hash[2], hash[3]);
|
||||
|
||||
err = GRUB_ERR_BAD_SIGNATURE;
|
||||
- for (pk = grub_trusted_key; pk; pk = pk->next)
|
||||
+ for (pk = db.keys; pk; pk = pk->next)
|
||||
{
|
||||
rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
|
||||
if (rc)
|
||||
@@ -376,16 +596,16 @@ grub_cmd_distrust (grub_command_t cmd __attribute__ ((unused)), int argc, char *
|
||||
|
||||
if (cert_num == 1)
|
||||
{
|
||||
- cert = grub_trusted_key;
|
||||
- grub_trusted_key = cert->next;
|
||||
+ cert = db.keys;
|
||||
+ db.keys = cert->next;
|
||||
|
||||
certificate_release (cert);
|
||||
grub_free (cert);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
i = 2;
|
||||
- prev = grub_trusted_key;
|
||||
- cert = grub_trusted_key->next;
|
||||
+ prev = db.keys;
|
||||
+ cert = db.keys->next;
|
||||
while (cert)
|
||||
{
|
||||
if (i == cert_num)
|
||||
@@ -432,8 +652,8 @@ grub_cmd_trust (grub_command_t cmd __attribute__ ((unused)), int argc, char **ar
|
||||
}
|
||||
grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n", cert->subject);
|
||||
|
||||
- cert->next = grub_trusted_key;
|
||||
- grub_trusted_key = cert;
|
||||
+ cert->next = db.keys;
|
||||
+ db.keys = cert;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
@@ -446,7 +666,7 @@ grub_cmd_list (grub_command_t cmd __attribute__ ((unused)), int argc __attribute
|
||||
int cert_num = 1;
|
||||
grub_size_t i;
|
||||
|
||||
- for (cert = grub_trusted_key; cert; cert = cert->next)
|
||||
+ for (cert = db.keys; cert; cert = cert->next)
|
||||
{
|
||||
grub_printf (N_("Certificate %d:\n"), cert_num);
|
||||
|
||||
@@ -539,6 +759,274 @@ static struct grub_fs pseudo_fs = { .name = "pseudo", .fs_read = pseudo_read };
|
||||
|
||||
static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust;
|
||||
|
||||
+/*
|
||||
+ * Verify the trusted certificate against the certificate hashes from platform keystore buffer's
|
||||
+ * distrusted list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+is_distrusted_cert_hash (const grub_uint8_t *data, const grub_size_t data_size)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_size_t i = 0, cert_hash_size = 0;
|
||||
+ grub_uint8_t cert_hash[GRUB_MAX_HASH_SIZE] = { 0 };
|
||||
+
|
||||
+ if (data == NULL || data_size == 0)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted certificate data/size is null");
|
||||
+
|
||||
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
|
||||
+ {
|
||||
+ if (grub_pks_keystore.dbx[i].data == NULL ||
|
||||
+ grub_pks_keystore.dbx[i].data_size == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ rc = get_hash (&grub_pks_keystore.dbx[i].guid, data, data_size,
|
||||
+ cert_hash, &cert_hash_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ continue;
|
||||
+
|
||||
+ if (cert_hash_size == grub_pks_keystore.dbx[i].data_size &&
|
||||
+ grub_memcmp (grub_pks_keystore.dbx[i].data, cert_hash, cert_hash_size) == 0)
|
||||
+ {
|
||||
+ grub_printf ("Warning: a trusted certificate (%02x%02x%02x%02x) is ignored "
|
||||
+ "because this certificate hash is on the distrusted list (dbx).\n",
|
||||
+ cert_hash[0], cert_hash[1], cert_hash[2], cert_hash[3]);
|
||||
+ grub_free (grub_pks_keystore.dbx[i].data);
|
||||
+ grub_memset (&grub_pks_keystore.dbx[i], 0, sizeof (grub_pks_keystore.dbx[i]));
|
||||
+ return GRUB_ERR_BAD_SIGNATURE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Verify the trusted binary hash against the platform keystore buffer's
|
||||
+ * distrusted list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+is_distrusted_binary_hash (const grub_uint8_t *binary_hash,
|
||||
+ const grub_size_t binary_hash_size)
|
||||
+{
|
||||
+ grub_size_t i = 0;
|
||||
+
|
||||
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
|
||||
+ {
|
||||
+ if (grub_pks_keystore.dbx[i].data == NULL ||
|
||||
+ grub_pks_keystore.dbx[i].data_size == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (binary_hash_size == grub_pks_keystore.dbx[i].data_size &&
|
||||
+ grub_memcmp (grub_pks_keystore.dbx[i].data, binary_hash, binary_hash_size) == 0)
|
||||
+ {
|
||||
+ grub_printf ("Warning: a trusted binary hash (%02x%02x%02x%02x) is ignored"
|
||||
+ " because it is on the distrusted list (dbx).\n",
|
||||
+ binary_hash[0], binary_hash[1], binary_hash[2], binary_hash[3]);
|
||||
+ grub_free (grub_pks_keystore.dbx[i].data);
|
||||
+ grub_memset (&grub_pks_keystore.dbx[i], 0, sizeof(grub_pks_keystore.dbx[i]));
|
||||
+ return GRUB_ERR_BAD_SIGNATURE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Extract the binary hashes from the platform keystore buffer,
|
||||
+ * and add it to the trusted list if it does not exist in the distrusted list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+add_trusted_binary_hash (const grub_uint8_t **data, const grub_size_t data_size)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+
|
||||
+ if (*data == NULL || data_size == 0)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted binary hash data/size is null");
|
||||
+
|
||||
+ rc = is_distrusted_binary_hash (*data, data_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ return rc;
|
||||
+
|
||||
+ rc = add_hash (data, data_size, &db.signatures, &db.signature_size,
|
||||
+ &db.signature_entries);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+is_hash (const grub_uuid_t *guid)
|
||||
+{
|
||||
+ /* GUID type of the binary hash */
|
||||
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
|
||||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
|
||||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0)
|
||||
+ return GRUB_ERR_NONE;
|
||||
+
|
||||
+ /* GUID type of the certificate hash */
|
||||
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
|
||||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
|
||||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) == 0)
|
||||
+ return GRUB_ERR_NONE;
|
||||
+
|
||||
+ return GRUB_ERR_UNKNOWN_COMMAND;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Extract the x509 certificates/binary hashes from the platform keystore buffer,
|
||||
+ * parse it, and add it to the trusted list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+create_trusted_list (void)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_size_t i = 0;
|
||||
+
|
||||
+ for (i = 0; i < grub_pks_keystore.db_entries; i++)
|
||||
+ {
|
||||
+ if (is_hash (&grub_pks_keystore.db[i].guid) == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ rc = add_trusted_binary_hash ((const grub_uint8_t **)
|
||||
+ &grub_pks_keystore.db[i].data,
|
||||
+ grub_pks_keystore.db[i].data_size);
|
||||
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
|
||||
+ return rc;
|
||||
+ }
|
||||
+ else if (is_x509 (&grub_pks_keystore.db[i].guid) == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ rc = is_distrusted_cert_hash (grub_pks_keystore.db[i].data,
|
||||
+ grub_pks_keystore.db[i].data_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ continue;
|
||||
+
|
||||
+ rc = add_certificate (grub_pks_keystore.db[i].data,
|
||||
+ grub_pks_keystore.db[i].data_size, &db, 1);
|
||||
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
|
||||
+ return rc;
|
||||
+ else if (rc != GRUB_ERR_NONE)
|
||||
+ continue;
|
||||
+ }
|
||||
+ else
|
||||
+ grub_dprintf ("appendedsig", "unsupported signature data type and "
|
||||
+ "skipping trusted data (%" PRIuGRUB_SIZE ")\n", i + 1);
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Extract the certificates, certificate/binary hashes out of the platform keystore buffer,
|
||||
+ * and add it to the distrusted list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+create_distrusted_list (void)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_size_t i = 0;
|
||||
+
|
||||
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
|
||||
+ {
|
||||
+ if (grub_pks_keystore.dbx[i].data != NULL ||
|
||||
+ grub_pks_keystore.dbx[i].data_size > 0)
|
||||
+ {
|
||||
+ if (is_x509 (&grub_pks_keystore.dbx[i].guid) == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ rc = add_certificate (grub_pks_keystore.dbx[i].data,
|
||||
+ grub_pks_keystore.dbx[i].data_size, &dbx, 0);
|
||||
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
|
||||
+ return rc;
|
||||
+ }
|
||||
+ else if (is_hash (&grub_pks_keystore.dbx[i].guid) == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ rc = add_hash ((const grub_uint8_t **) &grub_pks_keystore.dbx[i].data,
|
||||
+ grub_pks_keystore.dbx[i].data_size,
|
||||
+ &dbx.signatures, &dbx.signature_size,
|
||||
+ &dbx.signature_entries);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ return rc;
|
||||
+ }
|
||||
+ else
|
||||
+ grub_dprintf ("appendedsig", "unsupported signature data type and "
|
||||
+ "skipping distrusted data (%" PRIuGRUB_SIZE ")\n", i + 1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Extract the x509 certificates from the ELF note header,
|
||||
+ * parse it, and add it to the trusted list.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+build_static_trusted_list (const struct grub_module_header *header)
|
||||
+{
|
||||
+ grub_err_t err = GRUB_ERR_NONE;
|
||||
+ struct grub_file pseudo_file;
|
||||
+ grub_uint8_t *cert_data = NULL;
|
||||
+ grub_ssize_t cert_data_size = 0;
|
||||
+
|
||||
+ grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
|
||||
+ pseudo_file.fs = &pseudo_fs;
|
||||
+ pseudo_file.size = header->size - sizeof (struct grub_module_header);
|
||||
+ pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
|
||||
+
|
||||
+ grub_dprintf ("appendedsig", "found an x509 key, size=%" PRIuGRUB_UINT64_T "\n",
|
||||
+ pseudo_file.size);
|
||||
+
|
||||
+ err = grub_read_file (&pseudo_file, &cert_data, &cert_data_size);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
+
|
||||
+ err = add_certificate (cert_data, cert_data_size, &db, 1);
|
||||
+ grub_free (cert_data);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/* releasing memory */
|
||||
+static void
|
||||
+free_trusted_list (void)
|
||||
+{
|
||||
+ struct x509_certificate *cert;
|
||||
+ grub_size_t i = 0;
|
||||
+
|
||||
+ while (db.keys != NULL)
|
||||
+ {
|
||||
+ cert = db.keys;
|
||||
+ db.keys = db.keys->next;
|
||||
+ certificate_release (cert);
|
||||
+ grub_free (cert);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < db.signature_entries; i++)
|
||||
+ grub_free (db.signatures[i]);
|
||||
+
|
||||
+ grub_free (db.signatures);
|
||||
+ grub_free (db.signature_size);
|
||||
+ grub_memset (&db, 0, sizeof (db));
|
||||
+}
|
||||
+
|
||||
+/* releasing memory */
|
||||
+static void
|
||||
+free_distrusted_list (void)
|
||||
+{
|
||||
+ struct x509_certificate *cert;
|
||||
+ grub_size_t i = 0;
|
||||
+
|
||||
+ while (dbx.keys != NULL)
|
||||
+ {
|
||||
+ cert = dbx.keys;
|
||||
+ dbx.keys = dbx.keys->next;
|
||||
+ certificate_release (cert);
|
||||
+ grub_free (cert);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < dbx.signature_entries; i++)
|
||||
+ grub_free (dbx.signatures[i]);
|
||||
+
|
||||
+ grub_free (dbx.signatures);
|
||||
+ grub_free (dbx.signature_size);
|
||||
+ grub_memset (&dbx, 0, sizeof (dbx));
|
||||
+}
|
||||
+
|
||||
GRUB_MOD_INIT (appendedsig)
|
||||
{
|
||||
int rc;
|
||||
@@ -548,7 +1036,6 @@ GRUB_MOD_INIT (appendedsig)
|
||||
if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
|
||||
check_sigs = check_sigs_forced;
|
||||
|
||||
- grub_trusted_key = NULL;
|
||||
grub_register_variable_hook ("check_appended_signatures", grub_env_read_sec, grub_env_write_sec);
|
||||
grub_env_export ("check_appended_signatures");
|
||||
|
||||
@@ -556,37 +1043,50 @@ GRUB_MOD_INIT (appendedsig)
|
||||
if (rc)
|
||||
grub_fatal ("Error initing ASN.1 data structures: %d: %s\n", rc, asn1_strerror (rc));
|
||||
|
||||
- FOR_MODULES (header)
|
||||
- {
|
||||
- struct grub_file pseudo_file;
|
||||
- struct x509_certificate *pk = NULL;
|
||||
- grub_err_t err;
|
||||
+ if (!grub_pks_use_keystore && check_sigs == check_sigs_forced)
|
||||
+ {
|
||||
+ FOR_MODULES (header)
|
||||
+ {
|
||||
+ /* Not an ELF module, skip. */
|
||||
+ if (header->type != OBJ_TYPE_X509_PUBKEY)
|
||||
+ continue;
|
||||
|
||||
- /* Not an X.509 certificate, skip. */
|
||||
- if (header->type != OBJ_TYPE_X509_PUBKEY)
|
||||
- continue;
|
||||
+ rc = build_static_trusted_list (header);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ free_trusted_list ();
|
||||
+ grub_error (rc, "static trusted list creation failed");
|
||||
+ }
|
||||
+ else
|
||||
+ grub_dprintf ("appendedsig", "the trusted list now has %" PRIuGRUB_SIZE " static keys\n",
|
||||
+ db.key_entries);
|
||||
+ }
|
||||
+ }
|
||||
+ else if (grub_pks_use_keystore && check_sigs == check_sigs_forced)
|
||||
+ {
|
||||
+ rc = create_trusted_list ();
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ free_trusted_list ();
|
||||
+ grub_error (rc, "trusted list creation failed");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ rc = create_distrusted_list ();
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ free_trusted_list ();
|
||||
+ free_distrusted_list ();
|
||||
+ grub_error (rc, "distrusted list creation failed");
|
||||
+ }
|
||||
+ else
|
||||
+ grub_dprintf ("appendedsig", "the trusted list now has %" PRIuGRUB_SIZE " keys.\n"
|
||||
+ "the distrusted list now has %" PRIuGRUB_SIZE " keys.\n",
|
||||
+ db.signature_entries + db.key_entries, dbx.signature_entries);
|
||||
+ }
|
||||
|
||||
- grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
|
||||
- pseudo_file.fs = &pseudo_fs;
|
||||
- pseudo_file.size = header->size - sizeof (struct grub_module_header);
|
||||
- pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
|
||||
-
|
||||
- grub_dprintf ("appendedsig", "Found an x509 key, size=%" PRIuGRUB_UINT64_T "\n",
|
||||
- pseudo_file.size);
|
||||
-
|
||||
- pk = grub_zalloc (sizeof (struct x509_certificate));
|
||||
- if (!pk)
|
||||
- grub_fatal ("Out of memory loading initial certificates");
|
||||
-
|
||||
- err = read_cert_from_file (&pseudo_file, pk);
|
||||
- if (err != GRUB_ERR_NONE)
|
||||
- grub_fatal ("Error loading initial key: %s", grub_errmsg);
|
||||
-
|
||||
- grub_dprintf ("appendedsig", "loaded certificate CN='%s'\n", pk->subject);
|
||||
-
|
||||
- pk->next = grub_trusted_key;
|
||||
- grub_trusted_key = pk;
|
||||
- }
|
||||
+ grub_pks_free_keystore ();
|
||||
+ }
|
||||
|
||||
cmd_trust = grub_register_command ("trust_certificate", grub_cmd_trust, N_("X509_CERTIFICATE"),
|
||||
N_("Add X509_CERTIFICATE to trusted certificates."));
|
||||
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
|
||||
index 58fae17..fa73c04 100644
|
||||
--- a/grub-core/kern/file.c
|
||||
+++ b/grub-core/kern/file.c
|
||||
@@ -256,3 +256,37 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
|
||||
|
||||
return old;
|
||||
}
|
||||
+
|
||||
+grub_err_t
|
||||
+grub_read_file (const grub_file_t file, grub_uint8_t **data, grub_ssize_t *data_size)
|
||||
+{
|
||||
+ grub_uint8_t *buffer = NULL;
|
||||
+ grub_ssize_t read_size = 0;
|
||||
+ grub_off_t total_read_size = 0;
|
||||
+ grub_off_t file_size = grub_file_size (file);
|
||||
+
|
||||
+ if (file_size == GRUB_FILE_SIZE_UNKNOWN)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("could not determine the size of the file."));
|
||||
+
|
||||
+ buffer = grub_zalloc (file_size);
|
||||
+ if (buffer == NULL)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
+
|
||||
+ while (total_read_size < file_size)
|
||||
+ {
|
||||
+ read_size = grub_file_read (file, &buffer[total_read_size], file_size - total_read_size);
|
||||
+ if (read_size < 0)
|
||||
+ {
|
||||
+ grub_free (buffer);
|
||||
+ return grub_error (GRUB_ERR_READ_ERROR, N_("unable to read the file"));
|
||||
+ }
|
||||
+
|
||||
+ total_read_size += read_size;
|
||||
+ }
|
||||
+
|
||||
+ *data = buffer;
|
||||
+ *data_size = total_read_size;
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
diff --git a/include/grub/file.h b/include/grub/file.h
|
||||
index d678de0..27e1a88 100644
|
||||
--- a/include/grub/file.h
|
||||
+++ b/include/grub/file.h
|
||||
@@ -217,6 +217,7 @@ grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
|
||||
grub_size_t len);
|
||||
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
|
||||
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
|
||||
+grub_err_t EXPORT_FUNC(grub_read_file) (const grub_file_t file, grub_uint8_t **data, grub_ssize_t *data_size);
|
||||
|
||||
/* Return value of grub_file_size() in case file size is unknown. */
|
||||
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL
|
||||
@ -0,0 +1,250 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:38 +0530
|
||||
Subject: [PATCH] appendedsig: While verifying the kernel, use trusted and
|
||||
distrusted lists
|
||||
|
||||
To verify the kernel's signature: verify the kernel binary against lists of binary hashes
|
||||
that are either distrusted or trusted. If it is not list in either trusted or distrusted hashes list
|
||||
then the trusted keys from the trusted key list are used to verify the signature.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
grub-core/commands/appendedsig/appendedsig.c | 193 +++++++++++++++++++--------
|
||||
1 file changed, 139 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||
index 994852f..07d6b39 100644
|
||||
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||
@@ -454,6 +454,83 @@ extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
|
||||
return parse_pkcs7_signedData (appsigdata, pkcs7_size, &sig->pkcs7);
|
||||
}
|
||||
|
||||
+static grub_err_t
|
||||
+get_binary_hash (const grub_size_t binary_hash_size, const grub_uint8_t *data,
|
||||
+ const grub_size_t data_size, grub_uint8_t *hash, grub_size_t *hash_size)
|
||||
+{
|
||||
+ grub_uuid_t guid = { 0 };
|
||||
+
|
||||
+ /* support SHA256, SHA384 and SHA512 for binary hash */
|
||||
+ if (binary_hash_size == 32)
|
||||
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE);
|
||||
+ else if (binary_hash_size == 48)
|
||||
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE);
|
||||
+ else if (binary_hash_size == 64)
|
||||
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE);
|
||||
+ else
|
||||
+ {
|
||||
+ grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and skipping binary hash\n",
|
||||
+ binary_hash_size);
|
||||
+ return GRUB_ERR_UNKNOWN_COMMAND;
|
||||
+ }
|
||||
+
|
||||
+ return get_hash (&guid, data, data_size, hash, hash_size);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Verify binary hash against the list of binary hashes that are distrusted
|
||||
+ * and trusted.
|
||||
+ * The following errors can occur:
|
||||
+ * - GRUB_ERR_BAD_SIGNATURE: indicates that the hash is distrusted.
|
||||
+ * - GRUB_ERR_NONE: the hash is trusted, since it was found in the trusted hashes list
|
||||
+ * - GRUB_ERR_EOF: the hash could not be found in the hashes list
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+verify_binary_hash (const grub_uint8_t *data, const grub_size_t data_size)
|
||||
+{
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_size_t i = 0, hash_size = 0;
|
||||
+ grub_uint8_t hash[GRUB_MAX_HASH_SIZE] = { 0 };
|
||||
+
|
||||
+ for (i = 0; i < dbx.signature_entries; i++)
|
||||
+ {
|
||||
+ rc = get_binary_hash (dbx.signature_size[i], data, data_size, hash, &hash_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ continue;
|
||||
+
|
||||
+ if (hash_size == dbx.signature_size[i] &&
|
||||
+ grub_memcmp (dbx.signatures[i], hash, hash_size) == 0)
|
||||
+ {
|
||||
+ grub_dprintf ("appendedsig", "the binary hash (%02x%02x%02x%02x) was listed as distrusted\n",
|
||||
+ hash[0], hash[1], hash[2], hash[3]);
|
||||
+ return GRUB_ERR_BAD_SIGNATURE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < db.signature_entries; i++)
|
||||
+ {
|
||||
+ rc = get_binary_hash (db.signature_size[i], data, data_size, hash, &hash_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ continue;
|
||||
+
|
||||
+ if (hash_size == db.signature_size[i] &&
|
||||
+ grub_memcmp (db.signatures[i], hash, hash_size) == 0)
|
||||
+ {
|
||||
+ grub_dprintf ("appendedsig", "verified with a trusted binary hash (%02x%02x%02x%02x)\n",
|
||||
+ hash[0], hash[1], hash[2], hash[3]);
|
||||
+ return GRUB_ERR_NONE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_EOF;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Verify the kernel's integrity, the trusted key will be used from
|
||||
+ * the trusted key list. If it fails, verify it against the list of binary hashes
|
||||
+ * that are distrusted and trusted.
|
||||
+ */
|
||||
static grub_err_t
|
||||
grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||
{
|
||||
@@ -463,12 +540,12 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||
unsigned char *hash;
|
||||
gcry_mpi_t hashmpi;
|
||||
gcry_err_code_t rc;
|
||||
- struct x509_certificate *pk;
|
||||
+ struct x509_certificate *cert;
|
||||
struct grub_appended_signature sig;
|
||||
struct pkcs7_signerInfo *si;
|
||||
int i;
|
||||
|
||||
- if (!db.key_entries)
|
||||
+ if (!db.key_entries && !db.signature_entries)
|
||||
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify against"));
|
||||
|
||||
err = extract_appended_signature (buf, bufsize, &sig);
|
||||
@@ -476,69 +553,77 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||
return err;
|
||||
|
||||
datasize = bufsize - sig.signature_len;
|
||||
-
|
||||
- for (i = 0; i < sig.pkcs7.signerInfo_count; i++)
|
||||
+ err = verify_binary_hash (buf, datasize);
|
||||
+ if (err != GRUB_ERR_EOF && err != GRUB_ERR_NONE)
|
||||
{
|
||||
- /*
|
||||
- * This could be optimised in a couple of ways:
|
||||
- * - we could only compute hashes once per hash type
|
||||
- * - we could track signer information and only verify where IDs match
|
||||
- * For now we do the naive O(trusted keys * pkcs7 signers) approach.
|
||||
- */
|
||||
- si = &sig.pkcs7.signerInfos[i];
|
||||
- context = grub_zalloc (si->hash->contextsize);
|
||||
- if (!context)
|
||||
- return grub_errno;
|
||||
-
|
||||
- si->hash->init (context);
|
||||
- si->hash->write (context, buf, datasize);
|
||||
- si->hash->final (context);
|
||||
- hash = si->hash->read (context);
|
||||
-
|
||||
- grub_dprintf ("appendedsig", "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n",
|
||||
- datasize, i, hash[0], hash[1], hash[2], hash[3]);
|
||||
-
|
||||
- err = GRUB_ERR_BAD_SIGNATURE;
|
||||
- for (pk = db.keys; pk; pk = pk->next)
|
||||
+ err = grub_error (err, N_("failed to verify binary-hash/signature with any trusted binary-hash/key\n"));
|
||||
+ pkcs7_signedData_release (&sig.pkcs7);
|
||||
+ return err;
|
||||
+ }
|
||||
+ else if (err == GRUB_ERR_EOF)
|
||||
+ {
|
||||
+ /* Binary hash was not found in trusted and distrusted list: check signature now */
|
||||
+ for (i = 0; i < sig.pkcs7.signerInfo_count; i++)
|
||||
{
|
||||
- rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
|
||||
- if (rc)
|
||||
- {
|
||||
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||
- N_("Error padding hash for RSA verification: %d"), rc);
|
||||
- grub_free (context);
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ /*
|
||||
+ * This could be optimised in a couple of ways:
|
||||
+ * - we could only compute hashes once per hash type
|
||||
+ * - we could track signer information and only verify where IDs match
|
||||
+ * For now we do the naive O(db.keys * pkcs7 signers) approach.
|
||||
+ */
|
||||
+ si = &sig.pkcs7.signerInfos[i];
|
||||
+ context = grub_zalloc (si->hash->contextsize);
|
||||
+ if (context == NULL)
|
||||
+ return grub_errno;
|
||||
|
||||
- rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi, pk->mpis, NULL, NULL);
|
||||
- gcry_mpi_release (hashmpi);
|
||||
+ si->hash->init (context);
|
||||
+ si->hash->write (context, buf, datasize);
|
||||
+ si->hash->final (context);
|
||||
+ hash = si->hash->read (context);
|
||||
|
||||
- if (rc == 0)
|
||||
- {
|
||||
- grub_dprintf ("appendedsig", "verify signer %d with key '%s' succeeded\n",
|
||||
- i, pk->subject);
|
||||
- err = GRUB_ERR_NONE;
|
||||
- break;
|
||||
- }
|
||||
+ grub_dprintf ("appendedsig",
|
||||
+ "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n",
|
||||
+ datasize, i, hash[0], hash[1], hash[2], hash[3]);
|
||||
|
||||
- grub_dprintf ("appendedsig", "verify signer %d with key '%s' failed with %d\n",
|
||||
- i, pk->subject, rc);
|
||||
- }
|
||||
+ err = GRUB_ERR_BAD_SIGNATURE;
|
||||
+ for (cert = db.keys; cert; cert = cert->next)
|
||||
+ {
|
||||
+ rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, cert->mpis[0]);
|
||||
+ if (rc != 0)
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||
+ N_("Error padding hash for RSA verification: %d"), rc);
|
||||
+ grub_free (context);
|
||||
+ pkcs7_signedData_release (&sig.pkcs7);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- grub_free (context);
|
||||
+ rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi, cert->mpis, NULL, NULL);
|
||||
+ gcry_mpi_release (hashmpi);
|
||||
+ if (rc == 0)
|
||||
+ {
|
||||
+ grub_dprintf ("appendedsig", "verify signer %d with key '%s' succeeded\n",
|
||||
+ i, cert->subject);
|
||||
+ err = GRUB_ERR_NONE;
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
- if (err == GRUB_ERR_NONE)
|
||||
- break;
|
||||
+ grub_dprintf ("appendedsig", "verify signer %d with key '%s' failed with %d\n",
|
||||
+ i, cert->subject, rc);
|
||||
+ }
|
||||
+ grub_free (context);
|
||||
+ if (err == GRUB_ERR_NONE)
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
- /* If we didn't verify, provide a neat message */
|
||||
- if (err != GRUB_ERR_NONE)
|
||||
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||
- N_("Failed to verify signature against a trusted key"));
|
||||
-
|
||||
-cleanup:
|
||||
pkcs7_signedData_release (&sig.pkcs7);
|
||||
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ err = grub_error (err, N_("failed to verify signature with any trusted key\n"));
|
||||
+ else
|
||||
+ grub_dprintf ("appendedsig", "successfully verified the signature with a trusted key\n");
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
107
SOURCES/0472-powerpc_ieee1275-set-use_static_keys-flag.patch
Normal file
107
SOURCES/0472-powerpc_ieee1275-set-use_static_keys-flag.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:39 +0530
|
||||
Subject: [PATCH] powerpc_ieee1275: set use_static_keys flag
|
||||
|
||||
Introduce the use_static_keys flag to indicate that static keys are to be used
|
||||
rather than keys from the PKS storage's DB variable. This variable is set when
|
||||
Secure Boot is enabled with PKS but the DB variable is not present in the PKS storage.
|
||||
The appendedsig module would use this variable to extract the default DB keys from
|
||||
the ELF note and store the keys found there in the trustedlist.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
grub-core/kern/powerpc/ieee1275/platform_keystore.c | 16 +++++++++++++++-
|
||||
grub-core/term/tparm.c | 1 -
|
||||
include/grub/powerpc/ieee1275/platform_keystore.h | 11 ++++++-----
|
||||
include/grub/types.h | 2 ++
|
||||
4 files changed, 23 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||
index cf1d055..a83fcf7 100644
|
||||
--- a/grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||
+++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||
@@ -34,7 +34,11 @@
|
||||
/* Platform Keystore */
|
||||
static grub_size_t pks_max_object_size;
|
||||
grub_uint8_t grub_pks_use_keystore = 0;
|
||||
-grub_pks_t grub_pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, .dbx_entries = 0 };
|
||||
+grub_pks_t grub_pks_keystore = { .db = NULL,
|
||||
+ .dbx = NULL,
|
||||
+ .db_entries = 0,
|
||||
+ .dbx_entries = 0,
|
||||
+ .use_static_keys = false };
|
||||
|
||||
/* Convert the esl data into the ESL */
|
||||
static grub_esl_t *
|
||||
@@ -312,6 +316,16 @@ grub_pks_keystore_init (void)
|
||||
grub_memset (&grub_pks_keystore, 0, sizeof (grub_pks_t));
|
||||
/* DB */
|
||||
rc = read_secure_boot_variables (0, DB, &grub_pks_keystore.db, &grub_pks_keystore.db_entries);
|
||||
+ if (rc == PKS_OBJECT_NOT_FOUND)
|
||||
+ {
|
||||
+ rc = GRUB_ERR_NONE;
|
||||
+ /*
|
||||
+ * DB variable won't be available by default in PKS.
|
||||
+ * So, it will load the Default Keys from ELF Note
|
||||
+ */
|
||||
+ grub_pks_keystore.use_static_keys = true;
|
||||
+ }
|
||||
+
|
||||
if (rc == GRUB_ERR_NONE)
|
||||
{
|
||||
/* DBX */
|
||||
diff --git a/grub-core/term/tparm.c b/grub-core/term/tparm.c
|
||||
index fb5b15a..f2db325 100644
|
||||
--- a/grub-core/term/tparm.c
|
||||
+++ b/grub-core/term/tparm.c
|
||||
@@ -46,7 +46,6 @@
|
||||
/*
|
||||
* Common/troublesome character definitions
|
||||
*/
|
||||
-typedef char grub_bool_t;
|
||||
#ifndef FALSE
|
||||
# define FALSE (0)
|
||||
#endif
|
||||
diff --git a/include/grub/powerpc/ieee1275/platform_keystore.h b/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||
index 0641adb..870fb8c 100644
|
||||
--- a/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||
+++ b/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||
@@ -199,10 +199,11 @@ struct grub_pks_sd
|
||||
/* The structure of a PKS.*/
|
||||
struct grub_pks
|
||||
{
|
||||
- grub_pks_sd_t *db; /* signature database */
|
||||
- grub_pks_sd_t *dbx; /* forbidden signature database */
|
||||
- grub_size_t db_entries; /* size of signature database */
|
||||
- grub_size_t dbx_entries; /* size of forbidden signature database */
|
||||
+ grub_pks_sd_t *db; /* signature database */
|
||||
+ grub_pks_sd_t *dbx; /* forbidden signature database */
|
||||
+ grub_size_t db_entries; /* size of signature database */
|
||||
+ grub_size_t dbx_entries; /* size of forbidden signature database */
|
||||
+ grub_bool_t use_static_keys;/* flag to indicate use of static keys */
|
||||
} GRUB_PACKED;
|
||||
|
||||
#ifdef __powerpc__
|
||||
@@ -217,7 +218,7 @@ extern grub_pks_t EXPORT_VAR(grub_pks_keystore);
|
||||
#else
|
||||
|
||||
#define grub_pks_use_keystore 0
|
||||
-grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0};
|
||||
+grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0, false};
|
||||
void grub_pks_free_keystore (void);
|
||||
|
||||
#endif
|
||||
diff --git a/include/grub/types.h b/include/grub/types.h
|
||||
index bfa7af9..32ca225 100644
|
||||
--- a/include/grub/types.h
|
||||
+++ b/include/grub/types.h
|
||||
@@ -353,4 +353,6 @@ struct grub_uuid
|
||||
grub_uint8_t b[GRUB_UUID_SIZE];
|
||||
};
|
||||
|
||||
+typedef char grub_bool_t;
|
||||
+
|
||||
#endif /* ! GRUB_TYPES_HEADER */
|
||||
@ -0,0 +1,108 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:40 +0530
|
||||
Subject: [PATCH] appendedsig: Reads the default DB keys from ELF Note
|
||||
|
||||
If Secure Boot is enabled with PKS and the use_static_keys flag is set,
|
||||
then read the DB default keys from the ELF note and store them in the trusted list buffer.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
grub-core/commands/appendedsig/appendedsig.c | 56 ++++++++++++++++++++--------
|
||||
1 file changed, 40 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||
index 07d6b39..f51942b 100644
|
||||
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||
@@ -1041,7 +1041,7 @@ create_distrusted_list (void)
|
||||
* parse it, and add it to the trusted list.
|
||||
*/
|
||||
static grub_err_t
|
||||
-build_static_trusted_list (const struct grub_module_header *header)
|
||||
+build_static_trusted_list (const struct grub_module_header *header, const grub_bool_t is_pks)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
struct grub_file pseudo_file;
|
||||
@@ -1060,6 +1060,13 @@ build_static_trusted_list (const struct grub_module_header *header)
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
+ if (is_pks)
|
||||
+ {
|
||||
+ err = is_distrusted_cert_hash (cert_data, cert_data_size);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
err = add_certificate (cert_data, cert_data_size, &db, 1);
|
||||
grub_free (cert_data);
|
||||
|
||||
@@ -1112,6 +1119,22 @@ free_distrusted_list (void)
|
||||
grub_memset (&dbx, 0, sizeof (dbx));
|
||||
}
|
||||
|
||||
+static grub_err_t
|
||||
+load_static_keys (const struct grub_module_header *header, const grub_bool_t is_pks)
|
||||
+{
|
||||
+ int rc = GRUB_ERR_NONE;
|
||||
+ FOR_MODULES (header)
|
||||
+ {
|
||||
+ /* Not an ELF module, skip. */
|
||||
+ if (header->type != OBJ_TYPE_X509_PUBKEY)
|
||||
+ continue;
|
||||
+ rc = build_static_trusted_list (header, is_pks);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ return rc;
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
GRUB_MOD_INIT (appendedsig)
|
||||
{
|
||||
int rc;
|
||||
@@ -1130,26 +1153,27 @@ GRUB_MOD_INIT (appendedsig)
|
||||
|
||||
if (!grub_pks_use_keystore && check_sigs == check_sigs_forced)
|
||||
{
|
||||
- FOR_MODULES (header)
|
||||
+ rc = load_static_keys (header, false);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
{
|
||||
- /* Not an ELF module, skip. */
|
||||
- if (header->type != OBJ_TYPE_X509_PUBKEY)
|
||||
- continue;
|
||||
-
|
||||
- rc = build_static_trusted_list (header);
|
||||
- if (rc != GRUB_ERR_NONE)
|
||||
- {
|
||||
- free_trusted_list ();
|
||||
- grub_error (rc, "static trusted list creation failed");
|
||||
- }
|
||||
- else
|
||||
- grub_dprintf ("appendedsig", "the trusted list now has %" PRIuGRUB_SIZE " static keys\n",
|
||||
- db.key_entries);
|
||||
+ free_trusted_list ();
|
||||
+ grub_error (rc, "static trusted list creation failed");
|
||||
}
|
||||
+ else
|
||||
+ grub_dprintf ("appendedsig", "the trusted list now has %" PRIuGRUB_SIZE " static keys\n",
|
||||
+ db.key_entries);
|
||||
}
|
||||
else if (grub_pks_use_keystore && check_sigs == check_sigs_forced)
|
||||
{
|
||||
- rc = create_trusted_list ();
|
||||
+ if (grub_pks_keystore.use_static_keys)
|
||||
+ {
|
||||
+ grub_printf ("Warning: db variable is not available at PKS and using a static keys "
|
||||
+ "as a default key in trusted list\n");
|
||||
+ rc = load_static_keys (header, grub_pks_keystore.use_static_keys);
|
||||
+ }
|
||||
+ else
|
||||
+ rc = create_trusted_list ();
|
||||
+
|
||||
if (rc != GRUB_ERR_NONE)
|
||||
{
|
||||
free_trusted_list ();
|
||||
@ -0,0 +1,660 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:41 +0530
|
||||
Subject: [PATCH] appendedsig: The grub command's trusted and distrusted
|
||||
support
|
||||
|
||||
To support the following trusted and distrusted commands
|
||||
|
||||
1. trusted_list:
|
||||
It will show the list of trusted certificates and binary hashes
|
||||
2. distrusted_list:
|
||||
It will show the list of distrusted certificates and binary/certificate hashes
|
||||
3. trusted_certificate:
|
||||
It will add the trusted certificate to the trusted list
|
||||
4. trusted_signature:
|
||||
It will add the certificate/binary hash to the trusted list
|
||||
5. distrusted_certificate:
|
||||
It will remove the trusted certificate from trsuted list
|
||||
6. distrusted_signature:
|
||||
It will add the certificate/binary hash to the distrsuted list
|
||||
|
||||
Note:-
|
||||
The addition/deletion of trusted certificates and binary hashes
|
||||
are not allowed in grub command prompt while secure boot is enabled.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
grub-core/commands/appendedsig/appendedsig.c | 528 ++++++++++++++++++---------
|
||||
1 file changed, 356 insertions(+), 172 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||
index f51942b..b8548f8 100644
|
||||
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||
@@ -117,6 +117,36 @@ static enum
|
||||
check_sigs_forced = 2
|
||||
} check_sigs = check_sigs_no;
|
||||
|
||||
+enum
|
||||
+{
|
||||
+ OPTION_BINARY_HASH = 0,
|
||||
+ OPTION_CERT_HASH = 1
|
||||
+};
|
||||
+
|
||||
+static const struct grub_arg_option options[] =
|
||||
+{
|
||||
+ {"binary-hash", 'b', 0, N_("hash file of the binary."), 0, ARG_TYPE_NONE},
|
||||
+ {"cert-hash", 'c', 1, N_("hash file of the certificate."), 0, ARG_TYPE_NONE},
|
||||
+ {0, 0, 0, 0, 0, 0}
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+print_hex (const grub_uint8_t *data, const grub_size_t length)
|
||||
+{
|
||||
+ grub_size_t i, count = 0;
|
||||
+ for (i = 0; i < length-1; i++)
|
||||
+ {
|
||||
+ grub_printf ("%02x:", data[i]);
|
||||
+ count++;
|
||||
+ if (count == 16)
|
||||
+ {
|
||||
+ grub_printf ("\n\t ");
|
||||
+ count = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ grub_printf ("%02x\n", data[i]);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* GUID can be used to determine the hashing function and
|
||||
* generate the hash using determined hashing function.
|
||||
@@ -344,72 +374,6 @@ grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), const cha
|
||||
return grub_strdup (grub_env_read_sec (NULL, NULL));
|
||||
}
|
||||
|
||||
-static grub_err_t
|
||||
-file_read_all (grub_file_t file, grub_uint8_t **buf, grub_size_t *len)
|
||||
-{
|
||||
- grub_off_t full_file_size;
|
||||
- grub_size_t file_size, total_read_size = 0;
|
||||
- grub_ssize_t read_size;
|
||||
-
|
||||
- full_file_size = grub_file_size (file);
|
||||
- if (full_file_size == GRUB_FILE_SIZE_UNKNOWN)
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
- N_("Cannot read a file of unknown size into a buffer"));
|
||||
-
|
||||
- if (full_file_size > GRUB_SIZE_MAX)
|
||||
- return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
- N_("File is too large to read: %" PRIuGRUB_UINT64_T " bytes"),
|
||||
- full_file_size);
|
||||
-
|
||||
- file_size = (grub_size_t) full_file_size;
|
||||
-
|
||||
- *buf = grub_malloc (file_size);
|
||||
- if (!*buf)
|
||||
- return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
- N_("Could not allocate file data buffer size %" PRIuGRUB_SIZE),
|
||||
- file_size);
|
||||
-
|
||||
- while (total_read_size < file_size)
|
||||
- {
|
||||
- read_size = grub_file_read (file, *buf + total_read_size, file_size - total_read_size);
|
||||
-
|
||||
- if (read_size < 0)
|
||||
- {
|
||||
- grub_free (*buf);
|
||||
- return grub_errno;
|
||||
- }
|
||||
- else if (read_size == 0)
|
||||
- {
|
||||
- grub_free (*buf);
|
||||
- return grub_error (GRUB_ERR_IO,
|
||||
- N_("Could not read full file size "
|
||||
- "(%" PRIuGRUB_SIZE "), only %" PRIuGRUB_SIZE " bytes read"),
|
||||
- file_size, total_read_size);
|
||||
- }
|
||||
-
|
||||
- total_read_size += read_size;
|
||||
- }
|
||||
- *len = file_size;
|
||||
- return GRUB_ERR_NONE;
|
||||
-}
|
||||
-
|
||||
-static grub_err_t
|
||||
-read_cert_from_file (grub_file_t f, struct x509_certificate *certificate)
|
||||
-{
|
||||
- grub_err_t err;
|
||||
- grub_uint8_t *buf;
|
||||
- grub_size_t file_size;
|
||||
-
|
||||
- err = file_read_all (f, &buf, &file_size);
|
||||
- if (err != GRUB_ERR_NONE)
|
||||
- return err;
|
||||
-
|
||||
- err = parse_x509_certificate (buf, file_size, certificate);
|
||||
- grub_free (buf);
|
||||
-
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
static grub_err_t
|
||||
extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
|
||||
struct grub_appended_signature *sig)
|
||||
@@ -630,143 +594,345 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||
static grub_err_t
|
||||
grub_cmd_verify_signature (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||
{
|
||||
- grub_file_t f;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
- grub_uint8_t *data;
|
||||
- grub_size_t file_size;
|
||||
+ grub_file_t signed_file = NULL;
|
||||
+ grub_uint8_t *signed_data = NULL;
|
||||
+ grub_ssize_t signed_data_size = 0;
|
||||
|
||||
- if (argc < 1)
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
+ if (argc != 1)
|
||||
+ {
|
||||
+ grub_printf (N_("a signed file is expected\n"
|
||||
+ "Example:\n\tverify_appended <SIGNED FILE>\n"));
|
||||
+ return GRUB_ERR_BAD_ARGUMENT;
|
||||
+ }
|
||||
|
||||
grub_dprintf ("appendedsig", "verifying %s\n", args[0]);
|
||||
|
||||
- f = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
|
||||
- if (!f)
|
||||
+ signed_file = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
|
||||
+ if (signed_file == NULL)
|
||||
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("unable to open a signed file"));
|
||||
+
|
||||
+ err = grub_read_file (signed_file, &signed_data, &signed_data_size);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_file_close (signed_file);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ grub_file_close (signed_file);
|
||||
+ err = grub_verify_appended_signature (signed_data, signed_data_size);
|
||||
+ grub_free (signed_data);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_trusted_list (grub_command_t cmd __attribute__((unused)),
|
||||
+ int argc __attribute__((unused)), char **args __attribute__((unused)))
|
||||
+{
|
||||
+ struct x509_certificate *cert = NULL;
|
||||
+ grub_size_t i = 0, cert_num = 1;
|
||||
+
|
||||
+ for (cert = db.keys; cert; cert = cert->next)
|
||||
+ {
|
||||
+ grub_printf (N_("trusted certificate %" PRIuGRUB_SIZE ":\n"), cert_num);
|
||||
+ grub_printf (N_("\tserial: "));
|
||||
+
|
||||
+ for (i = 0; i < cert->serial_len - 1; i++)
|
||||
+ grub_printf ("%02x:", cert->serial[i]);
|
||||
+
|
||||
+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
|
||||
+ grub_printf ("\tCN: %s\n\n", cert->subject);
|
||||
+ cert_num++;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < db.signature_entries; i++)
|
||||
+ {
|
||||
+ grub_printf (N_("trusted binary hash %" PRIuGRUB_SIZE ":\n"), i+1);
|
||||
+ grub_printf (N_("\thash: "));
|
||||
+ print_hex (db.signatures[i], db.signature_size[i]);
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_distrusted_list (grub_command_t cmd __attribute__((unused)),
|
||||
+ int argc __attribute__((unused)),
|
||||
+ char **args __attribute__((unused)))
|
||||
+{
|
||||
+ struct x509_certificate *cert = NULL;
|
||||
+ grub_size_t i = 0, cert_num = 1;
|
||||
+
|
||||
+ for (cert = dbx.keys; cert; cert = cert->next)
|
||||
+ {
|
||||
+ grub_printf (N_("distrusted certificate %" PRIuGRUB_SIZE ":\n"), cert_num);
|
||||
+ grub_printf (N_("\tserial: "));
|
||||
+
|
||||
+ for (i = 0; i < cert->serial_len - 1; i++)
|
||||
+ grub_printf ("%02x:", cert->serial[i]);
|
||||
+
|
||||
+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
|
||||
+ grub_printf ("\tCN: %s\n\n", cert->subject);
|
||||
+ cert_num++;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < dbx.signature_entries; i++)
|
||||
+ {
|
||||
+ grub_printf (N_("distrusted certificate/binary hash %" PRIuGRUB_SIZE ":\n"), i+1);
|
||||
+ grub_printf (N_("\thash: "));
|
||||
+ print_hex (dbx.signatures[i], dbx.signature_size[i]);
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_trusted_cert (grub_command_t cmd __attribute__((unused)),
|
||||
+ int argc, char **args)
|
||||
+{
|
||||
+ grub_err_t err = GRUB_ERR_NONE;
|
||||
+ grub_file_t cert_file = NULL;
|
||||
+ grub_uint8_t *cert_data = NULL;
|
||||
+ grub_ssize_t cert_data_size = 0;
|
||||
+
|
||||
+ if (argc != 1)
|
||||
{
|
||||
- err = grub_errno;
|
||||
- goto cleanup;
|
||||
+ grub_printf (N_("a trusted X.509 certificate file is expected\n"
|
||||
+ "Example:\n\ttrusted_certificate <CERT FILE>\n"));
|
||||
+ return GRUB_ERR_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
- err = file_read_all (f, &data, &file_size);
|
||||
+ if (check_sigs == check_sigs_forced)
|
||||
+ {
|
||||
+ grub_printf ("Warning: since secure boot is enabled, "
|
||||
+ "adding of trusted X.509 certificate is not permitted!\n");
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+
|
||||
+ if (grub_strlen (args[0]) == 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_FILENAME,
|
||||
+ N_("missing trusted X.509 certificate file"));
|
||||
+
|
||||
+ cert_file = grub_file_open (args[0], GRUB_FILE_TYPE_CERTIFICATE_TRUST |
|
||||
+ GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
+ if (cert_file == NULL)
|
||||
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
+ N_("unable to open the trusted X.509 certificate file"));
|
||||
+
|
||||
+ err = grub_read_file (cert_file, &cert_data, &cert_data_size);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
- goto cleanup;
|
||||
+ {
|
||||
+ grub_file_close (cert_file);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- err = grub_verify_appended_signature (data, file_size);
|
||||
+ grub_file_close (cert_file);
|
||||
+ err = add_certificate (cert_data, cert_data_size, &db, 1);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ free_trusted_list ();
|
||||
+ free_distrusted_list ();
|
||||
+ grub_error (err, "adding of trusted certificate failed");
|
||||
+ }
|
||||
|
||||
- grub_free (data);
|
||||
+ grub_free (cert_data);
|
||||
|
||||
-cleanup:
|
||||
- if (f)
|
||||
- grub_file_close (f);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_cmd_distrust (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||
+grub_cmd_trusted_hash (grub_command_t cmd __attribute__((unused)), int argc, char**args)
|
||||
{
|
||||
- unsigned long cert_num, i;
|
||||
- struct x509_certificate *cert, *prev;
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_file_t hash_file = NULL;
|
||||
+ grub_uint8_t *hash_data = NULL;
|
||||
+ grub_ssize_t hash_data_size = 0;
|
||||
|
||||
if (argc != 1)
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("One argument expected"));
|
||||
+ {
|
||||
+ grub_printf (N_("a trusted binary hash file is expected\n"
|
||||
+ "Example:\n\ttrusted_signature <BINARY HASH FILE>\n"));
|
||||
+ return GRUB_ERR_BAD_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ if (check_sigs == check_sigs_forced)
|
||||
+ {
|
||||
+ grub_printf ("Warning: since secure boot is enabled, "
|
||||
+ "adding of trusted binary hash is not permitted!\n");
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+
|
||||
+ if (grub_strlen (args[0]) == 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_FILENAME, N_("missing trusted binary hash file"));
|
||||
+
|
||||
+ hash_file = grub_file_open (args[0], GRUB_FILE_TYPE_TO_HASH | GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
+ if (hash_file == NULL)
|
||||
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
+ N_("unable to open the trusted binary hash file"));
|
||||
+
|
||||
+ rc = grub_read_file (hash_file, &hash_data, &hash_data_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_file_close (hash_file);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ grub_file_close (hash_file);
|
||||
+
|
||||
+ grub_dprintf ("appendedsig", "adding a trusted binary hash %s\n with size of %" PRIuGRUB_SIZE "\n",
|
||||
+ hash_data, hash_data_size);
|
||||
+
|
||||
+ /* only accept SHA256, SHA384 and SHA512 binary hash */
|
||||
+ if (hash_data_size != 32 && hash_data_size != 48 && hash_data_size != 64)
|
||||
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("unacceptable trusted binary hash type"));
|
||||
+
|
||||
+ rc = add_hash ((const grub_uint8_t **) &hash_data, hash_data_size, &db.signatures,
|
||||
+ &db.signature_size, &db.signature_entries);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ free_trusted_list ();
|
||||
+ free_distrusted_list ();
|
||||
+ grub_error (rc, "adding of trusted binary hash failed");
|
||||
+ }
|
||||
+
|
||||
+ grub_free (hash_data);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_distrusted_cert (grub_command_t cmd __attribute__((unused)), int argc, char **args)
|
||||
+{
|
||||
+ grub_size_t cert_num = 0, i = 1;
|
||||
+ struct x509_certificate *current_cert = db.keys;
|
||||
+ struct x509_certificate *previous_cert = db.keys;
|
||||
+
|
||||
+ if (argc != 1)
|
||||
+ {
|
||||
+ grub_printf (N_("trusted certificate number is expected\n"
|
||||
+ "Example:\n\tdistrusted_certificate <CERT_NUMER>\n"));
|
||||
+ return GRUB_ERR_BAD_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ if (check_sigs == check_sigs_forced)
|
||||
+ {
|
||||
+ grub_printf ("Warning: since secure boot is enabled, "
|
||||
+ "removing of trusted certificate is not permitted!\n");
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
|
||||
- grub_errno = GRUB_ERR_NONE;
|
||||
cert_num = grub_strtoul (args[0], NULL, 10);
|
||||
- if (grub_errno != GRUB_ERR_NONE)
|
||||
- return grub_errno;
|
||||
-
|
||||
if (cert_num < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
- N_("Certificate number too small - numbers start at 1"));
|
||||
+ N_("trusted certificate number should to begin with 1"));
|
||||
|
||||
- if (cert_num == 1)
|
||||
- {
|
||||
- cert = db.keys;
|
||||
- db.keys = cert->next;
|
||||
+ if (cert_num > db.key_entries)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("trusted certificate number should not exceed %" PRIuGRUB_SIZE ""),
|
||||
+ db.key_entries);
|
||||
+ else if (cert_num < db.key_entries)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("there is no certificate on the trusted list. so, not permitted"));
|
||||
|
||||
- certificate_release (cert);
|
||||
- grub_free (cert);
|
||||
- return GRUB_ERR_NONE;
|
||||
- }
|
||||
- i = 2;
|
||||
- prev = db.keys;
|
||||
- cert = db.keys->next;
|
||||
- while (cert)
|
||||
+ for (i = 1; i < db.key_entries; i++)
|
||||
{
|
||||
- if (i == cert_num)
|
||||
+ if (cert_num == 1)
|
||||
+ {
|
||||
+ previous_cert = current_cert->next;
|
||||
+ break;
|
||||
+ }
|
||||
+ else if (cert_num == i)
|
||||
{
|
||||
- prev->next = cert->next;
|
||||
- certificate_release (cert);
|
||||
- grub_free (cert);
|
||||
- return GRUB_ERR_NONE;
|
||||
+ previous_cert->next = current_cert->next;
|
||||
+ break;
|
||||
}
|
||||
- i++;
|
||||
- prev = cert;
|
||||
- cert = cert->next;
|
||||
+
|
||||
+ previous_cert = current_cert;
|
||||
+ current_cert = current_cert->next;
|
||||
}
|
||||
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
- N_("No certificate number %lu found - only %lu certificates in the store"),
|
||||
- cert_num, i - 1);
|
||||
+ certificate_release (current_cert);
|
||||
+ grub_free (current_cert);
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_cmd_trust (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||
+grub_cmd_distrusted_hash (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
- grub_file_t certf;
|
||||
- struct x509_certificate *cert = NULL;
|
||||
- grub_err_t err;
|
||||
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||
+ grub_file_t hash_file = NULL;
|
||||
+ grub_uint8_t *hash_data = NULL;
|
||||
+ grub_ssize_t hash_data_size = 0;
|
||||
|
||||
- if (argc != 1)
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
-
|
||||
- certf = grub_file_open (args[0], GRUB_FILE_TYPE_CERTIFICATE_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
- if (!certf)
|
||||
- return grub_errno;
|
||||
-
|
||||
- cert = grub_zalloc (sizeof (struct x509_certificate));
|
||||
- if (!cert)
|
||||
- return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("Could not allocate memory for certificate"));
|
||||
+ if (argc != 2)
|
||||
+ {
|
||||
+ grub_printf (N_("a distrusted certificate/binary hash file is expected\n"
|
||||
+ "Example:\n\tdistrusted_signature [option] <FILE>\n"
|
||||
+ "option:\n[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
|
||||
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]\n"));
|
||||
+ return GRUB_ERR_BAD_ARGUMENT;
|
||||
+ }
|
||||
|
||||
- err = read_cert_from_file (certf, cert);
|
||||
- grub_file_close (certf);
|
||||
- if (err != GRUB_ERR_NONE)
|
||||
+ if (check_sigs == check_sigs_forced)
|
||||
{
|
||||
- grub_free (cert);
|
||||
- return err;
|
||||
+ grub_printf ("Warning: since secure boot is enabled, "
|
||||
+ "adding of distrusted certificate/binary hash is not permitted!\n");
|
||||
+ return grub_errno;
|
||||
}
|
||||
- grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n", cert->subject);
|
||||
|
||||
- cert->next = db.keys;
|
||||
- db.keys = cert;
|
||||
+ if (!ctxt->state[OPTION_BINARY_HASH].set && !ctxt->state[OPTION_CERT_HASH].set)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing options and use --help to konw"));
|
||||
|
||||
- return GRUB_ERR_NONE;
|
||||
-}
|
||||
+ if (grub_strlen (args[1]) == 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_FILENAME,
|
||||
+ N_("missing distrusted certificate/binary hash file"));
|
||||
|
||||
-static grub_err_t
|
||||
-grub_cmd_list (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)),
|
||||
- char **args __attribute__ ((unused)))
|
||||
-{
|
||||
- struct x509_certificate *cert;
|
||||
- int cert_num = 1;
|
||||
- grub_size_t i;
|
||||
+ hash_file = grub_file_open (args[1], GRUB_FILE_TYPE_TO_HASH | GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
+ if (hash_file == NULL)
|
||||
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
+ N_("unable to open the distrusted certificate/binary hash file"));
|
||||
|
||||
- for (cert = db.keys; cert; cert = cert->next)
|
||||
+ rc = grub_read_file (hash_file, &hash_data, &hash_data_size);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
{
|
||||
- grub_printf (N_("Certificate %d:\n"), cert_num);
|
||||
+ grub_file_close (hash_file);
|
||||
+ return rc;
|
||||
+ }
|
||||
|
||||
- grub_printf (N_("\tSerial: "));
|
||||
- for (i = 0; i < cert->serial_len - 1; i++)
|
||||
- {
|
||||
- grub_printf ("%02x:", cert->serial[i]);
|
||||
- }
|
||||
- grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
|
||||
+ grub_file_close (hash_file);
|
||||
|
||||
- grub_printf ("\tCN: %s\n\n", cert->subject);
|
||||
- cert_num++;
|
||||
+ grub_dprintf ("appendedsig", "adding a distrusted certificate/binary hash %s\n"
|
||||
+ " with size of %" PRIuGRUB_SIZE "\n", hash_data, hash_data_size);
|
||||
+
|
||||
+ if (ctxt->state[OPTION_BINARY_HASH].set)
|
||||
+ {
|
||||
+ /* only accept SHA256, SHA384 and SHA512 binary hash */
|
||||
+ if (hash_data_size != 32 && hash_data_size != 48 && hash_data_size != 64)
|
||||
+ return grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||
+ N_("unacceptable distrusted binary hash type"));
|
||||
+ }
|
||||
+ else if (ctxt->state[OPTION_CERT_HASH].set)
|
||||
+ {
|
||||
+ /* only accept SHA256, SHA384 and SHA512 certificate hash */
|
||||
+ if (hash_data_size != 32 && hash_data_size != 48 && hash_data_size != 64)
|
||||
+ return grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||
+ N_("unacceptable distrusted certificate hash type"));
|
||||
}
|
||||
|
||||
- return GRUB_ERR_NONE;
|
||||
+ rc = add_hash ((const grub_uint8_t **) &hash_data, hash_data_size, &dbx.signatures,
|
||||
+ &dbx.signature_size, &dbx.signature_entries);
|
||||
+ if (rc != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ free_trusted_list ();
|
||||
+ free_distrusted_list ();
|
||||
+ grub_error (rc, "adding of distrusted binary/certificate hash failed");
|
||||
+ }
|
||||
+
|
||||
+ grub_free (hash_data);
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -842,8 +1008,6 @@ pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
|
||||
/* Filesystem descriptor. */
|
||||
static struct grub_fs pseudo_fs = { .name = "pseudo", .fs_read = pseudo_read };
|
||||
|
||||
-static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust;
|
||||
-
|
||||
/*
|
||||
* Verify the trusted certificate against the certificate hashes from platform keystore buffer's
|
||||
* distrusted list.
|
||||
@@ -1135,6 +1299,10 @@ load_static_keys (const struct grub_module_header *header, const grub_bool_t is_
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static grub_extcmd_t cmd_distrusted_hash;
|
||||
+static grub_command_t cmd_verify, cmd_trusted_list, cmd_trusted_cert, cmd_trusted_hash,
|
||||
+ cmd_distrusted_list, cmd_distrusted_cert;
|
||||
+
|
||||
GRUB_MOD_INIT (appendedsig)
|
||||
{
|
||||
int rc;
|
||||
@@ -1196,17 +1364,31 @@ GRUB_MOD_INIT (appendedsig)
|
||||
|
||||
grub_pks_free_keystore ();
|
||||
}
|
||||
-
|
||||
- cmd_trust = grub_register_command ("trust_certificate", grub_cmd_trust, N_("X509_CERTIFICATE"),
|
||||
- N_("Add X509_CERTIFICATE to trusted certificates."));
|
||||
- cmd_list = grub_register_command ("list_certificates", grub_cmd_list, 0,
|
||||
- N_("Show the list of trusted x509 certificates."));
|
||||
+ cmd_trusted_cert = grub_register_command ("trusted_certificate", grub_cmd_trusted_cert,
|
||||
+ N_("X509_CERTIFICATE"),
|
||||
+ N_("Add X509_CERTIFICATE to trusted list."));
|
||||
+ cmd_trusted_hash = grub_register_command ("trusted_signature", grub_cmd_trusted_hash,
|
||||
+ N_("BINARY HASH FILE"),
|
||||
+ N_("Add trusted BINARY HASH to trusted list."));
|
||||
+ cmd_distrusted_cert = grub_register_command ("distrusted_certificate", grub_cmd_distrusted_cert,
|
||||
+ N_("CERT_NUMBER"),
|
||||
+ N_("Remove CERT_NUMBER (as listed by list_trusted)"
|
||||
+ " from trusted list."));
|
||||
+ cmd_distrusted_hash = grub_register_extcmd ("distrusted_signature", grub_cmd_distrusted_hash, 0,
|
||||
+ N_("[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
|
||||
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]"),
|
||||
+ N_("Add distrusted CERTFICATE/BINARY HASH "
|
||||
+ "to distrusted list."),
|
||||
+ options);
|
||||
+ cmd_trusted_list = grub_register_command ("trusted_list", grub_cmd_trusted_list, 0,
|
||||
+ N_("Show the list of trusted x509 certificates and"
|
||||
+ " trusted binary hashes."));
|
||||
+ cmd_distrusted_list = grub_register_command ("distrusted_list", grub_cmd_distrusted_list, 0,
|
||||
+ N_("Show the list of distrusted certificates and"
|
||||
+ " certificate/binary hashes"));
|
||||
cmd_verify = grub_register_command ("verify_appended", grub_cmd_verify_signature, N_("FILE"),
|
||||
- N_("Verify FILE against the trusted x509 certificates."));
|
||||
- cmd_distrust = grub_register_command ("distrust_certificate", grub_cmd_distrust,
|
||||
- N_("CERT_NUMBER"),
|
||||
- N_("Remove CERT_NUMBER (as listed by list_certificates)"
|
||||
- " from trusted certificates."));
|
||||
+ N_("Verify FILE against the trusted x509 certificates/"
|
||||
+ "trusted binary hashes."));
|
||||
|
||||
grub_verifier_register (&grub_appendedsig_verifier);
|
||||
grub_dl_set_persistent (mod);
|
||||
@@ -1218,10 +1400,12 @@ GRUB_MOD_FINI (appendedsig)
|
||||
* grub_dl_set_persistent should prevent this from actually running, but
|
||||
* it does still run under emu.
|
||||
*/
|
||||
-
|
||||
grub_verifier_unregister (&grub_appendedsig_verifier);
|
||||
grub_unregister_command (cmd_verify);
|
||||
- grub_unregister_command (cmd_list);
|
||||
- grub_unregister_command (cmd_trust);
|
||||
- grub_unregister_command (cmd_distrust);
|
||||
+ grub_unregister_command (cmd_trusted_list);
|
||||
+ grub_unregister_command (cmd_distrusted_list);
|
||||
+ grub_unregister_command (cmd_trusted_cert);
|
||||
+ grub_unregister_command (cmd_distrusted_cert);
|
||||
+ grub_unregister_command (cmd_trusted_hash);
|
||||
+ grub_unregister_extcmd (cmd_distrusted_hash);
|
||||
}
|
||||
210
SOURCES/0475-appendedsig-documentation.patch
Normal file
210
SOURCES/0475-appendedsig-documentation.patch
Normal file
@ -0,0 +1,210 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Thu, 27 Mar 2025 01:02:42 +0530
|
||||
Subject: [PATCH] appendedsig: documentation
|
||||
|
||||
This explains how static and dynamic key appended signatures can be used to form part of
|
||||
a secure boot chain, and documents the commands and variables introduced.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
docs/grub.texi | 109 +++++++++++++++++++++++++++++++++++++++------------------
|
||||
1 file changed, 74 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index 72cf517..a4ae8cd 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -4016,7 +4016,9 @@ you forget a command, you can run the command @command{help}
|
||||
* date:: Display or set current date and time
|
||||
* devicetree:: Load a device tree blob
|
||||
* distrust:: Remove a pubkey from trusted keys
|
||||
-* distrust_certificate:: Remove a certificate from the list of trusted certificates
|
||||
+* distrusted_certificate:: Remove a certificate from the trusted list
|
||||
+* distrusted_list:: List distrusted certificates and binary/certificate hashes
|
||||
+* distrusted_signature:: Add a binary hash to the distrusted list
|
||||
* drivemap:: Map a drive to another
|
||||
* echo:: Display a line of text
|
||||
* eval:: Evaluate agruments as GRUB commands
|
||||
@@ -4033,7 +4035,6 @@ you forget a command, you can run the command @command{help}
|
||||
* keystatus:: Check key modifier status
|
||||
* linux:: Load a Linux kernel
|
||||
* linux16:: Load a Linux kernel (16-bit mode)
|
||||
-* list_certificates:: List trusted certificates
|
||||
* list_env:: List variables in environment block
|
||||
* list_trusted:: List trusted public keys
|
||||
* load_env:: Load variables from environment block
|
||||
@@ -4072,7 +4073,9 @@ you forget a command, you can run the command @command{help}
|
||||
* test:: Check file types and compare values
|
||||
* true:: Do nothing, successfully
|
||||
* trust:: Add public key to list of trusted keys
|
||||
-* trust_certificate:: Add an x509 certificate to the list of trusted certificates
|
||||
+* trusted_certificate:: Add an x509 certificate to the trusted list
|
||||
+* trusted_list:: List trusted certificates and binary hashes
|
||||
+* trusted_signature:: Add a binary hash to the trusted list.
|
||||
* unset:: Unset an environment variable
|
||||
@comment * vbeinfo:: List available video modes
|
||||
* verify_appended:: Verify appended digital signature
|
||||
@@ -4416,16 +4419,15 @@ These keys are used to validate signatures when environment variable
|
||||
GPG-style digital signatures}, for more information.
|
||||
@end deffn
|
||||
|
||||
+@node distrusted_certificate
|
||||
+@subsection distrusted_certificate
|
||||
|
||||
-@node distrust_certificate
|
||||
-@subsection distrust_certificate
|
||||
-
|
||||
-@deffn Command distrust_certificate cert_number
|
||||
+@deffn Command distrusted_certificate cert_number
|
||||
Remove the x509 certificate numbered @var{cert_number} from GRUB's keyring of
|
||||
trusted x509 certificates for verifying appended signatures.
|
||||
|
||||
@var{cert_number} is the certificate number as listed by
|
||||
-@command{list_certificates} (@pxref{list_certificates}).
|
||||
+@command{trusted_list} (@pxref{trusted_list}).
|
||||
|
||||
These certificates are used to validate appended signatures when environment
|
||||
variable @code{check_appended_signatures} is set to @code{enforce} or
|
||||
@@ -4434,6 +4436,27 @@ variable @code{check_appended_signatures} is set to @code{enforce} or
|
||||
@xref{Using appended signatures} for more information.
|
||||
@end deffn
|
||||
|
||||
+@node distrusted_list
|
||||
+@subsection distrusted_list
|
||||
+
|
||||
+@deffn Command distrusted_list
|
||||
+List all the distrusted x509 certificates and binary/certificate hashes.
|
||||
+The output is a numbered list of certificates and binary/certificate hashes,
|
||||
+showing the certificate's serial number and Common Name.
|
||||
+@end deffn
|
||||
+
|
||||
+@node distrusted_signature
|
||||
+@subsection distrusted_signature
|
||||
+
|
||||
+@deffn Command distrusted_signature
|
||||
+Read a binary hash from the file @var{binary hash file}
|
||||
+and add it to GRUB's internal distrusted list. These hash are used to
|
||||
+restrict validation of linux image integrity using trusted list if appended
|
||||
+signatures validation failed when the environment variable
|
||||
+@code{check_appended_signatures} is set to @code{enforce}.
|
||||
+
|
||||
+See @xref{Using appended signatures} for more information.
|
||||
+@end deffn
|
||||
|
||||
@node drivemap
|
||||
@subsection drivemap
|
||||
@@ -4691,22 +4714,6 @@ for the sake of convenience.
|
||||
This command is only available on x86 systems.
|
||||
@end deffn
|
||||
|
||||
-
|
||||
-@node list_certificates
|
||||
-@subsection list_certificates
|
||||
-
|
||||
-@deffn Command list_certificates
|
||||
-List all x509 certificates trusted by GRUB for validating appended signatures.
|
||||
-The output is a numbered list of certificates, showing the certificate's serial
|
||||
-number and Common Name.
|
||||
-
|
||||
-The certificate number can be used as an argument to
|
||||
-@command{distrust_certificate} (@pxref{distrust_certificate}).
|
||||
-
|
||||
-See @xref{Using appended signatures} for more information.
|
||||
-@end deffn
|
||||
-
|
||||
-
|
||||
@node list_env
|
||||
@subsection list_env
|
||||
|
||||
@@ -5540,10 +5547,10 @@ information.
|
||||
@end deffn
|
||||
|
||||
|
||||
-@node trust_certificate
|
||||
-@subsection trust_certificate
|
||||
+@node trusted_certificate
|
||||
+@subsection trusted_certificate
|
||||
|
||||
-@deffn Command trust_certificate x509_certificate
|
||||
+@deffn Command trusted_certificate x509_certificate
|
||||
Read an DER-formatted x509 certificate from the file @var{x509_certificate}
|
||||
and add it to GRUB's internal list of trusted x509 certificates. These
|
||||
certificates are used to validate appended signatures when the environment
|
||||
@@ -5551,7 +5558,7 @@ variable @code{check_appended_signatures} is set to @code{enforce} or
|
||||
@code{forced}.
|
||||
|
||||
Note that if @code{check_appended_signatures} is set to @code{enforce} or
|
||||
-@code{forced} when @command{trust_certificate} is executed, then
|
||||
+@code{forced} when @command{trusted_certificate} is executed, then
|
||||
@var{x509_certificate} must itself bear an appended signature. (It is not
|
||||
sufficient that @var{x509_certificate} be signed by a trusted certificate
|
||||
according to the x509 rules: grub does not include support for validating
|
||||
@@ -5560,6 +5567,32 @@ signatures within x509 certificates themselves.)
|
||||
See @xref{Using appended signatures} for more information.
|
||||
@end deffn
|
||||
|
||||
+@node trusted_list
|
||||
+@subsection trusted_list
|
||||
+
|
||||
+@deffn Command trusted_list
|
||||
+List all x509 certificates and binary hases trusted by GRUB for validating
|
||||
+appended signatures. The output is a numbered list of certificates and binary
|
||||
+hashes, showing the certificate's serial number and Common Name.
|
||||
+
|
||||
+The certificate number can be used as an argument to
|
||||
+@command{distrusted_certificate} (@pxref{distrusted_certificate}).
|
||||
+
|
||||
+See @xref{Using appended signatures} for more information.
|
||||
+@end deffn
|
||||
+
|
||||
+@node trusted_signature
|
||||
+@subsection trusted_signature
|
||||
+
|
||||
+@deffn Command trust_signature
|
||||
+Read a binary hash from the file @var{binary hash file}
|
||||
+and add it to GRUB's internal trusted list. These binary hash are used to
|
||||
+validate linux image integrity if appended signatures validation failed
|
||||
+when the environment variable @code{check_appended_signatures} is set
|
||||
+to @code{enforce}.
|
||||
+
|
||||
+See @xref{Using appended signatures} for more information.
|
||||
+@end deffn
|
||||
|
||||
@node unset
|
||||
@subsection unset
|
||||
@@ -5584,9 +5617,8 @@ only on PC BIOS platforms.
|
||||
|
||||
@deffn Command verify_appended file
|
||||
Verifies an appended signature on @var{file} against the trusted certificates
|
||||
-known to GRUB (See @pxref{list_certificates}, @pxref{trust_certificate}, and
|
||||
-@pxref{distrust_certificate}).
|
||||
-
|
||||
+known to GRUB (See @pxref{trusted_list}, @pxref{trusted_certificate}, and
|
||||
+@pxref{distrusted_certificate}).
|
||||
Exit code @code{$?} is set to 0 if the signature validates
|
||||
successfully. If validation fails, it is set to a non-zero value.
|
||||
See @xref{Using appended signatures}, for more information.
|
||||
@@ -6183,10 +6215,17 @@ with an appended signature ends with the magic string:
|
||||
|
||||
where @code{\n} represents the line-feed character, @code{0x0a}.
|
||||
|
||||
-Certificates can be managed at boot time using the @pxref{trust_certificate},
|
||||
-@pxref{distrust_certificate} and @pxref{list_certificates} commands.
|
||||
-Certificates can also be built in to the core image using the @code{--x509}
|
||||
-parameter to @command{grub-install} or @command{grub-mkimage}.
|
||||
+For static key, Certificates will be built in to the core image using
|
||||
+the @code{--x509} parameter to @command{grub-install} or @command{grub-mkimage}.
|
||||
+it can allow to list the trusted certificates and binary hashes at boot time using
|
||||
+@pxref{trusted_list} and list distrusted certificates and binary/certificate hashes
|
||||
+at boot time using @pxref{distrusted_list} commands.
|
||||
+
|
||||
+For dynamic key, loads the signature database (DB) and forbidden
|
||||
+signature database (DBX) from platform keystore (PKS) and it can allow to list
|
||||
+the trusted certificates and binary hashes at boot time using @pxref{trusted_list}
|
||||
+and list distrusted certificates and binary/certificate hashes at boot time using
|
||||
+@pxref{distrusted_list} commands.
|
||||
|
||||
A file can be explictly verified using the @pxref{verify_appended} command.
|
||||
|
||||
@ -0,0 +1,301 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Fri, 22 Jul 2022 02:16:33 -0500
|
||||
Subject: [PATCH] efi: Add efitextmode command for getting/setting the text
|
||||
mode resolution
|
||||
|
||||
This command is meant to behave similarly to the "mode" command of the EFI
|
||||
Shell application. In addition to allowing mode selection by giving the
|
||||
number of columns and rows as arguments, the command allows specifying the
|
||||
mode number to select the mode. Also supported are the arguments "min" and
|
||||
"max", which set the mode to the minimum and maximum mode respectively as
|
||||
calculated by the columns * rows of that mode.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
docs/grub.texi | 42 ++++++++++
|
||||
grub-core/Makefile.core.def | 6 ++
|
||||
grub-core/commands/efi/efitextmode.c | 155 +++++++++++++++++++++++++++++++++++
|
||||
include/grub/efi/api.h | 6 ++
|
||||
include/grub/err.h | 1 +
|
||||
5 files changed, 210 insertions(+)
|
||||
create mode 100644 grub-core/commands/efi/efitextmode.c
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index a4ae8cd..2677059 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -4021,6 +4021,7 @@ you forget a command, you can run the command @command{help}
|
||||
* distrusted_signature:: Add a binary hash to the distrusted list
|
||||
* drivemap:: Map a drive to another
|
||||
* echo:: Display a line of text
|
||||
+* efitextmode:: Set/Get text output mode resolution
|
||||
* eval:: Evaluate agruments as GRUB commands
|
||||
* export:: Export an environment variable
|
||||
* false:: Do nothing, unsuccessfully
|
||||
@@ -4527,6 +4528,47 @@ character will print that character.
|
||||
@end deffn
|
||||
|
||||
|
||||
+@node efitextmode
|
||||
+@subsection efitextmode
|
||||
+
|
||||
+@deffn Command efitextmode [min | max | <mode_num> | <cols> <rows>]
|
||||
+When used with no arguments displays all available text output modes. The
|
||||
+set mode determines the columns and rows of the text display when in
|
||||
+text mode. An asterisk, @samp{*}, will be at the end of the line of the
|
||||
+currently set mode.
|
||||
+
|
||||
+If given a single parameter, it must be @samp{min}, @samp{max}, or a mode
|
||||
+number given by the listing when run with no arguments. These arguments set
|
||||
+the mode to the minimum, maximum, and particular mode respectively.
|
||||
+
|
||||
+Otherwise, the command must be given two numerical arguments specifying the
|
||||
+columns and rows of the desired mode. Specifying a columns and rows
|
||||
+combination that corresponds to no supported mode, will return error, but
|
||||
+otherwise have no effect.
|
||||
+
|
||||
+By default GRUB will start in whatever mode the EFI firmware defaults to.
|
||||
+There are firmwares known to set up the default mode such that output
|
||||
+behaves strangely, for example the cursor in the GRUB shell never reaches
|
||||
+the bottom of the screen or, when typing characters at the prompt,
|
||||
+characters from previous command output are overwritten. Setting the mode
|
||||
+may fix this.
|
||||
+
|
||||
+The EFI specification says that mode 0 must be available and have
|
||||
+columns and rows of 80 and 25 respectively. Mode 1 may be defined and if
|
||||
+so must have columns and rows of 80 and 50 respectively. Any other modes
|
||||
+may have columns and rows arbitrarily defined by the firmware. This means
|
||||
+that a mode with columns and rows of 100 and 31 on one firmware may be
|
||||
+a different mode number on a different firmware or not exist at all.
|
||||
+Likewise, mode number 2 on one firmware may have a different number of
|
||||
+columns and rows than mode 2 on a different firmware. So one should not
|
||||
+rely on a particular mode number or a mode of a certain number of columns
|
||||
+and rows existing on all firmwares, except for mode 0.
|
||||
+
|
||||
+Note: This command is only available on EFI platforms and is similar to
|
||||
+EFI shell "mode" command.
|
||||
+@end deffn
|
||||
+
|
||||
+
|
||||
@node eval
|
||||
@subsection eval
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 218068b..4588fa7 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -844,6 +844,12 @@ module = {
|
||||
enable = efi;
|
||||
};
|
||||
|
||||
+module = {
|
||||
+ name = efitextmode;
|
||||
+ efi = commands/efi/efitextmode.c;
|
||||
+ enable = efi;
|
||||
+};
|
||||
+
|
||||
module = {
|
||||
name = blocklist;
|
||||
common = commands/blocklist.c;
|
||||
diff --git a/grub-core/commands/efi/efitextmode.c b/grub-core/commands/efi/efitextmode.c
|
||||
new file mode 100644
|
||||
index 0000000..3679f6b
|
||||
--- /dev/null
|
||||
+++ b/grub-core/commands/efi/efitextmode.c
|
||||
@@ -0,0 +1,155 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ *
|
||||
+ * GRUB is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * GRUB is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ *
|
||||
+ * Set/Get UEFI text output mode resolution.
|
||||
+ */
|
||||
+
|
||||
+#include <grub/dl.h>
|
||||
+#include <grub/misc.h>
|
||||
+#include <grub/mm.h>
|
||||
+#include <grub/command.h>
|
||||
+#include <grub/i18n.h>
|
||||
+#include <grub/efi/efi.h>
|
||||
+#include <grub/efi/api.h>
|
||||
+
|
||||
+GRUB_MOD_LICENSE ("GPLv3+");
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_efi_set_mode (grub_efi_simple_text_output_interface_t *o,
|
||||
+ grub_efi_int32_t mode)
|
||||
+{
|
||||
+ grub_efi_status_t status;
|
||||
+
|
||||
+ if (mode != o->mode->mode)
|
||||
+ {
|
||||
+ status = efi_call_2 (o->set_mode, o, mode);
|
||||
+ if (status == GRUB_EFI_SUCCESS)
|
||||
+ ;
|
||||
+ else if (status == GRUB_EFI_DEVICE_ERROR)
|
||||
+ return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
+ N_("device error: could not set requested mode"));
|
||||
+ else if (status == GRUB_EFI_UNSUPPORTED)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ N_("invalid mode: number not valid"));
|
||||
+ else
|
||||
+ return grub_error (GRUB_ERR_BAD_FIRMWARE,
|
||||
+ N_("unexpected EFI error number: `%u'"),
|
||||
+ (unsigned) status);
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_efitextmode (grub_command_t cmd __attribute__ ((unused)),
|
||||
+ int argc, char **args)
|
||||
+{
|
||||
+ grub_efi_simple_text_output_interface_t *o = grub_efi_system_table->con_out;
|
||||
+ unsigned long mode;
|
||||
+ const char *p = NULL;
|
||||
+ grub_err_t err;
|
||||
+ grub_efi_uintn_t columns, rows;
|
||||
+ grub_efi_int32_t i;
|
||||
+
|
||||
+ if (o == NULL)
|
||||
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("no UEFI output console interface"));
|
||||
+
|
||||
+ if (o->mode == NULL)
|
||||
+ return grub_error (GRUB_ERR_BUG, N_("no mode struct for UEFI output console"));
|
||||
+
|
||||
+ if (argc > 2)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("at most two arguments expected"));
|
||||
+
|
||||
+ if (argc == 0)
|
||||
+ {
|
||||
+ grub_printf_ (N_("Available modes for console output device.\n"));
|
||||
+
|
||||
+ for (i = 0; i < o->mode->max_mode; i++)
|
||||
+ if (GRUB_EFI_SUCCESS == efi_call_4 (o->query_mode, o, i,
|
||||
+ &columns, &rows))
|
||||
+ grub_printf_ (N_(" [%" PRIuGRUB_EFI_UINT32_T "] Col %5"
|
||||
+ PRIuGRUB_EFI_UINTN_T " Row %5" PRIuGRUB_EFI_UINTN_T
|
||||
+ " %c\n"),
|
||||
+ i, columns, rows, (i == o->mode->mode) ? '*' : ' ');
|
||||
+ }
|
||||
+ else if (argc == 1)
|
||||
+ {
|
||||
+ if (grub_strcmp (args[0], "min") == 0)
|
||||
+ mode = 0;
|
||||
+ else if (grub_strcmp (args[0], "max") == 0)
|
||||
+ mode = o->mode->max_mode - 1;
|
||||
+ else
|
||||
+ {
|
||||
+ mode = grub_strtoul (args[0], &p, 0);
|
||||
+
|
||||
+ if (*args[0] == '\0' || *p != '\0')
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("non-numeric or invalid mode `%s'"), args[0]);
|
||||
+ }
|
||||
+
|
||||
+ if (mode < (unsigned long) o->mode->max_mode)
|
||||
+ {
|
||||
+ err = grub_efi_set_mode (o, (grub_efi_int32_t) mode);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
+ }
|
||||
+ else
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("invalid mode: `%lu' is greater than maximum mode `%lu'"),
|
||||
+ mode, (unsigned long) o->mode->max_mode);
|
||||
+ }
|
||||
+ else if (argc == 2)
|
||||
+ {
|
||||
+ grub_efi_uintn_t u_columns, u_rows;
|
||||
+
|
||||
+ u_columns = (grub_efi_uintn_t) grub_strtoul (args[0], &p, 0);
|
||||
+
|
||||
+ if (*args[0] == '\0' || *p != '\0')
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("non-numeric or invalid columns number `%s'"), args[0]);
|
||||
+
|
||||
+ u_rows = (grub_efi_uintn_t) grub_strtoul (args[1], &p, 0);
|
||||
+
|
||||
+ if (*args[1] == '\0' || *p != '\0')
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("non-numeric or invalid rows number `%s'"), args[1]);
|
||||
+
|
||||
+ for (i = 0; i < o->mode->max_mode; i++)
|
||||
+ if (GRUB_EFI_SUCCESS == efi_call_4 (o->query_mode, o, i,
|
||||
+ &columns, &rows))
|
||||
+ if (u_columns == columns && u_rows == rows)
|
||||
+ return grub_efi_set_mode (o, (grub_efi_int32_t) i);
|
||||
+
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("no mode found with requested columns and rows"));
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+static grub_command_t cmd;
|
||||
+GRUB_MOD_INIT (efitextmode)
|
||||
+{
|
||||
+ cmd = grub_register_command ("efitextmode", grub_cmd_efitextmode,
|
||||
+ N_("[min | max | <mode_num> | <cols> <rows>]"),
|
||||
+ N_("Get or set EFI text mode."));
|
||||
+}
|
||||
+
|
||||
+GRUB_MOD_FINI (efitextmode)
|
||||
+{
|
||||
+ grub_unregister_command (cmd);
|
||||
+}
|
||||
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
||||
index 464842b..f224037 100644
|
||||
--- a/include/grub/efi/api.h
|
||||
+++ b/include/grub/efi/api.h
|
||||
@@ -545,9 +545,13 @@ typedef char grub_efi_boolean_t;
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||
typedef grub_int64_t grub_efi_intn_t;
|
||||
typedef grub_uint64_t grub_efi_uintn_t;
|
||||
+#define PRIxGRUB_EFI_UINTN_T PRIxGRUB_UINT64_T
|
||||
+#define PRIuGRUB_EFI_UINTN_T PRIuGRUB_UINT64_T
|
||||
#else
|
||||
typedef grub_int32_t grub_efi_intn_t;
|
||||
typedef grub_uint32_t grub_efi_uintn_t;
|
||||
+#define PRIxGRUB_EFI_UINTN_T PRIxGRUB_UINT32_T
|
||||
+#define PRIuGRUB_EFI_UINTN_T PRIuGRUB_UINT32_T
|
||||
#endif
|
||||
typedef grub_int8_t grub_efi_int8_t;
|
||||
typedef grub_uint8_t grub_efi_uint8_t;
|
||||
@@ -555,6 +559,8 @@ typedef grub_int16_t grub_efi_int16_t;
|
||||
typedef grub_uint16_t grub_efi_uint16_t;
|
||||
typedef grub_int32_t grub_efi_int32_t;
|
||||
typedef grub_uint32_t grub_efi_uint32_t;
|
||||
+#define PRIxGRUB_EFI_UINT32_T PRIxGRUB_UINT32_T
|
||||
+#define PRIuGRUB_EFI_UINT32_T PRIuGRUB_UINT32_T
|
||||
typedef grub_int64_t grub_efi_int64_t;
|
||||
typedef grub_uint64_t grub_efi_uint64_t;
|
||||
typedef grub_uint8_t grub_efi_char8_t;
|
||||
diff --git a/include/grub/err.h b/include/grub/err.h
|
||||
index 905a6df..7530f58 100644
|
||||
--- a/include/grub/err.h
|
||||
+++ b/include/grub/err.h
|
||||
@@ -73,6 +73,7 @@ typedef enum
|
||||
GRUB_ERR_NET_NO_DOMAIN,
|
||||
GRUB_ERR_EOF,
|
||||
GRUB_ERR_BAD_SIGNATURE,
|
||||
+ GRUB_ERR_BAD_FIRMWARE,
|
||||
GRUB_ERR_STILL_REFERENCED,
|
||||
GRUB_ERR_RECURSION_DEPTH
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leo Sandoval <lsandova@redhat.com>
|
||||
Date: Wed, 7 May 2025 13:23:37 -0600
|
||||
Subject: [PATCH] 10_linux.in: escape kernel option characters properly
|
||||
|
||||
This handles cases where kernel options, specifically the values,
|
||||
contain special characters, in this case ';', '&' and '$'.
|
||||
|
||||
For example, the user defines the following GRUB_CMDLINE_LINUX on the
|
||||
default grub file /etc/default/grub, note the dolar sign on the 'memmap'
|
||||
option
|
||||
|
||||
GRUB_CMDLINE_LINUX="console=ttyS0 memmap=32g\\\$0x2000000000"
|
||||
|
||||
then regenerating the grub cfg and BLS options line with the
|
||||
grub2-mkconfig command, resulting into
|
||||
|
||||
options root=UUID=6baedf23-2510-499a-815d-48b58cf6e619 ro
|
||||
rootflags=subvol=root console=ttyS0 memmap=32g\$0x2000000000
|
||||
|
||||
without this patch, we would end up with
|
||||
|
||||
options root=UUID=6baedf23-2510-499a-815d-48b58cf6e619 ro
|
||||
rootflags=subvol=root console=ttyS0 memmap=32g$0x2000000000
|
||||
|
||||
Note the missing '\' which is required to escape the '$', otherwise
|
||||
it would be consider a variable by blscfg parser which is not the case.
|
||||
|
||||
Signed-off-by: Leo Sandoval <lsandova@redhat.com>
|
||||
---
|
||||
util/grub.d/10_linux.in | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
|
||||
index fafdfbc4d3..4276d5e240 100755
|
||||
--- a/util/grub.d/10_linux.in
|
||||
+++ b/util/grub.d/10_linux.in
|
||||
@@ -180,6 +180,7 @@ update_bls_cmdline()
|
||||
options="$(echo "${options}" | sed -e 's/\//\\\//g')"
|
||||
options="$(echo "${options}" | sed -e 's/\;/\\\;/g')"
|
||||
options="$(echo "${options}" | sed -e 's/\\&/\\\\&/g')"
|
||||
+ options="$(echo "${options}" | sed -e 's/\$/\\\$/g')"
|
||||
sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf"
|
||||
done
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leo Sandoval <lsandova@redhat.com>
|
||||
Date: Wed, 7 May 2025 13:49:47 -0600
|
||||
Subject: [PATCH] blscfg: check if variable is escaped before considering one
|
||||
|
||||
Otherwise escaped variables are considered real variables.
|
||||
|
||||
Signed-off-by: Leo Sandoval <lsandova@redhat.com>
|
||||
---
|
||||
grub-core/commands/blscfg.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
|
||||
index 6e398fc175..5d931b0c9b 100644
|
||||
--- a/grub-core/commands/blscfg.c
|
||||
+++ b/grub-core/commands/blscfg.c
|
||||
@@ -695,7 +695,8 @@ static char *expand_val(const char *value)
|
||||
return NULL;
|
||||
|
||||
while (*value) {
|
||||
- if (*value == '$') {
|
||||
+ /* It's a variable only when *value is '$' and it is not escaped with '\'*/
|
||||
+ if (*value == '$' && *end != '\\') {
|
||||
if (start != end) {
|
||||
buffer = field_append(is_var, buffer, start, end);
|
||||
if (!buffer)
|
||||
@ -0,0 +1,86 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
|
||||
Date: Thu, 24 Apr 2025 11:43:28 +0200
|
||||
Subject: [PATCH] osdep/linux/getroot: Detect DDF container similar to IMSM
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Similarly to Intel IMSM, there are BIOS and UEFI implementations that
|
||||
support DDF containers natively.
|
||||
|
||||
DDF and IMSM are very similar in handling, especially these should not
|
||||
be considered as RAID abstraction. This fixes the requirement of having
|
||||
a device map when probing DDF containers.
|
||||
|
||||
Fixes: https://issues.redhat.com/browse/RHEL-44336
|
||||
|
||||
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/osdep/linux/getroot.c | 19 +++++++++++++------
|
||||
1 file changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
|
||||
index 893527a..7430391 100644
|
||||
--- a/grub-core/osdep/linux/getroot.c
|
||||
+++ b/grub-core/osdep/linux/getroot.c
|
||||
@@ -131,7 +131,7 @@ struct btrfs_ioctl_search_args {
|
||||
struct btrfs_ioctl_fs_info_args)
|
||||
|
||||
static int
|
||||
-grub_util_is_imsm (const char *os_dev);
|
||||
+grub_util_is_imsm_or_ddf (const char *os_dev);
|
||||
|
||||
|
||||
#define ESCAPED_PATH_MAX (4 * PATH_MAX)
|
||||
@@ -762,10 +762,10 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
-grub_util_is_imsm (const char *os_dev)
|
||||
+grub_util_is_imsm_or_ddf (const char *os_dev)
|
||||
{
|
||||
int retry;
|
||||
- int is_imsm = 0;
|
||||
+ int is_imsm_or_ddf = 0;
|
||||
int container_seen = 0;
|
||||
const char *dev = os_dev;
|
||||
|
||||
@@ -826,10 +826,17 @@ grub_util_is_imsm (const char *os_dev)
|
||||
if (strncmp (buf, "MD_METADATA=imsm",
|
||||
sizeof ("MD_METADATA=imsm") - 1) == 0)
|
||||
{
|
||||
- is_imsm = 1;
|
||||
+ is_imsm_or_ddf = 1;
|
||||
grub_util_info ("%s is imsm", dev);
|
||||
break;
|
||||
}
|
||||
+ if (strncmp (buf, "MD_METADATA=ddf",
|
||||
+ sizeof ("MD_METADATA=ddf") - 1) == 0)
|
||||
+ {
|
||||
+ is_imsm_or_ddf = 1;
|
||||
+ grub_util_info ("%s is ddf", dev);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
free (buf);
|
||||
@@ -840,7 +847,7 @@ grub_util_is_imsm (const char *os_dev)
|
||||
|
||||
if (dev != os_dev)
|
||||
free ((void *) dev);
|
||||
- return is_imsm;
|
||||
+ return is_imsm_or_ddf;
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -1205,7 +1212,7 @@ grub_util_get_dev_abstraction_os (const char *os_dev)
|
||||
|
||||
/* Check for RAID. */
|
||||
if (!strncmp (os_dev, "/dev/md", 7) && ! grub_util_device_is_mapped (os_dev)
|
||||
- && !grub_util_is_imsm (os_dev))
|
||||
+ && !grub_util_is_imsm_or_ddf (os_dev))
|
||||
return GRUB_DEV_ABSTRACTION_RAID;
|
||||
return GRUB_DEV_ABSTRACTION_NONE;
|
||||
}
|
||||
@ -0,0 +1,342 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leo Sandoval <lsandova@redhat.com>
|
||||
Date: Mon, 28 Jul 2025 12:37:06 -0600
|
||||
Subject: [PATCH] Set correctly the memory attributes for the kernel PE
|
||||
sections
|
||||
|
||||
Currently the whole kernel memory region is set to RO, so at some
|
||||
point when execution is passed to the kernel, the latter faults on a
|
||||
memory write access, e.g. zeroing .bss section. The proposed change
|
||||
sets the memory attribute appropriately for each kernel PE section.
|
||||
|
||||
Signed-off-by: Leo Sandoval <lsandova@redhat.com>
|
||||
---
|
||||
grub-core/loader/arm64/linux.c | 2 +-
|
||||
grub-core/loader/efi/linux.c | 165 ++++++++++++++++++++++++++++----------
|
||||
grub-core/loader/i386/efi/linux.c | 5 +-
|
||||
include/grub/efi/linux.h | 7 ++
|
||||
include/grub/efi/pe32.h | 28 +++++++
|
||||
5 files changed, 161 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
|
||||
index a3a193c255..c03e602974 100644
|
||||
--- a/grub-core/loader/arm64/linux.c
|
||||
+++ b/grub-core/loader/arm64/linux.c
|
||||
@@ -182,7 +182,7 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args,
|
||||
|
||||
grub_dprintf ("linux", "linux command line: '%s'\n", args);
|
||||
|
||||
- retval = grub_efi_linux_boot (addr, size, handover_offset,
|
||||
+ retval = grub_efi_linux_boot (addr, size, 0, handover_offset,
|
||||
(void *)addr, nx_supported);
|
||||
|
||||
/* Never reached... */
|
||||
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
|
||||
index e413bdcc23..4d7cd3c624 100644
|
||||
--- a/grub-core/loader/efi/linux.c
|
||||
+++ b/grub-core/loader/efi/linux.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/pe32.h>
|
||||
#include <grub/efi/linux.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
@@ -133,20 +134,130 @@ grub_efi_check_nx_required (int *nx_required)
|
||||
typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
|
||||
|
||||
grub_err_t
|
||||
-grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size,
|
||||
+grub_efi_mem_set_att (grub_addr_t kernel_address, grub_size_t kernel_size,
|
||||
+ grub_size_t kernel_start, int nx_supported)
|
||||
+{
|
||||
+ grub_addr_t kernel_start_address = kernel_address + kernel_start;
|
||||
+
|
||||
+ grub_uint64_t default_set_attrs = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X;
|
||||
+ grub_uint64_t default_clear_attrs = 0;
|
||||
+ grub_uint64_t stack_set_attrs = default_set_attrs;
|
||||
+ grub_uint64_t stack_clear_attrs = default_clear_attrs;
|
||||
+ grub_uint64_t kernel_set_attrs = default_set_attrs;
|
||||
+ grub_uint64_t kernel_clear_attrs = default_clear_attrs;
|
||||
+ grub_uint64_t attrs;
|
||||
+
|
||||
+ struct grub_msdos_image_header *header;
|
||||
+ struct grub_pe_image_header *pe_image_header;
|
||||
+ struct grub_pe32_coff_header *coff_header;
|
||||
+ struct grub_pe32_section_table *section, *sections;
|
||||
+ grub_uint16_t i;
|
||||
+ grub_size_t sz;
|
||||
+
|
||||
+ header = (struct grub_msdos_image_header *)kernel_address;
|
||||
+
|
||||
+ if (grub_add ((grub_addr_t) header, header->pe_image_header_offset, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("Error on PE image header address calculation"));
|
||||
+
|
||||
+ pe_image_header = (struct grub_pe_image_header *) (sz);
|
||||
+
|
||||
+ if (pe_image_header > (kernel_address + kernel_size))
|
||||
+ return grub_error (GRUB_ERR_BAD_OS, N_("PE image header address is invalid"));
|
||||
+
|
||||
+ if (grub_memcmp (pe_image_header->signature, GRUB_PE32_SIGNATURE,
|
||||
+ GRUB_PE32_SIGNATURE_SIZE) != 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel PE magic is invalid"));
|
||||
+
|
||||
+ coff_header = &(pe_image_header->coff_header);
|
||||
+ grub_dprintf ("nx", "coff_header 0x%"PRIxGRUB_ADDR" machine %08x\n", (grub_addr_t)coff_header, coff_header->machine);
|
||||
+
|
||||
+ if (grub_add ((grub_addr_t) coff_header, sizeof (*coff_header), &sz) ||
|
||||
+ grub_add (sz, coff_header->optional_header_size, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("Error on PE sections calculation"));
|
||||
+
|
||||
+ sections = (struct grub_pe32_section_table *) (sz);
|
||||
+
|
||||
+ if (sections > (kernel_address + kernel_size))
|
||||
+ return grub_error (GRUB_ERR_BAD_OS, N_("Section address is invalid"));
|
||||
+
|
||||
+ /* Parse the PE, remove W for code section, remove X for data sections, RO for the rest */
|
||||
+ for (i = 0, section = sections; i < coff_header->num_sections; i++, section++)
|
||||
+ {
|
||||
+ kernel_set_attrs = default_set_attrs;
|
||||
+ kernel_clear_attrs = default_clear_attrs;
|
||||
+
|
||||
+ if (nx_supported)
|
||||
+ {
|
||||
+ if (section->characteristics & GRUB_PE32_SCN_MEM_EXECUTE)
|
||||
+ {
|
||||
+ /* RX section */
|
||||
+ kernel_set_attrs &= ~GRUB_MEM_ATTR_W;
|
||||
+ kernel_clear_attrs |= GRUB_MEM_ATTR_W;
|
||||
+ }
|
||||
+ else if (section->characteristics & GRUB_PE32_SCN_MEM_WRITE)
|
||||
+ {
|
||||
+ /* RW section */
|
||||
+ kernel_set_attrs &= ~GRUB_MEM_ATTR_X;
|
||||
+ kernel_clear_attrs |= GRUB_MEM_ATTR_X;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* RO section */
|
||||
+ kernel_set_attrs &= ~GRUB_MEM_ATTR_W & ~GRUB_MEM_ATTR_X;
|
||||
+ kernel_clear_attrs |= GRUB_MEM_ATTR_X | GRUB_MEM_ATTR_W ;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Make sure we are inside range */
|
||||
+ if (grub_add ((grub_addr_t) kernel_address, section->raw_data_offset, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("Error on PE Executable section calculation"));
|
||||
+
|
||||
+ grub_update_mem_attrs (sz, section->raw_data_size, kernel_set_attrs, kernel_clear_attrs);
|
||||
+
|
||||
+ grub_get_mem_attrs (sz, 4096, &attrs);
|
||||
+ grub_dprintf ("nx", "permissions for section %s 0x%"PRIxGRUB_ADDR" are %s%s%s\n",
|
||||
+ section->name,
|
||||
+ (grub_addr_t)sz,
|
||||
+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-",
|
||||
+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-",
|
||||
+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-");
|
||||
+ }
|
||||
+
|
||||
+ if (grub_stack_addr != (grub_addr_t)-1ll)
|
||||
+ {
|
||||
+ if (nx_supported)
|
||||
+ {
|
||||
+ stack_set_attrs &= ~GRUB_MEM_ATTR_X;
|
||||
+ stack_clear_attrs |= GRUB_MEM_ATTR_X;
|
||||
+ }
|
||||
+
|
||||
+ grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n",
|
||||
+ grub_stack_addr, grub_stack_addr + grub_stack_size - 1,
|
||||
+ (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-');
|
||||
+
|
||||
+ grub_update_mem_attrs (grub_stack_addr, grub_stack_size,
|
||||
+ stack_set_attrs, stack_clear_attrs);
|
||||
+
|
||||
+ grub_get_mem_attrs (grub_stack_addr, 4096, &attrs);
|
||||
+ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n",
|
||||
+ grub_stack_addr,
|
||||
+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-",
|
||||
+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-",
|
||||
+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-");
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+grub_err_t
|
||||
+grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, grub_size_t kernel_start,
|
||||
grub_off_t handover_offset, void *kernel_params,
|
||||
int nx_supported)
|
||||
{
|
||||
+ grub_addr_t kernel_start_address = kernel_addr + kernel_start;
|
||||
grub_efi_loaded_image_t *loaded_image = NULL;
|
||||
handover_func hf;
|
||||
int offset = 0;
|
||||
- grub_uint64_t stack_set_attrs = GRUB_MEM_ATTR_R |
|
||||
- GRUB_MEM_ATTR_W |
|
||||
- GRUB_MEM_ATTR_X;
|
||||
- grub_uint64_t stack_clear_attrs = 0;
|
||||
- grub_uint64_t kernel_set_attrs = stack_set_attrs;
|
||||
- grub_uint64_t kernel_clear_attrs = stack_clear_attrs;
|
||||
- grub_uint64_t attrs;
|
||||
int nx_required = 0;
|
||||
|
||||
#ifdef __x86_64__
|
||||
@@ -171,41 +282,7 @@ grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size,
|
||||
if (nx_required && !nx_supported)
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("kernel does not support NX loading required by policy"));
|
||||
|
||||
- if (nx_supported)
|
||||
- {
|
||||
- kernel_set_attrs &= ~GRUB_MEM_ATTR_W;
|
||||
- kernel_clear_attrs |= GRUB_MEM_ATTR_W;
|
||||
- stack_set_attrs &= ~GRUB_MEM_ATTR_X;
|
||||
- stack_clear_attrs |= GRUB_MEM_ATTR_X;
|
||||
- }
|
||||
-
|
||||
- grub_dprintf ("nx", "Setting attributes for 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to r%cx\n",
|
||||
- kernel_addr, kernel_addr + kernel_size - 1,
|
||||
- (kernel_set_attrs & GRUB_MEM_ATTR_W) ? 'w' : '-');
|
||||
- grub_update_mem_attrs (kernel_addr, kernel_size,
|
||||
- kernel_set_attrs, kernel_clear_attrs);
|
||||
-
|
||||
- grub_get_mem_attrs (kernel_addr, 4096, &attrs);
|
||||
- grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n",
|
||||
- (grub_addr_t)kernel_addr,
|
||||
- (attrs & GRUB_MEM_ATTR_R) ? "r" : "-",
|
||||
- (attrs & GRUB_MEM_ATTR_W) ? "w" : "-",
|
||||
- (attrs & GRUB_MEM_ATTR_X) ? "x" : "-");
|
||||
- if (grub_stack_addr != (grub_addr_t)-1ll)
|
||||
- {
|
||||
- grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n",
|
||||
- grub_stack_addr, grub_stack_addr + grub_stack_size - 1,
|
||||
- (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-');
|
||||
- grub_update_mem_attrs (grub_stack_addr, grub_stack_size,
|
||||
- stack_set_attrs, stack_clear_attrs);
|
||||
-
|
||||
- grub_get_mem_attrs (grub_stack_addr, 4096, &attrs);
|
||||
- grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n",
|
||||
- grub_stack_addr,
|
||||
- (attrs & GRUB_MEM_ATTR_R) ? "r" : "-",
|
||||
- (attrs & GRUB_MEM_ATTR_W) ? "w" : "-",
|
||||
- (attrs & GRUB_MEM_ATTR_X) ? "x" : "-");
|
||||
- }
|
||||
+ grub_efi_mem_set_att (kernel_addr, kernel_size, kernel_start, nx_supported);
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
asm volatile ("cli");
|
||||
@@ -214,7 +291,7 @@ grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size,
|
||||
/* Invalidate the instruction cache */
|
||||
grub_arch_sync_caches((void *)kernel_addr, kernel_size);
|
||||
|
||||
- hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
|
||||
+ hf = (handover_func)((char *)kernel_start_address + handover_offset + offset);
|
||||
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
|
||||
|
||||
return GRUB_ERR_BUG;
|
||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
|
||||
index 9854b0defa..c44821608e 100644
|
||||
--- a/grub-core/loader/i386/efi/linux.c
|
||||
+++ b/grub-core/loader/i386/efi/linux.c
|
||||
@@ -41,6 +41,7 @@ static grub_command_t cmd_linuxefi, cmd_initrdefi;
|
||||
struct grub_linuxefi_context {
|
||||
void *kernel_mem;
|
||||
grub_uint64_t kernel_size;
|
||||
+ grub_uint64_t kernel_start;
|
||||
grub_uint32_t handover_offset;
|
||||
struct linux_kernel_params *params;
|
||||
char *cmdline;
|
||||
@@ -169,6 +170,7 @@ grub_linuxefi_boot (void *data)
|
||||
|
||||
return grub_efi_linux_boot ((grub_addr_t)context->kernel_mem,
|
||||
context->kernel_size,
|
||||
+ context->kernel_start,
|
||||
context->handover_offset,
|
||||
context->params,
|
||||
context->nx_supported);
|
||||
@@ -527,7 +529,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
LOW_U32(kernel_mem));
|
||||
lh->code32_start = LOW_U32(kernel_mem);
|
||||
|
||||
- grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
|
||||
+ grub_memcpy (kernel_mem, (char *)kernel, filelen);
|
||||
|
||||
lh->type_of_loader = 0x6;
|
||||
grub_dprintf ("linux", "setting lh->type_of_loader = 0x%02x\n",
|
||||
@@ -544,6 +546,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
goto fail;
|
||||
context->kernel_mem = kernel_mem;
|
||||
context->kernel_size = kernel_size;
|
||||
+ context->kernel_start = start;
|
||||
context->handover_offset = handover_offset;
|
||||
context->params = params;
|
||||
context->cmdline = cmdline;
|
||||
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
|
||||
index b82f71006a..0aec66dafb 100644
|
||||
--- a/include/grub/efi/linux.h
|
||||
+++ b/include/grub/efi/linux.h
|
||||
@@ -27,6 +27,7 @@
|
||||
grub_err_t
|
||||
EXPORT_FUNC(grub_efi_linux_boot) (grub_addr_t kernel_address,
|
||||
grub_size_t kernel_size,
|
||||
+ grub_size_t kernel_start,
|
||||
grub_off_t handover_offset,
|
||||
void *kernel_param, int nx_enabled);
|
||||
|
||||
@@ -38,4 +39,10 @@ EXPORT_FUNC(grub_efi_check_nx_image_support) (grub_addr_t kernel_addr,
|
||||
grub_err_t
|
||||
EXPORT_FUNC(grub_efi_check_nx_required) (int *nx_required);
|
||||
|
||||
+grub_err_t
|
||||
+EXPORT_FUNC(grub_efi_mem_set_att) (grub_addr_t kernel_address,
|
||||
+ grub_size_t kernel_size,
|
||||
+ grub_size_t kernel_start,
|
||||
+ int nx_supported);
|
||||
+
|
||||
#endif /* ! GRUB_EFI_LINUX_HEADER */
|
||||
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
|
||||
index a5e623eb04..131a2c0c3d 100644
|
||||
--- a/include/grub/efi/pe32.h
|
||||
+++ b/include/grub/efi/pe32.h
|
||||
@@ -71,6 +71,17 @@ struct grub_dos_header
|
||||
grub_uint32_t lfanew;
|
||||
};
|
||||
|
||||
+struct grub_msdos_image_header
|
||||
+{
|
||||
+ /* This is always 'MZ'. (GRUB_PE32_MAGIC) */
|
||||
+ grub_uint16_t msdos_magic;
|
||||
+
|
||||
+ grub_uint16_t reserved[29];
|
||||
+
|
||||
+ /* The file offset of the PE image header. */
|
||||
+ grub_uint32_t pe_image_header_offset;
|
||||
+};
|
||||
+
|
||||
/* According to the spec, the minimal alignment is 512 bytes...
|
||||
But some examples (such as EFI drivers in the Intel
|
||||
Sample Implementation) use 32 bytes (0x20) instead, and it seems
|
||||
@@ -308,6 +319,23 @@ struct grub_pe32_section_table
|
||||
#define GRUB_PE32_SIGNATURE_SIZE 4
|
||||
#define GRUB_PE32_SIGNATURE "PE\0\0"
|
||||
|
||||
+struct grub_pe_image_header
|
||||
+{
|
||||
+ /* This is always PE\0\0. */
|
||||
+ char signature[GRUB_PE32_SIGNATURE_SIZE];
|
||||
+
|
||||
+ /* The COFF file header. */
|
||||
+ struct grub_pe32_coff_header coff_header;
|
||||
+
|
||||
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
|
||||
+ /* The Optional header. */
|
||||
+ struct grub_pe64_optional_header optional_header;
|
||||
+#else
|
||||
+ /* The Optional header. */
|
||||
+ struct grub_pe32_optional_header optional_header;
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
struct grub_pe32_header
|
||||
{
|
||||
/* This should be filled in with GRUB_PE32_MSDOS_STUB. */
|
||||
@ -175,8 +175,9 @@ case "$COMMAND" in
|
||||
|
||||
if [[ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]] || [[ ! -f /sbin/new-kernel-pkg ]]; then
|
||||
BLS_TARGET="${BLS_DIR}/${MACHINE_ID}-${KERNEL_VERSION}.conf"
|
||||
BLS_FAKE_TARGET="${BLS_DIR}/ffffffffffffffffffffffffffffffff-${KERNEL_VERSION}.conf"
|
||||
BLS_DEBUG="$(echo ${BLS_TARGET} | sed -e "s/${KERNEL_VERSION}/${KERNEL_VERSION}~debug/")"
|
||||
rm -f "${BLS_TARGET}" "${BLS_DEBUG}"
|
||||
rm -f "${BLS_TARGET}" "${BLS_DEBUG}" "${BLS_FAKE_TARGET}"
|
||||
|
||||
for i in vmlinuz System.map config zImage.stub dtb; do
|
||||
rm -rf "/boot/${i}-${KERNEL_VERSION}"
|
||||
|
||||
29
SOURCES/gen_grub_cfgstub
Normal file
29
SOURCES/gen_grub_cfgstub
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ $# -ne 2 ]
|
||||
then
|
||||
echo "Missing argument"
|
||||
echo "Usage: script.sh GRUB_HOME EFI_HOME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GRUB_HOME=$1
|
||||
EFI_HOME=$2
|
||||
|
||||
# create a stub grub2 config in EFI
|
||||
BOOT_UUID=$(grub2-probe --target=fs_uuid "${GRUB_HOME}")
|
||||
GRUB_DIR=$(grub2-mkrelpath "${GRUB_HOME}")
|
||||
|
||||
echo "Generating grub stub config for drive " "${BOOT_UUID}"
|
||||
echo "GRUB_DIR=" "${GRUB_DIR}"
|
||||
echo "EFI_HOME=" "${EFI_HOME}"
|
||||
|
||||
cat << EOF > "${EFI_HOME}"/grub.cfg.stb
|
||||
search --no-floppy --root-dev-only --fs-uuid --set=dev ${BOOT_UUID}
|
||||
set prefix=(\$dev)${GRUB_DIR}
|
||||
export \$prefix
|
||||
configfile \$prefix/grub.cfg
|
||||
EOF
|
||||
|
||||
mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
|
||||
@ -527,6 +527,8 @@ install -m 700 %{3} $RPM_BUILD_ROOT%{efi_esp_dir}/%{3} \
|
||||
%ifarch %{arm} \
|
||||
install -D -m 700 %{2} $RPM_BUILD_ROOT%{efi_esp_boot}/BOOTARM.EFI \
|
||||
%endif \
|
||||
install -D -m 700 %{SOURCE13} \\\
|
||||
${RPM_BUILD_ROOT}/usr/bin/gen_grub_cfgstub \
|
||||
install -D -m 700 unicode.pf2 \\\
|
||||
${RPM_BUILD_ROOT}/boot/%{name}/fonts/unicode.pf2 \
|
||||
${RPM_BUILD_ROOT}/%{_bindir}/%{name}-editenv \\\
|
||||
@ -638,6 +640,7 @@ ln -s ../boot/%{name}/grub.cfg \\\
|
||||
%attr(0700,root,root) %verify(not mtime) %{efi_esp_boot}/BOOTARM.EFI \
|
||||
%endif \
|
||||
%attr(0700,root,root)/boot/%{name}/fonts \
|
||||
%attr(0700,root,root)/usr/bin/gen_grub_cfgstub \
|
||||
%dir %attr(0700,root,root)/boot/loader/entries \
|
||||
%ghost %config(noreplace) %attr(0600,root,root)/boot/%{name}/grub.cfg \
|
||||
%ghost %config(noreplace) %verify(not mtime) %attr(0700,root,root)%{efi_esp_dir}/grub.cfg \
|
||||
|
||||
@ -454,3 +454,26 @@ Patch0454: 0454-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch
|
||||
Patch0455: 0455-tpm-Disable-the-tpm-verifier-if-the-TPM-device-is-no.patch
|
||||
Patch0456: 0456-powerpc-increase-MIN-RMA-size-for-CAS-negotiation.patch
|
||||
Patch0457: 0457-ieee1275-ofnet-Fix-grub_malloc-removed-after-added-s.patch
|
||||
Patch0458: 0458-fs-Remove-trailing-whitespaces.patch
|
||||
Patch0459: 0459-fs-xfs-Fix-memory-leaks-in-XFS-module.patch
|
||||
Patch0460: 0460-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch
|
||||
Patch0461: 0461-fs-xfs-Fix-XFS-directory-extent-parsing.patch
|
||||
Patch0462: 0462-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch
|
||||
Patch0463: 0463-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch
|
||||
Patch0464: 0464-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch
|
||||
Patch0465: 0465-grub-mkimage-Create-new-ELF-note-for-SBAT.patch
|
||||
Patch0466: 0466-grub-mkimage-Add-SBAT-metadata-into-ELF-note-for-Pow.patch
|
||||
Patch0467: 0467-appended-sig-sync-d-with-upstream-code.patch
|
||||
Patch0468: 0468-ieee1275-Platform-Keystore-PKS-Support.patch
|
||||
Patch0469: 0469-ieee1275-Read-the-DB-and-DBX-secure-boot-variables.patch
|
||||
Patch0470: 0470-appendedsig-The-creation-of-trusted-and-distrusted-l.patch
|
||||
Patch0471: 0471-appendedsig-While-verifying-the-kernel-use-trusted-a.patch
|
||||
Patch0472: 0472-powerpc_ieee1275-set-use_static_keys-flag.patch
|
||||
Patch0473: 0473-appendedsig-Reads-the-default-DB-keys-from-ELF-Note.patch
|
||||
Patch0474: 0474-appendedsig-The-grub-command-s-trusted-and-distruste.patch
|
||||
Patch0475: 0475-appendedsig-documentation.patch
|
||||
Patch0476: 0476-efi-Add-efitextmode-command-for-getting-setting-the-.patch
|
||||
Patch0477: 0477-10_linux.in-escape-kernel-option-characters-properly.patch
|
||||
Patch0478: 0478-blscfg-check-if-variable-is-escaped-before-consideri.patch
|
||||
Patch0479: 0479-osdep-linux-getroot-Detect-DDF-container-similar-to-.patch
|
||||
Patch0480: 0480-Set-correctly-the-memory-attributes-for-the-kernel-P.patch
|
||||
@ -1,4 +1,5 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
grub,3,Free Software Foundation,grub,@@VERSION@@,https//www.gnu.org/software/grub/
|
||||
grub,5,Free Software Foundation,grub,@@VERSION@@,https//www.gnu.org/software/grub/
|
||||
grub.rh,2,Red Hat,grub2,@@RHEL_VERSION_RELEASE@@,mailto:secalert@redhat.com
|
||||
grub.almalinux,2,AlmaLinux,grub2,@@VERSION_RELEASE@@,mailto:security@almalinux.org
|
||||
grub.centos,2,Red Hat,grub2,@@VERSION_RELEASE@@,mailto:secalert@redhat.com
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
Name: grub2
|
||||
Epoch: 1
|
||||
Version: 2.06
|
||||
Release: 100%{?dist}.alma.1
|
||||
Release: 113%{?dist}.alma.1
|
||||
Summary: Bootloader with support for Linux, Multiboot and more
|
||||
License: GPLv3+
|
||||
URL: http://www.gnu.org/software/grub/
|
||||
@ -34,6 +34,7 @@ Source9: strtoull_test.c
|
||||
Source10: 20-grub.install
|
||||
Source11: grub.patches
|
||||
Source12: sbat.csv.in
|
||||
Source13: gen_grub_cfgstub
|
||||
|
||||
%include %{SOURCE1}
|
||||
|
||||
@ -352,23 +353,13 @@ if test -f ${EFI_HOME}/grub.cfg; then
|
||||
fi
|
||||
|
||||
# create a stub grub2 config in EFI
|
||||
BOOT_UUID=$(%{name}-probe --target=fs_uuid ${GRUB_HOME})
|
||||
GRUB_DIR=$(%{name}-mkrelpath ${GRUB_HOME})
|
||||
|
||||
cat << EOF > ${EFI_HOME}/grub.cfg.stb
|
||||
search --no-floppy --root-dev-only --fs-uuid --set=dev ${BOOT_UUID}
|
||||
set prefix=(\$dev)${GRUB_DIR}
|
||||
export \$prefix
|
||||
configfile \$prefix/grub.cfg
|
||||
EOF
|
||||
gen_grub_cfgstub $GRUB_HOME $EFI_HOME || :
|
||||
|
||||
if test -f ${EFI_HOME}/grubenv; then
|
||||
cp -a ${EFI_HOME}/grubenv ${EFI_HOME}/grubenv.rpmsave
|
||||
mv --force ${EFI_HOME}/grubenv ${GRUB_HOME}/grubenv
|
||||
fi
|
||||
|
||||
mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
|
||||
|
||||
%files common -f grub.lang
|
||||
%dir %{_libdir}/grub/
|
||||
%dir %{_datarootdir}/grub/
|
||||
@ -538,9 +529,50 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Fri Mar 28 2025 Eduard Abdullin <eabdullin@almalinux.org> - 1:2.06-100.alma.1
|
||||
* Mon Sep 15 2025 Eduard Abdullin <eabdullin@almalinux.org> - 1:2.06-113.alma.1
|
||||
- Debrand for AlmaLinux
|
||||
|
||||
* Thu Aug 7 2025 Nicolas Frayer <nfrayer@redhat.com> 2.06-113
|
||||
- sbat: add new sbat entry for centos
|
||||
- Resolves: #RHEL-108060
|
||||
|
||||
* Tue Jul 29 2025 Leo Sandoval <lsandova@redhat.com> 2.06-112
|
||||
- Set correctly the memory attributes for the kernel PE sections
|
||||
- Resolves: #RHEL-106075
|
||||
|
||||
* Tue Jul 29 2025 Nicolas Frayer <nfrayer@redhat.com> 2.06-111
|
||||
- spec/posttrans: move grub config stub creation out of spec
|
||||
- Resolves: #RHEL-69944
|
||||
|
||||
* Fri Jun 6 2025 Nicolas Frayer <nfrayer@redhat.com> - 2.06-110
|
||||
- osdep/linux/getroot: Detect DDF container similar to IMSM
|
||||
- Resolves: #RHEL-44336
|
||||
|
||||
* Mon Jun 2 2025 Leo Sandoval <lsandova@redhat.com> 2.06-109
|
||||
- Handle special kernel parameter characters properly
|
||||
- Resolves: #RHEL-64297
|
||||
|
||||
* Wed May 21 2025 Nicolas Frayer <nfrayer@redhat.com> - 2.06-108
|
||||
- ieee1275: Appended signature support
|
||||
- Resolves: #RHEL-24742
|
||||
|
||||
* Wed May 14 2025 Nicolas Frayer <nfrayer@redhat.com> - 2.06-107
|
||||
- Remove BLS fake config in case of kernel removal
|
||||
- Resolves: #RHEL-83915
|
||||
|
||||
* Wed May 14 2025 Nicolas Frayer <nfrayer@redhat.com> - 2.06-106
|
||||
- sbat: bump grub sbat for new shim release
|
||||
- Resolves: #RHEL-91278
|
||||
|
||||
* Tue Apr 15 2025 Nicolas Frayer <nfrayer@redhat.com> - 2.06-105
|
||||
- ppc/mkimage: SBAT support on powerpc
|
||||
- Resolves: #RHEL-87421
|
||||
|
||||
* Thu Apr 3 2025 Nicolas Frayer <nfrayer@redhat.com> 2.06-104
|
||||
- fs/xfs: Sync with latest xfs upstream
|
||||
- Resolves: #RHEL-85960
|
||||
- (NVR bump to catch up with zstream)
|
||||
|
||||
* Tue Mar 25 2025 Nicolas Frayer <nfrayer@redhat.com> 2.06-100
|
||||
- ieee1275/ofnet: Fix grub_malloc() removed after added safe
|
||||
- Resolves: #RHEL-83117
|
||||
|
||||
Loading…
Reference in New Issue
Block a user