You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux SUID程序调用execv后未保留euid问题咨询

解决SUID程序中exec bash后特权丢失的问题

这个问题我之前排查过,核心原因是bash在SUID模式启动时会主动放弃特权,咱们来一步步拆解分析:

问题场景回顾

你编写的test.c代码片段:

printf("ruid:%d, euid:%d\n",getuid(),geteuid()); 
char *args[] = {"/bin/bash","-c","exec id",0}; 
execv("/bin/bash",args);

通过以下命令编译并设置SUID位:

sudo gcc test.c -o test
sudo chmod +s ./test

程序属主为root,运行后printf输出符合预期:ruid:1000, euid:0,但后续执行的id命令却显示ruid和euid均为1000。

原因分析

你的SUID程序确实成功获取了root的有效用户ID(euid=0),这点从printf的输出可以确认。但问题出在/bin/bash的安全机制上:
当bash检测到自身是以SUID方式启动(即有效用户ID euid和实际用户ID ruid不一致)时,会自动将euid重置为ruid,主动放弃特权身份。所以当bash启动后,它已经把权限降回了普通用户(ruid=1000),此时再执行exec id,自然会显示普通用户的身份信息。

解决方案

根据你的实际需求,有几种可行的解决方式:

1. 直接执行id,跳过bash中转

不需要通过bash来执行id,直接调用execv运行id程序,这样就能保留SUID带来的特权:

printf("ruid:%d, euid:%d\n",getuid(),geteuid()); 
char *args[] = {"/usr/bin/id", NULL}; 
execv("/usr/bin/id", args);

运行后,id会正确显示euid=0。

2. 用bash的-p参数强制保留特权

bash提供了-p参数,用来关闭自动丢弃特权的行为,让它保留当前的euid身份。修改你的args数组即可:

printf("ruid:%d, euid:%d\n",getuid(),geteuid()); 
char *args[] = {"/bin/bash","-p","-c","exec id",0}; 
execv("/bin/bash",args);

添加-p后,bash不会重置euid,执行id就能看到正确的特权信息了。

3. 手动切换实际用户ID为root(谨慎使用)

如果你的程序需要全程以root身份运行,可以在exec之前调用setuid(0),将实际用户ID也设置为root:

printf("ruid:%d, euid:%d\n",getuid(),geteuid());
setuid(0); // 将实际用户ID切换为root
char *args[] = {"/bin/bash","-c","exec id",0}; 
execv("/bin/bash",args);

⚠️ 注意:这种方法会让程序全程拥有root权限,存在一定安全风险,只有在确实需要时才使用。

内容的提问来源于stack exchange,提问作者dcnh35

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:34:57