首页 > 解决方案 > 从系统 c++ 函数调用 shell 脚本,使 shell 脚本以不同的用户身份运行

问题描述

我正在使用系统 c++ 调用来执行调用程序以 root 身份运行的 shell 脚本,但是从 c++ 代码中调用的 shell sctipt 以不同的用户身份运行。

如何确保 shell 脚本也应该像 c++ 二进制文件一样以 root 用户身份运行。我不想依赖使用 sudo 命令,因为它可以要求输入密码。

> [user@user ~]$ ll a.out temp.sh
> -rwsrwsr-x 1 root     root     8952 Jun 14 13:16 a.out
> -rwxrwxr-x 1 user     user   34 Jun 14 15:43 temp.sh
[user@user ~]$ cat temp.sh

#!/bin/bash read -n 1 -p "Hello"

[user@user ~]$ ps aux | grep temp 
root     13247  0.0  0.0  13252 1540 pts/0    S+   15:44   0:00 ./a.out ./temp.sh 
user 13248  0.0  0.0 113152  2544 pts/0    S+   15:44   0:00 /bin/bash ./temp.sh 

c++代码

#include <bits/stdc++.h>
using namespace std;
int main(int argc, char *argv[])
{
system(argv[1]);
return 0;
}

标签: c++linuxbashshell

解决方案


一些文档开始:

man 3 system的警告部分:

不要使用system()特权程序(set-user-ID 或 set-group-ID 程序,或具有功能的程序),因为某些环境变量的奇怪值可能会破坏系统完整性。例如,PATH可以操纵任意程序以特权执行。改用exec(3)函数族,但不使用execlp(3)or execvp(3)(也使用PATH环境变量来搜索可执行文件)。

system()事实上,在/bin/shbash 版本 2 的系统上,具有 set-user-ID 或 set-group-ID 权限的程序无法正常工作:作为一项安全措施,bash 2 在启动时会放弃权限。Debian 使用不同的 shell,dash(1)当作为 sh 调用时它不会这样做。)

并且来自bash 手册-p对命令行参数的描述(添加了重点):

开启特权模式。在此模式下,不处理$BASH_ENVand$ENV文件,不从环境继承 shell 函数,并且如果出现在环境中的 , 和 变量将被SHELLOPTS忽略。如果 shell 以不等于真实用户(组)标识的有效用户(组)标识启动,并且未提供 -p 选项,则执行这些操作并将有效用户标识设置为真实用户标识。如果在启动时提供了 -p 选项,则不会重置有效用户 ID。关闭此选项会导致有效用户和组 ID 设置为真实用户和组 ID。BASHOPTSCDPATHGLOBIGNORE

因此,即使您/bin/sh在运行时没有放弃特权,bash也会在没有明确告诉它不要的情况下依次运行。

因此,一种选择是废弃使用system(),并执行较低级别的fork()/ exec()bash -p your-script-name

Allow suid on shell scripts中提到了允许脚本以提升的权限运行的其他一些方法。特别是setuid()用于更改真实 UID 的答案看起来值得研究。

或者配置sudo为不需要给定用户的特定脚本的密码。


另请参阅我为什么不应该#include <bits/stdc++.h>


推荐阅读