LINUX.ORG.RU

Ответ на: комментарий от Boy_from_Jungle

Проблема как обратится к памяти, которую ранее занимал убитый процесс из другого процесса.

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

Сесть systemtap'ом на функцию kfree у SLAB/SLUB/SLOB (что там у тебя в системе используется), проверять, что страницы чистые возвращаются.

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

Почитал я доку по systemtap. Непростая штука.

Насколько я понимаю надо писать что-то вроде:

probe kernel.function("kfree").return {
    // Print memory pages here
}

Непонятно как прочитать страницу, что бы вывести ее содержимое.

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

function test:long(ptr:long)
%{
	THIS->__retvalue = (long)memchr((void*)THIS->ptr, 0, PAGE_SIZE);
%}

probe kernel.function("kfree")
{

	if (execname() == "test" && $x) {
		printf("%p: ", $x);
		if (!test($x)) {
			println("ok");
		} else {
			println("bad");
		}
	}
}

sudo stap -vvg kfree.stp

У меня при выходе произвольного test выводит что-то типа

0xffff88006f8ede00: bad
0xffff88006fd1d800: bad
0xffff88006f8ed600: bad
0xffff880031a95600: bad
0xffff88004c881100: bad
0xffff88007689f3d0: bad
0xffff880073ac3800: bad
0xffff88004c8e1ae0: bad
0xffff88007689f940: bad
0xffff88007689f3f0: bad

В kfree попадают только кернельные странички. Может быть, slab_free ещё патчить придётся.

mv ★★★★★
()

А если попробывать наблюдать за определённым процессом, а после его завершения сразу же дополнительно занулять (vm_end-vm_start)?!

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

> Так, ничего больше патчить не нужно, вроде. Но и на kfree садиться бесполезно.

А точно проблема не в том, что в твоем коде ты сел на вход в kfree, а не на выход.

Вот так оно не буде работать: probe kernel.function("kfree").return {}?

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

А ты уверен, что код с memchr правильный? Если нашли нулевой байт - это разве значит, что bad? Или я совсем уже заработался?...

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

Да дело даже не в том, что код с memchr неправильный, а в том, что садиться на kfree для твоей задачи вообще неправильно.

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

Нет, не поздно.

В общем, как-то так:

%{
#include <linux/highmem.h>
%}

function check:long(page:long)
%{
	struct page *page = (struct page*)THIS->page;
	unsigned char *ptr = (unsigned char*)kmap(page);
	if (ptr) {
		int i;
		long sum = 0;
		for (i = 0; ptr && i < PAGE_SIZE; i++)
			sum += (long)ptr[i];
		THIS->__retvalue = sum;
	} else {
		THIS->__retvalue = -1;
	}
	kunmap(page);
%}

probe kernel.function("get_user_pages")
{
	if (execname() == "test") {
		printf("gup: start %p, len %d (%s)\n", $start, $len, kernel_string($tsk->comm));
	}
}

probe kernel.function("mmap_region")
{
	if (execname() == "test") {
		printf("mmap-region at %p, len %d\n", $addr, $len);
	}
}

probe kernel.function("make_pages_present")
{
	if (execname() == "test") {
		printf("make_pages_present %p-%p\n", $addr, $end);
	}
}

probe kernel.function("__free_one_page")
{
	if (execname() == "test") {
		printf("free_one_page %p %d: ", $page, $order);
		ret = check($page);
		if (!ret) {
			println("clean");
		} else if (ret == -1) {
			println("error");
		} else {
			printf("dirty %x\n", ret);
		}
	}
}

test.c:

#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

int main()
{
	char* mem;
	int sz = 1024 * getpagesize();
	mem = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_POPULATE |
		   MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
	if (mem == MAP_FAILED) {
		printf("mmap failed (%s)\n", strerror(errno));
		return 1;
	}
	memset(mem, 1, sz);
	printf("mmaped ok\n");
	return 0;
}

grep -c dirty\ 1000 говорит порядка 865. Куда остальные делись - точно хз, но ядро если живые странички у процесса отбирает, то само их чистит.

На ядре с наложенным grsecurity, по-идее, всё должно чистым быть (после sanitize).

В общем, я в кернельном memory management не специалист, как смог, помог.

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

Огромное спасибо! Буду разбираться.

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

> На ядре с наложенным grsecurity, по-идее, всё должно чистым быть (после sanitize).

Похоже на то. Насколько я понял sanitize делается как раз в free_one_page до __free_one_page.

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

У меня не работает скрипт из-за того, что _free_one_page - inline. Не может найти $page.

Подскажи какой версии у тебя systemtap и с какими опциями он был собран, а так же какая версия gcc.

У меня:

