LINUX.ORG.RU

модификация памяти ядра


0

0

Столкнулся с необходимостью модификации памяти в ядре. Для этого написал маленький модуль ядра, который должен править. Проблема в том, что попытка записи проваливается: BUG: unable to handle kernel paging request at хххххххх. И остальные Oops. Есть мысль, что проблема связана с тем, что у этой страницы памяти не установлен атрибут записи. Нашел функцию mprotect, но судя по всему ей можно пользоваться только из пользовательского пространства.Как быть? Чем воспользоваться, чтобы все-таки записать по этому адресу? Причем память по этому адресу точно существует - я ее без проблем могу читать.

Кусок из работающего systemtap-скрипта (это в сишном %{ %} блоке, в guru-режиме):

unsigned char *u_ptr = 0, *k_ptr, *old_ptr;
struct vm_area_struct* vma = current->mm->mmap;
unsigned char c = 0xaa;
unsigned char *addr;
while (vma) {
	prot = (unsigned long)vma->vm_page_prot.pgprot;
	addr = (unsigned char*)vma->vm_end - PAGE_SIZE;
	printk("-- start %p, end %p, prot 0x%lx, RW(%lu)\n",
	       (void*)vma->vm_start, (void*)vma->vm_end,
	       prot, prot & 2);
	if (addr < (unsigned char*)TASK_SIZE3264) {
// cross fingers and try to set read-write access to the page
		sys_mprotect((long)addr, PAGE_SIZE, 3);
		if (!__get_user_nocheck(c, addr, 1)
		    && !__put_user_nocheck(c, addr, 1)) {
			u_ptr = addr;
			break;
		}
		printk("oops, can't use it\n");
	}
	vma = vma->vm_next;
}
if (!u_ptr) {
	printk("can't find good page in userspace\n");
	goto exit__;
} else {
	printk("use page at %p (%x) for testing\n", u_ptr, c);
}

...

sys_mprotect((long)u_ptr, PAGE_SIZE, prot);

mv ★★★★★
()
Ответ на: комментарий от mv

попробовал использовать sys_mprotect несмотря на некоторое подозрение, что это системный вызов. Все скомпилилось, но модуль не грузится из-за того, что " Unknown symbol in module". Хотя, может, я что-то сделал не так.

codergeneration
() автор топика
Ответ на: комментарий от codergeneration

Всё так, sys_mprotect не экспортится. Я его адрес ищу в System.map и
потом sed'ом подставляю в прототип функции:

Makefile:
...
SYSMAP=/boot/System.map-`uname -r`
SYS_MPROTECT=$(firstword $(shell grep sys_mprotect $(SYSMAP)))

prep:
        cat copy.gen sed s#_SYS_MPROTECT_#0x$(SYS_MPROTECT)# > copy.stp
...

Болванка:
...
long (*sys_mprotect)(unsigned long, size_t, unsigned long) = (void*)_SYS_MPROTECT_;
...

Правильнее, конечно, сделать, как rei3er советует (это не сложно, btw),
но у меня всё равно уже пачка функций, не доступных модулям, таким 
образом доставалась, так что добавил и sys_mprotect :)

mv ★★★★★
()
Ответ на: комментарий от mv

у меня уже есть код, возвращающий адрес sct. Только вот я где-то читал, что могут возникнуть проблемы при таком использовании системных вызовов - они полагаются на то, что адреса, передаваемые им, из пространства пользователя. А тут вообще интересная ситуация получается: вряд ли функция, предназначенная для вызова из пространства пользователя умеет менять атрибуты страниц пространства ядра. Так что продолжаю эксперименты:)

codergeneration
() автор топика
Ответ на: комментарий от codergeneration

sys_mprotect работает с current->mm, поэтому кернельный тред что угодно поменять может.

mv ★★★★★
()
Ответ на: комментарий от codergeneration

Так, а ты чью память меняешь? Чужого процесса? Тогда доставай физический адрес и мапь его себе.

mv ★★★★★
()
Ответ на: комментарий от mv

я все ковыряюсь с примером по перехвату функций. Не получается никак. Мне тут подсказали, что можно попробовать сбросить бит wp в cr0 - тут опять не получается: asm вставка не видит сишной переменной, когда я пытаюсь забэкапить старое значение cr0. В общем, полный букет.

codergeneration
() автор топика
Ответ на: комментарий от mv

Спасибо за функции! Эта часть кода заработала. Хотя про синтаксис асам все равно надо почитать для общего развития на будущее.

codergeneration
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.