Python脚本的setuid/setgid包装器
我有一个Python脚本,想让它以系统用户guybrush
的身份运行,这个用户的UID是200,组名也是guybrush
,组ID是200。
目前我的Python脚本(放在/path/to/script.py
)是这样的:
#!/usr/bin/env python2
import os
print "uid: %s" % os.getuid()
print "euid: %s" % os.getgid()
print "gid: %s" % os.geteuid()
print "egid: %s" % os.getegid()
我尝试写的C语言包装器(scriptwrap.c
)是这样的:
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
setuid(geteuid());
setgid(getegid());
return execv("/path/to/script.py", argv);
}
然后我编译、修改文件所有者和权限,步骤如下:
$ gcc scriptwrap.c -o scriptwrap
$ chown guybrush:guybrush scriptwrap
$ chmod 6755 scriptwrap
但是当我运行这个包装器时,得到的输出是:
uid: 1000
euid: 1000
gid: 200
egid: 200
所以不知为什么,只有组ID被设置了(我正常的用户ID是1000)。我该怎么解决这个问题呢?
补充:如果我把脚本的所有者改成root:root
并运行它,UID、eUID、GID和eGID都会被设置为0。
另外,我是在Ubuntu 12.04.4 LTS上进行的操作。
1 个回答
6
我搞明白了这个问题(在这个过程中也学到了一些东西)。尴尬的是,我最开始的问题是因为我在Python脚本中打错了字:我把GID打印在了euid
的标签下,而把eUID打印在了gid
的标签下。哎呀。
所以其实eUID和eGID设置得是正确的——太好了。但是尽管我在C语言的包装中使用了setuid
和setgid
,UID和GID还是没有设置。
结果发现,这跟setuid
和setgid
的行为有关,具体取决于你是不是root
用户:如果你是root用户,调用setuid
会把你的真实UID和有效UID都设置成你传入的值;如果你不是root用户,它只会设置有效UID(来源)。所以我使用setuid
(和setgid
)实际上是没什么作用的。
不过,可以通过使用setreuid
和setregid
来设置真实的UID和GID:
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
setreuid(geteuid(), geteuid());
setregid(getegid(), getegid());
return execv("/path/to/script.py", argv);
}
这样在运行(修正过的)Python脚本时,会得到以下输出:
uid: 200
euid: 200
gid: 200
egid: 200