[PATCH v7 2/4] elf: Do not change stack permission on dlopen/dlmopen

Stafford Horne shorne@gmail.com
Mon Jan 6 09:47:29 GMT 2025


On Thu, Dec 26, 2024 at 02:57:43PM -0300, Adhemerval Zanella wrote:
> If some shared library loaded with dlopen/dlmopen requires an executable
> stack, either implicitly because of a missing GNU_STACK ELF header
> (where the ABI default flags implies in the executable bit) or explicitly
> because of the executable bit from GNU_STACK; the loader will try to set
> the both the main thread and all thread stacks (from the pthread cache)
> as executable.
> 
> Besides the issue where any __nptl_change_stack_perm failure does not
> undo the previous executable transition (meaning that if the library
> fails to load, there can be thread stacks with executable stacks), this
> behavior was used on recent CVE [1] as a vector for RCE.
> 
> This patch changes that if a shared library requires an executable
> stack, and the current stack is not executable, dlopen fails.  The
> change is done only for dynamically loaded modules, if the program
> or any dependency requires an executable stack, the loader will still
> change the main thread before program execution and any thread created
> with default stack configuration.

Note,

This causes an issue on OpenRISC which I found when running machine testing
for 2.41.  I bisected the issue to this commit.

Many tests are failing with (example nptl/tst-robust1):

    libgcc_s.so.1 must be installed for pthread_cancel to work

    make[2]: Leaving directory '/home/shorne/work/gnu-toolchain/glibc/nptl'
    FAIL: nptl/tst-robust1
    original exit status 1
    Didn't expect signal from child: got `Aborted'
    make[1]: Leaving directory '/home/shorne/work/gnu-toolchain/glibc'

I do have libgcc_s.so.1, but dlopen seems to be failing due to having an
executable stack header.

    $ readelf -l /home/shorne/work/gnu-toolchain/build-glibc/nptl/tst-robust1

    Elf file type is DYN (Position-Independent Executable file)
    Entry point 0x185c
    There are 9 program headers, starting at offset 52

    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      PHDR           0x000034 0x00000034 0x00000034 0x00120 0x00120 R   0x4
      INTERP         0x0042ac 0x000042ac 0x000042ac 0x00018 0x00018 R   0x1
	  [Requesting program interpreter: /lib/ld-linux-or1k.so.1]
      LOAD           0x000000 0x00000000 0x00000000 0x0464c 0x0464c R E 0x2000
      LOAD           0x005ecc 0x00007ecc 0x00007ecc 0x0028c 0x002f0 RW  0x2000
      DYNAMIC        0x005f18 0x00007f18 0x00007f18 0x000e8 0x000e8 RW  0x4
      NOTE           0x00462c 0x0000462c 0x0000462c 0x00020 0x00020 R   0x4
      GNU_EH_FRAME   0x0042c4 0x000042c4 0x000042c4 0x00094 0x00094 R   0x4
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10 <-- test RW
      GNU_RELRO      0x005ecc 0x00007ecc 0x00007ecc 0x00134 0x00134 R   0x1

    $ readelf -l ~/work/openrisc/buildroot/output/target/lib/libgcc_s.so.1 

    Elf file type is DYN (Shared object file)
    Entry point 0x0
    There are 6 program headers, starting at offset 52

    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      LOAD           0x000000 0x00000000 0x00000000 0x1c348 0x1c348 R E 0x2000
      LOAD           0x01df04 0x0001ff04 0x0001ff04 0x00208 0x002e4 RW  0x2000
      DYNAMIC        0x01df10 0x0001ff10 0x0001ff10 0x000f0 0x000f0 RW  0x4
      GNU_EH_FRAME   0x01b234 0x0001b234 0x0001b234 0x00294 0x00294 R   0x4
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10  <-- module RWE
      GNU_RELRO      0x01df04 0x0001ff04 0x0001ff04 0x000fc 0x000fc R   0x1

I will look to fixing this by seeing if I can get GCC to not need to have an
executable stack for libgcc_s.so.1.  But it will mean running new glibc with old
gcc installs may have some issues.

If you have any suggestions let me know.

> [1] https://www.qualys.com/2023/07/19/cve-2023-38408/rce-openssh-forwarded-ssh-agent.txt
> 
> Checked on x86_64-linux-gnu and i686-linux-gnu.
> ---
>  NEWS                                   |  6 +++
>  elf/dl-load.c                          | 13 ++---
>  elf/dl-support.c                       |  4 --
>  elf/rtld.c                             |  6 ---
>  elf/tst-execstack.c                    | 62 +++++++++++++++---------
>  nptl/allocatestack.c                   | 19 --------
>  sysdeps/generic/ldsodefs.h             | 22 ++-------
>  sysdeps/mach/hurd/Makefile             |  2 +
>  sysdeps/mach/hurd/dl-execstack.c       |  1 -
>  sysdeps/nptl/pthreadP.h                |  6 ---
>  sysdeps/unix/sysv/linux/Versions       |  3 --
>  sysdeps/unix/sysv/linux/dl-execstack.c | 67 +-------------------------
>  sysdeps/unix/sysv/linux/mips/Makefile  |  7 +++
>  13 files changed, 66 insertions(+), 152 deletions(-)
[snip]

-Stafford


More information about the Libc-alpha mailing list