C начало сеанса X11 с использованием system () против использования execl () - PullRequest
0 голосов
/ 20 ноября 2018

Я создал демоноподобную программу, которая запускает сеанс X11 для конкретного пользователя в его собственной среде после того, как он аутентифицируется.

Первым подходом было использование команды с использованием system(), где я бы выдал себя за пользователя и запустил сеанс x11 следующим образом:

std::string cmd = "echo daemonuserpwd | sudo -S su " + unixUser + " -c 'xinit -- :4' &";
system(cmd.c_str());

Это работает безупречно и вызывает *Файл 1007 *, расположенный в домашнем каталоге пользователя, что является необходимым шагом, поскольку я использую его для запуска необходимых программ, которые мне нужны для приложения, в котором я работаю.

Однако я прочитал о проблемах.с system(), поэтому я попытался пойти немного дальше и использовать fork для создания пользовательской среды и начать сеанс, используя execl(), следующим образом:

int child = fork();
if(child == 0)
{
    struct passwd * userInfo = getpwnam(unixUser.c_str());
    setgid(userInfo->pw_gid);
    setuid(userInfo->pw_uid);
    system("whoami");
    execl("/usr/bin/xinit", "xinit", "--", ":4", (char*)0);
    //system("xinit -- :4");
}

Это также работает, команда отладки system("whoami"); говорит, что я правильный пользователь.Сеанс X11 запущен, однако файл .xinitrc не вызывается при запуске сеанса из процесса fork.Я также попытался выполнить команду с системой, после настройки пользовательской среды, с тем же результатом (обе опции вызывают значение по умолчанию xinitrc в /etc/X11/xinit/xinitrc.

Я что-то упускаю в порядке .xinitrcфайл, который также будет вызываться при использовании подхода fork()?

Отказ от ответственности: аутентификация пользователя выполняется с помощью libpam, и пользовательский ввод должным образом очищается для предотвращения инъекций.


РЕДАКТИРОВАТЬ: Окончательный обходной путь с использованием execle, как предложено @LieRyan:

struct passwd * userInfo = getpwnam(unixUser.c_str());
char buf[0xff];
sprintf(buf, "HOME=%s", userInfo->pw_dir);
char *env[] = {buf, NULL};
execle("/usr/bin/sudo", "sudo", "-u", unixUser.c_str(), "xinit", "--", ":4", (char*)0, env);

1 Ответ

0 голосов
/ 20 ноября 2018

Вызов setuid изменяет, кому принадлежит процесс, но не изменяет переменные среды, которые были бы установлены, если бы этот пользователь вошел в систему, поэтому $HOME не будет указывать в нужное место, чтобы взятьФайл ".xinitrc".

Следующая строка кода должна исправить это для вас.

setenv("HOME",userInfo->pw_dir,1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...