A Address Sanitizer, ASan, é uma ferramenta que permite identificar erros de memória em tempo de execução.
Em outras palavras, quando executamos nossos programa e ocorre algum erro de memória: a ASan acusa a ocorrência do problema, bem como interrompendo a sua execução.
Segundo o descrito no paper "AddressSanitizer: A Fast Address Sanity Checker", ela é:
a new memory error detector. Our tool finds out-of-bounds accesses to heap, stack, and global objects, as well as use-after-free bugs. It employs a specialized memory allocator and code instrumentation that is simple enough to be implemented in any compiler, binary translation system, or even in hardware.
Por meio dela é possível identificar os seguintes erros:
- Use after free (dangling pointer dereference)
- Heap buffer overflow
- Stack buffer overflow
- Global buffer overflow
- Use after return
- Use after scope
- Initialization order bugs
- Memory leaks
Ela já vem disponível nos dois compiladores mais utilizados GCC e CLANG. Sua utilização é por meio de flags
definidas durante a compilação. Assim, a ASan insere no código da aplicação, que está sendo compilada, mecanismos que permite "identificar diversos problemas de acesso à memória, incluindo o uso de memória desalocada, estouros de buffer no stack e no heap, acesso à memória não inicializada e vazamentos de memória" (PRADO, 2018).
A sua forma de atuação pode ser consultada na documentação. Mas, basicamente, a ASan atua trocando as chamadas malloc/free
do código pelas suas próprias versões de gerenciadores de acesso/uso de memória.
A utilização dessa ferramenta é fundamental para identificar problemas/erros escondidos. Por que escondidos? Pois, pode ocorrer que o programa seja executado em sua totalidade com aparente estado de normalidade, todavia, sem que seja disparado algum erro ou interrompido a sua execução. Sendo que, há alguns erros que podem estarem ocorrendo e que terão consequências em outras execuções ou exporem o software à alguma vulnerabilidade.
Deve-se ressaltar que o seu uso provoca uma sobrecarga na execução e processamento da aplicação. Em razão disso, é recomenddo a sua utilização apenas em versões de desenvolvimento e testes.
Uso
Para habilitar o ASan, adicione a seguinte flag quando estiver compilando o progama.
-fsanitize=address (clang)
gcc app.c -fsanitize=address -o app
Tem outras flgas que podem serem consultadas na documentação.
Exemplos de usos
Erro Stack buffer overflow
"Buffer Overflow, também chamado de Buffer Overrun, é uma anomalia em um programa em que, ao escrever dados em um buffer (armazenamento temporário de dados), a escrita ultrapassa o tamanho do buffer e começa a escrever nos espaços adjacentes."
Veja-se o exemplo abaixo:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[2];
str[0] = 'O';
str[1] = 'l';
str[2] = 'a';
str[3] = '\0';
printf("%s\n", str);
return (0);
}
Quando compilado e executado, não é apresentado qualquer erro;
> gcc test.c -o test
> ./test
> Ola
Agora, quando compilado com a flag -fsanitize=address
e executado, a ASan entra em ação para apresentar os erros encontrados e interromper a respectiva execução.
> gcc test.c -fsanitize=address -o test
> ./test
=================================================================
==389==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe948a7662 at pc 0x55d86850528f bp 0x7ffe948a7630 sp 0x7ffe948a7628
WRITE of size 1 at 0x7ffe948a7662 thread T0
#0 0x55d86850528e in main (/home/senhor/School42/ft_printf/test+0x128e)
#1 0x7f06f5c9cd09 in __libc_start_main ../csu/libc-start.c:308
#2 0x55d8685050b9 in _start (/home/senhor/School42/ft_printf/test+0x10b9)
Address 0x7ffe948a7662 is located in stack of thread T0 at offset 34 in frame
#0 0x55d868505184 in main (/home/senhor/School42/ft_printf/test+0x1184)
This frame has 1 object(s):
[32, 34) 'str' (line 6) <== Memory access at offset 34 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/senhor/School42/ft_printf/test+0x128e) in main
Shadow bytes around the buggy address:
0x10005290ce70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290ce80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290ce90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290cea0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290ceb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10005290cec0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1[02]f3 f3 f3
0x10005290ced0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290cee0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290cef0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290cf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005290cf10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
Shadow gap: cc
==389==ABORTING
Erro Memory leaks
Outro exemplo é com Memory leaks. Memory leaks ou vazamento de memória, é segundo a Wikipédia, "um fenômeno que ocorre quando um programa de computador gerencia incorretamente alocações de memória de maneira que certa memória não é liberada quando não é mais necessária".
Veja-se o exemplo abaixo:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *buffer;
buffer = malloc(1024);
sprintf(buffer, "%s", argv[1]);
printf("%s\n", buffer);
return (0);
}
Quando compilado e executado, novamente, não é apresentado qualquer erro;
> gcc test.c -o test
> ./test hello
> hello
Agora, quando compilado com a flag -fsanitize=address
e executado, a ASan entra em ação para apresentar os erros encontrados.
> gcc test.c -fsanitize=address -o test
> ./test hello hello ================================================================= ==822==ERROR: LeakSanitizer: detected memory leaks Direct leak of 1024 byte(s) in 1 object(s) allocated from: #0 0x7f5f09215e8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145 #1 0x5624c33ff1bd in main (/home/senhor/School42/ft_printf/test+0x11bd) #2 0x7f5f08fbbd09 in __libc_start_main ../csu/libc-start.c:308 SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).
Referências:
- https://www.usenix.org/system/files/conference/atc12/atc12-final39.pdf
- https://sergioprado.org/identificando-problemas-de-acesso-memoria-com-o-addresssanitizer/
- https://pt.wikipedia.org/wiki/Vazamento_de_memória
- https://girishjoshi.io/post/using-address-sanitizer-with-gcc/
- https://azure.microsofts.workers.dev/en-us/cpp/sanitizers/
- https://clang.llvm.org/docs/AddressSanitizer.html
- https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early
- https://gitbook.ganeshicmc.com/pwning/buffer-overflow-e-a-stack
Top comments (0)