suid-root 没有效果

suid-root 没有效果

一个程序来自阿普埃

#include "apue.h"
#include <fcntl.h>

int main(int argc, char *argv[])
{
    if(argc!=2)
        err_quit("usage: a.out <pathname>");

    if(access(argv[1], R_OK)<0)
        err_ret("access error for %s",argv[1]);
    else
        printf("read access OK\n");
    if (open(argv[1], O_RDONLY)) {
        err_ret("open error for %s", argv[1]);
    } else {
        printf("open for reading OK\n");
    }

    return 0;
}

我将其编译为名为的可执行文件4-2,并更改了所有者并设置了 suid,这是以下输出ls -l

-rwsr-xr-x 1 root sinners 8490 Jan  7 18:50 4-2*

/etc/shadow

-rw------- 1 root root 421 Jan  4 01:29 /etc/shadow

但是当我运行它时:

user% ./4-2 /etc/shadow 
access error for /etc/shadow: Permission denied
open error for /etc/shadow: Permission denied

有人可以解释为什么我会收到这些access错误open吗?

答案1

引用access() 联机帮助页:

该检查是使用调用进程的真实 UID 和 GID 来完成的,而不是像实际尝试对文件进行操作(例如,open(2))时那样使用有效 ID。这使得设置用户 ID 程序可以轻松确定调用用户的权限。

设置用户 ID 位使进程的有效UID等于文件所有者,但真实用户 ID 保持不变(即保持之前的状态exec())。

您可以使用setreuid()修改进程的有效 UID 和真实 UID,或者您可以使用它open()来确定权限。我推荐第二种解决方案,特别是因为你已经打电话了open()。您可以检查是否errno等于来EPERM确定是否是权限不足导致open()失败。

open()代码中对 的调用失败,因为您使用返回值open()作为 if 条件。我猜想调用实际上成功了,并返回一个有效的非零(标准输入已采用零)文件描述符,使控件进入错误处理分支。 if 的错误处理分支显示EPERM错误消息,因为这是由于access()调用而发生的最后一个错误。进入错误处理分支的条件应该检查​​是否open()返回-1。

相关内容