TL; DR
我正在写一个C程序。我需要具有root特权才能fopen
sysfs文件,并且仍然需要root特权才能从中读取文件。但是,由于我的程序将需要连续读取sysfs文件,因此这意味着它始终需要具有提升的特权。我想尽快放弃root特权。解决这个问题的公认方法是什么?
细节
我正在编写一个与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
我需要在非特权用户可以调用的C程序中运行这些命令。一种方法是使用
fopen
,fprintf
,fscanf
等以通常的方式编写程序,并让用户通过sudo
运行程序。但是,这意味着用户需要是sudoer,并且程序将始终具有root特权。我强烈推荐的另一种解决方案(因为不必将用户添加到sudoers中)将程序的所有者更改为root,并设置
setuid
位。 (我从here中学到了这一点)。但是,有些事情我想知道。我想做的是在程序的
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);
因此,似乎需要保留较高的权限才能从
/sys/class/gpio/gpio971/value
进行读取。但这正是我所不想要的!该程序将需要在程序的整个执行过程中轮询该值,并且我不希望一直拥有root特权。最后,为了完整起见,这是我对可执行文件设置的权限:
-rwsr-xr-x 1 root myuser 10943 Jan 1 20:17 main*
那么如何放弃root特权,而又继续从访问控制的sysfs文件中读取呢?
最佳答案
我还没有尝试过使用/sysfs
进行此操作,但即使使用普通文件,我的理解是,在调用setuid()
之后,文件流不会保留访问权限。但是,由于我不明白的原因,文件句柄可以。因此,如果您的系统表现得像我的(x64上的Fedora 20),则可以使用open()
/read()
代替fopen()
/fscanf()
。