
Насколько я понимаю, программы пользовательского пространства работают в непривилегированном режиме и, таким образом, не имеют прямого доступа к памяти или вводу-выводу.
Тогда как именно мы можем напрямую получить доступ к памяти или ячейкам ввода-вывода, когда мы выполняем 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
не будучи в привилегированном режиме, независимо от того, где в оперативной памяти этот виртуальный адрес сопоставлен