Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Dec 2011 18:22:57 +0100
From:      joris dedieu <joris.dedieu@gmail.com>
To:        freebsd-hackers <freebsd-hackers@freebsd.org>
Subject:   rtld and noexec
Message-ID:  <CAPd55qAoCttEbV8fkALDaFBc60jigfbu9=Uwa_%2BaECYaHFJpSw@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hi,

Here is a patch I use to prevent loading a shared object from a noexec
mountpoint.  It's an easy way, I found, after the last root exploit
((http://seclists.org/fulldisclosure/2011/Nov/452),  to enhance  the
security of my web servers (with /home, /tmp and /var/tmp mounted with
noexec).

- the last ftpd/porftpd  (libc ?) exploit does not work (indirect use
of rtld via nsswitch)
- the previous rtld security issue should have been more difficult to
use in a noexec context.
- It may help to prevent some miscellaneous usage of common softwares
using dlopen like apache or php.

I think it also makes sens because loading a shared object sounds like
a kind of "execution".

What do you think about this patch and the opportunity to open a PR on
this subject?

Cheers
Joris


--- libexec/rtld-elf/rtld.c.orig        2011-12-02 12:09:40.000000000 +0100
+++ libexec/rtld-elf/rtld.c     2011-12-02 13:45:18.000000000 +0100
@@ -1123,32 +1123,50 @@
 {
     char *pathname;
     char *name;
+    struct statfs mnt;

     if (strchr(xname, '/') != NULL) {  /* Hard coded pathname */
+      name = NULL;
        if (xname[0] != '/' && !trust) {
            _rtld_error("Absolute pathname required for shared object \"%s\"",
              xname);
            return NULL;
        }
        if (refobj != NULL && refobj->z_origin)
-           return origin_subst(xname, refobj->origin_path);
+           pathname = origin_subst(xname, refobj->origin_path);
        else
-           return xstrdup(xname);
+           pathname = xstrdup(xname);
+    }
+    else { /* xname is not a path */
+       if (libmap_disable || (refobj == NULL) ||
+           (name = lm_find(refobj->path, xname)) == NULL)
+           name = (char *)xname;
+
+       dbg(" Searching for \"%s\"", name);
+
+       pathname = search_library_path(name, ld_library_path);
+       if (pathname == NULL && refobj != NULL)
+            pathname = search_library_path(name, refobj->rpath);
+       if (pathname == NULL)
+            pathname = search_library_path(name, gethints());
+       if (pathname == NULL)
+            pathname = search_library_path(name, STANDARD_LIBRARY_PATH);
+    }
+
+    if (pathname != NULL) { /* noexec mountpoint in pathname */
+       if (statfs(pathname, &mnt) != 0)
+            free(pathname);
+       else {
+            if (mnt.f_flags & MNT_NOEXEC) {
+              _rtld_error("noexec violation for shared object
\"%s\"", pathname);
+              free(pathname);
+              return NULL;
+            }
+            else
+              return pathname;
+       }
     }

-    if (libmap_disable || (refobj == NULL) ||
-       (name = lm_find(refobj->path, xname)) == NULL)
-       name = (char *)xname;
-
-    dbg(" Searching for \"%s\"", name);
-
-    if ((pathname = search_library_path(name, ld_library_path)) != NULL ||
-      (refobj != NULL &&
-      (pathname = search_library_path(name, refobj->rpath)) != NULL) ||
-      (pathname = search_library_path(name, gethints())) != NULL ||
-      (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
-       return pathname;
-
     if(refobj != NULL && refobj->path != NULL) {
        _rtld_error("Shared object \"%s\" not found, required by \"%s\"",
          name, basename(refobj->path));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAPd55qAoCttEbV8fkALDaFBc60jigfbu9=Uwa_%2BaECYaHFJpSw>