Administro un cuadro Gentoo Hardened que utiliza capacidades de archivo para eliminar la mayor parte de la necesidad de binarios setuid-root (por ejemplo, /bin/ping
tiene CAP_NET_RAW, etc.).
De hecho, el único binario que me queda es este:
abraxas ~ # find / -xdev -type f -perm -u=s
/usr/lib64/misc/glibc/pt_chown
abraxas ~ #
Si elimino el bit setuid, o vuelvo a montar mi sistema de archivos raíz nosuid
, sshd y GNU Screen dejan de funcionar, porque llaman grantpt(3)
a sus pesudoterminals maestros y glibc aparentemente ejecuta este programa para reconocer y cambiar el pseudoterminal esclavo /dev/pts/
, y GNU Screen se preocupa por cuándo esta función falla
El problema es que la página de manual para grantpt(3)
explícitamente establece que bajo Linux, con el devpts
sistema de archivos montado, no se requiere dicho binario auxiliar; el kernel configurará automáticamente el UID y GID del esclavo al UID y GID real del proceso que se abrió /dev/ptmx
(mediante una llamada getpt(3)
).
He escrito un pequeño programa de ejemplo para demostrar esto:
#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;
}
Obsérvelo en acción con el bit setuid en el programa mencionado eliminado:
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
Solo tengo algunas ideas sobre cómo solucionar este problema:
1) Reemplace el programa con un esqueleto que simplemente devuelve 0.
2) Parche grantpt () en mi libc para no hacer nada.
Puedo automatizar ambos, pero ¿alguien tiene una recomendación para uno sobre el otro, o recomendaciones sobre cómo resolver esto?
Una vez que esto se resuelva, finalmente puedo mount -o remount,nosuid /
.
pty
(como debe ser), pero para el programa?