From: Kees Cook <keescook@chromium.org>
To: "GONG, Ruiqi" <gongruiqi1@huawei.com>, Jann Horn <jannh@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
linux-hardening@vger.kernel.org,
Hyeonggon Yoo <42.hyeyoo@gmail.com>,
Alexander Lobakin <aleksander.lobakin@intel.com>,
kasan-dev@googlegroups.com,
Wang Weiyang <wangweiyang2@huawei.com>,
Xiu Jianfeng <xiujianfeng@huawei.com>
Subject: Re: [PATCH RFC v2] Randomized slab caches for kmalloc()
Date: Tue, 16 May 2023 12:34:11 -0700 [thread overview]
Message-ID: <202305161204.CB4A87C13@keescook> (raw)
In-Reply-To: <20230508075507.1720950-1-gongruiqi1@huawei.com>
For new CCs, the start of this thread is here[0].
On Mon, May 08, 2023 at 03:55:07PM +0800, GONG, Ruiqi wrote:
> When exploiting memory vulnerabilities, "heap spraying" is a common
> technique targeting those related to dynamic memory allocation (i.e. the
> "heap"), and it plays an important role in a successful exploitation.
> Basically, it is to overwrite the memory area of vulnerable object by
> triggering allocation in other subsystems or modules and therefore
> getting a reference to the targeted memory location. It's usable on
> various types of vulnerablity including use after free (UAF), heap out-
> of-bound write and etc.
I heartily agree we need some better approaches to deal with UAF, and
by extension, heap spraying.
> There are (at least) two reasons why the heap can be sprayed: 1) generic
> slab caches are shared among different subsystems and modules, and
> 2) dedicated slab caches could be merged with the generic ones.
> Currently these two factors cannot be prevented at a low cost: the first
> one is a widely used memory allocation mechanism, and shutting down slab
> merging completely via `slub_nomerge` would be overkill.
>
> To efficiently prevent heap spraying, we propose the following approach:
> to create multiple copies of generic slab caches that will never be
> merged, and random one of them will be used at allocation. The random
> selection is based on the address of code that calls `kmalloc()`, which
> means it is static at runtime (rather than dynamically determined at
> each time of allocation, which could be bypassed by repeatedly spraying
> in brute force). In this way, the vulnerable object and memory allocated
> in other subsystems and modules will (most probably) be on different
> slab caches, which prevents the object from being sprayed.
This is a nice balance between the best option we have now
("slub_nomerge") and most invasive changes (type-based allocation
segregation, which requires at least extensive compiler support),
forcing some caches to be "out of reach".
>
> The overhead of performance has been tested on a 40-core x86 server by
> comparing the results of `perf bench all` between the kernels with and
> without this patch based on the latest linux-next kernel, which shows
> minor difference. A subset of benchmarks are listed below:
>
> control experiment (avg of 3 samples)
> sched/messaging (sec) 0.019 0.019
> sched/pipe (sec) 5.253 5.340
> syscall/basic (sec) 0.741 0.742
> mem/memcpy (GB/sec) 15.258789 14.860495
> mem/memset (GB/sec) 48.828125 50.431069
>
> The overhead of memory usage was measured by executing `free` after boot
> on a QEMU VM with 1GB total memory, and as expected, it's positively
> correlated with # of cache copies:
>
> control 4 copies 8 copies 16 copies
> total 969.8M 968.2M 968.2M 968.2M
> used 20.0M 21.9M 24.1M 26.7M
> free 936.9M 933.6M 931.4M 928.6M
> available 932.2M 928.8M 926.6M 923.9M
Great to see the impact: it's relatively tiny. Nice!
Back when we looked at cache quarantines, Jann pointed out that it
was still possible to perform heap spraying -- it just needed more
allocations. In this case, I think that's addressed (probabilistically)
by making it less likely that a cache where a UAF is reachable is merged
with something with strong exploitation primitives (e.g. msgsnd).
In light of all the UAF attack/defense breakdowns in Jann's blog
post[1], I'm curious where this defense lands. It seems like it would
keep the primitives described there (i.e. "upgrading" the heap spray
into a page table "type confusion") would be addressed probabilistically
just like any other style of attack. Jann, what do you think, and how
does it compare to the KCTF work[2] you've been doing?
In addition to this work, I'd like to see something like the kmalloc
caches, but for kmem_cache_alloc(), where a dedicated cache of
variably-sized allocations can be managed. With that, we can split off
_dedicated_ caches where we know there are strong exploitation
primitives (i.e. msgsnd, etc). Then we can carve off known weak heap
allocation caches as well as make merging probabilistically harder.
I imagine it would be possible to then split this series into two
halves: one that creates the "make arbitrary-sized caches" API, and the
second that applies that to kmalloc globally (as done here).
>
> Signed-off-by: GONG, Ruiqi <gongruiqi1@huawei.com>
> ---
>
> v2:
> - Use hash_64() and a per-boot random seed to select kmalloc() caches.
This is good: I was hoping there would be something to make it per-boot
randomized beyond just compile-time.
So, yes, I think this is worth it, but I'd like to see what design holes
Jann can poke in it first. :)
-Kees
[0] https://lore.kernel.org/lkml/20230508075507.1720950-1-gongruiqi1@huawei.com/
[1] https://googleprojectzero.blogspot.com/2021/10/how-simple-linux-kernel-memory.html
[2] https://github.com/thejh/linux/commit/a87ad16046f6f7fd61080ebfb93753366466b761
--
Kees Cook
next prev parent reply other threads:[~2023-05-16 19:34 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-08 7:55 [PATCH RFC v2] Randomized slab caches for kmalloc() GONG, Ruiqi
2023-05-10 18:43 ` Hyeonggon Yoo
2023-05-10 19:32 ` Pedro Falcato
2023-05-12 10:11 ` Gong Ruiqi
2023-05-14 9:30 ` Vlastimil Babka
2023-05-15 8:20 ` Gong Ruiqi
2023-05-16 22:35 ` Hyeonggon Yoo
2023-05-22 7:35 ` Gong Ruiqi
2023-05-22 8:03 ` Hyeonggon Yoo
2023-05-22 8:58 ` GONG, Ruiqi
2023-05-24 5:54 ` Hyeonggon Yoo
2023-05-31 3:47 ` GONG, Ruiqi
2023-05-11 12:30 ` xiujianfeng
2023-05-11 14:54 ` Alexander Lobakin
2023-05-15 6:26 ` Gong Ruiqi
2023-05-16 12:43 ` Alexander Lobakin
2023-05-16 1:35 ` kernel test robot
2023-05-16 19:34 ` Kees Cook [this message]
2023-05-31 7:59 ` Gong Ruiqi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=202305161204.CB4A87C13@keescook \
--to=keescook@chromium.org \
--cc=42.hyeyoo@gmail.com \
--cc=aleksander.lobakin@intel.com \
--cc=gongruiqi1@huawei.com \
--cc=jannh@google.com \
--cc=kasan-dev@googlegroups.com \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=vbabka@suse.cz \
--cc=wangweiyang2@huawei.com \
--cc=xiujianfeng@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.