Я пытаюсь найти причину segfault и сузил ее до PLT, используя btrace gdb. Segfault происходит во время перехода от PLT к GOT, что я интерпретирую, чтобы показать, что PLT был поврежден во время выполнения. На основании анализа, представленного ниже, является ли эта интерпретация правильной? Каковы вероятные виновники коррупции в PLT? Переполнение стека? Я считаю, что установка точки наблюдения на GOT-адрес может быть полезна в этом случае. watch -l 0x55555562f048
будет правильным подходом? Другие идеи для отладки приветствуются.
Для контекста, segfault происходит во время вызова strlen
в функции foo
:
int foo(char * path, ...) {
...
if (strlen(path) >= PATH_MAX) {
Соответствующие строки сборки :
0x58114 <foo+212> cmpq $0x0,-0x4c8(%rbp)
0x5811c <foo+220> jne 0x5812a <foo+234>
0x5811e <foo+222> lea 0xb96fb(%rip),%rdi # 0x111820
0x58125 <foo+229> callq 0x376c0 <__ubsan_handle_nonnull_arg@plt>
0x5812a <foo+234> mov -0x4c8(%rbp),%rax
0x58131 <foo+241> mov %rax,%rdi
0x58134 <foo+244> callq 0x37090 <strlen@plt>
Во-первых, path
сравнивается с NULL (cmpq $0x0,-0x4c8(%rbp)
), который, как я полагаю, в данном случае добавляется исключительно для убсановских приборов. За этой ветвью не последовало, и программа перешла на <foo+234>
, где она установила для вызова strlen
, переместив path
на rax
, а затем rdi
и, наконец, вызвав strlen@plt
. Выполнение record btrace
в gdb
непосредственно перед тем, как это произвело эту историю команд:
(gdb) record btrace
(gdb) c
136 0x00005555555ac114 <foo+212>: cmpq $0x0,-0x4c8(%rbp)
137 0x00005555555ac11c <foo+220>: jne 0x5555555ac12a <foo+234>
138 0x00005555555ac12a <foo+234>: mov -0x4c8(%rbp),%rax
139 0x00005555555ac131 <foo+241>: mov %rax,%rdi
140 0x00005555555ac134 <foo+244>: callq 0x55555558b090 <strlen@plt>
141 0x000055555558b090 <strlen@plt+0>: jmpq *0xa3fb2(%rip) # 0x55555562f048 <strlen@got.plt>
Здесь мы видим, что path
не был нулевым, и поэтому программа перепрыгнула на <foo+234>
и настроила для вызова strlen
(mov
, mov
, callq <strlen@plt>
). Последняя выполненная инструкция была jmpq *0xa3fb2(%rip)
для записи для strlen
в GOT (strlen@got.plt
), после чего программа потерпела крах и GDB потеряла контекст (сообщив, что она Cannot find bounds of current function
).