Как работает mmaping /dev/mem, несмотря на то, что он находится в непривилегированном режиме?

Как работает mmaping /dev/mem, несмотря на то, что он находится в непривилегированном режиме?

Насколько я понимаю, программы пользовательского пространства работают в непривилегированном режиме и, таким образом, не имеют прямого доступа к памяти или вводу-выводу.

Тогда как именно мы можем напрямую получить доступ к памяти или ячейкам ввода-вывода, когда мы выполняем mmap /dev/mem в программах пользовательского пространства?

Например:

int fd = 0;
u8 leds = 0;
fd = open("/dev/mem", O_RDWR|O_SYNC);
leds = (u8 *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80840000);

Этот прием очень часто используется во встраиваемых устройствах.

Теперь переменную ledsможно использовать «на лету» для доступа к любому устройству, которое может присутствовать по адресу 0x80840000.

Мы больше не будем использовать системные вызовы для доступа к этому адресу.

Даже что-то вроде

leds[0x20] = val;

должно сработать.

Однако привилегированные операции, такие как чтение/запись непосредственно на адрес ввода-вывода/с него, должны быть возможны только путем перевода процессора в привилегированный режим с помощью системного вызова.

Источник.

решение1

Разрешение доступа /dev/memнепривилегированным процессам действительно представляет собой проблему безопасности и не должно допускаться.

В моей системе ls -l /dev/memэто выглядит так:

crw-r----- 1 root kmem 1, 1 Sep  8 10:12 /dev/mem

So rootможет читать и писать, члены группы kmem(которых, как оказалось, нет) могут читать, но не писать, а все остальные вообще не могут его открыть. Так что это должно быть безопасно.

Если у вас /dev/memчто-то похожее на мое, то ваш непривилегированный процесс вообще не должен был иметь возможности открыть файл, не говоря уже о mmapнем.

Проверьте разрешения /dev/memв вашей системе, чтобы убедиться, что они безопасны!

решение2

Адреса, видимые пользовательскому процессу (независимо от того, запущен ли он как root или как непривилегированный пользователь), являются виртуальными адресами, которые сопоставляются с физическими адресами MMU через таблицы страниц. Настройка таблиц страниц является привилегированной операцией и может быть выполнена только кодом ядра; однако после настройки таблиц страниц доступ к памяти разрешен в пользовательском режиме.

Конкретно, ваш код использует mmapдля запроса, чтобы ядро ​​установило таблицы страниц для разрешения доступа к заданному диапазону физической памяти. Ядро проверяет привилегии процесса (у него есть доступ на чтение/запись к /dev/mem) и устанавливает таблицы страниц для разрешения доступа к физической памяти.

решение3

Значение leds— это виртуальный адрес. Пока он находится в пользовательском пространстве текущего процесса, процесс может получить к нему прямой доступ с помощью инструкций типа , leds[0] = valне будучи в привилегированном режиме, независимо от того, где в оперативной памяти этот виртуальный адрес сопоставлен

Связанный контент