Ich verwalte eine Gentoo Hardened-Box, die /bin/ping
Dateifunktionen verwendet, um die Notwendigkeit von setuid-root-Binärdateien (z. B. CAP_NET_RAW usw.) zum größten Teil zu beseitigen .
Tatsächlich ist die einzige Binärdatei, die ich noch habe, die folgende:
abraxas ~ # find / -xdev -type f -perm -u=s
/usr/lib64/misc/glibc/pt_chown
abraxas ~ #
Wenn ich das setuid-Bit entferne oder mein Root-Dateisystem wieder nosuid
einbinde, funktionieren sshd und GNU Screen nicht mehr, weil sie grantpt(3)
ihre Master-Pesudoterminals aufrufen und glibc anscheinend dieses Programm ausführt, um das Slave-Pseudoterminal darunter zu chownen und chmodieren /dev/pts/
, und GNU Screen kümmert sich darum, wann diese Funktion funktioniert scheitert.
Das Problem ist, dass in der Manpage für grantpt(3)
explizit angegeben ist, dass unter Linux bei devpts
eingehängtem Dateisystem keine solche Hilfsbinärdatei erforderlich ist. Der Kernel setzt automatisch die UID & GID des Slaves auf die reale UID & GID des Prozesses, der geöffnet wurde /dev/ptmx
(durch Aufrufen getpt(3)
).
Ich habe ein kleines Beispielprogramm geschrieben, um dies zu demonstrieren:
#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;
}
Beobachten Sie es in Aktion, während das setuid-Bit des oben genannten Programms entfernt ist:
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
Ich habe nur ein paar Ideen, wie ich dieses Problem umgehen kann:
1) Ersetzen Sie das Programm durch ein Skelett, das einfach 0 zurückgibt.
2) Patch grantpt () in meiner libc, um nichts zu tun.
Ich kann beide automatisieren, aber hat jemand eine Empfehlung für eine über die andere, oder Empfehlungen, wie man dies sonst lösen kann?
Sobald dies gelöst ist, kann ich endlich mount -o remount,nosuid /
.
pty
(wie sie sollen) sondern nach dem Programm?