gdb игнорирует исполняемые возможности

Я отлаживаю программу, которая использует libnetfilter_queue. В документации указано, что приложению для обработки очередей пользовательского пространства для работы требуется возможность CAP_NET_ADMIN. Я сделал это с помощью утилиты setcap следующим образом:

$ sudo setcap cap_net_raw,cap_net_admin=eip ./a.out

Я убедился, что возможности применяются правильно: а) программа работает и б) getcap возвращает следующий вывод:

$ getcap ./a.out
./a.out = cap_net_admin,cap_net_raw+eip

Однако, когда я пытаюсь отлаживать эту программу, используя gdb (например, $ gdb ./a.out) из командной строки, происходит сбой из-за отсутствия правильных разрешений. Функциональность отладки gdb в остальном работает отлично и отлаживает как обычно.

Я даже пытался применить эти возможности к самому двоичному файлу gdb, но безрезультатно. Я сделал это так, как казалось (как задокументировано man-страницы, что флаг "i" может позволить отлаживаемой программе наследовать возможности от отладчика.

Есть ли что-то тривиальное, что мне не хватает, или это действительно невозможно сделать?


person Sedate Alien    schedule 05.12.2010    source источник
comment
GDB использует подсистему ptrace. Есть ли у него возможность CAP_SYS_PTRACE? Работает ли он с любым другим двоичным файлом? Например. программа привет мир?   -  person thkala    schedule 05.12.2010
comment
@thkala: я отредактировал вопрос, чтобы быть более точным. gdb работает нормально, в противном случае он может отлаживать любую программу (включая эту).   -  person Sedate Alien    schedule 05.12.2010
comment
Не могли бы вы упомянуть точное сообщение об ошибке?   -  person thkala    schedule 05.12.2010
comment
Как такового сообщения об ошибке нет. Я использую этот образец кода, предоставленный разработчиками, и nfq_unbind_pf() возвращается -1errno установлено на 1), что указывает на сбой.   -  person Sedate Alien    schedule 05.12.2010


Ответы (6)


Некоторое время назад я столкнулся с той же проблемой. Я предполагаю, что запуск отлаженной программы с дополнительными возможностями является проблемой безопасности.

Ваша программа имеет больше привилегий, чем пользователь, который ее запускает. С помощью отладчика пользователь может манипулировать выполнением программы. Таким образом, если программа запускается под отладчиком с дополнительными привилегиями, пользователь может использовать эти привилегии для других целей, отличных от тех, для которых программа намеревалась их использовать. Это было бы серьезной дырой в безопасности, потому что пользователь изначально не имеет привилегий.

person Fabian    schedule 05.12.2010
comment
Этот ответ имеет для меня большой смысл. Я попытаюсь изучить источник gdb, чтобы подтвердить, что это так, но я все равно отмечу ваш ответ как принятый. - person Sedate Alien; 06.12.2010
comment
Я предполагаю, что это обрабатывается ядром, а не gdb. Вероятно, вам следует изучить системный вызов ptrace. - person Fabian; 06.12.2010
comment
Из man-страницы linux execve: если бит set-user-ID установлен в программном файле, на который указывает имя файла, и базовая файловая система не смонтирована nosuid (флаг MS_NOSUID для mount(2)), а вызывающий процесс не трассируется, то эффективный идентификатор пользователя вызывающего процесса заменяется идентификатором владельца программного файла. Вероятно, это относится и к файловым возможностям, поскольку, как и suid/sgid, они обеспечивают повышение привилегий. - person Fabian; 06.12.2010
comment
Предположение неверно - см. ответ Ника Хуанга. Это сработало для меня. - person Christian; 26.02.2016

