Я пытаюсь настроить kprobe на системный вызов stat
, чтобы получить некоторую информацию. При проверке /proc/kallsyms
у меня много похожих имен, и я немного смущаюсь, какое из них мне подойдет.
Я пытаюсь найти правильный системный вызов, используемый для получения данных, отображаемых в выводе таких команд, как stat filename
или stat dir
.
Сначала я попробовал __x64_sys_stat
, но мои обработчики не вызываются. Затем я попробовал __do_sys_stat
, __x64_sys_newstat
, но ни один из обработчиков не был вызван.
Ниже приведен вывод /proc/kallsyms
,
user@xubun2204:~$ cat /proc/kallsyms | grep newstat
0000000000000000 t __do_sys_newstat
0000000000000000 T __x64_sys_newstat
0000000000000000 T __ia32_sys_newstat
0000000000000000 t __do_compat_sys_newstat
0000000000000000 T __ia32_compat_sys_newstat
0000000000000000 T __x64_compat_sys_newstat
0000000000000000 d event_exit__newstat
0000000000000000 d event_enter__newstat
0000000000000000 d __syscall_meta__newstat
0000000000000000 d args__newstat
0000000000000000 d types__newstat
0000000000000000 d __event_exit__newstat
0000000000000000 d __event_enter__newstat
0000000000000000 d __p_syscall_meta__newstat
0000000000000000 d _eil_addr___x64_compat_sys_newstat
0000000000000000 d _eil_addr___ia32_compat_sys_newstat
0000000000000000 d _eil_addr___ia32_sys_newstat
0000000000000000 d _eil_addr___x64_sys_newstat
user@xubun2204:~$ cat /proc/kallsyms | grep do_stat
0000000000000000 T proc_do_static_key
0000000000000000 T do_statx
0000000000000000 t do_statfs_native
0000000000000000 t do_statfs64
user@xubun2204:~$ cat /proc/kallsyms | grep sys_stat
0000000000000000 t __do_sys_stat
0000000000000000 T __x64_sys_stat
0000000000000000 T __ia32_sys_stat
0000000000000000 T __x64_sys_statx
0000000000000000 T __ia32_sys_statx
0000000000000000 t __do_sys_statfs
0000000000000000 T __x64_sys_statfs
0000000000000000 T __ia32_sys_statfs
0000000000000000 t __do_sys_statfs64
0000000000000000 T __x64_sys_statfs64
0000000000000000 T __ia32_sys_statfs64
0000000000000000 t __do_compat_sys_statfs
0000000000000000 T __ia32_compat_sys_statfs
0000000000000000 T __x64_compat_sys_statfs
0000000000000000 T kcompat_sys_statfs64
0000000000000000 T __ia32_compat_sys_statfs64
0000000000000000 T __x64_compat_sys_statfs64
0000000000000000 d _eil_addr___ia32_sys_statx
0000000000000000 d _eil_addr___x64_sys_statx
0000000000000000 d _eil_addr___ia32_sys_stat
0000000000000000 d _eil_addr___x64_sys_stat
0000000000000000 d _eil_addr___x64_compat_sys_statfs64
0000000000000000 d _eil_addr___ia32_compat_sys_statfs64
0000000000000000 d _eil_addr___x64_compat_sys_statfs
0000000000000000 d _eil_addr___ia32_compat_sys_statfs
0000000000000000 d _eil_addr___ia32_sys_statfs64
0000000000000000 d _eil_addr___x64_sys_statfs64
0000000000000000 d _eil_addr___ia32_sys_statfs
0000000000000000 d _eil_addr___x64_sys_statfs
Потом я попробовал __x64_sys_statfs
и теперь звонят моим кураторам!
Насколько я понял разницу между sys_stat
и sys_statfs
, sys_stat
используется для получения информации о файлах и каталогах, а sys_statfs
— для получения информации о файловой системе.
Но в этом случае, что бы я ни делал в командной строке stat
(файловая система или конкретный файл или каталог), __x64_sys_statfs
вызывается!
Проблема начинается, когда я хочу прочитать, что возвращает этот системный вызов, следует ли мне ожидать struct kstat
или struct statfs
?
Вот код, с помощью которого мне удается запустить обработчик kretprobe:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/statfs.h>
#include <linux/slab.h>
#include <linux/fs.h>
static struct kretprobe my_kretprobe;
static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
printk("entry_handler\n");
return 0;
}
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
printk("ret_handler\n");
return 0;
}
static int __init my_module_init(void)
{
int ret;
my_kretprobe.kp.symbol_name = "__x64_sys_statfs";
my_kretprobe.entry_handler = entry_handler;
my_kretprobe.handler = ret_handler;
my_kretprobe.maxactive = 20;
ret = register_kretprobe(&my_kretprobe);
if (ret < 0) {
printk(KERN_INFO "register_kretprobe failed, returned %d\n", ret);
return ret;
}
printk(KERN_INFO "Kretprobe registered for __x64_sys_statfs\n");
return 0;
}
static void __exit my_module_exit(void)
{
unregister_kretprobe(&my_kretprobe);
printk(KERN_INFO "Kretprobe unregistered\n");
}
module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jelal");
MODULE_DESCRIPTION("simple kret lkm");
и Makefile,
obj-m += statdata.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Я экспериментирую, и у меня нет какой-либо конечной цели для продукта, единственная цель — получить доступ к данным, отображаемым командой терминала stat из ядра.
sys_stat
, sys_statfs
, sys_newstat
и sys_statx
?Спасибо
Когда вы используете утилиту статистики командной строки, от версии утилиты зависит, использует ли она:
Все они возвращают практически одну и ту же информацию об именованном объекте (statx использует другую структуру) для немного разных программных входных данных, которые инструмент командной строки не предоставляет.
В вашем случае похоже, что statx связан с исправлениями символов для приложения, поэтому, вероятно, на самом деле используется этот API.
Во многих случаях в старых дистрибутивах приложение stat сначала вызывает lstat или sys_newfstatat с флагом NOFOLLOW, поскольку команда stat хочет сообщить, что она увидела ссылку. Определив, что указанный ресурс не является ссылкой, ему не нужно снова вызывать stat, но, возможно, так и было бы, если бы это была ссылка.
ltrace и strace могут быть полезными инструментами для просмотра того, какие библиотечные и системные вызовы на самом деле выполняются приложением.
Обычно вызов динамической библиотеки представляет собой тонкую оболочку вокруг системного вызова, но в случае функций семейства stat точки входа в библиотеку имеют x в начале имени и принимают дополнительный аргумент, определяющий версию stat. структуру, которую ожидает приложение. Реализация динамической библиотеки может преобразовать результат системного вызова в более ранние версии структуры или завершить вызов без выполнения системного вызова, если версия не распознана. Однако я не думаю, что эта функция управления версиями когда-либо действительно использовалась в гневе. Часто к имени вызова библиотеки добавляется 64 для поддержки 32-битных программ, которые использовали 64-битный интерфейс в переходный период, а теперь перекомпилируются как 64-битные программы.
Это все функции статистики.
Кроме того, ОП напоминает мне, что они спрашивали о statfs. StatFS возвращает некоторую «интересную» информацию о файловой системе, обслуживающей этот файл, но не о самом файле.
Программа stat, запускаемая из командной строки, имеет опцию --file-system для отображения этой информации, поэтому вы можете видеть привязку к вызову библиотеки statfs, но по умолчанию она не выполняет вызов и не отображает информацию.
В начале своего ответа вы упомянули несколько случаев, но я не вижу ни одного упоминания о __x64_sys_statfs
. Где этот системный вызов вступает в игру?
sys_stat()
должно быть для системного вызоваstat()
,sys_statfs()
должно быть дляstatfs()
. Они совершенно не связаны друг с другом: один предназначен для информации о файле, другой — для информации о файловой системе.