У меня есть процесс, который запускается дэймоном, работающим от имени 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, но позднее отбрасывать привилегии, см. Код в этом ответе , который иллюстрирует, как понизить привилегии в процессе.