Thread (55 messages) 55 messages, 10 authors, 2023-07-20

Re: [PATCH 12/13] x86/jitalloc: prepare to allocate exectuatble memory as ROX

From: Mike Rapoport <rppt@kernel.org>
Date: 2023-06-05 20:43:34
Also in: bpf, linux-arm-kernel, linux-mips, linux-modules, linux-riscv, linux-s390, linuxppc-dev, lkml, loongarch, netdev, sparclinux

On Mon, Jun 05, 2023 at 04:10:21PM +0000, Edgecombe, Rick P wrote:
On Mon, 2023-06-05 at 11:11 +0300, Mike Rapoport wrote:
quoted
On Sun, Jun 04, 2023 at 10:52:44PM -0400, Steven Rostedt wrote:
quoted
On Thu, 1 Jun 2023 16:54:36 -0700
Nadav Amit [off-list ref] wrote:
quoted
quoted
The way text_poke() is used here, it is creating a new writable
alias
and flushing it for *each* write to the module (like for each
write of
an individual relocation, etc). I was just thinking it might
warrant
some batching or something.  
quoted
quoted
I am not advocating to do so, but if you want to have many
efficient
writes, perhaps you can just disable CR0.WP. Just saying that if
you
are about to write all over the memory, text_poke() does not
provide
too much security for the poking thread.
Heh, this is definitely and easier hack to implement :)
I don't know the details, but previously there was some strong dislike
of CR0.WP toggling. And now there is also the problem of CET. Setting
CR0.WP=0 will #GP if CR4.CET is 1 (as it currently is for kernel IBT).
I guess you might get away with toggling them both in some controlled
situation, but it might be a lot easier to hack up then to be made
fully acceptable. It does sound much more efficient though.
 
I don't think we'd really want that, especially looking at 

		WARN_ONCE(bits_missing, "CR0 WP bit went missing!?\n");

at native_write_cr0().
 
quoted
quoted
Batching does exist, which is what the text_poke_queue() thing
does.
For module loading text_poke_queue() will still be much slower than a
bunch
of memset()s for no good reason because we don't need all the
complexity of
text_poke_bp_batch() for module initialization because we are sure we
are
not patching live code.

What we'd need here is a new batching mode that will create a
writable
alias mapping at the beginning of apply_relocate_*() and
module_finalize(),
then it will use memcpy() to that writable alias and will tear the
mapping
down in the end.
It's probably only a tiny bit faster than keeping a separate writable
allocation and text_poking it in at the end.
Right, but it still will be faster than text_poking every relocation.
 
quoted
Another option is to teach alternatives to update a writable copy
rather
than do in place changes like Song suggested. My feeling is that it
will be
more intrusive change though.
You mean keeping a separate RW allocation and then text_poking() the
whole thing in when you are done? That is what I was trying to say at
the beginning of this thread. The other benefit is you don't make the
intermediate loading states of the module, executable.

I tried this technique previously [0], and I thought it was not too
bad. In most of the callers it looks similar to what you have in
do_text_poke(). Sometimes less, sometimes more. It might need
enlightening of some of the stuff currently using text_poke() during
module loading, like jump labels. So that bit is more intrusive, yea.
But it sounds so much cleaner and well controlled. Did you have a
particular trouble spot in mind?
Nothing in particular, except the intrusive part. Except the changes in
modules.c we'd need to teach alternatives to deal with a writable copy.
 
[0]
https://lore.kernel.org/lkml/20201120202426.18009-5-rick.p.edgecombe@intel.com/ (local)
-- 
Sincerely yours,
Mike.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help