简体   繁体   English

在 uvloop 中使用 os.setuid() 拒绝权限

[英]Permission denied with os.setuid() in uvloop

I need to run a subprocess in my main process as "nobody" user, code like this:我需要在我的主进程中以“nobody”用户身份运行一个子进程,代码如下:

# os.setuid(65534)  # out the set_id work fine!!

logging.warning(f"outside user: {getpass.getuser()}")
# output: outside user: root

def set_id() -> None:
    logging.warning(f"sub !sub! process user id is {os.getuid(), os.getgid(), os.getgroups()}!!!!!!!!!!!!")
    # output: root:sub !sub! process user id is (0, 0, [])!!!!!!!!!!!!
    assert os.getuid() == 0

    logging.warning(f"inside user: {getpass.getuser()}")
    # output: inside user: root

    # os.setgid(65534)  # work fine
    os.setuid(65534)  # can't work

pro = await asyncio.subprocess.create_subprocess_exec(
    # *tmp_cmd,
    "ls",
    stdout=asyncio.subprocess.PIPE,
    stdin=asyncio.subprocess.PIPE,
    stderr=asyncio.subprocess.PIPE,
    cwd=self._cwd,
    preexec_fn=set_id,
    start_new_session=True,
    close_fds=True,
)

When I call os.setuid(65534) , raise an error PermissionError: [Errno 13] Permission denied .当我调用os.setuid(65534)时,引发错误PermissionError: [Errno 13] Permission denied
But os.setgid(65534) work fine.但是os.setgid(65534)工作正常。
Extra info:额外信息:

  • Inside the set_id function, os.getuid(), os.getgid(), os.getgroups() 's out is (0, 0, [])set_id function 里面, os.getuid(), os.getgid(), os.getgroups()的出来是(0, 0, [])
  • Outside the set_id , os.setuid(65534) work fine.set_id之外, os.setuid(65534)工作正常。
  • getpass.getuser() == "root"

That's why?这就是为什么? How can I fix this?我怎样才能解决这个问题? Thanks in advance.提前致谢。
Traceback:追溯:

ERROR:uvicorn.error:Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/uvicorn/protocols/websockets/websockets_impl.py", line 153, in run_asgi
    result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
  File "/usr/local/lib/python3.7/dist-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/fastapi/applications.py", line 149, in __call__
    await super().__call__(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/applications.py", line 102, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/middleware/errors.py", line 146, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/middleware/cors.py", line 68, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/exceptions.py", line 58, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/routing.py", line 550, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/routing.py", line 283, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/routing.py", line 57, in app
    await func(session)
  File "/usr/local/lib/python3.7/dist-packages/fastapi/routing.py", line 209, in app
    await dependant.call(**values)
  File "/opt/MakerServer/app/api/routes/websockets_runner/runner.py", line 21, in wss_back
    process = await WSProcess.create(file_m, ws=websocket)
  File "/opt/MakerServer/app/services/processer.py", line 100, in create
    self.proc: asyncio.subprocess.Process = await self._create_sub_process()  # type: ignore
  File "/opt/MakerServer/app/services/processer.py", line 136, in _create_sub_process
    close_fds=True,
  File "/usr/lib/python3.7/asyncio/subprocess.py", line 217, in create_subprocess_exec
    stderr=stderr, **kwds)
  File "uvloop/loop.pyx", line 2749, in subprocess_exec
  File "uvloop/loop.pyx", line 2707, in __subprocess_run
  File "uvloop/handles/process.pyx", line 596, in uvloop.loop.UVProcessTransport.new
  File "uvloop/handles/process.pyx", line 98, in uvloop.loop.UVProcess._init
PermissionError: [Errno 13] Permission denied

The question does not provide all the elements, but here is what I would see:这个问题没有提供所有元素,但这是我会看到的:

  • os.setuid cannot generate an errno of 13. A permission error from setuid would be EPERM , which is errno 1. os.setuid无法生成 13 的 errno。来自setuid的权限错误将是EPERM ,即 errno 1。
  • therefore, I believe it's not the os.setuid that generates the exception.因此,我相信不是os.setuid会产生异常。
  • my guess would be that the exception is generated after your set_id function returns, when Popen tries to open some file as user 65534 (it could be the target executable, some library or some config file that gets loaded down the line).我的猜测是在您的set_id function 返回生成异常,当 Popen 尝试以用户 65534 身份打开某个文件(它可能是目标可执行文件、某个库或某个配置文件被加载到该行)。

How to proceed to solve this:如何着手解决这个问题:

  • confirm the issue by adding a try catch block around os.setuid .通过在os.setuid周围添加try catch块来确认问题。 I'm 99% sure it won't trigger.我有 99% 的把握它不会触发。
  • then try to run your command from the shell with su as nobody user.然后尝试从 shell 以su为无人用户运行您的命令。 Most likely you'll get the same error.很可能你会得到同样的错误。

You can also use strace -f on your program to see which system call fails and what parameters it is invoked with.您还可以在程序上使用strace -f来查看哪个系统调用失败以及调用它的参数。 That should point you in the right direction.那应该为您指明正确的方向。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM