Что такое «теневые байты» в AddressSanitizer и как их интерпретировать? - PullRequest
8 голосов
/ 08 мая 2020

Я отлаживаю C программу и серьезно запутался в нижней половине выходных данных AddressSanitizer, когда обнаружил проблемы. Давайте использовать это, например:

==33184==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000005 at pc 0x55f312fe2509 bp 0x7ffc99f5f5c0 sp 0x7ffc99f5f5b0
WRITE of size 1 at 0x602000000005 thread T0
    #0 0x55f312fe2508 in main /home/user/c/friends/main.c:20
    #1 0x7fa5ea0e9b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #2 0x55f312fe21c9 in _start (/home/user/c/friends/cmake-build-debug/friends+0x11c9)

0x602000000005 is located 11 bytes to the left of 5-byte region [0x602000000010,0x602000000015)
allocated by thread T0 here:
    #0 0x7fa5eb2b8b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
    #1 0x55f312fe23f4 in main /home/user/c/friends/main.c:18
    #2 0x7fa5ea0e9b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/user/c/friends/main.c:20 in main

  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000:[fa]fa 05 fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==33184==ABORTING

Все, что находится выше этой строки, я понимаю: SUMMARY: AddressSanitizer: heap-buffer-overflow /home/user/c/friends/main.c:20 in main

Мой вопрос касается данных, представленных ниже этой строки. Я прочитал этот ответ , но он не ответил на мой вопрос. Дамп памяти, показанный ASAN, выглядит так:

  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000:[fa]fa 05 fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  1. Что за линия со стрелкой пытается мне сказать? Я предполагаю, что 05, которое появляется между fa s, относится к 0x602000000005 is located 11 bytes to the left of 5-byte region «5-байтовой области». Тем не менее, я все еще сбит с толку, потому что легенда гласит, что fa означает «куча левой красной зоны», но она появляется справа от 05 и слева от нее. . Почему нет "красных зон кучи справа?"

  2. В этом примере ASAN сообщает, что программа вышла на 11 байт из 5-байтовой области, но показывает гораздо больше fa s, чем это.

  3. Есть ли какая-либо надлежащая подробная документация, которая на самом деле объясняет, что эти термины "красная зона слева в куче", "красная зона в середине стека", "глобальная красная зона" и т. д. c значит? Мне не удалось найти ни одного.

  4. Что такое «теневой байт / адрес» в этом контексте?

1 Ответ

9 голосов
/ 11 мая 2020

Что такое «теневые байты» в AddressSanitizer и как их интерпретировать?

Со страницы AddressSanitizerAlgorithm на GitHub (на которую также есть ссылка Страница LLVM AddressSanitizer ):

Виртуальное адресное пространство разделено на 2 непересекающихся класса:

  • Основная память приложения (Mem): эта память используется обычным кодом приложения.
  • Теневая память (Shadow): эта память содержит теневые значения (или метаданные). Между тенью и основной памятью приложения есть соответствие. Отравление байта в основной памяти означает запись некоторого специального значения в соответствующую теневую память.

Итак, «теневые байты» - это метаданные, описывающие состояние адресуемой памяти вашей программы.

Если мы посмотрим на вывод asan:

Shadow byte legend (one shadow byte represents 8 application bytes):

, он сообщает нам, что шестнадцатеричный дамп относится к теневой памяти, которая описывает состояние «реальной» памяти вашей программы. Какие состояния он отслеживает?

  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  ...

поэтому, если адресуема целая 8-байтовая строка, байт тени, который отслеживает (или затеняет), должен иметь значение 00. Если он частично адресуемый, теневой байт будет 01..07, что предположительно является количеством адресуемых байтов в строке.

Значение, на которое указывает шестнадцатеричный дамп, - fa, или «Куча left redzone "- предположительно, это своего рода защитная область вокруг выделения кучи для обнаружения переполнения.

Из той же ссылки:

Библиотека времени выполнения заменяет mallo c и бесплатные функции. Память вокруг mallo c -ed регионов (красные зоны) отравлена ​​

В более широком смысле, это описание (в адресах программ)

0x602000000005 is located 11 bytes to the left of 5-byte region
  [0x602000000010,0x602000000015)

соответствует показанной карте теней:

=>0x0c047fff8000:[fa]fa 05 fa ...

Предполагая естественное выравнивание,

  • байт тени 0x0c047fff8000 описывает (или, опять же, тени) программные адреса 0x602000000000..0x602000000007, который включает адрес, к которому вы обращались
  • следующий байт тени в 0x0c047fff8001 описывает адреса программы 0x602000000008..0x60200000000F
  • оба из них имеют значение fa, что означает «красная зона слева от кучи»
  • следующий теневой байт в 0x0c047fff8002 описывает программные адреса 0x602000000010..0x602000000007 и имеет значение 05, что означает, что 5 байтов адресуются. Это 5 байтов вашей кучи.

Все это согласуется с частью ошибки, которую вы сделали поняли.

  1. Тем не менее, я все еще сбит с толку, потому что легенда гласит, что fa означает «куча левой красной зоны», но она появляется справа от 05 и для слева от него. Почему нет "кучи правильных красных зон?"

    Я не знаю, что на самом деле означает направленность. Обычно кучи изначально растут в одном направлении (традиционно вверх по мере роста стека вниз), но могут быть фрагментированы, освобождены, объединены и перераспределены. Является ли промежуток между двумя выделениями "справа" или "слева", или и тем, и другим, или ни одного? Все, что нам нужно знать, это то, что это отравленная область кучи, которая никогда не выделялась пользователю.

    Может быть, это должна быть просто «красная зона кучи», если нет ориентации, соответствующей левому / среднему / правому стеку значения.

  2. В этом примере ASAN сообщает, что программа вышла на 11 байт из 5-байтовой области, но показывает гораздо большую скорость, чем это.

    каждый fa представляет восемь байтов, как гласит легенда. Таким образом, если вы обращались к чему-либо от девяти до пятнадцати байтов до выделения (по модулю арифметики c ошибок), это было бы в том же теневом байте. Если бы вы обращались к одному-восьми байтам раньше, он отобразился бы в следующем байте тени (прямо перед 05).

    Остальные fa s представляют собой просто карту окрестностей, которая в данном случае не кажется полезной, но может быть полезной в других.

  3. Существует ли соответствующая подробная документация, которая на самом деле объясняет, что означают эти термины «красная зона слева от кучи», «красная зона в середине стека», «глобальная красная зона» и т. Д.?

    Понятия не имею . Они кажутся вполне естественными из варианта использования - вы попали в красную зону = вы получили доступ к адресу, который вам не нужен. Вы всегда можете просто прочитать код, например. asan_internal.h определяет значение kAsanHeapLeftRedzoneMagic, а asan_allocator.cpp отравляет им теневые байты.

  4. Что такое «Теневой байт / адрес» в этом контексте?

    Просто для полноты, теневой байт - это байт, который затеняет группу из восьми обычно доступных программных байтов и отслеживает некоторую информацию о них полезны для дезинфицирующего средства.

    Теневой адрес - это адрес теневого байта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...