使用os.setuid()时出现“操作不允许”

6 投票
5 回答
18391 浏览
提问于 2025-04-17 02:55

我正在尝试搭建一个平台,用来启动一些脚本。这些脚本放在每个用户的主文件夹里。每次启动脚本时都需要用到每个用户的ID,所以我对每个用户都做了以下操作:

user_id = pwd.getpwnam( user )[ 3 ]
user_home = pwd.getpwnam( user )[ 5 ]

os.chdir( user_home )
os.setuid( user_id )

subprocess.Popen( shlex.split( "user_script.py" ) )

但是,当Python尝试执行 os.setuid( user_id ) 时,会抛出一个异常:

Traceback (most recent call last):
  File "launcher.py", line XX, in <module>

OSError: [Errno 1] Operation not permitted

顺便说一下,启动这个脚本的用户属于根组(在GNU/Linux操作系统上),并且拥有所有的根权限。

如果我尝试用根用户来启动相同的代码,我会得到一个不同的错误:

OSError: [Errno 13] Permission denied

如果有人能帮我理解发生了什么,那就太好了……

5 个回答

0

OSError: [Errno 1] Operation not permitted 这个错误意思是,运行这个脚本的用户权限不够。仅仅是属于根用户组是不够的,实际上还需要有CAP_SETUID这个特权。

OSError: [Errno 13] Permission denied 这个错误可能和前面的错误没有关系。你应该查看一下它的错误追踪信息。

2

只有超级用户才能随时更改用户的身份标识符(uid),仅仅把用户加入到根用户组是不够的。

setuid(2) 这个函数的说明中提到:

 The setuid() system call is permitted if the specified ID is equal to the
 real user ID or the effective user ID of the process, or if the effective
 user ID is that of the super user.

在Linux系统中,还有:

   Under Linux, setuid() is implemented like the POSIX version with the 
   _POSIX_SAVED_IDS feature.  This allows a set-user-ID (other than  root)
   program to drop all of its user privileges, do some un-privileged work, and
   then reengage the original effective user ID in a secure manner.

我甚至不知道Python是否直接实现了这个功能,但这也不是你真正想要的。

所以简单来说:要以根用户身份启动初始进程。

如果你担心安全问题,可以启动两个进程,一个以根用户身份运行,另一个以普通用户身份运行,让普通用户的进程通过套接字与根用户的进程进行通信。不过,这种设置比较复杂……

5

只有超级用户(root)才能执行setuid操作,单单是属于root组是不够的。

撰写回答