linux进程的权限,Linux进程权限问题

来源

chengyaogen.blog.chinaunix.net

一、进程与权限

A.进程时Linux/Unix操作系统中最重要的抽象之一

B.进程是一个处于执行期的程序(目标代码存储在某种介质上)

A    process   is   a  program(object  code  stored  on some  media)  in the  midst  of

execution.

而进程在执行过程中经常涉及到文件访问操作等

1.一个运行中的进程究竟可以访问哪些资源,而不能访问哪些资源?

2.一个进程运行过程中如何实现在某个执行阶段拥有一些权限而在另一个阶段又具备另外一种权限呢?

上述状况对应于进程的访问权限以及进程执行中不同权限的切换。这一切都和进程实际用户ID,进程有效用户ID,进程保存设置用户ID有关联。

二、进程的用户ID

1.实际用户ID(real user id,RUID)

为该进程的创建者的用户ID,也可以说是进程的执行者。该ID仅root用户可以修改

2.有效用户ID(effective  user  id,EUID)

该ID用户标识用户进程执行操作的权限。例如:如果EUID是0即(root),此时进程拥有root用户权限。普通用户可以将EUID设置为RUID或者SUID,而超级用户可以将EUID设置为任意的合法UID。

注意:对于一个可执行的二进制文件,如果其set-user-id bit被设置,则运行改程序时,对应进程的有效用户ID(EUID)为该文件的文件所有者用户ID。

3.保存设置用户ID(saved set-user-id,SUID)

对于没有设置set-uid-bit的可执行程序而言,其对应进程的保存设置用户ID(SUID)为其实际用户ID;而对于设置了set-uid-bit的程序而言,其对应的保存设置用户ID(SUID)为该可执行文件的文件拥有者用户ID。只能root用户权限,才能更改(当一个程序文件运行的时候,其值已经确定)。

注意:linux不提供返回保存的设置-用户-ID的函数

总结:

RUID代表此进程是哪个用户创建的, EUID代表此进程所拥有的权限,SUID保存了EUID,当EUID改变后,如果想回到以前的EUID,此时SUID将发挥作用。

三、相关API

#include

#include

int   setuid(uid);

可以用setuid函数设置实际用户ID和有效用户ID。注意,我们并不能想怎么设就怎么设。有若干规则需要我们遵守:

(1)若进程具有超级用户特权,则setuid函数将实际用户ID、有效用户ID,以及保存的设置-用户-D设置为uid。

(2)若进程没有超级用户特权,但是uid等于实际用户ID或保存的设置-用户-ID,则setuid只将有效用户ID设置为。不改变实际用户ID和保存的设置-用户-ID。

(3)如果上面两个条件都不满足,则errno设置为EPERM,并返回出错.。

关于内核所维护的三个用户ID,还要注意下列几点

(1)只有超级用户进程可以更改实际用户ID。通常,实际用户ID是在用户登录时,由login(1)程序设置的,而且决不会改变它。因为login是一个超级用户进程,当它调用setuid时,设置所有三个用户ID。

(2)仅当对程序文件设置了 set-user-id bit时,exec函数设置有效用户ID为文件所有者。如果set-user-id bit没有设置,则exec函数不会改变有效用户ID,而将其位置原先值。任何时候都可以调用setuid,将有效用户ID设置为实际用户ID或保存的设置-用户-ID。自然,不能讲有效用户ID设置为任意随机值。

四、探究

案例一:

有个要在MacOS上实现一个关机程序,它熟悉linux,其实老祖宗都是unix,所以MacOS对他并不陌生。如下他写了如下程序实现关机

0818b9ca8b590ca3270a3433284dd417.png

编译运行:

0818b9ca8b590ca3270a3433284dd417.png

从上面看,这段代码可以实现关机,但是有个不符合要求的地方,运行程序不能是超级用户,只能是普通用户。

他很苦恼,后来找到了我,我做了如下事情

0818b9ca8b590ca3270a3433284dd417.png

呵呵,可以了。我将这个可执行文件的owner和group都改为了root,然后有讲其set-user-id bit位加以了设置。这样以普通用户运行这个程序时,此进程的EUID就是root了,这样满足了shutdown命令执行的权限。

