Hello,Our dynamic linker ld_elf.so in map_object.c currently can only handle 2 PT_LOAD segments (one for text and one for data); the kernel elf loader does not have this limitation, it can load multiple PT_LOAD segment. The following patch (from FreeBSD) removes this limitation from the dynamic linker. The reason I made this patch now is that the latest binutils (2.39) for amd64 sets a maxinum pagesize of 2Mb, and when using relocation read only binaries (ld -z relro) this will cause the binaries to have an extra 2Mbytes for alignment. This can be fixed by building binutils to set a separate code segment by default (ld -z separate-code). Binutils then sets the maximum page size to 4Kb. Setting this option creates 4 PT_LOAD segments, two for text (r--, r-x) and two for data (r--, rw-), which also improves security. This is the default for linux on x86 and the patch also makes it the default for NetBSD x86. The patch also adds -z noseparate-code to the kernel builds so that we don't need to fix the boot loaders. I am planning to commit this soon, so please let me know if you hsve any objections.
Best, christos
Index: distrib/sets/lists/comp/md.amd64 =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/md.amd64,v retrieving revision 1.291 diff -u -p -u -r1.291 md.amd64 --- distrib/sets/lists/comp/md.amd64 28 Dec 2022 22:04:05 -0000 1.291 +++ distrib/sets/lists/comp/md.amd64 4 Jan 2023 19:24:50 -0000 @@ -1437,6 +1437,7 @@ ./usr/libdata/ldscripts/elf_i386.x comp-util-bin binutils ./usr/libdata/ldscripts/elf_i386.xbn comp-util-bin binutils ./usr/libdata/ldscripts/elf_i386.xc comp-util-bin binutils +./usr/libdata/ldscripts/elf_i386.xce comp-util-bin binutils ./usr/libdata/ldscripts/elf_i386.xd comp-util-bin binutils ./usr/libdata/ldscripts/elf_i386.xdc comp-util-bin binutils ./usr/libdata/ldscripts/elf_i386.xdw comp-util-bin binutils @@ -1450,6 +1451,7 @@ ./usr/libdata/ldscripts/elf_iamcu.x comp-util-bin binutils ./usr/libdata/ldscripts/elf_iamcu.xbn comp-util-bin binutils ./usr/libdata/ldscripts/elf_iamcu.xc comp-util-bin binutils +./usr/libdata/ldscripts/elf_iamcu.xce comp-util-bin binutils ./usr/libdata/ldscripts/elf_iamcu.xd comp-util-bin binutils ./usr/libdata/ldscripts/elf_iamcu.xdc comp-util-bin binutils ./usr/libdata/ldscripts/elf_iamcu.xdw comp-util-bin binutils @@ -1463,6 +1465,7 @@ ./usr/libdata/ldscripts/elf_k1om.x comp-util-bin binutils=234 ./usr/libdata/ldscripts/elf_k1om.xbn comp-util-bin binutils=234 ./usr/libdata/ldscripts/elf_k1om.xc comp-util-bin binutils=234 +./usr/libdata/ldscripts/elf_k1om.xc comp-util-bin binutils=234 ./usr/libdata/ldscripts/elf_k1om.xd comp-util-bin binutils=234 ./usr/libdata/ldscripts/elf_k1om.xdc comp-util-bin binutils=234 ./usr/libdata/ldscripts/elf_k1om.xdw comp-util-bin binutils=234 @@ -1489,6 +1492,7 @@ ./usr/libdata/ldscripts/elf_x86_64.x comp-util-bin binutils ./usr/libdata/ldscripts/elf_x86_64.xbn comp-util-bin binutils ./usr/libdata/ldscripts/elf_x86_64.xc comp-util-bin binutils +./usr/libdata/ldscripts/elf_x86_64.xce comp-util-bin binutils ./usr/libdata/ldscripts/elf_x86_64.xd comp-util-bin binutils ./usr/libdata/ldscripts/elf_x86_64.xdc comp-util-bin binutils ./usr/libdata/ldscripts/elf_x86_64.xdw comp-util-bin binutils Index: external/gpl3/binutils/dist/bfd/configure =================================================================== RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/configure,v retrieving revision 1.17 diff -u -p -u -r1.17 configure --- external/gpl3/binutils/dist/bfd/configure 24 Dec 2022 20:17:04 -0000 1.17 +++ external/gpl3/binutils/dist/bfd/configure 4 Jan 2023 19:24:50 -0000 @@ -11977,9 +11977,9 @@ if test "${enable_separate_code+set}" = esac fi -# Enable -z separate-code by default for Linux/x86. +# Enable -z separate-code by default for Linux/x86 and NetBSD/x86 case "${target}" in -i[3-7]86-*-linux-* | x86_64-*-linux-*) +i[3-7]86-*-linux-* | x86_64-*-linux-* | i[3-7]86-*-netbsd* | x86_64-*-netbsd*) if test ${ac_default_ld_z_separate_code} = unset; then ac_default_ld_z_separate_code=1 fi Index: external/gpl3/binutils/dist/bfd/configure.ac =================================================================== RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/configure.ac,v retrieving revision 1.10 diff -u -p -u -r1.10 configure.ac --- external/gpl3/binutils/dist/bfd/configure.ac 24 Dec 2022 20:17:04 -0000 1.10 +++ external/gpl3/binutils/dist/bfd/configure.ac 4 Jan 2023 19:24:50 -0000 @@ -136,10 +136,10 @@ AC_ARG_ENABLE(separate-code, yes) ac_default_ld_z_separate_code=1 ;; no) ac_default_ld_z_separate_code=0 ;; esac]) -# Enable -z separate-code by default for Linux/x86. +# Enable -z separate-code by default for Linux/x86 and NetBSD/x86 changequote(,)dnl case "${target}" in -i[3-7]86-*-linux-* | x86_64-*-linux-*) +i[3-7]86-*-linux-* | x86_64-*-linux-* | i[3-7]86-*-netbsd | x86_64-*-netbsd* ) changequote([,])dnl if test ${ac_default_ld_z_separate_code} = unset; then ac_default_ld_z_separate_code=1 Index: external/gpl3/binutils/dist/ld/configure.tgt =================================================================== RCS file: /cvsroot/src/external/gpl3/binutils/dist/ld/configure.tgt,v retrieving revision 1.38 diff -u -p -u -r1.38 configure.tgt --- external/gpl3/binutils/dist/ld/configure.tgt 24 Dec 2022 20:17:07 -0000 1.38 +++ external/gpl3/binutils/dist/ld/configure.tgt 4 Jan 2023 19:24:50 -0000 @@ -1219,7 +1219,7 @@ esac # Enable -z separate-code and --warn-textrel by default for Linux/x86. case "${target}" in -i[3-7]86-*-linux-* | x86_64-*-linux-*) +i[3-7]86-*-linux-* | x86_64-*-linux-* | i[3-7]86-*-netbsd* | x86_64-*-netbsd*) if test ${ac_default_ld_z_separate_code} = unset; then ac_default_ld_z_separate_code=1 fi Index: external/gpl3/binutils/lib/libbfd/arch/x86_64/config.h =================================================================== RCS file: /cvsroot/src/external/gpl3/binutils/lib/libbfd/arch/x86_64/config.h,v retrieving revision 1.10 diff -u -p -u -r1.10 config.h --- external/gpl3/binutils/lib/libbfd/arch/x86_64/config.h 24 Dec 2022 20:17:08 -0000 1.10 +++ external/gpl3/binutils/lib/libbfd/arch/x86_64/config.h 4 Jan 2023 19:24:50 -0000 @@ -1,5 +1,5 @@ /* This file is automatically generated. DO NOT EDIT! */ -/* Generated from: NetBSD: mknative-binutils,v 1.13 2020/04/04 01:34:53 christos Exp */ +/* Generated from: NetBSD: mknative-binutils,v 1.14 2022/12/24 20:17:46 christos Exp */ /* Generated from: NetBSD: mknative.common,v 1.16 2018/04/15 15:13:37 christos Exp */ /* config.h. Generated from config.in by configure. */ @@ -17,7 +17,7 @@ /* Define to 1 if you want to enable -z separate-code in ELF linker by default. */ -#define DEFAULT_LD_Z_SEPARATE_CODE 0 +#define DEFAULT_LD_Z_SEPARATE_CODE 1 /* Define if you want run-time sanity checks. */ /* #undef ENABLE_CHECKING */ Index: external/gpl3/binutils/usr.bin/ld/Makefile =================================================================== RCS file: /cvsroot/src/external/gpl3/binutils/usr.bin/ld/Makefile,v retrieving revision 1.35 diff -u -p -u -r1.35 Makefile --- external/gpl3/binutils/usr.bin/ld/Makefile 24 Dec 2022 20:17:10 -0000 1.35 +++ external/gpl3/binutils/usr.bin/ld/Makefile 4 Jan 2023 19:24:50 -0000 @@ -87,6 +87,13 @@ FILES+= ${f}.${e} . endif . endfor . endif +. if ${BINUTILS_MACHINE_ARCH} == "x86_64" || ${BINUTILS_MACHINE_ARCH} == "i386" +. for e in xce +. if exists(ldscripts/${f}.${e}) +FILES+= ${f}.${e} +. endif +. endfor +. endif .endfor .include <bsd.prog.mk> Index: external/gpl3/binutils/usr.bin/ld/arch/x86_64/config.h =================================================================== RCS file: /cvsroot/src/external/gpl3/binutils/usr.bin/ld/arch/x86_64/config.h,v retrieving revision 1.11 diff -u -p -u -r1.11 config.h --- external/gpl3/binutils/usr.bin/ld/arch/x86_64/config.h 24 Dec 2022 20:17:10 -0000 1.11 +++ external/gpl3/binutils/usr.bin/ld/arch/x86_64/config.h 4 Jan 2023 19:24:50 -0000 @@ -1,5 +1,5 @@ /* This file is automatically generated. DO NOT EDIT! */ -/* Generated from: NetBSD: mknative-binutils,v 1.13 2020/04/04 01:34:53 christos Exp */ +/* Generated from: NetBSD: mknative-binutils,v 1.14 2022/12/24 20:17:46 christos Exp */ /* Generated from: NetBSD: mknative.common,v 1.16 2018/04/15 15:13:37 christos Exp */ /* config.h. Generated from config.in by configure. */ @@ -44,7 +44,7 @@ /* Define to 1 if you want to enable -z separate-code in ELF linker by default. */ -#define DEFAULT_LD_Z_SEPARATE_CODE 0 +#define DEFAULT_LD_Z_SEPARATE_CODE 1 /* Define to 1 if you want to set DT_RUNPATH instead of DT_RPATH by default. */ Index: libexec/ld.elf_so/map_object.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/map_object.c,v retrieving revision 1.62 diff -u -p -u -r1.62 map_object.c --- libexec/ld.elf_so/map_object.c 30 Mar 2022 08:26:45 -0000 1.62 +++ libexec/ld.elf_so/map_object.c 4 Jan 2023 19:24:50 -0000 @@ -49,7 +49,8 @@ __RCSID("$NetBSD: map_object.c,v 1.62 20 #include "debug.h" #include "rtld.h" -static int protflags(int); /* Elf flags -> mmap protection */ +static int convert_prot(int); /* Elf flags -> mmap protection */ +static int convert_flags(int); /* Elf flags -> mmap flags */ #define EA_UNDEF (~(Elf_Addr)0) @@ -69,35 +70,35 @@ _rtld_map_object(const char *path, int f #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) Elf_Phdr *phtls; #endif - size_t phsize; Elf_Phdr *phlimit; - Elf_Phdr *segs[2]; + Elf_Phdr **segs = NULL; int nsegs; caddr_t mapbase = MAP_FAILED; size_t mapsize = 0; int mapflags; - Elf_Off base_offset; Elf_Addr base_alignment; Elf_Addr base_vaddr; Elf_Addr base_vlimit; Elf_Addr text_vlimit; - int text_flags; + Elf_Addr text_end; void *base_addr; Elf_Off data_offset; Elf_Addr data_vaddr; Elf_Addr data_vlimit; int data_flags; + int data_prot; caddr_t data_addr; + Elf_Addr bss_vaddr; + Elf_Addr bss_vlimit; + caddr_t bss_addr; #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) Elf_Addr tls_vaddr = 0; /* Noise GCC */ #endif Elf_Addr phdr_vaddr; - size_t phdr_memsz; - caddr_t gap_addr; - size_t gap_size; int i; #ifdef RTLD_LOADER Elf_Addr clear_vaddr; + caddr_t clear_page; caddr_t clear_addr; size_t nclear; #endif @@ -105,6 +106,9 @@ _rtld_map_object(const char *path, int f Elf_Addr relro_page; size_t relro_size; #endif +#ifdef notyet + int stack_flags; +#endif if (sb != NULL && sb->st_size < (off_t)sizeof (Elf_Ehdr)) { _rtld_error("%s: not ELF file (too short)", path); @@ -124,34 +128,34 @@ _rtld_map_object(const char *path, int f obj->ehdr = ehdr; if (ehdr == MAP_FAILED) { _rtld_error("%s: read error: %s", path, xstrerror(errno)); - goto bad; + goto error; } /* Make sure the file is valid */ if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0) { _rtld_error("%s: not ELF file (magic number bad)", path); - goto bad; + goto error; } if (ehdr->e_ident[EI_CLASS] != ELFCLASS) { _rtld_error("%s: invalid ELF class %x; expected %x", path, ehdr->e_ident[EI_CLASS], ELFCLASS); - goto bad; + goto error; } /* Elf_e_ident includes class */ if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_version != EV_CURRENT || ehdr->e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) { _rtld_error("%s: unsupported file version", path); - goto bad; + goto error; } if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) { _rtld_error("%s: unsupported file type", path); - goto bad; + goto error; } switch (ehdr->e_machine) { ELFDEFNNAME(MACHDEP_ID_CASES) default: _rtld_error("%s: unsupported machine", path); - goto bad; + goto error; } /* @@ -173,16 +177,22 @@ _rtld_map_object(const char *path, int f #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) phtls = NULL; #endif - phsize = ehdr->e_phnum * sizeof(phdr[0]); obj->phdr = NULL; #ifdef GNU_RELRO relro_page = 0; relro_size = 0; #endif phdr_vaddr = EA_UNDEF; - phdr_memsz = 0; phlimit = phdr + ehdr->e_phnum; - nsegs = 0; + segs = xmalloc(sizeof(segs[0]) * ehdr->e_phnum); + if (segs == NULL) { + _rtld_error("No memory for segs"); + goto error; + } +#ifdef notyet + stack_flags = PF_R | PF_W; +#endif + nsegs = -1; while (phdr < phlimit) { switch (phdr->p_type) { case PT_INTERP: @@ -191,21 +201,37 @@ _rtld_map_object(const char *path, int f break; case PT_LOAD: - if (nsegs < 2) - segs[nsegs] = phdr; - ++nsegs; + segs[++nsegs] = phdr; + if ((segs[nsegs]->p_align & (_rtld_pagesz - 1)) != 0) { + _rtld_error( + "%s: PT_LOAD segment %d not page-aligned", + path, nsegs); + goto error; + } + if ((segs[nsegs]->p_flags & PF_X) == PF_X) { + text_end = MAX(text_end, + round_up(segs[nsegs]->p_vaddr + + segs[nsegs]->p_memsz)); + } - dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_LOAD", + dbg(("%s: %s %p phsize %" PRImemsz, obj->path, + "PT_LOAD", (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz)); break; case PT_PHDR: phdr_vaddr = phdr->p_vaddr; - phdr_memsz = phdr->p_memsz; - dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_PHDR", + dbg(("%s: %s %p phsize %" PRImemsz, obj->path, + "PT_PHDR", (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz)); break; +#ifdef notyet + case PT_GNU_STACK: + stack_flags = phdr->p_flags; + break; +#endif + #ifdef GNU_RELRO case PT_GNU_RELRO: relro_page = phdr->p_vaddr; @@ -215,7 +241,8 @@ _rtld_map_object(const char *path, int f case PT_DYNAMIC: obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr; - dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_DYNAMIC", + dbg(("%s: %s %p phsize %" PRImemsz, obj->path, + "PT_DYNAMIC", (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz)); break; @@ -240,12 +267,7 @@ _rtld_map_object(const char *path, int f obj->entry = (void *)(uintptr_t)ehdr->e_entry; if (!obj->dynamic) { _rtld_error("%s: not dynamically linked", path); - goto bad; - } - if (nsegs != 2) { - _rtld_error("%s: wrong number of segments (%d != 2)", path, - nsegs); - goto bad; + goto error; } /* @@ -261,17 +283,15 @@ _rtld_map_object(const char *path, int f */ base_alignment = segs[0]->p_align; - base_offset = round_down(segs[0]->p_offset); base_vaddr = round_down(segs[0]->p_vaddr); - base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz); + base_vlimit = round_up(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz); text_vlimit = round_up(segs[0]->p_vaddr + segs[0]->p_memsz); - text_flags = protflags(segs[0]->p_flags); - data_offset = round_down(segs[1]->p_offset); - data_vaddr = round_down(segs[1]->p_vaddr); - data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz); - data_flags = protflags(segs[1]->p_flags); + data_offset = round_down(segs[nsegs]->p_offset); + data_vaddr = round_down(segs[nsegs]->p_vaddr); + data_vlimit = round_up(segs[nsegs]->p_vaddr + segs[nsegs]->p_filesz); + data_flags = convert_prot(segs[nsegs]->p_flags); #ifdef RTLD_LOADER - clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz; + clear_vaddr = segs[nsegs]->p_vaddr + segs[nsegs]->p_filesz; #endif obj->textsize = text_vlimit - base_vaddr; @@ -289,54 +309,15 @@ _rtld_map_object(const char *path, int f } #endif - obj->phdr_loaded = false; - for (i = 0; i < nsegs; i++) { - if (phdr_vaddr != EA_UNDEF && - segs[i]->p_vaddr <= phdr_vaddr && - segs[i]->p_memsz >= phdr_memsz) { - obj->phdr_loaded = true; - break; - } - if (segs[i]->p_offset <= ehdr->e_phoff && - segs[i]->p_memsz >= phsize) { - phdr_vaddr = segs[i]->p_vaddr + ehdr->e_phoff; - phdr_memsz = phsize; - obj->phdr_loaded = true; - break; - } - } - if (obj->phdr_loaded) { - obj->phdr = (void *)(uintptr_t)phdr_vaddr; - obj->phsize = phdr_memsz; - } else { - Elf_Phdr *buf; - buf = xmalloc(phsize); - if (buf == NULL) { - _rtld_error("%s: cannot allocate program header", path); - goto bad; - } - memcpy(buf, phdr, phsize); - obj->phdr = buf; - obj->phsize = phsize; - } - dbg(("%s: phdr %p phsize %zu (%s)", obj->path, obj->phdr, obj->phsize, - obj->phdr_loaded ? "loaded" : "allocated")); - - /* Unmap header if it overlaps the first load section. */ - if (base_offset < _rtld_pagesz) { - munmap(ehdr, _rtld_pagesz); - obj->ehdr = MAP_FAILED; - } - /* * Calculate log2 of the base section alignment. */ - mapflags = 0; + mapflags = MAP_PRIVATE | MAP_ANON; if (base_alignment > _rtld_pagesz) { unsigned int log2 = 0; for (; base_alignment > 1; base_alignment >>= 1) log2++; - mapflags = MAP_ALIGNED(log2); + mapflags |= MAP_ALIGNED(log2); } base_addr = NULL; @@ -347,56 +328,89 @@ _rtld_map_object(const char *path, int f } #endif mapsize = base_vlimit - base_vaddr; - mapbase = mmap(base_addr, mapsize, text_flags, - mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset); + mapbase = mmap(base_addr, mapsize, PROT_NONE, mapflags, -1, 0); if (mapbase == MAP_FAILED) { _rtld_error("mmap of entire address space failed: %s", xstrerror(errno)); - goto bad; + goto error; } #ifdef RTLD_LOADER if (!obj->isdynamic && mapbase != base_addr) { _rtld_error("mmap of executable at correct address failed"); - goto bad; + goto error; } #endif - /* Overlay the data segment onto the proper region. */ - data_addr = mapbase + (data_vaddr - base_vaddr); - if (mmap(data_addr, data_vlimit - data_vaddr, data_flags, - MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) == - MAP_FAILED) { - _rtld_error("mmap of data failed: %s", xstrerror(errno)); - goto bad; - } - - /* Overlay the bss segment onto the proper region. */ - if (base_vlimit > data_vlimit) { - if (mmap(mapbase + data_vlimit - base_vaddr, - base_vlimit - data_vlimit, data_flags, - MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) == MAP_FAILED) { - _rtld_error("mmap of bss failed: %s", xstrerror(errno)); - goto bad; + for (i = 0; i <= nsegs; i++) { + /* Overlay the segment onto the proper region. */ + data_offset = round_down(segs[i]->p_offset); + data_vaddr = round_down(segs[i]->p_vaddr); + data_vlimit = round_up(segs[i]->p_vaddr + + segs[i]->p_filesz); + data_addr = mapbase + (data_vaddr - base_vaddr); + data_prot = convert_prot(segs[i]->p_flags); + data_flags = convert_flags(segs[i]->p_flags) | MAP_FIXED; + if (data_vlimit != data_vaddr && + mmap(data_addr, data_vlimit - data_vaddr, data_prot, + data_flags, fd, data_offset) == MAP_FAILED) { + _rtld_error("%s: mmap of data failed: %s", path, + xstrerror(errno)); + goto error; } - } - - /* Unmap the gap between the text and data. */ - gap_addr = mapbase + round_up(text_vlimit - base_vaddr); - gap_size = data_addr - gap_addr; - if (gap_size != 0 && mprotect(gap_addr, gap_size, PROT_NONE) == -1) { - _rtld_error("mprotect of text -> data gap failed: %s", - xstrerror(errno)); - goto bad; - } + /* Do BSS setup */ + if (segs[i]->p_filesz != segs[i]->p_memsz) { #ifdef RTLD_LOADER - /* Clear any BSS in the last page of the data segment. */ - clear_addr = mapbase + (clear_vaddr - base_vaddr); - if ((nclear = data_vlimit - clear_vaddr) > 0) - memset(clear_addr, 0, nclear); + /* Clear any BSS in the last page of the segment. */ + clear_vaddr = segs[i]->p_vaddr + segs[i]->p_filesz; + clear_addr = mapbase + (clear_vaddr - base_vaddr); + clear_page = mapbase + (round_down(clear_vaddr) + - base_vaddr); + + if ((nclear = data_vlimit - clear_vaddr) > 0) { + /* Make sure the end of the segment is writable + */ + if ((data_prot & PROT_WRITE) == 0 && -1 == + mprotect(clear_page, _rtld_pagesz, + data_prot|PROT_WRITE)) { + _rtld_error("%s: mprotect failed: %s", + path, xstrerror(errno)); + goto error; + } + + memset(clear_addr, 0, nclear); + + /* Reset the data protection back */ + if ((data_prot & PROT_WRITE) == 0) + mprotect(clear_page, _rtld_pagesz, + data_prot); + } +#endif + + /* Overlay the BSS segment onto the proper region. */ + bss_vaddr = data_vlimit; + bss_vlimit = round_up(segs[i]->p_vaddr + + segs[i]->p_memsz); + bss_addr = mapbase + (bss_vaddr - base_vaddr); + if (bss_vlimit > bss_vaddr) { + /* There is something to do */ + if (mmap(bss_addr, bss_vlimit - bss_vaddr, + data_prot, data_flags | MAP_ANON, -1, 0) + == MAP_FAILED) { + _rtld_error( + "%s: mmap of bss failed: %s", + path, xstrerror(errno)); + goto error; + } + } + } - /* Non-file portion of BSS mapped above. */ -#endif + if (phdr_vaddr == 0 && data_offset <= ehdr->e_phoff && + (data_vlimit - data_vaddr + data_offset) >= + (ehdr->e_phoff + ehdr->e_phnum * sizeof (Elf_Phdr))) { + phdr_vaddr = data_vaddr + ehdr->e_phoff - data_offset; + } + } #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) if (phtls != NULL) @@ -425,15 +439,17 @@ _rtld_map_object(const char *path, int f if (obj->exidx_start) obj->exidx_start = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->exidx_start); #endif + xfree(segs); return obj; -bad: - if (obj->ehdr != MAP_FAILED) - munmap(obj->ehdr, _rtld_pagesz); +error: if (mapbase != MAP_FAILED) munmap(mapbase, mapsize); + if (obj->ehdr != MAP_FAILED) + munmap(obj->ehdr, _rtld_pagesz); _rtld_obj_free(obj); + xfree(segs); return NULL; } @@ -487,7 +503,7 @@ _rtld_obj_new(void) * flags for MMAP. */ static int -protflags(int elfflags) +convert_prot(int elfflags) { int prot = 0; @@ -501,3 +517,19 @@ protflags(int elfflags) prot |= PROT_EXEC; return prot; } + +static int +convert_flags(int elfflags __unused) +{ + int flags = MAP_PRIVATE; /* All mappings are private */ + +#ifdef MAP_NOCORE + /* + * Readonly mappings are marked "MAP_NOCORE", because they can be + * reconstructed by a debugger. + */ + if (!(elfflags & PF_W)) + flags |= MAP_NOCORE; +#endif + return flags; +} Index: share/mk/bsd.sys.mk =================================================================== RCS file: /cvsroot/src/share/mk/bsd.sys.mk,v retrieving revision 1.310 diff -u -p -u -r1.310 bsd.sys.mk --- share/mk/bsd.sys.mk 30 Dec 2022 02:01:42 -0000 1.310 +++ share/mk/bsd.sys.mk 4 Jan 2023 19:24:50 -0000 @@ -138,10 +138,7 @@ CFLAGS+= -Wno-maybe-uninitialized .endif .if ${MKRELRO:Uno} != "no" -# XXX Workaround for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1014301 -# Set manually the maxpagesize to 4096 which is ok for now since we only -# support relro by default on x86 and aarch64 -LDFLAGS+= -Wl,-z,relro -Wl,-z,max-page-size=4096 +LDFLAGS+= -Wl,-z,relro .endif .if ${MKRELRO:Uno} == "full" && ${NOFULLRELRO:Uno} == "no" Index: doc/HACKS =================================================================== RCS file: /cvsroot/src/doc/HACKS,v retrieving revision 1.233 diff -u -p -u -r1.233 HACKS --- doc/HACKS 30 Dec 2022 02:05:38 -0000 1.233 +++ doc/HACKS 4 Jan 2023 19:24:50 -0000 @@ -1072,17 +1072,3 @@ descr clang 13.0.0 miscompiles copy{in,out}() with -O[12]. As a result, kernel cannot execute /sbin/init. kcah - -hack Clamp max-page-size in ld to 4K when using relro to avoid 2M binary - bloat -cdate Thu Dec 29 21:02:43 EST 2022 -who christos -port x86, aarch64 -file share/mk/bsd.sys.mk: 1.309 -pr 57147 -descr - binutils 2.38+ fix for - https://sourceware.org/bugzilla/show_bug.cgi?id=28824 - results in a 2M binary bloat when using relro because of the relro - segment alignment. There is no upstream fix yet. -kcah Index: sys/arch/amd64/conf/Makefile.amd64 =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/conf/Makefile.amd64,v retrieving revision 1.85 diff -u -p -u -r1.85 Makefile.amd64 --- sys/arch/amd64/conf/Makefile.amd64 11 May 2020 15:15:15 -0000 1.85 +++ sys/arch/amd64/conf/Makefile.amd64 4 Jan 2023 19:24:50 -0000 @@ -109,6 +109,7 @@ EXTRA_LINKFLAGS= -z max-page-size=0x2000 KERNLDSCRIPT?= ${AMD64}/conf/kern.ldscript .endif LINKFLAGS_NORMAL= -X +EXTRA_LINKFLAGS+= -z noseparate-code ## ## (6) port specific target dependencies Index: sys/arch/i386/conf/Makefile.i386 =================================================================== RCS file: /cvsroot/src/sys/arch/i386/conf/Makefile.i386,v retrieving revision 1.196 diff -u -p -u -r1.196 Makefile.i386 --- sys/arch/i386/conf/Makefile.i386 11 May 2020 15:15:15 -0000 1.196 +++ sys/arch/i386/conf/Makefile.i386 4 Jan 2023 19:24:50 -0000 @@ -45,6 +45,7 @@ CFLAGS+= ${${ACTIVE_CC} == "gcc" :? -min CFLAGS+= ${${ACTIVE_CC} == "gcc" :? -mindirect-branch-register :} .endif EXTRA_INCLUDES= -I$S/external/mit/xen-include-public/dist/ +EXTRA_LINKFLAGS= -z noseparate-code ## ## (3) libkern and compat
Attachment:
signature.asc
Description: OpenPGP digital signature