TL;DR
I am writing a C program. I need to have root privileges to fopen
a sysfs file, and I still need root privileges in order to read from it. However, since my program will need to continuously read the sysfs file, this implies that it will need to have elevated privileges the whole time. I would like to drop root privilege as soon as possible. What's the accepted way of approaching this problem?
我正在写一个C程序。我需要有root权限才能打开sysfs文件,而且我还需要root权限才能从它中读取。然而,由于我的程序将需要不断地读取sysfs文件,这意味着它将需要在整个过程中拥有更高的权限。我想尽快取消root权限。解决这个问题的公认方法是什么?
Details
I am writing a program that interacts with sysfs. If I was running the commands on the shell, I would use:
我正在编写一个与sysfs交互的程序。如果我在shell中运行命令,我将使用:
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
I need to run these commands in a C program that is callable by a non-privileged user. One way to do this is to write the program in the usual way using fopen
, fprintf
, fscanf
, etc and have the user run the program through sudo
. However, this means the user needs to be a sudoer, and the program will have root privilege the whole time.
我需要在C程序中运行这些命令,该程序可以由非特权用户调用。一种方法是使用fopen、fprintf、fscanf等以通常的方式编写程序,并让用户通过sudo运行程序。然而,这意味着用户需要是一个sudoer,并且程序将始终具有root特权。
Another solution, which I strongly prefer (since the user will not have to be added to sudoers) is to change the program's owner to root, and set the setuid
bit. (I learned this from here).
另一种解决方案是将程序的所有者更改为root,并设置setuid位(因为用户不必添加到sudoers中)。(我从这里学到的)。
However, there's something I'm wondering about. What I would like to do is open the sysfs files while the program's euid
is 0, but then drop all privileges right away (for safety). Then, now that the file has been opened, we simply setuid()
to the user's UID. However, although I can't be entirely sure, this isn't working. Here is the relevant part of my code:
然而,有件事我很好奇。我想做的是在程序的euid为0时打开sysfs文件,然后立即删除所有特权(为了安全)。然后,既然文件已经打开,我们只需将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);
So it seems that I will need to keep elevated permissions to be able to read from /sys/class/gpio/gpio971/value
. But this is exactly what I don't want! This program will need to poll the value throughout execution of the program, and I don't want root privileges the whole time.
因此,我似乎需要保持较高的权限才能读取/sys/class/gpio/gpio971/value。但这正是我不想要的!这个程序需要在整个程序执行过程中轮询值,而且我不希望一直使用root特权。
Finally for the sake of completion, here are the permissions I've set on my executable:
最后,为了完成这个任务,我在可执行文件上设置了以下权限:
-rwsr-xr-x 1 root myuser 10943 Jan 1 20:17 main*
So how does one drop root privilege, but continue to read from an access-controlled sysfs file?
那么,如何删除根特权,而继续从访问控制的sysfs文件中读取?
1 个解决方案
#1
0
I haven't tried this with /sysfs
, but even with plain files my understanding is that file streams do not retain access permissions after a call to setuid()
. File handles do, however, for reasons I don't understand. So, if your system behaves like mine (Fedora 20 on x64) you might be able to use open()
/read()
instead of fopen()
/fscanf()
.
我还没有尝试使用/sysfs,但是即使使用普通文件,我的理解是,在调用setuid()之后,文件流也不会保留访问权限。然而,文件句柄却可以,因为我不明白的原因。因此,如果您的系统的行为与我的(x64上的Fedora 20)类似,您可能可以使用open()/read()而不是fopen()/fscanf()。
#1
0
I haven't tried this with /sysfs
, but even with plain files my understanding is that file streams do not retain access permissions after a call to setuid()
. File handles do, however, for reasons I don't understand. So, if your system behaves like mine (Fedora 20 on x64) you might be able to use open()
/read()
instead of fopen()
/fscanf()
.
我还没有尝试使用/sysfs,但是即使使用普通文件,我的理解是,在调用setuid()之后,文件流也不会保留访问权限。然而,文件句柄却可以,因为我不明白的原因。因此,如果您的系统的行为与我的(x64上的Fedora 20)类似,您可能可以使用open()/read()而不是fopen()/fscanf()。