Почитал я доку по systemtap. Непростая штука.
Насколько я понимаю надо писать что-то вроде:
probe kernel.function("kfree").return {
// Print memory pages here
}
Непонятно как прочитать страницу, что бы вывести ее содержимое.
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 ещё патчить придётся.
У меня не работает скрипт из-за того, что _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
$ 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 есть. Какая версия ядра?
В общем, вот что у меня получилось. Смутило то, что один раз подвисло ядро. Может оно временно, я ждать не стал - перезагрузился. =)
#!/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");
}
}
}
Меня вот что смущает, probe kernel.function выполнится ведь до того как выполнится сама function. То есть по идеи и при grsecurity странички будут приходить как грязные. Или это не так?