Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp5108906yba; Wed, 10 Apr 2019 11:31:12 -0700 (PDT) X-Google-Smtp-Source: APXvYqxU8sQ0FQqg/Vg10nGyBnvsp8dTqodXVh795yiIeRnfTPGq7wCcYBJh9KpEU2w4AmWVzGu9 X-Received: by 2002:a63:ed4f:: with SMTP id m15mr41297262pgk.387.1554921072856; Wed, 10 Apr 2019 11:31:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554921072; cv=none; d=google.com; s=arc-20160816; b=e0m1V6hqPUovNeFvdt4/HMzArvB91lya3gA3ZSugYEFZxqvIS/sh0cA5RUMnen9ii5 IZIIscfmGbKaLRO4sHlTE4fAQIR1ZELoMalt8rC/P79HhdV6KXq3gzDXsTtoMAAz9pND lklHl6vYtMr3eqJGe+rdwRNK7ibmbIsiqz9xOHJXzKtdZHInPZ/b7aaIKURwjcpQGzk3 XNKXpnGpTUbEP1Y+m9qHkRHzNJLZbdC0lVonfrWjYowHPlFITdZXzjJP6TS9Jtgxx6Qb mc1MIAHtHAvdl6eljbAXiSSIKp2LVTCGa3BoTy8ETrj6RlNX2b/SIx6V/jFpv2n65YIi IqHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=oetVctymltZqtvR87sfwAul/AFt4PYvDOmU248wa/2U=; b=KZCBhzErtrm5/QvX96ZYOx417mjKjv1B0jVLms2jdHm8Y49V3kNNl+2cRC8GkMKu6C 6H4BEypGCLu8uxHaWW9zT4FXSIe2crzCf31slaalkQ5NDPbJ0GeuW0gP9WzEm4aYaW0I 3BuTiZYoVEt+n8uy8X2h9NjBOGOKhvdNCQ4soKVyFG7+I+sNmClaNlY7G3WuvYDNySP1 315GBYCWG8N414WEI6DXJpqoSYXo7341nt+Fk6J+MUzYMHrKh+9HG2hvEZXYjNgvG6p0 SyuX1iOik6fLqChayE0Og/RkcsZE5iqRiTPLy6X/FziGo41YzwNj1GbyUiVhTs+bTiHh ch3w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b9si31981262pgn.457.2019.04.10.11.30.55; Wed, 10 Apr 2019 11:31:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387588AbfDJPvh (ORCPT + 99 others); Wed, 10 Apr 2019 11:51:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33167 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387523AbfDJPvP (ORCPT ); Wed, 10 Apr 2019 11:51:15 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7C9928765E; Wed, 10 Apr 2019 15:51:13 +0000 (UTC) Received: from jlaw-desktop.bos.redhat.com (dhcp-17-208.bos.redhat.com [10.18.17.208]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1C6DF1077D2D; Wed, 10 Apr 2019 15:51:12 +0000 (UTC) From: Joe Lawrence To: linux-kernel@vger.kernel.org, live-patching@vger.kernel.org, linux-kbuild@vger.kernel.org Cc: Jessica Yu , Jiri Kosina , Joao Moreira , Joe Lawrence , Josh Poimboeuf , Konstantin Khlebnikov , Masahiro Yamada , Michael Matz , Miroslav Benes , Nicolai Stange , Petr Mladek Subject: [PATCH v3 6/9] modpost: Add modinfo flag to livepatch modules Date: Wed, 10 Apr 2019 11:50:55 -0400 Message-Id: <20190410155058.9437-7-joe.lawrence@redhat.com> In-Reply-To: <20190410155058.9437-1-joe.lawrence@redhat.com> References: <20190410155058.9437-1-joe.lawrence@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 10 Apr 2019 15:51:13 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Miroslav Benes Currently, livepatch infrastructure in the kernel relies on MODULE_INFO(livepatch, "Y") statement in a livepatch module. Then the kernel module loader knows a module is indeed livepatch module and can behave accordingly. klp-convert, on the other hand relies on LIVEPATCH_* statement in the module's Makefile for exactly the same reason. Remove dependency on modinfo and generate MODULE_INFO flag automatically in modpost when LIVEPATCH_* is defined in the module's Makefile. Generate a list of all built livepatch modules based on the .livepatch file and store it in (MODVERDIR)/livepatchmods. Give this list as an argument for modpost which will use it to identify livepatch modules. As MODULE_INFO is no longer needed, remove it. Signed-off-by: Miroslav Benes Signed-off-by: Joao Moreira Signed-off-by: Joe Lawrence --- lib/livepatch/Makefile | 5 ++ lib/livepatch/test_klp_atomic_replace.c | 1 - lib/livepatch/test_klp_callbacks_demo.c | 1 - lib/livepatch/test_klp_callbacks_demo2.c | 1 - lib/livepatch/test_klp_livepatch.c | 1 - samples/livepatch/Makefile | 4 ++ samples/livepatch/livepatch-sample.c | 1 - scripts/Makefile.modpost | 8 ++- scripts/mod/modpost.c | 84 ++++++++++++++++++++++-- 9 files changed, 94 insertions(+), 12 deletions(-) diff --git a/lib/livepatch/Makefile b/lib/livepatch/Makefile index 26900ddaef82..513d200b7942 100644 --- a/lib/livepatch/Makefile +++ b/lib/livepatch/Makefile @@ -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 \ diff --git a/lib/livepatch/test_klp_atomic_replace.c b/lib/livepatch/test_klp_atomic_replace.c index 5af7093ca00c..3bf08a1b7b12 100644 --- a/lib/livepatch/test_klp_atomic_replace.c +++ b/lib/livepatch/test_klp_atomic_replace.c @@ -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 "); MODULE_DESCRIPTION("Livepatch test: atomic replace"); diff --git a/lib/livepatch/test_klp_callbacks_demo.c b/lib/livepatch/test_klp_callbacks_demo.c index 3fd8fe1cd1cc..76e2f51a6771 100644 --- a/lib/livepatch/test_klp_callbacks_demo.c +++ b/lib/livepatch/test_klp_callbacks_demo.c @@ -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 "); MODULE_DESCRIPTION("Livepatch test: livepatch demo"); diff --git a/lib/livepatch/test_klp_callbacks_demo2.c b/lib/livepatch/test_klp_callbacks_demo2.c index 5417573e80af..76db98fc3071 100644 --- a/lib/livepatch/test_klp_callbacks_demo2.c +++ b/lib/livepatch/test_klp_callbacks_demo2.c @@ -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 "); MODULE_DESCRIPTION("Livepatch test: livepatch demo2"); diff --git a/lib/livepatch/test_klp_livepatch.c b/lib/livepatch/test_klp_livepatch.c index aff08199de71..d94d0ae232db 100644 --- a/lib/livepatch/test_klp_livepatch.c +++ b/lib/livepatch/test_klp_livepatch.c @@ -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 "); MODULE_DESCRIPTION("Livepatch test: livepatch module"); diff --git a/samples/livepatch/Makefile b/samples/livepatch/Makefile index 8b9b42a258ad..5fb3280bbdc4 100644 --- a/samples/livepatch/Makefile +++ b/samples/livepatch/Makefile @@ -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 diff --git a/samples/livepatch/livepatch-sample.c b/samples/livepatch/livepatch-sample.c index 01c9cf003ca2..8900a175046b 100644 --- a/samples/livepatch/livepatch-sample.c +++ b/samples/livepatch/livepatch-sample.c @@ -79,4 +79,3 @@ static void livepatch_exit(void) module_init(livepatch_init); module_exit(livepatch_exit); MODULE_LICENSE("GPL"); -MODULE_INFO(livepatch, "Y"); diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 1e8bb7442689..9fe4c5760aca 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -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))) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 374b22c76ec5..b3ab17d9d834 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -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; -- 2.20.1