summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDaniel Axtens <dja@axtens.net>2021-09-20 01:12:24 +1000
committerJulian Andres Klode <julian.klode@canonical.com>2022-06-08 12:41:03 +0200
commite7573be61b3cf005cdf0a068652153437daca4b3 (patch)
tree936e8da9337a490eb462101dccfd3a1b2657a785 /include
parent968febf3a4de5df0f91cc13bc6b6053fc22575e1 (diff)
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>
Diffstat (limited to 'include')
-rw-r--r--include/grub/net.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/grub/net.h b/include/grub/net.h
index cbcae79b1..8d71ca6cc 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);