rtld and noexec
Alexander Kabaev
kabaev at gmail.com
Fri Dec 2 22:03:55 UTC 2011
On Fri, 2 Dec 2011 18:22:57 +0100
joris dedieu <joris.dedieu at 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 188 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20111202/7972a7e5/signature.pgp
More information about the freebsd-hackers
mailing list