Commit Graph

107 Commits

Author SHA1 Message Date
Josh Poimboeuf
9d016add40 fix review comments 2014-06-18 12:23:38 -05:00
Josh Poimboeuf
6b45c5dbd0 remove unused kpatch_dynrela.objname field 2014-06-18 11:17:55 -05:00
Josh Poimboeuf
34cc258a31 fix undefined symbols for future loaded modules
When patching module A, if one of the new function's relas reference a
symbol in module B, we currently just leave it as a normal rela.  But if
module B hasn't been loaded yet, the patch module will fail to load due
to the rela's reference to an undefined symbol.

The fix is to convert these relas to dynrelas, which can be resolved
later in the module notifier when A is loaded.

Also added support for the R_X86_64_NONE relocation type, needed for
dynrelas which reference __fentry__.
2014-06-18 11:17:11 -05:00
Josh Poimboeuf
827c91bae6 fix review comments
- get rid of unneeded vmlinux variable
- create patch_make_funcs_list() and patch_make_dynrelas_list()
2014-06-17 12:17:58 -05:00
Josh Poimboeuf
84c34ff584 implement per-object patching/relocations
The recent module patching code has exposed some problems with our data
structures. We currently patch the funcs and dynrelas individually,
which is kind of scary now that different objects can be patched at
different times.  Instead it's cleaner and safer to group them by
patched object.

This patch implements per-object patching and relocations by refactoring
the interfaces:

- Completely separate the create-diff-object <-> patch module interface
  from the patch module <-> core module interface. create-diff-object
  will include "kpatch-patch.h" but not "kpatch.h". Thus,
  create-diff-object has no knowledge about the core module's
  interfaces, and the core module has no knowledge about the patch
  module's special sections.

- Newly added kpatch-patch.h defines the format of the patch module
  special sections. It's used by create-diff-object to create the
  special sections and used by the patch module to read them.

- kpatch.h still defines the core module interfaces. Each kpatch_module
  has a list of kpatch_objects for each module object to be patched.
  Each kpatch_object has a list of kpatch_funcs and a list of
  kpatch_dynrelas. The patch module creates these lists when populating
  kpatch_module.

This way of structuring the data allows us to patch funcs and dynrelas
on a per patched object basis, which will allow us to catch more error
scenarios and make the code easier to manage going forward.  It also
allows the use of much more common code between kpatch_register() and
kpatch_module_notify().
2014-06-17 10:03:08 -05:00
Josh Poimboeuf
844af68115 kmod/core: support for patching of future loaded modules
This allows a patch module to contain patched functions for modules
which haven't been loaded yet.  If/when the module is loaded later, it
will be patched from the module notifier function.
2014-06-13 12:49:43 -05:00
Josh Poimboeuf
052806fe43 kmod/core: fix replace race condition
In the replace case, stop calling module_put on a patch module before
we're potentially done with it.

