Skip to content

Commit 0faef83

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching
Pull livepatching fixes from Jiri Kosina: - symbol lookup locking fix, from Miroslav Benes - error handling improvements in case of failure of the module coming notifier, from Minfei Huang - we were too pessimistic when kASLR has been enabled on x86 and were dropping address hints on the floor unnecessarily in such case. Fix from Jiri Kosina - a few other small fixes and cleanups * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching: livepatch: add module locking around kallsyms calls livepatch: annotate klp_init() with __init livepatch: introduce patch/func-walking helpers livepatch: make kobject in klp_object statically allocated livepatch: Prevent patch inconsistencies if the coming module notifier fails livepatch: match return value to function signature x86: kaslr: fix build due to missing ALIGN definition livepatch: x86: make kASLR logic more accurate x86: introduce kaslr_offset()
2 parents 67db8a8 + 110c146 commit 0faef83

File tree

6 files changed

+79
-38
lines changed

6 files changed

+79
-38
lines changed

arch/x86/include/asm/livepatch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#ifndef _ASM_X86_LIVEPATCH_H
2222
#define _ASM_X86_LIVEPATCH_H
2323

24+
#include <asm/setup.h>
2425
#include <linux/module.h>
2526
#include <linux/ftrace.h>
2627

arch/x86/include/asm/setup.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,24 @@ static inline void x86_ce4100_early_setup(void) { }
6060
#ifndef _SETUP
6161

6262
#include <asm/espfix.h>
63+
#include <linux/kernel.h>
6364

6465
/*
6566
* This is set up by the setup-routine at boot-time
6667
*/
6768
extern struct boot_params boot_params;
69+
extern char _text[];
6870

6971
static inline bool kaslr_enabled(void)
7072
{
7173
return !!(boot_params.hdr.loadflags & KASLR_FLAG);
7274
}
7375

76+
static inline unsigned long kaslr_offset(void)
77+
{
78+
return (unsigned long)&_text - __START_KERNEL;
79+
}
80+
7481
/*
7582
* Do NOT EVER look at the BIOS memory size location.
7683
* It does not work on many machines.

arch/x86/kernel/machine_kexec_64.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <asm/io_apic.h>
2727
#include <asm/debugreg.h>
2828
#include <asm/kexec-bzimage64.h>
29+
#include <asm/setup.h>
2930

3031
#ifdef CONFIG_KEXEC_FILE
3132
static struct kexec_file_ops *kexec_file_loaders[] = {
@@ -335,7 +336,7 @@ void arch_crash_save_vmcoreinfo(void)
335336
VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
336337
#endif
337338
vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
338-
(unsigned long)&_text - __START_KERNEL);
339+
kaslr_offset());
339340
}
340341

341342
/* arch-dependent functionality related to kexec file-based syscall */

arch/x86/kernel/setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
836836
{
837837
if (kaslr_enabled()) {
838838
pr_emerg("Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)\n",
839-
(unsigned long)&_text - __START_KERNEL,
839+
kaslr_offset(),
840840
__START_KERNEL,
841841
__START_KERNEL_map,
842842
MODULES_VADDR-1);

include/linux/livepatch.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ struct klp_object {
9999
struct klp_func *funcs;
100100

101101
/* internal */
102-
struct kobject *kobj;
102+
struct kobject kobj;
103103
struct module *mod;
104104
enum klp_state state;
105105
};
@@ -123,6 +123,12 @@ struct klp_patch {
123123
enum klp_state state;
124124
};
125125

126+
#define klp_for_each_object(patch, obj) \
127+
for (obj = patch->objs; obj->funcs; obj++)
128+
129+
#define klp_for_each_func(obj, func) \
130+
for (func = obj->funcs; func->old_name; func++)
131+
126132
int klp_register_patch(struct klp_patch *);
127133
int klp_unregister_patch(struct klp_patch *);
128134
int klp_enable_patch(struct klp_patch *);

kernel/livepatch/core.c

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ static bool klp_is_patch_registered(struct klp_patch *patch)
128128

129129
static bool klp_initialized(void)
130130
{
131-
return klp_root_kobj;
131+
return !!klp_root_kobj;
132132
}
133133

134134
struct klp_find_arg {
@@ -179,7 +179,9 @@ static int klp_find_object_symbol(const char *objname, const char *name,
179179
.count = 0
180180
};
181181

182+
mutex_lock(&module_mutex);
182183
kallsyms_on_each_symbol(klp_find_callback, &args);
184+
mutex_unlock(&module_mutex);
183185

184186
if (args.count == 0)
185187
pr_err("symbol '%s' not found in symbol table\n", name);
@@ -219,13 +221,19 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
219221
.name = name,
220222
.addr = addr,
221223
};
224+
int ret;
222225

223-
if (kallsyms_on_each_symbol(klp_verify_callback, &args))
224-
return 0;
226+
mutex_lock(&module_mutex);
227+
ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
228+
mutex_unlock(&module_mutex);
225229

226-
pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
227-
name, addr);
228-
return -EINVAL;
230+
if (!ret) {
231+
pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
232+
name, addr);
233+
return -EINVAL;
234+
}
235+
236+
return 0;
229237
}
230238

