Eu administro uma caixa Gentoo Hardened que usa recursos de arquivo para eliminar a maior parte da necessidade de binários raiz setuid (por exemplo, /bin/ping
tem CAP_NET_RAW, etc).
De fato, o único binário que me resta é este:
abraxas ~ # find / -xdev -type f -perm -u=s
/usr/lib64/misc/glibc/pt_chown
abraxas ~ #
Se eu remover o bit setuid ou remontar meu sistema de arquivos raiz nosuid
, sshd e GNU Screen parem de funcionar, porque eles chamam grantpt(3)
seus pesudoterminals principais e a glibc aparentemente executa esse programa para mostrar e chmod o pseudoterminal escravo em baixo /dev/pts/
, e o GNU Screen se preocupa quando essa função falha.
O problema é que a página de manual grantpt(3)
declara explicitamente que, no Linux, com o devpts
sistema de arquivos montado, esse binário auxiliar não é necessário; o kernel definirá automaticamente o UID & GID do escravo como o verdadeiro UID & GID do processo que foi aberto /dev/ptmx
(chamando getpt(3)
).
Eu escrevi um pequeno programa de exemplo para demonstrar isso:
#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;
}
Observe-o em ação com o bit setuid no programa mencionado acima removido:
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
Eu tenho apenas algumas idéias sobre como solucionar esse problema:
1) Substitua o programa por um esqueleto que simplesmente retorne 0.
2) Patch grantpt () na minha libc para não fazer nada.
Posso automatizar os dois, mas alguém tem uma recomendação para um sobre o outro, ou recomendações sobre como resolver isso?
Uma vez resolvido, posso finalmente mount -o remount,nosuid /
.
pty
(como deveriam), mas o programa?