This will also be needed for future module patching if we want to
properly replace a patch module which only patches a future loaded
module (that's a mouthful).

Fixes #165.
2014-06-13 12:49:43 -05:00
Josh Poimboeuf
2ec9a0481d kmod/core: create global kpmod_list
Create a list of registered patch modules, which will be used in the
module notifier to patch future loaded modules.  It will also be used to
fix the kpatch replace race condition where it calls module_put too
early.
2014-06-13 11:57:15 -05:00
Josh Poimboeuf
063e9a62f5 kmod/core: get rid of kpatch_internal
The kpatch_internal struct is a good idea, in that it documents which
parts of kpatch_module shouldn't be used by the patch module.  But it
creates extra code and will require more extra code if we want to keep a
list of kpmods, which is needed to create a module notifier for module
patching of future loaded modules.

Embedding the private data directly in the public struct allows the code
to be simpler: no extra kmallocs/kfrees, no need to store pointers
between the public and private structs.  I think the simpler code is
worth the tradeoff (exposing implementation detail).  Kernel code
usually doesn't bother with hiding a internal struct data from other
kernel code anyway.  For example, see ftrace_ops or struct kprobe.

The private fields are documented with a "private" comment.
2014-06-13 11:57:15 -05:00
Josh Poimboeuf
b58e77ae9c kmod/core: move kpatch_write_relocations call
Write the relocations _after_ calling kpatch_calculate_old_addr() so
that we'll have a reference to the affected modules.
2014-06-13 11:57:15 -05:00
Josh Poimboeuf
c61fb88a23 kmod/core: add ftrace helper functions
Move all the ftrace filtering and registering logic into a couple of new
helper functions.  Change kpatch_num_registered to kpatch_num_patched,
which now tracks the number of patched functions rather than the number
of patch modules.

This simplifies the code a bit and will also prevent a future loaded
module scenario where ftrace_ops can be registered with an empty filter,
resulting in _all_ kernel functions getting registered with ftrace.
2014-06-13 11:57:14 -05:00
Josh Poimboeuf
dfc2641de2 kmod/core: use single quotes
Use single quotes when printing the name of a patch module, rather than
double quotes.  This is more consistent with other printk messages, and
looks better too!
2014-06-13 11:56:17 -05:00
Josh Poimboeuf
3ad35bd4f4 kmod/core: protect find_module with module_mutex 2014-06-13 11:56:17 -05:00
Josh Poimboeuf
6d951dc996 kmod/core: fix error path for kpatch_verify_symbol_match failure
If kpatch_verify_symbol_match() fails, set the num_funcs variable so
that the ftrace rollback only removes the filter for the affected
functions.
2014-06-13 11:56:17 -05:00
Josh Poimboeuf
579ee5f499 kmod/core: fix kpatch_put_modules call in error path
If kpatch_ftrace_add_func fails, num_funcs will be one less than what it
needs to be for kpatch_put_modules to work properly.  Instead give it
the full array size, and it can figure out which modules to put based on
whether func->mod is nonzero.
2014-06-13 11:56:16 -05:00
Josh Poimboeuf
31bd3a1538 kmod/core: fix kpatch_put_modules call order
kpatch_put_modules() should be called _after_ removing the ftrace
filters.
2014-06-13 11:55:16 -05:00
Seth Jennings
d026f9d866 Merge pull request #235 from jpoimboe/verbose-fix
__verbose rela fix
2014-06-04 16:26:50 -05:00
Josh Poimboeuf
0f908fb805 kmod/core: support R_X86_64_64 for module patching 2014-06-04 13:44:27 -05:00
Josh Poimboeuf
cb78565295 kmod/core: print func name on activeness safety failure 2014-06-04 12:20:49 -05:00
Josh Poimboeuf
76157dce4a kmod/core: add support for R_X86_64_64 dynrelas
Needed for relocations to data sections.
2014-06-04 11:48:19 -05:00
Seth Jennings
15b22cf01b review changes for module support PR
Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-06-03 11:36:51 -05:00
Seth Jennings
5f00b0b05f add module patching support to core module
This commit adds support for patching modules.  If a patch or dynrela is
determined to be for a kernel module, the old_offset/src is not used and
the symbol location is looked up using kallsyms.  The module being
patched is also references to keep if from disappearing from underneath
us.

This commit introduces early and limited support.  The kernel module to
be patched must already be loaded or the patch module will not apply.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-06-02 20:34:37 -05:00
Seth Jennings
3f864cc864 add module patching support to create-diff-object
This commit adds module patching support to create-diff-object by:

1) generalizing the vmlinux CLI parameter
2) adding the kernel object name to each patch and dynrela
3) adding slightly different logic for vmlinux/module in the dynrela
creation

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-06-02 20:34:37 -05:00
Seth Jennings
aa8c5da5ba change struct kpatch_patch s/old_addr/old_offset
Make old addresses relative to the start address of the relocatable
kernel or module.

This commit has no functional effect; it just prepares the code for
future acceptance of the module patching support.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-06-02 15:57:12 -05:00
Josh Poimboeuf
ecf6173869 kmod/core: validate dynrela destination address
Ensure that dynrela destination addresses are within the patch module's
memory.