案例二:

#include

#include

#include

#include

#include

#include

void test_read_file(const char *name)

{

int fd = -1;

fd = open(name ,O_RDWR);

if(fd < 0){

printf("=[ERROR]:read failed.\n");

}else{

printf("=[OK]:read successful\n");

close(fd);

}

}

//打印uid和euid

void p_states()

{

int uid = 0;

int euid = 0;

printf("------Current states--------\n");

printf("real uid\t %d\n",getuid());

printf("effective uid\t %d\n",geteuid());

printf("----------------------------\n");

}

//调用setuid

void run_setuid_fun(int uid)

{

if(setuid(uid) == -1)

{

printf("=[ERROR]:setuid(%d) error\n",uid);

}

p_states();

}

//调用setuid

void run_seteuid_fun(int uid)

{

if(setuid(uid) == -1)

{

printf("=[ERROR]:seteuid(%d) error\n",uid);

}

p_states();

}

int main()

{

int t_re = 0;

const char *file = "root_only.txt";

printf("\nTEST 1:\n");

p_states();

//此时real uid = login user id

//effective uid = root

//saved uid = root

test_read_file(file);

getchar();

printf("\nTEST 2:setuid(getuid())\n");

run_seteuid_fun(getuid());

//此时real uid = login user id

//effective uid = login user id

//saved uid = root

test_read_file(file);

getchar();

printf("\nTEST 3:setuid(0)\n");

run_setuid_fun(0);

//此时real uid = login user id

//effective uid = root

//saved uid = root

test_read_file(file);

getchar();

printf("\nTEST 4:setuid(0)\n");

run_setuid_fun(0);

//此时real uid = root

//effective uid = root

//saved uid = root

test_read_file(file);

getchar();

printf("\nTEST 5:setuid(503)\n");

run_setuid_fun(503);

//此时real uid = login user id

//effective id = login user id

//saved uid = login user id

test_read_file(file);

getchar();

printf("\nTEST 6:setuid(0)\n");

//read uid = login user id

//effective uid = login user id

//saved uid = login user id

run_setuid_fun(0);

test_read_file(file);

return 0;

}

编译运行:

0818b9ca8b590ca3270a3433284dd417.png

root_only.txt文件建立:

0818b9ca8b590ca3270a3433284dd417.png

第一次:

RUID:实际用户

EUID:文件所有者(root)

SUID:文件所有者(root)

0818b9ca8b590ca3270a3433284dd417.png

此时进程拥有root用户权限,能对

root_only.txt

进行读写操作

第二次:

此时普通用户调用setuid(getuid()),只会将EUID改为getuid(),其他都不变

RUID:实际用户

EUID:实际用户

SUID:root

0818b9ca8b590ca3270a3433284dd417.png

此时进程没有有root用户权限,不能能对

root_only.txt

进行读写操作

第三次:

此时普通用户调用seteuid(0),只会将EUID改为0,其他都不变

RUID:实际用户

EUID:root

SUID:root

0818b9ca8b590ca3270a3433284dd417.png

此时进程拥有root用户权限,能对

root_only.txt

进行读写操作

第四次:

此时进程拥有root用户权限,调用setuid(0),会将三个ID都设置为0

RUID:root

EUID:root SUID:root

0818b9ca8b590ca3270a3433284dd417.png

此时进程拥有root用户权限,能对

root_only.txt

进行读写操作

第五次:

此时进程拥有root用户权限,调用setuid(503),会将三个ID都设置为503

RUID:503

EUID:503

SUID:503

0818b9ca8b590ca3270a3433284dd417.png

此时进程拥有普通用户权限,不能对

root_only.txt

进行读写操作

第六次:

此时进程拥有普通用户权限,调用setuid(0),此时RUID,SUID都不为0,这一次操作将失败

RUID:503

EUID:503

SUID:503

0818b9ca8b590ca3270a3433284dd417.png

此时进程拥有普通用户权限,不能能对

root_only.txt

进行读写操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值