адреса имён ядра (ASLR)

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 08 авг 2019, 17:22

Смотрим адреса имён ядра:

Код: Выделить всё

olej@ACER:~$ cat /boot/System.map-`uname -r` | grep ' T ' | grep kmalloc
ffffffff811c3510 T mempool_kmalloc
ffffffff811eefe0 T kmalloc_order
ffffffff811ef010 T kmalloc_order_trace
ffffffff811f0ac0 T kmalloc_slab
ffffffff812362d0 T __kmalloc
ffffffff81236500 T __kmalloc_node
ffffffff81239510 T __kmalloc_track_caller
ffffffff81239720 T __kmalloc_node_track_caller
ffffffff8152c9b0 T devm_kmalloc
ffffffff815bd6e0 T sock_kmalloc
ffffffff82488933 T create_kmalloc_cache
ffffffff82488a18 T setup_kmalloc_cache_index_table
ffffffff82488a1e T create_kmalloc_caches
ffffffff82578e40 T kmalloc_info

Код: Выделить всё

olej@ACER:~$ sudo cat /proc/kallsyms | grep ' T ' | grep kmalloc
[sudo] пароль для olej: 
ffffffff87fc3510 T mempool_kmalloc
ffffffff87feefe0 T kmalloc_order
ffffffff87fef010 T kmalloc_order_trace
ffffffff87ff0ac0 T kmalloc_slab
ffffffff880362d0 T __kmalloc
ffffffff88036500 T __kmalloc_node
ffffffff88039510 T __kmalloc_track_caller
ffffffff88039720 T __kmalloc_node_track_caller
ffffffff8832c9b0 T devm_kmalloc
ffffffff883bd6e0 T sock_kmalloc
ffffffff89288933 T create_kmalloc_cache
ffffffff89288a18 T setup_kmalloc_cache_index_table
ffffffff89288a1e T create_kmalloc_caches
ffffffff89378e40 T kmalloc_info
1-е - это при инсталляции системы.
2-е - это при текущей загрузке.
Раньше такого различия я не видел (32-бит x86 и сильно предыдущие версии ядра)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра

Непрочитанное сообщение Olej » 08 авг 2019, 17:26

Утверждается, что это ASLR (рандомизация размещения адресного пространства).
Если при сборке ядра установлен параметр:

Код: Выделить всё

olej@ACER:~$ cat /boot/config-`uname -r` | grep CONFIG_RANDOMIZE_BASE
CONFIG_RANDOMIZE_BASE=y
На настоящее время, якобы, только базовый адрес может быть рандомизирован.
Причём величина этого сдвига будет меняться при каждой загрузке.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра

Непрочитанное сообщение Olej » 08 авг 2019, 17:30

ASLR
ASLR (англ. address space layout randomization — «рандомизация размещения адресного пространства») — технология, применяемая в операционных системах, при использовании которой случайным образом изменяется расположение в адресном пространстве процесса важных структур данных, а именно образов исполняемого файла, подгружаемых библиотек, кучи и стека.

Технология ASLR создана для усложнения эксплуатации нескольких типов уязвимостей. Например, если при помощи переполнения буфера или другим методом атакующий получит возможность передать управление по произвольному адресу, ему нужно будет угадать, по какому именно адресу расположен стек, куча или другие структуры данных, в которые можно поместить шелл-код. Сходные проблемы возникнут и при атаке типа «возврат в библиотеку» (return-to-libc): атакующему не будет известен адрес, по которому загружена библиотека. В приведённых примерах от атакующего скрыты конкретные адреса, и, если не удастся угадать правильный адрес, приложение скорее всего аварийно завершится, тем самым лишив атакующего возможности повторной атаки и привлекая внимание системного администратора.
Linux
В ядре Linux простой вариант ASLR имеется с 2005 года (с версии 2.6.12). Более сложные и полные варианты ASLR предлагаются в виде патчей (PaX, ExecShield и др.). В дистрибутивах, содержащих в названии слово «hardened», а также в современных версиях дистрибутива Ubuntu, сильные варианты включены по умолчанию.

Для работы ASLR (для размещения исполняемых файлов в памяти по случайным адресам) исполняемые файлы должны быть скомпилированы в режиме position-independent executable (разновидность позиционно-независимого кода для исполняемых файлов).

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 11 авг 2019, 14:01

Очень детальный разбор ALSR в Национальной библиотеке им. Н. Э. Баумана - ASLR (Address Space Layout Randomization)
Последнее изменение этой страницы: 22:22, 4 мая 2017.
Правда, это в основном на примерах Windows, но принципы понятны.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 11 авг 2019, 23:47

Olej писал(а):

Код: Выделить всё

ffffffff811c3510 T mempool_kmalloc

Код: Выделить всё

ffffffff87fc3510 T mempool_kmalloc
ffffffff87fc3510−ffffffff811c3510=6E00000
Olej писал(а):

Код: Выделить всё

ffffffff89378e40 T kmalloc_info

Код: Выделить всё

ffffffff82578e40 T kmalloc_info
ffffffff89378e40−ffffffff82578e40=6E00000

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 11 авг 2019, 23:53

