[source] build: fix invocation of bundled ld.so in SDK and Imagebuilder

LEDE Commits lede-commits at lists.infradead.org
Thu Dec 14 09:44:53 PST 2017


jow pushed a commit to source.git, branch lede-17.01:
https://git.lede-project.org/338968a17060373e979edd2f53d218cde1bd76b3

commit 338968a17060373e979edd2f53d218cde1bd76b3
Author: Jo-Philipp Wich <jo at mein.io>
AuthorDate: Sun Jul 16 23:43:19 2017 +0200

    build: fix invocation of bundled ld.so in SDK and Imagebuilder
    
    Commit 72d751cba9 "build: rework library bundling" introduced a new helper
    binary "runas" whose sole purpose was mangling the argv vector passed to
    the actual called ELF image so that the renamed executable could obtain the
    proper name from argv[0].
    
    This approach, however totally defeated the purpose of calling bundled ELF
    executables through the shipped ld.so loader since the execv() invocation
    performed by "runas" would cause the kernel the interprete the final program
    image through the system ELF loader again.
    
    To solve the problem, use an alternative approach of shipping a shared object
    "runas.so" which uses an ELF ".init_array" function pointer to obtain the
    argv[] vector of the to-be-executed main() function and mangle it in-place.
    
    The actual argv[0] value to use is communicated out-of-band using an
    environment variable "RUNAS_ARG0" by the shell wrapper script. The wrapper
    script also takes care of setting LD_PRELOAD to instruct the shipped ELF
    loader to preload the actual ELF program image with the "runas.so" helper
    library.
    
    Fixes FS#909.
    
    Signed-off-by: Jo-Philipp Wich <jo at mein.io>
    (cherry picked from commit ef1cafa736679eb035d405bcdf903fd1fb329865)
---
 scripts/bundle-libraries.sh | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/scripts/bundle-libraries.sh b/scripts/bundle-libraries.sh
index dfc2b85..b108fd8 100755
--- a/scripts/bundle-libraries.sh
+++ b/scripts/bundle-libraries.sh
@@ -70,26 +70,27 @@ _relpath() {
 	done
 }
 
-_wrapper() {
-	cat <<-EOT | ${CC:-gcc} -x c -o "$1" -
+_runas_so() {
+	cat <<-EOT | ${CC:-gcc} -x c -fPIC -shared -o "$1" -
 		#include <unistd.h>
 		#include <stdio.h>
+		#include <stdlib.h>
 
-		int main(int argc, char **argv) {
-			const char *self   = argv[0];
-			const char *target = argv[1];
+		int mangle_arg0(int argc, char **argv, char **env) {
+			char *arg0 = getenv("RUNAS_ARG0");
 
-			if (argc < 3) {
-				fprintf(stderr, "Usage: %s executable arg0 [args...]\n", self);
-				return 1;
-			}
+			if (arg0)
+				argv[0] = arg0;
 
-			return execv(target, argv + 2);
+			return 0;
 		}
+
+		__attribute__((section(".init_array")))
+		static void *mangle_arg0_constructor = &mangle_arg0;
 	EOT
 
 	[ -x "$1" ] || {
-		echo "compiling wrapper failed" >&2
+		echo "compiling preload library failed" >&2
 		exit 5
 	}
 }
@@ -113,13 +114,13 @@ for BIN in "$@"; do
 		_ln "../lib" "$DIR/usr/lib"
 	}
 
-	[ ! -x "$DIR/lib/runas" ] && {
-		_wrapper "$DIR/lib/runas"
+	[ ! -x "$DIR/lib/runas.so" ] && {
+		_runas_so "$DIR/lib/runas.so"
 	}
 
 	LDSO=""
 
-	[ -n "$LDD" ] && [ -x "$BIN" ] && file "$BIN" | grep -sqE "ELF.*executable" && {
+	[ -n "$LDD" ] && [ -x "$BIN" ] && file "$BIN" | grep -sqE "ELF.*(executable|interpreter)" && {
 		for token in $("$LDD" "$BIN" 2>/dev/null); do
 			case "$token" in */*.so*)
 				case "$token" in
@@ -150,7 +151,9 @@ for BIN in "$@"; do
 		cat <<-EOF > "$BIN"
 			#!/usr/bin/env bash
 			dir="\$(dirname "\$0")"
-			exec "\$dir/${REL:+$REL/}$LDSO" --library-path "\$dir/${REL:+$REL/}" "\$dir/${REL:+$REL/}runas" "\$dir/.${BIN##*/}.bin" "\$0" "\$@"
+			export RUNAS_ARG0="\$0"
+			export LD_PRELOAD="\$dir/${REL:+$REL/}runas.so"
+			exec "\$dir/${REL:+$REL/}$LDSO" --library-path "\$dir/${REL:+$REL/}" "\$dir/.${BIN##*/}.bin" "\$@"
 		EOF
 
 		chmod ${VERBOSE:+-v} 0755 "$BIN"



More information about the lede-commits mailing list