Sin embargo, esto no funciona con las bibliotecas dinámicas.
Funciona para bibliotecas dinámicas. Si un objeto compartido se encuentra en una partición que está montada con la opción noexec, no se puede cargar, de lo contrario noexec
sería bastante inútil.
$ grep -E '/tmp |ext4' /proc/mounts
/dev/mapper/root_crypt / ext4 rw,nodev,noatime,data=ordered 0 0
tmpfs /tmp tmpfs rw,nosuid,nodev,noexec,noatime,size=2031200k 0 0
$ cat > main.c
#include <stdio.h>
void main(void)
{
printf("%d\n", getpid());
}
$ gcc -o main main.c
$ ./main
4950
$ cat > shared.c
int getpid(void)
{
return 1;
}
$ gcc -shared -fPIC -o shared.so shared.c
$ LD_PRELOAD=./shared.so ./main
1
$ mv shared.so /tmp
$ LD_PRELOAD=/tmp/shared.so ./main
ERROR: ld.so: object '/tmp/shared.so' from LD_PRELOAD cannot be preloaded (failed to map segment from shared object): ignored.
4978
Si desea usar seccomp para evitar la ejecución de objetos compartidos no confiables, puede hacerlo restringiendo las llamadas a mmap()
, mprotect()
y, obviamente, execve()
. Asegúrese de que el proceso no pueda asignar nada con PROT_EXEC
. La restricción de archivos no es suficiente, ya que cualquier dato arbitrario puede pasarse a mmap()
a través de un descriptor de archivo, y mprotect()
puede cambiar los permisos de páginas arbitrarias de memoria para hacerlos ejecutables. Además, dado que este ejemplo es una lista negra en lugar de una lista blanca, también tendrá que denegar el acceso a algunos argumentos ptrace()
, ya que se pueden usar para salir de una caja de arena seccomp.
rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mmap), 1,
SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
if (rc == -1)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCESS), SCMP_SYS(mprotect), 1,
SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
if (rc == -1)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCESS), SCMP_SYS(execve), 0);
if (rc == -1)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(ptrace), 1,
SCMP_A0(SCMP_CMP_EQ, PTRACE_POKEUSER));
if (rc == -1)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(ptrace), 1,
SCMP_A0(SCMP_CMP_EQ, PTRACE_SETREGS));
if (rc == -1)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(ptrace), 1,
SCMP_A0(SCMP_CMP_EQ, PTRACE_SETREGSET));
if (rc == -1)
goto out;
Probablemente hay formas de omitir este fragmento de fragmento de compilación en el que no he pensado, así que esto es solo para darte una idea de lo que se necesita.
Nunca he usado NaCl, así que no puedo decir cómo restringirías la ejecución con él.