Почему дезинфицирующее средство адресов не работает при глобальном переполнении bss?

Что я сделал.

Тест1

  1 #include <stdio.h>                                                              
  2                                                                                 
  3 int test[16];                                                                   
  4                                                                                 
  5 int main()                                                                      
  6 {                                                                               
  7     test[17] = -1;                                                              
  8 } 

/tmp $ gcc ./main.c -o main -fsanitize=address
/tmp $ ./main 
/tmp $

Тест2

  1 #include <stdio.h>                                                              
  2                                                                                 
  3 int test[16] = {1};                                                             
  4                                                                                 
  5 int main()                                                                      
  6 {                                                                               
  7     test[17] = -1;                                                              
  8 }

 /tmp $ gcc ./main.c -o main -fsanitize=address
 /tmp $ ./main 

=================================================================
==19776==ERROR: AddressSanitizer: global-buffer-overflow on address 
...

Похоже, не работает обнаружение переполнения глобального буфера для глобальных переменных, размещенных в bss (так ли это?). Каковы причины этого?

Обновление:

Код, который хранится, не оптимизирован. Системная информация:

$ gcc --version
gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

person Alex Hoppus    schedule 19.04.2018    source источник
comment
вы пробовали с clang ?   -  person Jean-François Fabre    schedule 19.04.2018
comment
Я не уверен, что присваивание вообще генерирует какой-либо код.   -  person Eugene Sh.    schedule 19.04.2018
comment
@ЕвгенийШ. было бы нормально не генерировать код (поскольку это в любом случае UB, и даже если нет, без volatile нет наблюдаемого поведения), но я был бы удивлен, когда это зависит от того, инициализирована ли переменная или нет...   -  person    schedule 19.04.2018
comment
@ Jean-François Fabre Я не пробовал clang, меня сейчас интересует только gcc.   -  person Alex Hoppus    schedule 19.04.2018
comment
godbolt программы, похоже, показывает вызов __asan_report_store4 как для gcc, так и для clang... хммм   -  person Shafik Yaghmour    schedule 19.04.2018
comment
Если проверка, которую выполняет gcc, неверна, что не очевидно, если посмотреть на генерируемую проверку.   -  person Shafik Yaghmour    schedule 19.04.2018
comment
__asan_report_store4 — не единственное, что должен делать асаны. На самом деле, это должно отравить красные зоны вокруг глобальных переменных в хуке __asan_register_global в libasan (эти хуки находятся в разделе ctors и вызываются при инициализации). Я не уверен прямо сейчас, но похоже, что эти хуки не вызываются для глобальных переменных, которые размещены в bss. Также я проверил дезинфицирующее средство адреса ядра (из linux-kernel) и похоже, что оно обнаруживает переполнение глобального буфера bss.   -  person Alex Hoppus    schedule 19.04.2018


Ответы (2)


Это находится в разделе FAQ:

В: Почему ASan не сообщил о явно недопустимом доступе к памяти в моем коде?

A1: Если ваши ошибки слишком очевидны, возможно, компилятор уже оптимизировал их к моменту запуска Asan.

A2: Другой вариант, предназначенный только для C, — это доступ к глобальным общим символам, которые не защищены Asan (вы можете использовать -fno-common, чтобы отключить генерацию общих символов и, надеюсь, обнаружить больше ошибок).

Ваш случай, вероятно, покрывается A2, поэтому добавление -fno-common должно помочь.

Проблема с общими символами (которые по умолчанию генерируются для глобальных переменных с нулевой инициализацией) заключается в том, что из-за их странной устаревшей семантики Асан не может вставлять для них красные зоны (см. GCC #55739 для подробностей). Предоставляя -fno-common, вы отключаете генерацию общих символов и вместо этого просите GCC генерировать нормальные глобальные символы во всех случаях (это имеет небольшой шанс сломать плохо написанные программы, которые полагаются на поведение общих символов, но обычно это не проблема).

person yugr    schedule 19.04.2018
comment
Здесь помогает добавление флага -fno-common. Кроме того, если вы хотите, вы можете дать более широкое объяснение этого флага и того, как он конкретно влияет на поведение асан. Это было бы полезно для других людей, которые будут обращаться к этому вопросу в будущем. Спасибо. - person Alex Hoppus; 19.04.2018
comment
@AlexHoppus Я попытался добавить еще несколько деталей, дайте мне знать, можно ли их улучшить. - person yugr; 19.04.2018

Это делают и другие инструменты, в том числе наш инструмент CheckPointer (Semantic Designs). (Вывод отредактирован для удаления ненужного текста):

Для test1.c, как это определил OP:

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>DMSCheckPointer C~GCC4 test1.c
C~GCC4 CheckPointer Version 1.2.1001
Copyright (C) 2011-2016 Semantic Designs, Inc; All Rights Reserved; SD Confidential

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>gcc.exe -I"c:\DMS\Domains\C\GCC4\Tools\CheckPointer" -I.\Target -otest1.exe Target\test1.c <snip>

test1
*** Error: CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
       Dereference of pointer is out of bounds.
in function: main, line: 7, file c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source\test1.c

Для test2.c:

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>DMSCheckPointer C~GCC4 test2.c
C~GCC4 CheckPointer Version 1.2.1001
Copyright (C) 2011-2016 Semantic Designs, Inc; All Rights Reserved; SD Confidential

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>gcc.exe -I"c:\DMS\Domains\C\GCC4\Tools\CheckPointer" -I.\Target -otest2.exe Target\test2.c <snip>

test2
*** Error: CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
       Dereference of pointer is out of bounds.
in function: main, line: 7, file c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source\test2.c

CheckPointer не нуждается в «красных зонах» вокруг данных; он проверяет доступы по языковой семантике. Это означает, например, что он будет обнаруживать доступ к концу массива символов в любом месте структуры, независимо от того, является ли структура локальной переменной (стека), в куче, в локальном хранилище потока или встроена в какую-либо другую структуру.

«Нечетная формулировка», связанная с «CWE-119», не является нашим выбором слов, она определяется стандартом для Общие недостатки. CheckPointer сообщает об ошибках, используя определения, классификации и описания CWE.

person Ira Baxter    schedule 20.04.2018