forked from pool/grub2
e016790fe1
- Security fixes and hardenings for boothole 3 / boothole 2022 (bsc#1198581) * 0001-video-Remove-trailing-whitespaces.patch * 0002-loader-efi-chainloader-Simplify-the-loader-state.patch * 0003-commands-boot-Add-API-to-pass-context-to-loader.patch - Fix CVE-2022-28736 (bsc#1198496) * 0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch - Fix CVE-2022-28735 (bsc#1198495) * 0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch * 0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch * 0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch * 0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch - Fix CVE-2021-3695 (bsc#1191184) * 0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch - Fix CVE-2021-3696 (bsc#1191185) * 0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch * 0011-video-readers-png-Sanity-check-some-huffman-codes.patch * 0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch * 0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch * 0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch - Fix CVE-2021-3697 (bsc#1191186) * 0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch * 0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch - Fix CVE-2022-28733 (bsc#1198460) * 0017-net-ip-Do-IP-fragment-maths-safely.patch * 0018-net-netbuff-Block-overly-large-netbuff-allocs.patch * 0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch * 0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch * 0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch * 0022-net-tftp-Avoid-a-trivial-UAF.patch * 0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch OBS-URL: https://build.opensuse.org/request/show/981228 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=416
116 lines
4.1 KiB
Diff
116 lines
4.1 KiB
Diff
From 4adbb12d15af04f8f279a6290cd0195e57cc9e69 Mon Sep 17 00:00:00 2001
|
|
From: Daniel Axtens <dja@axtens.net>
|
|
Date: Mon, 20 Sep 2021 01:12:24 +1000
|
|
Subject: [PATCH 21/32] net/tftp: Prevent a UAF and double-free from a failed
|
|
seek
|
|
|
|
A malicious tftp server can cause UAFs and a double free.
|
|
|
|
An attempt to read from a network file is handled by grub_net_fs_read(). If
|
|
the read is at an offset other than the current offset, grub_net_seek_real()
|
|
is invoked.
|
|
|
|
In grub_net_seek_real(), if a backwards seek cannot be satisfied from the
|
|
currently received packets, and the underlying transport does not provide
|
|
a seek method, then grub_net_seek_real() will close and reopen the network
|
|
protocol layer.
|
|
|
|
For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t
|
|
file->data. The file->data pointer is not nulled out after the free.
|
|
|
|
If the ->open() call fails, the file->data will not be reallocated and will
|
|
continue point to a freed memory block. This could happen from a server
|
|
refusing to send the requisite ack to the new tftp request, for example.
|
|
|
|
The seek and the read will then fail, but the grub_file continues to exist:
|
|
the failed seek does not necessarily cause the entire file to be thrown
|
|
away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc.,
|
|
a read failure is interpreted as a decompressor passing on the file, not as
|
|
an invalidation of the entire grub_file_t structure).
|
|
|
|
This means subsequent attempts to read or seek the file will use the old
|
|
file->data after free. Eventually, the file will be close()d again and
|
|
file->data will be freed again.
|
|
|
|
Mark a net_fs file that doesn't reopen as broken. Do not permit read() or
|
|
close() on a broken file (seek is not exposed directly to the file API -
|
|
it is only called as part of read, so this blocks seeks as well).
|
|
|
|
As an additional defence, null out the ->data pointer if tftp_open() fails.
|
|
That would have lead to a simple null pointer dereference rather than
|
|
a mess of UAFs.
|
|
|
|
This may affect other protocols, I haven't checked.
|
|
|
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
grub-core/net/net.c | 11 +++++++++--
|
|
grub-core/net/tftp.c | 1 +
|
|
include/grub/net.h | 1 +
|
|
3 files changed, 11 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
|
index d11672fbee..b8238b7df1 100644
|
|
--- a/grub-core/net/net.c
|
|
+++ b/grub-core/net/net.c
|
|
@@ -1546,7 +1546,8 @@ grub_net_fs_close (grub_file_t file)
|
|
grub_netbuff_free (file->device->net->packs.first->nb);
|
|
grub_net_remove_packet (file->device->net->packs.first);
|
|
}
|
|
- file->device->net->protocol->close (file);
|
|
+ if (!file->device->net->broken)
|
|
+ file->device->net->protocol->close (file);
|
|
grub_free (file->device->net->name);
|
|
return GRUB_ERR_NONE;
|
|
}
|
|
@@ -1768,7 +1769,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
|
file->device->net->stall = 0;
|
|
err = file->device->net->protocol->open (file, file->device->net->name);
|
|
if (err)
|
|
- return err;
|
|
+ {
|
|
+ file->device->net->broken = 1;
|
|
+ return err;
|
|
+ }
|
|
grub_net_fs_read_real (file, NULL, offset);
|
|
return grub_errno;
|
|
}
|
|
@@ -1777,6 +1781,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
|
static grub_ssize_t
|
|
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
|
{
|
|
+ if (file->device->net->broken)
|
|
+ return -1;
|
|
+
|
|
if (file->offset != file->device->net->offset)
|
|
{
|
|
grub_err_t err;
|
|
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
|
index f3e7879388..d1afa25352 100644
|
|
--- a/grub-core/net/tftp.c
|
|
+++ b/grub-core/net/tftp.c
|
|
@@ -404,6 +404,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
{
|
|
grub_net_udp_close (data->sock);
|
|
grub_free (data);
|
|
+ file->data = NULL;
|
|
return grub_errno;
|
|
}
|
|
|
|
diff --git a/include/grub/net.h b/include/grub/net.h
|
|
index cbcae79b1f..8d71ca6cc5 100644
|
|
--- a/include/grub/net.h
|
|
+++ b/include/grub/net.h
|
|
@@ -277,6 +277,7 @@ typedef struct grub_net
|
|
grub_fs_t fs;
|
|
int eof;
|
|
int stall;
|
|
+ int broken;
|
|
} *grub_net_t;
|
|
|
|
extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
|
|
--
|
|
2.34.1
|
|
|