Deny alg_socket to Containers with SELinux to Mitigate CVE‑2026‑31431
CVE-2026-31431 or “Copy Fail” is a bug in the Linux kernel’s implementation of the AF_ALG socket type that exposes the kernel’s crypto subsystem to unprivileged userspace. Because most applications don’t use this and there is a risk of container escape, it makes sense to deny access.
In the example below, I’m using the fish shell with an SELinux userspace release after 3.6 which is when support for deny rules was added.
opc@sparkling ~> sudo semodule -r psub-container-alg
libsemanage.semanage_direct_remove_key: Removing last psub-container-alg module (no other psub-container-alg module exists at another priority).
opc@sparkling ~> sudo podman run -ti --rm alpine/openssl engine -t -c -vv afalg
(afalg) AFALG engine support
[AES-128-CBC, AES-192-CBC, AES-256-CBC]
[ available ]
opc@sparkling ~> sudo semodule -i (sesearch -A -s container_ -rs -c alg_socket -p create | egrep -v unconfined | sed 's/^allow/\(deny/; s/:/ \(/; s/{/\(/; s/};/)))/' | psub -s -container-alg.cil)
opc@sparkling ~> sudo podman run -ti --rm alpine/openssl engine -t -c -vv afalg
20DD97B0FFFF0000:error:4000006D:lib(128)::reason(109):engines/e_afalg.c:882:
20DD97B0FFFF0000:error:1300006D:engine routines:dynamic_load:init failed:crypto/engine/eng_dyn.c:498:
20DD97B0FFFF0000:error:13000074:engine routines:ENGINE_by_id:no such engine:crypto/engine/eng_list.c:470:id=afalg
opc@sparkling ~ [1]> # :)
opc@sparkling ~ [1]>
Alternative Mitigations
Red Hat suggests an initcall_blacklist in the boot arguments.
Lennart Poettering’s advice for CVE-2016-8655 should also work for CVE‑2026‑31431 by using RestrictAddressFamilies=~AF_ALG on a per-service basis. In my testing this works for both containers and other services. R-fx Networks pairs this with SystemCallArchitectures=native.
Running as unit: run-u3914.service
Press ^] three times within 1s to disconnect TTY.
(afalg) AFALG engine support
[AES-128-CBC, AES-192-CBC, AES-256-CBC]
[ available ]
Finished with result: success
Main processes terminated with: code=exited/status=0
Service runtime: 548ms
user@serv ~> sudo systemd-run --pty --wait --collect -p 'RestrictAddressFamilies=~AF_PACKET AF_ALG' podman run -ti --rm alpine/openssl engine -t -c -vvv afalg
Running as unit: run-u3923.service
Press ^] three times within 1s to disconnect TTY.
280B94F7067F0000:error:4000006D:lib(128)::reason(109):engines/e_afalg.c:882:
280B94F7067F0000:error:1300006D:engine routines:dynamic_load:init failed:crypto/engine/eng_dyn.c:498:
280B94F7067F0000:error:13000074:engine routines:ENGINE_by_id:no such engine:crypto/engine/eng_list.c:470:id=afalg
Finished with result: exit-code
Main processes terminated with: code=exited/status=1
Service runtime: 563ms
user@serv ~ [1]> sudo systemd-run --pty --wait --collect openssl engine -t -c -vvv afalg
Running as unit: run-u3932.service
Press ^] three times within 1s to disconnect TTY.
(afalg) AFALG engine support
[AES-128-CBC, AES-192-CBC, AES-256-CBC]
[ available ]
Finished with result: success
Main processes terminated with: code=exited/status=0
Service runtime: 8ms
user@serv ~> sudo systemd-run --pty --wait --collect -p 'RestrictAddressFamilies=~AF_PACKET AF_ALG' openssl engine -t -c -vvv afalg
Running as unit: run-u3935.service
Press ^] three times within 1s to disconnect TTY.
139718332651328:error:8006406D:lib(128):func(100):reason(109):engines/e_afalg.c:800:
139718332651328:error:260B606D:engine routines:dynamic_load:init failed:crypto/engine/eng_dyn.c:485:
139718332651328:error:2606A074:engine routines:ENGINE_by_id:no such engine:crypto/engine/eng_list.c:334:id=afalg
Finished with result: exit-code
Main processes terminated with: code=exited/status=1
Service runtime: 7ms
user@serv ~ [1]>
Questions about SELinux
Why was support for deny rules only added to the SELinux userspace in 2023?
Why is the output of sesearch so dissimilar to the input of semanage ?
What is the purpose of allow unconfined_domain_type domain:alg_socket and does leaving this rule alone ruin the mitigation?
Type Attributes: 1
attribute unconfined_domain_type;
container_runtime_t
opc@sparkling ~>
This relates to container_runtime_t. This is for privileged containers in rootless mode and for the container management engine itself. So it’s probably OK.