On 3/1/23 12:09, Vegard Nossum wrote:
On 1/12/23 19:00, Serge E. Hallyn wrote:
On Thu, Jan 12, 2023 at 02:19:11PM +0100, Vegard Nossum wrote:
Creating a new user namespace grants you the ability to reach a lot
of code
(including loading certain kernel modules) that would otherwise be
out of
reach of an attacker. We can reduce the attack surface and block
exploits
by ensuring that user namespaces cannot trigger module (auto-)loading.
A cursory search of exploits found online yields the following
non-exhaustive list of vulnerabilities, and shows that the technique is
both old and still in use:
- CVE-2016-8655
- CVE-2017-1000112
- CVE-2021-32606
- CVE-2022-2588
- CVE-2022-27666
- CVE-2022-34918
- CVE-2023-0179
I think it would be worth pointing out how many of the above would
actually be aided by this patch. The first two would not, but certainly
at least the can module one counts. So I support this at least in
principle. I'll take a closer look at the code hopefully tonight.
The intention was to list _only_ CVEs with exploits that would be
mitigated by this patch. Let me go through them one by one, just using
public exploits found with Google:
CVE-2016-8655: this uses AF_PACKET. I guess your objection is that
AF_PACKET is rarely built as a module and even then would most certainly
already be loaded as part of regular operations? I see at least one
distro kernel having used CONFIG_PACKET=m in the past, so I wouldn't
write this off completely. You need CAP_NET_RAW to create this socket
type AFAICT, which is why the exploit uses user/network namespaces.
CVE-2017-1000112: uses AF_INET. Agreed that this would certainly be
compiled in or already loaded, so we can drop this.
[...]
All the exploits seem to be using user namespaces, for CVE-2017-1000112
I think it needs it to set the MTU of a dummy interface. I'm happy to
drop this CVE from the list (I probably looked too fast when looking at
it), but I think the rest are legitimate. Added Andrey Konovalov to Cc
as he wrote the exploit I looked at and can maybe confirm (and in
general has more experience with exploits).
Oh, I see -- the request_module() call in socket() happens before the
CAP_NET_RAW check in e.g. packet_create(), which means you don't need
user namespaces to _load_ these protocols, you can just do the socket()
call in the init user namespace, which will load the module but fail
creating the socket, then call socket() again inside the user namespace,
which now succeeds because the module has been loaded...
I haven't looked at the other CVEs from this angle, I'll look over them
again and see what I can find.
Vegard