Какова роль обработчика неопределенных исключений (__und_svc) в kprobes?

Я попытался преобразовать kprobe в загружаемый модуль ядра.

Я могу запускать образцы, доступные в папке samples/kprobes/ из дерева ядра.

Если мы настроим kprobes в ядре (CONFIG_KPROBES), то макрос svc_entry будет расширен на 64 байта в обработчике __und_svc().

Ссылка: http://lxr.free-electrons.com/source/arch/arm/kernel/entry-armv.S?a=arm#L245

Моя цель, не касаясь ядра, сделать kprobe модулем ядра.

поэтому ядро ​​компилируется без включения CONFIG_KPROBES. поэтому макрос svc_entry будет расширен на 0 в __und_svc()

Я хотел бы избавиться от этих сомнений.

  1. Если kprobe обрабатывает исключение неопределенной инструкции (только bcos kprobe), то почему вызывается __und_svc(). какова роль обработчика __und_svc() по отношению к kprobes??

  2. Если 64 байта памяти обязательно, то как выделить без компиляции ядра. т.е. как это сделать динамически.??

Пожалуйста, поделитесь своими знаниями.


person Jeyaram    schedule 13.12.2013    source источник
comment
Хотя мне нравятся точные вопросы в SO, я боюсь, что этот слишком специфичен. Пробовали ли вы использовать один из списков рассылки, связанных с ядром?   -  person Andrejs Cainikovs    schedule 13.12.2013
comment
Да. Я разместил этот вопрос в списке рассылки systemtap, а также в списке рассылки linux-arm. Плохо то, что в linux-arm она еще не опубликована.   -  person Jeyaram    schedule 13.12.2013


Ответы (1)


Вы можете не получить ответы, так как ваше понимание вещей не очень хорошо, и кому-либо из списка linux-arm-kernel потребуется некоторое время, чтобы ответить. Прочитайте kprobes.txt и подробно изучите архитектуру ARM.

Если kprobe обрабатывает исключение неопределенной инструкции (только bcos kprobe), то почему вызывается __und_svc(). какова роль обработчика __und_svc() по отношению к kprobes?

В ARM режим 0b11011 является режимом неопределенных инструкций. Последовательность действий при выполнении неопределенной инструкции следующая:

  1. lr_und = pc инструкции undef + 4
  2. SPSR_und = CPSR режима, в котором произошла инструкция.
  3. Измените режим на ARM с отключенным прерыванием.
  4. PC = векторное основание + 4

Основная векторная таблица четвертого шага находится по адресу __vectors_start, и это просто переходит к vector_und. Код представляет собой макрос с именем vector_stub, который принимает решение о вызове __und_svc или __und_usr. Стек — это страница размером 4/8 КБ, зарезервированная для каждого процесса. Это страница ядра, которая содержит как структуру задач, так и стек ядра.

kprobe работает, помещая неопределенные инструкции в кодовые адреса, которые вы хотите проверить. Т.е. он включает неопределенный обработчик инструкций. Это должно быть довольно очевидно. Он вызывает две процедуры: call_fpe или do_undefinstr(). Вас интересует второй случай, который получает код операции и вызывает call_undef_hook(). Добавьте хук с помощью register_undef_hook(); который вы можете увидеть arch_init_kprobes(). Основной обратный вызов kprobe_handler вызывается с struct pt_regs *regs, что является дополнительной памятью, зарезервированной в __und_svc. Обратите внимание, например, на kretprobe_trampoline(), который шутит со стеком, с которым он выполняется в данный момент.

Если 64 байта памяти обязательно, то как выделить без компиляции ядра. т.е. как это сделать динамически.?

Нет. Вы можете использовать другой механизм, но вам, возможно, придется изменить код kprobes. Скорее всего, вам придется ограничить функциональность. Также можно полностью перезаписать фрейм стека и зарезервировать лишние 64 байта постфактум. Это не распределение, как в kmalloc(). Это просто добавление/вычитание числа из указателя стека супервизора. Я предполагаю, что код перезаписывает адрес возврата из неопределенного обработчика для выполнения в контексте (ISR, IRQ нижней половины/потока, work_queue, задача ядра) kprobed адрес. Но, вероятно, есть дополнительные проблемы, с которыми вы еще не сталкивались. Если arch_init_kprobes() никогда не вызывается, то вы всегда можете сделать резервирование в __und_svc; он просто съедает 64 байта стека, что повышает вероятность переполнения стека ядра. То есть изменить,

__und_svc:
    @ Always reserve 64 bytes, even if kprobe is not active.
    svc_entry 64

arch_init_kprobes() — это то, что на самом деле устанавливает эту функцию.

person artless noise    schedule 13.12.2013
comment
спасибо за просветление call_undef_hook() связанных вещей. Более информативно. Но я не могу изменить __und_svc() из entry-armv.S. В коммите d30a0c8bf99f0e6a7d8c57bd4524039585ffbced добавляются только эти 64 байта. поэтому я пытаюсь понять, для какой функции/ошибки они добавили. - person Jeyaram; 16.12.2013
comment
Просто пропатчите ядро. Установите entry-armv.S, svc_entry с кодом, который корректирует задачу, а затем всегда используйте svc_entry 64. Вам не нужно тянуть полный набор патчей. git diff d30a0c8bf99~1..d30a0c8bf99 дает мне полный патч. Вы можете сохранить его и запустить echo svc_entry.patch | patch -p1. Или вы спрашиваете нельзя ли перекомпилировать ядро ​​и исправить это? Это почти невозможно; вам придется переписать весь код arm/kernel/kprobes.c. - person artless noise; 16.12.2013
comment
Мое требование заключается в том, чтобы без применения каких-либо исправлений или даже отдельных изменений в ядре модифицировать kprobes как LKM. поэтому у меня нет других вариантов, кроме перезаписи arm/kernel/kprobes.c. - person Jeyaram; 17.12.2013