harkaq: el salto del check de arquitectura ya no se apoya en UB (SDD 25 T17)

`f[k++] = BPF_JUMP(..., I_KILL - k - 1 + 1)` leía y modificaba `k` en la misma
expresión, sin punto de secuencia: UB en C11. Andaba porque gcc y clang leen `k`
después del incremento y ese `+1` era la compensación exacta, pero si algún
compilador leyera antes el salto caería una instrucción más allá del final.

El índice se fija ahora en `I_ARCH` antes de usarlo. El código generado es
IDÉNTICO —mismo objdump del objeto a -O1 y a -O2, la única línea que difiere es
el nombre del fichero—, que es lo que prueba que es la misma cuenta escrita sin
UB y no un arreglo que además mueve el salto. Comprobado además que la jaula
sigue puesta: ptrace desde dentro da EPERM y un ejecutable fuera de la clausura
no arranca.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACUcwo9mZsE5ocYVE9npih
This commit is contained in:
Sergio
2026-09-01 16:59:22 +00:00
co-authored by Claude Opus 5
parent 1df77985fa
commit 9591e69b70
2 changed files with 24 additions and 11 deletions
+8 -2
View File
@@ -156,8 +156,14 @@ static int poner_seccomp(void) {
// el error clásico de los filtros seccomp escritos a mano.
f[k++] = (struct sock_filter)BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
offsetof(struct seccomp_data, arch));
f[k++] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0,
I_KILL - k - 1 + 1);
// El desplazamiento se cuenta desde ESTA instrucción, así que hace falta su índice. Fijarlo en
// una variable y no escribir `f[k++] = ... (I_KILL - k - 1 + 1)`: eso lee y modifica `k` en la
// misma expresión, sin punto de secuencia — UB en C11. Andaba (gcc y clang leen `k` después del
// incremento, y ese `+1` era justo la compensación), pero andaba apoyado en UB. Comprobado que
// el código generado no cambia, a `-O1` y `-O2`. Ver SDD 25 T17.
const int I_ARCH = k++;
f[I_ARCH] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0,
I_KILL - I_ARCH - 1);
f[k++] = (struct sock_filter)BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
offsetof(struct seccomp_data, nr));
for (int i = 0; i < n; i++, k++)