@@ -2,6 +2,11 @@
#
# Makefile for livepatch test code.
+LIVEPATCH_test_klp_atomic_replace := y
+LIVEPATCH_test_klp_callbacks_demo := y
+LIVEPATCH_test_klp_callbacks_demo2 := y
+LIVEPATCH_test_klp_livepatch := y
+
obj-$(CONFIG_TEST_LIVEPATCH) += test_klp_atomic_replace.o \
test_klp_callbacks_demo.o \
test_klp_callbacks_demo2.o \
@@ -52,6 +52,5 @@ static void test_klp_atomic_replace_exit(void)
module_init(test_klp_atomic_replace_init);
module_exit(test_klp_atomic_replace_exit);
MODULE_LICENSE("GPL");
-MODULE_INFO(livepatch, "Y");
MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
MODULE_DESCRIPTION("Livepatch test: atomic replace");
@@ -116,6 +116,5 @@ static void test_klp_callbacks_demo_exit(void)
module_init(test_klp_callbacks_demo_init);
module_exit(test_klp_callbacks_demo_exit);
MODULE_LICENSE("GPL");
-MODULE_INFO(livepatch, "Y");
MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
MODULE_DESCRIPTION("Livepatch test: livepatch demo");
@@ -88,6 +88,5 @@ static void test_klp_callbacks_demo2_exit(void)
module_init(test_klp_callbacks_demo2_init);
module_exit(test_klp_callbacks_demo2_exit);
MODULE_LICENSE("GPL");
-MODULE_INFO(livepatch, "Y");
MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
MODULE_DESCRIPTION("Livepatch test: livepatch demo2");
@@ -46,6 +46,5 @@ static void test_klp_livepatch_exit(void)
module_init(test_klp_livepatch_init);
module_exit(test_klp_livepatch_exit);
MODULE_LICENSE("GPL");
-MODULE_INFO(livepatch, "Y");
MODULE_AUTHOR("Seth Jennings <sjenning@redhat.com>");
MODULE_DESCRIPTION("Livepatch test: livepatch module");
@@ -1,4 +1,8 @@
LIVEPATCH_livepatch-sample := y
+LIVEPATCH_livepatch-shadow-fix1 := y
+LIVEPATCH_livepatch-shadow-fix2 := y
+LIVEPATCH_livepatch-callbacks-demo := y
+
obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-sample.o
obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-mod.o
obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-fix1.o
@@ -79,4 +79,3 @@ static void livepatch_exit(void)
module_init(livepatch_init);
module_exit(livepatch_exit);
MODULE_LICENSE("GPL");
-MODULE_INFO(livepatch, "Y");
@@ -65,6 +65,11 @@ MODLISTCMD := find $(MODVERDIR) -name '*.mod' | xargs -r grep -h '\.ko$$' | sort
__modules := $(shell $(MODLISTCMD))
modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
+# find all .livepatch files listed in $(MODVERDIR)/
+ifdef CONFIG_LIVEPATCH
+$(shell find $(MODVERDIR) -name '*.livepatch' | xargs -r -I{} basename {} .livepatch > $(MODVERDIR)/livepatchmods)
+endif
+
# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
@@ -78,7 +83,8 @@ modpost = scripts/mod/modpost \
$(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
$(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
$(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
- $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
+ $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
+ $(if $(CONFIG_LIVEPATCH),-l $(MODVERDIR)/livepatchmods)
MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
@@ -1974,10 +1974,6 @@ static void read_symbols(const char *modname)
license = get_next_modinfo(&info, "license", license);
}
- /* Livepatch modules have unresolved symbols resolved by klp-convert */
- if (get_modinfo(&info, "livepatch"))
- mod->livepatch = 1;
-
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
symname = remove_dot(info.strtab + sym->st_name);
@@ -2416,6 +2412,76 @@ static void write_dump(const char *fname)
free(buf.p);
}
+struct livepatch_mod_list {
+ struct livepatch_mod_list *next;
+ char *livepatch_mod;
+};
+
+static struct livepatch_mod_list *load_livepatch_mods(const char *fname)
+{
+ struct livepatch_mod_list *list_iter, *list_start = NULL;
+ unsigned long size, pos = 0;
+ void *file = grab_file(fname, &size);
+ char *line;
+
+ if (!file)
+ return NULL;
+
+ while ((line = get_next_line(&pos, file, size))) {
+ list_iter = NOFAIL(malloc(sizeof(*list_iter)));
+ list_iter->next = list_start;
+ list_iter->livepatch_mod = NOFAIL(strdup(line));
+ list_start = list_iter;
+ }
+ release_file(file, size);
+
+ return list_start;
+}
+
+static void free_livepatch_mods(struct livepatch_mod_list *list_start)
+{
+ struct livepatch_mod_list *list_iter;
+
+ while (list_start) {
+ list_iter = list_start->next;
+ free(list_start->livepatch_mod);
+ free(list_start);
+ list_start = list_iter;
+ }
+}
+
+static int is_livepatch_mod(const char *modname,
+ struct livepatch_mod_list *list)
+{
+ const char *myname;
+
+ if (!list)
+ return 0;
+
+ myname = strrchr(modname, '/');
+ if (myname)
+ myname++;
+ else
+ myname = modname;
+
+ while (list) {
+ if (!strcmp(myname, list->livepatch_mod))
+ return 1;
+ list = list->next;
+ }
+ return 0;
+}
+
+static void add_livepatch_flag(struct buffer *b, struct module *mod,
+ struct livepatch_mod_list *list)
+{
+ if (is_livepatch_mod(mod->name, list)) {
+ buf_printf(b, "\nMODULE_INFO(livepatch, \"Y\");\n");
+ mod->livepatch = 1;
+ }
+}
+
+
struct ext_sym_list {
struct ext_sym_list *next;
const char *file;
@@ -2431,8 +2497,9 @@ int main(int argc, char **argv)
int err;
struct ext_sym_list *extsym_iter;
struct ext_sym_list *extsym_start = NULL;
+ struct livepatch_mod_list *livepatch_mods = NULL;
- while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awE")) != -1) {
+ while ((opt = getopt(argc, argv, "i:I:e:l:mnsT:o:awE")) != -1) {
switch (opt) {
case 'i':
kernel_read = optarg;
@@ -2449,6 +2516,9 @@ int main(int argc, char **argv)
extsym_iter->file = optarg;
extsym_start = extsym_iter;
break;
+ case 'l':
+ livepatch_mods = load_livepatch_mods(optarg);
+ break;
case 'm':
modversions = 1;
break;
@@ -2506,15 +2576,16 @@ int main(int argc, char **argv)
buf.pos = 0;
err |= check_modname_len(mod);
- err |= check_exports(mod);
add_header(&buf, mod);
add_intree_flag(&buf, !external_module);
add_retpoline(&buf);
add_staging_flag(&buf, mod->name);
+ add_livepatch_flag(&buf, mod, livepatch_mods);
err |= add_versions(&buf, mod);
add_depends(&buf, mod);
add_moddevtable(&buf, mod);
add_srcversion(&buf, mod);
+ err |= check_exports(mod);
sprintf(fname, "%s.mod.c", mod->name);
write_if_changed(&buf, fname);
@@ -2524,6 +2595,7 @@ int main(int argc, char **argv)
if (sec_mismatch_count && sec_mismatch_fatal)
fatal("modpost: Section mismatches detected.\n"
"Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
+ free_livepatch_mods(livepatch_mods);
free(buf.p);
return err;