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 означает, что системный вызов процедура уже завершилась, и это должно было снять любую блокировку, связанную с самой файловой системой, но я, вероятно, что-то упустил.

Отладка ядра в этот момент дает мне следующую трассировку. По-видимому, взаимоблокировка находится в блокировке 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.


person Tavo    schedule 20.06.2018    source источник
comment
Любая подсказка, почему ядро ​​зависает? - Функция, работающая с файлами, может блокировать некоторые ресурсы (например, мьютекс для индексного дескриптора). Если вы вызываете эту функцию из контекста, где эти ресурсы уже заблокированы, вы получаете взаимоблокировку. Трудно получить более точную диагностику без просмотра использования ваших функций.   -  person Tsyvarev    schedule 20.06.2018
comment
Спасибо @Tsyvarev, это имеет смысл, потому что эти функции вызываются в контексте зонда syscall.open.return. Однако, AFAIU, возвратные зонды реализованы как kretprobe в Systemtap... который заменяет адрес возврата функции на трамплин... а это значит, что системный вызов уже сделал все, включая снятие любой блокировки.   -  person Tavo    schedule 21.06.2018


Ответы (1)


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

person fche    schedule 03.08.2018