【发布时间】:2020-10-15 03:42:21
【问题描述】:
我尝试使用call_usermodehelper 在 Linux 内核模块中执行用户空间二进制文件。我发现启动的应用程序正在以 root 模式运行。是否可以在用户模式下运行应用程序,例如命名为user1?
int alter_uid_gid(uid_t uid, gid_t gid, struct cred *new)
{
// struct cred *new;
new = prepare_creds();
if (!new)
return -ENOMEM;
new->uid = new->euid = new->suid = new->fsuid = KUIDT_INIT(uid);
new->gid = new->egid = new->sgid = new->fsgid = KGIDT_INIT(gid);
return commit_creds(new);
}
static int init_func(struct subprocess_info *info, struct cred *new)
{
printk("[%d]\n", current->pid);
alter_uid_gid(1000, 1000, new);
return 0;
}
static int user_process_fork(void *data)
{
struct subprocess_info *sub_info;
int ret = 0;
char *path = (char *)data;
char *argv[] = {path, NULL};
static char *envp[] = {"HOME=/", "TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL};
sub_info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC,
init_func, NULL, NULL);
if (sub_info == NULL) return -ENOMEM;
ret = call_usermodehelper_exec(sub_info, UMH_KILLABLE);
pr_info("%s: ret %d\n", __func__, ret);
do_exit(0);
return ret;
}
根据 Milag 的评论,我尝试使用 prepare_creds() 和 commit_creds(new) 更新 init_func() 中的 u[g/e/s]id。在内核日志中,我可以看到current->uid 已更改为1000。但是当我运行ps aux 时,进程仍处于root 模式。知道为什么吗?
【问题讨论】:
-
您的内核版本是否将 (struct cred *) 传递给您的
init_func()? -
@Milag,我不确定我是否明白你所说的。这是初始化函数
int (*init)(struct subprocess_info *info, struct cred *new),作为call_usermodehelper_setup函数中的参数的声明。 -
看看相关的内核源码;似乎在提供的 init 例程中修改 (struct cred *new) 成员,如您的
init_func()可能 是可以的,以及在设置CONFIG_SECURITY_SELINUX并满足其他条件时可能出现的恐慌情况。 -
你好@Milag,在
init_func()我更新了cred'uid/euid/gid 为1000,但启动的用户空间进程仍处于root模式。我正在使用new = prepare_creds(); new->uid = KUIDT_INIT(uid); commit_creds(new);。你知道为什么吗? -
上周的想法是修改传递给您的 init 例程的
(struct cred *)的成员。不建议分配另一个结构;考虑这个顺序:内核分配+初始化一个struct cred,使用对该结构的引用调用您的初始化例程,然后在您的初始化例程返回之后提交那个结构。在 init 例程中不需要另一个 prep+commit ;这些凭据将被内核的提交替换。
标签: linux linux-kernel kernel linux-device-driver kernel-module