Add several CVE fixes
- Resolves: CVE-2024-45779 CVE-2024-45778 CVE-2025-1118 - Resolves: CVE-2025-0677 CVE-2024-45782 CVE-2025-0690 - Resolves: CVE-2024-45783 CVE-2025-0624 CVE-2024-45776 - Resolves: CVE-2025-0622 CVE-2024-45774 CVE-2024-45775 - Resolves: CVE-2024-45781 CVE-2024-45780 - Resolves: #RHEL-79700 - Resolves: #RHEL-79341 - Resolves: #RHEL-79875 - Resolves: #RHEL-79849 - Resolves: #RHEL-79707 - Resolves: #RHEL-79857 - Resolves: #RHEL-79709 - Resolves: #RHEL-79846 - Resolves: #RHEL-75737 - Resolves: #RHEL-79713 - Resolves: #RHEL-73785 - Resolves: #RHEL-73787 - Resolves: #RHEL-79704 - Resolves: #RHEL-79702 Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
This commit is contained in:
parent
76fac13a2b
commit
6eaa34fe07
65
0355-misc-Implement-grub_strlcpy.patch
Normal file
65
0355-misc-Implement-grub_strlcpy.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sat, 15 Jun 2024 02:33:08 +0100
|
||||
Subject: [PATCH] misc: Implement grub_strlcpy()
|
||||
|
||||
grub_strlcpy() acts the same way as strlcpy() does on most *NIX,
|
||||
returning the length of src and ensuring dest is always NUL
|
||||
terminated except when size is 0.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
include/grub/misc.h | 39 +++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 39 insertions(+)
|
||||
|
||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
|
||||
index 981526644..0592aa68f 100644
|
||||
--- a/include/grub/misc.h
|
||||
+++ b/include/grub/misc.h
|
||||
@@ -72,6 +72,45 @@ grub_stpcpy (char *dest, const char *src)
|
||||
return d - 1;
|
||||
}
|
||||
|
||||
+static inline grub_size_t
|
||||
+grub_strlcpy (char *dest, const char *src, grub_size_t size)
|
||||
+{
|
||||
+ char *d = dest;
|
||||
+ grub_size_t res = 0;
|
||||
+ /*
|
||||
+ * We do not subtract one from size here to avoid dealing with underflowing
|
||||
+ * the value, which is why to_copy is always checked to be greater than one
|
||||
+ * throughout this function.
|
||||
+ */
|
||||
+ grub_size_t to_copy = size;
|
||||
+
|
||||
+ /* Copy size - 1 bytes to dest. */
|
||||
+ if (to_copy > 1)
|
||||
+ while ((*d++ = *src++) != '\0' && ++res && --to_copy > 1)
|
||||
+ ;
|
||||
+
|
||||
+ /*
|
||||
+ * NUL terminate if size != 0. The previous step may have copied a NUL byte
|
||||
+ * if it reached the end of the string, but we know dest[size - 1] must always
|
||||
+ * be a NUL byte.
|
||||
+ */
|
||||
+ if (size != 0)
|
||||
+ dest[size - 1] = '\0';
|
||||
+
|
||||
+ /* If there is still space in dest, but are here, we reached the end of src. */
|
||||
+ if (to_copy > 1)
|
||||
+ return res;
|
||||
+
|
||||
+ /*
|
||||
+ * If we haven't reached the end of the string, iterate through to determine
|
||||
+ * the strings total length.
|
||||
+ */
|
||||
+ while (*src++ != '\0' && ++res)
|
||||
+ ;
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */
|
||||
static inline void *
|
||||
grub_memcpy (void *dest, const void *src, grub_size_t n)
|
31
0356-fs-ufs-Fix-a-heap-OOB-write.patch
Normal file
31
0356-fs-ufs-Fix-a-heap-OOB-write.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 02:03:33 +0100
|
||||
Subject: [PATCH] fs/ufs: Fix a heap OOB write
|
||||
|
||||
grub_strcpy() was used to copy a symlink name from the filesystem
|
||||
image to a heap allocated buffer. This led to a OOB write to adjacent
|
||||
heap allocations. Fix by using grub_strlcpy().
|
||||
|
||||
Fixes: CVE-2024-45781
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/ufs.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
|
||||
index 34a698b71..47272665e 100644
|
||||
--- a/grub-core/fs/ufs.c
|
||||
+++ b/grub-core/fs/ufs.c
|
||||
@@ -463,7 +463,7 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
||||
/* Check against zero is paylindromic, no need to swap. */
|
||||
if (data->inode.nblocks == 0
|
||||
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
|
||||
- grub_strcpy (symlink, (char *) data->inode.symlink);
|
||||
+ grub_strlcpy (symlink, (char *) data->inode.symlink, sz);
|
||||
else
|
||||
{
|
||||
if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0)
|
31
0357-fs-hfs-Fix-stack-OOB-write-with-grub_strcpy.patch
Normal file
31
0357-fs-hfs-Fix-stack-OOB-write-with-grub_strcpy.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 02:48:33 +0100
|
||||
Subject: [PATCH] fs/hfs: Fix stack OOB write with grub_strcpy()
|
||||
|
||||
Replaced with grub_strlcpy().
|
||||
|
||||
Fixes: CVE-2024-45782
|
||||
Fixes: CVE-2024-56737
|
||||
Fixes: https://savannah.gnu.org/bugs/?66599
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/hfs.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
|
||||
index f419965d1..bb7af5f67 100644
|
||||
--- a/grub-core/fs/hfs.c
|
||||
+++ b/grub-core/fs/hfs.c
|
||||
@@ -379,7 +379,7 @@ grub_hfs_mount (grub_disk_t disk)
|
||||
volume name. */
|
||||
key.parent_dir = grub_cpu_to_be32_compile_time (1);
|
||||
key.strlen = data->sblock.volname[0];
|
||||
- grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));
|
||||
+ grub_strlcpy ((char *) key.str, (char *) (data->sblock.volname + 1), sizeof (key.str));
|
||||
|
||||
if (grub_hfs_find_node (data, (char *) &key, data->cat_root,
|
||||
0, (char *) &dir, sizeof (dir)) == 0)
|
40
0358-fs-tar-Initialize-name-in-grub_cpio_find_file.patch
Normal file
40
0358-fs-tar-Initialize-name-in-grub_cpio_find_file.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 02:47:54 +0100
|
||||
Subject: [PATCH] fs/tar: Initialize name in grub_cpio_find_file()
|
||||
|
||||
It was possible to iterate through grub_cpio_find_file() without
|
||||
allocating name and not setting mode to GRUB_ARCHELP_ATTR_END, which
|
||||
would cause the uninitialized value for name to be used as an argument
|
||||
for canonicalize() in grub_archelp_dir().
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/tar.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
|
||||
index c551ed6b5..646bce5eb 100644
|
||||
--- a/grub-core/fs/tar.c
|
||||
+++ b/grub-core/fs/tar.c
|
||||
@@ -78,6 +78,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
int reread = 0, have_longname = 0, have_longlink = 0;
|
||||
|
||||
data->hofs = data->next_hofs;
|
||||
+ *name = NULL;
|
||||
|
||||
for (reread = 0; reread < 3; reread++)
|
||||
{
|
||||
@@ -202,6 +203,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
+
|
||||
+ if (*name == NULL)
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
|
||||
+
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
89
0359-fs-tar-Integer-overflow-leads-to-heap-OOB-write.patch
Normal file
89
0359-fs-tar-Integer-overflow-leads-to-heap-OOB-write.patch
Normal file
@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Fri, 22 Nov 2024 06:27:58 +0000
|
||||
Subject: [PATCH] fs/tar: Integer overflow leads to heap OOB write
|
||||
|
||||
Both namesize and linksize are derived from hd.size, a 12-digit octal
|
||||
number parsed by read_number(). Later direct arithmetic calculation like
|
||||
"namesize + 1" and "linksize + 1" may exceed the maximum value of
|
||||
grub_size_t leading to heap OOB write. This patch fixes the issue by
|
||||
using grub_add() and checking for an overflow.
|
||||
|
||||
Fixes: CVE-2024-45780
|
||||
|
||||
Reported-by: Nils Langius <nils@langius.de>
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
---
|
||||
grub-core/fs/tar.c | 23 ++++++++++++++++++-----
|
||||
1 file changed, 18 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
|
||||
index 646bce5eb..386c09022 100644
|
||||
--- a/grub-core/fs/tar.c
|
||||
+++ b/grub-core/fs/tar.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -76,6 +77,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
{
|
||||
struct head hd;
|
||||
int reread = 0, have_longname = 0, have_longlink = 0;
|
||||
+ grub_size_t sz;
|
||||
|
||||
data->hofs = data->next_hofs;
|
||||
*name = NULL;
|
||||
@@ -98,7 +100,11 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
|
||||
- *name = grub_malloc (namesize + 1);
|
||||
+
|
||||
+ if (grub_add (namesize, 1, &sz))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("name size overflow"));
|
||||
+
|
||||
+ *name = grub_malloc (sz);
|
||||
if (*name == NULL)
|
||||
return grub_errno;
|
||||
err = grub_disk_read (data->disk, 0,
|
||||
@@ -118,15 +124,19 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
|
||||
- if (data->linkname_alloc < linksize + 1)
|
||||
+
|
||||
+ if (grub_add (linksize, 1, &sz))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("link size overflow"));
|
||||
+
|
||||
+ if (data->linkname_alloc < sz)
|
||||
{
|
||||
char *n;
|
||||
- n = grub_calloc (2, linksize + 1);
|
||||
+ n = grub_calloc (2, sz);
|
||||
if (!n)
|
||||
return grub_errno;
|
||||
grub_free (data->linkname);
|
||||
data->linkname = n;
|
||||
- data->linkname_alloc = 2 * (linksize + 1);
|
||||
+ data->linkname_alloc = 2 * (sz);
|
||||
}
|
||||
|
||||
err = grub_disk_read (data->disk, 0,
|
||||
@@ -149,7 +159,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
while (extra_size < sizeof (hd.prefix)
|
||||
&& hd.prefix[extra_size])
|
||||
extra_size++;
|
||||
- *name = grub_malloc (sizeof (hd.name) + extra_size + 2);
|
||||
+
|
||||
+ if (grub_add (sizeof (hd.name) + 2, extra_size, &sz))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("long name size overflow"));
|
||||
+ *name = grub_malloc (sz);
|
||||
if (*name == NULL)
|
||||
return grub_errno;
|
||||
if (hd.prefix[0])
|
31
0360-fs-f2fs-Set-a-grub_errno-if-mount-fails.patch
Normal file
31
0360-fs-f2fs-Set-a-grub_errno-if-mount-fails.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 06:15:03 +0100
|
||||
Subject: [PATCH] fs/f2fs: Set a grub_errno if mount fails
|
||||
|
||||
It was previously possible for grub_errno to not be set when
|
||||
grub_f2fs_mount() failed if nat_bitmap_ptr() returned NULL.
|
||||
|
||||
This issue is solved by ensuring a grub_errno is set in the fail case.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/f2fs.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
|
||||
index df6beb544..f7daa9435 100644
|
||||
--- a/grub-core/fs/f2fs.c
|
||||
+++ b/grub-core/fs/f2fs.c
|
||||
@@ -872,6 +872,9 @@ grub_f2fs_mount (grub_disk_t disk)
|
||||
return data;
|
||||
|
||||
fail:
|
||||
+ if (grub_errno == GRUB_ERR_NONE)
|
||||
+ grub_error (GRUB_ERR_BAD_FS, "not a F2FS filesystem");
|
||||
+
|
||||
grub_free (data);
|
||||
|
||||
return NULL;
|
35
0361-fs-hfsplus-Set-a-grub_errno-if-mount-fails.patch
Normal file
35
0361-fs-hfsplus-Set-a-grub_errno-if-mount-fails.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 06:22:51 +0100
|
||||
Subject: [PATCH] fs/hfsplus: Set a grub_errno if mount fails
|
||||
|
||||
It was possible for mount to fail but not set grub_errno. This led to
|
||||
a possible double decrement of the module reference count if the NULL
|
||||
page was mapped.
|
||||
|
||||
Fixing in general as a similar bug was fixed in commit 61b13c187
|
||||
(fs/hfsplus: Set grub_errno to prevent NULL pointer access) and there
|
||||
are likely more variants around.
|
||||
|
||||
Fixes: CVE-2024-45783
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/hfsplus.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
|
||||
index 19c7b3367..e7fd98a07 100644
|
||||
--- a/grub-core/fs/hfsplus.c
|
||||
+++ b/grub-core/fs/hfsplus.c
|
||||
@@ -393,7 +393,7 @@ grub_hfsplus_mount (grub_disk_t disk)
|
||||
|
||||
fail:
|
||||
|
||||
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
||||
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE)
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
|
||||
|
||||
grub_free (data);
|
33
0362-fs-iso9660-Set-a-grub_errno-if-mount-fails.patch
Normal file
33
0362-fs-iso9660-Set-a-grub_errno-if-mount-fails.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 06:37:08 +0100
|
||||
Subject: [PATCH] fs/iso9660: Set a grub_errno if mount fails
|
||||
|
||||
It was possible for a grub_errno to not be set if mount of an ISO 9660
|
||||
filesystem failed when set_rockridge() returned 0.
|
||||
|
||||
This isn't known to be exploitable as the other filesystems due to
|
||||
filesystem helper checking the requested file type. Though fixing
|
||||
as a precaution.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/iso9660.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
|
||||
index ac011950a..82cf1a271 100644
|
||||
--- a/grub-core/fs/iso9660.c
|
||||
+++ b/grub-core/fs/iso9660.c
|
||||
@@ -491,6 +491,9 @@ grub_iso9660_mount (grub_disk_t disk)
|
||||
return data;
|
||||
|
||||
fail:
|
||||
+ if (grub_errno == GRUB_ERR_NONE)
|
||||
+ grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
|
||||
+
|
||||
grub_free (data);
|
||||
return 0;
|
||||
}
|
50
0363-fs-iso9660-Fix-invalid-free.patch
Normal file
50
0363-fs-iso9660-Fix-invalid-free.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Fri, 31 May 2024 15:14:42 +0800
|
||||
Subject: [PATCH] fs/iso9660: Fix invalid free
|
||||
|
||||
The ctx->filename can point to either a string literal or a dynamically
|
||||
allocated string. The ctx->filename_alloc field is used to indicate the
|
||||
type of allocation.
|
||||
|
||||
An issue has been identified where ctx->filename is reassigned to
|
||||
a string literal in susp_iterate_dir() but ctx->filename_alloc is not
|
||||
correctly handled. This oversight causes a memory leak and an invalid
|
||||
free operation later.
|
||||
|
||||
The fix involves checking ctx->filename_alloc, freeing the allocated
|
||||
string if necessary and clearing ctx->filename_alloc for string literals.
|
||||
|
||||
Reported-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/iso9660.c | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
|
||||
index 82cf1a271..7a59a65a5 100644
|
||||
--- a/grub-core/fs/iso9660.c
|
||||
+++ b/grub-core/fs/iso9660.c
|
||||
@@ -568,9 +568,19 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
||||
filename type is stored. */
|
||||
/* FIXME: Fix this slightly improper cast. */
|
||||
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
|
||||
- ctx->filename = (char *) ".";
|
||||
+ {
|
||||
+ if (ctx->filename_alloc)
|
||||
+ grub_free (ctx->filename);
|
||||
+ ctx->filename_alloc = 0;
|
||||
+ ctx->filename = (char *) ".";
|
||||
+ }
|
||||
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
|
||||
- ctx->filename = (char *) "..";
|
||||
+ {
|
||||
+ if (ctx->filename_alloc)
|
||||
+ grub_free (ctx->filename);
|
||||
+ ctx->filename_alloc = 0;
|
||||
+ ctx->filename = (char *) "..";
|
||||
+ }
|
||||
else if (entry->len >= 5)
|
||||
{
|
||||
grub_size_t off = 0, csize = 1;
|
63
0364-fs-jfs-Fix-OOB-read-in-jfs_getent.patch
Normal file
63
0364-fs-jfs-Fix-OOB-read-in-jfs_getent.patch
Normal file
@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Fri, 22 Nov 2024 06:27:59 +0000
|
||||
Subject: [PATCH] fs/jfs: Fix OOB read in jfs_getent()
|
||||
|
||||
The JFS fuzzing revealed an OOB read in grub_jfs_getent(). The crash
|
||||
was caused by an invalid leaf nodes count, diro->dirpage->header.count,
|
||||
which was larger than the maximum number of leaf nodes allowed in an
|
||||
inode. This fix is to ensure that the leaf nodes count is validated in
|
||||
grub_jfs_opendir() before calling grub_jfs_getent().
|
||||
|
||||
On the occasion replace existing raw numbers with newly defined constant.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
---
|
||||
grub-core/fs/jfs.c | 17 +++++++++++++++--
|
||||
1 file changed, 15 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
||||
index 6f7c43904..32dec7fb7 100644
|
||||
--- a/grub-core/fs/jfs.c
|
||||
+++ b/grub-core/fs/jfs.c
|
||||
@@ -41,6 +41,12 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define GRUB_JFS_TREE_LEAF 2
|
||||
|
||||
+/*
|
||||
+ * Define max entries stored in-line in an inode.
|
||||
+ * https://jfs.sourceforge.net/project/pub/jfslayout.pdf
|
||||
+ */
|
||||
+#define GRUB_JFS_INODE_INLINE_ENTRIES 8
|
||||
+
|
||||
struct grub_jfs_sblock
|
||||
{
|
||||
/* The magic for JFS. It should contain the string "JFS1". */
|
||||
@@ -203,9 +209,9 @@ struct grub_jfs_inode
|
||||
grub_uint8_t freecnt;
|
||||
grub_uint8_t freelist;
|
||||
grub_uint32_t idotdot;
|
||||
- grub_uint8_t sorted[8];
|
||||
+ grub_uint8_t sorted[GRUB_JFS_INODE_INLINE_ENTRIES];
|
||||
} header;
|
||||
- struct grub_jfs_leaf_dirent dirents[8];
|
||||
+ struct grub_jfs_leaf_dirent dirents[GRUB_JFS_INODE_INLINE_ENTRIES];
|
||||
} GRUB_PACKED dir;
|
||||
/* Fast symlink. */
|
||||
struct
|
||||
@@ -453,6 +459,13 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||||
/* Check if the entire tree is contained within the inode. */
|
||||
if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
|
||||
{
|
||||
+ if (inode->dir.header.count > GRUB_JFS_INODE_INLINE_ENTRIES)
|
||||
+ {
|
||||
+ grub_free (diro);
|
||||
+ grub_error (GRUB_ERR_BAD_FS, N_("invalid JFS inode"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
diro->leaf = inode->dir.dirents;
|
||||
diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de;
|
||||
diro->sorted = inode->dir.header.sorted;
|
@ -0,0 +1,64 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Fri, 22 Nov 2024 06:28:00 +0000
|
||||
Subject: [PATCH] fs/jfs: Fix OOB read caused by invalid dir slot index
|
||||
|
||||
While fuzz testing JFS with ASAN enabled an OOB read was detected in
|
||||
grub_jfs_opendir(). The issue occurred due to an invalid directory slot
|
||||
index in the first entry of the sorted directory slot array in the inode
|
||||
directory header. The fix ensures the slot index is validated before
|
||||
accessing it. Given that an internal or a leaf node in a directory B+
|
||||
tree is a 4 KiB in size and each directory slot is always 32 bytes, the
|
||||
max number of slots in a node is 128. The validation ensures that the
|
||||
slot index doesn't exceed this limit.
|
||||
|
||||
[1] https://jfs.sourceforge.net/project/pub/jfslayout.pdf
|
||||
|
||||
JFS will allocate 4K of disk space for an internal node of the B+ tree.
|
||||
An internal node looks the same as a leaf node.
|
||||
- page 10
|
||||
|
||||
Fixed number of Directory Slots depending on the size of the node. These are
|
||||
the slots to be used for storing the directory slot array and the directory
|
||||
entries or router entries. A directory slot is always 32 bytes.
|
||||
...
|
||||
A Directory Slot Array which is a sorted array of indices to the directory
|
||||
slots that are currently in use.
|
||||
...
|
||||
An internal or a leaf node in the directory B+ tree is a 4K page.
|
||||
- page 25
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
---
|
||||
grub-core/fs/jfs.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
||||
index 32dec7fb7..88fb884df 100644
|
||||
--- a/grub-core/fs/jfs.c
|
||||
+++ b/grub-core/fs/jfs.c
|
||||
@@ -46,6 +46,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
* https://jfs.sourceforge.net/project/pub/jfslayout.pdf
|
||||
*/
|
||||
#define GRUB_JFS_INODE_INLINE_ENTRIES 8
|
||||
+#define GRUB_JFS_DIR_MAX_SLOTS 128
|
||||
|
||||
struct grub_jfs_sblock
|
||||
{
|
||||
@@ -481,6 +482,14 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ if (inode->dir.header.sorted[0] >= GRUB_JFS_DIR_MAX_SLOTS)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FS, N_("invalid directory slot index"));
|
||||
+ grub_free (diro->dirpage);
|
||||
+ grub_free (diro);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
|
||||
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
|
||||
|
128
0366-fs-jfs-Use-full-40-bits-offset-and-address-for-a-dat.patch
Normal file
128
0366-fs-jfs-Use-full-40-bits-offset-and-address-for-a-dat.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Mon, 16 Dec 2024 20:22:39 +0000
|
||||
Subject: [PATCH] fs/jfs: Use full 40 bits offset and address for a data extent
|
||||
|
||||
An extent's logical offset and address are represented as a 40-bit value
|
||||
split into two parts: the most significant 8 bits and the least
|
||||
significant 32 bits. Currently the JFS code uses only the least
|
||||
significant 32 bits value for offsets and addresses assuming the data
|
||||
size will never exceed the 32-bit range. This approach ignores the most
|
||||
significant 8 bits potentially leading to incorrect offsets and
|
||||
addresses for larger values. The patch fixes it by incorporating the
|
||||
most significant 8 bits into the calculation to get the full 40-bits
|
||||
value for offsets and addresses.
|
||||
|
||||
https://jfs.sourceforge.net/project/pub/jfslayout.pdf
|
||||
|
||||
"off1,off2 is a 40-bit field, containing the logical offset of the first
|
||||
block in the extent.
|
||||
...
|
||||
addr1,addr2 is a 40-bit field, containing the address of the extent."
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/jfs.c | 41 +++++++++++++++++++++++++++++------------
|
||||
1 file changed, 29 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
||||
index 88fb884df..2bde48d45 100644
|
||||
--- a/grub-core/fs/jfs.c
|
||||
+++ b/grub-core/fs/jfs.c
|
||||
@@ -265,6 +265,20 @@ static grub_dl_t my_mod;
|
||||
|
||||
static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino);
|
||||
|
||||
+/*
|
||||
+ * An extent's offset, physical and logical, is represented as a 40-bit value.
|
||||
+ * This 40-bit value is split into two parts:
|
||||
+ * - offset1: the most signficant 8 bits of the offset,
|
||||
+ * - offset2: the least significant 32 bits of the offset.
|
||||
+ *
|
||||
+ * This function calculates and returns the 64-bit offset of an extent.
|
||||
+ */
|
||||
+static grub_uint64_t
|
||||
+get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2)
|
||||
+{
|
||||
+ return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2));
|
||||
+}
|
||||
+
|
||||
static grub_int64_t
|
||||
getblk (struct grub_jfs_treehead *treehead,
|
||||
struct grub_jfs_tree_extent *extents,
|
||||
@@ -274,22 +288,25 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||
{
|
||||
int found = -1;
|
||||
int i;
|
||||
+ grub_uint64_t ext_offset, ext_blk;
|
||||
|
||||
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
|
||||
i < max_extents; i++)
|
||||
{
|
||||
+ ext_offset = get_ext_offset (extents[i].offset1, extents[i].offset2);
|
||||
+ ext_blk = get_ext_offset (extents[i].extent.blk1, extents[i].extent.blk2);
|
||||
+
|
||||
if (treehead->flags & GRUB_JFS_TREE_LEAF)
|
||||
{
|
||||
/* Read the leafnode. */
|
||||
- if (grub_le_to_cpu32 (extents[i].offset2) <= blk
|
||||
+ if (ext_offset <= blk
|
||||
&& ((grub_le_to_cpu16 (extents[i].extent.length))
|
||||
+ (extents[i].extent.length2 << 16)
|
||||
- + grub_le_to_cpu32 (extents[i].offset2)) > blk)
|
||||
- return (blk - grub_le_to_cpu32 (extents[i].offset2)
|
||||
- + grub_le_to_cpu32 (extents[i].extent.blk2));
|
||||
+ + ext_offset) > blk)
|
||||
+ return (blk - ext_offset + ext_blk);
|
||||
}
|
||||
else
|
||||
- if (blk >= grub_le_to_cpu32 (extents[i].offset2))
|
||||
+ if (blk >= ext_offset)
|
||||
found = i;
|
||||
}
|
||||
|
||||
@@ -307,10 +324,9 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||
return -1;
|
||||
|
||||
if (!grub_disk_read (data->disk,
|
||||
- ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
|
||||
- << (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||||
- - GRUB_DISK_SECTOR_BITS), 0,
|
||||
- sizeof (*tree), (char *) tree))
|
||||
+ (grub_disk_addr_t) ext_blk
|
||||
+ << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS),
|
||||
+ 0, sizeof (*tree), (char *) tree))
|
||||
{
|
||||
if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) ||
|
||||
grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent)))
|
||||
@@ -361,7 +377,7 @@ grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino,
|
||||
sizeof (iag_inodes), &iag_inodes))
|
||||
return grub_errno;
|
||||
|
||||
- inoblk = grub_le_to_cpu32 (iag_inodes[inoext].blk2);
|
||||
+ inoblk = get_ext_offset (iag_inodes[inoext].blk1, iag_inodes[inoext].blk2);
|
||||
inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||||
- GRUB_DISK_SECTOR_BITS);
|
||||
inoblk += inonum;
|
||||
@@ -490,7 +506,8 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
|
||||
+ blk = get_ext_offset (de[inode->dir.header.sorted[0]].ex.blk1,
|
||||
+ de[inode->dir.header.sorted[0]].ex.blk2);
|
||||
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
/* Read in the nodes until we are on the leaf node level. */
|
||||
@@ -508,7 +525,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||||
|
||||
de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
|
||||
index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
|
||||
- blk = (grub_le_to_cpu32 (de[index].ex.blk2)
|
||||
+ blk = (get_ext_offset (de[index].ex.blk1, de[index].ex.blk2)
|
||||
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||||
- GRUB_DISK_SECTOR_BITS));
|
||||
} while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
|
@ -0,0 +1,85 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Mon, 16 Dec 2024 20:22:40 +0000
|
||||
Subject: [PATCH] fs/jfs: Inconsistent signed/unsigned types usage in return
|
||||
values
|
||||
|
||||
The getblk() returns a value of type grub_int64_t which is assigned to
|
||||
iagblk and inoblk, both of type grub_uint64_t, in grub_jfs_read_inode()
|
||||
via grub_jfs_blkno(). This patch fixes the type mismatch in the
|
||||
functions. Additionally, the getblk() will return 0 instead of -1 on
|
||||
failure cases. This change is safe because grub_errno is always set in
|
||||
getblk() to indicate errors and it is later checked in the callers.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/jfs.c | 15 +++++++++------
|
||||
1 file changed, 9 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
||||
index 2bde48d45..70a2f4947 100644
|
||||
--- a/grub-core/fs/jfs.c
|
||||
+++ b/grub-core/fs/jfs.c
|
||||
@@ -279,7 +279,7 @@ get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2)
|
||||
return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2));
|
||||
}
|
||||
|
||||
-static grub_int64_t
|
||||
+static grub_uint64_t
|
||||
getblk (struct grub_jfs_treehead *treehead,
|
||||
struct grub_jfs_tree_extent *extents,
|
||||
int max_extents,
|
||||
@@ -290,6 +290,8 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||
int i;
|
||||
grub_uint64_t ext_offset, ext_blk;
|
||||
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+
|
||||
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
|
||||
i < max_extents; i++)
|
||||
{
|
||||
@@ -312,7 +314,7 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||
|
||||
if (found != -1)
|
||||
{
|
||||
- grub_int64_t ret = -1;
|
||||
+ grub_uint64_t ret = 0;
|
||||
struct
|
||||
{
|
||||
struct grub_jfs_treehead treehead;
|
||||
@@ -321,7 +323,7 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||
|
||||
tree = grub_zalloc (sizeof (*tree));
|
||||
if (!tree)
|
||||
- return -1;
|
||||
+ return 0;
|
||||
|
||||
if (!grub_disk_read (data->disk,
|
||||
(grub_disk_addr_t) ext_blk
|
||||
@@ -334,19 +336,20 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "jfs: infinite recursion detected");
|
||||
- ret = -1;
|
||||
+ ret = 0;
|
||||
}
|
||||
}
|
||||
grub_free (tree);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- return -1;
|
||||
+ grub_error (GRUB_ERR_READ_ERROR, "jfs: block %" PRIuGRUB_UINT64_T " not found", blk);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/* Get the block number for the block BLK in the node INODE in the
|
||||
mounted filesystem DATA. */
|
||||
-static grub_int64_t
|
||||
+static grub_uint64_t
|
||||
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
|
||||
grub_uint64_t blk)
|
||||
{
|
46
0368-fs-ext2-Fix-out-of-bounds-read-for-inline-extents.patch
Normal file
46
0368-fs-ext2-Fix-out-of-bounds-read-for-inline-extents.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Fri, 31 May 2024 15:14:23 +0800
|
||||
Subject: [PATCH] fs/ext2: Fix out-of-bounds read for inline extents
|
||||
|
||||
When inline extents are used, i.e. the extent tree depth equals zero,
|
||||
a maximum of four entries can fit into the inode's data block. If the
|
||||
extent header states a number of entries greater than four the current
|
||||
ext2 implementation causes an out-of-bounds read. Fix this issue by
|
||||
capping the number of extents to four when reading inline extents.
|
||||
|
||||
Reported-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/ext2.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
|
||||
index 731d346f8..eac639e36 100644
|
||||
--- a/grub-core/fs/ext2.c
|
||||
+++ b/grub-core/fs/ext2.c
|
||||
@@ -481,6 +481,8 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
struct grub_ext4_extent *ext;
|
||||
int i;
|
||||
grub_disk_addr_t ret;
|
||||
+ grub_uint16_t nent;
|
||||
+ const grub_uint16_t max_inline_ext = sizeof (inode->blocks) / sizeof (*ext) - 1; /* Minus 1 extent header. */
|
||||
|
||||
leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock);
|
||||
if (! leaf)
|
||||
@@ -490,7 +492,13 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
}
|
||||
|
||||
ext = (struct grub_ext4_extent *) (leaf + 1);
|
||||
- for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
|
||||
+
|
||||
+ nent = grub_le_to_cpu16 (leaf->entries);
|
||||
+
|
||||
+ if (leaf->depth == 0)
|
||||
+ nent = grub_min (nent, max_inline_ext);
|
||||
+
|
||||
+ for (i = 0; i < nent; i++)
|
||||
{
|
||||
if (fileblock < grub_le_to_cpu32 (ext[i].block))
|
||||
break;
|
47
0369-fs-ntfs-Fix-out-of-bounds-read.patch
Normal file
47
0369-fs-ntfs-Fix-out-of-bounds-read.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Mon, 3 Jun 2024 12:12:06 +0800
|
||||
Subject: [PATCH] fs/ntfs: Fix out-of-bounds read
|
||||
|
||||
When parsing NTFS file records the presence of the 0xFF marker indicates
|
||||
the end of the attribute list. This value signifies that there are no
|
||||
more attributes to process.
|
||||
|
||||
However, when the end marker is missing due to corrupted metadata the
|
||||
loop continues to read beyond the attribute list resulting in out-of-bounds
|
||||
reads and potentially entering an infinite loop.
|
||||
|
||||
This patch adds a check to provide a stop condition for the loop ensuring
|
||||
it stops at the end of the attribute list or at the end of the Master File
|
||||
Table. This guards against out-of-bounds reads and prevents infinite loops.
|
||||
|
||||
Reported-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/ntfs.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index deb058ac9..976ad1dc4 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -139,6 +139,8 @@ free_attr (struct grub_ntfs_attr *at)
|
||||
static grub_uint8_t *
|
||||
find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
{
|
||||
+ grub_uint8_t *mft_end;
|
||||
+
|
||||
if (at->flags & GRUB_NTFS_AF_ALST)
|
||||
{
|
||||
retry:
|
||||
@@ -191,7 +193,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
return NULL;
|
||||
}
|
||||
at->attr_cur = at->attr_nxt;
|
||||
- while (*at->attr_cur != 0xFF)
|
||||
+ mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||
+ while (at->attr_cur < mft_end && *at->attr_cur != 0xFF)
|
||||
{
|
||||
at->attr_nxt += u16at (at->attr_cur, 4);
|
||||
if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
|
141
0370-fs-ntfs-Track-the-end-of-the-MFT-attribute-buffer.patch
Normal file
141
0370-fs-ntfs-Track-the-end-of-the-MFT-attribute-buffer.patch
Normal file
@ -0,0 +1,141 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 7 Jan 2025 11:38:34 +0000
|
||||
Subject: [PATCH] fs/ntfs: Track the end of the MFT attribute buffer
|
||||
|
||||
The end of the attribute buffer should be stored alongside the rest of
|
||||
the attribute struct as right now it is not possible to implement bounds
|
||||
checking when accessing attributes sequentially.
|
||||
|
||||
This is done via:
|
||||
- updating init_attr() to set at->end and check is is not initially out of bounds,
|
||||
- implementing checks as init_attr() had its type change in its callers,
|
||||
- updating the value of at->end when needed.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/ntfs.c | 34 ++++++++++++++++++++++++++++------
|
||||
include/grub/ntfs.h | 1 +
|
||||
2 files changed, 29 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index 976ad1dc4..562b4f7eb 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -119,13 +119,20 @@ static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
|
||||
grub_disk_read_hook_t read_hook,
|
||||
void *read_hook_data);
|
||||
|
||||
-static void
|
||||
+static grub_err_t
|
||||
init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
|
||||
{
|
||||
at->mft = mft;
|
||||
at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
|
||||
at->attr_nxt = mft->buf + first_attr_off (mft->buf);
|
||||
+ at->end = mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||
+
|
||||
+ if (at->attr_nxt > at->end)
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "attributes start outside the MFT");
|
||||
+
|
||||
at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -239,6 +246,10 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||
}
|
||||
at->flags |= GRUB_NTFS_AF_ALST;
|
||||
+
|
||||
+ /* From this point on pa_end is the end of the buffer */
|
||||
+ at->end = pa_end;
|
||||
+
|
||||
while (at->attr_nxt < at->attr_end)
|
||||
{
|
||||
if ((*at->attr_nxt == attr) || (attr == 0))
|
||||
@@ -298,7 +309,9 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
|
||||
{
|
||||
grub_uint8_t *pa;
|
||||
|
||||
- init_attr (at, mft);
|
||||
+ if (init_attr (at, mft) != GRUB_ERR_NONE)
|
||||
+ return NULL;
|
||||
+
|
||||
pa = find_attr (at, attr);
|
||||
if (pa == NULL)
|
||||
return NULL;
|
||||
@@ -314,7 +327,8 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
free_attr (at);
|
||||
- init_attr (at, mft);
|
||||
+ if (init_attr (at, mft) != GRUB_ERR_NONE)
|
||||
+ return NULL;
|
||||
pa = find_attr (at, attr);
|
||||
}
|
||||
return pa;
|
||||
@@ -585,7 +599,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
|
||||
mft->attr.attr_end = 0; /* Don't jump to attribute list */
|
||||
}
|
||||
else
|
||||
- init_attr (&mft->attr, mft);
|
||||
+ return init_attr (&mft->attr, mft);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -807,7 +821,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
bmp = NULL;
|
||||
|
||||
at = &attr;
|
||||
- init_attr (at, mft);
|
||||
+ if (init_attr (at, mft) != GRUB_ERR_NONE)
|
||||
+ return 0;
|
||||
+
|
||||
while (1)
|
||||
{
|
||||
cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT);
|
||||
@@ -838,7 +854,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
bitmap = NULL;
|
||||
bitmap_len = 0;
|
||||
free_attr (at);
|
||||
+ /* No need to check errors here, as it will already be fine */
|
||||
init_attr (at, mft);
|
||||
+
|
||||
while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL)
|
||||
{
|
||||
int ofs;
|
||||
@@ -1203,6 +1221,7 @@ grub_ntfs_label (grub_device_t device, char **label)
|
||||
struct grub_ntfs_data *data = 0;
|
||||
struct grub_fshelp_node *mft = 0;
|
||||
grub_uint8_t *pa;
|
||||
+ grub_err_t err;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
@@ -1228,7 +1247,10 @@ grub_ntfs_label (grub_device_t device, char **label)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- init_attr (&mft->attr, mft);
|
||||
+ err = init_attr (&mft->attr, mft);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
+
|
||||
pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
|
||||
|
||||
if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
|
||||
diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h
|
||||
index d1a6af696..ec1c4db38 100644
|
||||
--- a/include/grub/ntfs.h
|
||||
+++ b/include/grub/ntfs.h
|
||||
@@ -134,6 +134,7 @@ struct grub_ntfs_attr
|
||||
grub_uint8_t *attr_cur, *attr_nxt, *attr_end;
|
||||
grub_uint32_t save_pos;
|
||||
grub_uint8_t *sbuf;
|
||||
+ grub_uint8_t *end;
|
||||
struct grub_ntfs_file *mft;
|
||||
};
|
||||
|
183
0371-fs-ntfs-Use-a-helper-function-to-access-attributes.patch
Normal file
183
0371-fs-ntfs-Use-a-helper-function-to-access-attributes.patch
Normal file
@ -0,0 +1,183 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 14 May 2024 12:39:56 +0100
|
||||
Subject: [PATCH] fs/ntfs: Use a helper function to access attributes
|
||||
|
||||
Right now to access the next attribute the code reads the length of the
|
||||
current attribute and adds that to the current pointer. This is error
|
||||
prone as bounds checking needs to be performed all over the place. So,
|
||||
implement a helper and ensure its used across find_attr() and read_attr().
|
||||
|
||||
This commit does *not* implement full bounds checking. It is just the
|
||||
preparation work for this to be added into the helper.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/ntfs.c | 69 +++++++++++++++++++++++++++++++++++++++++++----------
|
||||
include/grub/ntfs.h | 2 ++
|
||||
2 files changed, 58 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index 562b4f7eb..9311ba9ef 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -70,6 +70,25 @@ res_attr_data_len (void *res_attr_ptr)
|
||||
return u32at (res_attr_ptr, 0x10);
|
||||
}
|
||||
|
||||
+/* Return the next attribute if it exists, otherwise return NULL. */
|
||||
+static grub_uint8_t *
|
||||
+next_attribute (grub_uint8_t *curr_attribute, void *end)
|
||||
+{
|
||||
+ grub_uint8_t *next = curr_attribute;
|
||||
+
|
||||
+ /*
|
||||
+ * Need to verify we aren't exceeding the end of the buffer by reading the
|
||||
+ * header for the current attribute
|
||||
+ */
|
||||
+ if (curr_attribute + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end)
|
||||
+ return NULL;
|
||||
+
|
||||
+ next += u16at (curr_attribute, 4);
|
||||
+
|
||||
+ return next;
|
||||
+}
|
||||
+
|
||||
+
|
||||
grub_ntfscomp_func_t grub_ntfscomp_func;
|
||||
|
||||
static grub_err_t
|
||||
@@ -151,13 +170,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
if (at->flags & GRUB_NTFS_AF_ALST)
|
||||
{
|
||||
retry:
|
||||
- while (at->attr_nxt < at->attr_end)
|
||||
+ while (at->attr_nxt)
|
||||
{
|
||||
at->attr_cur = at->attr_nxt;
|
||||
- at->attr_nxt += u16at (at->attr_cur, 4);
|
||||
+ at->attr_nxt = next_attribute (at->attr_cur, at->attr_end);
|
||||
if ((*at->attr_cur == attr) || (attr == 0))
|
||||
{
|
||||
- grub_uint8_t *new_pos;
|
||||
+ grub_uint8_t *new_pos, *end;
|
||||
|
||||
if (at->flags & GRUB_NTFS_AF_MMFT)
|
||||
{
|
||||
@@ -181,15 +200,36 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Only time emft_bufs is defined is in this function, with this
|
||||
+ * size.
|
||||
+ */
|
||||
+ grub_size_t emft_buf_size =
|
||||
+ at->mft->data->mft_size << GRUB_NTFS_BLK_SHR;
|
||||
+
|
||||
+ /*
|
||||
+ * Needs to be enough space for the successful case to even
|
||||
+ * bother.
|
||||
+ */
|
||||
+ if (first_attr_off (at->emft_buf) >= (emft_buf_size - 0x18 - 2))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FS,
|
||||
+ "can\'t find 0x%X in attribute list",
|
||||
+ (unsigned char) *at->attr_cur);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
|
||||
- while (*new_pos != 0xFF)
|
||||
+ end = &at->emft_buf[emft_buf_size];
|
||||
+
|
||||
+ while (new_pos && *new_pos != 0xFF)
|
||||
{
|
||||
if ((*new_pos == *at->attr_cur)
|
||||
&& (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
|
||||
{
|
||||
return new_pos;
|
||||
}
|
||||
- new_pos += u16at (new_pos, 4);
|
||||
+ new_pos = next_attribute (new_pos, end);
|
||||
}
|
||||
grub_error (GRUB_ERR_BAD_FS,
|
||||
"can\'t find 0x%X in attribute list",
|
||||
@@ -203,7 +243,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||
while (at->attr_cur < mft_end && *at->attr_cur != 0xFF)
|
||||
{
|
||||
- at->attr_nxt += u16at (at->attr_cur, 4);
|
||||
+ at->attr_nxt = next_attribute (at->attr_cur, at->end);
|
||||
if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
|
||||
at->attr_end = at->attr_cur;
|
||||
if ((*at->attr_cur == attr) || (attr == 0))
|
||||
@@ -250,13 +290,14 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
/* From this point on pa_end is the end of the buffer */
|
||||
at->end = pa_end;
|
||||
|
||||
- while (at->attr_nxt < at->attr_end)
|
||||
+ while (at->attr_nxt)
|
||||
{
|
||||
if ((*at->attr_nxt == attr) || (attr == 0))
|
||||
break;
|
||||
- at->attr_nxt += u16at (at->attr_nxt, 4);
|
||||
+ at->attr_nxt = next_attribute (at->attr_nxt, pa_end);
|
||||
}
|
||||
- if (at->attr_nxt >= at->attr_end)
|
||||
+
|
||||
+ if (at->attr_nxt >= at->attr_end || at->attr_nxt == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA))
|
||||
@@ -277,7 +318,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
grub_cpu_to_le32 (at->mft->data->mft_start
|
||||
+ 1));
|
||||
pa = at->attr_nxt + u16at (pa, 4);
|
||||
- while (pa < at->attr_end)
|
||||
+
|
||||
+ while (pa)
|
||||
{
|
||||
if (*pa != attr)
|
||||
break;
|
||||
@@ -293,7 +335,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
|
||||
at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
|
||||
return NULL;
|
||||
- pa += u16at (pa, 4);
|
||||
+ pa = next_attribute (pa, pa_end);
|
||||
}
|
||||
at->attr_nxt = at->attr_cur;
|
||||
at->flags &= ~GRUB_NTFS_AF_GPOS;
|
||||
@@ -530,14 +572,15 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||
else
|
||||
vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR);
|
||||
pa = at->attr_nxt + u16at (at->attr_nxt, 4);
|
||||
- while (pa < at->attr_end)
|
||||
+
|
||||
+ while (pa)
|
||||
{
|
||||
if (*pa != attr)
|
||||
break;
|
||||
if (u32at (pa, 8) > vcn)
|
||||
break;
|
||||
at->attr_nxt = pa;
|
||||
- pa += u16at (pa, 4);
|
||||
+ pa = next_attribute (pa, at->attr_end);
|
||||
}
|
||||
}
|
||||
pp = find_attr (at, attr);
|
||||
diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h
|
||||
index ec1c4db38..2c8078403 100644
|
||||
--- a/include/grub/ntfs.h
|
||||
+++ b/include/grub/ntfs.h
|
||||
@@ -89,6 +89,8 @@ enum
|
||||
#define GRUB_NTFS_COM_SEC (GRUB_NTFS_COM_LEN >> GRUB_NTFS_BLK_SHR)
|
||||
#define GRUB_NTFS_LOG_COM_SEC (GRUB_NTFS_COM_LOG_LEN - GRUB_NTFS_BLK_SHR)
|
||||
|
||||
+#define GRUB_NTFS_ATTRIBUTE_HEADER_SIZE 16
|
||||
+
|
||||
enum
|
||||
{
|
||||
GRUB_NTFS_AF_ALST = 1,
|
245
0372-fs-ntfs-Implement-attribute-verification.patch
Normal file
245
0372-fs-ntfs-Implement-attribute-verification.patch
Normal file
@ -0,0 +1,245 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 14 May 2024 12:39:56 +0100
|
||||
Subject: [PATCH] fs/ntfs: Implement attribute verification
|
||||
|
||||
It was possible to read OOB when an attribute had a size that exceeded
|
||||
the allocated buffer. This resolves that by making sure all attributes
|
||||
that get read are fully in the allocated space by implementing
|
||||
a function to validate them.
|
||||
|
||||
Defining the offsets in include/grub/ntfs.h but they are only used in
|
||||
the validation function and not across the rest of the NTFS code.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/ntfs.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/grub/ntfs.h | 22 ++++++++
|
||||
2 files changed, 175 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index 9311ba9ef..8fdb8f2ff 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -70,6 +70,149 @@ res_attr_data_len (void *res_attr_ptr)
|
||||
return u32at (res_attr_ptr, 0x10);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Check if the attribute is valid and doesn't exceed the allocated region.
|
||||
+ * This accounts for resident and non-resident data.
|
||||
+ *
|
||||
+ * This is based off the documentation from the linux-ntfs project:
|
||||
+ * https://flatcap.github.io/linux-ntfs/ntfs/concepts/attribute_header.html
|
||||
+ */
|
||||
+static bool
|
||||
+validate_attribute (grub_uint8_t *attr, void *end)
|
||||
+{
|
||||
+ grub_size_t attr_size = 0;
|
||||
+ grub_size_t min_size = 0;
|
||||
+ grub_size_t spare = (grub_uint8_t *) end - attr;
|
||||
+ /*
|
||||
+ * Just used as a temporary variable to try and deal with cases where someone
|
||||
+ * tries to overlap fields.
|
||||
+ */
|
||||
+ grub_size_t curr = 0;
|
||||
+
|
||||
+ /* Need verify we can entirely read the attributes header. */
|
||||
+ if (attr + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end)
|
||||
+ goto fail;
|
||||
+
|
||||
+ /*
|
||||
+ * So, the rest of this code uses a 16bit int for the attribute length but
|
||||
+ * from reading the all the documentation I could find it says this field is
|
||||
+ * actually 32bit. But let's be consistent with the rest of the code.
|
||||
+ *
|
||||
+ * https://elixir.bootlin.com/linux/v6.10.7/source/fs/ntfs3/ntfs.h#L370
|
||||
+ */
|
||||
+ attr_size = u16at (attr, GRUB_NTFS_ATTRIBUTE_LENGTH);
|
||||
+
|
||||
+ if (attr_size > spare)
|
||||
+ goto fail;
|
||||
+
|
||||
+ /* Not an error case, just reached the end of the attributes. */
|
||||
+ if (attr_size == 0)
|
||||
+ return false;
|
||||
+
|
||||
+ /*
|
||||
+ * Extra validation by trying to calculate a minimum possible size for this
|
||||
+ * attribute. +8 from the size of the resident data struct which is the
|
||||
+ * minimum that can be added.
|
||||
+ */
|
||||
+ min_size = GRUB_NTFS_ATTRIBUTE_HEADER_SIZE + 8;
|
||||
+
|
||||
+ if (min_size > attr_size)
|
||||
+ goto fail;
|
||||
+
|
||||
+ /* Is the data is resident (0) or not (1). */
|
||||
+ if (attr[GRUB_NTFS_ATTRIBUTE_RESIDENT] == 0)
|
||||
+ {
|
||||
+ /* Read the offset and size of the attribute. */
|
||||
+ curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_RES_OFFSET);
|
||||
+ curr += u32at (attr, GRUB_NTFS_ATTRIBUTE_RES_LENGTH);
|
||||
+ if (curr > min_size)
|
||||
+ min_size = curr;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /*
|
||||
+ * If the data is non-resident, the minimum size is 64 which is where
|
||||
+ * the data runs start. We already have a minimum size of 24. So, just
|
||||
+ * adding 40 to get to the real value.
|
||||
+ */
|
||||
+ min_size += 40;
|
||||
+ if (min_size > attr_size)
|
||||
+ goto fail;
|
||||
+ /* If the compression unit size is > 0, +8 bytes*/
|
||||
+ if (u16at (attr, GRUB_NTFS_ATTRIBUTE_COMPRESSION_UNIT_SIZE) > 0)
|
||||
+ min_size += 8;
|
||||
+
|
||||
+ /*
|
||||
+ * Need to consider the data runs now. Each member of the run has byte
|
||||
+ * that describes the size of the data length and offset. Each being
|
||||
+ * 4 bits in the byte.
|
||||
+ */
|
||||
+ curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_DATA_RUNS);
|
||||
+
|
||||
+ if (curr + 1 > min_size)
|
||||
+ min_size = curr + 1;
|
||||
+
|
||||
+ if (min_size > attr_size)
|
||||
+ goto fail;
|
||||
+
|
||||
+ /*
|
||||
+ * Each attribute can store multiple data runs which are stored
|
||||
+ * continuously in the attribute. They exist as one header byte
|
||||
+ * with up to 14 bytes following it depending on the lengths.
|
||||
+ * We stop when we hit a header that is just a NUL byte.
|
||||
+ *
|
||||
+ * https://flatcap.github.io/linux-ntfs/ntfs/concepts/data_runs.html
|
||||
+ */
|
||||
+ while (attr[curr] != 0)
|
||||
+ {
|
||||
+ /*
|
||||
+ * We stop when we hit a header that is just a NUL byte. The data
|
||||
+ * run header is stored as a single byte where the top 4 bits refer
|
||||
+ * to the number of bytes used to store the total length of the
|
||||
+ * data run, and the number of bytes used to store the offset.
|
||||
+ * These directly follow the header byte, so we use them to update
|
||||
+ * the minimum size.
|
||||
+ */
|
||||
+ min_size += (attr[curr] & 0x7) + ((attr[curr] >> 4) & 0x7);
|
||||
+ curr += min_size;
|
||||
+ min_size++;
|
||||
+ if (min_size > attr_size)
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Name offset, doing this after data residence checks. */
|
||||
+ if (u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET) != 0)
|
||||
+ {
|
||||
+ curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET);
|
||||
+ /*
|
||||
+ * Multiple the name length by 2 as its UTF-16. Can be zero if this in an
|
||||
+ * unamed attribute.
|
||||
+ */
|
||||
+ curr += attr[GRUB_NTFS_ATTRIBUTE_NAME_LENGTH] * 2;
|
||||
+ if (curr > min_size)
|
||||
+ min_size = curr;
|
||||
+ }
|
||||
+
|
||||
+ /* Padded to 8 bytes. */
|
||||
+ if (min_size % 8 != 0)
|
||||
+ min_size += 8 - (min_size % 8);
|
||||
+
|
||||
+ /*
|
||||
+ * At this point min_size should be exactly attr_size but being flexible
|
||||
+ * here to avoid any issues.
|
||||
+ */
|
||||
+ if (min_size > attr_size)
|
||||
+ goto fail;
|
||||
+
|
||||
+ return true;
|
||||
+
|
||||
+ fail:
|
||||
+ grub_dprintf ("ntfs", "spare=%" PRIuGRUB_SIZE " min_size=%" PRIuGRUB_SIZE " attr_size=%" PRIuGRUB_SIZE "\n",
|
||||
+ spare, min_size, attr_size);
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
/* Return the next attribute if it exists, otherwise return NULL. */
|
||||
static grub_uint8_t *
|
||||
next_attribute (grub_uint8_t *curr_attribute, void *end)
|
||||
@@ -84,6 +227,8 @@ next_attribute (grub_uint8_t *curr_attribute, void *end)
|
||||
return NULL;
|
||||
|
||||
next += u16at (curr_attribute, 4);
|
||||
+ if (validate_attribute (next, end) == false)
|
||||
+ return NULL;
|
||||
|
||||
return next;
|
||||
}
|
||||
@@ -290,6 +435,9 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
/* From this point on pa_end is the end of the buffer */
|
||||
at->end = pa_end;
|
||||
|
||||
+ if (validate_attribute (at->attr_nxt, pa_end) == false)
|
||||
+ return NULL;
|
||||
+
|
||||
while (at->attr_nxt)
|
||||
{
|
||||
if ((*at->attr_nxt == attr) || (attr == 0))
|
||||
@@ -319,6 +467,9 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
+ 1));
|
||||
pa = at->attr_nxt + u16at (pa, 4);
|
||||
|
||||
+ if (validate_attribute (pa, pa_end) == true)
|
||||
+ pa = NULL;
|
||||
+
|
||||
while (pa)
|
||||
{
|
||||
if (*pa != attr)
|
||||
@@ -572,6 +723,8 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||
else
|
||||
vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR);
|
||||
pa = at->attr_nxt + u16at (at->attr_nxt, 4);
|
||||
+ if (validate_attribute (pa, at->attr_end) == false)
|
||||
+ pa = NULL;
|
||||
|
||||
while (pa)
|
||||
{
|
||||
diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h
|
||||
index 2c8078403..77b182acf 100644
|
||||
--- a/include/grub/ntfs.h
|
||||
+++ b/include/grub/ntfs.h
|
||||
@@ -91,6 +91,28 @@ enum
|
||||
|
||||
#define GRUB_NTFS_ATTRIBUTE_HEADER_SIZE 16
|
||||
|
||||
+/*
|
||||
+ * To make attribute validation clearer the offsets for each value in the
|
||||
+ * attribute headers are defined as macros.
|
||||
+ *
|
||||
+ * These offsets are all from:
|
||||
+ * https://flatcap.github.io/linux-ntfs/ntfs/concepts/attribute_header.html
|
||||
+ */
|
||||
+
|
||||
+/* These offsets are part of the attribute header. */
|
||||
+#define GRUB_NTFS_ATTRIBUTE_LENGTH 4
|
||||
+#define GRUB_NTFS_ATTRIBUTE_RESIDENT 8
|
||||
+#define GRUB_NTFS_ATTRIBUTE_NAME_LENGTH 9
|
||||
+#define GRUB_NTFS_ATTRIBUTE_NAME_OFFSET 10
|
||||
+
|
||||
+/* Offsets for values needed for resident data. */
|
||||
+#define GRUB_NTFS_ATTRIBUTE_RES_LENGTH 16
|
||||
+#define GRUB_NTFS_ATTRIBUTE_RES_OFFSET 20
|
||||
+
|
||||
+/* Offsets for values needed for non-resident data. */
|
||||
+#define GRUB_NTFS_ATTRIBUTE_DATA_RUNS 32
|
||||
+#define GRUB_NTFS_ATTRIBUTE_COMPRESSION_UNIT_SIZE 34
|
||||
+
|
||||
enum
|
||||
{
|
||||
GRUB_NTFS_AF_ALST = 1,
|
43
0373-fs-xfs-Fix-out-of-bounds-read.patch
Normal file
43
0373-fs-xfs-Fix-out-of-bounds-read.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Fri, 31 May 2024 15:14:57 +0800
|
||||
Subject: [PATCH] fs/xfs: Fix out-of-bounds read
|
||||
|
||||
The number of records in the root key array read from disk was not being
|
||||
validated against the size of the root node. This could lead to an
|
||||
out-of-bounds read.
|
||||
|
||||
This patch adds a check to ensure that the number of records in the root
|
||||
key array does not exceed the expected size of a root node read from
|
||||
disk. If this check detects an out-of-bounds condition the operation is
|
||||
aborted to prevent random errors due to metadata corruption.
|
||||
|
||||
Reported-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/xfs.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index e3816d1ec..43be00e99 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -568,6 +568,17 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
do
|
||||
{
|
||||
int i;
|
||||
+ grub_addr_t keys_end, data_end;
|
||||
+
|
||||
+ if (grub_mul (sizeof (grub_uint64_t), nrec, &keys_end) ||
|
||||
+ grub_add ((grub_addr_t) keys, keys_end, &keys_end) ||
|
||||
+ grub_add ((grub_addr_t) node->data, node->data->data_size, &data_end) ||
|
||||
+ keys_end > data_end)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FS, "invalid number of XFS root keys");
|
||||
+ grub_free (leaf);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < nrec; i++)
|
||||
{
|
@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 06:03:58 +0100
|
||||
Subject: [PATCH] fs/xfs: Ensuring failing to mount sets a grub_errno
|
||||
|
||||
It was previously possible for grub_xfs_mount() to return NULL without
|
||||
setting grub_errno if the XFS version was invalid. This resulted in it
|
||||
being possible for grub_dl_unref() to be called twice allowing the XFS
|
||||
module to be unloaded while there were still references to it.
|
||||
|
||||
Fixing this problem in general by ensuring a grub_errno is set if the
|
||||
fail label is reached.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/xfs.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index 43be00e99..9d3420ece 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -315,6 +315,8 @@ static int grub_xfs_sb_valid(struct grub_xfs_data *data)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
+
|
||||
+ grub_error (GRUB_ERR_BAD_FS, "unsupported XFS filesystem version");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -984,7 +986,7 @@ grub_xfs_mount (grub_disk_t disk)
|
||||
return data;
|
||||
fail:
|
||||
|
||||
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
||||
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE)
|
||||
grub_error (GRUB_ERR_BAD_FS, "not an XFS filesystem");
|
||||
|
||||
grub_free (data);
|
32
0375-kern-file-Ensure-file-data-is-set.patch
Normal file
32
0375-kern-file-Ensure-file-data-is-set.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 03:01:40 +0100
|
||||
Subject: [PATCH] kern/file: Ensure file->data is set
|
||||
|
||||
This is to avoid a generic issue were some filesystems would not set
|
||||
data and also not set a grub_errno. This meant it was possible for many
|
||||
filesystems to grub_dl_unref() themselves multiple times resulting in
|
||||
it being possible to unload the filesystems while there were still
|
||||
references to them, e.g., via a loopback.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/file.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
|
||||
index 868ce3b63..1dc4339dc 100644
|
||||
--- a/grub-core/kern/file.c
|
||||
+++ b/grub-core/kern/file.c
|
||||
@@ -124,6 +124,9 @@ grub_file_open (const char *name, enum grub_file_type type)
|
||||
if ((file->fs->fs_open) (file, file_name) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
|
||||
+ if (file->data == NULL)
|
||||
+ goto fail;
|
||||
+
|
||||
file->name = grub_strdup (name);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
440
0376-kern-file-Implement-filesystem-reference-counting.patch
Normal file
440
0376-kern-file-Implement-filesystem-reference-counting.patch
Normal file
@ -0,0 +1,440 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 13:44:25 -0600
|
||||
Subject: [PATCH] kern/file: Implement filesystem reference counting
|
||||
|
||||
The grub_file_open() and grub_file_close() should be the only places
|
||||
that allow a reference to a filesystem to stay open. So, add grub_dl_t
|
||||
to grub_fs_t and set this in the GRUB_MOD_INIT() for each filesystem to
|
||||
avoid issues when filesystems forget to do it themselves or do not track
|
||||
their own references, e.g. squash4.
|
||||
|
||||
The fs_label(), fs_uuid(), fs_mtime() and fs_read() should all ref and
|
||||
unref in the same function but it is essentially redundant in GRUB
|
||||
single threaded model.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/affs.c | 1 +
|
||||
grub-core/fs/bfs.c | 1 +
|
||||
grub-core/fs/btrfs.c | 1 +
|
||||
grub-core/fs/cbfs.c | 1 +
|
||||
grub-core/fs/cpio.c | 1 +
|
||||
grub-core/fs/cpio_be.c | 1 +
|
||||
grub-core/fs/ext2.c | 1 +
|
||||
grub-core/fs/f2fs.c | 1 +
|
||||
grub-core/fs/fat.c | 1 +
|
||||
grub-core/fs/hfs.c | 1 +
|
||||
grub-core/fs/hfsplus.c | 1 +
|
||||
grub-core/fs/iso9660.c | 1 +
|
||||
grub-core/fs/jfs.c | 1 +
|
||||
grub-core/fs/minix.c | 1 +
|
||||
grub-core/fs/newc.c | 1 +
|
||||
grub-core/fs/nilfs2.c | 1 +
|
||||
grub-core/fs/ntfs.c | 1 +
|
||||
grub-core/fs/odc.c | 1 +
|
||||
grub-core/fs/proc.c | 1 +
|
||||
grub-core/fs/reiserfs.c | 1 +
|
||||
grub-core/fs/romfs.c | 1 +
|
||||
grub-core/fs/sfs.c | 1 +
|
||||
grub-core/fs/squash4.c | 1 +
|
||||
grub-core/fs/tar.c | 1 +
|
||||
grub-core/fs/udf.c | 1 +
|
||||
grub-core/fs/ufs.c | 1 +
|
||||
grub-core/fs/xfs.c | 1 +
|
||||
grub-core/fs/zfs/zfs.c | 1 +
|
||||
grub-core/kern/file.c | 7 +++++++
|
||||
include/grub/fs.h | 4 ++++
|
||||
30 files changed, 39 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
|
||||
index cafcd0fba..b1c64e77d 100644
|
||||
--- a/grub-core/fs/affs.c
|
||||
+++ b/grub-core/fs/affs.c
|
||||
@@ -699,6 +699,7 @@ static struct grub_fs grub_affs_fs =
|
||||
|
||||
GRUB_MOD_INIT(affs)
|
||||
{
|
||||
+ grub_affs_fs.mod = mod;
|
||||
grub_fs_register (&grub_affs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c
|
||||
index 47dbe2011..17705812d 100644
|
||||
--- a/grub-core/fs/bfs.c
|
||||
+++ b/grub-core/fs/bfs.c
|
||||
@@ -1104,6 +1104,7 @@ GRUB_MOD_INIT (bfs)
|
||||
{
|
||||
COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE ==
|
||||
sizeof (struct grub_bfs_extent));
|
||||
+ grub_bfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_bfs_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 47325f6ad..3ed37a4db 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -3365,6 +3365,7 @@ subvol_get_env (struct grub_env_var *var __attribute__ ((unused)),
|
||||
|
||||
GRUB_MOD_INIT (btrfs)
|
||||
{
|
||||
+ grub_btrfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_btrfs_fs);
|
||||
cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info,
|
||||
"DEVICE",
|
||||
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
|
||||
index 581215ef1..3e527cbf2 100644
|
||||
--- a/grub-core/fs/cbfs.c
|
||||
+++ b/grub-core/fs/cbfs.c
|
||||
@@ -390,6 +390,7 @@ GRUB_MOD_INIT (cbfs)
|
||||
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
|
||||
init_cbfsdisk ();
|
||||
#endif
|
||||
+ grub_cbfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_cbfs_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c
|
||||
index dab5f9898..1799f7ff5 100644
|
||||
--- a/grub-core/fs/cpio.c
|
||||
+++ b/grub-core/fs/cpio.c
|
||||
@@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
|
||||
|
||||
GRUB_MOD_INIT (cpio)
|
||||
{
|
||||
+ grub_cpio_fs.mod = mod;
|
||||
grub_fs_register (&grub_cpio_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/cpio_be.c b/grub-core/fs/cpio_be.c
|
||||
index 846548892..7bed1b848 100644
|
||||
--- a/grub-core/fs/cpio_be.c
|
||||
+++ b/grub-core/fs/cpio_be.c
|
||||
@@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
|
||||
|
||||
GRUB_MOD_INIT (cpio_be)
|
||||
{
|
||||
+ grub_cpio_fs.mod = mod;
|
||||
grub_fs_register (&grub_cpio_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
|
||||
index eac639e36..0ee22e675 100644
|
||||
--- a/grub-core/fs/ext2.c
|
||||
+++ b/grub-core/fs/ext2.c
|
||||
@@ -1113,6 +1113,7 @@ static struct grub_fs grub_ext2_fs =
|
||||
|
||||
GRUB_MOD_INIT(ext2)
|
||||
{
|
||||
+ grub_ext2_fs.mod = mod;
|
||||
grub_fs_register (&grub_ext2_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
|
||||
index f7daa9435..e5dcbc470 100644
|
||||
--- a/grub-core/fs/f2fs.c
|
||||
+++ b/grub-core/fs/f2fs.c
|
||||
@@ -1353,6 +1353,7 @@ static struct grub_fs grub_f2fs_fs = {
|
||||
|
||||
GRUB_MOD_INIT (f2fs)
|
||||
{
|
||||
+ grub_f2fs_fs.mod = mod;
|
||||
grub_fs_register (&grub_f2fs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
|
||||
index ff6200c5b..1cf355af4 100644
|
||||
--- a/grub-core/fs/fat.c
|
||||
+++ b/grub-core/fs/fat.c
|
||||
@@ -1312,6 +1312,7 @@ GRUB_MOD_INIT(fat)
|
||||
#endif
|
||||
{
|
||||
COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
|
||||
+ grub_fat_fs.mod = mod;
|
||||
grub_fs_register (&grub_fat_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
|
||||
index bb7af5f67..3a9894443 100644
|
||||
--- a/grub-core/fs/hfs.c
|
||||
+++ b/grub-core/fs/hfs.c
|
||||
@@ -1434,6 +1434,7 @@ static struct grub_fs grub_hfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(hfs)
|
||||
{
|
||||
+ grub_hfs_fs.mod = mod;
|
||||
if (!grub_is_lockdown ())
|
||||
grub_fs_register (&grub_hfs_fs);
|
||||
my_mod = mod;
|
||||
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
|
||||
index e7fd98a07..d5f90007b 100644
|
||||
--- a/grub-core/fs/hfsplus.c
|
||||
+++ b/grub-core/fs/hfsplus.c
|
||||
@@ -1150,6 +1150,7 @@ static struct grub_fs grub_hfsplus_fs =
|
||||
|
||||
GRUB_MOD_INIT(hfsplus)
|
||||
{
|
||||
+ grub_hfsplus_fs.mod = mod;
|
||||
grub_fs_register (&grub_hfsplus_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
|
||||
index 7a59a65a5..0c0aae597 100644
|
||||
--- a/grub-core/fs/iso9660.c
|
||||
+++ b/grub-core/fs/iso9660.c
|
||||
@@ -1165,6 +1165,7 @@ static struct grub_fs grub_iso9660_fs =
|
||||
|
||||
GRUB_MOD_INIT(iso9660)
|
||||
{
|
||||
+ grub_iso9660_fs.mod = mod;
|
||||
grub_fs_register (&grub_iso9660_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
||||
index 70a2f4947..b0283ac00 100644
|
||||
--- a/grub-core/fs/jfs.c
|
||||
+++ b/grub-core/fs/jfs.c
|
||||
@@ -1005,6 +1005,7 @@ static struct grub_fs grub_jfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(jfs)
|
||||
{
|
||||
+ grub_jfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_jfs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
|
||||
index 3cd18c85b..beb1a6378 100644
|
||||
--- a/grub-core/fs/minix.c
|
||||
+++ b/grub-core/fs/minix.c
|
||||
@@ -732,6 +732,7 @@ GRUB_MOD_INIT(minix)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
+ grub_minix_fs.mod = mod;
|
||||
grub_fs_register (&grub_minix_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c
|
||||
index 4fb8b2e3d..43b7f8b64 100644
|
||||
--- a/grub-core/fs/newc.c
|
||||
+++ b/grub-core/fs/newc.c
|
||||
@@ -64,6 +64,7 @@ read_number (const char *str, grub_size_t size)
|
||||
|
||||
GRUB_MOD_INIT (newc)
|
||||
{
|
||||
+ grub_cpio_fs.mod = mod;
|
||||
grub_fs_register (&grub_cpio_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
|
||||
index 3c248a910..c44583ee8 100644
|
||||
--- a/grub-core/fs/nilfs2.c
|
||||
+++ b/grub-core/fs/nilfs2.c
|
||||
@@ -1231,6 +1231,7 @@ GRUB_MOD_INIT (nilfs2)
|
||||
grub_nilfs2_dat_entry));
|
||||
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
|
||||
== sizeof (struct grub_nilfs2_inode));
|
||||
+ grub_nilfs2_fs.mod = mod;
|
||||
grub_fs_register (&grub_nilfs2_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index 8fdb8f2ff..03e3e5c6a 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -1537,6 +1537,7 @@ static struct grub_fs grub_ntfs_fs =
|
||||
|
||||
GRUB_MOD_INIT (ntfs)
|
||||
{
|
||||
+ grub_ntfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_ntfs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c
|
||||
index 790000622..8e4e8aeac 100644
|
||||
--- a/grub-core/fs/odc.c
|
||||
+++ b/grub-core/fs/odc.c
|
||||
@@ -52,6 +52,7 @@ read_number (const char *str, grub_size_t size)
|
||||
|
||||
GRUB_MOD_INIT (odc)
|
||||
{
|
||||
+ grub_cpio_fs.mod = mod;
|
||||
grub_fs_register (&grub_cpio_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/proc.c b/grub-core/fs/proc.c
|
||||
index 5f516502d..bcde43349 100644
|
||||
--- a/grub-core/fs/proc.c
|
||||
+++ b/grub-core/fs/proc.c
|
||||
@@ -192,6 +192,7 @@ static struct grub_fs grub_procfs_fs =
|
||||
|
||||
GRUB_MOD_INIT (procfs)
|
||||
{
|
||||
+ grub_procfs_fs.mod = mod;
|
||||
grub_disk_dev_register (&grub_procfs_dev);
|
||||
grub_fs_register (&grub_procfs_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
|
||||
index b8253da7f..d9a8bf602 100644
|
||||
--- a/grub-core/fs/reiserfs.c
|
||||
+++ b/grub-core/fs/reiserfs.c
|
||||
@@ -1407,6 +1407,7 @@ static struct grub_fs grub_reiserfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(reiserfs)
|
||||
{
|
||||
+ grub_reiserfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_reiserfs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
|
||||
index d97b8fbb8..a43546d95 100644
|
||||
--- a/grub-core/fs/romfs.c
|
||||
+++ b/grub-core/fs/romfs.c
|
||||
@@ -475,6 +475,7 @@ static struct grub_fs grub_romfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(romfs)
|
||||
{
|
||||
+ grub_romfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_romfs_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
|
||||
index 983e88008..f0d7cac43 100644
|
||||
--- a/grub-core/fs/sfs.c
|
||||
+++ b/grub-core/fs/sfs.c
|
||||
@@ -779,6 +779,7 @@ static struct grub_fs grub_sfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(sfs)
|
||||
{
|
||||
+ grub_sfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_sfs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
|
||||
index 6dd731e23..ccfa3eea5 100644
|
||||
--- a/grub-core/fs/squash4.c
|
||||
+++ b/grub-core/fs/squash4.c
|
||||
@@ -1032,6 +1032,7 @@ static struct grub_fs grub_squash_fs =
|
||||
|
||||
GRUB_MOD_INIT(squash4)
|
||||
{
|
||||
+ grub_squash_fs.mod = mod;
|
||||
grub_fs_register (&grub_squash_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
|
||||
index 386c09022..fd2ec1f74 100644
|
||||
--- a/grub-core/fs/tar.c
|
||||
+++ b/grub-core/fs/tar.c
|
||||
@@ -354,6 +354,7 @@ static struct grub_fs grub_cpio_fs = {
|
||||
|
||||
GRUB_MOD_INIT (tar)
|
||||
{
|
||||
+ grub_cpio_fs.mod = mod;
|
||||
grub_fs_register (&grub_cpio_fs);
|
||||
}
|
||||
|
||||
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
|
||||
index 2ac5c1d00..3d4b40263 100644
|
||||
--- a/grub-core/fs/udf.c
|
||||
+++ b/grub-core/fs/udf.c
|
||||
@@ -1382,6 +1382,7 @@ static struct grub_fs grub_udf_fs = {
|
||||
|
||||
GRUB_MOD_INIT (udf)
|
||||
{
|
||||
+ grub_udf_fs.mod = mod;
|
||||
grub_fs_register (&grub_udf_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
|
||||
index 47272665e..7f72494cd 100644
|
||||
--- a/grub-core/fs/ufs.c
|
||||
+++ b/grub-core/fs/ufs.c
|
||||
@@ -899,6 +899,7 @@ GRUB_MOD_INIT(ufs1)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
+ grub_ufs_fs.mod = mod;
|
||||
grub_fs_register (&grub_ufs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index 9d3420ece..7b0ea577e 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -1220,6 +1220,7 @@ static struct grub_fs grub_xfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(xfs)
|
||||
{
|
||||
+ grub_xfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_xfs_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
|
||||
index cf4d2ab18..cbbd86730 100644
|
||||
--- a/grub-core/fs/zfs/zfs.c
|
||||
+++ b/grub-core/fs/zfs/zfs.c
|
||||
@@ -4394,6 +4394,7 @@ static struct grub_fs grub_zfs_fs = {
|
||||
GRUB_MOD_INIT (zfs)
|
||||
{
|
||||
COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE);
|
||||
+ grub_zfs_fs.mod = mod;
|
||||
grub_fs_register (&grub_zfs_fs);
|
||||
#ifndef GRUB_UTIL
|
||||
my_mod = mod;
|
||||
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
|
||||
index 1dc4339dc..58fae17ba 100644
|
||||
--- a/grub-core/kern/file.c
|
||||
+++ b/grub-core/kern/file.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/fs.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/dl.h>
|
||||
|
||||
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
|
||||
|
||||
@@ -127,6 +128,9 @@ grub_file_open (const char *name, enum grub_file_type type)
|
||||
if (file->data == NULL)
|
||||
goto fail;
|
||||
|
||||
+ if (file->fs->mod)
|
||||
+ grub_dl_ref (file->fs->mod);
|
||||
+
|
||||
file->name = grub_strdup (name);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
@@ -215,6 +219,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
|
||||
grub_err_t
|
||||
grub_file_close (grub_file_t file)
|
||||
{
|
||||
+ if (file->fs->mod)
|
||||
+ grub_dl_unref (file->fs->mod);
|
||||
+
|
||||
grub_dprintf ("file", "Closing `%s' ...\n", file->name);
|
||||
if (file->fs->fs_close)
|
||||
(file->fs->fs_close) (file);
|
||||
diff --git a/include/grub/fs.h b/include/grub/fs.h
|
||||
index 026bc3bb8..df4c93b16 100644
|
||||
--- a/include/grub/fs.h
|
||||
+++ b/include/grub/fs.h
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <grub/device.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/types.h>
|
||||
+#include <grub/dl.h>
|
||||
|
||||
#include <grub/list.h>
|
||||
/* For embedding types. */
|
||||
@@ -57,6 +58,9 @@ struct grub_fs
|
||||
/* My name. */
|
||||
const char *name;
|
||||
|
||||
+ /* My module */
|
||||
+ grub_dl_t mod;
|
||||
+
|
||||
/* Call HOOK with each file under DIR. */
|
||||
grub_err_t (*fs_dir) (grub_device_t device, const char *path,
|
||||
grub_fs_dir_hook_t hook, void *hook_data);
|
367
0377-cli_lock-Add-build-option-to-block-command-line-inte.patch
Normal file
367
0377-cli_lock-Add-build-option-to-block-command-line-inte.patch
Normal file
@ -0,0 +1,367 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Wed, 24 Jan 2024 06:26:37 +0000
|
||||
Subject: [PATCH] cli_lock: Add build option to block command line interface
|
||||
|
||||
Add functionality to disable command line interface access and editing of GRUB
|
||||
menu entries if GRUB image is built with --disable-cli.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
docs/grub.texi | 6 ++++--
|
||||
grub-core/kern/main.c | 28 ++++++++++++++++++++++++++++
|
||||
grub-core/kern/rescue_reader.c | 13 +++++++++++++
|
||||
grub-core/normal/auth.c | 3 +++
|
||||
grub-core/normal/menu_text.c | 31 +++++++++++++++++--------------
|
||||
include/grub/kernel.h | 1 +
|
||||
include/grub/misc.h | 2 ++
|
||||
include/grub/util/install.h | 8 ++++++--
|
||||
util/grub-install-common.c | 11 ++++++++---
|
||||
util/grub-mkimage.c | 9 ++++++++-
|
||||
util/mkimage.c | 15 ++++++++++++++-
|
||||
11 files changed, 104 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index 825278a7f..b39cdf275 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -5948,8 +5948,10 @@ the GRUB command line, edit menu entries, and execute any menu entry. If
|
||||
@samp{superusers} is set, then use of the command line and editing of menu
|
||||
entries are automatically restricted to superusers. Setting @samp{superusers}
|
||||
to empty string effectively disables both access to CLI and editing of menu
|
||||
-entries. Note: The environment variable needs to be exported to also affect
|
||||
-the section defined by the @samp{submenu} command (@pxref{submenu}).
|
||||
+entries. Building a grub image with @samp{--disable-cli} option will also
|
||||
+disable access to CLI and editing of menu entries, as well as disabling rescue
|
||||
+mode. Note: The environment variable needs to be exported to also affect the
|
||||
+section defined by the @samp{submenu} command (@pxref{submenu}).
|
||||
|
||||
Other users may be allowed to execute specific menu entries by giving a list of
|
||||
usernames (as above) using the @option{--users} option to the
|
||||
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
|
||||
index e94a2f78f..e4d4bf625 100644
|
||||
--- a/grub-core/kern/main.c
|
||||
+++ b/grub-core/kern/main.c
|
||||
@@ -30,11 +30,14 @@
|
||||
#include <grub/reader.h>
|
||||
#include <grub/parser.h>
|
||||
#include <grub/verify.h>
|
||||
+#include <grub/types.h>
|
||||
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
#include <grub/machine/memory.h>
|
||||
#endif
|
||||
|
||||
+static bool cli_disabled = false;
|
||||
+
|
||||
grub_addr_t
|
||||
grub_modules_get_end (void)
|
||||
{
|
||||
@@ -299,6 +302,28 @@ grub_load_normal_mode (void)
|
||||
grub_command_execute ("normal", 0, 0);
|
||||
}
|
||||
|
||||
+bool
|
||||
+grub_is_cli_disabled (void)
|
||||
+{
|
||||
+ return cli_disabled;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check_is_cli_disabled (void)
|
||||
+{
|
||||
+ struct grub_module_header *header;
|
||||
+ header = 0;
|
||||
+
|
||||
+ FOR_MODULES (header)
|
||||
+ {
|
||||
+ if (header->type == OBJ_TYPE_DISABLE_CLI)
|
||||
+ {
|
||||
+ cli_disabled = true;
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void
|
||||
reclaim_module_space (void)
|
||||
{
|
||||
@@ -356,6 +381,9 @@ grub_main (void)
|
||||
|
||||
grub_boot_time ("After loading embedded modules.");
|
||||
|
||||
+ /* Check if the CLI should be disabled */
|
||||
+ check_is_cli_disabled ();
|
||||
+
|
||||
/* It is better to set the root device as soon as possible,
|
||||
for convenience. */
|
||||
grub_set_prefix_and_root ();
|
||||
diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c
|
||||
index dcd7d4439..4259857ba 100644
|
||||
--- a/grub-core/kern/rescue_reader.c
|
||||
+++ b/grub-core/kern/rescue_reader.c
|
||||
@@ -78,6 +78,19 @@ grub_rescue_read_line (char **line, int cont,
|
||||
void __attribute__ ((noreturn))
|
||||
grub_rescue_run (void)
|
||||
{
|
||||
+ /* Stall if the CLI has been disabled */
|
||||
+ if (grub_is_cli_disabled ())
|
||||
+ {
|
||||
+ grub_printf ("Rescue mode has been disabled...\n");
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ /* Do not optimize out the loop. */
|
||||
+ asm volatile ("");
|
||||
+ }
|
||||
+ while (1);
|
||||
+ }
|
||||
+
|
||||
grub_printf ("Entering rescue mode...\n");
|
||||
|
||||
while (1)
|
||||
diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
|
||||
index 6be678c0d..53f2d723f 100644
|
||||
--- a/grub-core/normal/auth.c
|
||||
+++ b/grub-core/normal/auth.c
|
||||
@@ -209,6 +209,9 @@ grub_auth_check_authentication (const char *userlist)
|
||||
char entered[GRUB_AUTH_MAX_PASSLEN];
|
||||
struct grub_auth_user *user;
|
||||
|
||||
+ if (grub_is_cli_disabled ())
|
||||
+ return GRUB_ACCESS_DENIED;
|
||||
+
|
||||
grub_memset (login, 0, sizeof (login));
|
||||
|
||||
if (is_authenticated (userlist))
|
||||
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
|
||||
index 18240e76c..fd0d83999 100644
|
||||
--- a/grub-core/normal/menu_text.c
|
||||
+++ b/grub-core/normal/menu_text.c
|
||||
@@ -178,21 +178,24 @@ command-line or ESC to discard edits and return to the GRUB menu."),
|
||||
|
||||
grub_free (msg_translated);
|
||||
|
||||
- if (nested)
|
||||
+ if (!grub_is_cli_disabled ())
|
||||
{
|
||||
- ret += grub_print_message_indented_real
|
||||
- (_("Press enter to boot the selected OS, "
|
||||
- "`e' to edit the commands before booting "
|
||||
- "or `c' for a command-line. ESC to return previous menu."),
|
||||
- STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- ret += grub_print_message_indented_real
|
||||
- (_("Press enter to boot the selected OS, "
|
||||
- "`e' to edit the commands before booting "
|
||||
- "or `c' for a command-line."),
|
||||
- STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
+ if (nested)
|
||||
+ {
|
||||
+ ret += grub_print_message_indented_real
|
||||
+ (_("Press enter to boot the selected OS, "
|
||||
+ "`e' to edit the commands before booting "
|
||||
+ "or `c' for a command-line. ESC to return previous menu."),
|
||||
+ STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ret += grub_print_message_indented_real
|
||||
+ (_("Press enter to boot the selected OS, "
|
||||
+ "`e' to edit the commands before booting "
|
||||
+ "or `c' for a command-line."),
|
||||
+ STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
|
||||
index 98edc0863..f98a780da 100644
|
||||
--- a/include/grub/kernel.h
|
||||
+++ b/include/grub/kernel.h
|
||||
@@ -33,6 +33,7 @@ enum
|
||||
OBJ_TYPE_DISABLE_SHIM_LOCK,
|
||||
OBJ_TYPE_GPG_PUBKEY,
|
||||
OBJ_TYPE_X509_PUBKEY,
|
||||
+ OBJ_TYPE_DISABLE_CLI
|
||||
};
|
||||
|
||||
/* The module header. */
|
||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
|
||||
index 0592aa68f..8c0ffed16 100644
|
||||
--- a/include/grub/misc.h
|
||||
+++ b/include/grub/misc.h
|
||||
@@ -409,6 +409,8 @@ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
|
||||
grub_uint64_t d,
|
||||
grub_uint64_t *r);
|
||||
|
||||
+extern bool EXPORT_FUNC(grub_is_cli_disabled) (void);
|
||||
+
|
||||
/* Must match softdiv group in gentpl.py. */
|
||||
#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__) || \
|
||||
(defined(__riscv) && (__riscv_xlen == 32)))
|
||||
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
|
||||
index 51f3b13ac..b9627182a 100644
|
||||
--- a/include/grub/util/install.h
|
||||
+++ b/include/grub/util/install.h
|
||||
@@ -72,6 +72,8 @@
|
||||
{ "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
|
||||
"SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
|
||||
1}, \
|
||||
+ { "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \
|
||||
+ N_("disabled command line interface access"), 0 }, \
|
||||
{ "verbose", 'v', 0, 0, \
|
||||
N_("print verbose messages."), 1 }
|
||||
|
||||
@@ -134,7 +136,8 @@ enum grub_install_options {
|
||||
GRUB_INSTALL_OPTIONS_DTB,
|
||||
GRUB_INSTALL_OPTIONS_SBAT,
|
||||
GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
|
||||
- GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
|
||||
+ GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,
|
||||
+ GRUB_INSTALL_OPTIONS_DISABLE_CLI
|
||||
};
|
||||
|
||||
extern char *grub_install_source_directory;
|
||||
@@ -197,7 +200,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
const struct grub_install_image_target_desc *image_target,
|
||||
int note, size_t appsig_size,
|
||||
grub_compression_t comp, const char *dtb_file,
|
||||
- const char *sbat_path, const int disable_shim_lock);
|
||||
+ const char *sbat_path, const int disable_shim_lock,
|
||||
+ const int disable_cli);
|
||||
|
||||
const struct grub_install_image_target_desc *
|
||||
grub_install_get_image_target (const char *arg);
|
||||
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
|
||||
index c603f5b30..221b889c8 100644
|
||||
--- a/util/grub-install-common.c
|
||||
+++ b/util/grub-install-common.c
|
||||
@@ -464,6 +464,7 @@ static char **x509keys;
|
||||
static size_t nx509keys;
|
||||
static grub_compression_t compression;
|
||||
static size_t appsig_size;
|
||||
+static int disable_cli;
|
||||
|
||||
int
|
||||
grub_install_parse (int key, char *arg)
|
||||
@@ -509,6 +510,9 @@ grub_install_parse (int key, char *arg)
|
||||
* (nx509keys + 1));
|
||||
x509keys[nx509keys++] = xstrdup (arg);
|
||||
return 1;
|
||||
+ case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
|
||||
+ disable_cli = 1;
|
||||
+ return 1;
|
||||
|
||||
case GRUB_INSTALL_OPTIONS_VERBOSITY:
|
||||
verbosity++;
|
||||
@@ -689,12 +693,13 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
|
||||
" --dtb '%s' "
|
||||
"--sbat '%s' "
|
||||
"--format '%s' --compression '%s' "
|
||||
- "--appended-signature-size %zu %s %s %s\n",
|
||||
+ "--appended-signature-size %zu %s %s %s %s\n",
|
||||
dir, prefix,
|
||||
outname, dtb ? : "", sbat ? : "", mkimage_target,
|
||||
compnames[compression], appsig_size,
|
||||
disable_shim_lock ? "--disable-shim-lock" : "",
|
||||
- note ? "--note" : "", s);
|
||||
+ note ? "--note" : "",
|
||||
+ disable_cli ? " --disable-cli" : "", s);
|
||||
free (s);
|
||||
|
||||
tgt = grub_install_get_image_target (mkimage_target);
|
||||
@@ -707,7 +712,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
|
||||
x509keys, nx509keys,
|
||||
config_path, tgt,
|
||||
note, appsig_size, compression, dtb, sbat,
|
||||
- disable_shim_lock);
|
||||
+ disable_shim_lock, disable_cli);
|
||||
while (dc--)
|
||||
grub_install_pop_module ();
|
||||
}
|
||||
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
|
||||
index e1f111278..13bdc6cf0 100644
|
||||
--- a/util/grub-mkimage.c
|
||||
+++ b/util/grub-mkimage.c
|
||||
@@ -84,6 +84,7 @@ static struct argp_option options[] = {
|
||||
{"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
|
||||
{"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
|
||||
{"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
|
||||
+ {"disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, N_("disable command line interface access"), 0},
|
||||
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
|
||||
{"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0},
|
||||
{ 0, 0, 0, 0, 0, 0 }
|
||||
@@ -133,6 +134,7 @@ struct arguments
|
||||
int note;
|
||||
int disable_shim_lock;
|
||||
size_t appsig_size;
|
||||
+ int disable_cli;
|
||||
const struct grub_install_image_target_desc *image_target;
|
||||
grub_compression_t comp;
|
||||
};
|
||||
@@ -259,6 +261,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
|
||||
arguments->disable_shim_lock = 1;
|
||||
break;
|
||||
|
||||
+ case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
|
||||
+ arguments->disable_cli = 1;
|
||||
+ break;
|
||||
+
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
@@ -347,7 +353,8 @@ main (int argc, char *argv[])
|
||||
arguments.image_target, arguments.note,
|
||||
arguments.appsig_size, arguments.comp,
|
||||
arguments.dtb, arguments.sbat,
|
||||
- arguments.disable_shim_lock);
|
||||
+ arguments.disable_shim_lock,
|
||||
+ arguments.disable_cli);
|
||||
|
||||
if (grub_util_file_sync (fp) < 0)
|
||||
grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
|
||||
diff --git a/util/mkimage.c b/util/mkimage.c
|
||||
index c3d33aaac..9ba1a8988 100644
|
||||
--- a/util/mkimage.c
|
||||
+++ b/util/mkimage.c
|
||||
@@ -872,7 +872,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
const struct grub_install_image_target_desc *image_target,
|
||||
int note, size_t appsig_size, grub_compression_t comp,
|
||||
const char *dtb_path, const char *sbat_path,
|
||||
- int disable_shim_lock)
|
||||
+ int disable_shim_lock, int disable_cli)
|
||||
{
|
||||
char *kernel_img, *core_img;
|
||||
size_t total_module_size, core_size;
|
||||
@@ -947,6 +947,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
if (disable_shim_lock)
|
||||
total_module_size += sizeof (struct grub_module_header);
|
||||
|
||||
+ if (disable_cli)
|
||||
+ total_module_size += sizeof (struct grub_module_header);
|
||||
+
|
||||
if (config_path)
|
||||
{
|
||||
config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
|
||||
@@ -1113,6 +1116,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||
offset += sizeof (*header);
|
||||
}
|
||||
|
||||
+ if (disable_cli)
|
||||
+ {
|
||||
+ struct grub_module_header *header;
|
||||
+
|
||||
+ header = (struct grub_module_header *) (kernel_img + offset);
|
||||
+ header->type = grub_host_to_target32 (OBJ_TYPE_DISABLE_CLI);
|
||||
+ header->size = grub_host_to_target32 (sizeof (*header));
|
||||
+ offset += sizeof (*header);
|
||||
+ }
|
||||
+
|
||||
if (config_path)
|
||||
{
|
||||
struct grub_module_header *header;
|
184
0378-cryptodisk-Refactor-to-discard-have_it-global.patch
Normal file
184
0378-cryptodisk-Refactor-to-discard-have_it-global.patch
Normal file
@ -0,0 +1,184 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:51 -0600
|
||||
Subject: [PATCH] cryptodisk: Refactor to discard have_it global
|
||||
|
||||
The global "have_it" was never used by the crypto-backends, but was used to
|
||||
determine if a crypto-backend successfully mounted a cryptodisk with a given
|
||||
UUID. This is not needed however, because grub_device_iterate() will return
|
||||
1 if and only if grub_cryptodisk_scan_device() returns 1. And
|
||||
grub_cryptodisk_scan_device() will now only return 1 if a search_uuid has
|
||||
been specified and a cryptodisk was successfully setup by a crypto-backend or
|
||||
a cryptodisk of the requested UUID is already open.
|
||||
|
||||
To implement this grub_cryptodisk_scan_device_real() is modified to return
|
||||
a cryptodisk or NULL on failure and having the appropriate grub_errno set to
|
||||
indicated failure. Note that grub_cryptodisk_scan_device_real() will fail now
|
||||
with a new errno GRUB_ERR_BAD_MODULE when none of the cryptodisk backend
|
||||
modules succeed in identifying the source disk.
|
||||
|
||||
With this change grub_device_iterate() will return 1 when a crypto device is
|
||||
successfully decrypted or when the source device has already been successfully
|
||||
opened. Prior to this change, trying to mount an already successfully opened
|
||||
device would trigger an error with the message "no such cryptodisk found",
|
||||
which is at best misleading. The mount should silently succeed in this case,
|
||||
which is what happens with this patch.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 56 ++++++++++++++++++++++++++++-----------------
|
||||
1 file changed, 35 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 90f82b2..9df3d31 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -983,7 +983,7 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
|
||||
|
||||
#endif
|
||||
|
||||
-static int check_boot, have_it;
|
||||
+static int check_boot;
|
||||
static char *search_uuid;
|
||||
|
||||
static void
|
||||
@@ -995,7 +995,7 @@ cryptodisk_close (grub_cryptodisk_t dev)
|
||||
grub_free (dev);
|
||||
}
|
||||
|
||||
-static grub_err_t
|
||||
+static grub_cryptodisk_t
|
||||
grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
|
||||
{
|
||||
grub_err_t err;
|
||||
@@ -1005,13 +1005,13 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
|
||||
dev = grub_cryptodisk_get_by_source_disk (source);
|
||||
|
||||
if (dev)
|
||||
- return GRUB_ERR_NONE;
|
||||
+ return dev;
|
||||
|
||||
FOR_CRYPTODISK_DEVS (cr)
|
||||
{
|
||||
dev = cr->scan (source, search_uuid, check_boot);
|
||||
if (grub_errno)
|
||||
- return grub_errno;
|
||||
+ return NULL;
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
@@ -1019,16 +1019,16 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
|
||||
if (err)
|
||||
{
|
||||
cryptodisk_close (dev);
|
||||
- return err;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
grub_cryptodisk_insert (dev, name, source);
|
||||
|
||||
- have_it = 1;
|
||||
-
|
||||
- return GRUB_ERR_NONE;
|
||||
+ return dev;
|
||||
}
|
||||
- return GRUB_ERR_NONE;
|
||||
+
|
||||
+ grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
@@ -1082,8 +1082,10 @@ static int
|
||||
grub_cryptodisk_scan_device (const char *name,
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
- grub_err_t err;
|
||||
+ int ret = 0;
|
||||
grub_disk_t source;
|
||||
+ grub_cryptodisk_t dev;
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
/* Try to open disk. */
|
||||
source = grub_disk_open (name);
|
||||
@@ -1093,13 +1095,26 @@ grub_cryptodisk_scan_device (const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- err = grub_cryptodisk_scan_device_real (name, source);
|
||||
+ dev = grub_cryptodisk_scan_device_real (name, source);
|
||||
+ if (dev)
|
||||
+ {
|
||||
+ ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
- grub_disk_close (source);
|
||||
-
|
||||
- if (err)
|
||||
+ /*
|
||||
+ * Do not print error when err is GRUB_ERR_BAD_MODULE to avoid many unhelpful
|
||||
+ * error messages.
|
||||
+ */
|
||||
+ if (grub_errno == GRUB_ERR_BAD_MODULE)
|
||||
+ grub_error_pop ();
|
||||
+
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
grub_print_error ();
|
||||
- return have_it && search_uuid ? 1 : 0;
|
||||
+
|
||||
+ cleanup:
|
||||
+ grub_disk_close (source);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -1110,9 +1125,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
if (argc < 1 && !state[1].set && !state[2].set)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
|
||||
- have_it = 0;
|
||||
if (state[0].set)
|
||||
{
|
||||
+ int found_uuid;
|
||||
grub_cryptodisk_t dev;
|
||||
|
||||
dev = grub_cryptodisk_get_by_uuid (args[0]);
|
||||
@@ -1125,10 +1140,10 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
|
||||
check_boot = state[2].set;
|
||||
search_uuid = args[0];
|
||||
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
|
||||
+ found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
|
||||
search_uuid = NULL;
|
||||
|
||||
- if (!have_it)
|
||||
+ if (!found_uuid)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
@@ -1142,7 +1157,6 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
}
|
||||
else
|
||||
{
|
||||
- grub_err_t err;
|
||||
grub_disk_t disk;
|
||||
grub_cryptodisk_t dev;
|
||||
char *diskname;
|
||||
@@ -1178,13 +1192,13 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
- err = grub_cryptodisk_scan_device_real (diskname, disk);
|
||||
+ dev = grub_cryptodisk_scan_device_real (diskname, disk);
|
||||
|
||||
grub_disk_close (disk);
|
||||
if (disklast)
|
||||
*disklast = ')';
|
||||
|
||||
- return err;
|
||||
+ return (dev == NULL) ? grub_errno : GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:52 -0600
|
||||
Subject: [PATCH] cryptodisk: Return failure in cryptomount when no cryptodisk
|
||||
modules are loaded
|
||||
|
||||
This displays an error notifying the user that they'll want to load
|
||||
a backend module to make cryptomount useful.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 9df3d31..2749187 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1125,6 +1125,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
if (argc < 1 && !state[1].set && !state[2].set)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
|
||||
+ if (grub_cryptodisk_list == NULL)
|
||||
+ return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
|
||||
+
|
||||
if (state[0].set)
|
||||
{
|
||||
int found_uuid;
|
@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:53 -0600
|
||||
Subject: [PATCH] cryptodisk: Improve error messaging in cryptomount
|
||||
invocations
|
||||
|
||||
Update such that "cryptomount -u UUID" will not print two error messages
|
||||
when an invalid passphrase is given and the most relevant error message
|
||||
will be displayed.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 21 +++++++++++++++++----
|
||||
1 file changed, 17 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 2749187..3a896c6 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1109,7 +1109,10 @@ grub_cryptodisk_scan_device (const char *name,
|
||||
if (grub_errno == GRUB_ERR_BAD_MODULE)
|
||||
grub_error_pop ();
|
||||
|
||||
- if (grub_errno != GRUB_ERR_NONE)
|
||||
+ if (search_uuid != NULL)
|
||||
+ /* Push error onto stack to save for cryptomount. */
|
||||
+ grub_error_push ();
|
||||
+ else
|
||||
grub_print_error ();
|
||||
|
||||
cleanup:
|
||||
@@ -1146,9 +1149,19 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
|
||||
search_uuid = NULL;
|
||||
|
||||
- if (!found_uuid)
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
|
||||
- return GRUB_ERR_NONE;
|
||||
+ if (found_uuid)
|
||||
+ return GRUB_ERR_NONE;
|
||||
+ else if (grub_errno == GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ /*
|
||||
+ * Try to pop the next error on the stack. If there is not one, then
|
||||
+ * no device matched the given UUID.
|
||||
+ */
|
||||
+ grub_error_pop ();
|
||||
+ if (grub_errno == GRUB_ERR_NONE)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
|
||||
+ }
|
||||
+ return grub_errno;
|
||||
}
|
||||
else if (state[1].set || (argc == 0 && state[2].set))
|
||||
{
|
28
0381-cryptodisk-Improve-cryptomount-u-error-message.patch
Normal file
28
0381-cryptodisk-Improve-cryptomount-u-error-message.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:54 -0600
|
||||
Subject: [PATCH] cryptodisk: Improve cryptomount -u error message
|
||||
|
||||
When a cryptmount is specified with a UUID, but no cryptodisk backends find
|
||||
a disk with that UUID, return a more detailed message giving telling the
|
||||
user that they might not have a needed cryptobackend module loaded.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 3a896c6..5a9780b 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1159,7 +1159,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
*/
|
||||
grub_error_pop ();
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found, perhaps a needed disk or cryptodisk module is not loaded");
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
249
0382-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch
Normal file
249
0382-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch
Normal file
@ -0,0 +1,249 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:55 -0600
|
||||
Subject: [PATCH] cryptodisk: Add infrastructure to pass data from cryptomount
|
||||
to cryptodisk modules
|
||||
|
||||
Previously, the cryptomount arguments were passed by global variable and
|
||||
function call argument, neither of which are ideal. This change passes data
|
||||
via a grub_cryptomount_args struct, which can be added to over time as
|
||||
opposed to continually adding arguments to the cryptodisk scan and
|
||||
recover_key.
|
||||
|
||||
As an example, passing a password as a cryptomount argument is implemented.
|
||||
However, the backends are not implemented, so testing this will return a not
|
||||
implemented error.
|
||||
|
||||
Also, add comments to cryptomount argument parsing to make it more obvious
|
||||
which argument states are being handled.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 31 +++++++++++++++++++++----------
|
||||
grub-core/disk/geli.c | 6 +++++-
|
||||
grub-core/disk/luks.c | 7 ++++++-
|
||||
grub-core/disk/luks2.c | 7 ++++++-
|
||||
include/grub/cryptodisk.h | 9 ++++++++-
|
||||
5 files changed, 46 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 5a9780b..14c661a 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] =
|
||||
/* TRANSLATORS: It's still restricted to cryptodisks only. */
|
||||
{"all", 'a', 0, N_("Mount all."), 0, 0},
|
||||
{"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
|
||||
+ {"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -996,7 +997,9 @@ cryptodisk_close (grub_cryptodisk_t dev)
|
||||
}
|
||||
|
||||
static grub_cryptodisk_t
|
||||
-grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
|
||||
+grub_cryptodisk_scan_device_real (const char *name,
|
||||
+ grub_disk_t source,
|
||||
+ grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_cryptodisk_t dev;
|
||||
@@ -1015,7 +1018,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
- err = cr->recover_key (source, dev);
|
||||
+ err = cr->recover_key (source, dev, cargs);
|
||||
if (err)
|
||||
{
|
||||
cryptodisk_close (dev);
|
||||
@@ -1080,11 +1083,12 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
|
||||
|
||||
static int
|
||||
grub_cryptodisk_scan_device (const char *name,
|
||||
- void *data __attribute__ ((unused)))
|
||||
+ void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
grub_disk_t source;
|
||||
grub_cryptodisk_t dev;
|
||||
+ grub_cryptomount_args_t cargs = data;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
/* Try to open disk. */
|
||||
@@ -1095,7 +1099,7 @@ grub_cryptodisk_scan_device (const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- dev = grub_cryptodisk_scan_device_real (name, source);
|
||||
+ dev = grub_cryptodisk_scan_device_real (name, source, cargs);
|
||||
if (dev)
|
||||
{
|
||||
ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
|
||||
@@ -1124,6 +1128,7 @@ static grub_err_t
|
||||
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
+ struct grub_cryptomount_args cargs = {0};
|
||||
|
||||
if (argc < 1 && !state[1].set && !state[2].set)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
@@ -1131,7 +1136,13 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
if (grub_cryptodisk_list == NULL)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
|
||||
|
||||
- if (state[0].set)
|
||||
+ if (state[3].set) /* password */
|
||||
+ {
|
||||
+ cargs.key_data = (grub_uint8_t *) state[3].arg;
|
||||
+ cargs.key_len = grub_strlen (state[3].arg);
|
||||
+ }
|
||||
+
|
||||
+ if (state[0].set) /* uuid */
|
||||
{
|
||||
int found_uuid;
|
||||
grub_cryptodisk_t dev;
|
||||
@@ -1146,7 +1157,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
|
||||
check_boot = state[2].set;
|
||||
search_uuid = args[0];
|
||||
- found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
|
||||
+ found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||
search_uuid = NULL;
|
||||
|
||||
if (found_uuid)
|
||||
@@ -1163,11 +1174,11 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
||||
- else if (state[1].set || (argc == 0 && state[2].set))
|
||||
+ else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
|
||||
{
|
||||
search_uuid = NULL;
|
||||
check_boot = state[2].set;
|
||||
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
|
||||
+ grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||
search_uuid = NULL;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
@@ -1208,7 +1219,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
- dev = grub_cryptodisk_scan_device_real (diskname, disk);
|
||||
+ dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
|
||||
|
||||
grub_disk_close (disk);
|
||||
if (disklast)
|
||||
@@ -1347,7 +1358,7 @@ GRUB_MOD_INIT (cryptodisk)
|
||||
{
|
||||
grub_disk_dev_register (&grub_cryptodisk_dev);
|
||||
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
|
||||
- N_("SOURCE|-u UUID|-a|-b"),
|
||||
+ N_("[-p password] <SOURCE|-u UUID|-a|-b>"),
|
||||
N_("Mount a crypto device."), options);
|
||||
grub_procfs_register ("luks_script", &luks_script);
|
||||
}
|
||||
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
|
||||
index 2f34a35..777da3a 100644
|
||||
--- a/grub-core/disk/geli.c
|
||||
+++ b/grub-core/disk/geli.c
|
||||
@@ -398,7 +398,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
||||
+recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_size_t keysize;
|
||||
grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
|
||||
@@ -414,6 +414,10 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
||||
grub_disk_addr_t sector;
|
||||
grub_err_t err;
|
||||
|
||||
+ /* Keyfiles are not implemented yet */
|
||||
+ if (cargs->key_data != NULL || cargs->key_len)
|
||||
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
+
|
||||
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
|
||||
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
|
||||
|
||||
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
|
||||
index 13103ea..c5858fc 100644
|
||||
--- a/grub-core/disk/luks.c
|
||||
+++ b/grub-core/disk/luks.c
|
||||
@@ -152,7 +152,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
|
||||
static grub_err_t
|
||||
luks_recover_key (grub_disk_t source,
|
||||
- grub_cryptodisk_t dev)
|
||||
+ grub_cryptodisk_t dev,
|
||||
+ grub_cryptomount_args_t cargs)
|
||||
{
|
||||
struct grub_luks_phdr header;
|
||||
grub_size_t keysize;
|
||||
@@ -165,6 +166,10 @@ luks_recover_key (grub_disk_t source,
|
||||
grub_size_t max_stripes = 1;
|
||||
char *tmp;
|
||||
|
||||
+ /* Keyfiles are not implemented yet */
|
||||
+ if (cargs->key_data != NULL || cargs->key_len)
|
||||
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
+
|
||||
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
|
||||
if (err)
|
||||
return err;
|
||||
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
|
||||
index c917a5f..8a9f42d 100644
|
||||
--- a/grub-core/disk/luks2.c
|
||||
+++ b/grub-core/disk/luks2.c
|
||||
@@ -542,7 +542,8 @@ luks2_decrypt_key (grub_uint8_t *out_key,
|
||||
|
||||
static grub_err_t
|
||||
luks2_recover_key (grub_disk_t source,
|
||||
- grub_cryptodisk_t crypt)
|
||||
+ grub_cryptodisk_t crypt,
|
||||
+ grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
|
||||
char passphrase[MAX_PASSPHRASE], cipher[32];
|
||||
@@ -556,6 +557,10 @@ luks2_recover_key (grub_disk_t source,
|
||||
grub_json_t *json = NULL, keyslots;
|
||||
grub_err_t ret;
|
||||
|
||||
+ /* Keyfiles are not implemented yet */
|
||||
+ if (cargs->key_data != NULL || cargs->key_len)
|
||||
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
+
|
||||
ret = luks2_read_header (source, &header);
|
||||
if (ret)
|
||||
return ret;
|
||||
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
|
||||
index dcf17fb..282f8ac 100644
|
||||
--- a/include/grub/cryptodisk.h
|
||||
+++ b/include/grub/cryptodisk.h
|
||||
@@ -66,6 +66,13 @@ typedef gcry_err_code_t
|
||||
(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
|
||||
grub_uint64_t zoneno);
|
||||
|
||||
+struct grub_cryptomount_args
|
||||
+{
|
||||
+ grub_uint8_t *key_data;
|
||||
+ grub_size_t key_len;
|
||||
+};
|
||||
+typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
|
||||
+
|
||||
struct grub_cryptodisk
|
||||
{
|
||||
struct grub_cryptodisk *next;
|
||||
@@ -119,7 +126,7 @@ struct grub_cryptodisk_dev
|
||||
|
||||
grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
|
||||
int boot_only);
|
||||
- grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev);
|
||||
+ grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs);
|
||||
};
|
||||
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
|
||||
|
339
0383-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch
Normal file
339
0383-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch
Normal file
@ -0,0 +1,339 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:56 -0600
|
||||
Subject: [PATCH] cryptodisk: Refactor password input out of crypto dev modules
|
||||
into cryptodisk
|
||||
|
||||
The crypto device modules should only be setting up the crypto devices and
|
||||
not getting user input. This has the added benefit of simplifying the code
|
||||
such that three essentially duplicate pieces of code are merged into one.
|
||||
|
||||
Add documentation of passphrase option for cryptomount as it is now usable.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
docs/grub.texi | 8 ++++---
|
||||
grub-core/disk/cryptodisk.c | 56 ++++++++++++++++++++++++++++++++++++---------
|
||||
grub-core/disk/geli.c | 26 ++++-----------------
|
||||
grub-core/disk/luks.c | 27 ++++------------------
|
||||
grub-core/disk/luks2.c | 25 ++++----------------
|
||||
include/grub/cryptodisk.h | 1 +
|
||||
6 files changed, 64 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index b39cdf2..3c7d99e 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -4329,9 +4329,11 @@ Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum}
|
||||
@node cryptomount
|
||||
@subsection cryptomount
|
||||
|
||||
-@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b}
|
||||
-Setup access to encrypted device. If necessary, passphrase
|
||||
-is requested interactively. Option @var{device} configures specific grub device
|
||||
+@deffn Command cryptomount [@option{-p} password] device|@option{-u} uuid|@option{-a}|@option{-b}
|
||||
+Setup access to encrypted device. If @option{-p} is not given, a passphrase
|
||||
+is requested interactively. Otherwise, the given @var{password} will be used and
|
||||
+no passphrase will be requested interactively.
|
||||
+Option @var{device} configures specific grub device
|
||||
(@pxref{Naming convention}); option @option{-u} @var{uuid} configures device
|
||||
with specified @var{uuid}; option @option{-a} configures all detected encrypted
|
||||
devices; option @option{-b} configures all geli containers that have boot flag set.
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 14c661a..d12368a 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1001,9 +1001,11 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
grub_disk_t source,
|
||||
grub_cryptomount_args_t cargs)
|
||||
{
|
||||
- grub_err_t err;
|
||||
+ grub_err_t ret = GRUB_ERR_NONE;
|
||||
grub_cryptodisk_t dev;
|
||||
grub_cryptodisk_dev_t cr;
|
||||
+ int askpass = 0;
|
||||
+ char *part = NULL;
|
||||
|
||||
dev = grub_cryptodisk_get_by_source_disk (source);
|
||||
|
||||
@@ -1017,21 +1019,53 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
return NULL;
|
||||
if (!dev)
|
||||
continue;
|
||||
-
|
||||
- err = cr->recover_key (source, dev, cargs);
|
||||
- if (err)
|
||||
- {
|
||||
- cryptodisk_close (dev);
|
||||
- return NULL;
|
||||
- }
|
||||
+
|
||||
+ if (!cargs->key_len)
|
||||
+ {
|
||||
+ /* Get the passphrase from the user, if no key data. */
|
||||
+ askpass = 1;
|
||||
+ if (source->partition != NULL)
|
||||
+ part = grub_partition_get_name (source->partition);
|
||||
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||
+ source->partition != NULL ? "," : "",
|
||||
+ part != NULL ? part : "",
|
||||
+ dev->uuid);
|
||||
+ grub_free (part);
|
||||
+
|
||||
+ cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
|
||||
+ if (cargs->key_data == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
|
||||
+ goto error;
|
||||
+ }
|
||||
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
|
||||
+ }
|
||||
+
|
||||
+ ret = cr->recover_key (source, dev, cargs);
|
||||
+ if (ret != GRUB_ERR_NONE)
|
||||
+ goto error;
|
||||
|
||||
grub_cryptodisk_insert (dev, name, source);
|
||||
|
||||
- return dev;
|
||||
+ goto cleanup;
|
||||
}
|
||||
-
|
||||
grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
|
||||
- return NULL;
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ error:
|
||||
+ cryptodisk_close (dev);
|
||||
+ dev = NULL;
|
||||
+
|
||||
+ cleanup:
|
||||
+ if (askpass)
|
||||
+ {
|
||||
+ cargs->key_len = 0;
|
||||
+ grub_free (cargs->key_data);
|
||||
+ }
|
||||
+ return dev;
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
|
||||
index 777da3a..7299a47 100644
|
||||
--- a/grub-core/disk/geli.c
|
||||
+++ b/grub-core/disk/geli.c
|
||||
@@ -135,8 +135,6 @@ const char *algorithms[] = {
|
||||
[0x16] = "aes"
|
||||
};
|
||||
|
||||
-#define MAX_PASSPHRASE 256
|
||||
-
|
||||
static gcry_err_code_t
|
||||
geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
|
||||
{
|
||||
@@ -406,17 +404,14 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
|
||||
grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
|
||||
grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
|
||||
grub_uint8_t geli_cipher_key[64];
|
||||
- char passphrase[MAX_PASSPHRASE] = "";
|
||||
unsigned i;
|
||||
gcry_err_code_t gcry_err;
|
||||
struct grub_geli_phdr header;
|
||||
- char *tmp;
|
||||
grub_disk_addr_t sector;
|
||||
grub_err_t err;
|
||||
|
||||
- /* Keyfiles are not implemented yet */
|
||||
- if (cargs->key_data != NULL || cargs->key_len)
|
||||
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
+ if (cargs->key_data == NULL || cargs->key_len == 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
|
||||
|
||||
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
|
||||
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
|
||||
@@ -438,23 +433,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
|
||||
|
||||
grub_puts_ (N_("Attempting to decrypt master key..."));
|
||||
|
||||
- /* Get the passphrase from the user. */
|
||||
- tmp = NULL;
|
||||
- if (source->partition)
|
||||
- tmp = grub_partition_get_name (source->partition);
|
||||
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||
- source->partition ? "," : "", tmp ? : "",
|
||||
- dev->uuid);
|
||||
- grub_free (tmp);
|
||||
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
|
||||
-
|
||||
/* Calculate the PBKDF2 of the user supplied passphrase. */
|
||||
if (grub_le_to_cpu32 (header.niter) != 0)
|
||||
{
|
||||
grub_uint8_t pbkdf_key[64];
|
||||
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
|
||||
- grub_strlen (passphrase),
|
||||
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
|
||||
+ cargs->key_len,
|
||||
header.salt,
|
||||
sizeof (header.salt),
|
||||
grub_le_to_cpu32 (header.niter),
|
||||
@@ -477,7 +461,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
|
||||
return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
|
||||
|
||||
grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
|
||||
- grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase));
|
||||
+ grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
|
||||
|
||||
gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
|
||||
if (gcry_err)
|
||||
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
|
||||
index c5858fc..39a7af6 100644
|
||||
--- a/grub-core/disk/luks.c
|
||||
+++ b/grub-core/disk/luks.c
|
||||
@@ -29,8 +29,6 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
-#define MAX_PASSPHRASE 256
|
||||
-
|
||||
#define LUKS_KEY_ENABLED 0x00AC71F3
|
||||
|
||||
/* On disk LUKS header */
|
||||
@@ -158,17 +156,14 @@ luks_recover_key (grub_disk_t source,
|
||||
struct grub_luks_phdr header;
|
||||
grub_size_t keysize;
|
||||
grub_uint8_t *split_key = NULL;
|
||||
- char passphrase[MAX_PASSPHRASE] = "";
|
||||
grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
|
||||
unsigned i;
|
||||
grub_size_t length;
|
||||
grub_err_t err;
|
||||
grub_size_t max_stripes = 1;
|
||||
- char *tmp;
|
||||
|
||||
- /* Keyfiles are not implemented yet */
|
||||
- if (cargs->key_data != NULL || cargs->key_len)
|
||||
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
+ if (cargs->key_data == NULL || cargs->key_len == 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
|
||||
|
||||
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
|
||||
if (err)
|
||||
@@ -188,20 +183,6 @@ luks_recover_key (grub_disk_t source,
|
||||
if (!split_key)
|
||||
return grub_errno;
|
||||
|
||||
- /* Get the passphrase from the user. */
|
||||
- tmp = NULL;
|
||||
- if (source->partition)
|
||||
- tmp = grub_partition_get_name (source->partition);
|
||||
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||
- source->partition ? "," : "", tmp ? : "",
|
||||
- dev->uuid);
|
||||
- grub_free (tmp);
|
||||
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
|
||||
- {
|
||||
- grub_free (split_key);
|
||||
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
|
||||
- }
|
||||
-
|
||||
/* Try to recover master key from each active keyslot. */
|
||||
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
|
||||
{
|
||||
@@ -216,8 +197,8 @@ luks_recover_key (grub_disk_t source,
|
||||
grub_dprintf ("luks", "Trying keyslot %d\n", i);
|
||||
|
||||
/* Calculate the PBKDF2 of the user supplied passphrase. */
|
||||
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
|
||||
- grub_strlen (passphrase),
|
||||
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
|
||||
+ cargs->key_len,
|
||||
header.keyblock[i].passwordSalt,
|
||||
sizeof (header.keyblock[i].passwordSalt),
|
||||
grub_be_to_cpu32 (header.keyblock[i].
|
||||
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
|
||||
index 8a9f42d..0425100 100644
|
||||
--- a/grub-core/disk/luks2.c
|
||||
+++ b/grub-core/disk/luks2.c
|
||||
@@ -35,8 +35,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define LUKS_MAGIC_1ST "LUKS\xBA\xBE"
|
||||
#define LUKS_MAGIC_2ND "SKUL\xBA\xBE"
|
||||
|
||||
-#define MAX_PASSPHRASE 256
|
||||
-
|
||||
enum grub_luks2_kdf_type
|
||||
{
|
||||
LUKS2_KDF_TYPE_ARGON2I,
|
||||
@@ -546,8 +544,7 @@ luks2_recover_key (grub_disk_t source,
|
||||
grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
|
||||
- char passphrase[MAX_PASSPHRASE], cipher[32];
|
||||
- char *json_header = NULL, *part = NULL, *ptr;
|
||||
+ char cipher[32], *json_header = NULL, *ptr;
|
||||
grub_size_t candidate_key_len = 0, json_idx, size;
|
||||
grub_luks2_header_t header;
|
||||
grub_luks2_keyslot_t keyslot;
|
||||
@@ -557,9 +554,8 @@ luks2_recover_key (grub_disk_t source,
|
||||
grub_json_t *json = NULL, keyslots;
|
||||
grub_err_t ret;
|
||||
|
||||
- /* Keyfiles are not implemented yet */
|
||||
- if (cargs->key_data != NULL || cargs->key_len)
|
||||
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
+ if (cargs->key_data == NULL || cargs->key_len == 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
|
||||
|
||||
ret = luks2_read_header (source, &header);
|
||||
if (ret)
|
||||
@@ -586,18 +582,6 @@ luks2_recover_key (grub_disk_t source,
|
||||
goto err;
|
||||
}
|
||||
|
||||
- /* Get the passphrase from the user. */
|
||||
- if (source->partition)
|
||||
- part = grub_partition_get_name (source->partition);
|
||||
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||
- source->partition ? "," : "", part ? : "",
|
||||
- crypt->uuid);
|
||||
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
|
||||
- {
|
||||
- ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
if (grub_json_getvalue (&keyslots, json, "keyslots") ||
|
||||
grub_json_getsize (&size, &keyslots))
|
||||
{
|
||||
@@ -722,7 +706,7 @@ luks2_recover_key (grub_disk_t source,
|
||||
}
|
||||
|
||||
ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
|
||||
- (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
|
||||
+ cargs->key_data, cargs->key_len);
|
||||
if (ret)
|
||||
{
|
||||
grub_dprintf ("luks2", "Decryption with keyslot \"%" PRIuGRUB_UINT64_T "\" failed: %s\n",
|
||||
@@ -774,7 +758,6 @@ luks2_recover_key (grub_disk_t source,
|
||||
}
|
||||
|
||||
err:
|
||||
- grub_free (part);
|
||||
grub_free (json_header);
|
||||
grub_json_free (json);
|
||||
return ret;
|
||||
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
|
||||
index 282f8ac..5bd9706 100644
|
||||
--- a/include/grub/cryptodisk.h
|
||||
+++ b/include/grub/cryptodisk.h
|
||||
@@ -59,6 +59,7 @@ typedef enum
|
||||
#define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
|
||||
#define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
|
||||
#define GRUB_CRYPTODISK_MAX_KEYLEN 128
|
||||
+#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
|
||||
|
||||
struct grub_cryptodisk;
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:50 -0600
|
||||
Subject: [PATCH] luks2: Add debug message to align with luks and geli modules
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/luks2.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
|
||||
index 0425100..caed4d4 100644
|
||||
--- a/grub-core/disk/luks2.c
|
||||
+++ b/grub-core/disk/luks2.c
|
||||
@@ -368,7 +368,10 @@ luks2_scan (grub_disk_t disk, const char *check_uuid, int check_boot)
|
||||
uuid[j] = '\0';
|
||||
|
||||
if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
|
||||
- return NULL;
|
||||
+ {
|
||||
+ grub_dprintf ("luks2", "%s != %s\n", uuid, check_uuid);
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
cryptodisk = grub_zalloc (sizeof (*cryptodisk));
|
||||
if (!cryptodisk)
|
245
0385-cryptodisk-Move-global-variables-into-grub_cryptomou.patch
Normal file
245
0385-cryptodisk-Move-global-variables-into-grub_cryptomou.patch
Normal file
@ -0,0 +1,245 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:57 -0600
|
||||
Subject: [PATCH] cryptodisk: Move global variables into grub_cryptomount_args
|
||||
struct
|
||||
|
||||
Note that cargs.search_uuid does not need to be initialized in various parts
|
||||
of the cryptomount argument parsing, just once when cargs is declared with
|
||||
a struct initializer. The previous code used a global variable which would
|
||||
retain the value across cryptomount invocations.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 24 +++++++++---------------
|
||||
grub-core/disk/geli.c | 9 ++++-----
|
||||
grub-core/disk/luks.c | 9 ++++-----
|
||||
grub-core/disk/luks2.c | 8 ++++----
|
||||
include/grub/cryptodisk.h | 9 +++++++--
|
||||
5 files changed, 28 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index d12368a..7ca8804 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -984,9 +984,6 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
|
||||
|
||||
#endif
|
||||
|
||||
-static int check_boot;
|
||||
-static char *search_uuid;
|
||||
-
|
||||
static void
|
||||
cryptodisk_close (grub_cryptodisk_t dev)
|
||||
{
|
||||
@@ -1014,7 +1011,7 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
|
||||
FOR_CRYPTODISK_DEVS (cr)
|
||||
{
|
||||
- dev = cr->scan (source, search_uuid, check_boot);
|
||||
+ dev = cr->scan (source, cargs);
|
||||
if (grub_errno)
|
||||
return NULL;
|
||||
if (!dev)
|
||||
@@ -1077,6 +1074,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
|
||||
grub_cryptodisk_t dev;
|
||||
grub_cryptodisk_dev_t cr;
|
||||
grub_disk_t source;
|
||||
+ struct grub_cryptomount_args cargs = {0};
|
||||
|
||||
/* Try to open disk. */
|
||||
source = grub_disk_open (sourcedev);
|
||||
@@ -1093,7 +1091,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
|
||||
|
||||
FOR_CRYPTODISK_DEVS (cr)
|
||||
{
|
||||
- dev = cr->scan (source, search_uuid, check_boot);
|
||||
+ dev = cr->scan (source, &cargs);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (!dev)
|
||||
@@ -1136,7 +1134,7 @@ grub_cryptodisk_scan_device (const char *name,
|
||||
dev = grub_cryptodisk_scan_device_real (name, source, cargs);
|
||||
if (dev)
|
||||
{
|
||||
- ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
|
||||
+ ret = (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, dev->uuid) == 0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1147,7 +1145,7 @@ grub_cryptodisk_scan_device (const char *name,
|
||||
if (grub_errno == GRUB_ERR_BAD_MODULE)
|
||||
grub_error_pop ();
|
||||
|
||||
- if (search_uuid != NULL)
|
||||
+ if (cargs->search_uuid != NULL)
|
||||
/* Push error onto stack to save for cryptomount. */
|
||||
grub_error_push ();
|
||||
else
|
||||
@@ -1189,10 +1187,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
- check_boot = state[2].set;
|
||||
- search_uuid = args[0];
|
||||
+ cargs.check_boot = state[2].set;
|
||||
+ cargs.search_uuid = args[0];
|
||||
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||
- search_uuid = NULL;
|
||||
|
||||
if (found_uuid)
|
||||
return GRUB_ERR_NONE;
|
||||
@@ -1210,10 +1207,8 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
}
|
||||
else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
|
||||
{
|
||||
- search_uuid = NULL;
|
||||
- check_boot = state[2].set;
|
||||
+ cargs.check_boot = state[2].set;
|
||||
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||
- search_uuid = NULL;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
else
|
||||
@@ -1224,8 +1219,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
char *disklast = NULL;
|
||||
grub_size_t len;
|
||||
|
||||
- search_uuid = NULL;
|
||||
- check_boot = state[2].set;
|
||||
+ cargs.check_boot = state[2].set;
|
||||
diskname = args[0];
|
||||
len = grub_strlen (diskname);
|
||||
if (len && diskname[0] == '(' && diskname[len - 1] == ')')
|
||||
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
|
||||
index 7299a47..23789c4 100644
|
||||
--- a/grub-core/disk/geli.c
|
||||
+++ b/grub-core/disk/geli.c
|
||||
@@ -240,8 +240,7 @@ grub_util_get_geli_uuid (const char *dev)
|
||||
#endif
|
||||
|
||||
static grub_cryptodisk_t
|
||||
-configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
- int boot_only)
|
||||
+configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_cryptodisk_t newdev;
|
||||
struct grub_geli_phdr header;
|
||||
@@ -289,7 +288,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
|
||||
+ if (cargs->check_boot && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
|
||||
{
|
||||
grub_dprintf ("geli", "not a boot volume\n");
|
||||
return NULL;
|
||||
@@ -302,9 +301,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
|
||||
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
|
||||
{
|
||||
- grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid);
|
||||
+ grub_dprintf ("geli", "%s != %s\n", uuid, cargs->search_uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
|
||||
index 39a7af6..f0feb38 100644
|
||||
--- a/grub-core/disk/luks.c
|
||||
+++ b/grub-core/disk/luks.c
|
||||
@@ -63,8 +63,7 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
|
||||
grub_size_t blocknumbers);
|
||||
|
||||
static grub_cryptodisk_t
|
||||
-configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
- int check_boot)
|
||||
+configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_cryptodisk_t newdev;
|
||||
const char *iptr;
|
||||
@@ -76,7 +75,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
char hashspec[sizeof (header.hashSpec) + 1];
|
||||
grub_err_t err;
|
||||
|
||||
- if (check_boot)
|
||||
+ if (cargs->check_boot)
|
||||
return NULL;
|
||||
|
||||
/* Read the LUKS header. */
|
||||
@@ -103,9 +102,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
}
|
||||
*optr = 0;
|
||||
|
||||
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
|
||||
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
|
||||
{
|
||||
- grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
|
||||
+ grub_dprintf ("luks", "%s != %s\n", uuid, cargs->search_uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
|
||||
index caed4d4..bf741d7 100644
|
||||
--- a/grub-core/disk/luks2.c
|
||||
+++ b/grub-core/disk/luks2.c
|
||||
@@ -346,14 +346,14 @@ luks2_read_header (grub_disk_t disk, grub_luks2_header_t *outhdr)
|
||||
}
|
||||
|
||||
static grub_cryptodisk_t
|
||||
-luks2_scan (grub_disk_t disk, const char *check_uuid, int check_boot)
|
||||
+luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_cryptodisk_t cryptodisk;
|
||||
grub_luks2_header_t header;
|
||||
char uuid[sizeof (header.uuid) + 1];
|
||||
grub_size_t i, j;
|
||||
|
||||
- if (check_boot)
|
||||
+ if (cargs->check_boot)
|
||||
return NULL;
|
||||
|
||||
if (luks2_read_header (disk, &header))
|
||||
@@ -367,9 +367,9 @@ luks2_scan (grub_disk_t disk, const char *check_uuid, int check_boot)
|
||||
uuid[j++] = header.uuid[i];
|
||||
uuid[j] = '\0';
|
||||
|
||||
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
|
||||
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
|
||||
{
|
||||
- grub_dprintf ("luks2", "%s != %s\n", uuid, check_uuid);
|
||||
+ grub_dprintf ("luks2", "%s != %s\n", uuid, cargs->search_uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
|
||||
index 5bd9706..c6524c9 100644
|
||||
--- a/include/grub/cryptodisk.h
|
||||
+++ b/include/grub/cryptodisk.h
|
||||
@@ -69,7 +69,13 @@ typedef gcry_err_code_t
|
||||
|
||||
struct grub_cryptomount_args
|
||||
{
|
||||
+ /* scan: Flag to indicate that only bootable volumes should be decrypted */
|
||||
+ grub_uint32_t check_boot : 1;
|
||||
+ /* scan: Only volumes matching this UUID should be decrpyted */
|
||||
+ char *search_uuid;
|
||||
+ /* recover_key: Key data used to decrypt voume */
|
||||
grub_uint8_t *key_data;
|
||||
+ /* recover_key: Length of key_data */
|
||||
grub_size_t key_len;
|
||||
};
|
||||
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
|
||||
@@ -125,8 +131,7 @@ struct grub_cryptodisk_dev
|
||||
struct grub_cryptodisk_dev *next;
|
||||
struct grub_cryptodisk_dev **prev;
|
||||
|
||||
- grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
|
||||
- int boot_only);
|
||||
+ grub_cryptodisk_t (*scan) (grub_disk_t disk, grub_cryptomount_args_t cargs);
|
||||
grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs);
|
||||
};
|
||||
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
|
@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Thu, 9 Dec 2021 11:14:58 -0600
|
||||
Subject: [PATCH] cryptodisk: Improve handling of partition name in cryptomount
|
||||
password prompt
|
||||
|
||||
Call grub_partition_get_name() unconditionally to initialize the part
|
||||
variable. Then part will only be NULL when grub_partition_get_name() errors.
|
||||
Note that when source->partition is NULL, then grub_partition_get_name()
|
||||
returns an allocated empty string. So no comma or partition will be printed,
|
||||
as desired.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 7ca8804..4970973 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1021,11 +1021,10 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
{
|
||||
/* Get the passphrase from the user, if no key data. */
|
||||
askpass = 1;
|
||||
- if (source->partition != NULL)
|
||||
- part = grub_partition_get_name (source->partition);
|
||||
+ part = grub_partition_get_name (source->partition);
|
||||
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||
source->partition != NULL ? "," : "",
|
||||
- part != NULL ? part : "",
|
||||
+ part != NULL ? part : N_("UNKNOWN"),
|
||||
dev->uuid);
|
||||
grub_free (part);
|
||||
|
72
0387-cryptodisk-Fix-Coverity-use-after-free-bug.patch
Normal file
72
0387-cryptodisk-Fix-Coverity-use-after-free-bug.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Sat, 1 Jan 2022 15:48:25 -0600
|
||||
Subject: [PATCH] cryptodisk: Fix Coverity use after free bug
|
||||
|
||||
The Coverity output is:
|
||||
|
||||
*** CID 366905: Memory - illegal accesses (USE_AFTER_FREE)
|
||||
/grub-core/disk/cryptodisk.c: 1064 in grub_cryptodisk_scan_device_real()
|
||||
1058 cleanup:
|
||||
1059 if (askpass)
|
||||
1060 {
|
||||
1061 cargs->key_len = 0;
|
||||
1062 grub_free (cargs->key_data);
|
||||
1063 }
|
||||
>>> CID 366905: Memory - illegal accesses (USE_AFTER_FREE)
|
||||
>>> Using freed pointer "dev".
|
||||
1064 return dev;
|
||||
1065 }
|
||||
1066
|
||||
1067 #ifdef GRUB_UTIL
|
||||
1068 #include <grub/util/misc.h>
|
||||
1069 grub_err_t
|
||||
|
||||
Here the "dev" variable can point to a freed cryptodisk device if the
|
||||
function grub_cryptodisk_insert() fails. This can happen only on a OOM
|
||||
condition, but when this happens grub_cryptodisk_insert() calls grub_free on
|
||||
the passed device. Since grub_cryptodisk_scan_device_real() assumes that
|
||||
grub_cryptodisk_insert() is always successful, it will return the device,
|
||||
though the device was freed.
|
||||
|
||||
Change grub_cryptodisk_insert() to not free the passed device on failure.
|
||||
Then on grub_cryptodisk_insert() failure, free the device pointer. This is
|
||||
done by going to the label "error", which will call cryptodisk_close() to
|
||||
free the device and set the device pointer to NULL, so that a pointer to
|
||||
freed memory is not returned.
|
||||
|
||||
Fixes: CID 366905
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 4970973..e7c4795 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -889,10 +889,7 @@ grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
|
||||
{
|
||||
newdev->source = grub_strdup (name);
|
||||
if (!newdev->source)
|
||||
- {
|
||||
- grub_free (newdev);
|
||||
- return grub_errno;
|
||||
- }
|
||||
+ return grub_errno;
|
||||
|
||||
newdev->id = last_cryptodisk_id++;
|
||||
newdev->source_id = source->id;
|
||||
@@ -1044,7 +1041,9 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
if (ret != GRUB_ERR_NONE)
|
||||
goto error;
|
||||
|
||||
- grub_cryptodisk_insert (dev, name, source);
|
||||
+ ret = grub_cryptodisk_insert (dev, name, source);
|
||||
+ if (ret != GRUB_ERR_NONE)
|
||||
+ goto error;
|
||||
|
||||
goto cleanup;
|
||||
}
|
155
0388-disk-cryptodisk-Add-options-to-cryptomount-to-suppor.patch
Normal file
155
0388-disk-cryptodisk-Add-options-to-cryptomount-to-suppor.patch
Normal file
@ -0,0 +1,155 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Lane <john@lane.uk.net>
|
||||
Date: Fri, 20 May 2022 14:32:17 -0500
|
||||
Subject: [PATCH] disk/cryptodisk: Add options to cryptomount to support
|
||||
keyfiles
|
||||
|
||||
Add the options --key-file, --keyfile-offset, and --keyfile-size to
|
||||
cryptomount and code to put read the requested key file data and pass
|
||||
via the cargs struct. Note, key file data is for all intents and purposes
|
||||
equivalent to a password given to cryptomount. So there is no need to
|
||||
enable support for key files in the various crypto backends (e.g. LUKS1)
|
||||
because the key data is passed just as if it were a password.
|
||||
|
||||
Signed-off-by: John Lane <john@lane.uk.net>
|
||||
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 81 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
include/grub/cryptodisk.h | 2 ++
|
||||
include/grub/file.h | 2 ++
|
||||
3 files changed, 84 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index e7c4795..0706afa 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -42,6 +42,9 @@ static const struct grub_arg_option options[] =
|
||||
{"all", 'a', 0, N_("Mount all."), 0, 0},
|
||||
{"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
|
||||
{"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING},
|
||||
+ {"key-file", 'k', 0, N_("Key file"), 0, ARG_TYPE_STRING},
|
||||
+ {"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
|
||||
+ {"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -1172,6 +1175,80 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
cargs.key_len = grub_strlen (state[3].arg);
|
||||
}
|
||||
|
||||
+ if (state[4].set) /* keyfile */
|
||||
+ {
|
||||
+ const char *p = NULL;
|
||||
+ grub_file_t keyfile;
|
||||
+ unsigned long long keyfile_offset = 0, keyfile_size = 0;
|
||||
+
|
||||
+ if (state[5].set) /* keyfile-offset */
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+ keyfile_offset = grub_strtoull (state[5].arg, &p, 0);
|
||||
+
|
||||
+ if (state[5].arg[0] == '\0' || *p != '\0')
|
||||
+ return grub_error (grub_errno,
|
||||
+ N_("non-numeric or invalid keyfile offset `%s'"),
|
||||
+ state[5].arg);
|
||||
+ }
|
||||
+
|
||||
+ if (state[6].set) /* keyfile-size */
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+ keyfile_size = grub_strtoull (state[6].arg, &p, 0);
|
||||
+
|
||||
+ if (state[6].arg[0] == '\0' || *p != '\0')
|
||||
+ return grub_error (grub_errno,
|
||||
+ N_("non-numeric or invalid keyfile size `%s'"),
|
||||
+ state[6].arg);
|
||||
+
|
||||
+ if (keyfile_size == 0)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("key file size is 0"));
|
||||
+
|
||||
+ if (keyfile_size > GRUB_CRYPTODISK_MAX_KEYFILE_SIZE)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ N_("key file size exceeds maximum (%d)"),
|
||||
+ GRUB_CRYPTODISK_MAX_KEYFILE_SIZE);
|
||||
+ }
|
||||
+
|
||||
+ keyfile = grub_file_open (state[4].arg,
|
||||
+ GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY);
|
||||
+ if (keyfile == NULL)
|
||||
+ return grub_errno;
|
||||
+
|
||||
+ if (keyfile_offset > keyfile->size)
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ N_("Keyfile offset, %llu, is greater than"
|
||||
+ "keyfile size, %" PRIuGRUB_UINT64_T),
|
||||
+ keyfile_offset, keyfile->size);
|
||||
+
|
||||
+ if (grub_file_seek (keyfile, (grub_off_t) keyfile_offset) == (grub_off_t) -1)
|
||||
+ return grub_errno;
|
||||
+
|
||||
+ if (keyfile_size != 0)
|
||||
+ {
|
||||
+ if (keyfile_size > (keyfile->size - keyfile_offset))
|
||||
+ return grub_error (GRUB_ERR_FILE_READ_ERROR,
|
||||
+ N_("keyfile is too small: requested %llu bytes,"
|
||||
+ " but the file only has %" PRIuGRUB_UINT64_T
|
||||
+ " bytes left at offset %llu"),
|
||||
+ keyfile_size,
|
||||
+ (grub_off_t) (keyfile->size - keyfile_offset),
|
||||
+ keyfile_offset);
|
||||
+
|
||||
+ cargs.key_len = keyfile_size;
|
||||
+ }
|
||||
+ else
|
||||
+ cargs.key_len = keyfile->size - keyfile_offset;
|
||||
+
|
||||
+ cargs.key_data = grub_malloc (cargs.key_len);
|
||||
+ if (cargs.key_data == NULL)
|
||||
+ return GRUB_ERR_OUT_OF_MEMORY;
|
||||
+
|
||||
+ if (grub_file_read (keyfile, cargs.key_data, cargs.key_len) != (grub_ssize_t) cargs.key_len)
|
||||
+ return grub_error (GRUB_ERR_FILE_READ_ERROR, (N_("failed to read key file")));
|
||||
+ }
|
||||
+
|
||||
if (state[0].set) /* uuid */
|
||||
{
|
||||
int found_uuid;
|
||||
@@ -1384,7 +1461,9 @@ GRUB_MOD_INIT (cryptodisk)
|
||||
{
|
||||
grub_disk_dev_register (&grub_cryptodisk_dev);
|
||||
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
|
||||
- N_("[-p password] <SOURCE|-u UUID|-a|-b>"),
|
||||
+ N_("[ [-p password] | [-k keyfile"
|
||||
+ " [-O keyoffset] [-S keysize] ] ]"
|
||||
+ " <SOURCE|-u UUID|-a|-b>"),
|
||||
N_("Mount a crypto device."), options);
|
||||
grub_procfs_register ("luks_script", &luks_script);
|
||||
}
|
||||
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
|
||||
index c6524c9..467065f 100644
|
||||
--- a/include/grub/cryptodisk.h
|
||||
+++ b/include/grub/cryptodisk.h
|
||||
@@ -61,6 +61,8 @@ typedef enum
|
||||
#define GRUB_CRYPTODISK_MAX_KEYLEN 128
|
||||
#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
|
||||
|
||||
+#define GRUB_CRYPTODISK_MAX_KEYFILE_SIZE 8192
|
||||
+
|
||||
struct grub_cryptodisk;
|
||||
|
||||
typedef gcry_err_code_t
|
||||
diff --git a/include/grub/file.h b/include/grub/file.h
|
||||
index 96827a4..2e9fff7 100644
|
||||
--- a/include/grub/file.h
|
||||
+++ b/include/grub/file.h
|
||||
@@ -92,6 +92,8 @@ enum grub_file_type
|
||||
GRUB_FILE_TYPE_FONT,
|
||||
/* File holding encryption key for encrypted ZFS. */
|
||||
GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
|
||||
+ /* File holding the encryption key. */
|
||||
+ GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY,
|
||||
/* File we open n grub-fstest. */
|
||||
GRUB_FILE_TYPE_FSTEST,
|
||||
/* File we open n grub-mount. */
|
140
0389-disk-cryptodisk-Use-enum-constants-as-indexes-into-c.patch
Normal file
140
0389-disk-cryptodisk-Use-enum-constants-as-indexes-into-c.patch
Normal file
@ -0,0 +1,140 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Fri, 20 May 2022 14:32:18 -0500
|
||||
Subject: [PATCH] disk/cryptodisk: Use enum constants as indexes into
|
||||
cryptomount option array
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 49 +++++++++++++++++++++++++++------------------
|
||||
1 file changed, 30 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 0706afa..9db5f65 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -35,6 +35,17 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
grub_cryptodisk_dev_t grub_cryptodisk_list;
|
||||
|
||||
+enum
|
||||
+ {
|
||||
+ OPTION_UUID,
|
||||
+ OPTION_ALL,
|
||||
+ OPTION_BOOT,
|
||||
+ OPTION_PASSWORD,
|
||||
+ OPTION_KEYFILE,
|
||||
+ OPTION_KEYFILE_OFFSET,
|
||||
+ OPTION_KEYFILE_SIZE
|
||||
+ };
|
||||
+
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
|
||||
@@ -1163,44 +1174,44 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
struct grub_cryptomount_args cargs = {0};
|
||||
|
||||
- if (argc < 1 && !state[1].set && !state[2].set)
|
||||
+ if (argc < 1 && !state[OPTION_ALL].set && !state[OPTION_BOOT].set)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
|
||||
if (grub_cryptodisk_list == NULL)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
|
||||
|
||||
- if (state[3].set) /* password */
|
||||
+ if (state[OPTION_PASSWORD].set) /* password */
|
||||
{
|
||||
- cargs.key_data = (grub_uint8_t *) state[3].arg;
|
||||
- cargs.key_len = grub_strlen (state[3].arg);
|
||||
+ cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg;
|
||||
+ cargs.key_len = grub_strlen (state[OPTION_PASSWORD].arg);
|
||||
}
|
||||
|
||||
- if (state[4].set) /* keyfile */
|
||||
+ if (state[OPTION_KEYFILE].set) /* keyfile */
|
||||
{
|
||||
const char *p = NULL;
|
||||
grub_file_t keyfile;
|
||||
unsigned long long keyfile_offset = 0, keyfile_size = 0;
|
||||
|
||||
- if (state[5].set) /* keyfile-offset */
|
||||
+ if (state[OPTION_KEYFILE_OFFSET].set) /* keyfile-offset */
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
- keyfile_offset = grub_strtoull (state[5].arg, &p, 0);
|
||||
+ keyfile_offset = grub_strtoull (state[OPTION_KEYFILE_OFFSET].arg, &p, 0);
|
||||
|
||||
- if (state[5].arg[0] == '\0' || *p != '\0')
|
||||
+ if (state[OPTION_KEYFILE_OFFSET].arg[0] == '\0' || *p != '\0')
|
||||
return grub_error (grub_errno,
|
||||
N_("non-numeric or invalid keyfile offset `%s'"),
|
||||
- state[5].arg);
|
||||
+ state[OPTION_KEYFILE_OFFSET].arg);
|
||||
}
|
||||
|
||||
- if (state[6].set) /* keyfile-size */
|
||||
+ if (state[OPTION_KEYFILE_SIZE].set) /* keyfile-size */
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
- keyfile_size = grub_strtoull (state[6].arg, &p, 0);
|
||||
+ keyfile_size = grub_strtoull (state[OPTION_KEYFILE_SIZE].arg, &p, 0);
|
||||
|
||||
- if (state[6].arg[0] == '\0' || *p != '\0')
|
||||
+ if (state[OPTION_KEYFILE_SIZE].arg[0] == '\0' || *p != '\0')
|
||||
return grub_error (grub_errno,
|
||||
N_("non-numeric or invalid keyfile size `%s'"),
|
||||
- state[6].arg);
|
||||
+ state[OPTION_KEYFILE_SIZE].arg);
|
||||
|
||||
if (keyfile_size == 0)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("key file size is 0"));
|
||||
@@ -1211,7 +1222,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
GRUB_CRYPTODISK_MAX_KEYFILE_SIZE);
|
||||
}
|
||||
|
||||
- keyfile = grub_file_open (state[4].arg,
|
||||
+ keyfile = grub_file_open (state[OPTION_KEYFILE].arg,
|
||||
GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY);
|
||||
if (keyfile == NULL)
|
||||
return grub_errno;
|
||||
@@ -1249,7 +1260,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR, (N_("failed to read key file")));
|
||||
}
|
||||
|
||||
- if (state[0].set) /* uuid */
|
||||
+ if (state[OPTION_UUID].set) /* uuid */
|
||||
{
|
||||
int found_uuid;
|
||||
grub_cryptodisk_t dev;
|
||||
@@ -1262,7 +1273,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
- cargs.check_boot = state[2].set;
|
||||
+ cargs.check_boot = state[OPTION_BOOT].set;
|
||||
cargs.search_uuid = args[0];
|
||||
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||
|
||||
@@ -1280,9 +1291,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
||||
- else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
|
||||
+ else if (state[OPTION_ALL].set || (argc == 0 && state[OPTION_BOOT].set)) /* -a|-b */
|
||||
{
|
||||
- cargs.check_boot = state[2].set;
|
||||
+ cargs.check_boot = state[OPTION_BOOT].set;
|
||||
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
@@ -1294,7 +1305,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
char *disklast = NULL;
|
||||
grub_size_t len;
|
||||
|
||||
- cargs.check_boot = state[2].set;
|
||||
+ cargs.check_boot = state[OPTION_BOOT].set;
|
||||
diskname = args[0];
|
||||
len = grub_strlen (diskname);
|
||||
if (len && diskname[0] == '(' && diskname[len - 1] == ')')
|
259
0390-cryptodisk-Add-support-for-using-detached-header-fil.patch
Normal file
259
0390-cryptodisk-Add-support-for-using-detached-header-fil.patch
Normal file
@ -0,0 +1,259 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Wed, 8 Jun 2022 10:34:03 -0500
|
||||
Subject: [PATCH] cryptodisk: Add support for using detached header files
|
||||
|
||||
Using the disk read hook mechanism, setup a read hook on the source disk
|
||||
which will read from the given header file during the scan and recovery
|
||||
cryptodisk backend functions. Disk read hooks are executed after the data
|
||||
has been read from the disk. This is okay, because the read hook is given
|
||||
the read buffer before its sent back to the caller. In this case, the hook
|
||||
can then overwrite the data read from the disk device with data from the
|
||||
header file sent in as the read hook data. This is transparent to the
|
||||
read caller. Since the callers of this function have just opened the
|
||||
source disk, there are no current read hooks, so there's no need to
|
||||
save/restore them nor consider if they should be called or not.
|
||||
|
||||
This hook assumes that the header is at the start of the volume, which
|
||||
is not the case for some formats (e.g. GELI). So GELI will return an
|
||||
error if a detached header is specified. It also can only be used
|
||||
with formats where the detached header file can be written to the
|
||||
first blocks of the volume and the volume could still be unlocked.
|
||||
So the header file can not be formatted differently from the on-disk
|
||||
header. If these assumpts are not met, detached header file processing
|
||||
must be specially handled in the cryptodisk backend module.
|
||||
|
||||
The hook will be called potentially many times by a backend. This is fine
|
||||
because of the assumptions mentioned and the read hook reads from absolute
|
||||
offsets and is stateless.
|
||||
|
||||
Also add a --header (short -H) option to cryptomount which takes a file
|
||||
argument.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Patrick Steinhardt <ps@pks.im>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 92 +++++++++++++++++++++++++++++++++++++++++++--
|
||||
grub-core/disk/geli.c | 4 ++
|
||||
include/grub/cryptodisk.h | 2 +
|
||||
include/grub/file.h | 2 +
|
||||
4 files changed, 96 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 9db5f65..3d8472e 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -43,7 +43,8 @@ enum
|
||||
OPTION_PASSWORD,
|
||||
OPTION_KEYFILE,
|
||||
OPTION_KEYFILE_OFFSET,
|
||||
- OPTION_KEYFILE_SIZE
|
||||
+ OPTION_KEYFILE_SIZE,
|
||||
+ OPTION_HEADER
|
||||
};
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
@@ -56,9 +57,16 @@ static const struct grub_arg_option options[] =
|
||||
{"key-file", 'k', 0, N_("Key file"), 0, ARG_TYPE_STRING},
|
||||
{"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
|
||||
{"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT},
|
||||
+ {"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
+struct cryptodisk_read_hook_ctx
|
||||
+{
|
||||
+ grub_file_t hdr_file;
|
||||
+};
|
||||
+typedef struct cryptodisk_read_hook_ctx *cryptodisk_read_hook_ctx_t;
|
||||
+
|
||||
/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */
|
||||
#define GF_POLYNOM 0x87
|
||||
static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev)
|
||||
@@ -1004,6 +1012,30 @@ cryptodisk_close (grub_cryptodisk_t dev)
|
||||
grub_free (dev);
|
||||
}
|
||||
|
||||
+static grub_err_t
|
||||
+cryptodisk_read_hook (grub_disk_addr_t sector, unsigned offset,
|
||||
+ unsigned length, char *buf, void *data)
|
||||
+{
|
||||
+ cryptodisk_read_hook_ctx_t ctx = data;
|
||||
+
|
||||
+ if (ctx->hdr_file == NULL)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("header file not found"));
|
||||
+
|
||||
+ if (grub_file_seek (ctx->hdr_file,
|
||||
+ (sector * GRUB_DISK_SECTOR_SIZE) + offset)
|
||||
+ == (grub_off_t) -1)
|
||||
+ return grub_errno;
|
||||
+
|
||||
+ if (grub_file_read (ctx->hdr_file, buf, length) != (grub_ssize_t) length)
|
||||
+ {
|
||||
+ if (grub_errno == GRUB_ERR_NONE)
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("header file too small"));
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
static grub_cryptodisk_t
|
||||
grub_cryptodisk_scan_device_real (const char *name,
|
||||
grub_disk_t source,
|
||||
@@ -1012,6 +1044,7 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
grub_err_t ret = GRUB_ERR_NONE;
|
||||
grub_cryptodisk_t dev;
|
||||
grub_cryptodisk_dev_t cr;
|
||||
+ struct cryptodisk_read_hook_ctx read_hook_data = {0};
|
||||
int askpass = 0;
|
||||
char *part = NULL;
|
||||
|
||||
@@ -1020,11 +1053,46 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
+ if (cargs->hdr_file != NULL)
|
||||
+ {
|
||||
+ /*
|
||||
+ * Set read hook to read header from a file instead of the source disk.
|
||||
+ * Disk read hooks are executed after the data has been read from the
|
||||
+ * disk. This is okay, because the read hook is given the read buffer
|
||||
+ * before its sent back to the caller. In this case, the hook can then
|
||||
+ * overwrite the data read from the disk device with data from the
|
||||
+ * header file sent in as the read hook data. This is transparent to the
|
||||
+ * read caller. Since the callers of this function have just opened the
|
||||
+ * source disk, there are no current read hooks, so there's no need to
|
||||
+ * save/restore them nor consider if they should be called or not.
|
||||
+ *
|
||||
+ * This hook assumes that the header is at the start of the volume, which
|
||||
+ * is not the case for some formats (eg. GELI). It also can only be used
|
||||
+ * with formats where the detached header file can be written to the
|
||||
+ * first blocks of the volume and the volume could still be unlocked.
|
||||
+ * So the header file can not be formatted differently from the on-disk
|
||||
+ * header. If these assumpts are not met, detached header file processing
|
||||
+ * must be specially handled in the cryptodisk backend module.
|
||||
+ *
|
||||
+ * This hook needs only be set once and will be called potentially many
|
||||
+ * times by a backend. This is fine because of the assumptions mentioned
|
||||
+ * and the read hook reads from absolute offsets and is stateless.
|
||||
+ */
|
||||
+ read_hook_data.hdr_file = cargs->hdr_file;
|
||||
+ source->read_hook = cryptodisk_read_hook;
|
||||
+ source->read_hook_data = (void *) &read_hook_data;
|
||||
+ }
|
||||
+
|
||||
FOR_CRYPTODISK_DEVS (cr)
|
||||
{
|
||||
+ /*
|
||||
+ * Loop through each cryptodisk backend that is registered (ie. loaded).
|
||||
+ * If the scan returns NULL, then the backend being tested does not
|
||||
+ * recognize the source disk, so move on to the next backend.
|
||||
+ */
|
||||
dev = cr->scan (source, cargs);
|
||||
if (grub_errno)
|
||||
- return NULL;
|
||||
+ goto error_no_close;
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
@@ -1041,7 +1109,7 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
|
||||
cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
|
||||
if (cargs->key_data == NULL)
|
||||
- return NULL;
|
||||
+ goto error_no_close;
|
||||
|
||||
if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
|
||||
{
|
||||
@@ -1066,9 +1134,13 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
|
||||
error:
|
||||
cryptodisk_close (dev);
|
||||
+ error_no_close:
|
||||
dev = NULL;
|
||||
|
||||
cleanup:
|
||||
+ if (cargs->hdr_file != NULL)
|
||||
+ source->read_hook = NULL;
|
||||
+
|
||||
if (askpass)
|
||||
{
|
||||
cargs->key_len = 0;
|
||||
@@ -1260,6 +1332,18 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR, (N_("failed to read key file")));
|
||||
}
|
||||
|
||||
+ if (state[OPTION_HEADER].set) /* header */
|
||||
+ {
|
||||
+ if (state[OPTION_UUID].set)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("cannot use UUID lookup with detached header"));
|
||||
+
|
||||
+ cargs.hdr_file = grub_file_open (state[OPTION_HEADER].arg,
|
||||
+ GRUB_FILE_TYPE_CRYPTODISK_DETACHED_HEADER);
|
||||
+ if (cargs.hdr_file == NULL)
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+
|
||||
if (state[OPTION_UUID].set) /* uuid */
|
||||
{
|
||||
int found_uuid;
|
||||
@@ -1473,7 +1557,7 @@ GRUB_MOD_INIT (cryptodisk)
|
||||
grub_disk_dev_register (&grub_cryptodisk_dev);
|
||||
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
|
||||
N_("[ [-p password] | [-k keyfile"
|
||||
- " [-O keyoffset] [-S keysize] ] ]"
|
||||
+ " [-O keyoffset] [-S keysize] ] ] [-H file]"
|
||||
" <SOURCE|-u UUID|-a|-b>"),
|
||||
N_("Mount a crypto device."), options);
|
||||
grub_procfs_register ("luks_script", &luks_script);
|
||||
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
|
||||
index 23789c4..52dd504 100644
|
||||
--- a/grub-core/disk/geli.c
|
||||
+++ b/grub-core/disk/geli.c
|
||||
@@ -252,6 +252,10 @@ configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
grub_disk_addr_t sector;
|
||||
grub_err_t err;
|
||||
|
||||
+ /* Detached headers are not implemented yet */
|
||||
+ if (cargs->hdr_file != NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
|
||||
return NULL;
|
||||
|
||||
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
|
||||
index 467065f..d94df68 100644
|
||||
--- a/include/grub/cryptodisk.h
|
||||
+++ b/include/grub/cryptodisk.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#define GRUB_CRYPTODISK_HEADER 1
|
||||
|
||||
#include <grub/disk.h>
|
||||
+#include <grub/file.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/list.h>
|
||||
#ifdef GRUB_UTIL
|
||||
@@ -79,6 +80,7 @@ struct grub_cryptomount_args
|
||||
grub_uint8_t *key_data;
|
||||
/* recover_key: Length of key_data */
|
||||
grub_size_t key_len;
|
||||
+ grub_file_t hdr_file;
|
||||
};
|
||||
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
|
||||
|
||||
diff --git a/include/grub/file.h b/include/grub/file.h
|
||||
index 2e9fff7..d678de0 100644
|
||||
--- a/include/grub/file.h
|
||||
+++ b/include/grub/file.h
|
||||
@@ -94,6 +94,8 @@ enum grub_file_type
|
||||
GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
|
||||
/* File holding the encryption key. */
|
||||
GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY,
|
||||
+ /* File holding the encryption metadata header */
|
||||
+ GRUB_FILE_TYPE_CRYPTODISK_DETACHED_HEADER,
|
||||
/* File we open n grub-fstest. */
|
||||
GRUB_FILE_TYPE_FSTEST,
|
||||
/* File we open n grub-mount. */
|
@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Sun, 7 Aug 2022 00:18:52 -0500
|
||||
Subject: [PATCH] disk/cryptodisk: Support encrypted volumes using detached
|
||||
headers on a partition
|
||||
|
||||
Update the read hook to take into account encrypted volumes on a partition.
|
||||
GRUB disk read hooks supply an absolute sector number at which the read is
|
||||
started from. If the encrypted volume is in a partition, the sector number
|
||||
given to the read hook will be offset by the number of the sector at the
|
||||
start of the partition. The read hook then needs to subtract the partition
|
||||
start from the supplied sector to get the correct start sector for the read
|
||||
into the detached header file.
|
||||
|
||||
Reported-by: brutser <brutser@perso.be>
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Tested-by: brutser <brutser@perso.be>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 3d8472e..42370db 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -64,6 +64,7 @@ static const struct grub_arg_option options[] =
|
||||
struct cryptodisk_read_hook_ctx
|
||||
{
|
||||
grub_file_t hdr_file;
|
||||
+ grub_disk_addr_t part_start;
|
||||
};
|
||||
typedef struct cryptodisk_read_hook_ctx *cryptodisk_read_hook_ctx_t;
|
||||
|
||||
@@ -1022,7 +1023,7 @@ cryptodisk_read_hook (grub_disk_addr_t sector, unsigned offset,
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("header file not found"));
|
||||
|
||||
if (grub_file_seek (ctx->hdr_file,
|
||||
- (sector * GRUB_DISK_SECTOR_SIZE) + offset)
|
||||
+ ((sector - ctx->part_start) * GRUB_DISK_SECTOR_SIZE) + offset)
|
||||
== (grub_off_t) -1)
|
||||
return grub_errno;
|
||||
|
||||
@@ -1078,6 +1079,7 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
* times by a backend. This is fine because of the assumptions mentioned
|
||||
* and the read hook reads from absolute offsets and is stateless.
|
||||
*/
|
||||
+ read_hook_data.part_start = grub_partition_get_start (source->partition);
|
||||
read_hook_data.hdr_file = cargs->hdr_file;
|
||||
source->read_hook = cryptodisk_read_hook;
|
||||
source->read_hook_data = (void *) &read_hook_data;
|
200
0392-disk-cryptodisk-Allows-UUIDs-to-be-compared-in-a-das.patch
Normal file
200
0392-disk-cryptodisk-Allows-UUIDs-to-be-compared-in-a-das.patch
Normal file
@ -0,0 +1,200 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Fri, 19 Aug 2022 18:06:15 -0500
|
||||
Subject: [PATCH] disk/cryptodisk: Allows UUIDs to be compared in a
|
||||
dash-insensitive manner
|
||||
|
||||
A user can now specify UUID strings with dashes, instead of having to remove
|
||||
dashes. This is backwards-compatibility preserving and also fixes a source
|
||||
of user confusion over the inconsistency with how UUIDs are specified
|
||||
between file system UUIDs and cryptomount UUIDs. Since cryptsetup, the
|
||||
reference implementation for LUKS, displays and generates UUIDs with dashes
|
||||
there has been additional confusion when using the UUID strings from
|
||||
cryptsetup as exact input into GRUB does not find the expected cryptodisk.
|
||||
|
||||
A new function grub_uuidcasecmp() is added that is general enough to be used
|
||||
other places where UUIDs are being compared.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Patrick Steinhardt <ps@pks.im>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 4 ++--
|
||||
grub-core/disk/geli.c | 2 +-
|
||||
grub-core/disk/luks.c | 21 ++++-----------------
|
||||
grub-core/disk/luks2.c | 15 ++++-----------
|
||||
include/grub/misc.h | 30 ++++++++++++++++++++++++++++++
|
||||
5 files changed, 41 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 42370db..17b5034 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -702,7 +702,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
|
||||
if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
|
||||
{
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
- if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0)
|
||||
+ if (grub_uuidcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid, sizeof (dev->uuid)) == 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -929,7 +929,7 @@ grub_cryptodisk_get_by_uuid (const char *uuid)
|
||||
{
|
||||
grub_cryptodisk_t dev;
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
- if (grub_strcasecmp (dev->uuid, uuid) == 0)
|
||||
+ if (grub_uuidcasecmp (dev->uuid, uuid, sizeof (dev->uuid)) == 0)
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
|
||||
index 52dd504..bd18b19 100644
|
||||
--- a/grub-core/disk/geli.c
|
||||
+++ b/grub-core/disk/geli.c
|
||||
@@ -305,7 +305,7 @@ configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
|
||||
+ if (cargs->search_uuid != NULL && grub_uuidcasecmp (cargs->search_uuid, uuid, sizeof (uuid)) != 0)
|
||||
{
|
||||
grub_dprintf ("geli", "%s != %s\n", uuid, cargs->search_uuid);
|
||||
return NULL;
|
||||
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
|
||||
index f0feb38..f6a0cbc 100644
|
||||
--- a/grub-core/disk/luks.c
|
||||
+++ b/grub-core/disk/luks.c
|
||||
@@ -66,10 +66,7 @@ static grub_cryptodisk_t
|
||||
configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_cryptodisk_t newdev;
|
||||
- const char *iptr;
|
||||
struct grub_luks_phdr header;
|
||||
- char *optr;
|
||||
- char uuid[sizeof (header.uuid) + 1];
|
||||
char ciphername[sizeof (header.cipherName) + 1];
|
||||
char ciphermode[sizeof (header.cipherMode) + 1];
|
||||
char hashspec[sizeof (header.hashSpec) + 1];
|
||||
@@ -92,19 +89,9 @@ configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
|| grub_be_to_cpu16 (header.version) != 1)
|
||||
return NULL;
|
||||
|
||||
- grub_memset (uuid, 0, sizeof (uuid));
|
||||
- optr = uuid;
|
||||
- for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)];
|
||||
- iptr++)
|
||||
+ if (cargs->search_uuid != NULL && grub_uuidcasecmp (cargs->search_uuid, header.uuid, sizeof (header.uuid)) != 0)
|
||||
{
|
||||
- if (*iptr != '-')
|
||||
- *optr++ = *iptr;
|
||||
- }
|
||||
- *optr = 0;
|
||||
-
|
||||
- if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
|
||||
- {
|
||||
- grub_dprintf ("luks", "%s != %s\n", uuid, cargs->search_uuid);
|
||||
+ grub_dprintf ("luks", "%s != %s\n", header.uuid, cargs->search_uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -123,7 +110,7 @@ configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
newdev->source_disk = NULL;
|
||||
newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
|
||||
newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
|
||||
- grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
|
||||
+ grub_memcpy (newdev->uuid, header.uuid, sizeof (header.uuid));
|
||||
newdev->modname = "luks";
|
||||
|
||||
/* Configure the hash used for the AF splitter and HMAC. */
|
||||
@@ -143,7 +130,7 @@ configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
|
||||
+ COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (header.uuid));
|
||||
return newdev;
|
||||
}
|
||||
|
||||
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
|
||||
index bf741d7..ac3ab09 100644
|
||||
--- a/grub-core/disk/luks2.c
|
||||
+++ b/grub-core/disk/luks2.c
|
||||
@@ -350,8 +350,6 @@ luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
{
|
||||
grub_cryptodisk_t cryptodisk;
|
||||
grub_luks2_header_t header;
|
||||
- char uuid[sizeof (header.uuid) + 1];
|
||||
- grub_size_t i, j;
|
||||
|
||||
if (cargs->check_boot)
|
||||
return NULL;
|
||||
@@ -362,14 +360,9 @@ luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- for (i = 0, j = 0; i < sizeof (header.uuid); i++)
|
||||
- if (header.uuid[i] != '-')
|
||||
- uuid[j++] = header.uuid[i];
|
||||
- uuid[j] = '\0';
|
||||
-
|
||||
- if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
|
||||
+ if (cargs->search_uuid != NULL && grub_uuidcasecmp (cargs->search_uuid, header.uuid, sizeof (header.uuid)) != 0)
|
||||
{
|
||||
- grub_dprintf ("luks2", "%s != %s\n", uuid, cargs->search_uuid);
|
||||
+ grub_dprintf ("luks2", "%s != %s\n", header.uuid, cargs->search_uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -377,8 +370,8 @@ luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs)
|
||||
if (!cryptodisk)
|
||||
return NULL;
|
||||
|
||||
- COMPILE_TIME_ASSERT (sizeof (cryptodisk->uuid) >= sizeof (uuid));
|
||||
- grub_memcpy (cryptodisk->uuid, uuid, sizeof (uuid));
|
||||
+ COMPILE_TIME_ASSERT (sizeof (cryptodisk->uuid) >= sizeof (header.uuid));
|
||||
+ grub_memcpy (cryptodisk->uuid, header.uuid, sizeof (header.uuid));
|
||||
|
||||
cryptodisk->modname = "luks2";
|
||||
return cryptodisk;
|
||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
|
||||
index 8c0ffed..fae4910 100644
|
||||
--- a/include/grub/misc.h
|
||||
+++ b/include/grub/misc.h
|
||||
@@ -290,6 +290,36 @@ grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
|
||||
- (int) grub_tolower ((grub_uint8_t) *s2);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Do a case insensitive compare of two UUID strings by ignoring all dashes.
|
||||
+ * Note that the parameter n, is the number of significant characters to
|
||||
+ * compare, where significant characters are any except the dash.
|
||||
+ */
|
||||
+static inline int
|
||||
+grub_uuidcasecmp (const char *uuid1, const char *uuid2, grub_size_t n)
|
||||
+{
|
||||
+ if (n == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ while (*uuid1 && *uuid2 && --n)
|
||||
+ {
|
||||
+ /* Skip forward to non-dash on both UUIDs. */
|
||||
+ while ('-' == *uuid1)
|
||||
+ ++uuid1;
|
||||
+
|
||||
+ while ('-' == *uuid2)
|
||||
+ ++uuid2;
|
||||
+
|
||||
+ if (grub_tolower ((grub_uint8_t) *uuid1) != grub_tolower ((grub_uint8_t) *uuid2))
|
||||
+ break;
|
||||
+
|
||||
+ uuid1++;
|
||||
+ uuid2++;
|
||||
+ }
|
||||
+
|
||||
+ return (int) grub_tolower ((grub_uint8_t) *uuid1) - (int) grub_tolower ((grub_uint8_t) *uuid2);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Note that these differ from the C standard's definitions of strtol,
|
||||
* strtoul(), and strtoull() by the addition of two const qualifiers on the end
|
@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Fri, 14 Oct 2022 17:47:08 -0400
|
||||
Subject: [PATCH] disk/cryptodisk: Fix unintentional integer overflow
|
||||
|
||||
In the function grub_cryptodisk_endecrypt(), a for loop is incrementing the
|
||||
variable i by (1U << log_sector_size). The variable i is of type grub_size_t
|
||||
which is a 64-bit unsigned integer on x86_64 architecture. On the other hand, 1U
|
||||
is a 32-bit unsigned integer. By performing a left shift on a 32-bit value and
|
||||
assigning it to a 64-bit variable, the 64-bit variable may have incorrect values
|
||||
in the high 32-bits if the shift has an overflow. To avoid this, we replace 1U
|
||||
with (grub_size_t)1.
|
||||
|
||||
Fixes: CID 307788
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Patrick Steinhardt <ps@pks.im>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 17b5034..e23c618 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -262,7 +262,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
|
||||
return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
|
||||
: grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
|
||||
|
||||
- for (i = 0; i < len; i += (1U << log_sector_size))
|
||||
+ for (i = 0; i < len; i += ((grub_size_t) 1 << log_sector_size))
|
||||
{
|
||||
grub_size_t sz = ((dev->cipher->cipher->blocksize
|
||||
+ sizeof (grub_uint32_t) - 1)
|
@ -0,0 +1,73 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Fabian Vogt <fvogt@suse.de>
|
||||
Date: Thu, 12 Jan 2023 17:05:07 -0600
|
||||
Subject: [PATCH] disk/cryptodisk: When cheatmounting, use the sector info of
|
||||
the cheat device
|
||||
|
||||
When using grub-probe with cryptodisk, the mapped block device from the host
|
||||
is used directly instead of decrypting the source device in GRUB code.
|
||||
In that case, the sector size and count of the host device needs to be used.
|
||||
This is especially important when using LUKS2, which does not assign
|
||||
total_sectors and log_sector_size when scanning, but only later when the
|
||||
segments in the JSON area are evaluated. With an unset log_sector_size,
|
||||
grub_device_open() complains.
|
||||
|
||||
This fixes grub-probe failing with
|
||||
"error: sector sizes of 1 bytes aren't supported yet.".
|
||||
|
||||
Signed-off-by: Fabian Vogt <fvogt@suse.de>
|
||||
Reviewed-by: Patrick Steinhardt <ps@pks.im>
|
||||
Tested-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Patrick Steinhardt <ps@pks.im>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 20 ++++++++++++++++++--
|
||||
1 file changed, 18 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index e23c618..2384792 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -718,16 +718,31 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
|
||||
if (!dev)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
|
||||
|
||||
- disk->log_sector_size = dev->log_sector_size;
|
||||
-
|
||||
#ifdef GRUB_UTIL
|
||||
if (dev->cheat)
|
||||
{
|
||||
+ grub_uint64_t cheat_dev_size;
|
||||
+ unsigned int cheat_log_sector_size;
|
||||
+
|
||||
if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd))
|
||||
dev->cheat_fd = grub_util_fd_open (dev->cheat, GRUB_UTIL_FD_O_RDONLY);
|
||||
if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd))
|
||||
return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"),
|
||||
dev->cheat, grub_util_fd_strerror ());
|
||||
+
|
||||
+ /* Use the sector size and count of the cheat device. */
|
||||
+ cheat_dev_size = grub_util_get_fd_size (dev->cheat_fd, dev->cheat, &cheat_log_sector_size);
|
||||
+ if (cheat_dev_size == -1)
|
||||
+ {
|
||||
+ const char *errmsg = grub_util_fd_strerror ();
|
||||
+ grub_util_fd_close (dev->cheat_fd);
|
||||
+ dev->cheat_fd = GRUB_UTIL_FD_INVALID;
|
||||
+ return grub_error (GRUB_ERR_IO, N_("failed to query size of device `%s': %s"),
|
||||
+ dev->cheat, errmsg);
|
||||
+ }
|
||||
+
|
||||
+ dev->log_sector_size = cheat_log_sector_size;
|
||||
+ dev->total_sectors = cheat_dev_size >> cheat_log_sector_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -741,6 +756,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
|
||||
}
|
||||
|
||||
disk->data = dev;
|
||||
+ disk->log_sector_size = dev->log_sector_size;
|
||||
disk->total_sectors = dev->total_sectors;
|
||||
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
|
||||
disk->id = dev->id;
|
@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Fri, 18 Aug 2023 12:27:22 -0500
|
||||
Subject: [PATCH] disk/cryptodisk: Fix missing change when updating to use
|
||||
grub_uuidcasecmp()
|
||||
|
||||
This was causing the cryptomount command to return failure even though
|
||||
the crypto device was successfully added. Of course, this meant that any
|
||||
script using the return code would behave unexpectedly.
|
||||
|
||||
Fixes: 3cf2e848bc03 (disk/cryptodisk: Allows UUIDs to be compared in a dash-insensitive manner)
|
||||
|
||||
Suggested-by: Olaf Hering <olaf@aepfle.de>
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Patrich Steinhardt <ps@pks.im>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 2384792..bbe39a8 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1236,7 +1236,8 @@ grub_cryptodisk_scan_device (const char *name,
|
||||
dev = grub_cryptodisk_scan_device_real (name, source, cargs);
|
||||
if (dev)
|
||||
{
|
||||
- ret = (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, dev->uuid) == 0);
|
||||
+ ret = (cargs->search_uuid != NULL
|
||||
+ && grub_uuidcasecmp (cargs->search_uuid, dev->uuid, sizeof (dev->uuid)) == 0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
34
0396-disk-cryptodisk-Optimize-luks_script_get.patch
Normal file
34
0396-disk-cryptodisk-Optimize-luks_script_get.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Fri, 14 Jul 2023 15:49:17 -0500
|
||||
Subject: [PATCH] disk/cryptodisk: Optimize luks_script_get()
|
||||
|
||||
Use the return value of grub_snprintf() to move the string pointer forward,
|
||||
instead of incrementing the string pointer iteratively until a NULL byte is
|
||||
reached. Move the space out of the format string argument, a small
|
||||
optimization, but also makes the spacing clearer. Also, use the new
|
||||
PRIxGRUB_OFFSET instead of PRIuGRUB_UINT64_T to accurately reflect the
|
||||
format string for this type.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index bbe39a8..751fe9b 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1504,9 +1504,8 @@ luks_script_get (grub_size_t *sz)
|
||||
ptr = grub_stpcpy (ptr, "luks_mount ");
|
||||
ptr = grub_stpcpy (ptr, i->uuid);
|
||||
*ptr++ = ' ';
|
||||
- grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
|
||||
- while (*ptr)
|
||||
- ptr++;
|
||||
+ ptr += grub_snprintf (ptr, 21, "%" PRIxGRUB_OFFSET, i->offset_sectors);
|
||||
+ *ptr++ = ' ';
|
||||
for (iptr = i->cipher->cipher->name; *iptr; iptr++)
|
||||
*ptr++ = grub_tolower (*iptr);
|
||||
switch (i->mode)
|
@ -0,0 +1,69 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Fri, 14 Jul 2023 15:49:18 -0500
|
||||
Subject: [PATCH] disk/cryptodisk: Add support for LUKS2 in (proc)/luks_script
|
||||
|
||||
The sector size in bytes is added to each line and it is allowed to be
|
||||
6 decimal digits long, which covers the most common cases of 512 and 4096
|
||||
byte sectors with space for two additional digits as future-proofing. The
|
||||
size allocation is updated to reflect this additional field. Also make
|
||||
clearer the size allocation calculation.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 24 +++++++++++++++++++-----
|
||||
1 file changed, 19 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 751fe9b..49af8a9 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1479,12 +1479,22 @@ luks_script_get (grub_size_t *sz)
|
||||
*sz = 0;
|
||||
|
||||
for (i = cryptodisk_list; i != NULL; i = i->next)
|
||||
- if (grub_strcmp (i->modname, "luks") == 0)
|
||||
+ if (grub_strcmp (i->modname, "luks") == 0 ||
|
||||
+ grub_strcmp (i->modname, "luks2") == 0)
|
||||
{
|
||||
- size += sizeof ("luks_mount ");
|
||||
+ size += grub_strlen (i->modname);
|
||||
+ size += sizeof ("_mount");
|
||||
size += grub_strlen (i->uuid);
|
||||
size += grub_strlen (i->cipher->cipher->name);
|
||||
- size += 54;
|
||||
+ /*
|
||||
+ * Add space in the line for (in order) spaces, cipher mode, cipher IV
|
||||
+ * mode, sector offset, sector size and the trailing newline. This is
|
||||
+ * an upper bound on the size of this data. There are 15 extra bytes
|
||||
+ * in an earlier version of this code that are unaccounted for. It is
|
||||
+ * left in the calculations in case it is needed. At worst, its short-
|
||||
+ * lived wasted space.
|
||||
+ */
|
||||
+ size += 5 + 5 + 8 + 20 + 6 + 1 + 15;
|
||||
if (i->essiv_hash)
|
||||
size += grub_strlen (i->essiv_hash->name);
|
||||
size += i->keysize * 2;
|
||||
@@ -1497,15 +1507,19 @@ luks_script_get (grub_size_t *sz)
|
||||
ptr = ret;
|
||||
|
||||
for (i = cryptodisk_list; i != NULL; i = i->next)
|
||||
- if (grub_strcmp (i->modname, "luks") == 0)
|
||||
+ if (grub_strcmp (i->modname, "luks") == 0 ||
|
||||
+ grub_strcmp (i->modname, "luks2") == 0)
|
||||
{
|
||||
unsigned j;
|
||||
const char *iptr;
|
||||
- ptr = grub_stpcpy (ptr, "luks_mount ");
|
||||
+ ptr = grub_stpcpy (ptr, i->modname);
|
||||
+ ptr = grub_stpcpy (ptr, "_mount ");
|
||||
ptr = grub_stpcpy (ptr, i->uuid);
|
||||
*ptr++ = ' ';
|
||||
ptr += grub_snprintf (ptr, 21, "%" PRIxGRUB_OFFSET, i->offset_sectors);
|
||||
*ptr++ = ' ';
|
||||
+ ptr += grub_snprintf (ptr, 7, "%u", 1 << i->log_sector_size);
|
||||
+ *ptr++ = ' ';
|
||||
for (iptr = i->cipher->cipher->name; *iptr; iptr++)
|
||||
*ptr++ = grub_tolower (*iptr);
|
||||
switch (i->mode)
|
337
0398-disk-cryptodisk-Require-authentication-after-TPM-unl.patch
Normal file
337
0398-disk-cryptodisk-Require-authentication-after-TPM-unl.patch
Normal file
@ -0,0 +1,337 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Tue, 11 Feb 2025 15:08:06 -0600
|
||||
Subject: [PATCH] disk/cryptodisk: Require authentication after TPM unlock for
|
||||
CLI access
|
||||
|
||||
The GRUB may use TPM to verify the integrity of boot components and the
|
||||
result can determine whether a previously sealed key can be released. If
|
||||
everything checks out, showing nothing has been tampered with, the key
|
||||
is released and GRUB unlocks the encrypted root partition for the next
|
||||
stage of booting.
|
||||
|
||||
However, the liberal Command Line Interface (CLI) can be misused by
|
||||
anyone in this case to access files in the encrypted partition one way
|
||||
or another. Despite efforts to keep the CLI secure by preventing utility
|
||||
command output from leaking file content, many techniques in the wild
|
||||
could still be used to exploit the CLI, enabling attacks or learning
|
||||
methods to attack. It's nearly impossible to account for all scenarios
|
||||
where a hack could be applied.
|
||||
|
||||
Therefore, to mitigate potential misuse of the CLI after the root device
|
||||
has been successfully unlocked via TPM, the user should be required to
|
||||
authenticate using the LUKS password. This added layer of security
|
||||
ensures that only authorized users can access the CLI reducing the risk
|
||||
of exploitation or unauthorized access to the encrypted partition.
|
||||
|
||||
Fixes: CVE-2024-49504
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
docs/grub.texi | 29 +++++++++++++++
|
||||
grub-core/disk/cryptodisk.c | 87 ++++++++++++++++++++++++++++++++++++++++++-
|
||||
grub-core/kern/main.c | 12 ++++++
|
||||
grub-core/normal/auth.c | 30 +++++++++++++++
|
||||
grub-core/normal/main.c | 4 ++
|
||||
grub-core/normal/menu_entry.c | 4 ++
|
||||
include/grub/auth.h | 1 +
|
||||
include/grub/cryptodisk.h | 3 ++
|
||||
include/grub/misc.h | 2 +
|
||||
9 files changed, 171 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index 3c7d99e..d3faecb 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -6312,6 +6312,35 @@ sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
|
||||
As with UEFI secure boot, it is necessary to build in the required modules,
|
||||
or sign them separately.
|
||||
|
||||
+@subsection Command line and menuentry editor protection
|
||||
+
|
||||
+The TPM key protector provides full disk encryption support on servers or
|
||||
+virtual machine images, meanwhile keeping the boot process unattended. This
|
||||
+prevents service disruptions by eliminating the need for manual password input
|
||||
+during startup, improving system uptime and continuity. It is achieved by TPM,
|
||||
+which verifies the integrity of boot components by checking cryptographic
|
||||
+hashes against securely stored values, to confirm the disks are unlocked in a
|
||||
+trusted state.
|
||||
+
|
||||
+However, for users to access the system interactively, some form of
|
||||
+authentication is still required, as the disks are not unlocked by an
|
||||
+authorized user. This raised concerns about using an unprotected
|
||||
+@samp{command-line interface} (@pxref{Command-line interface}), as anyone could
|
||||
+execute commands to access decrypted data. To address this issue, the LUKS
|
||||
+password is used to ensure that only authorized users are granted access to the
|
||||
+interface. Additionally, the @samp{menu entry editor} (@pxref{Menu entry
|
||||
+editor}) is also safeguarded by the LUKS password, as modifying a boot entry is
|
||||
+effectively the same as altering the @file{grub.cfg} file read from encrypted
|
||||
+files.
|
||||
+
|
||||
+It is worth mentioning that the built-in password support, as described in
|
||||
+@samp{Authentication and Authorization in GRUB} (@pxref{Authentication and
|
||||
+authorisation}), can also be used to protect the command-line interface from
|
||||
+unauthorized access. However, it is not recommended to rely on this approach as
|
||||
+it is an optional step. Setting it up requires additional manual intervention,
|
||||
+which increases the risk of password leakage during the process. Moreover, the
|
||||
+superuser list must be well maintained, and the password used cannot be
|
||||
+synchronized with LUKS key rotation.
|
||||
|
||||
@node Platform limitations
|
||||
@chapter Platform limitations
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 49af8a9..9c456c2 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -1144,7 +1144,9 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||
ret = grub_cryptodisk_insert (dev, name, source);
|
||||
if (ret != GRUB_ERR_NONE)
|
||||
goto error;
|
||||
-
|
||||
+#ifndef GRUB_UTIL
|
||||
+ grub_cli_set_auth_needed ();
|
||||
+#endif
|
||||
goto cleanup;
|
||||
}
|
||||
grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
|
||||
@@ -1576,6 +1578,89 @@ luks_script_get (grub_size_t *sz)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+grub_err_t
|
||||
+grub_cryptodisk_challenge_password (void)
|
||||
+{
|
||||
+ grub_cryptodisk_t cr_dev;
|
||||
+
|
||||
+ for (cr_dev = cryptodisk_list; cr_dev != NULL; cr_dev = cr_dev->next)
|
||||
+ {
|
||||
+ grub_cryptodisk_dev_t cr;
|
||||
+ grub_disk_t source = NULL;
|
||||
+ grub_err_t ret = GRUB_ERR_NONE;
|
||||
+ grub_cryptodisk_t dev = NULL;
|
||||
+ char *part = NULL;
|
||||
+ struct grub_cryptomount_args cargs = {0};
|
||||
+
|
||||
+ cargs.check_boot = 0;
|
||||
+ cargs.search_uuid = cr_dev->uuid;
|
||||
+
|
||||
+ source = grub_disk_open (cr_dev->source);
|
||||
+
|
||||
+ if (source == NULL)
|
||||
+ {
|
||||
+ ret = grub_errno;
|
||||
+ goto error_out;
|
||||
+ }
|
||||
+
|
||||
+ FOR_CRYPTODISK_DEVS (cr)
|
||||
+ {
|
||||
+ dev = cr->scan (source, &cargs);
|
||||
+ if (grub_errno)
|
||||
+ {
|
||||
+ ret = grub_errno;
|
||||
+ goto error_out;
|
||||
+ }
|
||||
+ if (dev == NULL)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (dev == NULL)
|
||||
+ {
|
||||
+ ret = grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
|
||||
+ goto error_out;
|
||||
+ }
|
||||
+
|
||||
+ part = grub_partition_get_name (source->partition);
|
||||
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||
+ source->partition != NULL ? "," : "",
|
||||
+ part != NULL ? part : N_("UNKNOWN"), cr_dev->uuid);
|
||||
+ grub_free (part);
|
||||
+
|
||||
+ cargs.key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
|
||||
+ if (cargs.key_data == NULL)
|
||||
+ {
|
||||
+ ret = grub_errno;
|
||||
+ goto error_out;
|
||||
+ }
|
||||
+
|
||||
+ if (!grub_password_get ((char *) cargs.key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
|
||||
+ {
|
||||
+ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
|
||||
+ goto error_out;
|
||||
+ }
|
||||
+ cargs.key_len = grub_strlen ((char *) cargs.key_data);
|
||||
+ ret = cr->recover_key (source, dev, &cargs);
|
||||
+
|
||||
+ error_out:
|
||||
+ grub_disk_close (source);
|
||||
+ if (dev != NULL)
|
||||
+ cryptodisk_close (dev);
|
||||
+ if (cargs.key_data)
|
||||
+ {
|
||||
+ grub_memset (cargs.key_data, 0, cargs.key_len);
|
||||
+ grub_free (cargs.key_data);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+#endif /* GRUB_MACHINE_EFI */
|
||||
+
|
||||
struct grub_procfs_entry luks_script =
|
||||
{
|
||||
.name = "luks_script",
|
||||
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
|
||||
index e4d4bf6..0a4a8d8 100644
|
||||
--- a/grub-core/kern/main.c
|
||||
+++ b/grub-core/kern/main.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#endif
|
||||
|
||||
static bool cli_disabled = false;
|
||||
+static bool cli_need_auth = false;
|
||||
|
||||
grub_addr_t
|
||||
grub_modules_get_end (void)
|
||||
@@ -308,6 +309,17 @@ grub_is_cli_disabled (void)
|
||||
return cli_disabled;
|
||||
}
|
||||
|
||||
+bool
|
||||
+grub_is_cli_need_auth (void)
|
||||
+{
|
||||
+ return cli_need_auth;
|
||||
+}
|
||||
+
|
||||
+void grub_cli_set_auth_needed (void)
|
||||
+{
|
||||
+ cli_need_auth = true;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
check_is_cli_disabled (void)
|
||||
{
|
||||
diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
|
||||
index 53f2d72..075aba4 100644
|
||||
--- a/grub-core/normal/auth.c
|
||||
+++ b/grub-core/normal/auth.c
|
||||
@@ -25,6 +25,10 @@
|
||||
#include <grub/time.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+#include <grub/cryptodisk.h>
|
||||
+#endif
|
||||
+
|
||||
struct grub_auth_user
|
||||
{
|
||||
struct grub_auth_user *next;
|
||||
@@ -200,6 +204,32 @@ grub_username_get (char buf[], unsigned buf_size)
|
||||
return (key != GRUB_TERM_ESC);
|
||||
}
|
||||
|
||||
+grub_err_t
|
||||
+grub_auth_check_cli_access (void)
|
||||
+{
|
||||
+ if (grub_is_cli_need_auth () == true)
|
||||
+ {
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ static bool authenticated = false;
|
||||
+
|
||||
+ if (authenticated == false)
|
||||
+ {
|
||||
+ grub_err_t ret;
|
||||
+
|
||||
+ ret = grub_cryptodisk_challenge_password ();
|
||||
+ if (ret == GRUB_ERR_NONE)
|
||||
+ authenticated = true;
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return GRUB_ERR_NONE;
|
||||
+#else
|
||||
+ return GRUB_ACCESS_DENIED;
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
grub_err_t
|
||||
grub_auth_check_authentication (const char *userlist)
|
||||
{
|
||||
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
|
||||
index bac7b8a..6f6e4a8 100644
|
||||
--- a/grub-core/normal/main.c
|
||||
+++ b/grub-core/normal/main.c
|
||||
@@ -556,9 +556,13 @@ grub_cmdline_run (int nested, int force_auth)
|
||||
}
|
||||
while (err && force_auth);
|
||||
|
||||
+ if (err == GRUB_ERR_NONE)
|
||||
+ err = grub_auth_check_cli_access ();
|
||||
+
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
+ grub_wait_after_message ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
|
||||
index 50eef91..150a800 100644
|
||||
--- a/grub-core/normal/menu_entry.c
|
||||
+++ b/grub-core/normal/menu_entry.c
|
||||
@@ -1255,9 +1255,13 @@ grub_menu_entry_run (grub_menu_entry_t entry)
|
||||
|
||||
err = grub_auth_check_authentication (NULL);
|
||||
|
||||
+ if (err == GRUB_ERR_NONE)
|
||||
+ err = grub_auth_check_cli_access ();
|
||||
+
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
+ grub_wait_after_message ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
diff --git a/include/grub/auth.h b/include/grub/auth.h
|
||||
index 7473344..21d5190 100644
|
||||
--- a/include/grub/auth.h
|
||||
+++ b/include/grub/auth.h
|
||||
@@ -33,5 +33,6 @@ grub_err_t grub_auth_unregister_authentication (const char *user);
|
||||
grub_err_t grub_auth_authenticate (const char *user);
|
||||
grub_err_t grub_auth_deauthenticate (const char *user);
|
||||
grub_err_t grub_auth_check_authentication (const char *userlist);
|
||||
+grub_err_t grub_auth_check_cli_access (void);
|
||||
|
||||
#endif /* ! GRUB_AUTH_HEADER */
|
||||
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
|
||||
index d94df68..d2572f8 100644
|
||||
--- a/include/grub/cryptodisk.h
|
||||
+++ b/include/grub/cryptodisk.h
|
||||
@@ -187,4 +187,7 @@ grub_util_get_geli_uuid (const char *dev);
|
||||
grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid);
|
||||
grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+grub_err_t grub_cryptodisk_challenge_password (void);
|
||||
+#endif
|
||||
#endif
|
||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
|
||||
index fae4910..77d9f56 100644
|
||||
--- a/include/grub/misc.h
|
||||
+++ b/include/grub/misc.h
|
||||
@@ -440,6 +440,8 @@ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
|
||||
grub_uint64_t *r);
|
||||
|
||||
extern bool EXPORT_FUNC(grub_is_cli_disabled) (void);
|
||||
+extern bool EXPORT_FUNC(grub_is_cli_need_auth) (void);
|
||||
+extern void EXPORT_FUNC(grub_cli_set_auth_needed) (void);
|
||||
|
||||
/* Must match softdiv group in gentpl.py. */
|
||||
#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__) || \
|
108
0399-disk-loopback-Reference-tracking-for-the-loopback.patch
Normal file
108
0399-disk-loopback-Reference-tracking-for-the-loopback.patch
Normal file
@ -0,0 +1,108 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 15:22:28 -0600
|
||||
Subject: [PATCH] disk/loopback: Reference tracking for the loopback
|
||||
|
||||
It was possible to delete a loopback while there were still references
|
||||
to it. This led to an exploitable use-after-free.
|
||||
|
||||
Fixed by implementing a reference counting in the grub_loopback struct.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/loopback.c | 17 +++++++++++++++++
|
||||
include/grub/err.h | 3 ++-
|
||||
include/grub/loopback.h | 1 +
|
||||
3 files changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c
|
||||
index 99f4792..93026c5 100644
|
||||
--- a/grub-core/disk/loopback.c
|
||||
+++ b/grub-core/disk/loopback.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/mm.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -56,6 +57,8 @@ delete_loopback (const char *name)
|
||||
if (! dev)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "device not found");
|
||||
|
||||
+ if (dev->refcnt > 0)
|
||||
+ return grub_error (GRUB_ERR_STILL_REFERENCED, "device still referenced");
|
||||
/* Remove the device from the list. */
|
||||
*prev = dev->next;
|
||||
|
||||
@@ -109,6 +112,7 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
|
||||
newdev->file = file;
|
||||
newdev->id = last_id++;
|
||||
+ newdev->refcnt = 0;
|
||||
|
||||
/* Add the new entry to the list. */
|
||||
newdev->next = loopback_list;
|
||||
@@ -150,6 +154,9 @@ grub_loopback_open (const char *name, grub_disk_t disk)
|
||||
if (! dev)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
|
||||
|
||||
+ if (grub_add (dev->refcnt, 1, &dev->refcnt))
|
||||
+ grub_fatal ("Reference count overflow");
|
||||
+
|
||||
/* Use the filesize for the disk size, round up to a complete sector. */
|
||||
if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN)
|
||||
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
|
||||
@@ -167,6 +174,15 @@ grub_loopback_open (const char *name, grub_disk_t disk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void
|
||||
+grub_loopback_close (grub_disk_t disk)
|
||||
+{
|
||||
+ struct grub_loopback *dev = disk->data;
|
||||
+
|
||||
+ if (grub_sub (dev->refcnt, 1, &dev->refcnt))
|
||||
+ grub_fatal ("Reference count underflow");
|
||||
+}
|
||||
+
|
||||
static grub_err_t
|
||||
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
@@ -209,6 +225,7 @@ static struct grub_disk_dev grub_loopback_dev =
|
||||
.id = GRUB_DISK_DEVICE_LOOPBACK_ID,
|
||||
.disk_iterate = grub_loopback_iterate,
|
||||
.disk_open = grub_loopback_open,
|
||||
+ .disk_close = grub_loopback_close,
|
||||
.disk_read = grub_loopback_read,
|
||||
.disk_write = grub_loopback_write,
|
||||
.next = 0
|
||||
diff --git a/include/grub/err.h b/include/grub/err.h
|
||||
index c0f90ef..4b903df 100644
|
||||
--- a/include/grub/err.h
|
||||
+++ b/include/grub/err.h
|
||||
@@ -72,7 +72,8 @@ typedef enum
|
||||
GRUB_ERR_NET_PACKET_TOO_BIG,
|
||||
GRUB_ERR_NET_NO_DOMAIN,
|
||||
GRUB_ERR_EOF,
|
||||
- GRUB_ERR_BAD_SIGNATURE
|
||||
+ GRUB_ERR_BAD_SIGNATURE,
|
||||
+ GRUB_ERR_STILL_REFERENCED
|
||||
}
|
||||
grub_err_t;
|
||||
|
||||
diff --git a/include/grub/loopback.h b/include/grub/loopback.h
|
||||
index 3b9a9e3..915ef65 100644
|
||||
--- a/include/grub/loopback.h
|
||||
+++ b/include/grub/loopback.h
|
||||
@@ -25,6 +25,7 @@ struct grub_loopback
|
||||
grub_file_t file;
|
||||
struct grub_loopback *next;
|
||||
unsigned long id;
|
||||
+ grub_uint64_t refcnt;
|
||||
};
|
||||
|
||||
#endif /* ! GRUB_LOOPBACK_HEADER */
|
120
0400-kern-disk-Limit-recursion-depth.patch
Normal file
120
0400-kern-disk-Limit-recursion-depth.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 04:09:24 +0100
|
||||
Subject: [PATCH] kern/disk: Limit recursion depth
|
||||
|
||||
The grub_disk_read() may trigger other disk reads, e.g. via loopbacks.
|
||||
This may lead to very deep recursion which can corrupt the heap. So, fix
|
||||
the issue by limiting reads depth.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/disk.c | 27 ++++++++++++++++++++-------
|
||||
include/grub/err.h | 3 ++-
|
||||
2 files changed, 22 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
|
||||
index 05a28ab..60f6ad2 100644
|
||||
--- a/grub-core/kern/disk.c
|
||||
+++ b/grub-core/kern/disk.c
|
||||
@@ -28,6 +28,10 @@
|
||||
|
||||
#define GRUB_CACHE_TIMEOUT 2
|
||||
|
||||
+/* Disk reads may trigger other disk reads. So, limit recursion depth. */
|
||||
+#define MAX_READ_RECURSION_DEPTH 16
|
||||
+static unsigned int read_recursion_depth = 0;
|
||||
+
|
||||
/* The last time the disk was used. */
|
||||
static grub_uint64_t grub_last_time = 0;
|
||||
|
||||
@@ -417,6 +421,8 @@ grub_err_t
|
||||
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_off_t offset, grub_size_t size, void *buf)
|
||||
{
|
||||
+ grub_err_t err = GRUB_ERR_NONE;
|
||||
+
|
||||
/* First of all, check if the region is within the disk. */
|
||||
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
|
||||
{
|
||||
@@ -427,12 +433,17 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
+ if (++read_recursion_depth >= MAX_READ_RECURSION_DEPTH)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_RECURSION_DEPTH, "grub_disk_read(): Maximum recursion depth exceeded");
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
/* First read until first cache boundary. */
|
||||
if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1)))
|
||||
{
|
||||
grub_disk_addr_t start_sector;
|
||||
grub_size_t pos;
|
||||
- grub_err_t err;
|
||||
grub_size_t len;
|
||||
|
||||
start_sector = sector & ~((grub_disk_addr_t) GRUB_DISK_CACHE_SIZE - 1);
|
||||
@@ -444,7 +455,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
err = grub_disk_read_small (disk, start_sector,
|
||||
offset + pos, len, buf);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error;
|
||||
buf = (char *) buf + len;
|
||||
size -= len;
|
||||
offset += len;
|
||||
@@ -457,7 +468,6 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
{
|
||||
char *data = NULL;
|
||||
grub_disk_addr_t agglomerate;
|
||||
- grub_err_t err;
|
||||
|
||||
/* agglomerate read until we find a first cached entry. */
|
||||
for (agglomerate = 0; agglomerate
|
||||
@@ -493,7 +503,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
- disk->log_sector_size),
|
||||
buf);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error;
|
||||
|
||||
for (i = 0; i < agglomerate; i ++)
|
||||
grub_disk_cache_store (disk->dev->id, disk->id,
|
||||
@@ -527,13 +537,16 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
/* And now read the last part. */
|
||||
if (size)
|
||||
{
|
||||
- grub_err_t err;
|
||||
err = grub_disk_read_small (disk, sector, 0, size, buf);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error;
|
||||
}
|
||||
|
||||
- return grub_errno;
|
||||
+ err = grub_errno;
|
||||
+
|
||||
+ error:
|
||||
+ read_recursion_depth--;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
grub_uint64_t
|
||||
diff --git a/include/grub/err.h b/include/grub/err.h
|
||||
index 4b903df..905a6df 100644
|
||||
--- a/include/grub/err.h
|
||||
+++ b/include/grub/err.h
|
||||
@@ -73,7 +73,8 @@ typedef enum
|
||||
GRUB_ERR_NET_NO_DOMAIN,
|
||||
GRUB_ERR_EOF,
|
||||
GRUB_ERR_BAD_SIGNATURE,
|
||||
- GRUB_ERR_STILL_REFERENCED
|
||||
+ GRUB_ERR_STILL_REFERENCED,
|
||||
+ GRUB_ERR_RECURSION_DEPTH
|
||||
}
|
||||
grub_err_t;
|
||||
|
44
0401-kern-partition-Limit-recursion-in-part_iterate.patch
Normal file
44
0401-kern-partition-Limit-recursion-in-part_iterate.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sat, 16 Nov 2024 21:24:19 +0000
|
||||
Subject: [PATCH] kern/partition: Limit recursion in part_iterate()
|
||||
|
||||
The part_iterate() is used by grub_partition_iterate() as a callback in
|
||||
the partition iterate functions. However, part_iterate() may also call
|
||||
the partition iterate functions which may lead to recursion. Fix potential
|
||||
issue by limiting the recursion depth.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/partition.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c
|
||||
index 3068c4dca..f3f125e75 100644
|
||||
--- a/grub-core/kern/partition.c
|
||||
+++ b/grub-core/kern/partition.c
|
||||
@@ -28,6 +28,9 @@
|
||||
|
||||
grub_partition_map_t grub_partition_map_list;
|
||||
|
||||
+#define MAX_RECURSION_DEPTH 32
|
||||
+static unsigned int recursion_depth = 0;
|
||||
+
|
||||
/*
|
||||
* Checks that disk->partition contains part. This function assumes that the
|
||||
* start of part is relative to the start of disk->partition. Returns 1 if
|
||||
@@ -208,7 +211,12 @@ part_iterate (grub_disk_t dsk, const grub_partition_t partition, void *data)
|
||||
FOR_PARTITION_MAPS(partmap)
|
||||
{
|
||||
grub_err_t err;
|
||||
- err = partmap->iterate (dsk, part_iterate, ctx);
|
||||
+ recursion_depth++;
|
||||
+ if (recursion_depth <= MAX_RECURSION_DEPTH)
|
||||
+ err = partmap->iterate (dsk, part_iterate, ctx);
|
||||
+ else
|
||||
+ err = grub_error (GRUB_ERR_RECURSION_DEPTH, "maximum recursion depth exceeded");
|
||||
+ recursion_depth--;
|
||||
if (err)
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
if (ctx->ret)
|
55
0402-script-execute-Limit-the-recursion-depth.patch
Normal file
55
0402-script-execute-Limit-the-recursion-depth.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Thu, 18 Apr 2024 19:04:13 +0100
|
||||
Subject: [PATCH] script/execute: Limit the recursion depth
|
||||
|
||||
If unbounded recursion is allowed it becomes possible to collide the
|
||||
stack with the heap. As UEFI firmware often lacks guard pages this
|
||||
becomes an exploitable issue as it is possible in some cases to do
|
||||
a controlled overwrite of a section of this heap region with
|
||||
arbitrary data.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/script/execute.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
|
||||
index 0c6dd9c52..c383eb87c 100644
|
||||
--- a/grub-core/script/execute.c
|
||||
+++ b/grub-core/script/execute.c
|
||||
@@ -36,10 +36,18 @@
|
||||
is sizeof (int) * 3, and one extra for a possible -ve sign. */
|
||||
#define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1)
|
||||
|
||||
+/*
|
||||
+ * A limit on recursion, to avoid colliding with the heap. UEFI defines a baseline
|
||||
+ * stack size of 128 KiB. So, assuming at most 1-2 KiB per iteration this should
|
||||
+ * keep us safe.
|
||||
+ */
|
||||
+#define MAX_RECURSION_DEPTH 64
|
||||
+
|
||||
static unsigned long is_continue;
|
||||
static unsigned long active_loops;
|
||||
static unsigned long active_breaks;
|
||||
static unsigned long function_return;
|
||||
+static unsigned long recursion_depth;
|
||||
|
||||
#define GRUB_SCRIPT_SCOPE_MALLOCED 1
|
||||
#define GRUB_SCRIPT_SCOPE_ARGS_MALLOCED 2
|
||||
@@ -850,7 +858,13 @@ grub_script_execute_cmd (struct grub_script_cmd *cmd)
|
||||
if (cmd == 0)
|
||||
return 0;
|
||||
|
||||
+ recursion_depth++;
|
||||
+
|
||||
+ if (recursion_depth >= MAX_RECURSION_DEPTH)
|
||||
+ return grub_error (GRUB_ERR_RECURSION_DEPTH, N_("maximum recursion depth exceeded"));
|
||||
+
|
||||
ret = cmd->exec (cmd);
|
||||
+ recursion_depth--;
|
||||
|
||||
grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret);
|
||||
grub_env_set ("?", errnobuf);
|
@ -0,0 +1,29 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 15:27:10 -0600
|
||||
Subject: [PATCH] net: Unregister net_default_ip and net_default_mac variables
|
||||
hooks on unload
|
||||
|
||||
The net module is a dependency of normal. So, it shouldn't be possible
|
||||
to unload the net. Though unregister variables hooks as a precaution.
|
||||
It also gets in line with unregistering the other net module hooks.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/net.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
||||
index 1001c611d..fd78f09b0 100644
|
||||
--- a/grub-core/net/net.c
|
||||
+++ b/grub-core/net/net.c
|
||||
@@ -2166,6 +2166,8 @@ GRUB_MOD_FINI(net)
|
||||
|
||||
grub_register_variable_hook ("net_default_server", 0, 0);
|
||||
grub_register_variable_hook ("pxe_default_server", 0, 0);
|
||||
+ grub_register_variable_hook ("net_default_ip", 0, 0);
|
||||
+ grub_register_variable_hook ("net_default_mac", 0, 0);
|
||||
|
||||
grub_bootp_fini ();
|
||||
grub_dns_fini ();
|
@ -0,0 +1,84 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 15:42:44 -0600
|
||||
Subject: [PATCH] net: Remove variables hooks when interface is unregisted
|
||||
|
||||
The grub_net_network_level_interface_unregister(), previously
|
||||
implemented in a header, did not remove the variables hooks that
|
||||
were registered in grub_net_network_level_interface_register().
|
||||
Fix this by implementing the same logic used to register the
|
||||
variables and move the function into the grub-core/net/net.c.
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/net.c | 33 +++++++++++++++++++++++++++++++++
|
||||
include/grub/net.h | 11 +----------
|
||||
2 files changed, 34 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
||||
index fd78f09b0..251286227 100644
|
||||
--- a/grub-core/net/net.c
|
||||
+++ b/grub-core/net/net.c
|
||||
@@ -1051,6 +1051,39 @@ grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void
|
||||
+grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter)
|
||||
+{
|
||||
+ char *name;
|
||||
+
|
||||
+ {
|
||||
+ char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
|
||||
+
|
||||
+ grub_net_hwaddr_to_str (&inter->hwaddress, buf);
|
||||
+ name = grub_xasprintf ("net_%s_mac", inter->name);
|
||||
+ if (name != NULL)
|
||||
+ grub_register_variable_hook (name, NULL, NULL);
|
||||
+ grub_free (name);
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ char buf[GRUB_NET_MAX_STR_ADDR_LEN];
|
||||
+
|
||||
+ grub_net_addr_to_str (&inter->address, buf);
|
||||
+ name = grub_xasprintf ("net_%s_ip", inter->name);
|
||||
+ if (name != NULL)
|
||||
+ grub_register_variable_hook (name, NULL, NULL);
|
||||
+ grub_free (name);
|
||||
+ }
|
||||
+
|
||||
+ inter->card->num_ifaces--;
|
||||
+ *inter->prev = inter->next;
|
||||
+ if (inter->next)
|
||||
+ inter->next->prev = inter->prev;
|
||||
+ inter->next = 0;
|
||||
+ inter->prev = 0;
|
||||
+}
|
||||
+
|
||||
grub_err_t
|
||||
grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter,
|
||||
int mask)
|
||||
diff --git a/include/grub/net.h b/include/grub/net.h
|
||||
index 9e4898cc6..43eba9216 100644
|
||||
--- a/include/grub/net.h
|
||||
+++ b/include/grub/net.h
|
||||
@@ -618,16 +618,7 @@ void grub_bootp_fini (void);
|
||||
void grub_dns_init (void);
|
||||
void grub_dns_fini (void);
|
||||
|
||||
-static inline void
|
||||
-grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter)
|
||||
-{
|
||||
- inter->card->num_ifaces--;
|
||||
- *inter->prev = inter->next;
|
||||
- if (inter->next)
|
||||
- inter->next->prev = inter->prev;
|
||||
- inter->next = 0;
|
||||
- inter->prev = 0;
|
||||
-}
|
||||
+void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter);
|
||||
|
||||
void
|
||||
grub_net_tcp_retransmit (void);
|
79
0405-net-Fix-OOB-write-in-grub_net_search_config_file.patch
Normal file
79
0405-net-Fix-OOB-write-in-grub_net_search_config_file.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 16:38:44 -0600
|
||||
Subject: [PATCH] net: Fix OOB write in grub_net_search_config_file()
|
||||
|
||||
The function included a call to grub_strcpy() which copied data from an
|
||||
environment variable to a buffer allocated in grub_cmd_normal(). The
|
||||
grub_cmd_normal() didn't consider the length of the environment variable.
|
||||
So, the copy operation could exceed the allocation and lead to an OOB
|
||||
write. Fix the issue by replacing grub_strcpy() with grub_strlcpy() and
|
||||
pass the underlying buffers size to the grub_net_search_config_file().
|
||||
|
||||
Fixes: CVE-2025-0624
|
||||
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/net.c | 7 ++++---
|
||||
grub-core/normal/main.c | 2 +-
|
||||
include/grub/net.h | 2 +-
|
||||
3 files changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
||||
index 251286227..6c0bd00b4 100644
|
||||
--- a/grub-core/net/net.c
|
||||
+++ b/grub-core/net/net.c
|
||||
@@ -1971,14 +1971,15 @@ grub_config_search_through (char *config, char *suffix,
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
-grub_net_search_config_file (char *config)
|
||||
+grub_net_search_config_file (char *config, grub_size_t config_buf_len)
|
||||
{
|
||||
- grub_size_t config_len;
|
||||
+ grub_size_t config_len, suffix_len;
|
||||
char *suffix;
|
||||
|
||||
config_len = grub_strlen (config);
|
||||
config[config_len] = '-';
|
||||
suffix = config + config_len + 1;
|
||||
+ suffix_len = config_buf_len - (config_len + 1);
|
||||
|
||||
struct grub_net_network_level_interface *inf;
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
@@ -2004,7 +2005,7 @@ grub_net_search_config_file (char *config)
|
||||
|
||||
if (client_uuid)
|
||||
{
|
||||
- grub_strcpy (suffix, client_uuid);
|
||||
+ grub_strlcpy (suffix, client_uuid, suffix_len);
|
||||
if (grub_config_search_through (config, suffix, 1, 0) == 0)
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
|
||||
index 6f6e4a813..49b947292 100644
|
||||
--- a/grub-core/normal/main.c
|
||||
+++ b/grub-core/normal/main.c
|
||||
@@ -360,7 +360,7 @@ grub_try_normal_prefix (const char *prefix)
|
||||
return err;
|
||||
|
||||
grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
|
||||
- err = grub_net_search_config_file (config);
|
||||
+ err = grub_net_search_config_file (config, config_len);
|
||||
}
|
||||
|
||||
if (err != GRUB_ERR_NONE)
|
||||
diff --git a/include/grub/net.h b/include/grub/net.h
|
||||
index 43eba9216..1101b0397 100644
|
||||
--- a/include/grub/net.h
|
||||
+++ b/include/grub/net.h
|
||||
@@ -648,7 +648,7 @@ void
|
||||
grub_net_remove_dns_server (const struct grub_net_network_level_address *s);
|
||||
|
||||
grub_err_t
|
||||
-grub_net_search_config_file (char *config);
|
||||
+grub_net_search_config_file (char *config, grub_size_t config_buf_len);
|
||||
|
||||
extern char *grub_net_default_server;
|
||||
|
115
0406-net-tftp-Fix-stack-buffer-overflow-in-tftp_open.patch
Normal file
115
0406-net-tftp-Fix-stack-buffer-overflow-in-tftp_open.patch
Normal file
@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Thu, 18 Apr 2024 17:32:34 +0100
|
||||
Subject: [PATCH] net/tftp: Fix stack buffer overflow in tftp_open()
|
||||
|
||||
An overly long filename can be passed to tftp_open() which would cause
|
||||
grub_normalize_filename() to write out of bounds.
|
||||
|
||||
Fixed by adding an extra argument to grub_normalize_filename() for the
|
||||
space available, making it act closer to a strlcpy(). As several fixed
|
||||
strings are strcpy()'d after into the same buffer, their total length is
|
||||
checked to see if they exceed the remaining space in the buffer. If so,
|
||||
return an error.
|
||||
|
||||
On the occasion simplify code a bit by removing unneeded rrqlen zeroing.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/tftp.c | 38 ++++++++++++++++++++++++--------------
|
||||
1 file changed, 24 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
||||
index a95766dcb..ecfcc13d9 100644
|
||||
--- a/grub-core/net/tftp.c
|
||||
+++ b/grub-core/net/tftp.c
|
||||
@@ -266,17 +266,19 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||
* forward slashes to a single forward slash.
|
||||
*/
|
||||
static void
|
||||
-grub_normalize_filename (char *normalized, const char *filename)
|
||||
+grub_normalize_filename (char *normalized, const char *filename, int c)
|
||||
{
|
||||
char *dest = normalized;
|
||||
const char *src = filename;
|
||||
|
||||
- while (*src != '\0')
|
||||
+ while (*src != '\0' && c > 0)
|
||||
{
|
||||
if (src[0] == '/' && src[1] == '/')
|
||||
src++;
|
||||
- else
|
||||
+ else {
|
||||
+ c--;
|
||||
*dest++ = *src++;
|
||||
+ }
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
@@ -287,7 +289,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
struct tftphdr *tftph;
|
||||
char *rrq;
|
||||
int i;
|
||||
- int rrqlen;
|
||||
+ int rrqlen, rrqsize;
|
||||
int hdrlen;
|
||||
grub_uint8_t open_data[1500];
|
||||
struct grub_net_buff nb;
|
||||
@@ -315,37 +317,45 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
|
||||
tftph = (struct tftphdr *) nb.data;
|
||||
|
||||
- rrq = (char *) tftph->u.rrq;
|
||||
- rrqlen = 0;
|
||||
-
|
||||
tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ);
|
||||
|
||||
+ rrq = (char *) tftph->u.rrq;
|
||||
+ rrqsize = sizeof (tftph->u.rrq);
|
||||
+
|
||||
/*
|
||||
* Copy and normalize the filename to work-around issues on some TFTP
|
||||
* servers when file names are being matched for remapping.
|
||||
*/
|
||||
- grub_normalize_filename (rrq, filename);
|
||||
- rrqlen += grub_strlen (rrq) + 1;
|
||||
+ grub_normalize_filename (rrq, filename, rrqsize);
|
||||
+
|
||||
+ rrqlen = grub_strlen (rrq) + 1;
|
||||
rrq += grub_strlen (rrq) + 1;
|
||||
|
||||
- grub_strcpy (rrq, "octet");
|
||||
+ /* Verify there is enough space for the remaining components. */
|
||||
rrqlen += grub_strlen ("octet") + 1;
|
||||
+ rrqlen += grub_strlen ("blksize") + 1;
|
||||
+ rrqlen += grub_strlen ("1024") + 1;
|
||||
+ rrqlen += grub_strlen ("tsize") + 1;
|
||||
+ rrqlen += grub_strlen ("0") + 1;
|
||||
+
|
||||
+ if (rrqlen >= rrqsize) {
|
||||
+ grub_free (data);
|
||||
+ return grub_error (GRUB_ERR_BAD_FILENAME, N_("filename too long"));
|
||||
+ }
|
||||
+
|
||||
+ grub_strcpy (rrq, "octet");
|
||||
rrq += grub_strlen ("octet") + 1;
|
||||
|
||||
grub_strcpy (rrq, "blksize");
|
||||
- rrqlen += grub_strlen ("blksize") + 1;
|
||||
rrq += grub_strlen ("blksize") + 1;
|
||||
|
||||
grub_strcpy (rrq, "1024");
|
||||
- rrqlen += grub_strlen ("1024") + 1;
|
||||
rrq += grub_strlen ("1024") + 1;
|
||||
|
||||
grub_strcpy (rrq, "tsize");
|
||||
- rrqlen += grub_strlen ("tsize") + 1;
|
||||
rrq += grub_strlen ("tsize") + 1;
|
||||
|
||||
grub_strcpy (rrq, "0");
|
||||
- rrqlen += grub_strlen ("0") + 1;
|
||||
rrq += grub_strlen ("0") + 1;
|
||||
hdrlen = sizeof (tftph->opcode) + rrqlen;
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Fri, 8 Mar 2024 22:47:20 +1100
|
||||
Subject: [PATCH] video/readers/jpeg: Do not permit duplicate SOF0 markers in
|
||||
JPEG
|
||||
|
||||
Otherwise a subsequent header could change the height and width
|
||||
allowing future OOB writes.
|
||||
|
||||
Fixes: CVE-2024-45774
|
||||
|
||||
Reported-by: Nils Langius <nils@langius.de>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/jpeg.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
|
||||
index 2da04094b..c7aaac362 100644
|
||||
--- a/grub-core/video/readers/jpeg.c
|
||||
+++ b/grub-core/video/readers/jpeg.c
|
||||
@@ -332,6 +332,10 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
+ if (data->image_height != 0 || data->image_width != 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: cannot have duplicate SOF0 markers");
|
||||
+
|
||||
if (grub_jpeg_get_byte (data) != 8)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"jpeg: only 8-bit precision is supported");
|
138
0408-kern-dl-Fix-for-an-integer-overflow-in-grub_dl_ref.patch
Normal file
138
0408-kern-dl-Fix-for-an-integer-overflow-in-grub_dl_ref.patch
Normal file
@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 16:41:57 -0600
|
||||
Subject: [PATCH] kern/dl: Fix for an integer overflow in grub_dl_ref()
|
||||
|
||||
It was possible to overflow the value of mod->ref_count, a signed
|
||||
integer, by repeatedly invoking insmod on an already loaded module.
|
||||
This led to a use-after-free. As once ref_count was overflowed it became
|
||||
possible to unload the module while there was still references to it.
|
||||
|
||||
This resolves the issue by using grub_add() to check if the ref_count
|
||||
will overflow and then stops further increments. Further changes were
|
||||
also made to grub_dl_unref() to check for the underflow condition and
|
||||
the reference count was changed to an unsigned 64-bit integer.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/minicmd.c | 2 +-
|
||||
grub-core/kern/dl.c | 17 ++++++++++++-----
|
||||
include/grub/dl.h | 8 ++++----
|
||||
util/misc.c | 4 ++--
|
||||
4 files changed, 19 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
|
||||
index 2bd3ac76f..2001043cf 100644
|
||||
--- a/grub-core/commands/minicmd.c
|
||||
+++ b/grub-core/commands/minicmd.c
|
||||
@@ -167,7 +167,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
|
||||
{
|
||||
grub_dl_dep_t dep;
|
||||
|
||||
- grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count);
|
||||
+ grub_printf ("%s\t%" PRIuGRUB_UINT64_T "\t\t", mod->name, mod->ref_count);
|
||||
for (dep = mod->dep; dep; dep = dep->next)
|
||||
{
|
||||
if (dep != mod->dep)
|
||||
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
|
||||
index f3cdb9e0b..944e5600a 100644
|
||||
--- a/grub-core/kern/dl.c
|
||||
+++ b/grub-core/kern/dl.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <grub/env.h>
|
||||
#include <grub/cache.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
#include <grub/efi/sb.h>
|
||||
|
||||
/* Platforms where modules are in a readonly area of memory. */
|
||||
@@ -604,7 +605,7 @@ grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e)
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
-int
|
||||
+grub_uint64_t
|
||||
grub_dl_ref (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_dep_t dep;
|
||||
@@ -615,10 +616,13 @@ grub_dl_ref (grub_dl_t mod)
|
||||
for (dep = mod->dep; dep; dep = dep->next)
|
||||
grub_dl_ref (dep->mod);
|
||||
|
||||
- return ++mod->ref_count;
|
||||
+ if (grub_add (mod->ref_count, 1, &mod->ref_count))
|
||||
+ grub_fatal ("Module reference count overflow");
|
||||
+
|
||||
+ return mod->ref_count;
|
||||
}
|
||||
|
||||
-int
|
||||
+grub_uint64_t
|
||||
grub_dl_unref (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_dep_t dep;
|
||||
@@ -629,10 +633,13 @@ grub_dl_unref (grub_dl_t mod)
|
||||
for (dep = mod->dep; dep; dep = dep->next)
|
||||
grub_dl_unref (dep->mod);
|
||||
|
||||
- return --mod->ref_count;
|
||||
+ if (grub_sub (mod->ref_count, 1, &mod->ref_count))
|
||||
+ grub_fatal ("Module reference count underflow");
|
||||
+
|
||||
+ return mod->ref_count;
|
||||
}
|
||||
|
||||
-int
|
||||
+grub_uint64_t
|
||||
grub_dl_ref_count (grub_dl_t mod)
|
||||
{
|
||||
if (mod == NULL)
|
||||
diff --git a/include/grub/dl.h b/include/grub/dl.h
|
||||
index 6bc2560bf..fdf55d4ee 100644
|
||||
--- a/include/grub/dl.h
|
||||
+++ b/include/grub/dl.h
|
||||
@@ -177,7 +177,7 @@ typedef struct grub_dl_dep *grub_dl_dep_t;
|
||||
struct grub_dl
|
||||
{
|
||||
char *name;
|
||||
- int ref_count;
|
||||
+ grub_uint64_t ref_count;
|
||||
int persistent;
|
||||
grub_dl_dep_t dep;
|
||||
grub_dl_segment_t segment;
|
||||
@@ -206,9 +206,9 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
|
||||
grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
|
||||
grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size);
|
||||
int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
|
||||
-extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
|
||||
-extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
|
||||
-extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod);
|
||||
+extern grub_uint64_t EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
|
||||
+extern grub_uint64_t EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
|
||||
+extern grub_uint64_t EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod);
|
||||
|
||||
extern grub_dl_t EXPORT_VAR(grub_dl_head);
|
||||
|
||||
diff --git a/util/misc.c b/util/misc.c
|
||||
index d545212d9..0f928e5b4 100644
|
||||
--- a/util/misc.c
|
||||
+++ b/util/misc.c
|
||||
@@ -190,14 +190,14 @@ grub_xputs_real (const char *str)
|
||||
|
||||
void (*grub_xputs) (const char *str) = grub_xputs_real;
|
||||
|
||||
-int
|
||||
+grub_uint64_t
|
||||
grub_dl_ref (grub_dl_t mod)
|
||||
{
|
||||
(void) mod;
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int
|
||||
+grub_uint64_t
|
||||
grub_dl_unref (grub_dl_t mod)
|
||||
{
|
||||
(void) mod;
|
@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 17:01:26 -0600
|
||||
Subject: [PATCH] kern/dl: Check for the SHF_INFO_LINK flag in
|
||||
grub_dl_relocate_symbols()
|
||||
|
||||
The grub_dl_relocate_symbols() iterates through the sections in
|
||||
an ELF looking for relocation sections. According to the spec [1]
|
||||
the SHF_INFO_LINK flag should be set if the sh_info field is meant
|
||||
to be a section index.
|
||||
|
||||
[1] https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/dl.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
|
||||
index 944e5600a..f2806f8cf 100644
|
||||
--- a/grub-core/kern/dl.c
|
||||
+++ b/grub-core/kern/dl.c
|
||||
@@ -672,6 +672,9 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
||||
grub_dl_segment_t seg;
|
||||
grub_err_t err;
|
||||
|
||||
+ if (!(s->sh_flags & SHF_INFO_LINK))
|
||||
+ continue;
|
||||
+
|
||||
seg = grub_dl_find_segment(mod, s->sh_info);
|
||||
if (!seg)
|
||||
continue;
|
@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Fri, 22 Nov 2024 06:27:55 +0000
|
||||
Subject: [PATCH] commands/extcmd: Missing check for failed allocation
|
||||
|
||||
The grub_extcmd_dispatcher() calls grub_arg_list_alloc() to allocate
|
||||
a grub_arg_list struct but it does not verify the allocation was successful.
|
||||
In case of failed allocation the NULL state pointer can be accessed in
|
||||
parse_option() through grub_arg_parse() which may lead to a security issue.
|
||||
|
||||
Fixes: CVE-2024-45775
|
||||
|
||||
Reported-by: Nils Langius <nils@langius.de>
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
---
|
||||
grub-core/commands/extcmd.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c
|
||||
index 90a5ca24a..c236be13a 100644
|
||||
--- a/grub-core/commands/extcmd.c
|
||||
+++ b/grub-core/commands/extcmd.c
|
||||
@@ -49,6 +49,9 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
|
||||
}
|
||||
|
||||
state = grub_arg_list_alloc (ext, argc, args);
|
||||
+ if (state == NULL)
|
||||
+ return grub_errno;
|
||||
+
|
||||
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
|
||||
{
|
||||
context.state = state;
|
32
0411-commands-ls-Fix-NULL-dereference.patch
Normal file
32
0411-commands-ls-Fix-NULL-dereference.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Sun, 12 May 2024 11:08:23 +0100
|
||||
Subject: [PATCH] commands/ls: Fix NULL dereference
|
||||
|
||||
The grub_strrchr() may return NULL when the dirname do not contain "/".
|
||||
This can happen on broken filesystems.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/ls.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
|
||||
index 8e98c73cc..783c82713 100644
|
||||
--- a/grub-core/commands/ls.c
|
||||
+++ b/grub-core/commands/ls.c
|
||||
@@ -241,7 +241,11 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
||||
|
||||
grub_file_close (file);
|
||||
|
||||
- p = grub_strrchr (dirname, '/') + 1;
|
||||
+ p = grub_strrchr (dirname, '/');
|
||||
+ if (p == NULL)
|
||||
+ goto fail;
|
||||
+ ++p;
|
||||
+
|
||||
dirname = grub_strndup (dirname, p - dirname);
|
||||
if (! dirname)
|
||||
goto fail;
|
@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Fri, 1 Nov 2024 19:24:29 +0000
|
||||
Subject: [PATCH] commands/pgp: Unregister the "check_signatures" hooks on
|
||||
module unload
|
||||
|
||||
If the hooks are not removed they can be called after the module has
|
||||
been unloaded leading to an use-after-free.
|
||||
|
||||
Fixes: CVE-2025-0622
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/pgp.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
|
||||
index b81ac0ae4..4a6a5f9a0 100644
|
||||
--- a/grub-core/commands/pgp.c
|
||||
+++ b/grub-core/commands/pgp.c
|
||||
@@ -982,6 +982,8 @@ GRUB_MOD_INIT(pgp)
|
||||
|
||||
GRUB_MOD_FINI(pgp)
|
||||
{
|
||||
+ grub_register_variable_hook ("check_signatures", NULL, NULL);
|
||||
+ grub_env_unset ("check_signatures");
|
||||
grub_verifier_unregister (&grub_pubkey_verifier);
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_trust);
|
37
0413-normal-Remove-variables-hooks-on-module-unload.patch
Normal file
37
0413-normal-Remove-variables-hooks-on-module-unload.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Fri, 1 Nov 2024 23:46:55 +0000
|
||||
Subject: [PATCH] normal: Remove variables hooks on module unload
|
||||
|
||||
The normal module does not entirely cleanup after itself in
|
||||
its GRUB_MOD_FINI() leaving a few variables hooks in place.
|
||||
It is not possible to unload normal module now but fix the
|
||||
issues for completeness.
|
||||
|
||||
On the occasion replace 0s with NULLs for "pager" variable
|
||||
hooks unregister.
|
||||
|
||||
Fixes: CVE-2025-0622
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/normal/main.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
|
||||
index 49b947292..c96b6609d 100644
|
||||
--- a/grub-core/normal/main.c
|
||||
+++ b/grub-core/normal/main.c
|
||||
@@ -689,7 +689,9 @@ GRUB_MOD_FINI(normal)
|
||||
grub_xputs = grub_xputs_saved;
|
||||
|
||||
grub_set_history (0);
|
||||
- grub_register_variable_hook ("pager", 0, 0);
|
||||
+ grub_register_variable_hook ("pager", NULL, NULL);
|
||||
+ grub_register_variable_hook ("color_normal", NULL, NULL);
|
||||
+ grub_register_variable_hook ("color_highlight", NULL, NULL);
|
||||
grub_fs_autoload_hook = 0;
|
||||
grub_unregister_command (cmd_clear);
|
||||
}
|
34
0414-gettext-Remove-variables-hooks-on-module-unload.patch
Normal file
34
0414-gettext-Remove-variables-hooks-on-module-unload.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Fri, 1 Nov 2024 23:52:06 +0000
|
||||
Subject: [PATCH] gettext: Remove variables hooks on module unload
|
||||
|
||||
The gettext module does not entirely cleanup after itself in
|
||||
its GRUB_MOD_FINI() leaving a few variables hooks in place.
|
||||
It is not possible to unload gettext module because normal
|
||||
module depends on it. Though fix the issues for completeness.
|
||||
|
||||
Fixes: CVE-2025-0622
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/gettext/gettext.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
|
||||
index 7ec81ca0b..16169e81f 100644
|
||||
--- a/grub-core/gettext/gettext.c
|
||||
+++ b/grub-core/gettext/gettext.c
|
||||
@@ -542,6 +542,10 @@ GRUB_MOD_INIT (gettext)
|
||||
|
||||
GRUB_MOD_FINI (gettext)
|
||||
{
|
||||
+ grub_register_variable_hook ("locale_dir", NULL, NULL);
|
||||
+ grub_register_variable_hook ("secondary_locale_dir", NULL, NULL);
|
||||
+ grub_register_variable_hook ("lang", NULL, NULL);
|
||||
+
|
||||
grub_gettext_delete_list (&main_context);
|
||||
grub_gettext_delete_list (&secondary_context);
|
||||
|
@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Fri, 22 Nov 2024 06:27:56 +0000
|
||||
Subject: [PATCH] gettext: Integer overflow leads to heap OOB write or read
|
||||
|
||||
Calculation of ctx->grub_gettext_msg_list size in grub_mofile_open() may
|
||||
overflow leading to subsequent OOB write or read. This patch fixes the
|
||||
issue by replacing grub_zalloc() and explicit multiplication with
|
||||
grub_calloc() which does the same thing in safe manner.
|
||||
|
||||
Fixes: CVE-2024-45776
|
||||
|
||||
Reported-by: Nils Langius <nils@langius.de>
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
---
|
||||
grub-core/gettext/gettext.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
|
||||
index 16169e81f..868524839 100644
|
||||
--- a/grub-core/gettext/gettext.c
|
||||
+++ b/grub-core/gettext/gettext.c
|
||||
@@ -323,8 +323,8 @@ grub_mofile_open (struct grub_gettext_context *ctx,
|
||||
for (ctx->grub_gettext_max_log = 0; ctx->grub_gettext_max >> ctx->grub_gettext_max_log;
|
||||
ctx->grub_gettext_max_log++);
|
||||
|
||||
- ctx->grub_gettext_msg_list = grub_zalloc (ctx->grub_gettext_max
|
||||
- * sizeof (ctx->grub_gettext_msg_list[0]));
|
||||
+ ctx->grub_gettext_msg_list = grub_calloc (ctx->grub_gettext_max,
|
||||
+ sizeof (ctx->grub_gettext_msg_list[0]));
|
||||
if (!ctx->grub_gettext_msg_list)
|
||||
{
|
||||
grub_file_close (fd);
|
53
0416-gettext-Integer-overflow-leads-to-heap-OOB-write.patch
Normal file
53
0416-gettext-Integer-overflow-leads-to-heap-OOB-write.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Fri, 22 Nov 2024 06:27:57 +0000
|
||||
Subject: [PATCH] gettext: Integer overflow leads to heap OOB write
|
||||
|
||||
The size calculation of the translation buffer in
|
||||
grub_gettext_getstr_from_position() may overflow
|
||||
to 0 leading to heap OOB write. This patch fixes
|
||||
the issue by using grub_add() and checking for
|
||||
an overflow.
|
||||
|
||||
Fixes: CVE-2024-45777
|
||||
|
||||
Reported-by: Nils Langius <nils@langius.de>
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
---
|
||||
grub-core/gettext/gettext.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
|
||||
index 868524839..0e51b5d28 100644
|
||||
--- a/grub-core/gettext/gettext.c
|
||||
+++ b/grub-core/gettext/gettext.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/file.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -99,6 +100,7 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx,
|
||||
char *translation;
|
||||
struct string_descriptor desc;
|
||||
grub_err_t err;
|
||||
+ grub_size_t alloc_sz;
|
||||
|
||||
internal_position = (off + position * sizeof (desc));
|
||||
|
||||
@@ -109,7 +111,10 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx,
|
||||
length = grub_cpu_to_le32 (desc.length);
|
||||
offset = grub_cpu_to_le32 (desc.offset);
|
||||
|
||||
- translation = grub_malloc (length + 1);
|
||||
+ if (grub_add (length, 1, &alloc_sz))
|
||||
+ return NULL;
|
||||
+
|
||||
+ translation = grub_malloc (alloc_sz);
|
||||
if (!translation)
|
||||
return NULL;
|
||||
|
106
0417-commands-read-Add-silent-mode-to-read-command-to-sup.patch
Normal file
106
0417-commands-read-Add-silent-mode-to-read-command-to-sup.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Sun, 21 Mar 2021 15:22:19 -0500
|
||||
Subject: [PATCH] commands/read: Add silent mode to read command to suppress
|
||||
input echo
|
||||
|
||||
This conforms to the behavior of the -s option of the Bash read command.
|
||||
|
||||
docs/grub: Document the -s option for the read command.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
docs/grub.texi | 5 +++--
|
||||
grub-core/commands/read.c | 28 ++++++++++++++++++----------
|
||||
2 files changed, 21 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index bbcd1c931..913c3bff3 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -5041,10 +5041,11 @@ and the system will reboot.
|
||||
@node read
|
||||
@subsection read
|
||||
|
||||
-@deffn Command read [var]
|
||||
+@deffn Command read [-s] [var]
|
||||
Read a line of input from the user. If an environment variable @var{var} is
|
||||
given, set that environment variable to the line of input that was read,
|
||||
-with no terminating newline.
|
||||
+with no terminating newline. If the parameter @option{-s} is used, enable
|
||||
+silent mode where input is not printed to the terminal.
|
||||
@end deffn
|
||||
|
||||
|
||||
diff --git a/grub-core/commands/read.c b/grub-core/commands/read.c
|
||||
index fe3e88b15..c2969ccda 100644
|
||||
--- a/grub-core/commands/read.c
|
||||
+++ b/grub-core/commands/read.c
|
||||
@@ -23,13 +23,19 @@
|
||||
#include <grub/env.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/types.h>
|
||||
-#include <grub/command.h>
|
||||
+#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
+static const struct grub_arg_option options[] =
|
||||
+ {
|
||||
+ {"silent", 's', 0, N_("Do not echo input"), 0, 0},
|
||||
+ {0, 0, 0, 0, 0, 0}
|
||||
+ };
|
||||
+
|
||||
static char *
|
||||
-grub_getline (void)
|
||||
+grub_getline (int silent)
|
||||
{
|
||||
int i;
|
||||
char *line;
|
||||
@@ -48,7 +54,7 @@ grub_getline (void)
|
||||
break;
|
||||
|
||||
line[i] = c;
|
||||
- if (grub_isprint (c))
|
||||
+ if (!silent && grub_isprint (c))
|
||||
grub_printf ("%c", c);
|
||||
i++;
|
||||
tmp = grub_realloc (line, 1 + i + sizeof('\0'));
|
||||
@@ -65,9 +71,11 @@ grub_getline (void)
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_cmd_read (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||
+grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
- char *line = grub_getline ();
|
||||
+ struct grub_arg_list *state = ctxt->state;
|
||||
+ char *line = grub_getline (state[0].set);
|
||||
+
|
||||
if (! line)
|
||||
return grub_errno;
|
||||
if (argc > 0)
|
||||
@@ -77,16 +85,16 @@ grub_cmd_read (grub_command_t cmd __attribute__ ((unused)), int argc, char **arg
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static grub_command_t cmd;
|
||||
+static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(read)
|
||||
{
|
||||
- cmd = grub_register_command ("read", grub_cmd_read,
|
||||
- N_("[ENVVAR]"),
|
||||
- N_("Set variable with user input."));
|
||||
+ cmd = grub_register_extcmd ("read", grub_cmd_read, 0,
|
||||
+ N_("[-s] [ENVVAR]"),
|
||||
+ N_("Set variable with user input."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(read)
|
||||
{
|
||||
- grub_unregister_command (cmd);
|
||||
+ grub_unregister_extcmd (cmd);
|
||||
}
|
47
0418-commands-read-Fix-overflow-in-grub_getline.patch
Normal file
47
0418-commands-read-Fix-overflow-in-grub_getline.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Li Gen <ligenlive@gmail.com>
|
||||
Date: Thu, 25 Aug 2022 19:59:09 -0500
|
||||
Subject: [PATCH] commands/read: Fix overflow in grub_getline()
|
||||
|
||||
Store returned value from grub_getkey() in int instead of char to
|
||||
prevent throwing away the extended bits. This was a problem because,
|
||||
for instance, the left arrow key press would return
|
||||
(GRUB_TERM_EXTENDED | 0x4b), which would have the GRUB_TERM_EXTENDED
|
||||
thrown away leaving 0x4b or 'K'. These extended keys should either
|
||||
work as intended or do nothing. This change has them do nothing,
|
||||
instead of inserting a key not pressed by the user.
|
||||
|
||||
Signed-off-by: Li Gen <ligenlive@gmail.com>
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/read.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/read.c b/grub-core/commands/read.c
|
||||
index c2969ccda..597c90706 100644
|
||||
--- a/grub-core/commands/read.c
|
||||
+++ b/grub-core/commands/read.c
|
||||
@@ -40,7 +40,7 @@ grub_getline (int silent)
|
||||
int i;
|
||||
char *line;
|
||||
char *tmp;
|
||||
- char c;
|
||||
+ int c;
|
||||
|
||||
i = 0;
|
||||
line = grub_malloc (1 + i + sizeof('\0'));
|
||||
@@ -53,8 +53,11 @@ grub_getline (int silent)
|
||||
if ((c == '\n') || (c == '\r'))
|
||||
break;
|
||||
|
||||
- line[i] = c;
|
||||
- if (!silent && grub_isprint (c))
|
||||
+ if (!grub_isprint (c))
|
||||
+ continue;
|
||||
+
|
||||
+ line[i] = (char) c;
|
||||
+ if (!silent)
|
||||
grub_printf ("%c", c);
|
||||
i++;
|
||||
tmp = grub_realloc (line, 1 + i + sizeof('\0'));
|
@ -0,0 +1,69 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Bar Or <jonathanbaror@gmail.com>
|
||||
Date: Thu, 23 Jan 2025 19:17:05 +0100
|
||||
Subject: [PATCH] commands/read: Fix an integer overflow when supplying more
|
||||
than 2^31 characters
|
||||
|
||||
The grub_getline() function currently has a signed integer variable "i"
|
||||
that can be overflown when user supplies more than 2^31 characters.
|
||||
It results in a memory corruption of the allocated line buffer as well
|
||||
as supplying large negative values to grub_realloc().
|
||||
|
||||
Fixes: CVE-2025-0690
|
||||
|
||||
Reported-by: Jonathan Bar Or <jonathanbaror@gmail.com>
|
||||
Signed-off-by: Jonathan Bar Or <jonathanbaror@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/read.c | 19 +++++++++++++++----
|
||||
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/read.c b/grub-core/commands/read.c
|
||||
index 597c90706..8d72e45c9 100644
|
||||
--- a/grub-core/commands/read.c
|
||||
+++ b/grub-core/commands/read.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -37,13 +38,14 @@ static const struct grub_arg_option options[] =
|
||||
static char *
|
||||
grub_getline (int silent)
|
||||
{
|
||||
- int i;
|
||||
+ grub_size_t i;
|
||||
char *line;
|
||||
char *tmp;
|
||||
int c;
|
||||
+ grub_size_t alloc_size;
|
||||
|
||||
i = 0;
|
||||
- line = grub_malloc (1 + i + sizeof('\0'));
|
||||
+ line = grub_malloc (1 + sizeof('\0'));
|
||||
if (! line)
|
||||
return NULL;
|
||||
|
||||
@@ -59,8 +61,17 @@ grub_getline (int silent)
|
||||
line[i] = (char) c;
|
||||
if (!silent)
|
||||
grub_printf ("%c", c);
|
||||
- i++;
|
||||
- tmp = grub_realloc (line, 1 + i + sizeof('\0'));
|
||||
+ if (grub_add (i, 1, &i))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (grub_add (i, 1 + sizeof('\0'), &alloc_size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ tmp = grub_realloc (line, alloc_size);
|
||||
if (! tmp)
|
||||
{
|
||||
grub_free (line);
|
@ -0,0 +1,83 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Mon, 16 Dec 2024 20:22:41 +0000
|
||||
Subject: [PATCH] commands/test: Stack overflow due to unlimited recursion
|
||||
depth
|
||||
|
||||
The test_parse() evaluates test expression recursively. Due to lack of
|
||||
recursion depth check a specially crafted expression may cause a stack
|
||||
overflow. The recursion is only triggered by the parentheses usage and
|
||||
it can be unlimited. However, sensible expressions are unlikely to
|
||||
contain more than a few parentheses. So, this patch limits the recursion
|
||||
depth to 100, which should be sufficient.
|
||||
|
||||
Reported-by: Nils Langius <nils@langius.de>
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/test.c | 21 ++++++++++++++++++---
|
||||
1 file changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c
|
||||
index 62d3fb398..b585c3d70 100644
|
||||
--- a/grub-core/commands/test.c
|
||||
+++ b/grub-core/commands/test.c
|
||||
@@ -29,6 +29,9 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
+/* Set a limit on recursion to avoid stack overflow. */
|
||||
+#define MAX_TEST_RECURSION_DEPTH 100
|
||||
+
|
||||
/* A simple implementation for signed numbers. */
|
||||
static int
|
||||
grub_strtosl (char *arg, const char ** const end, int base)
|
||||
@@ -150,7 +153,7 @@ get_fileinfo (char *path, struct test_parse_ctx *ctx)
|
||||
|
||||
/* Parse a test expression starting from *argn. */
|
||||
static int
|
||||
-test_parse (char **args, int *argn, int argc)
|
||||
+test_parse (char **args, int *argn, int argc, int *depth)
|
||||
{
|
||||
struct test_parse_ctx ctx = {
|
||||
.and = 1,
|
||||
@@ -387,13 +390,24 @@ test_parse (char **args, int *argn, int argc)
|
||||
if (grub_strcmp (args[*argn], ")") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
+ if (*depth > 0)
|
||||
+ (*depth)--;
|
||||
+
|
||||
return ctx.or || ctx.and;
|
||||
}
|
||||
/* Recursively invoke if parenthesis. */
|
||||
if (grub_strcmp (args[*argn], "(") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
- update_val (test_parse (args, argn, argc), &ctx);
|
||||
+
|
||||
+ if (++(*depth) > MAX_TEST_RECURSION_DEPTH)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("max recursion depth exceeded"));
|
||||
+ depth--;
|
||||
+ return ctx.or || ctx.and;
|
||||
+ }
|
||||
+
|
||||
+ update_val (test_parse (args, argn, argc, depth), &ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -428,11 +442,12 @@ grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int argn = 0;
|
||||
+ int depth = 0;
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
|
||||
argc--;
|
||||
|
||||
- return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
|
||||
+ return test_parse (args, &argn, argc, &depth) ? GRUB_ERR_NONE
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Thu, 18 Apr 2024 20:29:39 +0100
|
||||
Subject: [PATCH] commands/minicmd: Block the dump command in lockdown mode
|
||||
|
||||
The dump enables a user to read memory which should not be possible
|
||||
in lockdown mode.
|
||||
|
||||
Fixes: CVE-2025-1118
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Reported-by: Jonathan Bar Or <jonathanbaror@gmail.com>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/minicmd.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
|
||||
index 2001043cf..9efb7718c 100644
|
||||
--- a/grub-core/commands/minicmd.c
|
||||
+++ b/grub-core/commands/minicmd.c
|
||||
@@ -215,8 +215,8 @@ GRUB_MOD_INIT(minicmd)
|
||||
grub_register_command ("help", grub_mini_cmd_help,
|
||||
0, N_("Show this message."));
|
||||
cmd_dump =
|
||||
- grub_register_command ("dump", grub_mini_cmd_dump,
|
||||
- N_("ADDR [SIZE]"), N_("Show memory contents."));
|
||||
+ grub_register_command_lockdown ("dump", grub_mini_cmd_dump,
|
||||
+ N_("ADDR [SIZE]"), N_("Show memory contents."));
|
||||
cmd_rmmod =
|
||||
grub_register_command ("rmmod", grub_mini_cmd_rmmod,
|
||||
N_("MODULE"), N_("Remove a module."));
|
@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Tue, 11 Feb 2025 17:12:29 -0600
|
||||
Subject: [PATCH] commands/memrw: Disable memory reading in lockdown mode
|
||||
|
||||
With the rest of module being blocked in lockdown mode it does not make
|
||||
a lot of sense to leave memory reading enabled. This also goes in par
|
||||
with disabling the dump command.
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/memrw.c | 21 ++++++++++++---------
|
||||
1 file changed, 12 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c
|
||||
index 39cf3a06d..9d8a54a4b 100644
|
||||
--- a/grub-core/commands/memrw.c
|
||||
+++ b/grub-core/commands/memrw.c
|
||||
@@ -126,17 +126,20 @@ GRUB_MOD_INIT(memrw)
|
||||
return;
|
||||
|
||||
cmd_read_byte =
|
||||
- grub_register_extcmd ("read_byte", grub_cmd_read, 0,
|
||||
- N_("ADDR"), N_("Read 8-bit value from ADDR."),
|
||||
- options);
|
||||
+ grub_register_extcmd_lockdown ("read_byte", grub_cmd_read, 0,
|
||||
+ N_("ADDR"),
|
||||
+ N_("Read 8-bit value from ADDR."),
|
||||
+ options);
|
||||
cmd_read_word =
|
||||
- grub_register_extcmd ("read_word", grub_cmd_read, 0,
|
||||
- N_("ADDR"), N_("Read 16-bit value from ADDR."),
|
||||
- options);
|
||||
+ grub_register_extcmd_lockdown ("read_word", grub_cmd_read, 0,
|
||||
+ N_("ADDR"),
|
||||
+ N_("Read 16-bit value from ADDR."),
|
||||
+ options);
|
||||
cmd_read_dword =
|
||||
- grub_register_extcmd ("read_dword", grub_cmd_read, 0,
|
||||
- N_("ADDR"), N_("Read 32-bit value from ADDR."),
|
||||
- options);
|
||||
+ grub_register_extcmd_lockdown ("read_dword", grub_cmd_read, 0,
|
||||
+ N_("ADDR"),
|
||||
+ N_("Read 32-bit value from ADDR."),
|
||||
+ options);
|
||||
cmd_write_byte =
|
||||
grub_register_command_lockdown ("write_byte", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"),
|
@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: B Horn <b@horn.uk>
|
||||
Date: Fri, 19 Apr 2024 22:31:45 +0100
|
||||
Subject: [PATCH] commands/hexdump: Disable memory reading in lockdown mode
|
||||
|
||||
Reported-by: B Horn <b@horn.uk>
|
||||
Signed-off-by: B Horn <b@horn.uk>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/hexdump.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c
|
||||
index eaa12465b..d6f61d98a 100644
|
||||
--- a/grub-core/commands/hexdump.c
|
||||
+++ b/grub-core/commands/hexdump.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <grub/lib/hexdump.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -51,7 +52,11 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
length = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 256;
|
||||
|
||||
if (!grub_strcmp (args[0], "(mem)"))
|
||||
- hexdump (skip, (char *) (grub_addr_t) skip, length);
|
||||
+ {
|
||||
+ if (grub_is_lockdown() == GRUB_LOCKDOWN_ENABLED)
|
||||
+ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("memory reading is disabled in lockdown mode"));
|
||||
+ hexdump (skip, (char *) (grub_addr_t) skip, length);
|
||||
+ }
|
||||
else if ((args[0][0] == '(') && (args[0][namelen - 1] == ')'))
|
||||
{
|
||||
grub_disk_t disk;
|
52
0424-fs-bfs-Disable-under-lockdown.patch
Normal file
52
0424-fs-bfs-Disable-under-lockdown.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Sat, 23 Mar 2024 15:59:43 +1100
|
||||
Subject: [PATCH] fs/bfs: Disable under lockdown
|
||||
|
||||
The BFS is not fuzz-clean. Don't allow it to be loaded under lockdown.
|
||||
This will also disable the AFS.
|
||||
|
||||
Fixes: CVE-2024-45778
|
||||
Fixes: CVE-2024-45779
|
||||
|
||||
Reported-by: Nils Langius <nils@langius.de>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/bfs.c | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c
|
||||
index 17705812d..760c6229a 100644
|
||||
--- a/grub-core/fs/bfs.c
|
||||
+++ b/grub-core/fs/bfs.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/fshelp.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -1104,8 +1105,11 @@ GRUB_MOD_INIT (bfs)
|
||||
{
|
||||
COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE ==
|
||||
sizeof (struct grub_bfs_extent));
|
||||
- grub_bfs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_bfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_bfs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_bfs_fs);
|
||||
+ }
|
||||
}
|
||||
|
||||
#ifdef MODE_AFS
|
||||
@@ -1114,5 +1118,6 @@ GRUB_MOD_FINI (afs)
|
||||
GRUB_MOD_FINI (bfs)
|
||||
#endif
|
||||
{
|
||||
- grub_fs_unregister (&grub_bfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_bfs_fs);
|
||||
}
|
391
0425-fs-Disable-many-filesystems-under-lockdown.patch
Normal file
391
0425-fs-Disable-many-filesystems-under-lockdown.patch
Normal file
@ -0,0 +1,391 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Sat, 23 Mar 2024 16:20:45 +1100
|
||||
Subject: [PATCH] fs: Disable many filesystems under lockdown
|
||||
|
||||
The idea is to permit the following: btrfs, cpio, exfat, ext, f2fs, fat,
|
||||
hfsplus, iso9660, squash4, tar, xfs and zfs.
|
||||
|
||||
The JFS, ReiserFS, romfs, UDF and UFS security vulnerabilities were
|
||||
reported by Jonathan Bar Or <jonathanbaror@gmail.com>.
|
||||
|
||||
Fixes: CVE-2025-0677
|
||||
Fixes: CVE-2025-0684
|
||||
Fixes: CVE-2025-0685
|
||||
Fixes: CVE-2025-0686
|
||||
Fixes: CVE-2025-0689
|
||||
|
||||
Suggested-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/affs.c | 11 ++++++++---
|
||||
grub-core/fs/cbfs.c | 11 ++++++++---
|
||||
grub-core/fs/jfs.c | 11 ++++++++---
|
||||
grub-core/fs/minix.c | 11 ++++++++---
|
||||
grub-core/fs/nilfs2.c | 11 ++++++++---
|
||||
grub-core/fs/ntfs.c | 11 ++++++++---
|
||||
grub-core/fs/reiserfs.c | 11 ++++++++---
|
||||
grub-core/fs/romfs.c | 11 ++++++++---
|
||||
grub-core/fs/sfs.c | 11 ++++++++---
|
||||
grub-core/fs/udf.c | 11 ++++++++---
|
||||
grub-core/fs/ufs.c | 11 ++++++++---
|
||||
11 files changed, 88 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
|
||||
index b1c64e77d..0133528ea 100644
|
||||
--- a/grub-core/fs/affs.c
|
||||
+++ b/grub-core/fs/affs.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/charset.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -699,12 +700,16 @@ static struct grub_fs grub_affs_fs =
|
||||
|
||||
GRUB_MOD_INIT(affs)
|
||||
{
|
||||
- grub_affs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_affs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_affs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_affs_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(affs)
|
||||
{
|
||||
- grub_fs_unregister (&grub_affs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_affs_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
|
||||
index 3e527cbf2..90c07ddf8 100644
|
||||
--- a/grub-core/fs/cbfs.c
|
||||
+++ b/grub-core/fs/cbfs.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/cbfs_core.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -390,13 +391,17 @@ GRUB_MOD_INIT (cbfs)
|
||||
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
|
||||
init_cbfsdisk ();
|
||||
#endif
|
||||
- grub_cbfs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_cbfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_cbfs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_cbfs_fs);
|
||||
+ }
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (cbfs)
|
||||
{
|
||||
- grub_fs_unregister (&grub_cbfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_cbfs_fs);
|
||||
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
|
||||
fini_cbfsdisk ();
|
||||
#endif
|
||||
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
||||
index b0283ac00..ab175c7f1 100644
|
||||
--- a/grub-core/fs/jfs.c
|
||||
+++ b/grub-core/fs/jfs.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -1005,12 +1006,16 @@ static struct grub_fs grub_jfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(jfs)
|
||||
{
|
||||
- grub_jfs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_jfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_jfs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_jfs_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(jfs)
|
||||
{
|
||||
- grub_fs_unregister (&grub_jfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_jfs_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
|
||||
index beb1a6378..fc7fa80d9 100644
|
||||
--- a/grub-core/fs/minix.c
|
||||
+++ b/grub-core/fs/minix.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -732,8 +733,11 @@ GRUB_MOD_INIT(minix)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
- grub_minix_fs.mod = mod;
|
||||
- grub_fs_register (&grub_minix_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_minix_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_minix_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
@@ -755,5 +759,6 @@ GRUB_MOD_FINI(minix)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
- grub_fs_unregister (&grub_minix_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_minix_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
|
||||
index c44583ee8..dd10c08f3 100644
|
||||
--- a/grub-core/fs/nilfs2.c
|
||||
+++ b/grub-core/fs/nilfs2.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -1231,12 +1232,16 @@ GRUB_MOD_INIT (nilfs2)
|
||||
grub_nilfs2_dat_entry));
|
||||
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
|
||||
== sizeof (struct grub_nilfs2_inode));
|
||||
- grub_nilfs2_fs.mod = mod;
|
||||
- grub_fs_register (&grub_nilfs2_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_nilfs2_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_nilfs2_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (nilfs2)
|
||||
{
|
||||
- grub_fs_unregister (&grub_nilfs2_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_nilfs2_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index 03e3e5c6a..96f038c54 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/ntfs.h>
|
||||
#include <grub/charset.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -1537,12 +1538,16 @@ static struct grub_fs grub_ntfs_fs =
|
||||
|
||||
GRUB_MOD_INIT (ntfs)
|
||||
{
|
||||
- grub_ntfs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_ntfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_ntfs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_ntfs_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (ntfs)
|
||||
{
|
||||
- grub_fs_unregister (&grub_ntfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_ntfs_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
|
||||
index d9a8bf602..84aadfae9 100644
|
||||
--- a/grub-core/fs/reiserfs.c
|
||||
+++ b/grub-core/fs/reiserfs.c
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -1407,12 +1408,16 @@ static struct grub_fs grub_reiserfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(reiserfs)
|
||||
{
|
||||
- grub_reiserfs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_reiserfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_reiserfs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_reiserfs_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(reiserfs)
|
||||
{
|
||||
- grub_fs_unregister (&grub_reiserfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_reiserfs_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
|
||||
index a43546d95..6ee469911 100644
|
||||
--- a/grub-core/fs/romfs.c
|
||||
+++ b/grub-core/fs/romfs.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <grub/disk.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/fshelp.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -475,11 +476,15 @@ static struct grub_fs grub_romfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(romfs)
|
||||
{
|
||||
- grub_romfs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_romfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_romfs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_romfs_fs);
|
||||
+ }
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(romfs)
|
||||
{
|
||||
- grub_fs_unregister (&grub_romfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_romfs_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
|
||||
index f0d7cac43..88705b3a2 100644
|
||||
--- a/grub-core/fs/sfs.c
|
||||
+++ b/grub-core/fs/sfs.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/charset.h>
|
||||
+#include <grub/lockdown.h>
|
||||
#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
@@ -779,12 +780,16 @@ static struct grub_fs grub_sfs_fs =
|
||||
|
||||
GRUB_MOD_INIT(sfs)
|
||||
{
|
||||
- grub_sfs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_sfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_sfs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_sfs_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(sfs)
|
||||
{
|
||||
- grub_fs_unregister (&grub_sfs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_sfs_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
|
||||
index 3d4b40263..c0c31ae9c 100644
|
||||
--- a/grub-core/fs/udf.c
|
||||
+++ b/grub-core/fs/udf.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/datetime.h>
|
||||
+#include <grub/lockdown.h>
|
||||
#include <grub/udf.h>
|
||||
#include <grub/safemath.h>
|
||||
|
||||
@@ -1382,12 +1383,16 @@ static struct grub_fs grub_udf_fs = {
|
||||
|
||||
GRUB_MOD_INIT (udf)
|
||||
{
|
||||
- grub_udf_fs.mod = mod;
|
||||
- grub_fs_register (&grub_udf_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_udf_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_udf_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (udf)
|
||||
{
|
||||
- grub_fs_unregister (&grub_udf_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_udf_fs);
|
||||
}
|
||||
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
|
||||
index 7f72494cd..22b669b4c 100644
|
||||
--- a/grub-core/fs/ufs.c
|
||||
+++ b/grub-core/fs/ufs.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/lockdown.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -899,8 +900,11 @@ GRUB_MOD_INIT(ufs1)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
- grub_ufs_fs.mod = mod;
|
||||
- grub_fs_register (&grub_ufs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ {
|
||||
+ grub_ufs_fs.mod = mod;
|
||||
+ grub_fs_register (&grub_ufs_fs);
|
||||
+ }
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
@@ -914,6 +918,7 @@ GRUB_MOD_FINI(ufs1)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
- grub_fs_unregister (&grub_ufs_fs);
|
||||
+ if (!grub_is_lockdown ())
|
||||
+ grub_fs_unregister (&grub_ufs_fs);
|
||||
}
|
||||
|
603
0426-disk-plainmount-Support-plain-encryption-mode.patch
Normal file
603
0426-disk-plainmount-Support-plain-encryption-mode.patch
Normal file
@ -0,0 +1,603 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Maxim Fomin <maxim@fomin.one>
|
||||
Date: Wed, 28 Dec 2022 17:20:00 +0000
|
||||
Subject: [PATCH] disk/plainmount: Support plain encryption mode
|
||||
|
||||
This patch adds support for plain encryption mode, plain dm-crypt, via
|
||||
new module/command named "plainmount".
|
||||
|
||||
Signed-off-by: Maxim Fomin <maxim@fomin.one>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Glenn Washburn <development@efficientek.com>
|
||||
---
|
||||
docs/grub.texi | 80 ++++++++
|
||||
grub-core/Makefile.core.def | 5 +
|
||||
grub-core/disk/plainmount.c | 458 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 543 insertions(+)
|
||||
create mode 100644 grub-core/disk/plainmount.c
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index 913c3bff3..50c37d6ff 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -4052,6 +4052,7 @@ you forget a command, you can run the command @command{help}
|
||||
* parttool:: Modify partition table entries
|
||||
* password:: Set a clear-text password
|
||||
* password_pbkdf2:: Set a hashed password
|
||||
+* plainmount:: Open device encrypted in plain mode
|
||||
* play:: Play a tune
|
||||
* probe:: Retrieve device info
|
||||
* rdmsr:: Read values from model-specific registers
|
||||
@@ -4344,6 +4345,14 @@ function is supported, as Argon2 is not yet supported.
|
||||
|
||||
Also, note that, unlike filesystem UUIDs, UUIDs for encrypted devices must be
|
||||
specified without dash separators.
|
||||
+
|
||||
+Successfully decrypted disks are named as (cryptoX) and have increasing numeration
|
||||
+suffix for each new decrypted disk. If the encrypted disk hosts some higher level
|
||||
+of abstraction (like LVM2 or MDRAID) it will be created under a separate device
|
||||
+namespace in addition to the cryptodisk namespace.
|
||||
+
|
||||
+Support for plain encryption mode (plain dm-crypt) is provided via separate
|
||||
+@command{@pxref{plainmount}} command.
|
||||
@end deffn
|
||||
|
||||
@node cutmem
|
||||
@@ -4990,6 +4999,77 @@ to generate password hashes. @xref{Security}.
|
||||
@end deffn
|
||||
|
||||
|
||||
+@node plainmount
|
||||
+@subsection plainmount
|
||||
+
|
||||
+@deffn Command plainmount device @option{-c} cipher @option{-s} key size [@option{-h} hash]
|
||||
+[@option{-S} sector size] [@option{-p} password] [@option{-u} uuid]
|
||||
+[[@option{-d} keyfile] [@option{-O} keyfile offset]]
|
||||
+
|
||||
+
|
||||
+Setup access to the encrypted device in plain mode. Offset of the encrypted
|
||||
+data at the device is specified in terms of 512 byte sectors using the blocklist
|
||||
+syntax and loopback device. The following example shows how to specify 1MiB
|
||||
+offset:
|
||||
+
|
||||
+@example
|
||||
+loopback node (hd0,gpt1)2048+
|
||||
+plainmount node @var{...}
|
||||
+@end example
|
||||
+
|
||||
+The @command{plainmount} command can be used to open LUKS encrypted volume
|
||||
+if its master key and parameters (key size, cipher, offset, etc) are known.
|
||||
+
|
||||
+There are two ways to specify a password: a keyfile and a secret passphrase.
|
||||
+The keyfile path parameter has higher priority than the secret passphrase
|
||||
+parameter and is specified with the option @option{-d}. Password data obtained
|
||||
+from keyfiles is not hashed and is used directly as a cipher key. An optional
|
||||
+offset of password data in the keyfile can be specified with the option
|
||||
+@option{-O} or directly with the option @option{-d} and GRUB blocklist syntax,
|
||||
+if the keyfile data can be accessed from a device and is 512 byte aligned.
|
||||
+The following example shows both methods to specify password data in the
|
||||
+keyfile at offset 1MiB:
|
||||
+
|
||||
+@example
|
||||
+plainmount -d (hd0,gpt1)2048+ @var{...}
|
||||
+plainmount -d (hd0,gpt1)+ -O 1048576 @var{...}
|
||||
+@end example
|
||||
+
|
||||
+If no keyfile is specified then the password is set to the string specified
|
||||
+by option @option{-p} or is requested interactively from the console. In both
|
||||
+cases the provided password is hashed with the algorithm specified by the
|
||||
+option @option{-h}. This option is mandatory if no keyfile is specified, but
|
||||
+it can be set to @samp{plain} which means that no hashing is done and such
|
||||
+password is used directly as a key.
|
||||
+
|
||||
+Cipher @option{-c} and keysize @option{-s} options specify the cipher algorithm
|
||||
+and the key size respectively and are mandatory options. Cipher must be specified
|
||||
+with the mode separated by a dash (for example, @samp{aes-xts-plain64}). Key size
|
||||
+option @option{-s} is the key size of the cipher in bits, not to be confused with
|
||||
+the offset of the key data in a keyfile specified with the @option{-O} option. It
|
||||
+must not exceed 1024 bits, so a 32 byte key would be specified as 256 bits
|
||||
+
|
||||
+The optional parameter @option{-S} specifies encrypted device sector size. It
|
||||
+must be at least 512 bytes long (default value) and a power of 2. @footnote{Current
|
||||
+implementation of cryptsetup supports only 512/1024/2048/4096 byte sectors}.
|
||||
+Disk sector size is configured when creating the encrypted volume. Attempting
|
||||
+to decrypt volumes with a different sector size than it was created with will
|
||||
+not result in an error, but will decrypt to random bytes and thus prevent
|
||||
+accessing the volume (in some cases the filesystem driver can detect the presence
|
||||
+of a filesystem, but nevertheless will refuse to mount it).
|
||||
+
|
||||
+By default new plainmount devices will be given a UUID starting with
|
||||
+'109fea84-a6b7-34a8-4bd1-1c506305a401' where the last digits are incremented
|
||||
+by one for each plainmounted device beyond the first up to 2^10 devices.
|
||||
+
|
||||
+All encryption arguments (cipher, hash, key size, disk offset and disk sector
|
||||
+size) must match the parameters used to create the volume. If any of them does
|
||||
+not match the actual arguments used during the initial encryption, plainmount
|
||||
+will create virtual device with the garbage data and GRUB will report unknown
|
||||
+filesystem for such device.
|
||||
+@end deffn
|
||||
+
|
||||
+
|
||||
@node play
|
||||
@subsection play
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 505c3b63d..b8e29c788 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -1239,6 +1239,11 @@ module = {
|
||||
common = disk/cryptodisk.c;
|
||||
};
|
||||
|
||||
+module = {
|
||||
+ name = plainmount;
|
||||
+ common = disk/plainmount.c;
|
||||
+};
|
||||
+
|
||||
module = {
|
||||
name = json;
|
||||
common = lib/json/json.c;
|
||||
diff --git a/grub-core/disk/plainmount.c b/grub-core/disk/plainmount.c
|
||||
new file mode 100644
|
||||
index 000000000..47e64805f
|
||||
--- /dev/null
|
||||
+++ b/grub-core/disk/plainmount.c
|
||||
@@ -0,0 +1,458 @@
|
||||
+/*
|
||||
+ * 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/>.
|
||||
+ */
|
||||
+
|
||||
+/* plaimount.c - Open device encrypted in plain mode. */
|
||||
+
|
||||
+#include <grub/cryptodisk.h>
|
||||
+#include <grub/dl.h>
|
||||
+#include <grub/err.h>
|
||||
+#include <grub/extcmd.h>
|
||||
+#include <grub/partition.h>
|
||||
+#include <grub/file.h>
|
||||
+
|
||||
+GRUB_MOD_LICENSE ("GPLv3+");
|
||||
+
|
||||
+#define PLAINMOUNT_DEFAULT_SECTOR_SIZE 512
|
||||
+#define PLAINMOUNT_DEFAULT_UUID "109fea84-a6b7-34a8-4bd1-1c506305a400"
|
||||
+
|
||||
+
|
||||
+enum PLAINMOUNT_OPTION
|
||||
+ {
|
||||
+ OPTION_HASH,
|
||||
+ OPTION_CIPHER,
|
||||
+ OPTION_KEY_SIZE,
|
||||
+ OPTION_SECTOR_SIZE,
|
||||
+ OPTION_PASSWORD,
|
||||
+ OPTION_KEYFILE,
|
||||
+ OPTION_KEYFILE_OFFSET,
|
||||
+ OPTION_UUID
|
||||
+ };
|
||||
+
|
||||
+static const struct grub_arg_option options[] =
|
||||
+ {
|
||||
+ /* TRANSLATORS: It's still restricted to this module only. */
|
||||
+ {"hash", 'h', 0, N_("Password hash"), 0, ARG_TYPE_STRING},
|
||||
+ {"cipher", 'c', 0, N_("Password cipher"), 0, ARG_TYPE_STRING},
|
||||
+ {"key-size", 's', 0, N_("Key size (in bits)"), 0, ARG_TYPE_INT},
|
||||
+ {"sector-size", 'S', 0, N_("Device sector size"), 0, ARG_TYPE_INT},
|
||||
+ {"password", 'p', 0, N_("Password (key)"), 0, ARG_TYPE_STRING},
|
||||
+ {"keyfile", 'd', 0, N_("Keyfile path"), 0, ARG_TYPE_STRING},
|
||||
+ {"keyfile-offset", 'O', 0, N_("Keyfile offset"), 0, ARG_TYPE_INT},
|
||||
+ {"uuid", 'u', 0, N_("Set device UUID"), 0, ARG_TYPE_STRING},
|
||||
+ {0, 0, 0, 0, 0, 0}
|
||||
+ };
|
||||
+
|
||||
+/* Cryptodisk setkey() function wrapper */
|
||||
+static grub_err_t
|
||||
+plainmount_setkey (grub_cryptodisk_t dev, grub_uint8_t *key,
|
||||
+ grub_size_t size)
|
||||
+{
|
||||
+ gcry_err_code_t code = grub_cryptodisk_setkey (dev, key, size);
|
||||
+ if (code != GPG_ERR_NO_ERROR)
|
||||
+ {
|
||||
+ grub_dprintf ("plainmount", "failed to set cipher key with code: %d\n", code);
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot set specified key"));
|
||||
+ }
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/* Configure cryptodisk uuid */
|
||||
+static void plainmount_set_uuid (grub_cryptodisk_t dev, const char *user_uuid)
|
||||
+{
|
||||
+ grub_size_t pos = 0;
|
||||
+
|
||||
+ /* Size of user_uuid is checked in main func */
|
||||
+ if (user_uuid != NULL)
|
||||
+ grub_strcpy (dev->uuid, user_uuid);
|
||||
+ else
|
||||
+ {
|
||||
+ /*
|
||||
+ * Set default UUID. Last digits start from 1 and are incremented for
|
||||
+ * each new plainmount device by snprintf().
|
||||
+ */
|
||||
+ grub_snprintf (dev->uuid, sizeof (dev->uuid) - 1, "%36lx", dev->id + 1);
|
||||
+ while (dev->uuid[++pos] == ' ');
|
||||
+ grub_memcpy (dev->uuid, PLAINMOUNT_DEFAULT_UUID, pos);
|
||||
+ }
|
||||
+ COMPILE_TIME_ASSERT (sizeof (dev->uuid) >= sizeof (PLAINMOUNT_DEFAULT_UUID));
|
||||
+}
|
||||
+
|
||||
+/* Configure cryptodevice sector size (-S option) */
|
||||
+static grub_err_t
|
||||
+plainmount_configure_sectors (grub_cryptodisk_t dev, grub_disk_t disk,
|
||||
+ grub_size_t sector_size)
|
||||
+{
|
||||
+ dev->total_sectors = grub_disk_native_sectors (disk);
|
||||
+ if (dev->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
|
||||
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot determine disk %s size"),
|
||||
+ disk->name);
|
||||
+
|
||||
+ /* Convert size to sectors */
|
||||
+ dev->log_sector_size = grub_log2ull (sector_size);
|
||||
+ dev->total_sectors = grub_convert_sector (dev->total_sectors,
|
||||
+ GRUB_DISK_SECTOR_BITS,
|
||||
+ dev->log_sector_size);
|
||||
+ if (dev->total_sectors == 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
+ N_("cannot set specified sector size on disk %s"),
|
||||
+ disk->name);
|
||||
+
|
||||
+ grub_dprintf ("plainmount", "log_sector_size=%d, total_sectors=%"
|
||||
+ PRIuGRUB_UINT64_T"\n", dev->log_sector_size, dev->total_sectors);
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/* Hashes a password into a key and stores it with the cipher. */
|
||||
+static grub_err_t
|
||||
+plainmount_configure_password (grub_cryptodisk_t dev, const char *hash,
|
||||
+ grub_uint8_t *key_data, grub_size_t key_size,
|
||||
+ grub_size_t password_size)
|
||||
+{
|
||||
+ grub_uint8_t *derived_hash, *dh;
|
||||
+ char *p;
|
||||
+ unsigned int round, i, len, size;
|
||||
+ grub_size_t alloc_size;
|
||||
+ grub_err_t err = GRUB_ERR_NONE;
|
||||
+
|
||||
+ /* Support none (plain) hash */
|
||||
+ if (grub_strcmp (hash, "plain") == 0)
|
||||
+ {
|
||||
+ dev->hash = NULL;
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Hash argument was checked at main func */
|
||||
+ dev->hash = grub_crypto_lookup_md_by_name (hash);
|
||||
+ len = dev->hash->mdlen;
|
||||
+
|
||||
+ alloc_size = grub_max (password_size, key_size);
|
||||
+ /*
|
||||
+ * Allocate buffer for the password and for an added prefix character
|
||||
+ * for each hash round ('alloc_size' may not be a multiple of 'len').
|
||||
+ */
|
||||
+ p = grub_zalloc (alloc_size + (alloc_size / len) + 1);
|
||||
+ derived_hash = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN * 2);
|
||||
+ if (p == NULL || derived_hash == NULL)
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ dh = derived_hash;
|
||||
+
|
||||
+ /*
|
||||
+ * Hash password. Adapted from cryptsetup.
|
||||
+ * https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/lib/crypt_plain.c
|
||||
+ */
|
||||
+ for (round = 0, size = alloc_size; size; round++, dh += len, size -= len)
|
||||
+ {
|
||||
+ for (i = 0; i < round; i++)
|
||||
+ p[i] = 'A';
|
||||
+
|
||||
+ grub_memcpy (p + i, (char*) key_data, password_size);
|
||||
+
|
||||
+ if (len > size)
|
||||
+ len = size;
|
||||
+
|
||||
+ grub_crypto_hash (dev->hash, dh, p, password_size + round);
|
||||
+ }
|
||||
+ grub_memcpy (key_data, derived_hash, key_size);
|
||||
+
|
||||
+ fail:
|
||||
+ grub_free (p);
|
||||
+ grub_free (derived_hash);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/* Read key material from keyfile */
|
||||
+static grub_err_t
|
||||
+plainmount_configure_keyfile (char *keyfile, grub_uint8_t *key_data,
|
||||
+ grub_size_t key_size, grub_size_t keyfile_offset)
|
||||
+{
|
||||
+ grub_file_t g_keyfile = grub_file_open (keyfile, GRUB_FILE_TYPE_NONE);
|
||||
+ if (g_keyfile == NULL)
|
||||
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("cannot open keyfile %s"),
|
||||
+ keyfile);
|
||||
+
|
||||
+ if (grub_file_seek (g_keyfile, keyfile_offset) == (grub_off_t) - 1)
|
||||
+ return grub_error (GRUB_ERR_FILE_READ_ERROR,
|
||||
+ N_("cannot seek keyfile at offset %"PRIuGRUB_SIZE),
|
||||
+ keyfile_offset);
|
||||
+
|
||||
+ if (key_size > (g_keyfile->size - keyfile_offset))
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Specified key size (%"
|
||||
+ PRIuGRUB_SIZE") is too small for keyfile size (%"
|
||||
+ PRIuGRUB_UINT64_T") and offset (%"PRIuGRUB_SIZE")"),
|
||||
+ key_size, g_keyfile->size, keyfile_offset);
|
||||
+
|
||||
+ if (grub_file_read (g_keyfile, key_data, key_size) != (grub_ssize_t) key_size)
|
||||
+ return grub_error (GRUB_ERR_FILE_READ_ERROR, N_("error reading key file"));
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+/* Plainmount command entry point */
|
||||
+static grub_err_t
|
||||
+grub_cmd_plainmount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
+{
|
||||
+ struct grub_arg_list *state = ctxt->state;
|
||||
+ grub_cryptodisk_t dev = NULL;
|
||||
+ grub_disk_t disk = NULL;
|
||||
+ const gcry_md_spec_t *gcry_hash;
|
||||
+ char *diskname, *disklast = NULL, *cipher, *mode, *hash, *keyfile, *uuid;
|
||||
+ grub_size_t len, key_size, sector_size, keyfile_offset = 0, password_size = 0;
|
||||
+ grub_err_t err;
|
||||
+ const char *p;
|
||||
+ grub_uint8_t *key_data;
|
||||
+
|
||||
+ if (argc < 1)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("device name required"));
|
||||
+
|
||||
+ /* Check whether required arguments are specified */
|
||||
+ if (!state[OPTION_CIPHER].set || !state[OPTION_KEY_SIZE].set)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "cipher and key size must be set");
|
||||
+ if (!state[OPTION_HASH].set && !state[OPTION_KEYFILE].set)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "hash algorithm must be set");
|
||||
+
|
||||
+ /* Check hash */
|
||||
+ if (!state[OPTION_KEYFILE].set)
|
||||
+ {
|
||||
+ gcry_hash = grub_crypto_lookup_md_by_name (state[OPTION_HASH].arg);
|
||||
+ if (!gcry_hash)
|
||||
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("couldn't load hash %s"),
|
||||
+ state[OPTION_HASH].arg);
|
||||
+
|
||||
+ if (gcry_hash->mdlen > GRUB_CRYPTODISK_MAX_KEYLEN)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("hash length %"PRIuGRUB_SIZE" exceeds maximum %d bits"),
|
||||
+ gcry_hash->mdlen * GRUB_CHAR_BIT,
|
||||
+ GRUB_CRYPTODISK_MAX_KEYLEN * GRUB_CHAR_BIT);
|
||||
+ }
|
||||
+
|
||||
+ /* Check cipher mode */
|
||||
+ if (!grub_strchr (state[OPTION_CIPHER].arg,'-'))
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("invalid cipher mode, must be of format cipher-mode"));
|
||||
+
|
||||
+ /* Check password size */
|
||||
+ if (state[OPTION_PASSWORD].set && grub_strlen (state[OPTION_PASSWORD].arg) >
|
||||
+ GRUB_CRYPTODISK_MAX_PASSPHRASE)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("password exceeds maximium size"));
|
||||
+
|
||||
+ /* Check uuid length */
|
||||
+ if (state[OPTION_UUID].set && grub_strlen (state[OPTION_UUID].arg) >
|
||||
+ GRUB_CRYPTODISK_MAX_UUID_LENGTH - 1)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("specified UUID exceeds maximum size"));
|
||||
+ if (state[OPTION_UUID].set && grub_strlen (state[OPTION_UUID].arg) == 1)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("specified UUID too short"));
|
||||
+
|
||||
+ /* Parse plainmount arguments */
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+ keyfile_offset = state[OPTION_KEYFILE_OFFSET].set ?
|
||||
+ grub_strtoull (state[OPTION_KEYFILE_OFFSET].arg, &p, 0) : 0;
|
||||
+ if (state[OPTION_KEYFILE_OFFSET].set &&
|
||||
+ (state[OPTION_KEYFILE_OFFSET].arg[0] == '\0' || *p != '\0' ||
|
||||
+ grub_errno != GRUB_ERR_NONE))
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized keyfile offset"));
|
||||
+
|
||||
+ sector_size = state[OPTION_SECTOR_SIZE].set ?
|
||||
+ grub_strtoull (state[OPTION_SECTOR_SIZE].arg, &p, 0) :
|
||||
+ PLAINMOUNT_DEFAULT_SECTOR_SIZE;
|
||||
+ if (state[OPTION_SECTOR_SIZE].set && (state[OPTION_SECTOR_SIZE].arg[0] == '\0' ||
|
||||
+ *p != '\0' || grub_errno != GRUB_ERR_NONE))
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized sector size"));
|
||||
+
|
||||
+ /* Check key size */
|
||||
+ key_size = grub_strtoull (state[OPTION_KEY_SIZE].arg, &p, 0);
|
||||
+ if (state[OPTION_KEY_SIZE].arg[0] == '\0' || *p != '\0' ||
|
||||
+ grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized key size"));
|
||||
+ if ((key_size % GRUB_CHAR_BIT) != 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("key size is not multiple of %d bits"), GRUB_CHAR_BIT);
|
||||
+ key_size = key_size / GRUB_CHAR_BIT;
|
||||
+ if (key_size > GRUB_CRYPTODISK_MAX_KEYLEN)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("key size %"PRIuGRUB_SIZE" exceeds maximum %d bits"),
|
||||
+ key_size * GRUB_CHAR_BIT,
|
||||
+ GRUB_CRYPTODISK_MAX_KEYLEN * GRUB_CHAR_BIT);
|
||||
+
|
||||
+ /* Check disk sector size */
|
||||
+ if (sector_size < GRUB_DISK_SECTOR_SIZE)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("sector size -S must be at least %d"),
|
||||
+ GRUB_DISK_SECTOR_SIZE);
|
||||
+ if ((sector_size & (sector_size - 1)) != 0)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("sector size -S %"PRIuGRUB_SIZE" is not power of 2"),
|
||||
+ sector_size);
|
||||
+
|
||||
+ /* Allocate all stuff here */
|
||||
+ hash = state[OPTION_HASH].set ? grub_strdup (state[OPTION_HASH].arg) : NULL;
|
||||
+ cipher = grub_strdup (state[OPTION_CIPHER].arg);
|
||||
+ keyfile = state[OPTION_KEYFILE].set ?
|
||||
+ grub_strdup (state[OPTION_KEYFILE].arg) : NULL;
|
||||
+ dev = grub_zalloc (sizeof *dev);
|
||||
+ key_data = grub_zalloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
|
||||
+ uuid = state[OPTION_UUID].set ? grub_strdup (state[OPTION_UUID].arg) : NULL;
|
||||
+ if ((state[OPTION_HASH].set && hash == NULL) || cipher == NULL || dev == NULL ||
|
||||
+ (state[OPTION_KEYFILE].set && keyfile == NULL) || key_data == NULL ||
|
||||
+ (state[OPTION_UUID].set && uuid == NULL))
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Copy user password from -p option */
|
||||
+ if (state[OPTION_PASSWORD].set)
|
||||
+ {
|
||||
+ /*
|
||||
+ * Password from the '-p' option is limited to C-string.
|
||||
+ * Arbitrary data keys are supported via keyfiles.
|
||||
+ */
|
||||
+ password_size = grub_strlen (state[OPTION_PASSWORD].arg);
|
||||
+ grub_strcpy ((char*) key_data, state[OPTION_PASSWORD].arg);
|
||||
+ }
|
||||
+
|
||||
+ /* Set cipher mode (tested above) */
|
||||
+ mode = grub_strchr (cipher,'-');
|
||||
+ *mode++ = '\0';
|
||||
+
|
||||
+ /* Check cipher */
|
||||
+ err = grub_cryptodisk_setcipher (dev, cipher, mode);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ if (err == GRUB_ERR_FILE_NOT_FOUND)
|
||||
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid cipher %s"), cipher);
|
||||
+ else if (err == GRUB_ERR_BAD_ARGUMENT)
|
||||
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid mode %s"), mode);
|
||||
+ else
|
||||
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid cipher %s or mode %s"),
|
||||
+ cipher, mode);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Open SOURCE disk */
|
||||
+ diskname = args[0];
|
||||
+ len = grub_strlen (diskname);
|
||||
+ if (len && diskname[0] == '(' && diskname[len - 1] == ')')
|
||||
+ {
|
||||
+ disklast = &diskname[len - 1];
|
||||
+ *disklast = '\0';
|
||||
+ diskname++;
|
||||
+ }
|
||||
+ disk = grub_disk_open (diskname);
|
||||
+ if (disk == NULL)
|
||||
+ {
|
||||
+ if (disklast)
|
||||
+ *disklast = ')';
|
||||
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot open disk %s"), diskname);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Get password from console */
|
||||
+ if (!state[OPTION_KEYFILE].set && key_data[0] == '\0')
|
||||
+ {
|
||||
+ char *part = grub_partition_get_name (disk->partition);
|
||||
+ grub_printf_ (N_("Enter passphrase for %s%s%s: "), disk->name,
|
||||
+ disk->partition != NULL ? "," : "",
|
||||
+ part != NULL ? part : N_("UNKNOWN"));
|
||||
+ grub_free (part);
|
||||
+
|
||||
+ if (!grub_password_get ((char*) key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE - 1))
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("error reading password"));
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ /*
|
||||
+ * Password from interactive console is limited to C-string.
|
||||
+ * Arbitrary data keys are supported via keyfiles.
|
||||
+ */
|
||||
+ password_size = grub_strlen ((char*) key_data);
|
||||
+ }
|
||||
+
|
||||
+ /* Warn if hash and keyfile are both provided */
|
||||
+ if (state[OPTION_KEYFILE].set && state[OPTION_HASH].arg)
|
||||
+ grub_printf_ (N_("warning: hash is ignored if keyfile is specified\n"));
|
||||
+
|
||||
+ /* Warn if -p option is specified with keyfile */
|
||||
+ if (state[OPTION_PASSWORD].set && state[OPTION_KEYFILE].set)
|
||||
+ grub_printf_ (N_("warning: password specified with -p option "
|
||||
+ "is ignored if keyfile is provided\n"));
|
||||
+
|
||||
+ /* Warn of -O is provided without keyfile */
|
||||
+ if (state[OPTION_KEYFILE_OFFSET].set && !state[OPTION_KEYFILE].set)
|
||||
+ grub_printf_ (N_("warning: keyfile offset option -O "
|
||||
+ "specified without keyfile option -d\n"));
|
||||
+
|
||||
+ grub_dprintf ("plainmount", "parameters: cipher=%s, hash=%s, key_size=%"
|
||||
+ PRIuGRUB_SIZE ", keyfile=%s, keyfile offset=%" PRIuGRUB_SIZE "\n",
|
||||
+ cipher, hash, key_size, keyfile, keyfile_offset);
|
||||
+
|
||||
+ err = plainmount_configure_sectors (dev, disk, sector_size);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ goto fail;
|
||||
+
|
||||
+ /* Configure keyfile or password */
|
||||
+ if (state[OPTION_KEYFILE].set)
|
||||
+ err = plainmount_configure_keyfile (keyfile, key_data, key_size, keyfile_offset);
|
||||
+ else
|
||||
+ err = plainmount_configure_password (dev, hash, key_data, key_size, password_size);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ goto fail;
|
||||
+
|
||||
+ err = plainmount_setkey (dev, key_data, key_size);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ goto fail;
|
||||
+
|
||||
+ err = grub_cryptodisk_insert (dev, diskname, disk);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ goto fail;
|
||||
+
|
||||
+ dev->modname = "plainmount";
|
||||
+ dev->source_disk = disk;
|
||||
+ plainmount_set_uuid (dev, uuid);
|
||||
+
|
||||
+ fail:
|
||||
+ grub_free (hash);
|
||||
+ grub_free (cipher);
|
||||
+ grub_free (keyfile);
|
||||
+ grub_free (key_data);
|
||||
+ grub_free (uuid);
|
||||
+ if (err != GRUB_ERR_NONE && disk != NULL)
|
||||
+ grub_disk_close (disk);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ grub_free (dev);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static grub_extcmd_t cmd;
|
||||
+GRUB_MOD_INIT (plainmount)
|
||||
+{
|
||||
+ cmd = grub_register_extcmd ("plainmount", grub_cmd_plainmount, 0,
|
||||
+ N_("-c cipher -s key-size [-h hash] [-S sector-size]"
|
||||
+ " [-o offset] [-p password] [-u uuid] "
|
||||
+ " [[-d keyfile] [-O keyfile offset]] <SOURCE>"),
|
||||
+ N_("Open partition encrypted in plain mode."),
|
||||
+ options);
|
||||
+}
|
||||
+
|
||||
+GRUB_MOD_FINI (plainmount)
|
||||
+{
|
||||
+ grub_unregister_extcmd (cmd);
|
||||
+}
|
543
0427-disk-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
543
0427-disk-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
@ -0,0 +1,543 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Tue, 11 Feb 2025 17:59:04 -0600
|
||||
Subject: [PATCH] disk: Use safe math macros to prevent overflows
|
||||
|
||||
Replace direct arithmetic operations with macros from include/grub/safemath.h
|
||||
to prevent potential overflow issues when calculating the memory sizes.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/cryptodisk.c | 36 ++++++++++++++++++------
|
||||
grub-core/disk/diskfilter.c | 9 ++++--
|
||||
grub-core/disk/ieee1275/obdisk.c | 43 ++++++++++++++++++++++++----
|
||||
grub-core/disk/ieee1275/ofdisk.c | 60 ++++++++++++++++++++++++++++++++++------
|
||||
grub-core/disk/ldm.c | 36 ++++++++++++++++++++----
|
||||
grub-core/disk/luks2.c | 7 ++++-
|
||||
grub-core/disk/memdisk.c | 7 ++++-
|
||||
grub-core/disk/plainmount.c | 9 ++++--
|
||||
8 files changed, 172 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||||
index 9c456c2..bd5eaf0 100644
|
||||
--- a/grub-core/disk/cryptodisk.c
|
||||
+++ b/grub-core/disk/cryptodisk.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/file.h>
|
||||
#include <grub/procfs.h>
|
||||
#include <grub/partition.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/emu/hostdisk.h>
|
||||
@@ -1475,7 +1476,7 @@ static char *
|
||||
luks_script_get (grub_size_t *sz)
|
||||
{
|
||||
grub_cryptodisk_t i;
|
||||
- grub_size_t size = 0;
|
||||
+ grub_size_t size = 0, mul;
|
||||
char *ptr, *ret;
|
||||
|
||||
*sz = 0;
|
||||
@@ -1484,10 +1485,6 @@ luks_script_get (grub_size_t *sz)
|
||||
if (grub_strcmp (i->modname, "luks") == 0 ||
|
||||
grub_strcmp (i->modname, "luks2") == 0)
|
||||
{
|
||||
- size += grub_strlen (i->modname);
|
||||
- size += sizeof ("_mount");
|
||||
- size += grub_strlen (i->uuid);
|
||||
- size += grub_strlen (i->cipher->cipher->name);
|
||||
/*
|
||||
* Add space in the line for (in order) spaces, cipher mode, cipher IV
|
||||
* mode, sector offset, sector size and the trailing newline. This is
|
||||
@@ -1495,14 +1492,35 @@ luks_script_get (grub_size_t *sz)
|
||||
* in an earlier version of this code that are unaccounted for. It is
|
||||
* left in the calculations in case it is needed. At worst, its short-
|
||||
* lived wasted space.
|
||||
+ *
|
||||
+ * 60 = 5 + 5 + 8 + 20 + 6 + 1 + 15
|
||||
*/
|
||||
- size += 5 + 5 + 8 + 20 + 6 + 1 + 15;
|
||||
+ if (grub_add (size, grub_strlen (i->modname), &size) ||
|
||||
+ grub_add (size, sizeof ("_mount") + 60, &size) ||
|
||||
+ grub_add (size, grub_strlen (i->uuid), &size) ||
|
||||
+ grub_add (size, grub_strlen (i->cipher->cipher->name), &size) ||
|
||||
+ grub_mul (i->keysize, 2, &mul) ||
|
||||
+ grub_add (size, mul, &size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
||||
+ return 0;
|
||||
+ }
|
||||
if (i->essiv_hash)
|
||||
- size += grub_strlen (i->essiv_hash->name);
|
||||
- size += i->keysize * 2;
|
||||
+ {
|
||||
+ if (grub_add (size, grub_strlen (i->essiv_hash->name), &size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ if (grub_add (size, 1, &size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- ret = grub_malloc (size + 1);
|
||||
+ ret = grub_malloc (size);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
|
||||
index 7cdffe3..4c0b568 100644
|
||||
--- a/grub-core/disk/diskfilter.c
|
||||
+++ b/grub-core/disk/diskfilter.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <grub/misc.h>
|
||||
#include <grub/diskfilter.h>
|
||||
#include <grub/partition.h>
|
||||
+#include <grub/safemath.h>
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/util/misc.h>
|
||||
@@ -1016,7 +1017,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
{
|
||||
struct grub_diskfilter_vg *array;
|
||||
int i;
|
||||
- grub_size_t j;
|
||||
+ grub_size_t j, sz;
|
||||
grub_uint64_t totsize;
|
||||
struct grub_diskfilter_pv *pv;
|
||||
grub_err_t err;
|
||||
@@ -1110,7 +1111,11 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
}
|
||||
array->lvs->vg = array;
|
||||
|
||||
- array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen);
|
||||
+ if (grub_mul (uuidlen, 2, &sz) ||
|
||||
+ grub_add (sz, sizeof ("mduuid/"), &sz))
|
||||
+ goto fail;
|
||||
+
|
||||
+ array->lvs->idname = grub_malloc (sz);
|
||||
if (!array->lvs->idname)
|
||||
goto fail;
|
||||
|
||||
diff --git a/grub-core/disk/ieee1275/obdisk.c b/grub-core/disk/ieee1275/obdisk.c
|
||||
index ec413c3..8e4bbf1 100644
|
||||
--- a/grub-core/disk/ieee1275/obdisk.c
|
||||
+++ b/grub-core/disk/ieee1275/obdisk.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/mm.h>
|
||||
#include <grub/scsicmd.h>
|
||||
#include <grub/time.h>
|
||||
+#include <grub/safemath.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/ieee1275/obdisk.h>
|
||||
|
||||
@@ -128,9 +129,17 @@ count_commas (const char *src)
|
||||
static char *
|
||||
decode_grub_devname (const char *name)
|
||||
{
|
||||
- char *devpath = grub_malloc (grub_strlen (name) + 1);
|
||||
+ char *devpath;
|
||||
char *p, c;
|
||||
+ grub_size_t sz;
|
||||
|
||||
+ if (grub_add (grub_strlen (name), 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device name"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ devpath = grub_malloc (sz);
|
||||
if (devpath == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -156,12 +165,20 @@ static char *
|
||||
encode_grub_devname (const char *path)
|
||||
{
|
||||
char *encoding, *optr;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (path == NULL)
|
||||
return NULL;
|
||||
|
||||
- encoding = grub_malloc (sizeof (IEEE1275_DEV) + count_commas (path) +
|
||||
- grub_strlen (path) + 1);
|
||||
+ if (grub_add (sizeof (IEEE1275_DEV) + 1, count_commas (path), &sz) ||
|
||||
+ grub_add (sz, grub_strlen (path), &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining encoding size"));
|
||||
+ grub_print_error ();
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ encoding = grub_malloc (sz);
|
||||
|
||||
if (encoding == NULL)
|
||||
{
|
||||
@@ -396,6 +413,14 @@ canonicalise_disk (const char *devname)
|
||||
|
||||
real_unit_str_len = grub_strlen (op->name) + sizeof (IEEE1275_DISK_ALIAS)
|
||||
+ grub_strlen (real_unit_address);
|
||||
+ if (grub_add (grub_strlen (op->name), sizeof (IEEE1275_DISK_ALIAS), &real_unit_str_len) ||
|
||||
+ grub_add (real_unit_str_len, grub_strlen (real_unit_address), &real_unit_str_len))
|
||||
+ {
|
||||
+ grub_free (parent);
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of canonical name"));
|
||||
+ grub_print_error ();
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
real_canon = grub_malloc (real_unit_str_len);
|
||||
|
||||
@@ -413,6 +438,7 @@ canonicalise_disk (const char *devname)
|
||||
static struct disk_dev *
|
||||
add_canon_disk (const char *cname)
|
||||
{
|
||||
+ grub_size_t sz;
|
||||
struct disk_dev *dev;
|
||||
|
||||
dev = grub_zalloc (sizeof (struct disk_dev));
|
||||
@@ -428,13 +454,18 @@ add_canon_disk (const char *cname)
|
||||
* arguments and allows a client program to open
|
||||
* the entire (raw) disk. Any disk label is ignored.
|
||||
*/
|
||||
- dev->raw_name = grub_malloc (grub_strlen (cname) + sizeof (":nolabel"));
|
||||
+ if (grub_add (grub_strlen (cname), sizeof (":nolabel"), &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while appending :nolabel to end of canonical name");
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
+ dev->raw_name = grub_malloc (sz);
|
||||
|
||||
if (dev->raw_name == NULL)
|
||||
goto failed;
|
||||
|
||||
- grub_snprintf (dev->raw_name, grub_strlen (cname) + sizeof (":nolabel"),
|
||||
- "%s:nolabel", cname);
|
||||
+ grub_snprintf (dev->raw_name, sz, "%s:nolabel", cname);
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
|
||||
index 5534684..2099963 100644
|
||||
--- a/grub-core/disk/ieee1275/ofdisk.c
|
||||
+++ b/grub-core/disk/ieee1275/ofdisk.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <grub/ieee1275/ofdisk.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/time.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
static char *last_devpath;
|
||||
static grub_ieee1275_ihandle_t last_ihandle;
|
||||
@@ -80,6 +81,7 @@ ofdisk_hash_add_real (char *devpath)
|
||||
struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
|
||||
const char *iptr;
|
||||
char *optr;
|
||||
+ grub_size_t sz;
|
||||
|
||||
p = grub_zalloc (sizeof (*p));
|
||||
if (!p)
|
||||
@@ -87,8 +89,14 @@ ofdisk_hash_add_real (char *devpath)
|
||||
|
||||
p->devpath = devpath;
|
||||
|
||||
- p->grub_devpath = grub_malloc (sizeof ("ieee1275/")
|
||||
- + 2 * grub_strlen (p->devpath));
|
||||
+ if (grub_mul (grub_strlen (p->devpath), 2, &sz) ||
|
||||
+ grub_add (sz, sizeof ("ieee1275/"), &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ p->grub_devpath = grub_malloc (sz);
|
||||
|
||||
if (!p->grub_devpath)
|
||||
{
|
||||
@@ -98,7 +106,13 @@ ofdisk_hash_add_real (char *devpath)
|
||||
|
||||
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
|
||||
{
|
||||
- p->open_path = grub_malloc (grub_strlen (p->devpath) + 3);
|
||||
+ if (grub_add (grub_strlen (p->devpath), 3, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of an open path"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ p->open_path = grub_malloc (sz);
|
||||
if (!p->open_path)
|
||||
{
|
||||
grub_free (p->grub_devpath);
|
||||
@@ -224,7 +238,7 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||
args;
|
||||
char *buf, *bufptr;
|
||||
unsigned i;
|
||||
-
|
||||
+ grub_size_t sz;
|
||||
|
||||
RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle)
|
||||
if (! ihandle)
|
||||
@@ -245,7 +259,14 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||
return;
|
||||
}
|
||||
|
||||
- buf = grub_malloc (grub_strlen (alias->path) + 32);
|
||||
+ if (grub_add (grub_strlen (alias->path), 32, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for vscsi");
|
||||
+ grub_ieee1275_close (ihandle);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ buf = grub_malloc (sz);
|
||||
if (!buf)
|
||||
return;
|
||||
bufptr = grub_stpcpy (buf, alias->path);
|
||||
@@ -289,9 +310,15 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||
grub_uint64_t *table;
|
||||
grub_uint16_t table_size;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
+ grub_size_t sz;
|
||||
|
||||
- buf = grub_malloc (grub_strlen (alias->path) +
|
||||
- sizeof ("/disk@7766554433221100"));
|
||||
+ if (grub_add (grub_strlen (alias->path), sizeof ("/disk@7766554433221100"), &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for sas_ioa");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ buf = grub_malloc (sz);
|
||||
if (!buf)
|
||||
return;
|
||||
bufptr = grub_stpcpy (buf, alias->path);
|
||||
@@ -431,9 +458,17 @@ grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
|
||||
static char *
|
||||
compute_dev_path (const char *name)
|
||||
{
|
||||
- char *devpath = grub_malloc (grub_strlen (name) + 3);
|
||||
+ char *devpath;
|
||||
char *p, c;
|
||||
+ grub_size_t sz;
|
||||
|
||||
+ if (grub_add (grub_strlen (name), 3, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ devpath = grub_malloc (sz);
|
||||
if (!devpath)
|
||||
return NULL;
|
||||
|
||||
@@ -660,6 +695,7 @@ insert_bootpath (void)
|
||||
char *bootpath;
|
||||
grub_ssize_t bootpath_size;
|
||||
char *type;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
|
||||
&bootpath_size)
|
||||
@@ -670,7 +706,13 @@ insert_bootpath (void)
|
||||
return;
|
||||
}
|
||||
|
||||
- bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
|
||||
+ if (grub_add (bootpath_size, 64, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining bootpath size"));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bootpath = (char *) grub_malloc (sz);
|
||||
if (! bootpath)
|
||||
{
|
||||
grub_print_error ();
|
||||
diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
|
||||
index 4577a51..1726607 100644
|
||||
--- a/grub-core/disk/ldm.c
|
||||
+++ b/grub-core/disk/ldm.c
|
||||
@@ -220,6 +220,7 @@ make_vg (grub_disk_t disk,
|
||||
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||
/ sizeof (struct grub_ldm_vblk)];
|
||||
unsigned i;
|
||||
+ grub_size_t sz;
|
||||
err = grub_disk_read (disk, cursec, 0,
|
||||
sizeof(vblk), &vblk);
|
||||
if (err)
|
||||
@@ -251,7 +252,13 @@ make_vg (grub_disk_t disk,
|
||||
grub_free (pv);
|
||||
goto fail2;
|
||||
}
|
||||
- pv->internal_id = grub_malloc (ptr[0] + 2);
|
||||
+ if (grub_add (ptr[0], 2, &sz))
|
||||
+ {
|
||||
+ grub_free (pv);
|
||||
+ goto fail2;
|
||||
+ }
|
||||
+
|
||||
+ pv->internal_id = grub_malloc (sz);
|
||||
if (!pv->internal_id)
|
||||
{
|
||||
grub_free (pv);
|
||||
@@ -276,7 +283,15 @@ make_vg (grub_disk_t disk,
|
||||
goto fail2;
|
||||
}
|
||||
pv->id.uuidlen = *ptr;
|
||||
- pv->id.uuid = grub_malloc (pv->id.uuidlen + 1);
|
||||
+
|
||||
+ if (grub_add (pv->id.uuidlen, 1, &sz))
|
||||
+ {
|
||||
+ grub_free (pv->internal_id);
|
||||
+ grub_free (pv);
|
||||
+ goto fail2;
|
||||
+ }
|
||||
+
|
||||
+ pv->id.uuid = grub_malloc (sz);
|
||||
grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
|
||||
pv->id.uuid[pv->id.uuidlen] = 0;
|
||||
|
||||
@@ -343,7 +358,13 @@ make_vg (grub_disk_t disk,
|
||||
grub_free (lv);
|
||||
goto fail2;
|
||||
}
|
||||
- lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
||||
+ if (grub_add (ptr[0], 2, &sz))
|
||||
+ {
|
||||
+ grub_free (lv->segments);
|
||||
+ grub_free (lv);
|
||||
+ goto fail2;
|
||||
+ }
|
||||
+ lv->internal_id = grub_malloc (sz);
|
||||
if (!lv->internal_id)
|
||||
{
|
||||
grub_free (lv);
|
||||
@@ -455,6 +476,7 @@ make_vg (grub_disk_t disk,
|
||||
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||
/ sizeof (struct grub_ldm_vblk)];
|
||||
unsigned i;
|
||||
+ grub_size_t sz;
|
||||
err = grub_disk_read (disk, cursec, 0,
|
||||
sizeof(vblk), &vblk);
|
||||
if (err)
|
||||
@@ -489,7 +511,12 @@ make_vg (grub_disk_t disk,
|
||||
{
|
||||
goto fail2;
|
||||
}
|
||||
- comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
||||
+ if (grub_add (ptr[0], 2, &sz))
|
||||
+ {
|
||||
+ grub_free (comp);
|
||||
+ goto fail2;
|
||||
+ }
|
||||
+ comp->internal_id = grub_malloc (sz);
|
||||
if (!comp->internal_id)
|
||||
{
|
||||
grub_free (comp);
|
||||
@@ -639,7 +666,6 @@ make_vg (grub_disk_t disk,
|
||||
if (lv->segments->node_alloc == lv->segments->node_count)
|
||||
{
|
||||
void *t;
|
||||
- grub_size_t sz;
|
||||
|
||||
if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) ||
|
||||
grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz))
|
||||
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
|
||||
index ac3ab09..50f0e69 100644
|
||||
--- a/grub-core/disk/luks2.c
|
||||
+++ b/grub-core/disk/luks2.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
#include <base64.h>
|
||||
#include <json.h>
|
||||
@@ -549,6 +550,7 @@ luks2_recover_key (grub_disk_t source,
|
||||
gcry_err_code_t gcry_ret;
|
||||
grub_json_t *json = NULL, keyslots;
|
||||
grub_err_t ret;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (cargs->key_data == NULL || cargs->key_len == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
|
||||
@@ -557,7 +559,10 @@ luks2_recover_key (grub_disk_t source,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- json_header = grub_zalloc (grub_be_to_cpu64 (header.hdr_size) - sizeof (header));
|
||||
+ if (grub_sub (grub_be_to_cpu64 (header.hdr_size), sizeof (header), &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while calculating json header size");
|
||||
+
|
||||
+ json_header = grub_zalloc (sz);
|
||||
if (!json_header)
|
||||
return GRUB_ERR_OUT_OF_MEMORY;
|
||||
|
||||
diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c
|
||||
index 613779c..36de3bf 100644
|
||||
--- a/grub-core/disk/memdisk.c
|
||||
+++ b/grub-core/disk/memdisk.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/types.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -96,7 +97,11 @@ GRUB_MOD_INIT(memdisk)
|
||||
|
||||
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
|
||||
|
||||
- memdisk_size = header->size - sizeof (struct grub_module_header);
|
||||
+ if (grub_sub (header->size, sizeof (struct grub_module_header), &memdisk_size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while obtaining memdisk size");
|
||||
+ return;
|
||||
+ }
|
||||
memdisk_addr = grub_malloc (memdisk_size);
|
||||
|
||||
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
|
||||
diff --git a/grub-core/disk/plainmount.c b/grub-core/disk/plainmount.c
|
||||
index 47e6480..21ec407 100644
|
||||
--- a/grub-core/disk/plainmount.c
|
||||
+++ b/grub-core/disk/plainmount.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -126,7 +127,7 @@ plainmount_configure_password (grub_cryptodisk_t dev, const char *hash,
|
||||
grub_uint8_t *derived_hash, *dh;
|
||||
char *p;
|
||||
unsigned int round, i, len, size;
|
||||
- grub_size_t alloc_size;
|
||||
+ grub_size_t alloc_size, sz;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
/* Support none (plain) hash */
|
||||
@@ -145,7 +146,11 @@ plainmount_configure_password (grub_cryptodisk_t dev, const char *hash,
|
||||
* Allocate buffer for the password and for an added prefix character
|
||||
* for each hash round ('alloc_size' may not be a multiple of 'len').
|
||||
*/
|
||||
- p = grub_zalloc (alloc_size + (alloc_size / len) + 1);
|
||||
+ if (grub_add (alloc_size, (alloc_size / len), &sz) ||
|
||||
+ grub_add (sz, 1, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while allocating size of password buffer"));
|
||||
+
|
||||
+ p = grub_zalloc (sz);
|
||||
derived_hash = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN * 2);
|
||||
if (p == NULL || derived_hash == NULL)
|
||||
{
|
@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Wed, 12 Feb 2025 10:26:44 -0600
|
||||
Subject: [PATCH] disk: Prevent overflows when allocating memory for arrays
|
||||
|
||||
Use grub_calloc() when allocating memory for arrays to ensure proper
|
||||
overflow checks are in place.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/lvm.c | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
|
||||
index 8257159b3..99f5e7cc6 100644
|
||||
--- a/grub-core/disk/lvm.c
|
||||
+++ b/grub-core/disk/lvm.c
|
||||
@@ -671,8 +671,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
|
||||
- seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
|
||||
- * seg->node_count);
|
||||
+ seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0]));
|
||||
|
||||
p = grub_strstr (p, "mirrors = [");
|
||||
if (p == NULL)
|
||||
@@ -760,8 +759,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
}
|
||||
}
|
||||
|
||||
- seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
|
||||
- * seg->node_count);
|
||||
+ seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0]));
|
||||
|
||||
p = grub_strstr (p, "raids = [");
|
||||
if (p == NULL)
|
152
0429-disk-Check-if-returned-pointer-for-allocated-memory-.patch
Normal file
152
0429-disk-Check-if-returned-pointer-for-allocated-memory-.patch
Normal file
@ -0,0 +1,152 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 02:55:11 +0000
|
||||
Subject: [PATCH] disk: Check if returned pointer for allocated memory is NULL
|
||||
|
||||
When using grub_malloc(), grub_zalloc() or grub_calloc(), these functions can
|
||||
fail if we are out of memory. After allocating memory we should check if these
|
||||
functions returned NULL and handle this error if they did.
|
||||
|
||||
On the occasion make a NULL check in ATA code more obvious.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/ata.c | 4 ++--
|
||||
grub-core/disk/ieee1275/obdisk.c | 6 ++++++
|
||||
grub-core/disk/ldm.c | 6 ++++++
|
||||
grub-core/disk/lvm.c | 14 ++++++++++++++
|
||||
grub-core/disk/memdisk.c | 2 ++
|
||||
5 files changed, 30 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c
|
||||
index 3620a282e..8bc3ab7f3 100644
|
||||
--- a/grub-core/disk/ata.c
|
||||
+++ b/grub-core/disk/ata.c
|
||||
@@ -112,10 +112,10 @@ grub_ata_identify (struct grub_ata *dev)
|
||||
return grub_atapi_identify (dev);
|
||||
|
||||
info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
||||
+ if (info64 == NULL)
|
||||
+ return grub_errno;
|
||||
info32 = (grub_uint32_t *) info64;
|
||||
info16 = (grub_uint16_t *) info64;
|
||||
- if (! info16)
|
||||
- return grub_errno;
|
||||
|
||||
grub_memset (&parms, 0, sizeof (parms));
|
||||
parms.buffer = info16;
|
||||
diff --git a/grub-core/disk/ieee1275/obdisk.c b/grub-core/disk/ieee1275/obdisk.c
|
||||
index 8e4bbf11c..c72086072 100644
|
||||
--- a/grub-core/disk/ieee1275/obdisk.c
|
||||
+++ b/grub-core/disk/ieee1275/obdisk.c
|
||||
@@ -423,6 +423,12 @@ canonicalise_disk (const char *devname)
|
||||
}
|
||||
|
||||
real_canon = grub_malloc (real_unit_str_len);
|
||||
+ if (real_canon == NULL)
|
||||
+ {
|
||||
+ grub_free (parent);
|
||||
+ grub_print_error ();
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
grub_snprintf (real_canon, real_unit_str_len, "%s/disk@%s",
|
||||
op->name, real_unit_address);
|
||||
diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
|
||||
index 172660710..246eee3d6 100644
|
||||
--- a/grub-core/disk/ldm.c
|
||||
+++ b/grub-core/disk/ldm.c
|
||||
@@ -292,6 +292,12 @@ make_vg (grub_disk_t disk,
|
||||
}
|
||||
|
||||
pv->id.uuid = grub_malloc (sz);
|
||||
+ if (pv->id.uuid == NULL)
|
||||
+ {
|
||||
+ grub_free (pv->internal_id);
|
||||
+ grub_free (pv);
|
||||
+ goto fail2;
|
||||
+ }
|
||||
grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
|
||||
pv->id.uuid[pv->id.uuidlen] = 0;
|
||||
|
||||
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
|
||||
index 99f5e7cc6..4ddb81526 100644
|
||||
--- a/grub-core/disk/lvm.c
|
||||
+++ b/grub-core/disk/lvm.c
|
||||
@@ -370,6 +370,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
break;
|
||||
|
||||
pv = grub_zalloc (sizeof (*pv));
|
||||
+ if (pv == NULL)
|
||||
+ goto fail4;
|
||||
q = p;
|
||||
while (*q != ' ' && q < mda_end)
|
||||
q++;
|
||||
@@ -379,6 +381,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
|
||||
s = q - p;
|
||||
pv->name = grub_malloc (s + 1);
|
||||
+ if (pv->name == NULL)
|
||||
+ goto pvs_fail_noname;
|
||||
grub_memcpy (pv->name, p, s);
|
||||
pv->name[s] = '\0';
|
||||
|
||||
@@ -451,6 +455,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
break;
|
||||
|
||||
lv = grub_zalloc (sizeof (*lv));
|
||||
+ if (lv == NULL)
|
||||
+ goto fail4;
|
||||
|
||||
q = p;
|
||||
while (*q != ' ' && q < mda_end)
|
||||
@@ -545,6 +551,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
goto lvs_fail;
|
||||
}
|
||||
lv->segments = grub_calloc (lv->segment_count, sizeof (*seg));
|
||||
+ if (lv->segments == NULL)
|
||||
+ goto lvs_fail;
|
||||
seg = lv->segments;
|
||||
|
||||
for (i = 0; i < lv->segment_count; i++)
|
||||
@@ -612,6 +620,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
|
||||
seg->nodes = grub_calloc (seg->node_count,
|
||||
sizeof (*stripe));
|
||||
+ if (seg->nodes == NULL)
|
||||
+ goto lvs_segment_fail;
|
||||
stripe = seg->nodes;
|
||||
|
||||
p = grub_strstr (p, "stripes = [");
|
||||
@@ -672,6 +682,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
}
|
||||
|
||||
seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0]));
|
||||
+ if (seg->nodes == NULL)
|
||||
+ goto lvs_segment_fail;
|
||||
|
||||
p = grub_strstr (p, "mirrors = [");
|
||||
if (p == NULL)
|
||||
@@ -760,6 +772,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
}
|
||||
|
||||
seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0]));
|
||||
+ if (seg->nodes == NULL)
|
||||
+ goto lvs_segment_fail;
|
||||
|
||||
p = grub_strstr (p, "raids = [");
|
||||
if (p == NULL)
|
||||
diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c
|
||||
index 36de3bfab..2d7afaea3 100644
|
||||
--- a/grub-core/disk/memdisk.c
|
||||
+++ b/grub-core/disk/memdisk.c
|
||||
@@ -103,6 +103,8 @@ GRUB_MOD_INIT(memdisk)
|
||||
return;
|
||||
}
|
||||
memdisk_addr = grub_malloc (memdisk_size);
|
||||
+ if (memdisk_addr == NULL)
|
||||
+ return;
|
||||
|
||||
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
|
||||
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
|
@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 02:55:12 +0000
|
||||
Subject: [PATCH] disk/ieee1275/ofdisk: Call grub_ieee1275_close() when
|
||||
grub_malloc() fails
|
||||
|
||||
In the dev_iterate() function a handle is opened but isn't closed when
|
||||
grub_malloc() returns NULL. We should fix this by closing it on error.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/disk/ieee1275/ofdisk.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
|
||||
index 209996390..abb5082cd 100644
|
||||
--- a/grub-core/disk/ieee1275/ofdisk.c
|
||||
+++ b/grub-core/disk/ieee1275/ofdisk.c
|
||||
@@ -268,7 +268,10 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||
|
||||
buf = grub_malloc (sz);
|
||||
if (!buf)
|
||||
- return;
|
||||
+ {
|
||||
+ grub_ieee1275_close (ihandle);
|
||||
+ return;
|
||||
+ }
|
||||
bufptr = grub_stpcpy (buf, alias->path);
|
||||
|
||||
for (i = 0; i < args.nentries; i++)
|
353
0431-fs-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
353
0431-fs-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
@ -0,0 +1,353 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 12 Feb 2025 10:33:31 -0600
|
||||
Subject: [PATCH] fs: Use safe math macros to prevent overflows
|
||||
|
||||
Replace direct arithmetic operations with macros from include/grub/safemath.h
|
||||
to prevent potential overflow issues when calculating the memory sizes.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/archelp.c | 9 ++++++++-
|
||||
grub-core/fs/btrfs.c | 34 ++++++++++++++++++++++++++++------
|
||||
grub-core/fs/cpio_common.c | 16 ++++++++++++++--
|
||||
grub-core/fs/f2fs.c | 17 +++++++++++++++--
|
||||
grub-core/fs/ntfscomp.c | 9 ++++++++-
|
||||
grub-core/fs/squash4.c | 12 +++++++++---
|
||||
grub-core/fs/xfs.c | 17 +++++++++++++++--
|
||||
7 files changed, 97 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c
|
||||
index 0cf544f6f..6491f74f9 100644
|
||||
--- a/grub-core/fs/archelp.c
|
||||
+++ b/grub-core/fs/archelp.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <grub/fs.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dl.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -68,6 +69,7 @@ handle_symlink (struct grub_archelp_data *data,
|
||||
char *rest;
|
||||
char *linktarget;
|
||||
grub_size_t linktarget_len;
|
||||
+ grub_size_t sz;
|
||||
|
||||
*restart = 0;
|
||||
|
||||
@@ -98,7 +100,12 @@ handle_symlink (struct grub_archelp_data *data,
|
||||
if (linktarget[0] == '\0')
|
||||
return GRUB_ERR_NONE;
|
||||
linktarget_len = grub_strlen (linktarget);
|
||||
- target = grub_malloc (linktarget_len + grub_strlen (*name) + 2);
|
||||
+
|
||||
+ if (grub_add (linktarget_len, grub_strlen (*name), &sz) ||
|
||||
+ grub_add (sz, 2, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("link target length overflow"));
|
||||
+
|
||||
+ target = grub_malloc (sz);
|
||||
if (!target)
|
||||
return grub_errno;
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 3ed37a4db..0d45f09d3 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -1999,6 +1999,7 @@ find_path (struct grub_btrfs_data *data,
|
||||
char *origpath = NULL;
|
||||
unsigned symlinks_max = 32;
|
||||
const char *relpath = grub_env_get ("btrfs_relative_path");
|
||||
+ grub_size_t sz;
|
||||
|
||||
follow_default = 0;
|
||||
origpath = grub_strdup (path);
|
||||
@@ -2125,9 +2126,15 @@ find_path (struct grub_btrfs_data *data,
|
||||
struct grub_btrfs_dir_item *cdirel;
|
||||
if (elemsize > allocated)
|
||||
{
|
||||
- allocated = 2 * elemsize;
|
||||
+ if (grub_mul (2, elemsize, &allocated) ||
|
||||
+ grub_add (allocated, 1, &sz))
|
||||
+ {
|
||||
+ grub_free (path_alloc);
|
||||
+ grub_free (origpath);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory item size overflow"));
|
||||
+ }
|
||||
grub_free (direl);
|
||||
- direl = grub_malloc (allocated + 1);
|
||||
+ direl = grub_malloc (sz);
|
||||
if (!direl)
|
||||
{
|
||||
grub_free (path_alloc);
|
||||
@@ -2191,8 +2198,16 @@ find_path (struct grub_btrfs_data *data,
|
||||
grub_free (origpath);
|
||||
return err;
|
||||
}
|
||||
- tmp = grub_malloc (grub_le_to_cpu64 (inode.size)
|
||||
- + grub_strlen (path) + 1);
|
||||
+
|
||||
+ if (grub_add (grub_le_to_cpu64 (inode.size), grub_strlen (path), &sz) ||
|
||||
+ grub_add (sz, 1, &sz))
|
||||
+ {
|
||||
+ grub_free (direl);
|
||||
+ grub_free (path_alloc);
|
||||
+ grub_free (origpath);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow"));
|
||||
+ }
|
||||
+ tmp = grub_malloc (sz);
|
||||
if (!tmp)
|
||||
{
|
||||
grub_free (direl);
|
||||
@@ -2334,6 +2349,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||
grub_uint8_t type;
|
||||
char *new_path = NULL;
|
||||
grub_size_t est_size = 0;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (!data)
|
||||
return grub_errno;
|
||||
@@ -2383,9 +2399,15 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||
}
|
||||
if (elemsize > allocated)
|
||||
{
|
||||
- allocated = 2 * elemsize;
|
||||
+ if (grub_mul (2, elemsize, &allocated) ||
|
||||
+ grub_add (allocated, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory element size overflow"));
|
||||
+ r = -grub_errno;
|
||||
+ break;
|
||||
+ }
|
||||
grub_free (direl);
|
||||
- direl = grub_malloc (allocated + 1);
|
||||
+ direl = grub_malloc (sz);
|
||||
if (!direl)
|
||||
{
|
||||
r = -grub_errno;
|
||||
diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c
|
||||
index 4e885d623..ce49aa0b1 100644
|
||||
--- a/grub-core/fs/cpio_common.c
|
||||
+++ b/grub-core/fs/cpio_common.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/archelp.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -48,6 +49,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
struct head hd;
|
||||
grub_size_t namesize;
|
||||
grub_uint32_t modeval;
|
||||
+ grub_size_t sz;
|
||||
|
||||
data->hofs = data->next_hofs;
|
||||
|
||||
@@ -76,7 +78,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
|
||||
*mode = modeval;
|
||||
|
||||
- *name = grub_malloc (namesize + 1);
|
||||
+ if (grub_add (namesize, 1, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("file name size overflow"));
|
||||
+
|
||||
+ *name = grub_malloc (sz);
|
||||
if (*name == NULL)
|
||||
return grub_errno;
|
||||
|
||||
@@ -110,10 +115,17 @@ grub_cpio_get_link_target (struct grub_archelp_data *data)
|
||||
{
|
||||
char *ret;
|
||||
grub_err_t err;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (data->size == 0)
|
||||
return grub_strdup ("");
|
||||
- ret = grub_malloc (data->size + 1);
|
||||
+
|
||||
+ if (grub_add (data->size, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("target data size overflow"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ ret = grub_malloc (sz);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
|
||||
index e5dcbc470..a3182a3e5 100644
|
||||
--- a/grub-core/fs/f2fs.c
|
||||
+++ b/grub-core/fs/f2fs.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/fshelp.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -958,6 +959,7 @@ grub_f2fs_read_symlink (grub_fshelp_node_t node)
|
||||
char *symlink;
|
||||
struct grub_fshelp_node *diro = node;
|
||||
grub_uint64_t filesize;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (!diro->inode_read)
|
||||
{
|
||||
@@ -968,7 +970,12 @@ grub_f2fs_read_symlink (grub_fshelp_node_t node)
|
||||
|
||||
filesize = grub_f2fs_file_size(&diro->inode.i);
|
||||
|
||||
- symlink = grub_malloc (filesize + 1);
|
||||
+ if (grub_add (filesize, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ symlink = grub_malloc (sz);
|
||||
if (!symlink)
|
||||
return 0;
|
||||
|
||||
@@ -997,6 +1004,7 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
|
||||
enum FILE_TYPE ftype;
|
||||
int name_len;
|
||||
int ret;
|
||||
+ int sz;
|
||||
|
||||
if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0)
|
||||
{
|
||||
@@ -1010,7 +1018,12 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
|
||||
if (name_len >= F2FS_NAME_LEN)
|
||||
return 0;
|
||||
|
||||
- filename = grub_malloc (name_len + 1);
|
||||
+ if (grub_add (name_len, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory entry name length overflow"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ filename = grub_malloc (sz);
|
||||
if (!filename)
|
||||
return 0;
|
||||
|
||||
diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c
|
||||
index 3cd97d337..4bf95c85d 100644
|
||||
--- a/grub-core/fs/ntfscomp.c
|
||||
+++ b/grub-core/fs/ntfscomp.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/ntfs.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -310,6 +311,7 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||
{
|
||||
grub_err_t ret;
|
||||
grub_disk_addr_t vcn;
|
||||
+ int log_sz;
|
||||
|
||||
if (ctx->attr->sbuf)
|
||||
{
|
||||
@@ -349,7 +351,12 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||
}
|
||||
|
||||
ctx->comp.comp_head = ctx->comp.comp_tail = 0;
|
||||
- ctx->comp.cbuf = grub_malloc (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR));
|
||||
+ if (grub_add (ctx->comp.log_spc, GRUB_NTFS_BLK_SHR, &log_sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("compression buffer size overflow"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ ctx->comp.cbuf = grub_malloc (1 << log_sz);
|
||||
if (!ctx->comp.cbuf)
|
||||
return 0;
|
||||
|
||||
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
|
||||
index ccfa3eea5..0ee9bb2e8 100644
|
||||
--- a/grub-core/fs/squash4.c
|
||||
+++ b/grub-core/fs/squash4.c
|
||||
@@ -460,11 +460,11 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
char *ret;
|
||||
grub_err_t err;
|
||||
- grub_size_t sz;
|
||||
+ grub_uint32_t sz;
|
||||
|
||||
if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz))
|
||||
{
|
||||
- grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink name length overflow"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -577,6 +577,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
||||
struct grub_squash_dirent di;
|
||||
struct grub_squash_inode ino;
|
||||
grub_size_t sz;
|
||||
+ grub_uint16_t nlen;
|
||||
|
||||
err = read_chunk (dir->data, &di, sizeof (di),
|
||||
grub_le_to_cpu64 (dir->data->sb.diroffset)
|
||||
@@ -592,7 +593,12 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
- buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2);
|
||||
+ if (grub_add (grub_le_to_cpu16 (di.namelen), 2, &nlen))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ buf = grub_malloc (nlen);
|
||||
if (!buf)
|
||||
return 0;
|
||||
err = read_chunk (dir->data, buf,
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index 7b0ea577e..ff6fe3d83 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -676,6 +676,7 @@ static char *
|
||||
grub_xfs_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
grub_ssize_t size = grub_be_to_cpu64 (node->inode.size);
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
@@ -697,7 +698,12 @@ grub_xfs_read_symlink (grub_fshelp_node_t node)
|
||||
if (node->data->hascrc)
|
||||
off = 56;
|
||||
|
||||
- symlink = grub_malloc (size + 1);
|
||||
+ if (grub_add (size, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ symlink = grub_malloc (sz);
|
||||
if (!symlink)
|
||||
return 0;
|
||||
|
||||
@@ -747,8 +753,15 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
|
||||
{
|
||||
struct grub_fshelp_node *fdiro;
|
||||
grub_err_t err;
|
||||
+ grub_size_t sz;
|
||||
|
||||
- fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1);
|
||||
+ if (grub_add (grub_xfs_fshelp_size(ctx->diro->data), 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory data size overflow"));
|
||||
+ grub_print_error ();
|
||||
+ return 0;
|
||||
+ }
|
||||
+ fdiro = grub_malloc (sz);
|
||||
if (!fdiro)
|
||||
{
|
||||
grub_print_error ();
|
@ -0,0 +1,82 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Tue, 21 Jan 2025 19:02:37 +0000
|
||||
Subject: [PATCH] fs: Prevent overflows when allocating memory for arrays
|
||||
|
||||
Use grub_calloc() when allocating memory for arrays to ensure proper
|
||||
overflow checks are in place.
|
||||
|
||||
The HFS+ and squash4 security vulnerabilities were reported by
|
||||
Jonathan Bar Or <jonathanbaror@gmail.com>.
|
||||
|
||||
Fixes: CVE-2025-0678
|
||||
Fixes: CVE-2025-1125
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 4 ++--
|
||||
grub-core/fs/hfspluscomp.c | 9 +++++++--
|
||||
grub-core/fs/squash4.c | 8 ++++----
|
||||
3 files changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 0d45f09d3..4a4a8f243 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -1409,8 +1409,8 @@ grub_btrfs_mount (grub_device_t dev)
|
||||
}
|
||||
|
||||
data->n_devices_allocated = 16;
|
||||
- data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
|
||||
- * data->n_devices_allocated);
|
||||
+ data->devices_attached = grub_calloc (data->n_devices_allocated,
|
||||
+ sizeof (data->devices_attached[0]));
|
||||
if (!data->devices_attached)
|
||||
{
|
||||
grub_free (data);
|
||||
diff --git a/grub-core/fs/hfspluscomp.c b/grub-core/fs/hfspluscomp.c
|
||||
index d76f3f137..4965ef19a 100644
|
||||
--- a/grub-core/fs/hfspluscomp.c
|
||||
+++ b/grub-core/fs/hfspluscomp.c
|
||||
@@ -244,14 +244,19 @@ hfsplus_open_compressed_real (struct grub_hfsplus_file *node)
|
||||
return 0;
|
||||
}
|
||||
node->compress_index_size = grub_le_to_cpu32 (index_size);
|
||||
- node->compress_index = grub_malloc (node->compress_index_size
|
||||
- * sizeof (node->compress_index[0]));
|
||||
+ node->compress_index = grub_calloc (node->compress_index_size,
|
||||
+ sizeof (node->compress_index[0]));
|
||||
if (!node->compress_index)
|
||||
{
|
||||
node->compressed = 0;
|
||||
grub_free (attr_node);
|
||||
return grub_errno;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * The node->compress_index_size * sizeof (node->compress_index[0]) is safe here
|
||||
+ * due to relevant checks done in grub_calloc() above.
|
||||
+ */
|
||||
if (grub_hfsplus_read_file (node, 0, 0,
|
||||
0x104 + sizeof (index_size),
|
||||
node->compress_index_size
|
||||
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
|
||||
index 0ee9bb2e8..5239cdd5c 100644
|
||||
--- a/grub-core/fs/squash4.c
|
||||
+++ b/grub-core/fs/squash4.c
|
||||
@@ -810,10 +810,10 @@ direct_read (struct grub_squash_data *data,
|
||||
break;
|
||||
}
|
||||
total_blocks = ((total_size + data->blksz - 1) >> data->log2_blksz);
|
||||
- ino->block_sizes = grub_malloc (total_blocks
|
||||
- * sizeof (ino->block_sizes[0]));
|
||||
- ino->cumulated_block_sizes = grub_malloc (total_blocks
|
||||
- * sizeof (ino->cumulated_block_sizes[0]));
|
||||
+ ino->block_sizes = grub_calloc (total_blocks,
|
||||
+ sizeof (ino->block_sizes[0]));
|
||||
+ ino->cumulated_block_sizes = grub_calloc (total_blocks,
|
||||
+ sizeof (ino->cumulated_block_sizes[0]));
|
||||
if (!ino->block_sizes || !ino->cumulated_block_sizes)
|
||||
{
|
||||
grub_free (ino->block_sizes);
|
105
0433-fs-Prevent-overflows-when-assigning-returned-values-.patch
Normal file
105
0433-fs-Prevent-overflows-when-assigning-returned-values-.patch
Normal file
@ -0,0 +1,105 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Tue, 21 Jan 2025 19:02:38 +0000
|
||||
Subject: [PATCH] fs: Prevent overflows when assigning returned values from
|
||||
read_number()
|
||||
|
||||
The direct assignment of the unsigned long long value returned by
|
||||
read_number() can potentially lead to an overflow on a 32-bit systems.
|
||||
The fix replaces the direct assignments with calls to grub_cast()
|
||||
which detects the overflows and safely assigns the values if no
|
||||
overflow is detected.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/cpio_common.c | 18 ++++++++++++++----
|
||||
grub-core/fs/tar.c | 23 ++++++++++++++++-------
|
||||
2 files changed, 30 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c
|
||||
index ce49aa0b1..e6c51a6af 100644
|
||||
--- a/grub-core/fs/cpio_common.c
|
||||
+++ b/grub-core/fs/cpio_common.c
|
||||
@@ -62,11 +62,21 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
#endif
|
||||
)
|
||||
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
|
||||
- data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize));
|
||||
+
|
||||
+ if (grub_cast (read_number (hd.filesize, ARRAY_SIZE (hd.filesize)), &data->size))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("data size overflow"));
|
||||
+
|
||||
if (mtime)
|
||||
- *mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime));
|
||||
- modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
|
||||
- namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));
|
||||
+ {
|
||||
+ if (grub_cast (read_number (hd.mtime, ARRAY_SIZE (hd.mtime)), mtime))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("mtime overflow"));
|
||||
+ }
|
||||
+
|
||||
+ if (grub_cast (read_number (hd.mode, ARRAY_SIZE (hd.mode)), &modeval))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("mode overflow"));
|
||||
+
|
||||
+ if (grub_cast (read_number (hd.namesize, ARRAY_SIZE (hd.namesize)), &namesize))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("namesize overflow"));
|
||||
|
||||
/* Don't allow negative numbers. */
|
||||
if (namesize >= 0x80000000)
|
||||
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
|
||||
index fd2ec1f74..1eaa5349f 100644
|
||||
--- a/grub-core/fs/tar.c
|
||||
+++ b/grub-core/fs/tar.c
|
||||
@@ -99,9 +99,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
if (hd.typeflag == 'L')
|
||||
{
|
||||
grub_err_t err;
|
||||
- grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
|
||||
+ grub_size_t namesize;
|
||||
|
||||
- if (grub_add (namesize, 1, &sz))
|
||||
+ if (grub_cast (read_number (hd.size, sizeof (hd.size)), &namesize) ||
|
||||
+ grub_add (namesize, 1, &sz))
|
||||
return grub_error (GRUB_ERR_BAD_FS, N_("name size overflow"));
|
||||
|
||||
*name = grub_malloc (sz);
|
||||
@@ -123,9 +124,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
if (hd.typeflag == 'K')
|
||||
{
|
||||
grub_err_t err;
|
||||
- grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
|
||||
+ grub_size_t linksize;
|
||||
|
||||
- if (grub_add (linksize, 1, &sz))
|
||||
+ if (grub_cast (read_number (hd.size, sizeof (hd.size)), &linksize) ||
|
||||
+ grub_add (linksize, 1, &sz))
|
||||
return grub_error (GRUB_ERR_BAD_FS, N_("link size overflow"));
|
||||
|
||||
if (data->linkname_alloc < sz)
|
||||
@@ -174,15 +176,22 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
(*name)[extra_size + sizeof (hd.name)] = 0;
|
||||
}
|
||||
|
||||
- data->size = read_number (hd.size, sizeof (hd.size));
|
||||
+ if (grub_cast (read_number (hd.size, sizeof (hd.size)), &data->size))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("data size overflow"));
|
||||
+
|
||||
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
|
||||
data->next_hofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
|
||||
~(GRUB_DISK_SECTOR_SIZE - 1));
|
||||
if (mtime)
|
||||
- *mtime = read_number (hd.mtime, sizeof (hd.mtime));
|
||||
+ {
|
||||
+ if (grub_cast (read_number (hd.mtime, sizeof (hd.mtime)), mtime))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("mtime overflow"));
|
||||
+ }
|
||||
if (mode)
|
||||
{
|
||||
- *mode = read_number (hd.mode, sizeof (hd.mode));
|
||||
+ if (grub_cast (read_number (hd.mode, sizeof (hd.mode)), mode))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, N_("mode overflow"));
|
||||
+
|
||||
switch (hd.typeflag)
|
||||
{
|
||||
/* Hardlink. */
|
138
0434-fs-zfs-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
138
0434-fs-zfs-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 07:17:02 +0000
|
||||
Subject: [PATCH] fs/zfs: Use safe math macros to prevent overflows
|
||||
|
||||
Replace direct arithmetic operations with macros from include/grub/safemath.h
|
||||
to prevent potential overflow issues when calculating the memory sizes.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/zfs/zfs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 44 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
|
||||
index cbbd86730..b52d293f2 100644
|
||||
--- a/grub-core/fs/zfs/zfs.c
|
||||
+++ b/grub-core/fs/zfs/zfs.c
|
||||
@@ -2383,6 +2383,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||
zap_dnode->endian) << DNODE_SHIFT);
|
||||
grub_err_t err;
|
||||
grub_zfs_endian_t endian;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (zap_verify (zap, zap_dnode->endian))
|
||||
return 0;
|
||||
@@ -2444,8 +2445,14 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||
if (le->le_type != ZAP_CHUNK_ENTRY)
|
||||
continue;
|
||||
|
||||
- buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
|
||||
- * name_elem_length + 1);
|
||||
+ if (grub_mul (grub_zfs_to_cpu16 (le->le_name_length, endian), name_elem_length, &sz) ||
|
||||
+ grub_add (sz, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow"));
|
||||
+ grub_free (l);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+ buf = grub_malloc (sz);
|
||||
if (zap_leaf_array_get (l, endian, blksft,
|
||||
grub_zfs_to_cpu16 (le->le_name_chunk,
|
||||
endian),
|
||||
@@ -2866,6 +2873,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||
&& ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
|
||||
{
|
||||
char *sym_value;
|
||||
+ grub_size_t sz;
|
||||
grub_size_t sym_sz;
|
||||
int free_symval = 0;
|
||||
char *oldpath = path, *oldpathbuf = path_buf;
|
||||
@@ -2917,7 +2925,18 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||
break;
|
||||
free_symval = 1;
|
||||
}
|
||||
- path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
|
||||
+
|
||||
+ if (grub_add (sym_sz, grub_strlen (oldpath), &sz) ||
|
||||
+ grub_add (sz, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow"));
|
||||
+ grub_free (oldpathbuf);
|
||||
+ if (free_symval)
|
||||
+ grub_free (sym_value);
|
||||
+ err = grub_errno;
|
||||
+ break;
|
||||
+ }
|
||||
+ path = path_buf = grub_malloc (sz);
|
||||
if (!path_buf)
|
||||
{
|
||||
grub_free (oldpathbuf);
|
||||
@@ -2951,6 +2970,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||
{
|
||||
void *sahdrp;
|
||||
int hdrsize;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (dnode_path->dn.dn.dn_bonuslen != 0)
|
||||
{
|
||||
@@ -2984,7 +3004,15 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||
+ SA_SIZE_OFFSET),
|
||||
dnode_path->dn.endian);
|
||||
char *oldpath = path, *oldpathbuf = path_buf;
|
||||
- path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
|
||||
+ if (grub_add (sym_sz, grub_strlen (oldpath), &sz) ||
|
||||
+ grub_add (sz, 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow"));
|
||||
+ grub_free (oldpathbuf);
|
||||
+ err = grub_errno;
|
||||
+ break;
|
||||
+ }
|
||||
+ path = path_buf = grub_malloc (sz);
|
||||
if (!path_buf)
|
||||
{
|
||||
grub_free (oldpathbuf);
|
||||
@@ -3553,6 +3581,7 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name,
|
||||
unsigned i;
|
||||
grub_size_t nelm;
|
||||
int elemsize = 0;
|
||||
+ int sz;
|
||||
|
||||
found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair,
|
||||
&size, &nelm);
|
||||
@@ -3587,7 +3616,12 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- ret = grub_zalloc (elemsize + sizeof (grub_uint32_t));
|
||||
+ if (grub_add (elemsize, sizeof (grub_uint32_t), &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("elemsize overflow"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ ret = grub_zalloc (sz);
|
||||
if (!ret)
|
||||
return 0;
|
||||
grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
|
||||
@@ -4166,6 +4200,7 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
|
||||
struct grub_dirhook_info info;
|
||||
char *name2;
|
||||
int ret;
|
||||
+ grub_size_t sz;
|
||||
|
||||
dnode_end_t mdn;
|
||||
|
||||
@@ -4186,7 +4221,10 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- name2 = grub_malloc (grub_strlen (name) + 2);
|
||||
+ if (grub_add (grub_strlen (name), 2, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
|
||||
+
|
||||
+ name2 = grub_malloc (sz);
|
||||
name2[0] = '@';
|
||||
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
||||
ret = ctx->hook (name2, &info, ctx->hook_data);
|
@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 07:17:03 +0000
|
||||
Subject: [PATCH] fs/zfs: Prevent overflows when allocating memory for arrays
|
||||
|
||||
Use grub_calloc() when allocating memory for arrays to ensure proper
|
||||
overflow checks are in place.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/zfs/zfs.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
|
||||
index b52d293f2..913046ba9 100644
|
||||
--- a/grub-core/fs/zfs/zfs.c
|
||||
+++ b/grub-core/fs/zfs/zfs.c
|
||||
@@ -721,8 +721,8 @@ fill_vdev_info_real (struct grub_zfs_data *data,
|
||||
{
|
||||
fill->n_children = nelm;
|
||||
|
||||
- fill->children = grub_zalloc (fill->n_children
|
||||
- * sizeof (fill->children[0]));
|
||||
+ fill->children = grub_calloc (fill->n_children,
|
||||
+ sizeof (fill->children[0]));
|
||||
}
|
||||
|
||||
for (i = 0; i < nelm; i++)
|
||||
@@ -3697,8 +3697,8 @@ zfs_mount (grub_device_t dev)
|
||||
#endif
|
||||
|
||||
data->n_devices_allocated = 16;
|
||||
- data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
|
||||
- * data->n_devices_allocated);
|
||||
+ data->devices_attached = grub_calloc (data->n_devices_allocated,
|
||||
+ sizeof (data->devices_attached[0]));
|
||||
data->n_devices_attached = 0;
|
||||
err = scan_disk (dev, data, 1, &inserted);
|
||||
if (err)
|
@ -0,0 +1,88 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 07:17:01 +0000
|
||||
Subject: [PATCH] fs/zfs: Check if returned pointer for allocated memory is
|
||||
NULL
|
||||
|
||||
When using grub_malloc() or grub_zalloc(), these functions can fail if
|
||||
we are out of memory. After allocating memory we should check if these
|
||||
functions returned NULL and handle this error if they did.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/zfs/zfs.c | 26 ++++++++++++++++++++++++++
|
||||
1 file changed, 26 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
|
||||
index 913046ba9..9123b5682 100644
|
||||
--- a/grub-core/fs/zfs/zfs.c
|
||||
+++ b/grub-core/fs/zfs/zfs.c
|
||||
@@ -612,6 +612,8 @@ zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist)
|
||||
return grub_error (GRUB_ERR_BUG, "member drive unknown");
|
||||
|
||||
*nvlist = grub_malloc (VDEV_PHYS_SIZE);
|
||||
+ if (!*nvlist)
|
||||
+ return grub_errno;
|
||||
|
||||
/* Read in the vdev name-value pair list (112K). */
|
||||
err = grub_disk_read (diskdesc->dev->disk, diskdesc->vdev_phys_sector, 0,
|
||||
@@ -723,6 +725,11 @@ fill_vdev_info_real (struct grub_zfs_data *data,
|
||||
|
||||
fill->children = grub_calloc (fill->n_children,
|
||||
sizeof (fill->children[0]));
|
||||
+ if (!fill->children)
|
||||
+ {
|
||||
+ grub_free (type);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
}
|
||||
|
||||
for (i = 0; i < nelm; i++)
|
||||
@@ -2453,6 +2460,11 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||
return grub_errno;
|
||||
}
|
||||
buf = grub_malloc (sz);
|
||||
+ if (!buf)
|
||||
+ {
|
||||
+ grub_free (l);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
if (zap_leaf_array_get (l, endian, blksft,
|
||||
grub_zfs_to_cpu16 (le->le_name_chunk,
|
||||
endian),
|
||||
@@ -2468,6 +2480,12 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||
val_length = ((int) le->le_value_length
|
||||
* (int) le->le_int_size);
|
||||
val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
|
||||
+ if (!val)
|
||||
+ {
|
||||
+ grub_free (l);
|
||||
+ grub_free (buf);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
if (zap_leaf_array_get (l, endian, blksft,
|
||||
grub_zfs_to_cpu16 (le->le_value_chunk,
|
||||
endian),
|
||||
@@ -3699,6 +3717,11 @@ zfs_mount (grub_device_t dev)
|
||||
data->n_devices_allocated = 16;
|
||||
data->devices_attached = grub_calloc (data->n_devices_allocated,
|
||||
sizeof (data->devices_attached[0]));
|
||||
+ if (!data->devices_attached)
|
||||
+ {
|
||||
+ grub_free (data);
|
||||
+ return NULL;
|
||||
+ }
|
||||
data->n_devices_attached = 0;
|
||||
err = scan_disk (dev, data, 1, &inserted);
|
||||
if (err)
|
||||
@@ -4225,6 +4248,9 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
|
||||
|
||||
name2 = grub_malloc (sz);
|
||||
+ if (!name2)
|
||||
+ return grub_errno;
|
||||
+
|
||||
name2[0] = '@';
|
||||
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
||||
ret = ctx->hook (name2, &info, ctx->hook_data);
|
@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 07:17:04 +0000
|
||||
Subject: [PATCH] fs/zfs: Add missing NULL check after grub_strdup() call
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/zfs/zfs.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
|
||||
index 9123b5682..da014b123 100644
|
||||
--- a/grub-core/fs/zfs/zfs.c
|
||||
+++ b/grub-core/fs/zfs/zfs.c
|
||||
@@ -3297,6 +3297,8 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
||||
filename = 0;
|
||||
snapname = 0;
|
||||
fsname = grub_strdup (fullpath);
|
||||
+ if (!fsname)
|
||||
+ return grub_errno;
|
||||
}
|
||||
else
|
||||
{
|
240
0438-net-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
240
0438-net-Use-safe-math-macros-to-prevent-overflows.patch
Normal file
@ -0,0 +1,240 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 12 Feb 2025 10:38:17 -0600
|
||||
Subject: [PATCH] net: Use safe math macros to prevent overflows
|
||||
|
||||
Replace direct arithmetic operations with macros from include/grub/safemath.h
|
||||
to prevent potential overflow issues when calculating the memory sizes.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/bootp.c | 16 +++++++++++--
|
||||
grub-core/net/dns.c | 9 ++++++-
|
||||
grub-core/net/drivers/ieee1275/ofnet.c | 20 ++++++++++++++--
|
||||
grub-core/net/net.c | 44 +++++++++++++++++++++++++++-------
|
||||
4 files changed, 76 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
|
||||
index 7baf3540c..f00d4a9ad 100644
|
||||
--- a/grub-core/net/bootp.c
|
||||
+++ b/grub-core/net/bootp.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/list.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
static int
|
||||
dissect_url (const char *url, char **proto, char **host, char **path)
|
||||
@@ -1476,6 +1477,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
|
||||
unsigned num;
|
||||
const grub_uint8_t *ptr;
|
||||
grub_uint8_t taglength;
|
||||
+ grub_uint8_t len;
|
||||
|
||||
if (argc < 4)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
@@ -1517,7 +1519,12 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
|
||||
if (grub_strcmp (args[3], "string") == 0)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
- char *val = grub_malloc (taglength + 1);
|
||||
+ char *val;
|
||||
+
|
||||
+ if (grub_add (taglength, 1, &len))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("tag length overflow"));
|
||||
+
|
||||
+ val = grub_malloc (len);
|
||||
if (!val)
|
||||
return grub_errno;
|
||||
grub_memcpy (val, ptr, taglength);
|
||||
@@ -1550,7 +1557,12 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
|
||||
if (grub_strcmp (args[3], "hex") == 0)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
- char *val = grub_malloc (2 * taglength + 1);
|
||||
+ char *val;
|
||||
+
|
||||
+ if (grub_mul (taglength, 2, &len) || grub_add (len, 1, &len))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("tag length overflow"));
|
||||
+
|
||||
+ val = grub_malloc (len);
|
||||
int i;
|
||||
if (!val)
|
||||
return grub_errno;
|
||||
diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
|
||||
index 17961a9f1..64b48a31c 100644
|
||||
--- a/grub-core/net/dns.c
|
||||
+++ b/grub-core/net/dns.c
|
||||
@@ -224,10 +224,17 @@ get_name (const grub_uint8_t *name_at, const grub_uint8_t *head,
|
||||
{
|
||||
int length;
|
||||
char *ret;
|
||||
+ int len;
|
||||
|
||||
if (!check_name_real (name_at, head, tail, NULL, &length, NULL))
|
||||
return NULL;
|
||||
- ret = grub_malloc (length + 1);
|
||||
+
|
||||
+ if (grub_add (length, 1, &len))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ ret = grub_malloc (len);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!check_name_real (name_at, head, tail, NULL, NULL, ret))
|
||||
diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
|
||||
index bcb3f9ea0..650114806 100644
|
||||
--- a/grub-core/net/drivers/ieee1275/ofnet.c
|
||||
+++ b/grub-core/net/drivers/ieee1275/ofnet.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -404,6 +405,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
|
||||
grub_uint8_t *pprop;
|
||||
char *shortname;
|
||||
char need_suffix = 1;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (grub_strcmp (alias->type, "network") != 0)
|
||||
return 0;
|
||||
@@ -461,9 +463,23 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
|
||||
}
|
||||
|
||||
if (need_suffix)
|
||||
- ofdata->path = grub_malloc (grub_strlen (alias->path) + sizeof (SUFFIX));
|
||||
+ {
|
||||
+ if (grub_add (grub_strlen (alias->path), sizeof (SUFFIX), &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obatining size of ofdata path"));
|
||||
+ grub_print_error ();
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
- ofdata->path = grub_malloc (grub_strlen (alias->path) + 1);
|
||||
+ {
|
||||
+ if (grub_add (grub_strlen (alias->path), 1, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obatining size of ofdata path"));
|
||||
+ grub_print_error ();
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
if (!ofdata->path)
|
||||
{
|
||||
grub_print_error ();
|
||||
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
||||
index 6c0bd00b4..9826328ca 100644
|
||||
--- a/grub-core/net/net.c
|
||||
+++ b/grub-core/net/net.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <grub/loader.h>
|
||||
#include <grub/bufio.h>
|
||||
#include <grub/kernel.h>
|
||||
+#include <grub/safemath.h>
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
#include <grub/net/efi.h>
|
||||
#endif
|
||||
@@ -211,6 +212,7 @@ grub_net_ipv6_get_slaac (struct grub_net_card *card,
|
||||
{
|
||||
struct grub_net_slaac_mac_list *slaac;
|
||||
char *ptr;
|
||||
+ grub_size_t sz;
|
||||
|
||||
for (slaac = card->slaac_list; slaac; slaac = slaac->next)
|
||||
if (grub_net_hwaddr_cmp (&slaac->address, hwaddr) == 0)
|
||||
@@ -220,9 +222,16 @@ grub_net_ipv6_get_slaac (struct grub_net_card *card,
|
||||
if (!slaac)
|
||||
return NULL;
|
||||
|
||||
- slaac->name = grub_malloc (grub_strlen (card->name)
|
||||
- + GRUB_NET_MAX_STR_HWADDR_LEN
|
||||
- + sizeof (":slaac"));
|
||||
+ if (grub_add (grub_strlen (card->name),
|
||||
+ (GRUB_NET_MAX_STR_HWADDR_LEN + sizeof (":slaac")), &sz))
|
||||
+ {
|
||||
+ grub_free (slaac);
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "overflow detected while obtaining size of slaac name");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ slaac->name = grub_malloc (sz);
|
||||
ptr = grub_stpcpy (slaac->name, card->name);
|
||||
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
|
||||
{
|
||||
@@ -293,6 +302,7 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
||||
char *name;
|
||||
char *ptr;
|
||||
grub_net_network_level_address_t addr;
|
||||
+ grub_size_t sz;
|
||||
|
||||
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
||||
addr.ipv6[0] = grub_cpu_to_be64_compile_time (0xfe80ULL << 48);
|
||||
@@ -306,9 +316,14 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
||||
return inf;
|
||||
}
|
||||
|
||||
- name = grub_malloc (grub_strlen (card->name)
|
||||
- + GRUB_NET_MAX_STR_HWADDR_LEN
|
||||
- + sizeof (":link"));
|
||||
+ if (grub_add (grub_strlen (card->name),
|
||||
+ (GRUB_NET_MAX_STR_HWADDR_LEN + sizeof (":link")), &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "overflow detected while obtaining size of link name");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ name = grub_malloc (sz);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
@@ -1461,8 +1476,15 @@ grub_net_open_real (const char *name)
|
||||
if (grub_strchr (port_start + 1, ':'))
|
||||
{
|
||||
int iplen = grub_strlen (server);
|
||||
+ grub_size_t sz;
|
||||
+
|
||||
/* bracket bare ipv6 addrs */
|
||||
- host = grub_malloc (iplen + 3);
|
||||
+ if (grub_add (iplen, 3, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining length of host"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ host = grub_malloc (sz);
|
||||
if(!host)
|
||||
{
|
||||
return NULL;
|
||||
@@ -1722,6 +1744,7 @@ grub_env_set_net_property (const char *intername, const char *suffix,
|
||||
{
|
||||
char *varname, *varvalue;
|
||||
char *ptr;
|
||||
+ grub_size_t sz;
|
||||
|
||||
varname = grub_xasprintf ("net_%s_%s", intername, suffix);
|
||||
if (!varname)
|
||||
@@ -1729,7 +1752,12 @@ grub_env_set_net_property (const char *intername, const char *suffix,
|
||||
for (ptr = varname; *ptr; ptr++)
|
||||
if (*ptr == ':')
|
||||
*ptr = '_';
|
||||
- varvalue = grub_malloc (len + 1);
|
||||
+ if (grub_add (len, 1, &sz))
|
||||
+ {
|
||||
+ grub_free (varname);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining the size of an env variable");
|
||||
+ }
|
||||
+ varvalue = grub_malloc (sz);
|
||||
if (!varvalue)
|
||||
{
|
||||
grub_free (varname);
|
@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 18:04:43 +0000
|
||||
Subject: [PATCH] net: Prevent overflows when allocating memory for arrays
|
||||
|
||||
Use grub_calloc() when allocating memory for arrays to ensure proper
|
||||
overflow checks are in place.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/dns.c | 4 ++--
|
||||
grub-core/net/net.c | 4 ++--
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
|
||||
index 64b48a31c..aafd92902 100644
|
||||
--- a/grub-core/net/dns.c
|
||||
+++ b/grub-core/net/dns.c
|
||||
@@ -494,8 +494,8 @@ grub_net_dns_lookup (const char *name,
|
||||
&& grub_get_time_ms () < dns_cache[h].limit_time)
|
||||
{
|
||||
grub_dprintf ("dns", "retrieved from cache\n");
|
||||
- *addresses = grub_malloc (dns_cache[h].naddresses
|
||||
- * sizeof ((*addresses)[0]));
|
||||
+ *addresses = grub_calloc (dns_cache[h].naddresses,
|
||||
+ sizeof ((*addresses)[0]));
|
||||
if (!*addresses)
|
||||
return grub_errno;
|
||||
*naddresses = dns_cache[h].naddresses;
|
||||
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
||||
index 9826328ca..a17392abb 100644
|
||||
--- a/grub-core/net/net.c
|
||||
+++ b/grub-core/net/net.c
|
||||
@@ -91,8 +91,8 @@ grub_net_link_layer_add_address (struct grub_net_card *card,
|
||||
/* Add sender to cache table. */
|
||||
if (card->link_layer_table == NULL)
|
||||
{
|
||||
- card->link_layer_table = grub_zalloc (LINK_LAYER_CACHE_SIZE
|
||||
- * sizeof (card->link_layer_table[0]));
|
||||
+ card->link_layer_table = grub_calloc (LINK_LAYER_CACHE_SIZE,
|
||||
+ sizeof (card->link_layer_table[0]));
|
||||
if (card->link_layer_table == NULL)
|
||||
return;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Wed, 22 Jan 2025 18:04:44 +0000
|
||||
Subject: [PATCH] net: Check if returned pointer for allocated memory is NULL
|
||||
|
||||
When using grub_malloc(), the function can fail if we are out of memory.
|
||||
After allocating memory we should check if this function returned NULL
|
||||
and handle this error if it did.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/net.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
||||
index a17392abb..4bfe03d53 100644
|
||||
--- a/grub-core/net/net.c
|
||||
+++ b/grub-core/net/net.c
|
||||
@@ -232,6 +232,11 @@ grub_net_ipv6_get_slaac (struct grub_net_card *card,
|
||||
}
|
||||
|
||||
slaac->name = grub_malloc (sz);
|
||||
+ if (slaac->name == NULL)
|
||||
+ {
|
||||
+ grub_free (slaac);
|
||||
+ return NULL;
|
||||
+ }
|
||||
ptr = grub_stpcpy (slaac->name, card->name);
|
||||
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
|
||||
{
|
32
0441-fs-sfs-Check-if-allocated-memory-is-NULL.patch
Normal file
32
0441-fs-sfs-Check-if-allocated-memory-is-NULL.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Tue, 28 Jan 2025 05:15:50 +0000
|
||||
Subject: [PATCH] fs/sfs: Check if allocated memory is NULL
|
||||
|
||||
When using grub_zalloc(), if we are out of memory, this function can fail.
|
||||
After allocating memory, we should check if grub_zalloc() returns NULL.
|
||||
If so, we should handle this error.
|
||||
|
||||
Fixes: CID 473856
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/sfs.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
|
||||
index 88705b3a2..bad4ae8d1 100644
|
||||
--- a/grub-core/fs/sfs.c
|
||||
+++ b/grub-core/fs/sfs.c
|
||||
@@ -429,6 +429,9 @@ grub_sfs_mount (grub_disk_t disk)
|
||||
- 24 /* offsetof (struct grub_sfs_objc, objects) */
|
||||
- 25); /* offsetof (struct grub_sfs_obj, filename) */
|
||||
data->label = grub_zalloc (max_len + 1);
|
||||
+ if (data->label == NULL)
|
||||
+ goto fail;
|
||||
+
|
||||
grub_strncpy (data->label, (char *) rootobjc->objects[0].filename, max_len);
|
||||
|
||||
grub_free (rootobjc_data);
|
@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 29 Jan 2025 06:48:37 +0000
|
||||
Subject: [PATCH] script/execute: Fix potential underflow and NULL dereference
|
||||
|
||||
The result is initialized to 0 in grub_script_arglist_to_argv().
|
||||
If the for loop condition is not met both result.args and result.argc
|
||||
remain 0 causing result.argc - 1 to underflow and/or result.args NULL
|
||||
dereference. Fix the issues by adding relevant checks.
|
||||
|
||||
Fixes: CID 473880
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/script/execute.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
|
||||
index c383eb87c..89fdaa101 100644
|
||||
--- a/grub-core/script/execute.c
|
||||
+++ b/grub-core/script/execute.c
|
||||
@@ -794,6 +794,9 @@ cleanup:
|
||||
}
|
||||
}
|
||||
|
||||
+ if (result.args == NULL || result.argc == 0)
|
||||
+ goto fail;
|
||||
+
|
||||
if (! result.args[result.argc - 1])
|
||||
result.argc--;
|
||||
|
35
0443-osdep-unix-getroot-Fix-potential-underflow.patch
Normal file
35
0443-osdep-unix-getroot-Fix-potential-underflow.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Wed, 29 Jan 2025 06:48:38 +0000
|
||||
Subject: [PATCH] osdep/unix/getroot: Fix potential underflow
|
||||
|
||||
The entry_len is initialized in grub_find_root_devices_from_mountinfo()
|
||||
to 0 before the while loop iterates through /proc/self/mountinfo. If the
|
||||
file is empty or contains only invalid entries entry_len remains
|
||||
0 causing entry_len - 1 in the subsequent for loop initialization
|
||||
to underflow. To prevent this add a check to ensure entry_len > 0 before
|
||||
entering the for loop.
|
||||
|
||||
Fixes: CID 473877
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
|
||||
---
|
||||
grub-core/osdep/linux/getroot.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
|
||||
index f0c503f43..893527a95 100644
|
||||
--- a/grub-core/osdep/linux/getroot.c
|
||||
+++ b/grub-core/osdep/linux/getroot.c
|
||||
@@ -599,6 +599,9 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
+ if (!entry_len)
|
||||
+ goto out;
|
||||
+
|
||||
/* Now scan visible mounts for the ones we're interested in. */
|
||||
for (i = entry_len - 1; i >= 0; i--)
|
||||
{
|
55
0444-misc-Ensure-consistent-overflow-error-messages.patch
Normal file
55
0444-misc-Ensure-consistent-overflow-error-messages.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Tue, 21 Jan 2025 19:02:39 +0000
|
||||
Subject: [PATCH] misc: Ensure consistent overflow error messages
|
||||
|
||||
Update the overflow error messages to make them consistent
|
||||
across the GRUB code.
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/ntfs.c | 2 +-
|
||||
grub-core/fs/ntfscomp.c | 2 +-
|
||||
grub-core/video/readers/png.c | 2 +-
|
||||
3 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index 96f038c54..7ebcaf063 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -574,7 +574,7 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
- return grub_error (GRUB_ERR_BAD_FS, "run list overflown");
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "run list overflow");
|
||||
}
|
||||
ctx->curr_vcn = ctx->next_vcn;
|
||||
ctx->next_vcn += read_run_data (run, c1, 0); /* length of current VCN */
|
||||
diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c
|
||||
index 4bf95c85d..88594702e 100644
|
||||
--- a/grub-core/fs/ntfscomp.c
|
||||
+++ b/grub-core/fs/ntfscomp.c
|
||||
@@ -30,7 +30,7 @@ static grub_err_t
|
||||
decomp_nextvcn (struct grub_ntfs_comp *cc)
|
||||
{
|
||||
if (cc->comp_head >= cc->comp_tail)
|
||||
- return grub_error (GRUB_ERR_BAD_FS, "compression block overflown");
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "compression block overflow");
|
||||
if (grub_disk_read
|
||||
(cc->disk,
|
||||
(cc->comp_table[cc->comp_head].next_lcn -
|
||||
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
|
||||
index 7f2ba7849..3ff215dd6 100644
|
||||
--- a/grub-core/video/readers/png.c
|
||||
+++ b/grub-core/video/readers/png.c
|
||||
@@ -622,7 +622,7 @@ static grub_err_t
|
||||
grub_png_output_byte (struct grub_png_data *data, grub_uint8_t n)
|
||||
{
|
||||
if (--data->raw_bytes < 0)
|
||||
- return grub_error (GRUB_ERR_BAD_FILE_TYPE, "image size overflown");
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "image size overflow");
|
||||
|
||||
if (data->cur_column == 0)
|
||||
{
|
@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Tue, 4 Feb 2025 15:11:10 +0000
|
||||
Subject: [PATCH] bus/usb/ehci: Define GRUB_EHCI_TOGGLE as grub_uint32_t
|
||||
|
||||
The Coverity indicates that GRUB_EHCI_TOGGLE is an int that contains
|
||||
a negative value and we are using it for the variable token which is
|
||||
grub_uint32_t. To remedy this we can cast the definition to grub_uint32_t.
|
||||
|
||||
Fixes: CID 473851
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/bus/usb/ehci.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c
|
||||
index d966fc210..d1e8a01ca 100644
|
||||
--- a/grub-core/bus/usb/ehci.c
|
||||
+++ b/grub-core/bus/usb/ehci.c
|
||||
@@ -218,7 +218,7 @@ enum
|
||||
|
||||
#define GRUB_EHCI_TERMINATE (1<<0)
|
||||
|
||||
-#define GRUB_EHCI_TOGGLE (1<<31)
|
||||
+#define GRUB_EHCI_TOGGLE ((grub_uint32_t) 1<<31)
|
||||
|
||||
enum
|
||||
{
|
@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Tue, 4 Feb 2025 15:11:11 +0000
|
||||
Subject: [PATCH] normal/menu: Use safe math to avoid an integer overflow
|
||||
|
||||
The Coverity indicates that the variable current_entry might overflow.
|
||||
To prevent this use safe math when adding GRUB_MENU_PAGE_SIZE to current_entry.
|
||||
|
||||
On the occasion fix limiting condition which was broken.
|
||||
|
||||
Fixes: CID 473853
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/normal/menu.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
|
||||
index c8516a5a0..9a6033109 100644
|
||||
--- a/grub-core/normal/menu.c
|
||||
+++ b/grub-core/normal/menu.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/gfxterm.h>
|
||||
#include <grub/dl.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
/* Time to delay after displaying an error message about a default/fallback
|
||||
entry failing to boot. */
|
||||
@@ -784,9 +785,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
|
||||
|
||||
case GRUB_TERM_CTRL | 'c':
|
||||
case GRUB_TERM_KEY_NPAGE:
|
||||
- if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size)
|
||||
- current_entry += GRUB_MENU_PAGE_SIZE;
|
||||
- else
|
||||
+ if (grub_add (current_entry, GRUB_MENU_PAGE_SIZE, ¤t_entry) || current_entry >= menu->size)
|
||||
current_entry = menu->size - 1;
|
||||
menu_set_chosen_entry (current_entry);
|
||||
break;
|
@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Thu, 6 Feb 2025 18:16:56 +0000
|
||||
Subject: [PATCH] kern/partition: Add sanity check after grub_strtoul() call
|
||||
|
||||
The current code incorrectly assumes that both the input and the values
|
||||
returned by grub_strtoul() are always valid which can lead to potential
|
||||
errors. This fix ensures proper validation to prevent any unintended issues.
|
||||
|
||||
Fixes: CID 473843
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/partition.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c
|
||||
index f3f125e75..144a7b6a6 100644
|
||||
--- a/grub-core/kern/partition.c
|
||||
+++ b/grub-core/kern/partition.c
|
||||
@@ -125,14 +125,22 @@ grub_partition_probe (struct grub_disk *disk, const char *str)
|
||||
for (ptr = str; *ptr;)
|
||||
{
|
||||
grub_partition_map_t partmap;
|
||||
- int num;
|
||||
+ unsigned long num;
|
||||
const char *partname, *partname_end;
|
||||
|
||||
partname = ptr;
|
||||
while (*ptr && grub_isalpha (*ptr))
|
||||
ptr++;
|
||||
partname_end = ptr;
|
||||
- num = grub_strtoul (ptr, &ptr, 0) - 1;
|
||||
+
|
||||
+ num = grub_strtoul (ptr, &ptr, 0);
|
||||
+ if (*ptr != '\0' || num == 0 || num > GRUB_INT_MAX)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid partition number"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ num -= 1;
|
||||
|
||||
curpart = 0;
|
||||
/* Use the first partition map type found. */
|
@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lidong Chen <lidong.chen@oracle.com>
|
||||
Date: Thu, 6 Feb 2025 18:16:57 +0000
|
||||
Subject: [PATCH] kern/misc: Add sanity check after grub_strtoul() call
|
||||
|
||||
When the format string, fmt0, includes a positional argument
|
||||
grub_strtoul() or grub_strtoull() is called to extract the argument
|
||||
position. However, the returned argument position isn't fully validated.
|
||||
If the format is something like "%0$x" then these functions return
|
||||
0 which leads to an underflow in the calculation of the args index, curn.
|
||||
The fix is to add a check to ensure the extracted argument position is
|
||||
greater than 0 before computing curn. Additionally, replace one
|
||||
grub_strtoull() with grub_strtoul() and change curn type to make code
|
||||
more correct.
|
||||
|
||||
Fixes: CID 473841
|
||||
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/misc.c | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
|
||||
index 50af9ee1b..da2f6e551 100644
|
||||
--- a/grub-core/kern/misc.c
|
||||
+++ b/grub-core/kern/misc.c
|
||||
@@ -858,7 +858,7 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
|
||||
while ((c = *fmt++) != 0)
|
||||
{
|
||||
int longfmt = 0;
|
||||
- grub_size_t curn;
|
||||
+ unsigned long curn;
|
||||
const char *p;
|
||||
|
||||
if (c != '%')
|
||||
@@ -876,7 +876,10 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
|
||||
|
||||
if (*fmt == '$')
|
||||
{
|
||||
- curn = grub_strtoull (p, 0, 10) - 1;
|
||||
+ curn = grub_strtoul (p, 0, 10);
|
||||
+ if (curn == 0)
|
||||
+ continue;
|
||||
+ curn--;
|
||||
fmt++;
|
||||
}
|
||||
|
||||
@@ -1035,6 +1038,8 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
|
||||
|
||||
if (*fmt == '$')
|
||||
{
|
||||
+ if (format1 == 0)
|
||||
+ continue;
|
||||
curn = format1 - 1;
|
||||
fmt++;
|
||||
format1 = 0;
|
@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Wed, 12 Feb 2025 10:56:13 -0600
|
||||
Subject: [PATCH] loader/i386/linux: Cast left shift to grub_uint32_t
|
||||
|
||||
The Coverity complains that we might overflow into a negative value when
|
||||
setting linux_params.kernel_alignment to (1 << align). We can remedy
|
||||
this by casting it to grub_uint32_t.
|
||||
|
||||
Fixes: CID 473876
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/loader/i386/linux.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
|
||||
index 3c1ff6476..9d4c57619 100644
|
||||
--- a/grub-core/loader/i386/linux.c
|
||||
+++ b/grub-core/loader/i386/linux.c
|
||||
@@ -811,7 +811,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, GRUB_MEM_ATTR_X);
|
||||
|
||||
linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
|
||||
- linux_params.kernel_alignment = (1 << align);
|
||||
+ linux_params.kernel_alignment = ((grub_uint32_t)1 << align);
|
||||
linux_params.ps_mouse = linux_params.padding11 = 0;
|
||||
linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
|
||||
|
56
0450-loader-i386-bsd-Use-safe-math-to-avoid-underflow.patch
Normal file
56
0450-loader-i386-bsd-Use-safe-math-to-avoid-underflow.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Wed, 5 Feb 2025 22:04:08 +0000
|
||||
Subject: [PATCH] loader/i386/bsd: Use safe math to avoid underflow
|
||||
|
||||
The operation kern_end - kern_start may underflow when we input it into
|
||||
grub_relocator_alloc_chunk_addr() call. To avoid this we can use safe
|
||||
math for this subtraction.
|
||||
|
||||
Fixes: CID 73845
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/loader/i386/bsd.c | 14 ++++++++++----
|
||||
1 file changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
|
||||
index 54befc266..939628f9e 100644
|
||||
--- a/grub-core/loader/i386/bsd.c
|
||||
+++ b/grub-core/loader/i386/bsd.c
|
||||
@@ -1341,6 +1341,7 @@ static grub_err_t
|
||||
grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
||||
{
|
||||
grub_err_t err;
|
||||
+ grub_size_t sz;
|
||||
|
||||
kern_end = 0;
|
||||
kern_start = ~0;
|
||||
@@ -1371,8 +1372,11 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
||||
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
- err = grub_relocator_alloc_chunk_addr (relocator, &ch,
|
||||
- kern_start, kern_end - kern_start);
|
||||
+
|
||||
+ if (grub_sub (kern_end, kern_start, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while determining size of kernel for relocator");
|
||||
+
|
||||
+ err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start, sz);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1432,8 +1436,10 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start,
|
||||
- kern_end - kern_start);
|
||||
+ if (grub_sub (kern_end, kern_start, &sz))
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while determining size of kernel for relocator");
|
||||
+
|
||||
+ err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start, sz);
|
||||
if (err)
|
||||
return err;
|
||||
kern_chunk_src = get_virtual_current_address (ch);
|
78
0451-types-Make-bool-generally-available.patch
Normal file
78
0451-types-Make-bool-generally-available.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robbie Harwood <rharwood@redhat.com>
|
||||
Date: Fri, 4 Nov 2022 12:13:34 -0400
|
||||
Subject: [PATCH] types: Make bool generally available
|
||||
|
||||
Add an include on stdbool.h, making the bool type generally available
|
||||
within the GRUB without needing to add a file-specific include every
|
||||
time it would be used.
|
||||
|
||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/parttool.c | 2 +-
|
||||
grub-core/parttool/msdospart.c | 4 ++--
|
||||
include/grub/parttool.h | 2 +-
|
||||
include/grub/types.h | 1 +
|
||||
4 files changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c
|
||||
index 051e31320..ff45c65e6 100644
|
||||
--- a/grub-core/commands/parttool.c
|
||||
+++ b/grub-core/commands/parttool.c
|
||||
@@ -315,7 +315,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
||||
switch (curarg->type)
|
||||
{
|
||||
case GRUB_PARTTOOL_ARG_BOOL:
|
||||
- pargs[curarg - ptool->args].bool
|
||||
+ pargs[curarg - ptool->args].b
|
||||
= (args[j][grub_strlen (curarg->name)] != '-');
|
||||
break;
|
||||
|
||||
diff --git a/grub-core/parttool/msdospart.c b/grub-core/parttool/msdospart.c
|
||||
index 3918caa06..3a7699e45 100644
|
||||
--- a/grub-core/parttool/msdospart.c
|
||||
+++ b/grub-core/parttool/msdospart.c
|
||||
@@ -61,7 +61,7 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev,
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
- if (args[0].set && args[0].bool)
|
||||
+ if (args[0].set && args[0].b)
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
mbr.entries[i].flag = 0x0;
|
||||
@@ -116,7 +116,7 @@ static grub_err_t grub_pcpart_type (const grub_device_t dev,
|
||||
|
||||
if (args[1].set)
|
||||
{
|
||||
- if (args[1].bool)
|
||||
+ if (args[1].b)
|
||||
type |= GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG;
|
||||
else
|
||||
type &= ~GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG;
|
||||
diff --git a/include/grub/parttool.h b/include/grub/parttool.h
|
||||
index 4e8f8d5e5..4799a22c5 100644
|
||||
--- a/include/grub/parttool.h
|
||||
+++ b/include/grub/parttool.h
|
||||
@@ -32,7 +32,7 @@ struct grub_parttool_args
|
||||
int set;
|
||||
union
|
||||
{
|
||||
- int bool;
|
||||
+ int b;
|
||||
char *str;
|
||||
};
|
||||
};
|
||||
diff --git a/include/grub/types.h b/include/grub/types.h
|
||||
index ba446d990..c00842ab0 100644
|
||||
--- a/include/grub/types.h
|
||||
+++ b/include/grub/types.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#define GRUB_TYPES_HEADER 1
|
||||
|
||||
#include <config.h>
|
||||
+#include <stdbool.h>
|
||||
#ifndef GRUB_UTIL
|
||||
#include <grub/cpu/types.h>
|
||||
#endif
|
@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glenn Washburn <development@efficientek.com>
|
||||
Date: Wed, 28 Jun 2023 02:38:23 -0500
|
||||
Subject: [PATCH] include/grub/types.h: Add PRI*GRUB_OFFSET and
|
||||
PRI*GRUB_DISK_ADDR
|
||||
|
||||
These are currently always the same as PRI*GRUB_UINT64_T, but they may
|
||||
not be in the future.
|
||||
|
||||
Signed-off-by: Glenn Washburn <development@efficientek.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
include/grub/types.h | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/grub/types.h b/include/grub/types.h
|
||||
index c00842a..1587ff4 100644
|
||||
--- a/include/grub/types.h
|
||||
+++ b/include/grub/types.h
|
||||
@@ -181,10 +181,13 @@ typedef grub_uint64_t grub_properly_aligned_t;
|
||||
#define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
|
||||
|
||||
/* The type for representing a file offset. */
|
||||
-typedef grub_uint64_t grub_off_t;
|
||||
+typedef grub_uint64_t grub_off_t;
|
||||
+#define PRIxGRUB_OFFSET PRIxGRUB_UINT64_T
|
||||
+#define PRIuGRUB_OFFSET PRIuGRUB_UINT64_T
|
||||
|
||||
/* The type for representing a disk block address. */
|
||||
-typedef grub_uint64_t grub_disk_addr_t;
|
||||
+typedef grub_uint64_t grub_disk_addr_t;
|
||||
+#define PRIxGRUB_DISK_ADDR PRIxGRUB_UINT64_T
|
||||
|
||||
/* Byte-orders. */
|
||||
static inline grub_uint16_t grub_swap_bytes16(grub_uint16_t _x)
|
106
0453-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch
Normal file
106
0453-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Darren Kenny <darren.kenny@oracle.com>
|
||||
Date: Fri, 2 Jun 2023 18:08:44 +0000
|
||||
Subject: [PATCH] fs/xfs: Fix issues found while fuzzing the XFS filesystem
|
||||
|
||||
While performing fuzz testing with XFS filesystem images with ASAN
|
||||
enabled, several issues were found where the memory accesses are made
|
||||
beyond the data that is allocated into the struct grub_xfs_data
|
||||
structure's data field.
|
||||
|
||||
The existing structure didn't store the size of the memory allocated into
|
||||
the buffer in the data field and had no way to check it. To resolve these
|
||||
issues, the data size is stored to enable checks into the data buffer.
|
||||
|
||||
With these checks in place, the fuzzing corpus no longer cause any crashes.
|
||||
|
||||
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
|
||||
Signed-off-by: Marta Lewandowska <mlewando@redhat.com>
|
||||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/xfs.c | 26 ++++++++++++++++++++++++++
|
||||
1 file changed, 26 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||
index ff6fe3d..cc50feb 100644
|
||||
--- a/grub-core/fs/xfs.c
|
||||
+++ b/grub-core/fs/xfs.c
|
||||
@@ -239,6 +239,7 @@ struct grub_fshelp_node
|
||||
|
||||
struct grub_xfs_data
|
||||
{
|
||||
+ grub_size_t data_size;
|
||||
struct grub_xfs_sblock sblock;
|
||||
grub_disk_t disk;
|
||||
int pos;
|
||||
@@ -621,8 +622,20 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
}
|
||||
else if (node->inode.format == XFS_INODE_FORMAT_EXT)
|
||||
{
|
||||
+ grub_addr_t exts_end = 0;
|
||||
+ grub_addr_t data_end = 0;
|
||||
+
|
||||
nrec = grub_be_to_cpu32 (node->inode.nextents);
|
||||
exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode);
|
||||
+
|
||||
+ if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) ||
|
||||
+ grub_add ((grub_addr_t) node->data, exts_end, &exts_end) ||
|
||||
+ grub_add ((grub_addr_t) node->data, node->data->data_size, &data_end) ||
|
||||
+ exts_end > data_end)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FS, "invalid number of XFS extents");
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -825,6 +838,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de);
|
||||
grub_uint8_t c;
|
||||
|
||||
+ if ((inopos + (smallino ? 4 : 8)) > (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "not a correct XFS inode");
|
||||
+
|
||||
/* inopos might be unaligned. */
|
||||
if (smallino)
|
||||
ino = (((grub_uint32_t) inopos[0]) << 24)
|
||||
@@ -851,6 +867,10 @@ 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;
|
||||
}
|
||||
@@ -916,6 +936,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
}
|
||||
|
||||
filename = (char *)(direntry + 1);
|
||||
+ if (filename + direntry->len - 1 > (char *) tail)
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
|
||||
+
|
||||
/* The byte after the filename is for the filetype, padding, or
|
||||
tag, which is not used by GRUB. So it can be overwritten. */
|
||||
filename[direntry->len] = '\0';
|
||||
@@ -960,6 +983,8 @@ grub_xfs_mount (grub_disk_t disk)
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
+ data->data_size = sizeof (struct grub_xfs_data);
|
||||
+
|
||||
grub_dprintf("xfs", "Reading sb\n");
|
||||
/* Read the superblock. */
|
||||
if (grub_disk_read (disk, 0, 0,
|
||||
@@ -981,6 +1006,7 @@ grub_xfs_mount (grub_disk_t disk)
|
||||
if (! data)
|
||||
goto fail;
|
||||
|
||||
+ data->data_size = sz;
|
||||
data->diropen.data = data;
|
||||
data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino);
|
||||
data->diropen.inode_read = 1;
|
99
grub.patches
99
grub.patches
@ -352,3 +352,102 @@ Patch0351: 0351-arm64-Use-proper-memory-type-for-kernel-allocation.patch
|
||||
Patch0352: 0352-cmd-search-Fix-a-possible-NULL-ptr-dereference.patch
|
||||
Patch0353: 0353-10_linux.in-escape-semicolon-and-ampersand-on-BLS-up.patch
|
||||
Patch0354: 0354-kern-ieee1275-init-Add-IEEE-1275-Radix-support-for-K.patch
|
||||
Patch0355: 0355-misc-Implement-grub_strlcpy.patch
|
||||
Patch0356: 0356-fs-ufs-Fix-a-heap-OOB-write.patch
|
||||
Patch0357: 0357-fs-hfs-Fix-stack-OOB-write-with-grub_strcpy.patch
|
||||
Patch0358: 0358-fs-tar-Initialize-name-in-grub_cpio_find_file.patch
|
||||
Patch0359: 0359-fs-tar-Integer-overflow-leads-to-heap-OOB-write.patch
|
||||
Patch0360: 0360-fs-f2fs-Set-a-grub_errno-if-mount-fails.patch
|
||||
Patch0361: 0361-fs-hfsplus-Set-a-grub_errno-if-mount-fails.patch
|
||||
Patch0362: 0362-fs-iso9660-Set-a-grub_errno-if-mount-fails.patch
|
||||
Patch0363: 0363-fs-iso9660-Fix-invalid-free.patch
|
||||
Patch0364: 0364-fs-jfs-Fix-OOB-read-in-jfs_getent.patch
|
||||
Patch0365: 0365-fs-jfs-Fix-OOB-read-caused-by-invalid-dir-slot-index.patch
|
||||
Patch0366: 0366-fs-jfs-Use-full-40-bits-offset-and-address-for-a-dat.patch
|
||||
Patch0367: 0367-fs-jfs-Inconsistent-signed-unsigned-types-usage-in-r.patch
|
||||
Patch0368: 0368-fs-ext2-Fix-out-of-bounds-read-for-inline-extents.patch
|
||||
Patch0369: 0369-fs-ntfs-Fix-out-of-bounds-read.patch
|
||||
Patch0370: 0370-fs-ntfs-Track-the-end-of-the-MFT-attribute-buffer.patch
|
||||
Patch0371: 0371-fs-ntfs-Use-a-helper-function-to-access-attributes.patch
|
||||
Patch0372: 0372-fs-ntfs-Implement-attribute-verification.patch
|
||||
Patch0373: 0373-fs-xfs-Fix-out-of-bounds-read.patch
|
||||
Patch0374: 0374-fs-xfs-Ensuring-failing-to-mount-sets-a-grub_errno.patch
|
||||
Patch0375: 0375-kern-file-Ensure-file-data-is-set.patch
|
||||
Patch0376: 0376-kern-file-Implement-filesystem-reference-counting.patch
|
||||
Patch0377: 0377-cli_lock-Add-build-option-to-block-command-line-inte.patch
|
||||
Patch0378: 0378-cryptodisk-Refactor-to-discard-have_it-global.patch
|
||||
Patch0379: 0379-cryptodisk-Return-failure-in-cryptomount-when-no-cry.patch
|
||||
Patch0380: 0380-cryptodisk-Improve-error-messaging-in-cryptomount-in.patch
|
||||
Patch0381: 0381-cryptodisk-Improve-cryptomount-u-error-message.patch
|
||||
Patch0382: 0382-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch
|
||||
Patch0383: 0383-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch
|
||||
Patch0384: 0384-luks2-Add-debug-message-to-align-with-luks-and-geli-.patch
|
||||
Patch0385: 0385-cryptodisk-Move-global-variables-into-grub_cryptomou.patch
|
||||
Patch0386: 0386-cryptodisk-Improve-handling-of-partition-name-in-cry.patch
|
||||
Patch0387: 0387-cryptodisk-Fix-Coverity-use-after-free-bug.patch
|
||||
Patch0388: 0388-disk-cryptodisk-Add-options-to-cryptomount-to-suppor.patch
|
||||
Patch0389: 0389-disk-cryptodisk-Use-enum-constants-as-indexes-into-c.patch
|
||||
Patch0390: 0390-cryptodisk-Add-support-for-using-detached-header-fil.patch
|
||||
Patch0391: 0391-disk-cryptodisk-Support-encrypted-volumes-using-deta.patch
|
||||
Patch0392: 0392-disk-cryptodisk-Allows-UUIDs-to-be-compared-in-a-das.patch
|
||||
Patch0393: 0393-disk-cryptodisk-Fix-unintentional-integer-overflow.patch
|
||||
Patch0394: 0394-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch
|
||||
Patch0395: 0395-disk-cryptodisk-Fix-missing-change-when-updating-to-.patch
|
||||
Patch0396: 0396-disk-cryptodisk-Optimize-luks_script_get.patch
|
||||
Patch0397: 0397-disk-cryptodisk-Add-support-for-LUKS2-in-proc-luks_s.patch
|
||||
Patch0398: 0398-disk-cryptodisk-Require-authentication-after-TPM-unl.patch
|
||||
Patch0399: 0399-disk-loopback-Reference-tracking-for-the-loopback.patch
|
||||
Patch0400: 0400-kern-disk-Limit-recursion-depth.patch
|
||||
Patch0401: 0401-kern-partition-Limit-recursion-in-part_iterate.patch
|
||||
Patch0402: 0402-script-execute-Limit-the-recursion-depth.patch
|
||||
Patch0403: 0403-net-Unregister-net_default_ip-and-net_default_mac-va.patch
|
||||
Patch0404: 0404-net-Remove-variables-hooks-when-interface-is-unregis.patch
|
||||
Patch0405: 0405-net-Fix-OOB-write-in-grub_net_search_config_file.patch
|
||||
Patch0406: 0406-net-tftp-Fix-stack-buffer-overflow-in-tftp_open.patch
|
||||
Patch0407: 0407-video-readers-jpeg-Do-not-permit-duplicate-SOF0-mark.patch
|
||||
Patch0408: 0408-kern-dl-Fix-for-an-integer-overflow-in-grub_dl_ref.patch
|
||||
Patch0409: 0409-kern-dl-Check-for-the-SHF_INFO_LINK-flag-in-grub_dl_.patch
|
||||
Patch0410: 0410-commands-extcmd-Missing-check-for-failed-allocation.patch
|
||||
Patch0411: 0411-commands-ls-Fix-NULL-dereference.patch
|
||||
Patch0412: 0412-commands-pgp-Unregister-the-check_signatures-hooks-o.patch
|
||||
Patch0413: 0413-normal-Remove-variables-hooks-on-module-unload.patch
|
||||
Patch0414: 0414-gettext-Remove-variables-hooks-on-module-unload.patch
|
||||
Patch0415: 0415-gettext-Integer-overflow-leads-to-heap-OOB-write-or-.patch
|
||||
Patch0416: 0416-gettext-Integer-overflow-leads-to-heap-OOB-write.patch
|
||||
Patch0417: 0417-commands-read-Add-silent-mode-to-read-command-to-sup.patch
|
||||
Patch0418: 0418-commands-read-Fix-overflow-in-grub_getline.patch
|
||||
Patch0419: 0419-commands-read-Fix-an-integer-overflow-when-supplying.patch
|
||||
Patch0420: 0420-commands-test-Stack-overflow-due-to-unlimited-recurs.patch
|
||||
Patch0421: 0421-commands-minicmd-Block-the-dump-command-in-lockdown-.patch
|
||||
Patch0422: 0422-commands-memrw-Disable-memory-reading-in-lockdown-mo.patch
|
||||
Patch0423: 0423-commands-hexdump-Disable-memory-reading-in-lockdown-.patch
|
||||
Patch0424: 0424-fs-bfs-Disable-under-lockdown.patch
|
||||
Patch0425: 0425-fs-Disable-many-filesystems-under-lockdown.patch
|
||||
Patch0426: 0426-disk-plainmount-Support-plain-encryption-mode.patch
|
||||
Patch0427: 0427-disk-Use-safe-math-macros-to-prevent-overflows.patch
|
||||
Patch0428: 0428-disk-Prevent-overflows-when-allocating-memory-for-ar.patch
|
||||
Patch0429: 0429-disk-Check-if-returned-pointer-for-allocated-memory-.patch
|
||||
Patch0430: 0430-disk-ieee1275-ofdisk-Call-grub_ieee1275_close-when-g.patch
|
||||
Patch0431: 0431-fs-Use-safe-math-macros-to-prevent-overflows.patch
|
||||
Patch0432: 0432-fs-Prevent-overflows-when-allocating-memory-for-arra.patch
|
||||
Patch0433: 0433-fs-Prevent-overflows-when-assigning-returned-values-.patch
|
||||
Patch0434: 0434-fs-zfs-Use-safe-math-macros-to-prevent-overflows.patch
|
||||
Patch0435: 0435-fs-zfs-Prevent-overflows-when-allocating-memory-for-.patch
|
||||
Patch0436: 0436-fs-zfs-Check-if-returned-pointer-for-allocated-memor.patch
|
||||
Patch0437: 0437-fs-zfs-Add-missing-NULL-check-after-grub_strdup-call.patch
|
||||
Patch0438: 0438-net-Use-safe-math-macros-to-prevent-overflows.patch
|
||||
Patch0439: 0439-net-Prevent-overflows-when-allocating-memory-for-arr.patch
|
||||
Patch0440: 0440-net-Check-if-returned-pointer-for-allocated-memory-i.patch
|
||||
Patch0441: 0441-fs-sfs-Check-if-allocated-memory-is-NULL.patch
|
||||
Patch0442: 0442-script-execute-Fix-potential-underflow-and-NULL-dere.patch
|
||||
Patch0443: 0443-osdep-unix-getroot-Fix-potential-underflow.patch
|
||||
Patch0444: 0444-misc-Ensure-consistent-overflow-error-messages.patch
|
||||
Patch0445: 0445-bus-usb-ehci-Define-GRUB_EHCI_TOGGLE-as-grub_uint32_.patch
|
||||
Patch0446: 0446-normal-menu-Use-safe-math-to-avoid-an-integer-overfl.patch
|
||||
Patch0447: 0447-kern-partition-Add-sanity-check-after-grub_strtoul-c.patch
|
||||
Patch0448: 0448-kern-misc-Add-sanity-check-after-grub_strtoul-call.patch
|
||||
Patch0449: 0449-loader-i386-linux-Cast-left-shift-to-grub_uint32_t.patch
|
||||
Patch0450: 0450-loader-i386-bsd-Use-safe-math-to-avoid-underflow.patch
|
||||
Patch0451: 0451-types-Make-bool-generally-available.patch
|
||||
Patch0452: 0452-include-grub-types.h-Add-PRI-GRUB_OFFSET-and-PRI-GRU.patch
|
||||
Patch0453: 0453-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user