Джон Хэслэм с sunblogs предлагает тройку D-скриптов, которые могут быть полезны в практике. Первый позволяет следить за размером файла (файл должен лежать в ufs-партиции) - наверняка у многих возникала подобная задача, DTrace справляется с этим блестяще:
#!/usr/sbin/dtrace -s
#pragma D option quiet
BEGIN
{
size = 0;
}
/* wrip does the real work for a ufs write. The first argument is a struct inode* so
we can extract everything we need (vnode, size) from this */
fbt::wrip:entry
/(self->file = stringof(args[0]->i_vnode->v_path)) == $$1 /
{
self->inode = args[0];
}
/* If the file in question has changed size tell us */
fbt::wrip:return
/self->inode && size != self->inode->i_ic.ic_lsize/
{
printf("File %s changed size: size = %d\n",
self->file, self->inode->i_ic.ic_lsize);
size = self->inode->i_ic.ic_lsize;
self->inode = 0;
self->file = 0;
}
fbt::wrip:return
/self->inode && size == self->inode->i_ic.ic_lsize/
{
self->inode = 0;
self->file = 0;
}
Тестируем:
# ./file.d /var/tmp/bigfile
File /var/tmp/bigfile changed size: size = 132120576
File /var/tmp/bigfile changed size: size = 133169152
File /var/tmp/bigfile changed size: size = 134217728
File /var/tmp/bigfile changed size: size = 134712950
Второй маленький скрипт позволяет следить за обращениями к заданному файлу (пусть это будет /etc/passwd), сообщает uid и пресекает попытки:
#!/usr/sbin/dtrace -ws
ufs_read:entry
/ stringof(args[0]->v_path) == $$1 /
{
printf("File %s read by %d\n", $$1, curpsinfo->pr_uid);
raise(SIGKILL);
}
Запускаем в одном терминале скрипт, в другом пытаемся прочесть файл паролей:
Скрипт выводит инфо и убивает процесс more:
dtrace# ./read.d /etc/passwd: script './read.d' matched 1 probe
dtrace: allowing destructive actions
CPU ID FUNCTION:NAME
0 15625 ufs_read:entry File /etc/passwd read by 100
Третий скрипт сообщает о запуске setuid-программ пользователем:
#!/usr/sbin/dtrace -s
#pragma D option quiet
inline int PRIV_SETUGID = 0x04;
execsetid:entry
{
self->file = stringof(args[0]->v_path);
}
execsetid:return
/ (self->file != NULL) && (args[1] & PRIV_SETUGID) &&
(curpsinfo->pr_gid != $1 || curpsinfo->pr_egid != $1) /
{
printf("setuid/setgid file %s executed by uid %d\n", self->file,
curpsinfo->pr_uid);
self->file = 0;
}
Также запускаем скрипт в одном окне, а в другом - различные программы:
# ./group.d 14
setuid/setgid file /usr/bin/su executed by uid 100
setuid/setgid file /usr/sbin/../lib/fs/ufs/quota executed by uid 30079
setuid/setgid file /usr/bin/mail executed by uid 30079
Еще раз убеждаемся в том, что с помощью DTrace при желании можно решить любую задачу.