代码之家  ›  专栏  ›  技术社区  ›  detly FBruynbroeck

setuid包装的注意事项

  •  5
  • detly FBruynbroeck  · 技术社区  · 14 年前

    我编写的一个Python扩展需要根访问来执行一个硬件初始化调用。我不想只为扩展中的这个调用以根用户的身份运行整个脚本,所以我想在放弃用户权限并运行实际脚本之前编写一个包装器来进行初始化。

    我打算把这个包装袋 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 call看起来也有点奇怪,但据我所见,它的论点是正确的。
    2. 这个 执行副总裁 曼佩奇说 “应用程序不应直接访问环境数组” -这是否使 getenv 叫个坏主意?
    3. 有比这更好的电话吗 执行副总裁 ,所以我可以 sudo devwrap somescript.py (注意没有“python”)
    1 回复  |  直到 14 年前
        1
  •  1
  •   Jonathan Leffler    14 年前
    1. 有点理智…下面更多。
    2. 使用 getenv() 无法访问 environ 直接排列-很干净。访问 环境 数组直接表示“strcpy(buffer,environ[3])”或类似的词。
    3. 如果剧本开头是一个爆炸( #!/usr/bin/env python ,也许),你已经可以做你想做的了- somescript.py 当然,必须是可执行的。

    我在第一部分中看到的问题取决于如何处理硬件初始化中的错误。如果省略错误处理不退出,那么当您通过“SUDO”运行时,您可以获得核心转储(或SeStore),因为您运行 strtol() 在空指针上。如果 do_hardware_init() 在失败的情况下退出,没有问题,除非用户找到一种方法来从“SUDO”中颠覆环境。我真的认为你应该验证环境,如果错误地设置SdodouuID,则退出一个错误。根目录是否要运行此扩展?

    我没看过 sudo 要查看它是否设置了SUDO_UID环境变量-我认为您在这方面是正确的。

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

    sudo devwrap ls
    

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

    如果参数计数小于2,则应该给出错误退出,而不是成功退出。


    要求人们通过“sudo”运行扩展是非常不传统的。

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


    你能简单地使devwrap程序成为SUID根目录吗?然后需要以不同的方式重置UID:

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

    在执行命令之前删除任何SGID和SUID。很难造成重大损害。不清楚的是 setgid() 如果程序安装时没有SGID,则调用是必需的,但它也不会造成损害。