Тема эта возникла из-за одной "мелочи", которую я не могу пока понять...
- когда загружается модуль ядра Linux, то он связывается с именем ядра по абсолютному адресу имени...
- без ASLR это элементарно просто и понятно
- но с ASLR все адреса имён должны быть скорректированы на фиксированную величину (+6E00000 в примере выше)
- и это смещение меняется при каждой перезагрузке системы...
- каким механизмом и в какой момент это происходит?

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 31 окт 2019, 18:09

Ещё раз... 3 подряд последовательные перезагрузки системы - для 2-х разных имён ядра выбранных наугад:
1. Первый раз:

Код: Выделить всё

olej@ACER:~$ cat /boot/System.map-`uname -r` | grep ' T ' | grep kmalloc_info
ffffffff8257d7a0 T kmalloc_info

olej@ACER:~$ sudo cat /proc/kallsyms | grep ' T ' | grep kmalloc_info
ffffffffb957d7a0 T kmalloc_info
ffffffffb957d7a0−ffffffff8257d7a0 = 37000000

Код: Выделить всё

olej@ACER:~$ cat /boot/System.map-`uname -r` | grep ' T ' | grep mempool_kmalloc
ffffffff811c5f40 T mempool_kmalloc

olej@ACER:~$ sudo cat /proc/kallsyms | grep ' T ' | grep mempool_kmalloc
ffffffffb81c5f40 T mempool_kmalloc
ffffffffb81c5f40−ffffffff811c5f40 = 37000000
Все динамические имена ядра смещаются (в сторону увеличения) относительно статических адресов /boot/System.map на одну и ту же фиксированную величину 0x37000000

2. Перезагрузка...

Код: Выделить всё

olej@ACER:~/2019_WORK/HISTORY/10/31$ cat /boot/System.map-`uname -r` | grep ' T ' | grep kmalloc_info
ffffffff8257d7a0 T kmalloc_info

olej@ACER:~/2019_WORK/HISTORY/10/31$ sudo cat /proc/kallsyms | grep ' T ' | grep kmalloc_info
[sudo] пароль для olej: 
ffffffff8677d7a0 T kmalloc_info
ffffffff8677d7a0−ffffffff8257d7a0 = 4200000

Код: Выделить всё

olej@ACER:~/2019_WORK/HISTORY/10/31$ cat /boot/System.map-`uname -r` | grep ' T ' | grep mempool_kmalloc
ffffffff811c5f40 T mempool_kmalloc

olej@ACER:~/2019_WORK/HISTORY/10/31$ sudo cat /proc/kallsyms | grep ' T ' | grep mempool_kmalloc
ffffffff853c5f40 T mempool_kmalloc
ffffffff853c5f40−ffffffff811c5f40 = 4200000
Опять же, все динамические имена ядра смещаются относительно статических адресов /boot/System.map на одну и ту же, но совсем другую величину 0x4200000
Обращаем внимание на то, что адреса /boot/System.map сохраняются от раза к разу, что естественно - это статическое содержимое дискового файла, формировавшегося при сборке ядра.

3. Ещё перезагрузка...

Код: Выделить всё

olej@ACER:~/2019_WORK/HISTORY/10/31$ cat /boot/System.map-`uname -r` | grep ' T ' | grep kmalloc_info
ffffffff8257d7a0 T kmalloc_info

olej@ACER:~/2019_WORK/HISTORY/10/31$ sudo cat /proc/kallsyms | grep ' T ' | grep kmalloc_info
[sudo] пароль для olej: 
ffffffff82b7d7a0 T kmalloc_info
ffffffff82b7d7a0−ffffffff8257d7a0 = 600000

Код: Выделить всё

olej@ACER:~/2019_WORK/HISTORY/10/31$ cat /boot/System.map-`uname -r` | grep ' T ' | grep mempool_kmalloc
ffffffff811c5f40 T mempool_kmalloc

olej@ACER:~/2019_WORK/HISTORY/10/31$ sudo cat /proc/kallsyms | grep ' T ' | grep mempool_kmalloc
ffffffff817c5f40 T mempool_kmalloc
ffffffff817c5f40−ffffffff811c5f40 = 600000
Снова поменялось смещение динамических имен ядра относительно статических адресов /boot/System.map на совсем другую величину 0x600000

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 31 окт 2019, 20:43

Этот механизм ASLR (address space layout randomization) включается конфигурационным параметром ядра CONFIG_RANDOMIZE_BASE.
Который во многих дистрибутивах по умолчанию, с некоторых пор, включен:

Код: Выделить всё

olej@ACER:~/2019_WORK/ACCOUNTS/MAIL$ lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

olej@ACER:~/2019_WORK/ACCOUNTS/MAIL$ cat /boot/config-`uname -r` | grep CONFIG_RANDOMIZE_BASE
CONFIG_RANDOMIZE_BASE=y

Код: Выделить всё

[olej@DELL ~]$ lsb_release -a
LSB Version:	:core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID:	Fedora
Description:	Fedora release 30 (Thirty)
Release:	30
Codename:	Thirty

