Ваше использование parallel
неверно.
Каким-то образом 4-й запуск будет выполнен
curl http://127.0.0.1:81/a.php curl http://127.0.0.1:81/a.php
Я не совсем понимаю синтаксис, но это сработает:
yes | head -n4 | parallel ./a.sh
Пояснение из man-страницы
Задание может быть одной командой или небольшим скриптом, который должен быть запущен для каждой из строк во входных данных.
Эту инициализацию легко отследить, так как для (почти )каждый процесс strace
показывает очень подозрительный системный вызов в самом начале запуска процесса:
arch_prctl(ARCH_SET_FS, 0x7fc189ed0740) = 0
Вот что man 2 arch_prctl
говорит:
ARCH_SET_FS
Set the 64-bit base for the FS register to addr.
Ура, похоже, это то, что нам нужно. Чтобы узнать, кто звонит arch_prctl
, поищем бэктрек:
(gdb) catch syscall arch_prctl
Catchpoint 1 (syscall 'arch_prctl' [158])
(gdb) r
Starting program: <program path>
Catchpoint 1 (call to syscall arch_prctl), 0x00007ffff7dd9cad in init_tls () from /lib64/ld-linux-x86-64.so.2
(gdb) bt
#0 0x00007ffff7dd9cad in init_tls () from /lib64/ld-linux-x86-64.so.2
#1 0x00007ffff7ddd3e3 in dl_main () from /lib64/ld-linux-x86-64.so.2
#2 0x00007ffff7df04c0 in _dl_sysdep_start () from /lib64/ld-linux-x86-64.so.2
#3 0x00007ffff7dda028 in _dl_start () from /lib64/ld-linux-x86-64.so.2
#4 0x00007ffff7dd8fb8 in _start () from /lib64/ld-linux-x86-64.so.2
#5 0x0000000000000001 in ?? ()
#6 0x00007fffffffecef in ?? ()
#7 0x0000000000000000 in ?? ()
Итак, база сегмента ФС задается ld-linux
, входящей в состав glibc
, при загрузке программы (, если программа статически компонуется, этот код встраивается в бинарник ). Здесь все происходит.
Во время запуска загрузчик инициализирует TLS . Это включает в себя выделение памяти и настройку базового значения FS, чтобы оно указывало на начало TLS. Это делается с помощью системного вызоваarch_prctl
. После инициализации TLSsecurity_init
вызывается функция , которая генерирует значение защиты стека и записывает его в ячейку памяти, которая fs:[0x28]
указывает на:
А 0x28
— это смещение поля stack_guard
в структуре, расположенной в начале TLS.
То, что вы видите, называется (в GCC )Stack Smashing Protector (SSP ), который является формой защиты от переполнения буфера , созданной компилятор. Значение представляет собой случайное число, сгенерированное программой при запуске и, как упоминается в статье в Википедии, помещается в локальное хранилище потоков (TLS). Другие компиляторы могут использовать другие стратегии для реализации этого типа защиты.
Зачем хранить значение в TLS? Поскольку значение находится там, его адрес недоступен для регистров CS, DS и SS, что очень затрудняет угадывание сохраненного значения, если вы пытаетесь изменить стек с помощью вредоносного кода.