Как убить процесс, запущенный с другим пользователем, не будучи пользователем root или sudoer?

20

в среде Linux мне нужно убить процесс, который был запущен пользователем user2, если я пользователь user1, но не являюсь пользователем sudoers и не использую root. Знаете ли вы, есть ли способ установить это при запуске процесса? Например, список пользователей, которым разрешено убивать процесс?

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

У меня есть список пользователей, которым разрешено запускать процесс, определенный в базе данных, перед началом процесса я проверяю, есть ли текущий пользователь в списке, и, если да, я запускаю процесс с текущим пользователем. Если второй пользователь разрешил сделать это, хочет убить процесс, я бы хотел, чтобы ему разрешили это сделать, но я не хочу, чтобы это было sudoers.

Поэтому я думал о создании процесса, работающего от имени пользователя root, который получает запрос на удаление процессов от пользователя, проверяет, разрешено ли пользователю запускать / останавливать процесс, и убивает процесс.

Как вы думаете, это может быть лучшим решением?

slhck
источник
Добро пожаловать в ТАК. Я не думаю, что это возможно ... Во всяком случае, это больше подходит для дочернего сайта SO, serverfault.com. Это может быть перенесено туда скоро, не нужно ничего делать.
Пекка поддерживает GoFundMonica
О какой программе мы говорим? В общем случае это будет сложно, но в некоторых случаях (например, apache или приложение, которое вы можете изменить самостоятельно) это будет проще.
Ким

Ответы:

14

Извините, но это просто невозможно (так задумано). Однако, если члены общей группы, user1 может записать в файл, который проверяет процесс user2, указывая процессу, что он должен завершиться.

Или user2 может запустить что-то в фоновом режиме, что проверяет файл, а затем отправляет соответствующие сигналы. Затем User1 просто должен записать в этот файл. Это может быть проще, так как это не потребует какой-либо модификации программ user2.

Обычно нет, user1 не может отправлять сигналы POSIX процессу user2.

Тим Пост
источник
Спасибо за Ваш ответ. В моем случае, действительно, я не использую файл, но мы используем систему ( dim.web.cern.ch/dim ), которая может отправлять соответствующий сигнал, затем может быть вызван процесс, который проверяет, что пользователю разрешено остановить процесс и убивает процесс.
@ATelesca - я использую что-то очень похожее, чтобы позволить малообеспеченным пользователям управлять / запускать / останавливать виртуальные машины Xen на довольно большой ферме. В основном то же самое.
Тим Пост
9

Если ACL, SELinux или что-то еще не имеют лучшего способа сделать это, то, как я видел, это делается с помощью скрипта SetUID . Как вы можете себе представить, они печально известны своей угрозой безопасности.

Что касается вашего случая, скажите, что procOwner - это имя пользователя для владельца процесса, а userA (uid 1000), userB (uid 1201) и userC (uid 1450) - люди, которым разрешено уничтожать процесс.

killmyproc.bash:

#!/bin/bash
case ${UID} in
1000|1201|1450) ;;
*) echo "You are not allowed to kill the process."
   exit 1;;
esac

kill ${PROCESS_ID}
# PROCESS_ID could also be stored somewhere in /var/run.

Затем установите владельца и разрешения с помощью:

chown procOwner:procGroup killmyproc.bash
chmod 6750 killmyproc.bash

А также поместите userA, userB и userC в группу procGroup.


источник
Я попробовал это, и это не сработало. Пользователь, не являющийся владельцем, получил запрещение на команду kill.
Джавид Джамаэ
1
Я бы просто добавил, почему бы не позволить системе контролировать разрешения для сценария уничтожения? Создание группы из userA, userB и userC, затем добавление киллскрипта в эту группу и изменение его в g + x кажется мне более уместным.
Леонид Шевцов
1
Бит setUid не разрешен в сценариях оболочки, для его запуска необходимо создать простую скомпилированную программу-обертку
El '
2

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

Это может быть сделано, если целевой процесс сотрудничает. Один из способов - отслеживать внешнее событие (например, файл, создаваемый в / var / tmp или сообщение в сокете), инструктируя его убить себя. Если вы не можете написать это для этого, вы можете написать для него оболочку, которая запускает его, а затем выполняет мониторинг, убивая дочерний процесс в случае возникновения события.


источник
1

Нет, ты не можешь.

Если вы хотите поделиться процессами с другими пользователями, вы должны запустить процесс под общим идентификатором пользователя.

Konerak
источник
1

Конечно, вы можете написать программу таким образом, чтобы она грациозно завершала работу, когда получала определенный сигнал (термин, использованный свободно для обозначения «заранее определенного события», а не сигнала POSIX) от определенного (списка) пользователей.

drxzcl
источник
Сигналы не имеют поля пользователя. Они просто сигналы.
LtWorf
Вот почему я сказал «предопределенное событие, а не сигнал POSIX».
drxzcl
1

Вы можете написать программу suid, которую могут выполнять только пользователи в определенной группе и которая посылает соответствующий сигнал процессу. Не уверен, что вы хотели исключить suid, хотя.

Ким
источник
0

бит suid не работает со скриптами bash. imho, лучший способ - написать скрипт-оболочку "killservice". Предположим, что ваш сервис работает как пользователь serviceuser

#!/bin/bash
sudo -u serviceuser /usr/bin/killserviceworker

тогда

# addgroup servicekiller
# chown root:servicekiller /usr/bin/killservice
# chmod 750 /usr/bin/killservice
# adduser bob servicekiller

тогда вам просто нужно добавить правило в / etc / sudoers, чтобы они могли запускать / usr / bin / killserviceworker от имени пользователя serviceuser без запроса пароля:

servicekiller        ALL = (serviceuser:serviceuser) NOPASSWD: /usr/bin/killserviceworker

killserviceworker может выглядеть так:

#!/bin/bash
kill ${cat /run/service.pid}
Лед
источник