解决此glibc问题的最佳方法是什么?


26

我管理一个Gentoo Hardened框,该框使用文件功能来消除对setuid-root二进制文件(例如/bin/ping具有CAP_NET_RAW等)的大多数需要。

实际上,我剩下的唯一二进制文件是:

abraxas ~ # find / -xdev -type f -perm -u=s
/usr/lib64/misc/glibc/pt_chown
abraxas ~ # 

如果我删除setuid位或重新挂载我的根文件系统nosuid,则sshd和GNU Screen停止工作,因为它们调用grantpt(3)了它们的主伪终端,并且glibc显然执行了该程序来对下的伪伪终端进行chown和chmod /dev/pts/,而GNU Screen会在何时关注此函数失败。

问题是,联机帮助页上grantpt(3)明确指出,在Linux下,devpts安装了文件系统后,不需要此类帮助程序二进制文件;内核会自动将从站的UID和GID设置为打开的进程的实际UID和GID /dev/ptmx(通过调用getpt(3))。

我编写了一个小示例程序来演示这一点:

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
    int master;
    char slave[16];
    struct stat slavestat;
    if ((master = getpt()) < 0) {
        fprintf(stderr, "getpt: %m\n");
        return 1;
    }
    printf("Opened a UNIX98 master terminal, fd = %d\n", master);
    /* I am not going to call grantpt() because I am trying to
     * demonstrate that it is not necessary with devpts mounted,
     * the owners and mode will be set automatically by the kernel.
     */
    if (unlockpt(master) < 0) {
        fprintf(stderr, "unlockpt: %m\n");
        return 2;
    }
    memset(slave, 0, sizeof(slave));
    if (ptsname_r(master, slave, sizeof(slave)) < 0) {
        fprintf(stderr, "ptsname: %m\n");
        return 2;
    }
    printf("Device name of slave pseudoterminal: %s\n", slave);
    if (stat(slave, &slavestat) < 0) {
        fprintf(stderr, "stat: %m\n");
        return 3;
    }
    printf("Information for device %s:\n", slave);
    printf("    Owner UID:  %d\n", slavestat.st_uid);
    printf("    Owner GID:  %d\n", slavestat.st_gid);
    printf("    Octal mode: %04o\n", slavestat.st_mode & 00007777);
    return 0;
}

在删除上述程序的setuid位的情况下观察它的运行:

aaron@abraxas ~ $ id
uid=1000(aaron) gid=100(users) groups=100(users)
aaron@abraxas ~ $ ./ptytest 
Opened a UNIX98 master terminal, fd = 3
Device name of slave pseudoterminal: /dev/pts/17
Information for device /dev/pts/17:
    Owner UID:  1000
    Owner GID:  100
    Octal mode: 0620

关于如何解决此问题,我只有几个想法:

1)将程序替换为仅返回0的框架。

2)在我的libc中修补grantpt()却什么也不做。

我可以同时实现这两个功能,但是有人对另一个提出了建议吗,还是有人建议如何解决这个问题?

解决这个问题后,我终于可以了mount -o remount,nosuid /


在等待响应时,我采用了方法1,但sshd和GNU Screen仍然有效。
亚伦·琼斯

失败的程序到底是什么?也许它们坏了,而不是pty(按理)检查程序?
vonbrand

任何不具有CAP_CHOWN和CAP_FOWNER的程序都将调用Grantpt(),并且辅助二进制文件未以EUID == 0开头,并且将为Grantpt()提供非零的返回码,并且在发生这种情况时,程序应中止PTS的创建,根据ptmx(4)。
亚伦·琼斯

3
该“解决方案”使我意志坚定……在最佳情况下,它会记录一个错误,它可能会创建一个新的错误,在最坏情况下,它会创建一个严重的安全漏洞。请与glibc开发人员联系。
vonbrand

3
然后将此报告给glibc人员。
vonbrand

Answers:


2

如果您的glibc是最新的,并且devpts设置正确,则完全不需要调用pt_chown帮助程序。

您可能会遇到一个已知/潜在问题,即从中删除setuid-root pt_chown

grantpt()支持devfsglibc的-2.7,变化作了glibc的2.11,虽然,这样,而不是明确的检查DEVFS_SUPER_MAGIC,它会检查,而不是看它是否需要在尝试之前,做任何工作chown()或回落至调用pt_chown

glibc-2.17/sysdeps/unix/grantpt.c

  ...
  uid_t uid = __getuid ();
  if (st.st_uid != uid)
    {
       if (__chown (buf, uid, st.st_gid) < 0)
       goto helper;
    }
  ...

类似的节用于检查gid和权限。要注意的是,uid,gid和mode必须与期望值匹配(您,tty和恰好是 620;请使用确认/usr/libexec/pt_chown --help)。如果没有,chown()则尝试(这将要求调用二进制文件/进程的功能CAP_CHOWN,CAP_FOWNER),如果失败,则尝试使用pt_chown外部帮助程序(必须为setuid-root)。为了pt_chown能够使用功能,必须使用对其进行编译(因此也可以使用glibc)HAVE_LIBCAP但是,似乎pt_chown(从glibc-2.17开始,尽管您没有指出版本,但您已经指出)是硬编码的,geteuid()==0 无论是否需要以下HAVE_LIBCAP相关代码glibc-2.17/login/programs/pt_chown.c

  ...
  if (argc == 1 && euid == 0)
    {
#ifdef HAVE_LIBCAP
  /* Drop privileges.  */
     if (uid != euid)
  ...
#endif
    /* Normal invocation of this program is with no arguments and
       with privileges.  */
    return do_pt_chown ();
  }
...
  /* Check if we are properly installed.  */
  if (euid != 0)
    error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));

geteuid()==0尝试使用功能之前似乎并没有真正体现出功能的精神,我会记录一个关于此功能的错误。)

可能的解决方法是将CAP_CHOWN和CAP_FOWNER赋予受影响的程序,但我不建议这样做,因为您当然不能将其限制为ptys。

如果那不能帮助您解决问题,请进行修补,sshd并且screen比修补glibc令人讨厌。由于问题出在glibc之内,因此一种更清洁的方法是选择性地使用DLL注入来实现虚拟对象grantpt()


“由于问题出在glibc之内,所以更干净的方法是选择性地使用DLL注入来实现虚拟的Grantpt()。” -很棒 为什么我没有想到呢?谢谢。:)
亚伦·琼斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.