У меня есть процесс, который запускается дэймоном, работающим от имени root, теперь я хочу «понизить» привилегии этого процесса до привилегий вашего обычного пользователя. Это возможно? Если да, то как?
PS: работает Unix на Mac
У меня есть процесс, который запускается дэймоном, работающим от имени root, теперь я хочу «понизить» привилегии этого процесса до привилегий вашего обычного пользователя. Это возможно? Если да, то как?
PS: работает Unix на Mac
Ответы:
Сам процесс должен вызвать setuid (2). Вам также следует изучить запуск его внутри chroot (8), если вы этого еще не сделали. Насколько я знаю, root не может изменить uid другого процесса.
Если причина, по которой вы используете его как root, заключается в том, чтобы связать порты, я бы предложил запустить его как обычный пользователь на более высоком порту и использовать ipfw (8) в OS X для перенаправления порта 80/443 / etc на более высокий порт:
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
одного звонка совершенно недостаточно.
sudo tcpdump -Z
использует initgroups (3), setgid (2) и setuid (2) для удаления корневых привилегий своего собственного процесса.
# code taken from:
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c
/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
username,
(unsigned long)pw->pw_uid,
(unsigned long)pw->pw_gid,
pcap_strerror(errno));
exit(1);
}
...
}
initgroups
, setgid
, setuid
(Наконец!) Именно право парадигмы на UNIX, и всегда должны быть соблюдены. Кроме того, ответственная функция «droproot» проверяет, что ее uid и gid действительно установлены, даже если все три основные функции вернули успех.
Вы можете запускать команды как другие пользователи, используя su
:
su USERNAME -c COMMAND
Будет работать COMMAND
с привилегиями USER
.
Обратите внимание, что по умолчанию su
для запуска команды будет использоваться интерпретатор оболочки целевого пользователя. В отличие от этого, стандартным поведением sudo
является обработка COMMAND
отдельной программы, которая запускается в текущей среде. Конечно, это поведение по умолчанию может быть изменено с помощью различных переключателей и переменных среды.
su
, не работает, если USERNAME не имеет определенной оболочки (или /bin/false
), тогда как sudo работает.
su
будет отражать это. Тем не менее, всегда можно изменить это с помощью -s
переключателя. Обратите внимание, что цель su
состоит в том, чтобы имитировать поведение данного пользователя, на которое обычно влияет его / ее оболочка. В отличие от sudo
этого (по умолчанию) будет игнорировать настройки оболочки целевого пользователя.
Чтобы удалить привилегии, вам нужен не-root пользователь, чтобы перейти на. Тогда нужно просто переключиться на этого пользователя:
#define UNPRIV_UID 48
#define UNPRIV_GID 48
if (getuid() == 0) { // we are root
// setting UID/GID requires root privileges, so if you don't set
// the GID first, you won't be able to do it at all.
if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}
ASSERT(getuid() != 0);
Обратите внимание, что это делается в самой программе , а не в скрипте-оболочке. Многие программы требуют привилегий суперпользователя для какой-то конкретной цели (например, для привязки к порту с небольшим номером), но после этого корень не требуется. Таким образом, эти программы будут запускаться с правами суперпользователя, но затем будут отбрасывать привилегии, когда они больше не нужны.
Если вам вообще не нужны привилегии root, просто не запускайте его как root. Например:
# Change this:
myprog -C /my/config/file
# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
setuid
Функция устанавливает только эффективный UID, а не реальный UID. Вы должны использовать, setreuid
если вы не хотите, чтобы процесс мог вернуть привилегии. (И приведенный выше код также не относится к дополнительным групповым привилегиям. Он подходит только для запуска кода с наибольшим доверием.)
setuid()
устанавливает реальные и сохраненные идентификаторы пользователей; Вы можете думать о seteuid()
. Не все системы имеют setreuid()
, поэтому он не может быть использован везде. Точная семантика setuid()
сложна, но если у вас есть euid 0, вы сможете отбросить все традиционные привилегии пользователя с помощью setuid()
. Самым большим упущением в этом ответе является то, что initgroups
или setgroups
должно быть названо так же, как setgid
и setuid
, и что более тщательные утверждения должны быть сделаны в конце.
Если вы выполняете другой исполняемый файл, то есть вы вызываете execve
или другую exec
функцию из семейства, возможно, косвенно через функцию, подобную system
или popen
, и дочерний процесс должен запускаться без привилегий с самого начала, тогда самый простой способ - это получить Оболочка участвует, и звоните su
. Вот краткий обзор того, как может выглядеть код в Perl, с указанием цитаты, необходимой для:
$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;
Если дочерний процесс должен запускаться с правами root, но позднее отбрасывать привилегии, см. Код в этом ответе , который иллюстрирует, как понизить привилегии в процессе.