Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Dec 2011 16:41:57 -0500
From:      Alexander Kabaev <kabaev@gmail.com>
To:        joris dedieu <joris.dedieu@gmail.com>
Cc:        freebsd-hackers <freebsd-hackers@freebsd.org>
Subject:   Re: rtld and noexec
Message-ID:  <20111202164157.3058d91d@kan.dyndns.org>
In-Reply-To: <CAPd55qAoCttEbV8fkALDaFBc60jigfbu9=Uwa_%2BaECYaHFJpSw@mail.gmail.com>
References:  <CAPd55qAoCttEbV8fkALDaFBc60jigfbu9=Uwa_%2BaECYaHFJpSw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
--Sig_/AnY462gKKJBURQGWFx8zbXI
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: quoted-printable

On Fri, 2 Dec 2011 18:22:57 +0100
joris dedieu <joris.dedieu@gmail.com> wrote:

> Hi,
>=20
> 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).
>=20
> - 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.
>=20
> I think it also makes sens because loading a shared object sounds like
> a kind of "execution".
>=20
> What do you think about this patch and the opportunity to open a PR on
> this subject?
>=20
> Cheers
> Joris
>=20
>=20
> --- 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;
>=20
>      if (strchr(xname, '/') !=3D NULL) {  /* Hard coded pathname */
> +      name =3D NULL;
>         if (xname[0] !=3D '/' && !trust) {
>             _rtld_error("Absolute pathname required for shared object
> \"%s\"", xname);
>             return NULL;
>         }
>         if (refobj !=3D NULL && refobj->z_origin)
> -           return origin_subst(xname, refobj->origin_path);
> +           pathname =3D origin_subst(xname, refobj->origin_path);
>         else
> -           return xstrdup(xname);
> +           pathname =3D xstrdup(xname);
> +    }
> +    else { /* xname is not a path */
> +       if (libmap_disable || (refobj =3D=3D NULL) ||
> +           (name =3D lm_find(refobj->path, xname)) =3D=3D NULL)
> +           name =3D (char *)xname;
> +
> +       dbg(" Searching for \"%s\"", name);
> +
> +       pathname =3D search_library_path(name, ld_library_path);
> +       if (pathname =3D=3D NULL && refobj !=3D NULL)
> +            pathname =3D search_library_path(name, refobj->rpath);
> +       if (pathname =3D=3D NULL)
> +            pathname =3D search_library_path(name, gethints());
> +       if (pathname =3D=3D NULL)
> +            pathname =3D search_library_path(name,
> STANDARD_LIBRARY_PATH);
> +    }
> +
> +    if (pathname !=3D NULL) { /* noexec mountpoint in pathname */
> +       if (statfs(pathname, &mnt) !=3D 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;
> +       }
>      }
>=20
> -    if (libmap_disable || (refobj =3D=3D NULL) ||
> -       (name =3D lm_find(refobj->path, xname)) =3D=3D NULL)
> -       name =3D (char *)xname;
> -
> -    dbg(" Searching for \"%s\"", name);
> -
> -    if ((pathname =3D search_library_path(name, ld_library_path)) !=3D
> NULL ||
> -      (refobj !=3D NULL &&
> -      (pathname =3D search_library_path(name, refobj->rpath)) !=3D NULL)
> ||
> -      (pathname =3D search_library_path(name, gethints())) !=3D NULL ||
> -      (pathname =3D search_library_path(name,
> STANDARD_LIBRARY_PATH)) !=3D NULL)
> -       return pathname;
> -
>      if(refobj !=3D NULL && refobj->path !=3D 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


--=20
Alexander Kabaev

--Sig_/AnY462gKKJBURQGWFx8zbXI
Content-Type: application/pgp-signature; name=signature.asc
Content-Disposition: attachment; filename=signature.asc

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (FreeBSD)

iD8DBQFO2UYqQ6z1jMm+XZYRAiW3AJ9cEXng9NgR8lO/tWakLY8lqLSK4gCeKys0
lDv9CfGN3HZloh/QXW9szNU=
=E56d
-----END PGP SIGNATURE-----

--Sig_/AnY462gKKJBURQGWFx8zbXI--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111202164157.3058d91d>