Zarządzam modułem Gentoo Hardened, który korzysta z możliwości plików, aby wyeliminować większość potrzebnych plików binarnych z katalogu root setuid (np. /bin/ping
Ma CAP_NET_RAW itp.).
W rzeczywistości, jedyne pliki binarne, które mi pozostały, to:
abraxas ~ # find / -xdev -type f -perm -u=s
/usr/lib64/misc/glibc/pt_chown
abraxas ~ #
Jeśli usunę bit setuid lub ponownie zainstaluję mój główny system plików nosuid
, sshd i GNU Screen przestaną działać, ponieważ wywołują grantpt(3)
swoje pesudotermale nadrzędne i glibc najwyraźniej uruchamia ten program, aby zmienić i przeskoczyć pseudoterminal podrzędny /dev/pts/
, a GNU Screen dba o to, kiedy ta funkcja zawodzi.
Problem polega na tym, że strona podręcznika grantpt(3)
wyraźnie stwierdza, że pod Linuksem, z devpts
zamontowanym systemem plików, nie jest wymagany taki plik binarny pomocnika; jądro automatycznie ustawi UID i GID urządzenia podrzędnego na rzeczywisty UID i GID procesu, który został otwarty /dev/ptmx
(przez wywołanie getpt(3)
).
Napisałem mały przykładowy program, aby to zademonstrować:
#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;
}
Obserwuj to w akcji z usuniętym bitem setuid z wyżej wymienionego programu:
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
Mam tylko kilka pomysłów na obejście tego problemu:
1) Zamień program na szkielet, który po prostu zwraca 0.
2) Patch granpt () w moim libc, aby nic nie robić.
Mogę zautomatyzować oba z nich, ale czy ktoś ma rekomendacje dla jednego lub drugiego, czy też jak to rozwiązać?
Gdy problem zostanie rozwiązany, w końcu mogę mount -o remount,nosuid /
.
pty
(jak powinny), ale do programu?