Systemtap - вызов системного вызова из пространства ядра

Я пытаюсь создать жесткую ссылку, вызывая sys_link напрямую из кода Systemtap Embedded C. По сути, код выглядит так:

function sys_link:long(oldname, newname) %{  /* pure */
    int error;
    mm_segment_t old_fs;

    old_fs = get_fs();
    set_fs(get_ds());

    error = psys_link(STAP_ARG_oldname, STAP_ARG_newname);

    set_fs(old_fs);

    STAP_RETURN(error);
%}

sys_link не экспортируется ядром, поэтому psys_link разрешается с помощью kallsyms_lookup_name() при инициализации, и я могу проверить, что адрес разрешен правильно. Кажется, системный вызов вызывается, но он никогда не возвращается.

* Я ЗНАЮ, что это не лучшая идея вызывать системные вызовы из пространства ядра, но поверьте мне, мне нужно сделать это;) *

С другой стороны, я провел еще один более простой тест, вызвав filp_open, который экспортируется ядром, и это даже не системный вызов, а просто функция ядра, чтобы создать файл с такими же неудачными результатами:

function myopen:long(newname) %{  /* pure */
    struct file *file;
    mm_segment_t old_fs = get_fs();

    set_fs(get_ds());

    file = filp_open(STAP_ARG_newname, O_WRONLY|O_CREAT, 0644);

    set_fs(old_fs);

    STAP_RETURN(1);
%}

Любая подсказка, почему ядро ​​замерзает?

ОБНОВЛЕНИЕ: системный вызов и функция вызываются в контексте проверки syscall.open.return. Как обсуждалось в одном из комментариев, зонды возврата Systemtap реализованы с использованием kretprobe... который заменяет адрес возврата функции для батута... что AFAIU означает, что процедура syscall уже завершена, и это должно было снять любую блокировку, связанную с сама файловая система, но я, вероятно, что-то упустил.

Отладка ядра в этот момент дает мне следующую трассировку. По-видимому, тупик находится в блокировке kprobe.

>>> info threads
  Id   Target Id         Frame 
* 1    Thread 1 (CPU#0 [running]) __loop_delay () at arch/arm/lib/delay-loop.S:42
  2    Thread 2 (CPU#1 [running]) __loop_delay () at arch/arm/lib/delay-loop.S:42
  3    Thread 3 (CPU#2 [running]) __loop_delay () at arch/arm/lib/delay-loop.S:42
  4    Thread 4 (CPU#3 [running]) arch_spin_lock (lock=<optimised out>) at ./arch/arm/include/asm/spinlock.h:91

>>> thread 4
[Switching to thread 4 (Thread 4)]
#0  arch_spin_lock (lock=<optimised out>) at ./arch/arm/include/asm/spinlock.h:91
91          wfe();

>>> bt
#0  arch_spin_lock (lock=<optimised out>) at ./arch/arm/include/asm/spinlock.h:91
#1  do_raw_spin_lock_flags (flags=<optimised out>, lock=<optimised out>) at ./include/linux/spinlock.h:155
#2  __raw_spin_lock_irqsave (lock=<optimised out>) at ./include/linux/spinlock_api_smp.h:121
#3  _raw_spin_lock_irqsave (lock=0xc1541f80 <kretprobe_table_locks+2240>) at kernel/locking/spinlock.c:159
#4  0xc0412d18 in kretprobe_table_lock (flags=<optimised out>, hash=<optimised out>) at kernel/kprobes.c:1113
#5  kprobe_flush_task (tk=0xed165b00) at kernel/kprobes.c:1158
#6  0xc03814f8 in finish_task_switch (prev=0xed165b00) at kernel/sched/core.c:2783
#7  0xc0c19c38 in context_switch (cookie=..., next=<optimised out>, prev=<optimised out>, rq=<optimised out>) at kernel/sched/core.c:2902
#8  __schedule (preempt=<optimised out>) at kernel/sched/core.c:3402
#9  0xc0c1a1a4 in schedule () at kernel/sched/core.c:3457
#10 0xc0c1a54c in schedule_preempt_disabled () at kernel/sched/core.c:3490
#11 0xc03a23dc in cpu_idle_loop () at kernel/sched/idle.c:273
#12 cpu_startup_entry (state=<optimised out>) at kernel/sched/idle.c:302
#13 0xc031206c in secondary_start_kernel () at arch/arm/kernel/smp.c:412
#14 0x60301dec in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

ПРИМЕЧАНИЕ. Это трассировка ARM-машины, но тот же результат происходит в i386.

1 ответ

Обработчики тестов Systemtap, как правило, запускаются из атомарного контекста, что означает, что прерывание и / или прерывания отключены. Если вам удастся вызвать функцию ядра из такого контекста, целевая функция должна быть аналогично "атомарной", то есть никогда не брать новые блокировки или блоки.

Другие вопросы по тегам