]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipc, msg: Use dedicated slab buckets for alloc_msg()
authorKees Cook <kees@kernel.org>
Mon, 1 Jul 2024 19:13:02 +0000 (12:13 -0700)
committerVlastimil Babka <vbabka@suse.cz>
Wed, 3 Jul 2024 10:24:20 +0000 (12:24 +0200)
The msg subsystem is a common target for exploiting[1][2][3][4][5][6][7]
use-after-free type confusion flaws in the kernel for both read and write
primitives. Avoid having a user-controlled dynamically-size allocation
share the global kmalloc cache by using a separate set of kmalloc buckets
via the kmem_buckets API.

Link: https://blog.hacktivesecurity.com/index.php/2022/06/13/linux-kernel-exploit-development-1day-case-study/
Link: https://hardenedvault.net/blog/2022-11-13-msg_msg-recon-mitigation-ved/
Link: https://www.willsroot.io/2021/08/corctf-2021-fire-of-salvation-writeup.html
Link: https://a13xp0p0v.github.io/2021/02/09/CVE-2021-26708.html
Link: https://google.github.io/security-research/pocs/linux/cve-2021-22555/writeup.html
Link: https://zplin.me/papers/ELOISE.pdf
Link: https://syst3mfailure.io/wall-of-perdition/
Signed-off-by: Kees Cook <kees@kernel.org>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
ipc/msgutil.c

index d0a0e877cadd5a41ed283ea3fde792ead7588124..c7be0c79264767b74d6f3c716af16366034ceb1e 100644 (file)
@@ -42,6 +42,17 @@ struct msg_msgseg {
 #define DATALEN_MSG    ((size_t)PAGE_SIZE-sizeof(struct msg_msg))
 #define DATALEN_SEG    ((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
 
+static kmem_buckets *msg_buckets __ro_after_init;
+
+static int __init init_msg_buckets(void)
+{
+       msg_buckets = kmem_buckets_create("msg_msg", SLAB_ACCOUNT,
+                                         sizeof(struct msg_msg),
+                                         DATALEN_MSG, NULL);
+
+       return 0;
+}
+subsys_initcall(init_msg_buckets);
 
 static struct msg_msg *alloc_msg(size_t len)
 {
@@ -50,7 +61,7 @@ static struct msg_msg *alloc_msg(size_t len)
        size_t alen;
 
        alen = min(len, DATALEN_MSG);
-       msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL_ACCOUNT);
+       msg = kmem_buckets_alloc(msg_buckets, sizeof(*msg) + alen, GFP_KERNEL);
        if (msg == NULL)
                return NULL;