简体   繁体   中英

Permission denied with os.setuid() in uvloop

I need to run a subprocess in my main process as "nobody" user, code like this:

# 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 .
But os.setgid(65534) work fine.
Extra info:

  • Inside the set_id function, os.getuid(), os.getgid(), os.getgroups() 's out is (0, 0, [])
  • Outside the set_id , os.setuid(65534) work fine.
  • 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.
  • therefore, I believe it's not the os.setuid that generates the exception.
  • 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).

How to proceed to solve this:

  • confirm the issue by adding a try catch block around os.setuid . I'm 99% sure it won't trigger.
  • then try to run your command from the shell with su as nobody user. 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. That should point you in the right direction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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