[olej@DELL ~]$ cat /boot/config-`uname -r` | grep CONFIG_RANDOMIZE_BASE
CONFIG_RANDOMIZE_BASE=y

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 31 окт 2019, 21:44

Olej писал(а):
11 авг 2019, 23:53
Тема эта возникла из-за одной "мелочи", которую я не могу пока понять...
- когда загружается модуль ядра Linux, то он связывается с именем ядра по абсолютному адресу имени...
- без ASLR это элементарно просто и понятно
- но с ASLR все адреса имён должны быть скорректированы на фиксированную величину (+6E00000 в примере выше)
- и это смещение меняется при каждой перезагрузке системы...
- каким механизмом и в какой момент это происходит?
Смотрю модуль ядра, который собирался рамках курса "Модули ядра Linux" (см. Драйверы и модули ядра Linux), любой первый попавшийся - это здесь не имеет значения:

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/KPI/dev/cdev$ nm -n fixdev.ko 
                 U alloc_chrdev_region
                 U cdev_add
                 U cdev_del
                 U cdev_init
                 U _copy_to_user
                 U __fentry__
                 U param_ops_int
                 U printk
                 U register_chrdev_region
                 U __stack_chk_fail
                 U unregister_chrdev_region
                 U __warn_printk
0000000000000000 T cleanup_module
0000000000000000 t copy_overflow
0000000000000000 t dev_exit
0000000000000000 r dev_fops
0000000000000000 t dev_init
0000000000000000 t dev_open
0000000000000000 b hcdev
0000000000000000 T init_module
0000000000000000 r .LC1
0000000000000000 r _note_6
0000000000000000 r __param_major
0000000000000000 D __this_module
0000000000000000 r __UNIQUE_ID_majortype34
0000000000000000 r ____versions
0000000000000013 r __UNIQUE_ID_version33
0000000000000014 t dev_read.cold.0
000000000000001f r __UNIQUE_ID_author32
0000000000000020 t dev_release
0000000000000030 t dev_read
0000000000000045 r __UNIQUE_ID_license31
0000000000000058 r __UNIQUE_ID_srcversion23
0000000000000068 b device_open
000000000000006c b major
0000000000000080 r __module_depends
0000000000000089 r __UNIQUE_ID_retpoline22
0000000000000095 r __UNIQUE_ID_name21
00000000000000a1 r __UNIQUE_ID_vermagic20
0000000000000108 r __param_str_major

Это объектный модуль (по формату - формат объектного файла), и связываемые с ним имена ядра отмечены как U (UNDEFINED по адресу):

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/KPI/dev/cdev$ cat /boot/System.map-`uname -r` | grep ' T ' | grep cdev_
ffffffff81267860 T cdev_set_parent
ffffffff81267910 T cdev_add
ffffffff81267960 T cdev_del
ffffffff812679c0 T cdev_device_add
ffffffff81267a30 T cdev_device_del
ffffffff81267a60 T cdev_init
ffffffff81267ae0 T cdev_alloc
ffffffff81268220 T cdev_put
ffffffff8158f1e0 T thermal_cdev_update

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/KPI/dev/cdev$ sudo cat /proc/kallsyms | grep ' T ' | grep cdev_
ffffffff81867860 T cdev_set_parent
ffffffff81867910 T cdev_add
ffffffff81867960 T cdev_del
ffffffff818679c0 T cdev_device_add
ffffffff81867a30 T cdev_device_del
ffffffff81867a60 T cdev_init
ffffffff81867ae0 T cdev_alloc
ffffffff81868220 T cdev_put
ffffffff81b8f1e0 T thermal_cdev_update
Неверно в цитируемых фразах утверждение о связывании по абсолютным адресам, адреса связываются точно так же, как адреса объектного файла линкером GCC.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: адреса имён ядра (ASLR)

Непрочитанное сообщение Olej » 30 окт 2021, 00:38

Olej писал(а):
31 окт 2019, 18:09
Все динамические имена ядра смещаются (в сторону увеличения) относительно статических адресов /boot/System.map на одну и ту же фиксированную величину 0x37000000
Насколько я понимаю (предполагаю) это случайное смещение даёт вызов API ядра kaslr_get_random_long :

Код: Выделить всё

root@R420:/proc# cat kallsyms | grep -i ASLR
ffffffffb28775d0 T kaslr_get_random_long
ffffffffb343d460 d module_kaslr_mutex
ffffffffb381ffe0 t kaslr_regions
Эта функция определяется https://github.com/torvalds/linux/blob/ ... ib/kaslr.c (цифру версии ядра подставьте в URL интересующую):

Код: Выделить всё

unsigned long kaslr_get_random_long(const char *purpose)
{
#ifdef CONFIG_X86_64
    const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
#else
    const unsigned long mix_const = 0x3f39e593UL;
#endif
...
    debug_putstr(purpose);
    debug_putstr(" KASLR using");
...
    return random;
}
В комментариях там описано:
Функции энтропии, используемые при ранней загрузке для рандомизации базы KASLR и памяти. Базовая рандомизация выполняется в сжатом ядре, а рандомизация памяти выполняется раньше, когда запускается обычное ядро. Этот файл включен в сжатое ядро и обычно связан с обычным.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 5 гостей