[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[SECURITY PATCH 20/30] net/tftp: Prevent a UAF and double-free from a fa
From: |
Daniel Kiper |
Subject: |
[SECURITY PATCH 20/30] net/tftp: Prevent a UAF and double-free from a failed seek |
Date: |
Tue, 7 Jun 2022 19:01:29 +0200 |
From: Daniel Axtens <dja@axtens.net>
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 2b6771523..9f09f8e48 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1521,7 +1521,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;
}
@@ -1744,7 +1745,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;
}
@@ -1753,6 +1757,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 ebbafe7a1..ee305e18a 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -400,6 +400,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 db21e792f..a64a04cc8 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -276,6 +276,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.11.0
- [SECURITY PATCH 26/30] fs/f2fs: Do not read past the end of nat bitmap, (continued)
- [SECURITY PATCH 26/30] fs/f2fs: Do not read past the end of nat bitmap, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 12/30] video/readers/jpeg: Do not reallocate a given huff table, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 03/30] loader/efi/chainloader: Use grub_loader_set_ex(), Daniel Kiper, 2022/06/07
- [SECURITY PATCH 10/30] video/readers/png: Sanity check some huffman codes, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 09/30] video/readers/png: Avoid heap OOB R/W inserting huff table items, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 07/30] video/readers/png: Refuse to handle multiple image headers, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 15/30] normal/charset: Fix array out-of-bounds formatting unicode for display, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 19/30] net/dns: Don't read past the end of the string we're checking against, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 25/30] fs/f2fs: Do not read past the end of nat journal entries, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 30/30] fs/btrfs: Fix more fuzz issues related to chunks, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 20/30] net/tftp: Prevent a UAF and double-free from a failed seek,
Daniel Kiper <=
- [SECURITY PATCH 18/30] net/dns: Fix double-free addresses on corrupt DNS response, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 17/30] net/netbuff: Block overly large netbuff allocs, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 24/30] net/http: Error out on headers with LF without CR, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 08/30] video/readers/png: Drop greyscale support to fix heap out-of-bounds write, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 14/30] video/readers/jpeg: Block int underflow -> wild pointer write, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 27/30] fs/f2fs: Do not copy file names that are too long, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 29/30] fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 28/30] fs/btrfs: Fix several fuzz issues with invalid dir item sizing, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 06/30] video/readers/png: Abort sooner if a read operation fails, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 21/30] net/tftp: Avoid a trivial UAF, Daniel Kiper, 2022/06/07