我编写的Python扩展需要root访问才能执行单个硬件初始化调用.我宁愿不以root身份运行整个脚本只是为了我的扩展中的这一个调用,所以我想编写一个包装器来执行此初始化,然后再下载到用户权限并运行实际脚本.
我打算让这个包装器运行sudo,例如
$ sudo devwrap python somescript.py
Run Code Online (Sandbox Code Playgroud)
我正在考虑类似的东西(更新以修复几个错误):
int main(int argc, char * argv[])
{
if(argc < 2) return 0;
int res = do_hardware_init();
if(res != OK_VALUE)
{
// Print error message
return HW_ERR;
}
const char *sudo_uid = getenv("SUDO_UID");
if(sudo_uid)
{
int real_uid = (int) strtol(sudo_uid, NULL, 0);
setuid(real_uid);
}
return execvp(argv[1], &argv[1]); // No return if successful
}
Run Code Online (Sandbox Code Playgroud)
所以我有三个问题:
execvp电话看起来有点奇怪,但据我所知它在正确的地方有争议).execvp手册页说"不应该直接通过应用程序访问环境数组" - 这是否会使getenv调用成为一个坏主意?execvp,所以我可以这样做sudo devwrap somescript.py(注意没有"python")getenv()不是environ直接访问数组 - 这是干净的。直接访问environ数组意味着“strcpy(buffer,environ [3])”或类似的东西。#!/usr/bin/env python也许)开头,那么您已经可以做您想做的事情了 -somescript.py当然,该脚本必须是可执行的。我在第一部分中看到的问题取决于您如何处理硬件初始化中的错误。如果省略的错误处理不退出,那么当不通过“sudo”运行时,您可能会得到核心转储(或段错误),因为您strtol()在空指针上运行。如果do_hardware_init()它本身因失败而退出,那么没有问题,除非用户找到一种方法来从“sudo”破坏环境。我真的认为如果 SUDO_UID 未正确设置,您应该验证环境并退出并显示错误。root 想要运行这个扩展吗?
我没有查看 的规范,sudo发现它确实设置了 SUDO_UID 环境变量 - 我认为您是正确的。
用户输入此内容会产生什么后果?
sudo devwrap ls
Run Code Online (Sandbox Code Playgroud)
它执行硬件初始化,重置 UID,然后运行ls- 可能不会太有害,但可能不是您想要的。这有关系吗?你能控制吗?
如果参数计数小于 2,您可能应该给出错误退出,而不是成功退出。
要求人们通过“sudo”运行扩展是非常不传统的。
您确定没有其他方法可以实现吗?初始化有什么要求?是对所有进程执行一次,还是每个进程执行一次(因此链接至关重要)?
你能简单地让 devwrap 程序成为 SUID root 吗?然后您需要以不同的方式重置 UID:
setgid(getgid());
setuid(getuid());
Run Code Online (Sandbox Code Playgroud)
这会在执行命令之前删除任何 SGID 性和任何 SUID 性。造成重大损害是相当困难的。目前尚不清楚,setgid()如果程序安装时没有 SGID,则该调用是否是强制的,但也没有什么坏处。