决定必须使用超级用户调用setgroups()和initgroups()的机制是什么?

问题描述 投票:1回答:3

来自APUE

#include <grp.h> /* on Linux */
int setgroups(int ngroups, const gid_t grouplist[]);

超级用户可以调用setgroups函数来为调用进程设置补充组ID列表:grouplist包含组ID数组,ngroups指定数组中元素的数量。 ngroups的值不能大于NGROUPS_MAX。

#include <grp.h> /* on Linux and Solaris */
int initgroups(const char *username, gid_t basegid);

一个人必须是超级用户才能打电话给initgroups(),因为它叫setgroups()

决定必须用超级用户调用setgroups()initgroups()的机制是什么?

“机制”是指与以下内容相似或相似的内容。在Linux中,我了解到我们可以根据访问控制列表(ACL)确定进程对文件的可访问性:

  • 进程的有效用户ID,有效组ID和补充组ID
  • 文件的权限位。

谢谢。

c linux privileges access-control
3个回答
2
投票

APUE中的措辞可能有点不精确;它是程序员的教程指南,而不是法律纲要。任何过程都可以调用setgroups()initgroups()。但是如果进程没有root权限,那么该函数只会将errno设置为EPERM并返回错误指示。

显然,权限测试无法使用用户权限完成。库函数只是系统调用的一个薄包装器,测试在内核中完成。

值得一提的是,这是谷歌在被问及Linux系统调用机制时给我的第一个热门话题:http://www.linux.it/~rubini/docs/ksys/。但也许你有更好的资源。


1
投票

在Linux中,如果一个进程有CAP_SETGID capability,内核将尊重setgid()setegid()setregid()setresgid()setgroups()调用(除非被像SELinux这样的Linux安全模块拒绝)。

非特权用户可以通过两种主要机制获得功能:

  • 从特权进程继承它。对于普通用户,PAM模块可以在登录时授予额外功能。
  • 通过文件系统功能。

文件系统功能更有趣,对服务/应用程序很有用。它们只适用于二进制文件,而不是脚本,因为内核将功能更新为执行二进制文件的机制的一部分; shell使用完全不同的完全用户空间机制来解释脚本。

(文件系统必须支持扩展属性。必须使用user_xattr挂载选项挂载某些文件系统,如ext2,ext3和reiserfs,以启用扩展属性.ext4,xfs,jfs,btrfs和zfs都应使用默认挂载选项支持扩展属性一些Linux发行版如Debian和Ubuntu已经依赖于扩展属性和文件系统功能。)

注意:您可以使用getcaplsattr实用程序来检查二进制文件系统功能和扩展属性。在我的Ubuntu 16.04.4 LTS系统上,/usr/bin/systemd-detect-virt二进制文件具有允许且有效的CAP_DAC_OVERRIDE和CAP_SYS_PTRACE功能。

在实践中使用文件系统功能非常容易,但为了安全操作,首先应仔细考虑安全隐患:它是一个功能强大的工具,但您(开发人员,包管理员和/或系统管理员)负责确保它是使用正确。

例如,如果要安装受信任的/usr/bin/yourprog并且需要CAP_SETGID功能,那么您需要做的就是为该二进制文件设置允许且有效的功能。为此,您可以使用root权限运行setcap cap_setgid=pe /usr/bin/yourprog。 (在Debian .deb软件包安装脚本中,通常在安装后脚本中运行。)


1
投票

你可以看看actual code for setgroups。它是这样开始的:

SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
{
    struct group_info *group_info;
    int retval;

    if (!may_setgroups())
        return -EPERM;

    // other stuff
}

这是may_setgroups

bool may_setgroups(void)
{
    struct user_namespace *user_ns = current_user_ns();

    return ns_capable(user_ns, CAP_SETGID) &&
        userns_may_setgroups(user_ns);
}

如果你没有使用用户命名空间,这里是userns_may_setgroups

static inline bool userns_may_setgroups(const struct user_namespace *ns)
{
    return true;
}

所以:如果你没有setgroups能力,EPERM将返回CAP_SETGID错误。

推论:如果你有setgroups能力,你可以打电话给CAP_SETGID

Root自动具有所有功能(因此root可以调用setgroups),但是如果你不是root用户并且你具有CAP_SETGID功能,你也可以调用它。

© www.soinside.com 2019 - 2024. All rights reserved.