On Fri 2025-03-07 11:12:18, zhang warden wrote:
> I had faced a scenario like this:
> 
> There is a fuse.ko which is built as module of kernel source.
> However, our team maintain the fuse as oot module.
> 
> There is a bug of (name it as B1) the original fuse.ko. 
> And our team fix B1 of fuse.ko as release it as oot module fuse_o1.ko.
> Our system loaded fuse_o1.ko. Now, another team made a livepatch module base 
> on fuse.ko to fix B2 bug.
> They load this livepatch_fuse.ko to the system, it fixed B2 bug, however, the 
> livepatch_fuse.ko revert the fix of fuse_o1.ko.
> 
> It expose the B1 bug which is already fix in fuse_o1.ko
> The exposed B1 bug make fault to our cluster, which is a bad thing :(
> 
> This  scenario shows the vulnerable of live-patching when handling 
> out-of-tree module.
> 
> I have a original solution to handle this:
>     • In kpatch-build, we would record the patched object, take the object of 
> ko as a list of parameters.
>     • Pass this ko list as parameter to create-klp-moudle.c
>     • For each patched ko object, we should read its srcversion from the 
> original module. If we use --oot-module, we would read the srcversion from 
> the oot moudle version.
>     • Store the target srcversion to a section named '.klp.target_srcversions'
>     • When the kpatch module loading, we shoud check if section 
> '.klp.target_srcversion' existed. If existed, we should check srcversion of 
> the patch target in the system match our recorded srcversion or not. If thet 
> are not match, refuse to load it. This can make sure the livepatch module 
> would not load the wrong target.

The work with the elf sections is tricky. I would prefer to add
.srcversion into struct klp_object, something like:

 struct klp_object {
        /* external */
        const char *name;
+       const char *srcversion;
        struct klp_func *funcs;
        struct klp_callbacks callbacks;
        [...]
 }

It would be optional. I made just a quick look. It might be enough
to check it in klp_find_object_module() and do not set obj->mod
when obj->srcversion != NULL and does not match mod->srcversion.

Wait! We need to check it also in klp_write_section_relocs().
Otherwise, klp_apply_section_relocs() might apply the relocations
for non-compatible module.

Another question is whether the same livepatch could support more
srcversions of the same module. It might be safe when the livepatched
functions are compatible. But it would be error prone.

If we wanted to allow support for incompatible modules with the same
name, we would need to encode the srcversion also into the name
of the special .klp_rela sections so that we could have separate
relocations for each variant.


Alternative: I think about using "mod->build_id" instead of "srcversion".
        It would be even more strict because it would make dependency
        on a particular build.

        An advantage is that it is defined also for vmlinux,
        see vmlinux_build_id. So that we could easily use
        the same approach also for vmlinux.

        I do not have strong opinion on this though.


> This function can avoid livepatch from patching the wrong version of the 
> function.
> 
> The original discussion can be seem on [1]. (Discussion with Joe Lawrence)
> 
> After the discussion, we think that the actual enforcement of this seems like 
> a job for kernel/livepatch/core.c.
> Or it should be the process of sys call `init_module` when loading a module.
>
> I am here waiting for Request For Comment. Before I do codes.

I am open to accept such a feature. It might improve reliability of
the livepatching.

Let's see how the code looks like and how complicated would be to
create such livepatches from sources or using kPatch.

Best Regards,
Petr

Reply via email to