On Fri, 2 Dec 2011 18:22:57 +0100 joris dedieu <joris.ded...@gmail.com> wrote:
> 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)); > _______________________________________________ 1. There is a race using statfs and then loading the file. 2. We already have the check in do_load_object -- Alexander Kabaev
signature.asc
Description: PGP signature