231239
static int klp_find_verify_func_addr(struct klp_object *obj,
@@ -234,8 +242,9 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
234242
int ret;
235243

236244
#if defined(CONFIG_RANDOMIZE_BASE)
237-
/* KASLR is enabled, disregard old_addr from user */
238-
func->old_addr = 0;
245+
/* If KASLR has been enabled, adjust old_addr accordingly */
246+
if (kaslr_enabled() && func->old_addr)
247+
func->old_addr += kaslr_offset();
239248
#endif
240249

241250
if (!func->old_addr || klp_is_module(obj))
@@ -422,7 +431,7 @@ static void klp_disable_object(struct klp_object *obj)
422431
{
423432
struct klp_func *func;
424433

425-
for (func = obj->funcs; func->old_name; func++)
434+
klp_for_each_func(obj, func)
426435
if (func->state == KLP_ENABLED)
427436
klp_disable_func(func);
428437

@@ -440,7 +449,7 @@ static int klp_enable_object(struct klp_object *obj)
440449
if (WARN_ON(!klp_is_object_loaded(obj)))
441450
return -EINVAL;
442451

443-
for (func = obj->funcs; func->old_name; func++) {
452+
klp_for_each_func(obj, func) {
444453
ret = klp_enable_func(func);
445454
if (ret) {
446455
klp_disable_object(obj);
@@ -463,7 +472,7 @@ static int __klp_disable_patch(struct klp_patch *patch)
463472

464473
pr_notice("disabling patch '%s'\n", patch->mod->name);
465474

466-
for (obj = patch->objs; obj->funcs; obj++) {
475+
klp_for_each_object(patch, obj) {
467476
if (obj->state == KLP_ENABLED)
468477
klp_disable_object(obj);
469478
}
@@ -523,7 +532,7 @@ static int __klp_enable_patch(struct klp_patch *patch)
523532

524533
pr_notice("enabling patch '%s'\n", patch->mod->name);
525534

526-
for (obj = patch->objs; obj->funcs; obj++) {
535+
klp_for_each_object(patch, obj) {
527536
if (!klp_is_object_loaded(obj))
528537
continue;
529538

@@ -651,6 +660,15 @@ static struct kobj_type klp_ktype_patch = {
651660
.default_attrs = klp_patch_attrs,
652661
};
653662

663+
static void klp_kobj_release_object(struct kobject *kobj)
664+
{
665+
}
666+
667+
static struct kobj_type klp_ktype_object = {
668+
.release = klp_kobj_release_object,
669+
.sysfs_ops = &kobj_sysfs_ops,
670+
};
671+
654672
static void klp_kobj_release_func(struct kobject *kobj)
655673
{
656674
}
@@ -680,7 +698,7 @@ static void klp_free_object_loaded(struct klp_object *obj)
680698

681699
obj->mod = NULL;
682700

683-
for (func = obj->funcs; func->old_name; func++)
701+
klp_for_each_func(obj, func)
684702
func->old_addr = 0;
685703
}
686704

@@ -695,7 +713,7 @@ static void klp_free_objects_limited(struct klp_patch *patch,
695713

696714
for (obj = patch->objs; obj->funcs && obj != limit; obj++) {
697715
klp_free_funcs_limited(obj, NULL);
698-
kobject_put(obj->kobj);
716+
kobject_put(&obj->kobj);
699717
}
700718
}
701719

@@ -713,7 +731,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
713731
func->state = KLP_DISABLED;
714732

715733
return kobject_init_and_add(&func->kobj, &klp_ktype_func,
716-
obj->kobj, "%s", func->old_name);
734+
&obj->kobj, "%s", func->old_name);
717735
}
718736

719737
/* parts of the initialization that is done only when the object is loaded */
@@ -729,7 +747,7 @@ static int klp_init_object_loaded(struct klp_patch *patch,
729747
return ret;
730748
}
731749

732-
for (func = obj->funcs; func->old_name; func++) {
750+
klp_for_each_func(obj, func) {
733751
ret = klp_find_verify_func_addr(obj, func);
734752
if (ret)
735753
return ret;
@@ -753,11 +771,12 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
753771
klp_find_object_module(obj);
754772

755773
name = klp_is_module(obj) ? obj->name : "vmlinux";
756-
obj->kobj = kobject_create_and_add(name, &patch->kobj);
757-
if (!obj->kobj)
758-
return -ENOMEM;
774+
ret = kobject_init_and_add(&obj->kobj, &klp_ktype_object,
775+
&patch->kobj, "%s", name);
776+
if (ret)
777+
return ret;
759778

760-
for (func = obj->funcs; func->old_name; func++) {
779+
klp_for_each_func(obj, func) {
761780
ret = klp_init_func(obj, func);
762781
if (ret)
763782
goto free;
@@ -773,7 +792,7 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
773792

774793
free:
775794
klp_free_funcs_limited(obj, func);
776-
kobject_put(obj->kobj);
795+
kobject_put(&obj->kobj);
777796
return ret;
778797
}
779798

@@ -794,7 +813,7 @@ static int klp_init_patch(struct klp_patch *patch)
794813
if (ret)
795814
goto unlock;
796815

797-
for (obj = patch->objs; obj->funcs; obj++) {
816+
klp_for_each_object(patch, obj) {
798817
ret = klp_init_object(patch, obj);
799818
if (ret)
800819
goto free;
@@ -883,30 +902,31 @@ int klp_register_patch(struct klp_patch *patch)
883902
}
884903
EXPORT_SYMBOL_GPL(klp_register_patch);
885904

886-
static void klp_module_notify_coming(struct klp_patch *patch,
905+
static int klp_module_notify_coming(struct klp_patch *patch,
887906
struct klp_object *obj)
888907
{
889908
struct module *pmod = patch->mod;
890909
struct module *mod = obj->mod;
891910
int ret;
892911

893912
ret = klp_init_object_loaded(patch, obj);
894-
if (ret)
895-
goto err;
913+
if (ret) {
914+
pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
915+
pmod->name, mod->name, ret);
916+
return ret;
917+
}
896918

897919
if (patch->state == KLP_DISABLED)
898-
return;
920+
return 0;
899921

900922
pr_notice("applying patch '%s' to loading module '%s'\n",
901923
pmod->name, mod->name);
902924

903925
ret = klp_enable_object(obj);
904-
if (!ret)
905-
return;
906-
907-
err:
908-
pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
909-
pmod->name, mod->name, ret);
926+
if (ret)
927+
pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
928+
pmod->name, mod->name, ret);
929+
return ret;
910930
}
911931

912932
static void klp_module_notify_going(struct klp_patch *patch,
@@ -930,6 +950,7 @@ static void klp_module_notify_going(struct klp_patch *patch,
930950
static int klp_module_notify(struct notifier_block *nb, unsigned long action,
931951
void *data)
932952
{
953+
int ret;
933954
struct module *mod = data;
934955
struct klp_patch *patch;
935956
struct klp_object *obj;
@@ -949,13 +970,18 @@ static int klp_module_notify(struct notifier_block *nb, unsigned long action,
949970
mod->klp_alive = false;
950971

951972
list_for_each_entry(patch, &klp_patches, list) {
952-
for (obj = patch->objs; obj->funcs; obj++) {
973+
klp_for_each_object(patch, obj) {
953974
if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
954975
continue;
955976

956977
if (action == MODULE_STATE_COMING) {
957978
obj->mod = mod;
958-
klp_module_notify_coming(patch, obj);
979+
ret = klp_module_notify_coming(patch, obj);
980+
if (ret) {
981+
obj->mod = NULL;
982+
pr_warn("patch '%s' is in an inconsistent state!\n",
983+
patch->mod->name);
984+
}
959985
} else /* MODULE_STATE_GOING */
960986
klp_module_notify_going(patch, obj);
961987

@@ -973,7 +999,7 @@ static struct notifier_block klp_module_nb = {
973999
.priority = INT_MIN+1, /* called late but before ftrace notifier */
9741000
};
9751001

976-
static int klp_init(void)
1002+
static int __init klp_init(void)
9771003
{
9781004
int ret;
9791005

0 commit comments

Comments
 (0)