адреса ядра и приложения
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
адреса ядра и приложения
Пришлось освежить и проверить, в связи с 64-бит системами.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: адреса ядра и приложения
32 бит… Максимальный размер адресного пространства при 32-битных адресах равно 4Gb. В этом режиме в Linux принято решение разделить это адресное пространство между пользователем и ядром в соотношении 3:1. Границу M при этом указывает макрос-указатель current равный по умолчанию c0000000. Это константа периода компиляции, она может быть изменена, но путём пересборки ядра, что может иметь смысл (и имеет место) для некоторых аппаратных архитектур. Понятно, что адреса в приложениях пользователя будут выглядеть ниже этой границы, а адреса выше этой границы будут относится к ядру. Значение этой границы определяется (при сборке ядра) конфигурационным параметром CONFIG_PAGE_OFFSET :
В примере показан реальный вывод в системе с процессором ARM, хотя в более ранней литературе можно встретить утверждение, что границей раздела для ARM является 0x80000000.
Код: Выделить всё
$ uname -a
Linux orangepione 5.15.25-sunxi #22.02.1 SMP Sun Feb 27 09:23:25 UTC 2022 armv7l GNU/Linux
Код: Выделить всё
$ cat /boot/config-`uname -r` | grep CONFIG_PAGE_OFFSET
CONFIG_PAGE_OFFSET=0xC0000000
Код: Выделить всё
olej@orangepione:~$ inxi -Cxxx
CPU: Topology: Quad Core model: ARMv7 v7l variant: cortex-a7 bits: 32 type: MCP arch: v7l
rev: 5
features: Use -f option to see features bogomips: 0
Speed: 1008 MHz min/max: 480/1008 MHz Core speeds (MHz): 1: 1008 2: 1008 3: 1008 4: 1008
Код: Выделить всё
olej@orangepione:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 10 (buster)
Release: 10
Codename: buster
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: адреса ядра и приложения
64 бит… Всё становится гораздо веселее в Linux 64-бит. Прежде всего, когда мы говорим, временами, Intel X86_64 — это неверно, эту 64-бит спецификацию опубликовала в 2000 году фирма AMD, а Intel использует только лицензию AMD. Во-вторых, спецификация предполагает что для адресации используются только 48 (0-47) младших бит из 64, а старшие биты (48-63) расширяются битом 47 … подобно тому как это делается при расширении знакового разряда отрицательных целых. Эта спецификация адреса в сегодняшних процессорах поддерживается аппаратно. Это позволяет планировать лёгкость расширения в будущем до адресов 52, 57 и даже 64 бит (такие цифры называют в планах). В Linux 64-бит разделение виртуальных адресных пространств пользователь-ядро производится поровну, 1:1, по значению бита 47 (1 — ядро, 0 — пользовательский процесс). Поэтому адреса плоского адресного пространства для пользовательских процессов будут выглядеть как [000000000000000 — 00007fffffffffff), а для ядра будут выглядеть как [ffff800000000000 — ffffffffffffffff] (скобки квадратные и круглые в обозначении этих диапазонов означают, как это и принято в математике, «включая» и «исключая», соответственно). Как виртуальные 48-бит адреса затем аппаратно, с помощью MMU, преобразуются в физические адреса реальной памяти, нас на данном этапе не интересует. На интересует как они представляются. В этой модели памяти параметр конфигурации ядра CONFIG_PAGE_OFFSET не определяется — 48-битная граница фиксирована и в переопределении не нуждается:
Код: Выделить всё
$ cat /boot/config-`uname -r` | grep CONFIG_PAGE_OFFSET
$
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: адреса ядра и приложения
Модуль aslr.c :
Приложение intptr.c :
Система:
Вот адреса kernel-space:
Вот адреса user-space:
Там особо интересные значения в 3-й колонке - локальная переменная в стеке - впритык к верхушке user-space рядом с началом kernel-space.
Код: Выделить всё
#include <linux/module.h>
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Oleg Tsiliuric <olej.tsil@gmail.com>>");
static int __init my_init(void) {
uint16_t d = 1234;
void show(void* p) {
printk("%20p%20px%20pK%20lx\n",
p, p, p, (uintptr_t)p);
}
if (IS_ENABLED(CONFIG_64BIT)) {
printk("64-bit");
}
else {
printk("32-bit");
}
printk("%20s%20s%20s%20s\n", "%p", "%px", "%pK", "int");
show(&d);
#if defined(CONFIG_64BIT)
show(printk);
#else
show(_printk);
#endif
show((void*)PAGE_OFFSET);
show((void*)current);
show((void*)0xffff800000000000);
return -2;
}
module_init(my_init);
Код: Выделить всё
#include <stdint.h>
#include <stdio.h>
static uint16_t d1 = 1234;
static uint16_t d2;
int main(void) {
uint16_t d3 = 1234;
printf("%20p%20p%20p\n", &d1, &d2, &d3);
printf("%20lx%20lx%20lx\n",
(uintptr_t)&d1,
(uintptr_t)&d2,
(uintptr_t)&d3);
printf("%20llx%20llx%20llx\n",
(long long unsigned int)&d1,
(long long unsigned int)&d2,
(long long unsigned int)&d3);
return 0;
}
Код: Выделить всё
olej@R420:~/2022/own.BOOKs/BHV.kernel/examples/tools/aslr$ make
make -C /lib/modules/5.4.0-117-generic/build M=/home/olej/2022/own.BOOKs/BHV.kernel/examples/tools/aslr modules
make[1]: вход в каталог «/usr/src/linux-headers-5.4.0-117-generic»
CC [M] /home/olej/2022/own.BOOKs/BHV.kernel/examples/tools/aslr/aslr.o
Building modules, stage 2.
MODPOST 1 modules
CC [M] /home/olej/2022/own.BOOKs/BHV.kernel/examples/tools/aslr/aslr.mod.o
LD [M] /home/olej/2022/own.BOOKs/BHV.kernel/examples/tools/aslr/aslr.ko
make[1]: выход из каталога «/usr/src/linux-headers-5.4.0-117-generic»
gcc -Wall intptr.c -o intptr
Код: Выделить всё
olej@R420:~/2022/own.BOOKs/BHV.kernel/examples/tools/aslr$ uname -a
Linux R420 5.4.0-117-generic #132-Ubuntu SMP Thu Jun 2 00:39:06 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Код: Выделить всё
olej@R420:~/2022/own.BOOKs/BHV.kernel/examples/tools/aslr$ uname -a
Linux R420 5.4.0-117-generic #132-Ubuntu SMP Thu Jun 2 00:39:06 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Код: Выделить всё
olej@R420:~/2022/own.BOOKs/BHV.kernel/examples/tools/aslr$ sudo insmod aslr.ko
[sudo] пароль для olej:
insmod: ERROR: could not insert module aslr.ko: Unknown symbol in module
Код: Выделить всё
olej@R420:~/2022/own.BOOKs/BHV.kernel/examples/tools/aslr$ dmesg | tail -n6
[38452.016709] %p %px %pK int
[38452.016713] b6b126a0 ffffb73546eebc56 ffffb73546eebc56 ffffb73546eebc56
[38452.016714] ab07503d ffffffff8348b926 ffffffff8348b926 ffffffff8348b926
[38452.016715] 9c02798 ffff8eb780000000 ffff8eb780000000 ffff8eb780000000
[38452.016715] c35a2f8a ffff8ec27c651740 ffff8ec27c651740 ffff8ec27c651740
[38452.016716] 75ed937 ffff800000000000 ffff800000000000 ffff800000000000
Код: Выделить всё
olej@R420:~/2022/own.BOOKs/BHV.kernel/examples/tools/aslr$ ./intptr
0x55a350dbf010 0x55a350dbf014 0x7ffd7e3470f6
55a350dbf010 55a350dbf014 7ffd7e3470f6
55a350dbf010 55a350dbf014 7ffd7e3470f6
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: адреса ядра и приложения
32-бит ARM система:
Код: Выделить всё
olej@raspberrypi:~/2022/kernel/examples/tools/aslr $ uname -a
Linux raspberrypi 5.15.32-v7+ #1538 SMP Thu Mar 31 19:38:48 BST 2022 armv7l GNU/Linux
Код: Выделить всё
olej@raspberrypi:~/2022/kernel/examples/tools/aslr $ make
make -C /lib/modules/5.15.32-v7+/build M=/home/olej/2022/kernel/examples/tools/aslr modules
make[1]: вход в каталог «/usr/src/linux-headers-5.15.32-v7+»
CC [M] /home/olej/2022/kernel/examples/tools/aslr/aslr.o
MODPOST /home/olej/2022/kernel/examples/tools/aslr/Module.symvers
CC [M] /home/olej/2022/kernel/examples/tools/aslr/aslr.mod.o
LD [M] /home/olej/2022/kernel/examples/tools/aslr/aslr.ko
make[1]: выход из каталога «/usr/src/linux-headers-5.15.32-v7+»
gcc -Wall intptr.c -o intptr
intptr.c: In function ‘main’:
intptr.c:10:14: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘unsigned int’ [-Wformat=]
10 | printf("%20lx%20lx%20lx\n",
| ~~~~^
| |
| long unsigned int
| %20x
11 | (uintptr_t)&d1,
| ~~~~~~~~~~~~~~
| |
| unsigned int
intptr.c:10:19: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘unsigned int’ [-Wformat=]
10 | printf("%20lx%20lx%20lx\n",
| ~~~~^
| |
| long unsigned int
| %20x
11 | (uintptr_t)&d1,
12 | (uintptr_t)&d2,
| ~~~~~~~~~~~~~~
| |
| unsigned int
intptr.c:10:24: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 4 has type ‘unsigned int’ [-Wformat=]
10 | printf("%20lx%20lx%20lx\n",
| ~~~~^
| |
| long unsigned int
| %20x
......
13 | (uintptr_t)&d3);
| ~~~~~~~~~~~~~~
| |
| unsigned int
intptr.c:15:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
15 | (long long unsigned int)&d1,
| ^
intptr.c:16:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
16 | (long long unsigned int)&d2,
| ^
intptr.c:17:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
17 | (long long unsigned int)&d3);
| ^
Код: Выделить всё
olej@raspberrypi:~/2022/kernel/examples/tools/aslr $ sudo insmod aslr.ko
insmod: ERROR: could not insert module aslr.ko: Unknown symbol in module
Код: Выделить всё
olej@raspberrypi:~/2022/kernel/examples/tools/aslr $ dmesg | grep "%p" -A5
[1223042.115782] %p %px %pK int
[1223042.115805] de7b8fa7 8384fd8a de7b8fa7 8384fd8a
[1223042.115835] c6f80218 80a3df28 c6f80218 80a3df28
[1223042.115853] 1ab82f40 80000000 1ab82f40 80000000
[1223042.115870] c2fe70d 95599f00 c2fe70d 95599f00
[1223042.115888] 0 0 0 0
Код: Выделить всё
olej@raspberrypi:~/2022/kernel/examples/tools/aslr $ ./intptr
0x21028 0x2102c 0x7ee00396
21028 2102c 7ee00396
21028 2102c 7ee00396
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: адреса ядра и приложения
Ещё одна ARM 32-бит система:
Код: Выделить всё
olej@orangepione:~/2022/kernel/examples.tmp/aslr$ uname -a
Linux orangepione 5.15.25-sunxi #22.02.1 SMP Sun Feb 27 09:23:25 UTC 2022 armv7l GNU/Linux
Код: Выделить всё
olej@orangepione:~/2022/kernel/examples.tmp/aslr$ sudo insmod aslr.ko
[sudo] пароль для olej:
insmod: ERROR: could not insert module aslr.ko: Unknown symbol in module
Код: Выделить всё
olej@orangepione:~/2022/kernel/examples.tmp/aslr$ dmesg | tail -n6
[690891.041625] %p %px %pK int
[690891.041638] 682f0a8d c25d1dc2 682f0a8d c25d1dc2
[690891.041657] 6de3fc8a c09c49a1 6de3fc8a c09c49a1
[690891.041666] 6d66c095 c0000000 6d66c095 c0000000
[690891.041675] bfcfa5e2 c438a440 bfcfa5e2 c438a440
[690891.041685] 0 0 0 0
Код: Выделить всё
olej@orangepione:~/2022/kernel/examples.tmp/aslr$ ./intptr
0x501044 0x501048 0xbe9c042e
501044 501048 be9c042e
501044 501048 ffffffffbe9c042e
Код: Выделить всё
olej@orangepione:~/2022/kernel/examples.tmp/aslr$ cat /boot/config-`uname -r` | grep CONFIG_PAGE_OFFSET
CONFIG_PAGE_OFFSET=0xC0000000
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя