Я управляю коробкой Gentoo Hardened, которая использует файловые возможности для устранения большей части необходимости в двоичных файлах setuid-root (например, /bin/ping
имеет CAP_NET_RAW и т. Д.).
Infact, единственный двоичный файл, который я оставил, является этим:
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 заботится о том, когда эта функция выходит из строя.
Проблема в том, что man-страница 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) Патч grantpt () в моем libc ничего не делает.
Я могу автоматизировать оба из них, но есть ли у кого-нибудь рекомендации по одному над другим или рекомендации, как еще решить эту проблему?
Как только это решится, я наконец смогу mount -o remount,nosuid /
.
pty
(как следует), а на программу?