【问题标题】:Considerations for a setuid wrappersetuid 包装器的注意事项
【发布时间】:2010-12-09 12:28:32
【问题描述】:

我编写的 Python 扩展需要 root 访问权限才能执行单个硬件初始化调用。我宁愿不为我的扩展程序中的这个调用以 root 身份运行整个脚本,所以我想编写一个包装器来执行此初始化,然后再降低到用户权限并运行实际脚本。

我打算通过sudo 运行这个包装器,例如

$ sudo devwrap python somescript.py

我正在考虑类似(更新以修复几个错误):

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

}

所以我有三个问题:

  1. 这看起来很正常吗?我通常不需要弄乱 *uid() 调用,所以我不熟悉常见的陷阱。 execvp 调用也看起来有点奇怪,但据我所知,它在正确的位置有参数)。
  2. execvp 手册页说 “应用程序不应直接访问 environ 数组” - 这是否使调用 getenv 成为一个坏主意?
  3. 有没有比execvp 更好的调用,所以我可以调用sudo devwrap somescript.py(注意没有“python”)

【问题讨论】:

    标签: c setuid


    【解决方案1】:
    1. 有点理智……更多内容如下。
    2. 使用getenv() 不会直接访问environ 数组——这很干净。直接访问 environ 数组意味着 'strcpy(buffer, environ[3])` 或类似的东西。
    3. 如果脚本以 shebang 开头(可能是#!/usr/bin/env python),您可以做您想做的事 - 当然,somescript.py 必须是可执行的。

    我在第一部分看到的问题取决于您如何处理硬件初始化中的错误。如果省略的错误处理没有退出,那么当您没有通过“sudo”运行时,您可能会获得核心转储(或段错误),因为您在空指针上运行strtol()。如果do_hardware_init() 本身在失败时退出,则没有问题,除非用户找到一种方法来从“sudo”中颠覆环境。我真的认为如果 SUDO_UID 的设置不合理,你应该验证环境并退出错误。 root 想运行这个扩展吗?

    我没有查看 sudo 的规范,看它确实设置了 SUDO_UID 环境变量 - 我假设你是正确的。

    用户输入这个会有什么后果?

    sudo devwrap ls
    

    它会进行硬件初始化,重置 UID,然后运行 ​​ls - 可能不会太有害,但可能不是您想的那样。这有关系吗?你能控制它吗?

    如果参数计数小于两个,您可能应该给出错误退出,而不是成功退出。


    要求人们通过 'sudo' 运行扩展是非常规的。

    您确定没有其他方法可以实现它吗?初始化有什么要求?是对所有进程执行一次,还是每个进程执行一次(因此链接至关重要)?


    您可以简单地将 devwrap 程序设置为 SUID 根吗?然后,您需要以不同方式重置 UID:

    setgid(getgid());
    setuid(getuid());
    

    这会在执行命令之前删除任何 SGID 和任何 SUID。很难造成重大伤害。如果程序在没有 SGID 的情况下安装,则不清楚 setgid() 调用是否是强制性的,但它也没有任何害处。

    【讨论】:

    • 您确定没有其他方法可以实现吗? 不,我没有,但我想不出其他方法。如果初始化调用不是以 root 身份运行的,它会失败,完全停止。我不认为每个进程都需要它
    • ...但这没有记录。不过,我会感到惊讶,它似乎只是内存映射的控制寄存器。
    • 很抱歉这么久才接受这个。我决定听从你的建议,走 SUID 路线。
    猜你喜欢
    • 1970-01-01
    • 2014-08-23
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 2010-11-16
    相关资源
    最近更新 更多