Also, use the module address ranges to check whether set_memory_rw() is
needed.
2014-05-30 09:24:38 -05:00
Seth Jennings
2225bd83cc Merge pull request #180 from ryanmiao/print_funcs
export funcs via sysfs
2014-05-27 23:24:49 -05:00
Josh Poimboeuf
625fcdfb72 kmod/core: ensure page is RO before changing its permissions
Make sure we leave the page's execution permissions in the same state we
found them.
2014-05-27 21:58:15 -05:00
Josh Poimboeuf
ab941fb90a kmod/core: make loc variable a u64
So less casting is needed.
2014-05-27 21:49:45 -05:00
Josh Poimboeuf
80c1e8ac83 kmod/core: move dynamic relocation writes to new function
Unclutter kpatch_register a little bit.
2014-05-27 21:47:50 -05:00
Josh Poimboeuf
0ebbed244e create-diff-object: percpu support
The -fdata-sections gcc flag doesn't work with objects in the
.data..percpu section.  Any function which uses a percpu variable
references this section, causing the section to get incorrectly included
in the patch module.

Manually convert these section references to object symbol references so
that the needed symbol can be found in vmlinux.

Also, the core module symbol verification code will fail when looking up
a percpu variable, because sprint_symbol doesn't think a percpu address
is a valid kernel address.  So rewrite the symbol verification code to
use kallsyms_on_each_symbol() instead.  It's not ideal performance-wise:
it seems to cost about 1ms per symbol lookup.  I think that's acceptable
for now.  In the future we may want to try to get a better upstream
kallsyms interface.
2014-05-27 12:47:42 -05:00
Jincheng Miao
827a143caf kmod/patch: export patched functions information via sysfs
This feature is implemented as:
```
[root@localhost kpatch]# insmod ./kpatch-meminfo.ko
[root@localhost kpatch]# ls /sys/kernel/kpatch/patches/kpatch_meminfo/functions/meminfo_proc_show/
new_addr  old_addr
[root@localhost kpatch]# cat /sys/kernel/kpatch/patches/kpatch_meminfo/functions/meminfo_proc_show/new_addr
0xffffffffa05211e0
[root@localhost kpatch]# cat /sys/kernel/kpatch/patches/kpatch_meminfo/functions/meminfo_proc_show/old_addr
0xffffffff8125d0e0
```

The patch module init function will allocate and init kpatch_func_obj with
customized kobj_type func_ktype. The attribute new_addr and old_addr of
kpatch_func_obj is attached to this func_ktype, so that these files could
be created by kobject_add automatically.

Signed-off-by: Jincheng Miao <jincheng.miao@gmail.com>
2014-05-27 21:56:56 +08:00
Seth Jennings
a5d986ee96 review fixups
Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-23 23:41:28 -05:00
Seth Jennings
505e948af0 symbol location verification support
This commit introduces functionality to verify the location of symbols
used in both the patch and dynrelas sections.  It adds significant
protection from mismatches between the base and running kernels.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-23 16:39:56 -05:00
Seth Jennings
170c8b1ba1 fix review comments
Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-20 12:44:31 -05:00
Seth Jennings
21fc274448 dynrelas support, obsoleting link-vmlinux-syms
This adds dynamic linking support for the patch modules.  It is the
first step toward supporting patching module code and relocatable
kernels.

Rela entries that reference non-included local and non-exported global
symbols are converted to "dynrelas".  These dynrelas are relocations
that are done by the core module, not the kernel module linker.  This
allows the core module to apply offsets to the base addresses found
in the base vmlinux or module.

Signed-off-by: Seth Jennings <sjenning@redhat.com>

Conflicts:
	kpatch-build/kpatch-build
2014-05-20 12:44:31 -05:00
Seth Jennings
fd8176faf8 rename .patches section to .kpatch.patches
Adding .kpatch to the section name more clearly documents that these
are kpatch related sections.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-20 12:44:30 -05:00
Seth Jennings
797b7af234 cleanup: remove unneeded patches variable
Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-20 12:44:30 -05:00
Josh Poimboeuf
5e25365244 Revert #186 (add dynamic symbol linking support)
We merged PR #186 a little too hastily.  It seg faults with the new
parainstructions-section.patch in the integration test suite.  Reverting
it for now until we get it figured out.

