Board logo

标题: 应用挂载名称空间(2) [打印本页]

作者: look_w    时间: 2018-6-14 17:09     标题: 应用挂载名称空间(2)

每个用户专用的根LSPP共同准则 Labeled Security Protection Profile 为 IT 产品指定了一组安全功能和保障需求。它支持两类访问控制机制,这些机制允许用户指定如何共享他们控制的资源(通过安全标志或 “标签” 来实施),还可以对用户之间的共享实施限制。LSPP 提供的保护级别适合于 “非敌对性的管理良好的用户社区,可以防止意外操作破坏系统安全”。参见 。

在  一节中,我们看到了一个通过挂载名称空间为用户提供私有名称空间的简单示例。通过使用挂载传播,这个解决方案非常适合为用户提供私有的 /tmp 目录;如果再添加一个由 pam_ns.c 解析的配置文件,就可以根据用户对其他目录进行重定向。LSPP 就是以这种方式提供多个实例化的主目录,它会根据登录过程的许可在 /home/USER 上挂载不同的目录。
但是,同一用户的每次登录都会获得一个私有的从属文件系统。所以这个用户在一个登录会话中执行的挂载不影响另一个登录会话。
非管理员用户可以以几种方式挂载文件系统。例如,用户可以使用 FUSE 挂载 sshfs(安全 shell)文件系统或 loopback 文件系统(见 )。如果不考虑本文后面讨论的用户之间的挂载共享问题,就不容易理解这些挂载如何只出现在用户的一个登录终端中,而不出现在其他终端中。但是,通过使用 “每个登录专用的名称空间” 一节中的方法,确实可以实现这种效果。
清单 3 给出 pam_chroot.so PAM 模块的部分代码。pam_ns.so 在登录时克隆挂载名称空间,但是 pam_chroot.so 模块需要在 /share/USER/root 下设置一个用户专用的文件系统,并使用 chroot() 将用户限制在他的私有文件系统中。
清单 3. 使用 chroot() 的 PAM 模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
                const char **argv)
{
        const char *PAM_user = NULL;
        char fnam[400];
        int ret, err, count, i;
        struct mount_entries *entries;
        struct stat statbuf;

        ret = pam_get_user(pamh, &PAM_user, NULL);
        if (ret != PAM_SUCCESS) {
                mysyslog(LOG_ERR, "PAM-MOUNT: couldn't get user\n");
                return PAM_SESSION_ERR;
        }

        /* check whether /share/$pam_user/root exists.  If so, chroot to it */
        sprintf(fnam, "/share/%s/root", PAM_user);
        ret = stat(fnam, &statbuf);
        if (ret == 0 && S_ISDIR(statbuf.st_mode)) {
                ret = chroot(fnam);
                if (ret) {
                        mysyslog(LOG_ERR, "PAM-MOUNT: unable to chroot to %s\n", fnam);
                        return PAM_SESSION_ERR;
                }
        }

        return PAM_SUCCESS;
}




在这个示例中,在系统启动时提前执行所有挂载。例如,在启动之后,执行:
1
2
3
4
5
mkdir -p /share/USER/root
mount --make-rshared /
mount --rbind / /share/USER/root
mount --make-rslave /share/USER/root
mount --bind /share/USER/root/tmp/priv/USER /share/USER/root/tmp




这里没有使用私有名称空间。相反,USER 的每次登录都通过 chroot() 限制在同一个目录(/share/USER/root)中。因此,在 USER 的所有登录中,会看到他的任何登录所执行的任何挂载。而 OTHERUSER 通过 chroot() 限制在 /share/OTHERUSER/root 中,因此不会看到 USER 的挂载活动。
这种方法的一个缺点是,可以回避普通的 chroot() 机制(虽然这需要某些特权)。例如,在具有某些特权(包括 CAP_SYS_CHROOT)的情况下,程序可以回避 chroot()(参见 ),这会导致程序能够访问真正的文件系统根。根据使用用户专用文件系统树的实际意图的不同,这可能会成为一个问题。
pivot_root(2) 和 chroot(2)Linux 手册页指出:pivot_root(2) 命令将当前进程的根文件系统转移到目录 put_old,并使 new_root 成为新的当前进程根文件系统。chroot(2) 命令将根目录改为路径中指定的目录;当前进程的所有子进程都继承这个根目录。只有具有特权的进程可以调用这个命令。参见 。

解决这个问题的方法是,在私有名称空间中使用 pivot_root(2)(而不是 chroot(2))将登录的根目录改为 /share/USER/root。chroot() 仅仅将进程的文件系统根指向一个指定的新目录,而 pivot_root() 会使指定的 new_root 目录(它必须是一个挂载)脱离它的挂载点,然后将它附着到进程的根目录。因为在挂载树中新的根目录没有父目录,所以无法像使用 chroot() 时那样欺骗系统,从而访问真正的文件系统根。我们将使用 pivot_root() 方式。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0