harkaq: un portón de compilación para el techo de la denylist (SDD 25 T17)
`jt`/`jf` de la BPF clásica son __u8 y en la forma de poner_seccomp() el salto más largo mide n+3: pasadas ~252 entradas el desplazamiento da la vuelta y el filtro deja de decir lo que dice el fichero, sin error y sin aviso. Hoy son 25 y sobra sitio — el riesgo es que agregar syscalls a una denylist es exactamente lo que uno hace sin pensarlo. _Static_assert, o sea cero código generado: comprobado en las dos direcciones —baja el techo a 10 y el compilador para; y la sección .text del binario es byte a byte la misma con y sin el assert—, que es el requisito de este fichero (nada que re-hashee). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACUcwo9mZsE5ocYVE9npih
Delta semántico
Ninguna definición cambió: el cambio es de texto, documentación o datos.
1 archivos · +11 −0
- scripts/harkaq/harkaq-exec.c +11 −0
diff --git a/scripts/harkaq/harkaq-exec.c b/scripts/harkaq/harkaq-exec.c
index 686c123d..886daa86 100644
--- a/scripts/harkaq/harkaq-exec.c
+++ b/scripts/harkaq/harkaq-exec.c
@@ -131,6 +131,17 @@ static const int SYSCALLS_DENEGADAS[] = {
__NR_setns,
};
+// TECHO DE LA LISTA, y por qué no es un detalle: `jt`/`jf` de la BPF clásica son `__u8`. En la
+// forma de abajo el salto más largo mide n+3, así que a partir de ~252 entradas el desplazamiento
+// DA LA VUELTA y el filtro deja de decir lo que dice este fichero — sin error y sin aviso. Hoy son
+// 25 y sobra sitio; el riesgo es que agregar syscalls a una denylist es exactamente lo que uno
+// hace sin pensarlo. Esto no genera código: es un portón de compilación.
+// (SDD 25 T17 midió además que la longitud de esta lista NO cuesta nada en ejecución — el bitmap
+// de acción constante del kernel la hace plana —, así que no hay ningún motivo de rendimiento
+// para recortarla ni para reordenarla.)
+_Static_assert(sizeof(SYSCALLS_DENEGADAS) / sizeof(SYSCALLS_DENEGADAS[0]) <= 250,
+ "la denylist pasa el techo de salto de la BPF clasica (__u8): partir el filtro");
+
// Arma e instala el filtro. Devuelve 0 si quedó puesto, -1 si el kernel no lo aceptó.
static int poner_seccomp(void) {
const int n = (int)(sizeof(SYSCALLS_DENEGADAS) / sizeof(SYSCALLS_DENEGADAS[0]));