[PATCH RFC 0/2] livepatch: patch creation tooling proposal

From: Josh Poimboeuf
Date: Thu Oct 27 2016 - 10:37:08 EST


Here's what I've been working on in preparation for my talk about
"livepatch module creation tooling" at next week's Linux Plumbers
Conference. I'm posting this code now as a sneak preview. Hopefully we
can get the conversation started here, as the microconference agenda is
packed and there might not be that much time for discussion.

Other than the consistency model, our last big missing piece for live
patching is the tooling for creating patch modules.

In kpatch-land, we have kpatch-build:

https://github.com/dynup/kpatch/tree/master/kpatch-build

I wrote the original version of kpatch-build almost three years ago. It
has been made much better since then, thanks to many improvements (and
rewrites) from Seth, Jessica, and others. It's rather "magical". It
takes a source code patch and spits out a patch module. It works by
building the kernel twice: once without the patch and once with it. It
then does a binary diff of the two kernels, and extracts that difference
into the patch module, at a function granularity. It's a very powerful
tool, and it's very easy to use, when it works.

But maintenance of kpatch-build can be a nightmare. It needs to have
intimate knowledge of many gcc and kernel quirks. When one of those
quirks change, the tool breaks. Not to mention all the bugs we already
know about today (for example, see the issues on github). And porting
it to other arches is going to be really hard, since each arch has its
own set of quirks.

So while kpatch-build is powerful and easy to use, I get the feeling
that it's just too complex to be reasonably sustainable. We need
something simpler.

Today we *do* have something simpler upstream, but it's *too* simple.
The existing kernel build infrastructure can be used to build livepatch
modules pretty much like any other out-of-tree kernel module. See the
sample in samples/livepatch. But it can't deal with relocations of
local or unexported symbols.

So here's my proposal: use the existing kernel build infrastructure. If
klp relocations are needed, manually specify them with a new
klp_module_reloc struct and corresponding KLP_MODULE_RELOC macro. Then
run a post-processing tool called klp-convert which converts those
klp_module_reloc structs into the sections, relocations, and symbols
needed by the klp runtime code.

See patch 2/2 to see what a patch's module source code would look like.

Note this is somewhat harder to use than kpatch-build, because you have
to copy/paste the replacement function into the source file for your
livepatch module. And then you have to determine if the new function
needs any local or unexported symbols, and then specify those missing
symbols with the KLP_MODULE_RELOC macro.

With this patch set, figuring out the missing symbols is relatively
easy: build the patch without the livepatch modinfo, and the linker
warnings will tell you what's missing. Or alternatively, try to load
the module and it should tell you the unresolved symbols and then fail
to load.

We can probably add more tooling to make that easier. But anyway I
think it won't be too bad if we document the process. The patch
creation process doesn't need to be *too* easy: the patch author already
needs to be very careful regardless.

For kGraft, what tooling do you guys use for patch creation? I seem to
remember several approaches being mentioned -- one of them similar to
what I'm proposing here, I believe -- but I don't know what you ended up
with. Maybe you're already doing something like this?

In any case it would be good to hear everyone's opinions about this
approach. This code is functional, but it's a work in progress, so
don't review it *too* closely. Just wondering what people think about
the general idea.


NOTE: There's still a big missing piece here: how to support the new
.klp.arch.objname..altinstructions/.parainstructions sections.
Specifically, when parsing the entries in an .altinstructions section,
how can klp-convert determine which object a given entry belongs to?

One solution would be to replace the explicit klp_register_patch()
interface with a more implicit special section based interface. For
example, the klp_funcs/objects could be placed in a special section
which is recognized by the module loader.

Then klp-convert would then be able to tell which object a given
function belongs to, and could use that information to determine which
object a given .altinstruction entry belongs to, and then move the entry
to the appropriate .klp.arch section.


TODO:
- support .klp.arch.objname..altinstructions/parainstructions
- split up the patches better
- patch creation documentation
- more tooling support for detecting missing relocations? or
automatically converting them if a sympos isn't needed?

Josh Poimboeuf (2):
livepatch: add klp-convert tool and integrate with module build
livepatch: update sample module to use klp relocations

Makefile | 2 +-
include/linux/livepatch.h | 1 +
include/uapi/linux/Kbuild | 1 +
include/uapi/linux/livepatch.h | 37 ++
kernel/livepatch/core.c | 4 +-
samples/livepatch/livepatch-sample.c | 15 +-
scripts/Makefile | 1 +
scripts/Makefile.modpost | 18 +-
scripts/livepatch/.gitignore | 1 +
scripts/livepatch/Makefile | 7 +
scripts/livepatch/elf.c | 717 +++++++++++++++++++++++++++++++++++
scripts/livepatch/elf.h | 88 +++++
scripts/livepatch/klp-convert.c | 181 +++++++++
scripts/livepatch/list.h | 381 +++++++++++++++++++
scripts/mod/modpost.c | 9 +-
scripts/mod/modpost.h | 1 +
16 files changed, 1454 insertions(+), 10 deletions(-)
create mode 100644 include/uapi/linux/livepatch.h
create mode 100644 scripts/livepatch/.gitignore
create mode 100644 scripts/livepatch/Makefile
create mode 100644 scripts/livepatch/elf.c
create mode 100644 scripts/livepatch/elf.h
create mode 100644 scripts/livepatch/klp-convert.c
create mode 100644 scripts/livepatch/list.h

--
2.7.4