Соображения по поводу обертки setuid - PullRequest
5 голосов
/ 18 ноября 2010

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

Iнамеревался запустить эту оболочку через sudo, например,

$ sudo devwrap python somescript.py

Я рассматривал что-то вроде ( обновлено, чтобы исправить пару ошибок ):

int main(int argc, char * argv[])
{
  if(argc < 2) return 0;

  int res = do_hardware_init();
  if(res != OK_VALUE)
  {
    // Print error message
    return HW_ERR;
  }

  const char *sudo_uid = getenv("SUDO_UID");
  if(sudo_uid)
  {
      int real_uid = (int) strtol(sudo_uid, NULL, 0);
      setuid(real_uid);
  }

  return execvp(argv[1], &argv[1]); // No return if successful

}

Итак, у меня есть три вопроса:

  1. Это выглядит нормально?Мне обычно не нужно связываться с вызовами * uid (), поэтому я не знаком с обычными ловушками.Вызов execvp также выглядит немного странно, но, насколько я вижу, он имеет аргументы в нужном месте).
  2. Страница man execvp говорит, что "Массив окружения не долженбыть доступным напрямую из приложения " - это делает getenv вызов плохой идеей?
  3. Есть ли лучший вызов, чем execvp, поэтому я могу сделать sudo devwrap somescript.py (обратите внимание на отсутствие"питон")

1 Ответ

1 голос
/ 18 ноября 2010
  1. Вроде вменяемый ... подробнее ниже.
  2. Использование getenv() не имеет прямого доступа к массиву environ - это чисто.Прямой доступ к массиву environ означает «strcpy (buffer, environment [3])» или что-то в этом роде.
  3. Если скрипт начинается с шебанга (возможно, #!/usr/bin/env python), вы можете делать то, чтохочу уже - somescript.py должен быть исполняемым, конечно.

Проблемы, которые я вижу в первой части, зависят от того, как вы обрабатываете ошибки из-за аппаратной инициализации.Если пропущенная обработка ошибок не завершается, вы можете получить дамп ядра (или segfault), когда не запускаетесь через 'sudo', потому что вы запускаете strtol() с нулевым указателем.Если сам do_hardware_init() завершает работу при сбое, проблем не возникает, если только пользователь не найдет способ разрушить среду из 'sudo'.Я действительно думаю, что вы должны проверить среду и выйти с ошибкой, если SUDO_UID не установлен правдоподобно.Будет ли root хотеть запустить это расширение?

Я не смотрел спецификацию sudo, чтобы убедиться, что она устанавливает переменную среды SUDO_UID - я предполагаю, что вы правы в этом.

Каковы последствия того, что пользователь набрал это?

sudo devwrap ls

Он выполняет аппаратную инициализацию, сбрасывает UID, а затем запускает ls - вероятно, не слишком вредно, но, возможно, не то, что вы имели вразум.Это имеет значение?Можете ли вы вообще это контролировать?

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


Это очень нетрадиционно требоватьлюди могут запускать расширения через 'sudo'.

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


Можете ли вы просто сделать SUID root для программы devwrap?Затем вам нужно будет сбросить UID по-разному:

setgid(getgid());
setuid(getuid());

, который удаляет все SGID-ness и любые SUID-ness перед выполнением команды.Довольно сложно нанести значительный урон.Не ясно, является ли вызов setgid() обязательным, если программа установлена ​​без SGID, но это также не причиняет вреда.

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