diff options
author | Siddhesh Poyarekar <siddhesh@redhat.com> | 2014-11-12 19:30:24 +0530 |
---|---|---|
committer | Siddhesh Poyarekar <siddhesh@redhat.com> | 2014-11-12 19:42:59 +0530 |
commit | 533bb7c2ae156ff2d49b2e0b20b33810ba5e2721 (patch) | |
tree | aaeb627afb1e90b79e161e4d325b633064163168 /sysdeps/s390/s390-32/dl-machine.h | |
parent | fffa1cf8a7f95830d488d5fc6bf73cb9599143f4 (diff) | |
download | glibc-533bb7c2ae156ff2d49b2e0b20b33810ba5e2721.zip glibc-533bb7c2ae156ff2d49b2e0b20b33810ba5e2721.tar.gz glibc-533bb7c2ae156ff2d49b2e0b20b33810ba5e2721.tar.bz2 |
Fix stack alignment when loader is invoked directly
The s390 ABI requires the stack pointer to be aligned at 8-bytes.
When a program is invoked as an argument to the dynamic linker,
_dl_start_user adjusts the stack to remove the dynamic linker
arguments so that the program sees only its name and arguments. This
may result in the stack being misaligned since each argument shift is
only a word and not a double-word.
This is now fixed shifting argv and envp down instead of shifting argc
up and reclaiming the stack. This requires _dl_argv to be adjusted
and hence, is no longer relro.
Diffstat (limited to 'sysdeps/s390/s390-32/dl-machine.h')
-rw-r--r-- | sysdeps/s390/s390-32/dl-machine.h | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h index c56185c..0fd5a4f 100644 --- a/sysdeps/s390/s390-32/dl-machine.h +++ b/sysdeps/s390/s390-32/dl-machine.h @@ -166,18 +166,49 @@ _dl_start_user:\n\ # See if we were run as a command with the executable file\n\ # name as an extra leading argument.\n\ l %r1,_dl_skip_args@GOT12(0,%r12)\n\ - l %r1,0(%r1) # load _dl_skip_args\n\ + l %r1,0(%r1) # load _dl_skip_args\n\ + ltr %r1,%r1\n\ + je .L4 # Skip the arg adjustment if there were none.\n\ # Get the original argument count.\n\ l %r0,96(%r15)\n\ # Subtract _dl_skip_args from it.\n\ sr %r0,%r1\n\ - # Adjust the stack pointer to skip _dl_skip_args words.\n\ - sll %r1,2\n\ - ar %r15,%r1\n\ - # Set the back chain to zero again\n\ - xc 0(4,%r15),0(%r15)\n\ # Store back the modified argument count.\n\ st %r0,96(%r15)\n\ + # Copy argv and envp forward to account for skipped argv entries.\n\ + # We skipped at least one argument or we would not get here.\n\ + la %r6,100(%r15) # Destination pointer i.e. &argv[0]\n\ + lr %r5,%r6\n\ + lr %r0,%r1\n\ + sll %r0,2\n # Number of skipped bytes.\n\ + ar %r5,%r0 # Source pointer = Dest + Skipped args.\n\ + # argv copy loop:\n\ +.L1: l %r7,0(%r5) # Load a word from the source.\n\ + st %r7,0(%r6) # Store the word in the destination.\n\ + ahi %r5,4\n\ + ahi %r6,4\n\ + ltr %r7,%r7\n\ + jne .L1 # Stop after copying the NULL.\n\ + # envp copy loop:\n\ +.L2: l %r7,0(%r5) # Load a word from the source.\n\ + st %r7,0(%r6) # Store the word in the destination.\n\ + ahi %r5,4\n\ + ahi %r6,4\n\ + ltr %r7,%r7\n\ + jne .L2 # Stop after copying the NULL.\n\ + # Now we have to zero out the envp entries after NULL to allow\n\ + # start.S to properly find auxv by skipping zeroes.\n\ + # zero out loop:\n\ + lhi %r7,0\n\ +.L3: st %r7,0(%r6) # Store zero.\n\ + ahi %r6,4 # Advance dest pointer.\n\ + ahi %r1,-1 # Subtract one from the word count.\n\ + ltr %r1,%r1\n\ + jne .L3 # Keep copying if the word count is non-zero.\n\ + # Adjust _dl_argv\n\ + la %r6,100(%r15)\n\ + l %r1,_dl_argv@GOT(%r12)\n\ + st %r6,0(%r1)\n\ # The special initializer gets called with the stack just\n\ # as the application's entry point will see it; it can\n\ # switch stacks if it moves these contents over.\n\ @@ -185,7 +216,7 @@ _dl_start_user:\n\ # Call the function to run the initializers.\n\ # Load the parameters:\n\ # (%r2, %r3, %r4, %r5) = (_dl_loaded, argc, argv, envp)\n\ - l %r2,_rtld_local@GOT(%r12)\n\ +.L4: l %r2,_rtld_local@GOT(%r12)\n\ l %r2,0(%r2)\n\ l %r3,96(%r15)\n\ la %r4,100(%r15)\n\ |