Я столкнулся с той же проблемой, и вначале я подумал так же, как и выше, что, возможно, gdb игнорирует возможности исполняемого файла из соображений безопасности. Однако, читая исходный код и даже используя сам gdb для отладки eclipse, когда он отлаживает мою ext2fs-прогу, которая открывает /dev/sda1, я понимаю, что:

  1. gdb ничем не отличается от любой другой программы. (Как и в матрице, даже сами агенты подчиняются одному и тому же физическому закону, гравитации и т. д., за исключением того, что все они привратники.)
  2. gdb не является родительским процессом отлаживаемого исполняемого файла, вместо этого он является дедушкой.
  3. Истинный родительский процесс отлаживаемого исполняемого файла - это «оболочка», то есть /bin/bash в моем случае.

Итак, решение очень простое, помимо добавления cap_net_admin,cap_net_raw+eip в gdb, вы также должны применить это к своей оболочке. то есть setcap cap_net_admin,cap_net_raw+eip /bin/bash

Причина, по которой вы также должны сделать это с gdb, заключается в том, что gdb является родительским процессом /bin/bash перед созданием отлаженного процесса.

Настоящая исполняемая командная строка внутри gdb выглядит следующим образом:

/bin/bash exec /my/executable/program/path

И это параметр для vfork внутри gdb.

person Nick Huang    schedule 18.08.2014

Для тех, у кого такая же проблема, вы можете обойти ее, выполнив gdb с помощью sudo.

person ZazOufUmI    schedule 13.02.2013
comment
+1, хотя это не решение для каждого случая. У меня есть два приложения. Первый задал некоторые возможности, но зависит от второго приложения, которое связывается с первым через сигналы RT. Таким образом, использование только gdb ./a.out не работает, потому что приложение потеряло свои возможности, а использование sudo gdb ./a.out не работает, потому что пользовательское приложение не может отправлять сигналы приложениям, работающим под root. Это сложно отладить, и похоже, что обходного пути нет :) - person Mike S.; 15.09.2014

Для тех, кто запускает GDB через IDE, sudo-ing GDB (как в ответе @Stéphane J.) может оказаться невозможным. В этом случае вы можете запустить:

sudo gdbserver localhost:12345 /path/to/application

а затем подключите экземпляр GDB вашей IDE к этому (локальному) GDBServer.

В случае Eclipse CDT это означает создание новой конфигурации отладки «Удаленное приложение C/C++», затем на вкладке «Отладчик» > «Подключение» введите TCP/localhost/12345 (или любой другой порт, который вы выбрали выше). Это позволяет выполнять отладку в Eclipse, в то время как ваше приложение имеет привилегированный доступ.

person TomGreen    schedule 04.01.2018

Я использовал решение @NickHuang, пока одно из системных обновлений не сломало службы systemd (слишком много возможностей в bash, чтобы systemd мог запустить его или что-то в этом роде). Переключился на то, чтобы оставить bash в покое и вместо этого передать команду gdb для прямого вызова исполняемого файла. Команда

set startup-with-shell off
person Eugene Ryabtsev    schedule 15.05.2020

Хорошо, поэтому я немного боролся с этим, поэтому решил объединить ответы и подвести итоги.

Простое решение — просто sudo gdb, как было предложено, но будьте немного осторожны. Здесь вы запускаете отлаженную программу с правами root. Это вполне может привести к тому, что он будет работать иначе, чем когда вы запускаете его из командной строки в качестве обычного пользователя. Может быть немного запутанным. Не то чтобы я КОГДА-ЛИБО попал в эту ловушку... Упс.

Это нормально, если вы запускаете отлаживаемую программу от имени пользователя root с sudo ИЛИ если в отлаживаемой программе установлен бит setuid. Но если отлаживаемая программа работает с возможностями POSIX (setcap / getcap), то вам необходимо отразить эти более детализированные разрешения в bash и gdb, как предложил Ник Хуанг, а не просто перебирать разрешения с помощью «sudo».

Делая что-либо еще, вы можете оказаться в плохом месте экстремального обучения.

person Mike Higginbottom    schedule 14.01.2020