2018-01-22 06:22 UTC

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0014371CentOS-7kernelpublic2018-01-13 01:17
Reportertcarter 
PrioritynormalSeverityminorReproducibilityalways
StatusnewResolutionopen 
Platformx86_64 (KVM Guest)OSCentOSOS Version7.4.1708
Product Version7.4.1708 
Target VersionFixed in Version 
Summary0014371: Kernels since 3.10.0-693.1.1 no longer honour prelink addresses for dynamic ELF executables
DescriptionIn kernel 3.10.0-514.26.2 prelink --reloc-only=<address> could be used to fix the base address of a dynamic (ET_DYN) ELF executable (without disabling ASLR for the linked libraries)

Since kernel 3.10.0-693.1.1 the address from the ELF header appears to be ignored unless either ASLR is completely disabled (by personality() or sysctl) OR the binary is loaded using ld-linux as an explicit interpreter (eg /lib64/ld-linux-x86-64.so.2 /bin/cat /proc/self/maps)

The changed behaviour is present in all -693 kernels up to the current release.
Steps To Reproduce# Copy the php binary (dynamic / PIE executable)
$ cp /bin/php /tmp/php.orig
$ cp /bin/php /tmp/php.pre

# Set a fixed relocation for php.pre
$ prelink --reloc-only=0x00005e7da0a00000 /tmp/php.pre

# On -514 kernel
$ uname -r
3.10.0-514.26.2.el7.x86_64

# Normal system version subject to ASLR for the executable object on each invocation
$ /tmp/php.orig -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
7fa914052000-7fa91441a000 r-xp 00000000 fd:01 76176524 /tmp/php.orig
7fa91461a000-7fa9146a8000 r--p 003c8000 fd:01 76176524 /tmp/php.orig
7fa9146a8000-7fa9146ad000 rw-p 00456000 fd:01 76176524 /tmp/php.orig
$ /tmp/php.orig -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
7f12a2eb8000-7f12a3280000 r-xp 00000000 fd:01 76176524 /tmp/php.orig
7f12a3480000-7f12a350e000 r--p 003c8000 fd:01 76176524 /tmp/php.orig
7f12a350e000-7f12a3513000 rw-p 00456000 fd:01 76176524 /tmp/php.orig

# Prelinked version uses the same ELF LOAD header address on each invocation
$ /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
5e7da0a00000-5e7da0dc8000 r-xp 00000000 fd:01 76176522 /tmp/php.pre
5e7da0fc8000-5e7da1056000 r--p 003c8000 fd:01 76176522 /tmp/php.pre
5e7da1056000-5e7da105b000 rw-p 00456000 fd:01 76176522 /tmp/php.pre
$ /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
5e7da0a00000-5e7da0dc8000 r-xp 00000000 fd:01 76176522 /tmp/php.pre
5e7da0fc8000-5e7da1056000 r--p 003c8000 fd:01 76176522 /tmp/php.pre
5e7da1056000-5e7da105b000 rw-p 00456000 fd:01 76176522 /tmp/php.pre

# But on a -693 kernel
$ uname -r
3.10.0-693.11.6.el7.x86_64

# The prelinked version ignores the ELF LOAD header address and is still subject to ASLR
$ /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
5604ea41b000-5604ea7e3000 r-xp 00000000 fd:01 71512364 /tmp/php.pre
5604ea9e3000-5604eaa71000 r--p 003c8000 fd:01 71512364 /tmp/php.pre
5604eaa71000-5604eaa76000 rw-p 00456000 fd:01 71512364 /tmp/php.pre
$ /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
55f71ee63000-55f71f22b000 r-xp 00000000 fd:01 71512364 /tmp/php.pre
55f71f42b000-55f71f4b9000 r--p 003c8000 fd:01 71512364 /tmp/php.pre
55f71f4b9000-55f71f4be000 rw-p 00456000 fd:01 71512364 /tmp/php.pre

Additional InformationI Imagine this most likely an upstream kernel bug, but don't currently have access to an up to date RHEL 7 system to verify on, so have not yet reported it upstream.


# Invoking the prelinked binary via /lib64/ld-linux-x86-64.so.2 causes
# the prelink address to be honoured on the newer kernels:

$ /lib64/ld-linux-x86-64.so.2 \
  /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
5e7da0a00000-5e7da0dc8000 r-xp 00000000 fd:01 71512364 /tmp/php.pre
5e7da0dc8000-5e7da0fc8000 ---p 003c8000 fd:01 71512364 /tmp/php.pre
5e7da0fc8000-5e7da1056000 r--p 003c8000 fd:01 71512364 /tmp/php.pre
5e7da1056000-5e7da105b000 rw-p 00456000 fd:01 71512364 /tmp/php.pre
$ /lib64/ld-linux-x86-64.so.2 \
  /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
5e7da0a00000-5e7da0dc8000 r-xp 00000000 fd:01 71512364 /tmp/php.pre
5e7da0dc8000-5e7da0fc8000 ---p 003c8000 fd:01 71512364 /tmp/php.pre
5e7da0fc8000-5e7da1056000 r--p 003c8000 fd:01 71512364 /tmp/php.pre
5e7da1056000-5e7da105b000 rw-p 00456000 fd:01 71512364 /tmp/php.pre


# Setting LD_USE_LOAD_BIAS=1 explicitly has no effect
# (and the binary is not setuid/setgid)

$ /bin/env LD_USE_LOAD_BIAS=1 \
  /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
55c3ff05f000-55c3ff427000 r-xp 00000000 fd:01 71512364 /tmp/php.pre
55c3ff627000-55c3ff6b5000 r--p 003c8000 fd:01 71512364 /tmp/php.pre
55c3ff6b5000-55c3ff6ba000 rw-p 00456000 fd:01 71512364 /tmp/php.pre
$ /bin/env LD_USE_LOAD_BIAS=1 \
  /tmp/php.pre -r 'print file_get_contents("/proc/self/maps");' | grep /tmp/php
556509fbd000-55650a385000 r-xp 00000000 fd:01 71512364 /tmp/php.pre
55650a585000-55650a613000 r--p 003c8000 fd:01 71512364 /tmp/php.pre
55650a613000-55650a618000 rw-p 00456000 fd:01 71512364 /tmp/php.pre


The reason for the prelinking is that we use a patch the the PHP opcache module which allows for caching of code compilation for the PHP cli SAPI in persistent disk files, but it depends on the PHP binary being loaded at a fixed address however would prefer not to disable ASLR for the libraries (or the rest of the system).

I have also been able to reproduce the same behaviour with other dynamic ELF binaries.
TagsNo tags attached.
abrt_hash
URL
Attached Files

-Relationships
+Relationships

-Notes
There are no notes attached to this issue.
+Notes

-Issue History
Date Modified Username Field Change
2018-01-13 01:17 tcarter New Issue
+Issue History