HBSD: Harden LD_PRELOAD

Add a new sysctl node, hardening.harden_rtld, that will drive the RTLD's
hardening logic. Hardening LD_PRELOAD is a good first step towards a
generalized RTLD hardening approach. LD_PRELOAD is a common code
injection technique.

Signed-off-by:	Shawn Webb <shawn.webb@hardenedbsd.org>
MFC-to:		13-STABLE
This commit is contained in:
Shawn Webb 2022-06-10 20:51:15 -04:00
parent fbfea2c1d2
commit e9e9c42998
3 changed files with 38 additions and 0 deletions

View File

@ -204,6 +204,9 @@ static void rtld_fill_dl_phdr_info(const Obj_Entry *obj,
static uint32_t gnu_hash(const char *);
static bool matched_symbol(SymLook *, const Obj_Entry *, Sym_Match_Result *,
const unsigned long);
#ifdef HARDENEDBSD
static bool cache_harden_rtld(void);
#endif
void r_debug_state(struct r_debug *, struct link_map *) __noinline __exported;
void _r_debug_postinit(struct link_map *) __noinline __exported;
@ -242,6 +245,7 @@ static unsigned int obj_loads; /* Number of loads of objects (gen count) */
#ifdef HARDENEDBSD
static Elf_Word pax_flags = 0; /* PaX / HardenedBSD flags */
static bool harden_rtld = true;
#endif
static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */
@ -327,6 +331,23 @@ const char *ld_env_prefix = LD_;
static void (*rtld_exit_ptr)(void);
static bool
cache_harden_rtld(void)
{
int err, res;
size_t sz;
sz = sizeof(int);
err = sysctlbyname("hardening.harden_rtld", &res, &sz, NULL, 0);
if (err == 0) {
harden_rtld = res;
} else {
harden_rtld = true;
}
return (harden_rtld);
}
/*
* Fill in a DoneList with an allocation large enough to hold all of
* the currently-loaded objects. Keep this as a macro since it calls
@ -614,6 +635,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
pax_flags = aux_info[AT_PAXFLAGS]->a_un.a_val;
aux_info[AT_PAXFLAGS]->a_un.a_val = 0;
}
cache_harden_rtld();
#endif
trust = !issetugid();
@ -2728,6 +2751,10 @@ load_preload_objects(const char *penv, bool isfd)
if (penv == NULL)
return (0);
if (harden_rtld) {
return (0);
}
p = psave = xstrdup(penv);
p += strspn(p, delim);
while (*p != '\0') {

View File

@ -65,12 +65,14 @@ static int pax_randomize_pids_global = PAX_FEATURE_SIMPLE_ENABLED;
static int pax_init_hardening_global = PAX_FEATURE_SIMPLE_ENABLED;
static int pax_insecure_kmod_global = PAX_FEATURE_SIMPLE_DISABLED;
static int pax_tpe_global = PAX_FEATURE_OPTIN;
static int harden_rtld_global = PAX_FEATURE_SIMPLE_ENABLED;
#else
static int pax_procfs_harden_global = PAX_FEATURE_SIMPLE_DISABLED;
static int pax_randomize_pids_global = PAX_FEATURE_SIMPLE_DISABLED;
static int pax_init_hardening_global = PAX_FEATURE_SIMPLE_DISABLED;
static int pax_insecure_kmod_global = PAX_FEATURE_SIMPLE_ENABLED;
static int pax_tpe_global = PAX_FEATURE_OPTIN;
static int harden_rtld_global = PAX_FEATURE_SIMPLE_DISABLED;
#endif
static int pax_tpe_gid = 0;
@ -86,6 +88,7 @@ TUNABLE_INT("hardening.tpe.gid", &pax_tpe_gid);
TUNABLE_INT("hardening.tpe.negate", &pax_tpe_negate);
TUNABLE_INT("hardening.tpe.all", &pax_tpe_all);
TUNABLE_INT("hardening.tpe.root_owned", &pax_tpe_root_owned);
TUNABLE_INT("hardening.harden_rtld", &harden_rtld_global);
#ifdef PAX_SYSCTLS
SYSCTL_DECL(_hardening_pax);
@ -97,6 +100,10 @@ SYSCTL_HBSD_2STATE(pax_procfs_harden_global, pr_hbsd.hardening.procfs_harden,
SYSCTL_HBSD_2STATE_GLOBAL(pax_insecure_kmod_global, _hardening, insecure_kmod,
CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_SECURE,
"Enable loading of inecure kernel modules");
SYSCTL_HBSD_2STATE(harden_rtld_global, pr_hbsd.hardening.harden_rtld,
_hardening, harden_rtld,
CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_SECURE,
"Harden RTLD");
SYSCTL_DECL(_hardening_pax);
SYSCTL_NODE(_hardening_pax, OID_AUTO, tpe, CTLFLAG_RD, 0,
@ -193,6 +200,7 @@ pax_hardening_init_prison(struct prison *pr, struct vfsoptlist *opts)
pr->pr_hbsd.hardening.procfs_harden =
pax_procfs_harden_global;
pr->pr_hbsd.hardening.tpe = pax_tpe_global;
pr->pr_hbsd.hardening.harden_rtld = harden_rtld_global;
pr->pr_allow &= ~(PR_ALLOW_UNPRIV_DEBUG);
} else {
KASSERT(pr->pr_parent != NULL,
@ -202,6 +210,8 @@ pax_hardening_init_prison(struct prison *pr, struct vfsoptlist *opts)
pr->pr_hbsd.hardening.procfs_harden =
pr_p->pr_hbsd.hardening.procfs_harden;
pr->pr_hbsd.hardening.tpe = pr_p->pr_hbsd.hardening.tpe;
pr->pr_hbsd.hardening.harden_rtld =
pr_p->pr_hbsd.hardening.harden_rtld;
#if 0
error = pax_handle_prison_param(opts, "hardening.procfs_harden",
&pr->pr_hbsd.hardening.procfs_harden);

View File

@ -64,6 +64,7 @@ struct hbsd_features {
int tpe_all;
int tpe_negate;
int tpe_root_owned;
pax_state_t harden_rtld;
} hardening;
struct hbsd_log {
pax_state_t log; /* (p) Per-jail logging status */