1+ #! /bin/sh
2+
13# Raises `PT_GNU_STACK`'s memory to be at least 8 MB.
24#
35# This causes `musl` to use a 8 MB default for new threads, resolving the primary
79# for reference. This differs that instead of setting at time of link, it
810# patches the binary as an already-linked ELF executable.
911
10- #! /bin/bash
11- set -eo pipefail
12+ set -e
1213
1314ELF=" $1 "
1415if [ ! -f " $ELF " ]; then
@@ -19,26 +20,30 @@ if [ ! -f "$ELF" ]; then
1920 exit 1
2021fi
2122
22- function hex {
23- hexdump -e ' 1 1 "%.2x" ' -v
23+ hex () {
24+ od -tx1 -v -A none | tr -d " [:space:] "
2425}
25- function read_bytes {
26- dd status=none bs=1 skip=$1 count=$2 if=" $ELF " | hex
26+ read_bytes () {
27+ dd bs=1 skip=" $1 " count=" $2 " if=" $ELF " 2> /dev/null | hex
2728}
28- function write_bytes {
29+ write_bytes () {
2930 POS=$1
3031 BYTES=$2
31- while [ ! $BYTES = " " ]; do
32- printf " \x$( printf $BYTES | head -c2) " | dd status=none conv=notrunc bs=1 seek=$POS of=" $ELF "
33- # Start with the third byte, as in, after the first two bytes
34- BYTES=$( printf $BYTES | tail -c+3)
35- POS=$(( $POS + 1 ))
32+ while [ ! " $BYTES " = " " ]; do
33+ NEXT=$( printf " %s" " $BYTES " | head -c2)
34+ # Advance to the third byte, as in, after the first two bytes
35+ BYTES=$( printf " %s" " $BYTES " | tail -c+3)
36+
37+ # shellcheck disable=SC2059
38+ printf " \x$NEXT " | dd conv=notrunc bs=1 seek=" $POS " of=" $ELF " 2> /dev/null
39+ POS=$(( POS + 1 ))
3640 done
3741}
3842
3943# Magic
4044MAGIC=$( read_bytes 0 4)
41- if [ ! $MAGIC = $( printf " \x7fELF" | hex) ]; then
45+ EXPECTED_MAGIC=$( printf " \x7ELF" | hex)
46+ if [ ! " $MAGIC " = " $EXPECTED_MAGIC " ]; then
4247 echo " Not ELF"
4348 exit 2
4449fi
@@ -55,18 +60,20 @@ case $BITS in
5560esac
5661
5762# For `value_per_bits a b`, `a` if 32-bit and `b` if 64-bit
58- function value_per_bits {
63+ value_per_bits () {
5964 RESULT=$(( $1 ))
6065 if [ $BITS = 64 ]; then
6166 RESULT=$(( $2 ))
6267 fi
63- printf $RESULT
68+ printf " %s " " $RESULT "
6469}
6570
6671# Read an integer by its offset, differing depending on if 32- or 64-bit
67- function read_integer_by_offset {
68- OFFSET=$( value_per_bits $1 $2 )
69- printf $(( 0 x$(swap_native_endian $(read_bytes $OFFSET $3 )) ))
72+ read_integer_by_offset () {
73+ OFFSET=$( value_per_bits " $1 " " $2 " )
74+ BYTES=$( read_bytes " $OFFSET " " $3 " )
75+ BYTES=$( swap_native_endian " $BYTES " )
76+ printf " %i" $(( 0 x$BYTES ))
7077}
7178
7279# 1 if little-endian, 2 if big-endian
8390# While this script is written in big-endian, we need to work with the file in
8491# its declared endian. This function swaps from big to native, or vice versa,
8592# as necessary.
86- function swap_native_endian {
93+ swap_native_endian () {
8794 BYTES=" $1 "
8895 if [ " $BYTES " = " " ]; then
89- read BYTES
96+ read -r BYTES
9097 fi
9198
92- if [ $LITTLE_ENDIAN -eq 0 ]; then
93- printf $BYTES
99+ if [ " $LITTLE_ENDIAN " -eq 0 ]; then
100+ printf " %s " " $BYTES "
94101 return
95102 fi
96103
97- while [ ! $BYTES = " " ]; do
98- printf $( printf $BYTES | tail -c2)
99- BYTES=$( printf $BYTES | head -c-2)
104+ while [ ! " $BYTES " = " " ]; do
105+ printf " %s " " $BYTES " | tail -c2
106+ BYTES=$( printf " %s " " $BYTES " | head -c-2)
100107 done
101108}
102109
103110ELF_VERSION=$( read_bytes 6 1)
104- if [ ! $ELF_VERSION = " 01" ]; then
111+ if [ ! " $ELF_VERSION " = " 01" ]; then
105112 echo " Unknown ELF Version ($ELF_VERSION )"
106113 exit 5
107114fi
108115
109116ELF_VERSION_2=$( read_bytes $(( 0x14 )) 4)
110- if [ ! $ELF_VERSION_2 = $( swap_native_endian 00000001) ]; then
117+ if [ ! " $ELF_VERSION_2 " = " $( swap_native_endian 00000001) " ]; then
111118 echo " Unknown secondary ELF Version ($ELF_VERSION_2 )"
112119 exit 6
113120fi
114121
115122# Find where the program headers are
116- PROGRAM_HEADERS_OFFSET=$( read_integer_by_offset 0x1c 0x20 $( value_per_bits 4 8) )
123+ PROGRAM_HEADERS_OFFSET=$( read_integer_by_offset 0x1c 0x20 " $( value_per_bits 4 8) " )
117124PROGRAM_HEADER_SIZE=$( value_per_bits 0x20 0x38)
118125DECLARED_PROGRAM_HEADER_SIZE=$( read_integer_by_offset 0x2a 0x36 2)
119- if [ ! $PROGRAM_HEADER_SIZE -eq $DECLARED_PROGRAM_HEADER_SIZE ]; then
126+ if [ ! " $PROGRAM_HEADER_SIZE " -eq " $DECLARED_PROGRAM_HEADER_SIZE " ]; then
120127 echo " Unexpected size of a program header ($DECLARED_PROGRAM_HEADER_SIZE )"
121128 exit 7
122129fi
123- function program_header_start {
124- printf $(( $ PROGRAM_HEADERS_OFFSET + ($1 * $ PROGRAM_HEADER_SIZE)) )
130+ program_header_start () {
131+ printf " %i " $(( PROGRAM_HEADERS_OFFSET + ($1 * PROGRAM_HEADER_SIZE)) )
125132}
126- function read_program_header {
127- read_bytes $( program_header_start $1 ) $PROGRAM_HEADER_SIZE
133+ read_program_header () {
134+ START=$( program_header_start " $1 " )
135+ read_bytes " $START " " $PROGRAM_HEADER_SIZE "
128136}
129137
130138# Iterate over each program header
131139PROGRAM_HEADERS=$( read_integer_by_offset 0x2c 0x38 2)
132- NEXT_PROGRAM_HEADER=$(( $ PROGRAM_HEADERS - 1 ))
140+ NEXT_PROGRAM_HEADER=$(( PROGRAM_HEADERS - 1 ))
133141FOUND=0
134- while [ $NEXT_PROGRAM_HEADER -ne -1 ]; do
142+ while [ " $NEXT_PROGRAM_HEADER " -ne -1 ]; do
135143 THIS_PROGRAM_HEADER=$NEXT_PROGRAM_HEADER
136- NEXT_PROGRAM_HEADER=$(( $ NEXT_PROGRAM_HEADER - 1 ))
137- PROGRAM_HEADER=$( read_program_header $THIS_PROGRAM_HEADER )
144+ NEXT_PROGRAM_HEADER=$(( NEXT_PROGRAM_HEADER - 1 ))
145+ PROGRAM_HEADER=$( read_program_header " $THIS_PROGRAM_HEADER " )
138146
139- HEADER_TYPE=$( printf $PROGRAM_HEADER | head -c8)
147+ HEADER_TYPE=$( printf " %s" " $PROGRAM_HEADER " | head -c8)
148+ HEADER_TYPE=$( swap_native_endian " $HEADER_TYPE " )
140149 # `PT_GNU_STACK`
141150 # https://github.com/torvalds/linux/blob/c2f2b01b74be8b40a2173372bcd770723f87e7b2/include/uapi/linux/elf.h#L41
142- if [ ! " $( swap_native_endian $ HEADER_TYPE) " = " 6474e551" ]; then
151+ if [ ! " $HEADER_TYPE " = " 6474e551" ]; then
143152 continue
144153 fi
145154 FOUND=1
146155
147- MEMSZ_OFFSET=$(( $(program_header_start $THIS_PROGRAM_HEADER ) + $(value_per_bits 0x14 0x28 ) ))
156+ MEMSZ_OFFSET=$(( $(program_header_start " $THIS_PROGRAM_HEADER " ) + $(value_per_bits 0x14 0x28 ) ))
148157 MEMSZ_LEN=$( value_per_bits 4 8)
149158 # `MEMSZ_OFFSET MEMSZ_OFFSET` as we've already derived it depending on the amount of bits
150- MEMSZ=$( read_integer_by_offset $MEMSZ_OFFSET $MEMSZ_OFFSET $MEMSZ_LEN )
159+ MEMSZ=$( read_integer_by_offset " $MEMSZ_OFFSET " " $MEMSZ_OFFSET " " $MEMSZ_LEN " )
151160 DESIRED_STACK_SIZE=$(( 8 * 1024 * 1024 ))
152161 # Only run if the inherent value is _smaller_
153- if [ $MEMSZ -lt $DESIRED_STACK_SIZE ]; then
162+ if [ " $MEMSZ " -lt " $DESIRED_STACK_SIZE " ]; then
154163 # `2 *`, as this is its length in hexadecimal
155- HEX_MEMSZ=$( printf %." $(( 2 * $MEMSZ_LEN )) " x $DESIRED_STACK_SIZE )
156- write_bytes $MEMSZ_OFFSET $( swap_native_endian $HEX_MEMSZ )
164+ HEX_MEMSZ=$( printf %." $(( 2 * MEMSZ_LEN)) " x " $DESIRED_STACK_SIZE " )
165+ HEX_MEMSZ=$( swap_native_endian " $HEX_MEMSZ " )
166+ write_bytes " $MEMSZ_OFFSET " " $HEX_MEMSZ "
157167 fi
158168done
159169
160- if [ $FOUND -eq 0 ]; then
170+ if [ " $FOUND " -eq 0 ]; then
161171 echo " \` PT_GNU_STACK\` program header not found"
162172 exit 8
163173fi
0 commit comments