blob: 10f1c1897ca6156835018a35e2f7ea178f20f78a [file] [log] [blame]
From 3620037c6316d2a715bdd1c745fccfa6ac5b991f Mon Sep 17 00:00:00 2001
From: Jordan R Abrahams <ajordanr@google.com>
Date: Wed, 19 May 2021 22:09:57 +0000
Subject: [PATCH] Deny LD_PRELOAD of files in NOEXEC mount
This commit hardens against a security bug in dl-load.c
Previously, one could dynamically load any shared object files even if
they resided on a NOEXEC mount partition. This introduces an exploit
where an attacker may load shared objects. These shared objects may
then usea ROP attack to conduct arbitrary execution, getting around
the NOEXEC requirement.
This fixes it by checking the file before reading if it lies in
a NOEXEC mount via an fstatvfs call.
---
elf/dl-load.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index e39980fb19..0d15c46e1d 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -29,6 +29,7 @@
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/types.h>
#include <gnu/lib-names.h>
@@ -1541,6 +1542,18 @@ print_search_path (struct r_search_path_elem **list,
_dl_debug_printf_c ("\t\t(%s)\n", what);
}
+/* Check if a the passed in file descriptor points to file on an executable mount. */
+static bool
+check_exec (int fd)
+{
+ struct statvfs buf;
+ int stated = fstatvfs (fd, &buf);
+ if (stated == 0)
+ return !(buf.f_flag & ST_NOEXEC);
+ /* Could not fstat the file. */
+ return false;
+}
+
/* Open a file and verify it is an ELF file for this architecture. We
ignore only ELF files for other architectures. Non-ELF files and
ELF files with different header information cause fatal errors since
@@ -1636,6 +1649,14 @@ open_verify (const char *name, int fd,
__set_errno (0);
fbp->len = 0;
assert (sizeof (fbp->buf) > sizeof (ElfW(Ehdr)));
+
+ /* Before we read in the file, check if the file is in an exec mount */
+ if (__glibc_unlikely (!check_exec(fd)))
+ {
+ errstring = N_("file not located on exec mount");
+ goto call_lose;
+ }
+
/* Read in the header. */
do
{
--
2.32.0.288.g62a8d224e6-goog