unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Deny preload of files on NOEXEC mounts
@ 2021-07-19 19:33 Jordan R Abrahams via Libc-alpha
  2021-07-23 18:38 ` Adhemerval Zanella via Libc-alpha
  0 siblings, 1 reply; 16+ messages in thread
From: Jordan R Abrahams via Libc-alpha @ 2021-07-19 19:33 UTC (permalink / raw)
  To: libc-alpha; +Cc: llozano, ajordanr, manojgupta

I'm from Google's ChromeOS Toolchain team, and I have a security
hardening patch to port upstream. I've confirmed with our
security team that this patch can be public, and I'm looking for
review and feedback.

I'm a new contributor, but Google already has a CLA on file for
the FSF, so it should not be an issue. If I'm missing any
contribution info, please do let me know.

Best regards,
~Jordan R Abrahams

-- >8 --
This commit hardens a security flaw in dl-load.c.

At present, 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 get around this NOEXEC requirement by preloading
a malicious shared library.

For example, from shell this can look like:

  $ LD_PRELOAD='/tmp/malicious_lib.so' id
  Hello world from malicious_lib!

Which will work even if /tmp/ is a noexec mount.

A proof of concept of this exploit can be found here at
https://bugs.chromium.org/p/chromium/issues/detail?id=1182687
The bug thread is restricted, but we are willing to add
interested parties with the approval of our security team.

This patch hardens against the exploit by checking the file descriptor
if the file lies in a NOEXEC mount partition via an fstatvfs call.
The error string is set, and we jump to the `lose` cleanup code.

With this patch, the above example instead becomes:

  $ LD_PRELOAD='/tmp/malicious_lib.so' id
  /usr/bin/id: error while loading shared libraries: /tmp/malicious_lib.so: file not located on exec mount
  # <... normal stdout for id ...>

Signed-off-by: Jordan R Abrahams <ajordanr@google.com>
---
 elf/dl-load.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 650e4edc35..81ca08c38f 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>
 
@@ -1572,6 +1573,20 @@ print_search_path (struct r_search_path_elem **list,
     _dl_debug_printf_c ("\t\t(%s)\n", what);
 }
 \f
+/* Check if a the passed in file descriptor points to file on an executable mount.  */
+static int
+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;
+}
+\f
 /* 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
@@ -1650,8 +1665,8 @@ open_verify (const char *name, int fd,
 #endif
 
   if (fd == -1)
-    /* Open the file.  We always open files read-only.  */
-    fd = __open64_nocancel (name, O_RDONLY | O_CLOEXEC);
+      /* Open the file.  We always open files read-only.  */
+      fd = __open64_nocancel (name, O_RDONLY | O_CLOEXEC);
 
   if (fd != -1)
     {
@@ -1667,6 +1682,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.402.g57bb445576-goog


^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2021-09-06 21:49 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-19 19:33 [PATCH] Deny preload of files on NOEXEC mounts Jordan R Abrahams via Libc-alpha
2021-07-23 18:38 ` Adhemerval Zanella via Libc-alpha
2021-07-23 19:22   ` Florian Weimer via Libc-alpha
2021-07-23 20:42     ` Adhemerval Zanella via Libc-alpha
2021-07-23 20:50       ` Florian Weimer via Libc-alpha
2021-07-23 21:17         ` Adhemerval Zanella via Libc-alpha
2021-07-23 21:27           ` Alexander Monakov via Libc-alpha
2021-07-23 22:14             ` Jordan Abrahams via Libc-alpha
2021-08-23 11:29               ` Florian Weimer via Libc-alpha
2021-08-23 19:13                 ` Jordan Abrahams via Libc-alpha
2021-08-23 21:09                 ` Jann Horn via Libc-alpha
2021-09-06 15:10                   ` Florian Weimer via Libc-alpha
2021-09-06 21:48                     ` Mike Frysinger via Libc-alpha
2021-08-23 23:40                 ` Cristian Rodríguez
2021-08-24 12:00                   ` Adhemerval Zanella via Libc-alpha
2021-07-23 23:59             ` Adhemerval Zanella via Libc-alpha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).