Re: [PATCH 0/7] livepatch,module: Remove .klp.arch and module_disable_ro()

From: Jessica Yu
Date: Thu Apr 16 2020 - 11:31:46 EST


+++ Josh Poimboeuf [15/04/20 11:17 -0500]:
On Wed, Apr 15, 2020 at 04:24:15PM +0200, Peter Zijlstra wrote:
> It bothers me that both the notifiers and the module init() both see the
> same MODULE_STATE_COMING state, but only in the former case is the text
> writable.
>
> I think it's cognitively simpler if MODULE_STATE_COMING always means the
> same thing, like the comments imply, "fully formed" and thus
> not-writable:
>
> enum module_state {
> MODULE_STATE_LIVE, /* Normal state. */
> MODULE_STATE_COMING, /* Full formed, running module_init. */
> MODULE_STATE_GOING, /* Going away. */
> MODULE_STATE_UNFORMED, /* Still setting it up. */
> };
>
> And, it keeps tighter constraints on what a notifier can do, which is a
> good thing if we can get away with it.

Moo! -- but jump_label and static_call are on the notifier chain and I
was hoping to make it cheaper for them. Should we perhaps weane them off the
notifier and, like ftrace/klp put in explicit calls?

It'd make the error handling in prepare_coming_module() a bigger mess,
but it should work.

So you're wanting to have jump labels and static_call do direct writes
instead of text pokes, right? Makes sense.

I don't feel strongly about "don't let module notifiers modify text".

But I still not a fan of the fact that COMING has two different
"states". For example, after your patch, when apply_relocate_add() is
called from klp_module_coming(), it can use memcpy(), but when called
from klp module init() it has to use text poke. But both are COMING so
there's no way to look at the module state to know which can be used.

This is a good observation, thanks for bringing it up. I agree that we
should strive to be consistent with what the module states mean. In my
head, I think it is easiest to assume/establish the following meanings
for each module state:

MODULE_STATE_UNFORMED - no protections. relocations, alternatives,
ftrace module initialization, etc. any other text modifications are
in the process of being applied. Direct writes are permissible.

MODULE_STATE_COMING - module fully formed, text modifications are
done, protections applied, module is ready to execute init or is
executing init.

I wonder if we could enforce the meaning of these two states more
consistently without needing to add another module state.

Regarding Peter's patches, with the set_all_modules_text_*() api gone,
and ftrace reliance on MODULE_STATE_COMING gone (I think?), is there
anything preventing ftrace_module_init+enable from being called
earlier (i.e., before complete_formation()) while the module is
unformed? Then you don't have to move module_enable_ro/nx later and we
keep the MODULE_STATE_COMING semantics. And if we're enforcing the
above module state meanings, I would also be OK with moving jump_label
and static_call out of the coming notifier chain and making them
explicit calls while the module is still writable.

Sorry in advance if I missed anything above, I'm still trying to wrap
my head around which callers need what module state and what module
permissions :/

Jessica