Note: the following has been done in collaboration with Robin Verton.
Playing with our newly set up Raspberry Pis, we noticed that even though binaries are compiled to have a (by default) non-executable stack, they almost all end up having an executable stack. For example:
pi@raspwn:~ cat /proc/self/maps
00010000-00019000 r-xp 00000000 b3:02 524 /bin/cat
00028000-00029000 r--p 00008000 b3:02 524 /bin/cat
00029000-0002a000 rw-p 00009000 b3:02 524 /bin/cat
00e37000-00e58000 rw-p 00000000 00:00 0 [heap]
76bdc000-76bfe000 rw-p 00000000 00:00 0
76bfe000-76d88000 r--p 00000000 b3:02 233 /usr/lib/locale/locale-archive
76d88000-76eb3000 r-xp 00000000 b3:02 1946 /lib/arm-linux-gnueabihf/libc-2.19.so
76eb3000-76ec3000 ---p 0012b000 b3:02 1946 /lib/arm-linux-gnueabihf/libc-2.19.so
76ec3000-76ec5000 r--p 0012b000 b3:02 1946 /lib/arm-linux-gnueabihf/libc-2.19.so
76ec5000-76ec6000 rw-p 0012d000 b3:02 1946 /lib/arm-linux-gnueabihf/libc-2.19.so
76ec6000-76ec9000 rw-p 00000000 00:00 0
76ec9000-76ece000 r-xp 00000000 b3:02 33476 /usr/lib/arm-linux-gnueabihf/libarmmem.so
76ece000-76edd000 ---p 00005000 b3:02 33476 /usr/lib/arm-linux-gnueabihf/libarmmem.so
76edd000-76ede000 rw-p 00004000 b3:02 33476 /usr/lib/arm-linux-gnueabihf/libarmmem.so
76ede000-76efe000 r-xp 00000000 b3:02 1914 /lib/arm-linux-gnueabihf/ld-2.19.so
76f02000-76f04000 rw-p 00000000 00:00 0
76f0b000-76f0d000 rw-p 00000000 00:00 0
76f0d000-76f0e000 r--p 0001f000 b3:02 1914 /lib/arm-linux-gnueabihf/ld-2.19.so
76f0e000-76f0f000 rw-p 00020000 b3:02 1914 /lib/arm-linux-gnueabihf/ld-2.19.so
7e90c000-7e92d000 rwxp 00000000 00:00 0 [stack]
7ed76000-7ed77000 r-xp 00000000 00:00 0 [sigpage]
7ed77000-7ed78000 r--p 00000000 00:00 0 [vvar]
7ed78000-7ed79000 r-xp 00000000 00:00 0 [vdso]
ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
shows that cat
has a rwx stack, like in the 90’s! But cat
’s stack
should not be executable since readelf
shows a RW
flag, not a RWE
flag:
pi@raspwn:~$ readelf -l /bin/cat | grep GNU_STACK
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
After some search, we found
this link.
This post reveals that the problem had already occured in Wheezy (it is now
fixed). So we’ve discovered that is has reappeared in Jessie, although the
library libcofi_rpi
that was responsible for the bug in Wheezy is no
longer in /usr/lib/arm-linux-gnueabihf
. But this library seems, from the
cat
output above, to have been replaced by libarmmem
. And this library
is indeed the culprit since
pi@raspwn:~$ readelf -l /usr/lib/arm-linux-gnueabihf/libarmmem.so | grep GNU_STACK
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
Digging into the
arm-mem source
reveals that 1 file (architecture.S
) out of the 5 assembly source files
does not contain the instructions that prevent the stack from being
executable.
We then downloaded the source, added the missing lines
/* Prevent the stack from becoming executable */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
at the end of architecture.S
, compiled with make
, stripped the resulting
shared object with strip libarmmem.so
and checked that
pi@raspwn:~/arm-mem$ readelf -l ./libarmmem.so | grep GNU_STACK
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
The final step is to replace the original buggy libarmmem.so
thanks to
pi@raspwn:~/arm-mem$ sudo install ./libarmmem.so /usr/lib/arm-linux-gnueabihf/libarmmem.so
and check that the problem is cured:
pi@raspwn:~$ cat /proc/self/maps | grep stack
7e8cd000-7e8ee000 rw-p 00000000 00:00 0 [stack]
Note 1: We have submitted a pull request and reported the bug.
Note 2: One can wonder how many other libraries suffer from this problem, and the answer is: one, as can be seen from
pi@raspwn:~$ scanelf -lpqe
RWX --- --- /lib/klibc-YL2Pal4e_FwRI58JJ6S97Xf241g.so
(scanelf
is available after sudo apt install pax-utils
)