Astra linux трассировка ptrace
long ptrace(enum __ptrace_request request , pid_t pid , void * addr , void * data );
ОПИСАНИЕ
ptrace — это средство, позволяющее родительскому процессу наблюдать и контролировать протекание другого процесса, просматривать и изменять его данные и регистры. Обычно эта функция используется для создания точек прерывания в программе отладки и отслеживания системных вызовов.
Родительский процесс может начать трассировку, сначала вызвав функцию fork (2), а затем получившийся дочерний процесс может выполнить PTRACE_TRACEME, за которым (обычно) следует выполнение exec (3). С другой стороны, родительский процесс может начать отладку существующего процесса при помощи PTRACE_ATTACH.
При трассировке дочерний процесс останавливается каждый раз при получении сигнала, даже если этот сигнал игнорируется. (Исключением является SIGKILL, работающий обычным образом.) Родительский процесс будет уведомлен об этом при вызове wait (2), после которого он может просматривать и изменять содержимое дочернего процесса до его запуска. После этого родительский процесс разрешает дочернему продолжать работу, в некоторых случаях игнорируя посылаемый ему сигнал или отправляя вместо этого другой сигнал).
По окончании трассировки родительский процесс может прекратить работу дочернего при помощи функции PTRACE_KILL или дать ему возможность работать в обычном, нетрассируемом, режиме, используя PTRACE_DETACH.
Значение аргумента request определяет действие, выполняемое функцией: PTRACE_TRACEME Означает, что этот процесс должен быть трассирован его родительским процессом. Любой сигнал (кроме SIGKILL), получаемый этим процессом, приведет к его приостановке, и родительский процесс будет уведомлен об этом с помощью функции wait. Кроме того, если этот процесс вызовет exec , то к нему придет сигнал SIGTRAP, в результате чего родительский процесс получит управление до того, как запустится новая программа. Скорее всего, процессу не следует посылать этот вызов, если родительский процесс не готов к трассировке дочернего. (Параметры pid , addr и data игнорируются).
Вышеописанный запрос посылается только дочерним процессом; все остальные отправляются родительским. В запросах, описанных ниже, параметр pid задает номер процесса, над которым будут производиться действия. При вызове всех запросов (кроме PTRACE_KILL) дочерний процесс должен быть остановлен. PTRACE_PEEKTEXT, PTRACE_PEEKDATA Читает слово с адресом addr , находящееся в памяти дочернего процесса, возвращая это слово как результат функции ptrace . Linux не разделяет понятий адресных пространств текста и данных, поэтому оба вызова абсолютно идентичны. (Аргумент data игнорируется.) PTRACE_PEEKUSR Читает слово с адресом addr в области USER дочернего процесса, которая содержит информацию о регистрах и процессе (см. файлы и ). Слово возвращается в качестве результата функции ptrace . Обычно смещение должно быть выровнено по границе слова, хотя это может зависеть от архитектуры системы (параметр data игнорируется). PTRACE_POKETEXT, PTRACE_POKEDATA Копирует слово data в память дочернего процесса с адресом addr . Как описано выше, эти два запроса в данное время аналогичны. PTRACE_POKEUSR Копирует слово data по смещению addr в области USER дочернего процесса. Обычно смещение должно быть выровнено по границе слова. Для того, чтобы сохранить упорядоченность данных в системе, некоторые изменения в процесс вносить запрещено. PTRACE_GETREGS, PTRACE_GETFPREGS Копирует общие регистры или, соответственно, регистры сопроцессора, дочернего процесса в переменную data родительского. Формат передаваемой структуры описан в файле . (Параметр addr игнорируется). PTRACE_SETREGS, PTRACE_SETFPREGS Изменяет содержимое общих (или, соответственно, математических) регистров дочернего процесса на основании структуры, находящейся в переменной data родительского процесса. Как и в случае c PTRACE_POKEUSER, изменение некоторых общих регистров запрещено (параметр addr игнорируется). PTRACE_CONT Возобновляет работу остановленного дочернего процесса. Если параметр data не равен нулю или SIGSTOP, то он считается сигналом, который надо передать дочернему процессу; в противном случае сигнал не передается. Таким образом родительский процесс сможет контролировать передачу сигнала дочернему процессу (параметр addr игнорируется). PTRACE_SYSCALL, PTRACE_SINGLESTEP Аналогично PTRACE_CONT они возобновляют работу остановленного дочернего процесса, но указывают, что процесс должен быть остановлен при следующем входе в систему или выходе из нее при вызове или после исполнения одной из команд. (Дочерний процесс будет также остановлен при получении сигнала). С точки зрения родительского процесса, дочерний будет остановлен при получении сигнала SIGTRAP. Таким образом, PTRACE_SYSCALL позволяет изучить содержимое аргументов при первой остановке процесса, возникшей при вызове системной функции; а затем просмотреть результат исполнения системного вызова при второй остановке. (Параметр addr игнорируется.) PTRACE_KILL Посылает дочернему процессу сигнал SIGKILL, для того чтобы процесс прекратил свою работу (параметры addr и data игнорируются). PTRACE_ATTACH Подключается к процессу, заданному в pid , делая его трассируемым дочерним процессом; после этого дочерний процесс работает так, как будто он вызвал PTRACE_TRACEME. Текущий процесс, на самом деле, становится родительским для дочернего по многим критериям (например, он будет получать сообщения об операциях дочернего процесса и будет становиться родительским при работе команды ps (1)), но функция getppid (2), вызванная дочерним процессом, будет возвращать pid предыдущего родителя. Дочерний процесс получит сигнал SIGSTOP, но это необязательно вызовет его остановку; используйте для этого функцию wait . (Параметры addr и data игнорируются.) PTRACE_DETACH Возобновляет работу остановленного дочернего процесса аналогично PTRACE_CONT, но сначала отключается от него, аннулируя эффект PTRACE_ATTACH и эффект PTRACE_TRACEME. Хотя этого не было предусмотрено, в Linux при помощи этого вызова трассируемый дочерний процесс может возобновить свою нормальную работу (с отключением трассировки) независимо от того, как эта трассировка была запущена. (Поле addr игнорируется).
ЗАМЕЧАНИЯ
Несмотря на то, что параметры ptrace обрабатываются в соответствии с описанным выше прототипом, в GNU libc в данное время функция ptrace определена как вариативная функция с одним обязательным параметром request . Это означает, что ненужные параметры могут быть проигнорированы, что приведет в действие неописанный здесь механизм gcc(1) .
init (8), процесс с pid 1, не может быть трассирован.
Структура памяти и области USER дочернего процесса зависят от ОС и архитектуры системы.
Размер «слова» определяется вариантом ОС (например, для 32-битного варианта Linux слово будет 32-битным и т.п.).
Трассировка вызывает небольшие изменения в поведении трассируемых процессов. Например, если трассировка процесса запущена при помощи PTRACE_ATTACH, то его предыдущий родительский процесс не сможет при помощи wait получить сообщение о событиях в дочернем процессе, а для нового родительского процесса эффективного способа передать это сообщение старому процессу не существует.
Эта страница описывает работу системного вызова ptrace в Linux. Его работа может быть иной в других системах Unix.
Man-страница ptrace в SunOS описывает этот вызов как «уникальный и заумный», каким он на самом деле и является. Интерфейс отладки процессов, основанный на proc и представленный в Solaris 2, содержит дополнительные вызовы ptrace , обеспечивающие большую гибкость и функциональность отладки.
ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ
При удачном завершении работы функции запросы PTRACE_PEEK* возвращают данные памяти, а остальные запросы возвращают нулевое значение. При ошибке все запросы возвращают -1, а переменной errno присваивается номер ошибки. Значение, возвращаемое при удачном завершении PTRACE_PEEK*, может равняться -1, поэтому после вызова данной функции необходимо проверить содержимое errno , чтобы узнать, вернула ли функция ошибку или запрос был удовлетворен.
НАЙДЕННЫЕ ОШИБКИ
EPERM Заданный процесс не может быть трассирован. Это может произойти потому, что родительский процесс не имеет достаточного количества прав на трассирование: не-root процессы не могут по очевидным причинам трассировать процессы, которым невозможно послать сигналы или которые работают в режиме setuid/setgid. С другой стороны, процесс может уже быть трассируемым или называться init (pid 1). ESRCH Заданный процесс не существует, не трассируется вызывающим процессом или не остановлен (согласно запросам). EIO Задано неверное значение request , или была попытка записи информации в неподходящую область памяти дочернего или родительского процесса; было нарушено выравнивание слов по границе, или при возобновлении работы дочернего процесса номер сигнала был задан неверно. EFAULT Была сделана попытка записи информации в область памяти дочернего или родительского процесса, но, скорее всего, эта память не существует или недоступна. К сожалению, в Linux в разных ситуациях в результате этой ошибки возвращаются значения EIO или EFAULT, что не всегда поддается объяснению.
Ошибка отладчика Lazarus в AstraLinux
После успешной компиляции приложения в Lazarus под AstraLinux и попытке запуска появляется сообщение об ошибке отладчика: «Отладчик не смог запустить приложение». При этом окно подробностей ничего внятного не сообщает:
Причина
Вероятнее всего в таком случае виновата блокировка системных вызовов ptrace, которая активируется по-умолчанию, если не убрать соответствующую галочку при установке AstraLinux.
ptrace (от process trace) — системный вызов в Linux, который позволяет трассировать или отлаживать выбранный процесс. ptrace дает полный контроль над процессом: можно изменять ход выполнения программы, смотреть и изменять значения в памяти или состояния регистров. При этом никаких дополнительных прав не получаем — действия ограничены правами запущенного процесса.
Решение
Необходимо отключить блокировку ptrace. Сделать это можно под админом в графическом интерфейсе: Панель управления — Безопасность — Политика безопасности. Далее открываем раздел Настройки безопасности — Системные параметры. Нас интересует галочка «Блокировка трассировки ptrace для всех пользователей«. Её необходимо убрать:
После этого применяем изменения и перезагружаемся. После перезагрузки отладчик должен заработать как положено.
То же самое можно выполнить и в терминале (например, по SSH). Для проверки состояния выполняем команду:
$ systemctl is-enabled astra-ptrace-lock
Если ответ «enabled», значит блокировка включена. Выключаем её:
$ sudo astra-ptrace-lock disable $ sudo reboot
Данная статья проверялась для AstraLinux SE 1.7.2