TL;DR
Пишу программу на Си. Мне нужны привилегии root для fopen
файла sysfs, и мне все еще нужны привилегии root, чтобы читать из него. Однако, поскольку моя программа должна будет постоянно читать файл sysfs, это означает, что ей все время нужно будет иметь повышенные привилегии. Я хотел бы отказаться от привилегий root как можно скорее. Каков принятый способ решения этой проблемы?
Подробности
Я пишу программу, которая взаимодействует с sysfs. Если бы я запускал команды в оболочке, я бы использовал:
myuser@mymachine:~$ sudo su
root@mymachine:/home/myhomedir# cd /sys/class/gpio
root@mymachine:/sys/class/gpio# echo 971 > export
root@mymachine:/sys/class/gpio# cat gpio971/value
0
root@mymachine:/sys/class/gpio# exit
Мне нужно запустить эти команды в программе C, которую может вызывать непривилегированный пользователь. Один из способов сделать это — написать программу обычным способом, используя fopen
, fprintf
, fscanf
и т. д., и заставить пользователя запустить программу через sudo
. Однако это означает, что пользователь должен быть sudoer, и программа все время будет иметь привилегии root.
Еще одно решение, которое я настоятельно предпочитаю (поскольку пользователя не нужно будет добавлять в sudoers), — изменить владельца программы на root и установить бит setuid
. (Я узнал об этом из здесь).
Однако есть кое-что, о чем я задаюсь вопросом. Что я хотел бы сделать, так это открыть файлы sysfs, пока программа euid
равна 0, но затем сразу же отказаться от всех привилегий (для безопасности). Затем, когда файл был открыт, мы просто setuid()
получаем UID пользователя. Однако, хотя я не могу быть полностью уверен, это не работает. Вот соответствующая часть моего кода:
//At this point, due to the file permissions on the executable,
//euid = 0 and ruid = 1000. I know the following 4 lines work.
FILE *export = fopen("/sys/class/gpio/export", "wb");
fprintf(export, "971\n");
fclose(export);
FILE *sw_gpio = fopen("/sys/class/gpio971/value", "rb");
setuid(1000);
//Now euid = 1000 and ruid = 1000
int switch_val = -1;
fscanf(sw_gpio, "%d", &switch_val);
printf("Switch value: %d\n", switch_val); //-1
//Even though the only possible values in this sysfs file are 0 and 1,
//switch_val is still equal to -1
fclose(sw_gpio);
Так что, похоже, мне нужно будет сохранить повышенные разрешения, чтобы иметь возможность читать из /sys/class/gpio/gpio971/value
. Но это именно то, чего я не хочу! Эта программа должна будет опрашивать значение во время выполнения программы, и мне не нужны привилегии root все время.
Наконец, для завершения, вот разрешения, которые я установил для своего исполняемого файла:
-rwsr-xr-x 1 root myuser 10943 Jan 1 20:17 main*
Итак, как отказаться от привилегий root, но продолжить чтение из файла sysfs с контролируемым доступом?
fscanf
, и если оно равноEOF
, вызовитеperror
, чтобы сообщить вам, почему это не удалось. Вы также должны выполнить проверку ошибок для вызововfopen
. - person dbush   schedule 30.08.2017perror
по всему моему реальному коду (я не загромождал ими свой исходный пост). Все вызовы вернули успех. - person Marco Merlini   schedule 30.08.2017seteuid()
(установка эффективного идентификатора пользователя) делать то, что вы хотите? С установленным битом setuid двоичного файла, я думаю, вы можете переключаться между реальным (непривилегированным) пользователем и пользователем-владельцем (suid). - person TripeHound   schedule 30.08.2017gpio
), а затем добавление пользователей, которым разрешено возиться с контактами gpio, в эту группу. Для самого правила посмотрите, например. последний пост в этом обсуждении на форумах Raspberry Pi — должен быть два правила, две линии; хотя сам не проверял. Таким образом, вашей программе вообще не нужно иметь setuid/setgid или заботиться о разрешениях. - person Nominal Animal   schedule 30.08.2017strace
нерабочей версии и опубликовать результат где-нибудь? Вам нужно прикрепить запущенный процесс, иначе SUID не будет работать: 1) добавьтеsleep(60)
в начале вашей программы. 2) запустите его и найдите его PID. 3) запуститьstrace -p pid
в другой консоли. Когда программа выйдет из спящего режима, вы должны увидеть появление трассировки. - person spectras   schedule 31.08.2017