open(“/etc/ld.so.cache”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=12431, ...}) = 0
old_mmap(NULL, 12431, PROT_READ, MAP_PRIVATE, 4, 0) =
0x40015000
close(4) = 0
open(“/lib/libc.so.6”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0755, st_size=4101324, ...}) = 0
read(4,
“\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\210\212”...,
4096) = 4096Прочитаны первые 4 Кб библиотеки libc. Libc – это стандартная библиотека коллективного доступа, в которой расположены функции, вызываемые из программ на языке C (такие как printf, scanf и т. д.).
old_mmap(NULL, 1001564, PROT_READ|PROT_EXEC, MAP_PRIVATE, 4,
0) = 0x40019000
mprotect(0x40106000, 30812, PROT_NONE) = 0
old_mmap(0x40106000, 16384, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED, 4, 0xec000) = 0x40106000
old_mmap(0x4010a000, 14428, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED| MAP_ANONYMOUS, -1, 0)
= 0x4010a000
close(4) = 0
mprotect(0x40019000, 970752, PROT_READ|PROT_WRITE) = 0
mprotect(0x40019000, 970752, PROT_READ|PROT_EXEC) = 0
munmap(0x40015000, 12431) = 0
personality(PER_LINUX) = 0
getpid() = 9271
brk(0) = 0x804b160
brk(0x804b198) = 0x804b198
brk(0x804c000) = 0x804c000
open(“/usr/share/locale/locale.alias”, O_RDONLY) = 4
fstat64(0x4, 0xbfffb79c) = -1 ENOSYS (Function not
implemented)
fstat(4, {st_mode=S_IFREG|0644, st_size=2265, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, – 1, 0) = 0x40015000
read(4, “# Locale name alias data base.\n#”..., 4096) = 2265
read(4, “”, 4096) = 0
close(4) = 0
munmap(0x40015000, 4096) = 0Если в программе встречается вызов функции setlocale, то libc читает локализованную информацию (информацию о местной специфике) для определения формата отображения чисел, даты, времени и т. д. Напомним, что хотя стандартные разрешения не позволяют модифицировать файлы локализации непривилегированным пользователям, но их достаточно для чтения этих файлов. Добавим, что разрешения файлов обычно печатаются при выводе информации о каждом вызове fstat (например, в приведенном примере 0644). Это позволяет легко визуально отследить неверные разрешения. Если ищется файл локализации, в который предполагается записать информацию, будьте осторожны, чтобы при записи не получить ошибки переполнения буфера. Третий (косвенный) параметр в списке входных параметров – файлы локализации.
open(“/usr/share/i18n/locale.alias”, O_RDONLY) = -1 ENOENT
(No such file or directory)
open(“/usr/share/locale/en_US/LC_MESSAGES”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
close(4) = 0
open(“/usr/share/locale/en_US/LC_MESSAGES/SYS_LC_MESSAGES”,
O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=44, ...}) = 0
old_mmap(NULL, 44, PROT_READ, MAP_PRIVATE, 4, 0)
= 0x40015000
close(4) = 0
open(“/usr/share/locale/en_US/LC_MONETARY”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=93, ...}) = 0
old_mmap(NULL, 93, PROT_READ, MAP_PRIVATE, 4, 0)
= 0x40016000
close(4) = 0
open(“/usr/share/locale/en_US/LC_COLLATE”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=29970, ...}) = 0
old_mmap(NULL, 29970, PROT_READ, MAP_PRIVATE, 4, 0)
= 0x4010e000
close(4) = 0
brk(0x804d000) = 0x804d000
open(“/usr/share/locale/en_US/LC_TIME”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=508, ...}) = 0
old_mmap(NULL, 508, PROT_READ, MAP_PRIVATE, 4, 0)
= 0x40017000
close(4) = 0
open(“/usr/share/locale/en_US/LC_NUMERIC”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=27, ...}) = 0
old_mmap(NULL, 27, PROT_READ, MAP_PRIVATE, 4, 0)
= 0x40018000
close(4) = 0
open(“/usr/share/locale/en_US/LC_CTYPE”, O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=87756, ...}) = 0
old_mmap(NULL, 87756, PROT_READ, MAP_PRIVATE, 4, 0)
= 0x40116000
close(4) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4),
...}) = 0
open(“test”, O_RDONLY|O_LARGEFILE) = 4
fstat(4, {st_mode=S_IFREG|0664, st_size=6, ...}) = 0Наконец, команда cat открывает наш файл «test». Конечно, имя файла – это входные данные команды, но они безопасны для работоспособности команды из-за ее логики работы. В других случаях может потребоваться учет содержимого входного файла.
read(4, “hello\n”, 512) = 6
write(1, “hello\n”, 6) = 6
read(4, “”, 512) = 0
close(4) = 0
close(1) = 0
_exit(0) = ?В заключение cat пытается прочитать 512 байтов из файла (читает 6) и выводит их на экран (который описан STDOUT с дескриптором файла 1). При повторной попытке прочитать очередные 512 байтов файла читается 0 байт, что свидетельствует о достижении конца файла. В результате файл закрывается, дескриптор файла освобождается и выполняется нормальный выход (признаком нормального выхода является нулевой код завершения). Для демонстрации читателю представляем очень простой пример. Логика работы команды cat очень проста и легко восстанавливается. На псевдокоде команду cat можно записать следующим образом: