From 4d6fa591905a904a238a8f4d02359f1c8c170dc0 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Mon, 8 Jul 2024 22:34:29 +0000 Subject: [PATCH] HBSD: Prevent executable superpage mappings Superpage alignment degrades ASLR effectiveness. Prevent superpage alignment for executable code. Signed-off-by: Shawn Webb MFC-to: 14-STABLE MFC-to: 13-STABLE See-Also: https://zolutal.github.io/aslrnt/ See-Also: https://grsecurity.net/toolchain_necromancy_past_mistakes_haunting_aslr --- libexec/rtld-elf/map_object.c | 11 +++++++++-- libexec/rtld-elf/rtld.c | 11 ++++++++++- libexec/rtld-elf/rtld.h | 7 +++++++ sys/kern/imgact_elf.c | 7 +++++++ sys/vm/vm_mmap.c | 12 ++++++++++++ 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index a64dee74934c..7793093fdc59 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -208,8 +208,15 @@ map_object(int fd, const char *path, const struct stat *sb) base_addr = (caddr_t) base_vaddr; base_flags = __getosreldate() >= P_OSREL_MAP_GUARD ? MAP_GUARD : MAP_PRIVATE | MAP_ANON | MAP_NOCORE; - if (npagesizes > 1 && rtld_round_page(segs[0]->p_filesz) >= pagesizes[1]) - base_flags |= MAP_ALIGNED_SUPER; +#ifdef HARDENEDBSD + if (!is_rtld_hardened()) { +#endif + if (npagesizes > 1 && rtld_round_page(segs[0]->p_filesz) + >= pagesizes[1]) + base_flags |= MAP_ALIGNED_SUPER; +#ifdef HARDENEDBSD + } +#endif if (base_vaddr != 0) base_flags |= MAP_FIXED | MAP_EXCL; diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index ba9eb6aa6150..cd74d1b58ab2 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -339,13 +339,22 @@ cache_harden_rtld(void) sz = sizeof(int); err = sysctlbyname("hardening.harden_rtld", &res, &sz, NULL, 0); if (err == 0) { - harden_rtld = res; + if (res < 0) { + harden_rtld = true; + } + harden_rtld = (res > 0); } else { harden_rtld = true; } return (harden_rtld); } + +bool +is_rtld_hardened(void) +{ + return (harden_rtld == true); +} #endif /* diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 9df5b4ec8f59..c2f43f7d0fea 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -414,4 +414,11 @@ void ifunc_init(Elf_Auxinfo[__min_size(AT_COUNT)]); void init_pltgot(Obj_Entry *); void allocate_initial_tls(Obj_Entry *); +/* + * HardenedBSD additions. + */ +#ifdef HARDENEDBSD +bool is_rtld_hardened(void); +#endif + #endif /* } */ diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 56adb0f2c7d7..2265718eb0fb 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1033,13 +1033,20 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * loadable segment to the max supported superpage size. Too * large alignment requests are not useful and are indicators * of corrupted or outright malicious binary. + * + * HardenedBSD note: Enforce smallest unit alignment. Do not permit + * superpage mappings. */ maxalign = PAGE_SIZE; +#ifdef PAX_ASLR + maxsalign = PAGE_SIZE * 1024; +#else maxsalign = PAGE_SIZE * 1024; for (i = MAXPAGESIZES - 1; i > 0; i--) { if (pagesizes[i] > maxsalign) maxsalign = pagesizes[i]; } +#endif mapsz = 0; diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 35f1fcd1dd4c..cdb8172bbf40 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -287,6 +287,18 @@ kern_mmap(struct thread *td, const struct mmap_req *mrp) if (pax_disallow_map32bit_active(td, flags)) return (EPERM); #endif +#if defined(PAX_ASLR) + /* + * Disallow executable superpage mappings. Encourage smaller granularity + * so as not to reduce ASLR effectiveness. + */ + if (pax_aslr_active(p)) { + if (align == MAP_ALIGNED_SUPER && + ((prot & PROT_EXEC) == PROT_EXEC)) { + align = 0; + } + } +#endif /* * Check for illegal addresses. Watch out for address wrap... Note