From owner-freebsd-hackers@FreeBSD.ORG Fri Dec 2 17:49:50 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 33D48106566C for ; Fri, 2 Dec 2011 17:49:50 +0000 (UTC) (envelope-from joris.dedieu@gmail.com) Received: from mail-qw0-f47.google.com (mail-qw0-f47.google.com [209.85.216.47]) by mx1.freebsd.org (Postfix) with ESMTP id ED2438FC08 for ; Fri, 2 Dec 2011 17:49:49 +0000 (UTC) Received: by qadb17 with SMTP id b17so367711qad.13 for ; Fri, 02 Dec 2011 09:49:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; bh=Z6Is3mPH3CXFP2XHb04HfCQPhp/RdDaJNe7jHnp7gF8=; b=Exu9k/cus657RYs2hhenKVKbv47TGkHK9CyLrQbdOVdHPcdYn8hoJpBYdXLLlw2BaS 4zRqiwCjFhijmDGhbHLZAadvpq6OHFJs+AgPB9pDFEYQfaZRVn0HYlc9I73YvbtBSCHd fN6emmiAAfCMDnv80Z/zQrRRdonmXQ5skaByY= MIME-Version: 1.0 Received: by 10.224.31.69 with SMTP id x5mr3909614qac.8.1322846577567; Fri, 02 Dec 2011 09:22:57 -0800 (PST) Received: by 10.229.226.133 with HTTP; Fri, 2 Dec 2011 09:22:57 -0800 (PST) Date: Fri, 2 Dec 2011 18:22:57 +0100 Message-ID: From: joris dedieu To: freebsd-hackers Content-Type: text/plain; charset=ISO-8859-1 Subject: rtld and noexec X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 02 Dec 2011 17:49:50 -0000 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));