在 uvloop 中使用 os.setuid() 拒绝权限
Permission denied with os.setuid() in uvloop
我需要 运行 作为 "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,
)
当我调用 os.setuid(65534)
时,引发错误 PermissionError: [Errno 13] Permission denied
。
但是 os.setgid(65534)
工作正常。
额外信息:
- 在
set_id
函数中,os.getuid(), os.getgid(), os.getgroups()
的输出是
(0, 0, [])
- 在
set_id
之外,os.setuid(65534)
工作正常。
getpass.getuser() == "root"
这是为什么?我怎样才能解决这个问题?提前致谢。
回溯:
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
问题没有提供所有的要素,但这是我会看到的:
os.setuid
无法生成 13 的错误号。来自 setuid
的权限错误将是 EPERM
,即错误号 1。
- 因此,我认为产生异常的不是
os.setuid
。
- 我的猜测是当 Popen 尝试以用户 65534(它可能是目标可执行文件、一些库或一些在线加载的配置文件)。
如何继续解决这个问题:
- 通过在
os.setuid
周围添加 try
catch
块来确认问题。我 99% 确定它不会触发。
- 然后尝试从 shell 以
su
作为 nobody 用户 运行 你的命令。您很可能会遇到同样的错误。
您还可以在您的程序上使用 strace -f
来查看哪个系统调用失败以及调用时使用了哪些参数。那应该会为您指明正确的方向。
我需要 运行 作为 "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,
)
当我调用 os.setuid(65534)
时,引发错误 PermissionError: [Errno 13] Permission denied
。
但是 os.setgid(65534)
工作正常。
额外信息:
- 在
set_id
函数中,os.getuid(), os.getgid(), os.getgroups()
的输出是(0, 0, [])
- 在
set_id
之外,os.setuid(65534)
工作正常。 getpass.getuser() == "root"
这是为什么?我怎样才能解决这个问题?提前致谢。
回溯:
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
问题没有提供所有的要素,但这是我会看到的:
os.setuid
无法生成 13 的错误号。来自setuid
的权限错误将是EPERM
,即错误号 1。- 因此,我认为产生异常的不是
os.setuid
。 - 我的猜测是当 Popen 尝试以用户 65534(它可能是目标可执行文件、一些库或一些在线加载的配置文件)。
如何继续解决这个问题:
- 通过在
os.setuid
周围添加try
catch
块来确认问题。我 99% 确定它不会触发。 - 然后尝试从 shell 以
su
作为 nobody 用户 运行 你的命令。您很可能会遇到同样的错误。
您还可以在您的程序上使用 strace -f
来查看哪个系统调用失败以及调用时使用了哪些参数。那应该会为您指明正确的方向。