setuid包装器的注意事项 [英] Considerations for a setuid wrapper

查看:67
本文介绍了setuid包装器的注意事项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写的Python扩展程序需要root访问权限才能进行单个硬件初始化调用.我不想仅以扩展程序中的这个调用的root用户身份运行整个脚本,因此我想编写一个包装器以进行初始化,然后再使用用户权限并运行实际的脚本.

A Python extension I've written requires root access to do a single hardware initialisation call. I'd rather not run the whole script as root just for this one call in my extension, so I would like to write a wrapper to do this initialisation before dropping to user privileges and running the actual script.

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

I intend for this wrapper to be run via sudo, eg

$ 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手册页上说应用程序不应该直接访问环境数组" -这是否使getenv叫错了主意?
  3. 是否有比execvp更好的通话,所以我可以做sudo devwrap somescript.py(请注意缺少"python")
  1. Does this look sane? I don't usually need to mess with the *uid() calls, so I'm not familiar with the usual pitfalls. The execvp call also looks a little bizarre, but as far as I can see it has arguments in the right place).
  2. The execvp man page says that "The environ array should not be accessed directly by the application" - does this make the getenv call a bad idea?
  3. Is there a better call than execvp, so I can do sudo devwrap somescript.py (note absence of "python")

推荐答案

  1. 理智的排序...更多在下面.
  2. 使用getenv()不能直接访问environ数组-这很干净.直接访问environ数组意味着'strcpy(buffer,environ [3])`或类似的东西.
  3. 如果脚本以shebang(也许是#!/usr/bin/env python)开头,则您可以做自己想做的事-somescript.py必须是可执行文件.
  1. Sort of sane...more below.
  2. Using getenv() is not accessing the environ array directly - that is clean. Accessing the environ array directly means 'strcpy(buffer, environ[3])` or something like that.
  3. If the script starts with a shebang (#!/usr/bin/env python, perhaps), you can do what you want already - the somescript.py has to be executable, of course.

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

The problems I see with the first part depend on how you handle errors from the hardware initialization. If the omitted error handling does not exit, then you could get a core dump (or segfault) when not run via 'sudo' because you run strtol() on a null pointer. If do_hardware_init() itself exits on failure, there's no problem, unless the user finds a way to subvert the environment from 'sudo'. I really think you should validate the environment and exit with an error if SUDO_UID is not set plausibly. Would root want to run this extension?

我没有看过sudo的规范来确定它确实设置了SUDO_UID环境变量-我想您对此是正确的.

I've not looked at the specification of sudo to see that it does set the SUDO_UID environment variable - I assume you're correct on that.

用户键入此内容会有什么影响?

What are the ramifications of the user typing this?

sudo devwrap ls

它执行硬件初始化,重置UID,然后运行ls-可能不太有害,但可能与您的想法不符.那有关系吗你完全可以控制吗?

It does the hardware initialization, resets the UID, and then runs ls - probably not too harmful, but maybe not what you had in mind. Does that matter? Can you control that at all?

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

If the argument count is less than two, you should probably give an error exit, not a successful exit.

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

It is very unconventional to require people to run extensions via 'sudo'.

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

Are you sure there isn't another way to achieve it? What are the requirements on the initialization? Is it done once for all processes, or once per process (so the chaining is crucial)?

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

Can you simply make the devwrap program SUID root? You would then need to reset the UID differently:

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

这将在执行命令之前删除所有SGID-ness和任何SUID-ness.造成重大损害非常困难.尚不清楚如果未安装SGID的程序是否必须执行setgid()调用,但这也没有害处.

That removes any SGID-ness and any SUID-ness before executing the command. It's pretty hard to do significant damage. It isn't clear that the setgid() call is mandatory if the program is installed without SGID, but it does no harm either.

这篇关于setuid包装器的注意事项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