https://www.cnblogs.com/revercc/p/17803876.html Зв'язок між програмою uprobe eBPF і kernel/events/uprobe.c фактично полягає в тому, що механізм eBPF повторно використовує власну інфраструктуру uprobe ядра для реалізації функції hook функцій стану користувача. Зокрема, uprobe eBPF — це «застосування» фреймворку ядра, який пов'язаний внутрішнім ланцюгом викликів ядра та структурою даних. Основний зв'язок: eBPF покладається на фреймворк uprobe ядра для реалізації хуків Ядро uprobe.c є основною реалізацією нативного зонда стану користувача ядра Linux (uprobe) і відповідає за: Керування реєстрацією та скасуванням зондів у стані користувача (наприклад, register_uprobe(), unregister_uprobe()). Обробляє вставку точки зупину (запис інструкцій на адресу цільової функції, наприклад, int3 у x86). Захоплення тригерних подій точки зриву (застрягають у обробці стану ядра, коли програма виконується до точки зупину). Викликайте попередньо зареєстровану функцію зворотного виклику (тобто логіку зачіпа). Програма uprobe eBPF (наприклад, у прикладі hook libc.so, який ви написали) фактично реєструє функцію зворотного виклику eBPF на основі uprobe, з ядром через eBPF-завантажувач (наприклад, bcc, libbpf), яка повністю покладається на інфраструктуру, надану uprobe.c. Специфічний ланцюг дзвінків: потік від програми eBPF до uprobe.c Коли ви реєструєте апроб через eBPF-завантажувач (наприклад, attach_uprobe bcc), основний процес виглядає так: Завантажувач eBPF ініціює запит на реєстрацію. Завантажувач (наприклад, код на Python від bcc) повідомляє ядро через системний виклик (наприклад, bpf() або perf_event_open()), що «Я хочу підвішити eBPF-гачок на функцію openat libc.so» і передає байткод програми eBPF. Верифікація та підготовка програм eBPF ядра Перевірка ядра eBPF перевіряє легітимність програми, щоб переконатися, що вона не порушує безпеку ядра. Після передачі завантажте програму eBPF у ядро і отримайте «функцію зворотного виклику eBPF» (тобто uprobe_openat логіку, яку ви написали). Повторне використання ядра інтерфейсу реєстрації uprobe.c викликає функцію register_uprobe() в uprobe.c, реєструє «рідний uprobe» і використовує функцію зворотного виклику eBPF як «тригерний обробник» цього uprobe. Головне тут таке: суть uprobe eBPF полягає в прив'язанні callback типу eBPF до нативного упроба ядра. uprobe.c вставляє точку зупину і чекає на її активацію. Uprobe.c записує інструкцію точки зупину (наприклад, int3 у x86) у пам'ять стану користувача на основі зареєстрованої цільової адреси (адреса openat у libc.so) і записує початкову інструкцію точки розриву (для відновлення виконання після тригерування). Виклики функцій тригерних точок розриву, uprobe.c викликає зворотні виклики eBPF Коли додаток викликає libc.so:openat, виконання інструкції breakpoint запускає пастку і переходить у стан ядра. На цей момент: Ядро викликає функцію uprobe_handler() (логіка обробки ядра) в uprobe.c. uprobe_handler() перевірить реєстраційну інформацію, що відповідає точці зупину, і виявить, що вона прив'язана до eBPF-callback, тому викликає програму eBPF (тобто uprobe_openat, яку ви написали). Після виконання програми eBPF (наприклад, збір параметрів, запис у ringbuf) uprobe_handler() відновлює початкову інструкцію і дозволяє програмі продовжити виконання. Резюме: Взаємозв'язок між двома kernel/events/uprobe.c — це базова інфраструктура, яка забезпечує основні можливості, такі як вставка, захоплення та відновлення точок зупину стану користувача, і є основою для всіх зондів стану користувача (включаючи eBPF-апроб, налагодження gdb тощо). Програма uprobe eBPF — це додаток верхнього рівня, заснований на цій інфраструктурі, який реєструє функції зворотного виклику eBPF і дозволяє ядрі виконувати логіку eBPF при запуску uprobe, досягаючи ефективного відстеження стану користувача. Коротко кажучи: uprobe для eBPF — це «користувач», а uprobe.c — «постачальник послуг», і перший покладається на другого для завершення реєстрації, запускання та виконання хуків. |