dmitry@dmitry-laptop:~/Desktop$ stap -V
SystemTap translator/driver (version 0.8/0.131 non-git sources)
Copyright (C) 2005-2009 Red Hat, Inc. and others
This is free software; see the source for copying conditions.

dmitry@dmitry-laptop:~/Desktop$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.3-5ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4) 


Запускаю так: /usr/bin/stap -vvvg

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

$ rpm -qi systemtap
Name        : systemtap                    Relocations: (not relocatable)
Version     : 0.9.9                             Vendor: Fedora Project
Release     : 2.fc11                        Build Date: Wed 05 Aug 2009 06:10:57 AM CEST
Install Date: Sat 08 Aug 2009 02:07:25 PM CEST      Build Host: x86-6.fedora.phx.redhat.com
Group       : Development/System            Source RPM: systemtap-0.9.9-2.fc11.src.rpm
Size        : 4447549                          License: GPLv2+
Signature   : RSA/SHA1, Thu 06 Aug 2009 03:52:45 PM CEST, Key ID 1dc5c758d22e77f2
Packager    : Fedora Project
URL         : http://sourceware.org/systemtap/
Summary     : Instrumentation System
Description :
SystemTap is an instrumentation system for systems running Linux 2.6.
Developers can write instrumentation to collect data on the operation
of the system.

$ uname -r
2.6.29.6-217.2.3.fc11.x86_64

На инлайновых функциях в stap аргументы и .return не вычисляются. Можно сесть хоть на что, где ещё спинлок zone->lock держится и доступ к struct page есть. Какая версия ядра?

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

Попробуй в probe на free_one_page запомнить page в глобальной переменной, во _free_one_page используй её вместо недоступного параметра. Примерно:

global page = 0

probe kernel.function("free_one_page")
{
    if (execname....) {
         page = $page
    ....
}

probe kernel.function("__free_one_page")
{
    if (page && execname....) {
         // check, etc
        page = 0;
    }
}

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

У меня probe free_one_page не находит.

Хочу попробовать на free_pages_bulk и попытаться проитерировать по list_head.

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

В общем, вот что у меня получилось. Смутило то, что один раз подвисло ядро. Может оно временно, я ждать не стал - перезагрузился. =)

#!/usr/bin/stap -vvvg

%{
#include <linux/highmem.h>
%}

function check_pages_bulk:long(bulk:long, count:long)
%{
    struct list_head *list = (struct list_head*)(long)THIS->bulk;
    struct page *page;
    unsigned char *page_data;
  	
  	/*
  	 * Iterate over all pages in the list.
  	 */
  	while (THIS->count--) {
  	    /*
  	     * Kernel staff to get single page from a list of pages.
  	     */
		page = list_entry(list->prev, struct page, lru);

        /*
         * Read page bytes and sum them to check if all of them are zero.
         * Thanks to mv from linux.org.ru.
         */		
    	page_data = (unsigned char*)kmap(page);
    	
    	if (page_data) {
    		long sum = 0;
    		int i;
    		for (i = 0; page_data && i < PAGE_SIZE; i++) {
    			sum += (long)page_data[i];
    	    }
			
			/*
			 * If sum is not zero, then there was non zero bytes 
			 * and page is dirty.
			 */
			if (sum != 0) {
			    THIS->__retvalue = (long)page;
			    kunmap(page);
			    break;
			}
    	} else {
    		THIS->__retvalue = -1;
        	kunmap(page);
        	break;
    	}
	
    	kunmap(page);
	}
%}

probe kernel.function( "get_user_pages" ) {
	if (execname() == "test") {
		printf( "get_user_pages: start %p, len %d (%s)\n", 
		         $start, $len, kernel_string( $tsk->comm ) )
	}
}

probe kernel.function( "mmap_region" ) {
	if (execname() == "test") {
		printf( "mmap-region at %p, len %d\n", $addr, $len )
	}
}

probe kernel.function( "make_pages_present" ) {
	if (execname() == "test") {
		printf( "make_pages_present %p-%p\n", $addr, $end )
	}
}

probe kernel.function( "free_pages_bulk" ) {
	if (execname() == "test") {
		printf("free_pages_bulk %p: ", $list)
		result = check_pages_bulk( $list, $count )
        if (result) {
            printf("dirty\n");
  		    printf( "    page: %x\n", result );
   		} else if (result == 0) {
            printf("clean\n");
        } else {
            printf("error\n");
        }
	}
}

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

Взял, пока не виснет.

Меня вот что смущает, probe kernel.function выполнится ведь до того как выполнится сама function. То есть по идеи и при grsecurity странички будут приходить как грязные. Или это не так?

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

Ну если брейкпойнт поставил в том место, где странички ещё не sanitize'лись, то да, будут грязными.

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