This reverts commit e1177e3a03.
This reverts commit 880e271841.
This reverts commit 2de5f6cbfb.
This reverts commit 38b7ac74ad.
This reverts commit 108cd9f95e.
2014-05-15 17:34:16 -05:00
Seth Jennings
e1177e3a03 fix review comments
Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-15 13:42:27 -05:00
Seth Jennings
880e271841 dynrelas support, obsoleting link-vmlinux-syms
This adds dynamic linking support for the patch modules.  It is the
first step toward supporting patching module code and relocatable
kernels.

Rela entries that reference non-included local and non-exported global
symbols are converted to "dynrelas".  These dynrelas are relocations
that are done by the core module, not the kernel module linker.  This
allows the core module to apply offsets to the base addresses found
in the base vmlinux or module.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-15 13:29:15 -05:00
Seth Jennings
2de5f6cbfb rename .patches section to .kpatch.patches
Adding .kpatch to the section name more clearly documents that these
are kpatch related sections.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-15 13:28:24 -05:00
Seth Jennings
108cd9f95e cleanup: remove unneeded patches variable
Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-14 14:04:54 -05:00
Josh Poimboeuf
a6694fffff kmod: install core module to "extra" subdir
To be more consistent with other out-of-tree modules, install the core
module to /usr[/local]/lib/modules/`uname -r`/extra/kpatch/kpatch.ko.
2014-05-13 15:10:40 -05:00
Josh Poimboeuf
5ea376a47a Merge pull request #181 from spartacus06/interface-refactor
refactor core <-> patch interface
2014-05-12 15:43:26 -05:00
Seth Jennings
e5f17c6b9a fix incompatible pointer type warning
Fixes the following warning:

kpatch-patch-hook.c:71:2: warning: initialization from incompatible pointer type [enabled by default]
  __ATTR(enabled, 0644, patch_enabled_show, patch_enabled_store);
  ^

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-12 15:20:09 -05:00
Seth Jennings
681a6e80b9 refactor core <-> patch interface
Make kpatch_funs truly internal by:
Defining it in core.c
Adding a struct kpatch_internal, declared in kpatch.h and defined in
 core.c, that contains per patch module internal data.
Adding an "internal" field to struct kpatch_modules.
Allocating internal and funcs data in core.c, not in the patch module,
 since the patch module has no knowledge of kpatch_func anymore.
Adding a "patch" field to kpatch_func that points directly to the
 kpatch_patch provided by the module (rather than a field-by-field copy)

Signed-off-by: Seth Jennings <sjenning@redhat.com>
2014-05-12 14:58:29 -05:00
Jincheng Miao
171cd567ce Fix kpatch.ko build on Ubuntu Saucy.
The error likes:
make -C /lib/modules/3.11.0-12-generic/build M=/home/ryan/kpatch/kmod/core kpatch.ko
make[3]: Entering directory `/usr/src/linux-headers-3.11.0-12-generic'
  CC [M]  /home/ryan/kpatch/kmod/core/core.o
/home/ryan/kpatch/kmod/core/core.c:42:32: fatal error: linux/preempt_mask.h: No such file or directory
 #include <linux/preempt_mask.h>

I feel sorry to introduce this problem from my laster commit 6c2d6444.
Some old kernel doesn't have header file preempt_mask.h, and the safe
way is using hardirq.h to find in_nmi().

Signed-off-by: Jincheng Miao <jincheng.miao@gmail.com>
2014-05-07 17:48:02 +08:00
Josh Poimboeuf
ab112cce2d kmod/core: minor style fix
For compatibility with checkpatch
2014-05-05 13:40:42 -05:00
Josh Poimboeuf
6ee8803978 kmod/core: kpatch_unregister return error if !kpmod->enabled
It's probably cleaner to just return -EINVAL if the kpmod isn't enabled,
instead of warning and continuing, which would be dangerous.

I think the reason I had it WARN before is because this condition
shouldn't be possible given the source for the patch module.  But the
core module can't necessarily assume that it's our trustworthy patch
module code on the other side.
2014-05-02 23:02:29 -05:00
Josh Poimboeuf
4bde6c3bbf kmod/core: fix kpatch_num_registered decrement
Oops, kpatch_unregister doesn't decrement kpatch_num_registered whenever
it's > 1.
2014-05-02 22:55:32 -05:00