У мене є процес, який починається від демона, що працює під керуванням root, тепер я хочу "знизити" привілеї цього процесу до тих, що мають ваш середній користувач. Чи можливо це? Якщо так, то як?
PS: Запуск Unix на mac
У мене є процес, який починається від демона, що працює під керуванням root, тепер я хочу "знизити" привілеї цього процесу до тих, що мають ваш середній користувач. Чи можливо це? Якщо так, то як?
PS: Запуск Unix на mac
Відповіді:
Сам процес повинен викликати setuid (2). Ви також повинні дослідити запуск його в chroot (8), якщо ви ще цього не зробили. Наскільки я знаю, немає можливості кореня змінити uid іншого процесу.
Якщо причина, за якою ви запускаєте його як root, пов’язує порти, я б запропонував запустити його як звичайний користувач на більш високому порту та використовувати ipfw (8) в OS X для пересилання порту 80/443 / тощо на більш високий порт:
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
буде (за замовчуванням) ігнорувати налаштування оболонки цільового користувача.
Щоб скасувати привілеї, вам потрібно некористувальницького користувача, на який потрібно перейти. Тоді лише питання про перехід до цього користувача:
#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 не потребує цього. Тож ці програми запускаються як root, але потім скасовують привілеї, коли вони більше не потрібні.
Якщо вам зовсім не потрібні привілеї 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, але пізніше скасувати привілеї, дивіться код у цій відповіді , який ілюструє, як зменшити привілеї в процесі.