libc: implement rtld_get_stack_prot() for real

which makes stack prot correct for non-main threads created by binaries
with statically linked libthr.

Cache result, but do not engage into the full double-checked locking,
since calculation of the return value is idempotent.

PR:	252549
Reported and reviewed by:	emaste
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D28075
This commit is contained in:
Konstantin Belousov 2021-01-10 05:05:42 +02:00
parent 2a4b225146
commit 81b3a0a341

View File

@ -34,7 +34,9 @@ __FBSDID("$FreeBSD$");
/*
* Linkage to services provided by the dynamic linker.
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <machine/atomic.h>
#include <dlfcn.h>
#include <link.h>
#include <stddef.h>
@ -256,8 +258,30 @@ _rtld_addr_phdr(const void *addr __unused,
int
_rtld_get_stack_prot(void)
{
#ifndef IN_LIBDL
unsigned i;
int r;
static int ret;
return (PROT_EXEC | PROT_READ | PROT_WRITE);
r = atomic_load_int(&ret);
if (r != 0)
return (r);
_once(&dl_phdr_info_once, dl_init_phdr_info);
r = PROT_EXEC | PROT_READ | PROT_WRITE;
for (i = 0; i < phdr_info.dlpi_phnum; i++) {
if (phdr_info.dlpi_phdr[i].p_type != PT_GNU_STACK)
continue;
r = PROT_READ | PROT_WRITE;
if ((phdr_info.dlpi_phdr[i].p_flags & PF_X) != 0)
r |= PROT_EXEC;
break;
}
atomic_store_int(&ret, r);
return (r);
#else
return (0);
#endif
}
#pragma weak _rtld_is_dlopened