Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp4465132ybi; Tue, 11 Jun 2019 07:07:45 -0700 (PDT) X-Google-Smtp-Source: APXvYqxptsmfURm3+ym0bFdZyPZlhEB1dWFePM61m8vOhwhROayBIfEl9olIti7N41pk3Hamyyba X-Received: by 2002:a17:902:a60d:: with SMTP id u13mr7468483plq.144.1560262065859; Tue, 11 Jun 2019 07:07:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560262065; cv=none; d=google.com; s=arc-20160816; b=Tp3EFB+V1aQObq/6aco7bLS6oL+5RCS58e9ZZAsUTjS1tPyiVsW2uZR7iTXuJcvtlN emBQMFn6PNSyB3Q3fI2d/oN8NG7N6ZucgVXMUIH6rgzKDuLCHUgL6kDgt/ReUHBt1n5W SLDxrjECeEEavHB5J6yYmhdtrraQ7iBdHa+F8onsJM7spgu/JIqwqGy28Bze+k2nev3R MmEEoarh6zCSZSnjG6CCTk7uGWXctSlruebXZlZP8QR99nYfCsQbkzdOSbBy3lFxWfJi oqGaP+7KDf3anS3GRmd84TD5sG+pAB2/FV4REs0uJ/MmBW1FoT+IQTSCMFabwBsUotEZ U+2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=Ei+SBA7ivvkjl5Acm2XdU+hbdAuhus1yl7DSZRHuG+0=; b=EgkiZuYbOQIalkgrLW9Alt+IvvnebEjljzQ3hu9WR6pZ1lkF+AK7v2Y3xAcv5kPmXI JA0OoOhYD9EpHZ5KLLo1Zj3YMrVi5DiMzA2zZ1UGiY2a1EooiVxz6uBz0zDiV0bkbCWf 54N4Cupt385DyqXwK2lK2z3EKmgXsvUHAObZXb3Em2pE1LBtq2Xwk1G6OzFDIkknRnj4 SsJTyaysk9TqVBT2SI9evwEo9ZWsbuEiKcsfxfPldHhSTTSsNdloKc36prMabgSXrlqE FKNG+QpHvgF++UtIbs0kudLHBFnmnr/rVbNDCz+NHbpSNS1TRKLuN+ZObK6W4iQESBRu k6hA== 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u17si5512506pfc.210.2019.06.11.07.07.29; Tue, 11 Jun 2019 07:07:45 -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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391522AbfFKN5B (ORCPT + 99 others); Tue, 11 Jun 2019 09:57:01 -0400 Received: from mx2.suse.de ([195.135.220.15]:40044 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2391441AbfFKN46 (ORCPT ); Tue, 11 Jun 2019 09:56:58 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 359D3AEA1; Tue, 11 Jun 2019 13:56:57 +0000 (UTC) From: Petr Mladek To: Jiri Kosina , Josh Poimboeuf , Miroslav Benes Cc: Joe Lawrence , Kamalesh Babulal , Nicolai Stange , live-patching@vger.kernel.org, linux-kernel@vger.kernel.org, Petr Mladek Subject: [RFC 5/5] livepatch: Selftests of the API for tracking system state changes Date: Tue, 11 Jun 2019 15:56:27 +0200 Message-Id: <20190611135627.15556-6-pmladek@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190611135627.15556-1-pmladek@suse.com> References: <20190611135627.15556-1-pmladek@suse.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Four selftests for the new API. Signed-off-by: Petr Mladek --- lib/livepatch/Makefile | 5 +- lib/livepatch/test_klp_state.c | 161 ++++++++++++++++++++ lib/livepatch/test_klp_state2.c | 190 ++++++++++++++++++++++++ lib/livepatch/test_klp_state3.c | 5 + tools/testing/selftests/livepatch/Makefile | 3 +- tools/testing/selftests/livepatch/test-state.sh | 180 ++++++++++++++++++++++ 6 files changed, 542 insertions(+), 2 deletions(-) create mode 100644 lib/livepatch/test_klp_state.c create mode 100644 lib/livepatch/test_klp_state2.c create mode 100644 lib/livepatch/test_klp_state3.c create mode 100755 tools/testing/selftests/livepatch/test-state.sh diff --git a/lib/livepatch/Makefile b/lib/livepatch/Makefile index 26900ddaef82..295b94bff370 100644 --- a/lib/livepatch/Makefile +++ b/lib/livepatch/Makefile @@ -8,7 +8,10 @@ obj-$(CONFIG_TEST_LIVEPATCH) += test_klp_atomic_replace.o \ test_klp_callbacks_busy.o \ test_klp_callbacks_mod.o \ test_klp_livepatch.o \ - test_klp_shadow_vars.o + test_klp_shadow_vars.o \ + test_klp_state.o \ + test_klp_state2.o \ + test_klp_state3.o # Target modules to be livepatched require CC_FLAGS_FTRACE CFLAGS_test_klp_callbacks_busy.o += $(CC_FLAGS_FTRACE) diff --git a/lib/livepatch/test_klp_state.c b/lib/livepatch/test_klp_state.c new file mode 100644 index 000000000000..c43dc2f2e01d --- /dev/null +++ b/lib/livepatch/test_klp_state.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019 SUSE + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include + +#define CONSOLE_LOGLEVEL_STATE 1 +/* Version 1 does not support migration. */ +#define CONSOLE_LOGLEVEL_STATE_VERSION 1 + +static const char *const module_state[] = { + [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", + [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", + [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", + [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", +}; + +static void callback_info(const char *callback, struct klp_object *obj) +{ + if (obj->mod) + pr_info("%s: %s -> %s\n", callback, obj->mod->name, + module_state[obj->mod->state]); + else + pr_info("%s: vmlinux\n", callback); +} + +static struct klp_patch patch; + +static int allocate_loglevel_state(void) +{ + struct klp_state *loglevel_state; + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return -EINVAL; + + loglevel_state->data = kzalloc(sizeof(console_loglevel), GFP_KERNEL); + if (!loglevel_state->data) + return -ENOMEM; + + pr_info("%s: allocating space to store console_loglevel\n", + __func__); + return 0; +} + +static void fix_console_loglevel(void) +{ + struct klp_state *loglevel_state; + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return; + + pr_info("%s: fixing console_loglevel\n", __func__); + *(int *)loglevel_state->data = console_loglevel; + console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH; +} + +static void restore_console_loglevel(void) +{ + struct klp_state *loglevel_state; + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return; + + pr_info("%s: restoring console_loglevel\n", __func__); + console_loglevel = *(int *)loglevel_state->data; +} + +static void free_loglevel_state(void) +{ + struct klp_state *loglevel_state; + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return; + + pr_info("%s: freeing space for the stored console_loglevel\n", + __func__); + kfree(loglevel_state->data); +} + +/* Executed on object patching (ie, patch enablement) */ +static int pre_patch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + return allocate_loglevel_state(); +} + +/* Executed on object unpatching (ie, patch disablement) */ +static void post_patch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + fix_console_loglevel(); +} + +/* Executed on object unpatching (ie, patch disablement) */ +static void pre_unpatch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + restore_console_loglevel(); +} + +/* Executed on object unpatching (ie, patch disablement) */ +static void post_unpatch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + free_loglevel_state(); +} + +static struct klp_func no_funcs[] = { + {} +}; + +static struct klp_object objs[] = { + { + .name = NULL, /* vmlinux */ + .funcs = no_funcs, + .callbacks = { + .pre_patch = pre_patch_callback, + .post_patch = post_patch_callback, + .pre_unpatch = pre_unpatch_callback, + .post_unpatch = post_unpatch_callback, + }, + }, { } +}; + +static struct klp_state states[] = { + { + .id = CONSOLE_LOGLEVEL_STATE, + .version = 1, + }, { } +}; + +static struct klp_patch patch = { + .mod = THIS_MODULE, + .objs = objs, + .states = states, + .replace = true, +}; + +static int test_klp_callbacks_demo_init(void) +{ + return klp_enable_patch(&patch); +} + +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_state2.c b/lib/livepatch/test_klp_state2.c new file mode 100644 index 000000000000..2b4968fad60e --- /dev/null +++ b/lib/livepatch/test_klp_state2.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019 SUSE + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include + +#define CONSOLE_LOGLEVEL_STATE 1 +/* Version 2 supports migration. */ +#define CONSOLE_LOGLEVEL_STATE_VERSION 2 + +static const char *const module_state[] = { + [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", + [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", + [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", + [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", +}; + +static void callback_info(const char *callback, struct klp_object *obj) +{ + if (obj->mod) + pr_info("%s: %s -> %s\n", callback, obj->mod->name, + module_state[obj->mod->state]); + else + pr_info("%s: vmlinux\n", callback); +} + +static struct klp_patch patch; + +static int allocate_loglevel_state(void) +{ + struct klp_state *loglevel_state, *prev_loglevel_state; + + prev_loglevel_state = klp_get_prev_state(CONSOLE_LOGLEVEL_STATE); + if (prev_loglevel_state) { + pr_info("%s: space to store console_loglevel already allocated\n", + __func__); + return 0; + } + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return -EINVAL; + + loglevel_state->data = kzalloc(sizeof(console_loglevel), GFP_KERNEL); + if (!loglevel_state->data) + return -ENOMEM; + + pr_info("%s: allocating space to store console_loglevel\n", + __func__); + return 0; +} + +static void fix_console_loglevel(void) +{ + struct klp_state *loglevel_state, *prev_loglevel_state; + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return; + + prev_loglevel_state = klp_get_prev_state(CONSOLE_LOGLEVEL_STATE); + if (prev_loglevel_state) { + pr_info("%s: taking over the console_loglevel change\n", + __func__); + loglevel_state->data = prev_loglevel_state->data; + return; + } + + pr_info("%s: fixing console_loglevel\n", __func__); + *(int *)loglevel_state->data = console_loglevel; + console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH; +} + +static void restore_console_loglevel(void) +{ + struct klp_state *loglevel_state, *prev_loglevel_state; + + prev_loglevel_state = klp_get_prev_state(CONSOLE_LOGLEVEL_STATE); + if (prev_loglevel_state) { + pr_info("%s: passing the console_loglevel change back to the old livepatch\n", + __func__); + return; + } + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return; + + pr_info("%s: restoring console_loglevel\n", __func__); + console_loglevel = *(int *)loglevel_state->data; +} + +static void free_loglevel_state(void) +{ + struct klp_state *loglevel_state, *prev_loglevel_state; + + prev_loglevel_state = klp_get_prev_state(CONSOLE_LOGLEVEL_STATE); + if (prev_loglevel_state) { + pr_info("%s: keeping space to store console_loglevel\n", + __func__); + return; + } + + loglevel_state = klp_get_state(&patch, CONSOLE_LOGLEVEL_STATE); + if (!loglevel_state) + return; + + pr_info("%s: freeing space for the stored console_loglevel\n", + __func__); + kfree(loglevel_state->data); +} + +/* Executed on object patching (ie, patch enablement) */ +static int pre_patch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + return allocate_loglevel_state(); +} + +/* Executed on object unpatching (ie, patch disablement) */ +static void post_patch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + fix_console_loglevel(); +} + +/* Executed on object unpatching (ie, patch disablement) */ +static void pre_unpatch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + restore_console_loglevel(); +} + +/* Executed on object unpatching (ie, patch disablement) */ +static void post_unpatch_callback(struct klp_object *obj) +{ + callback_info(__func__, obj); + free_loglevel_state(); +} + +static struct klp_func no_funcs[] = { + {} +}; + +static struct klp_object objs[] = { + { + .name = NULL, /* vmlinux */ + .funcs = no_funcs, + .callbacks = { + .pre_patch = pre_patch_callback, + .post_patch = post_patch_callback, + .pre_unpatch = pre_unpatch_callback, + .post_unpatch = post_unpatch_callback, + }, + }, { } +}; + +static struct klp_state states[] = { + { + .id = CONSOLE_LOGLEVEL_STATE, + .version = CONSOLE_LOGLEVEL_STATE_VERSION, + }, { } +}; + +static struct klp_patch patch = { + .mod = THIS_MODULE, + .objs = objs, + .states = states, + .replace = true, +}; + +static int test_klp_callbacks_demo_init(void) +{ + return klp_enable_patch(&patch); +} + +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_state3.c b/lib/livepatch/test_klp_state3.c new file mode 100644 index 000000000000..9226579d10c5 --- /dev/null +++ b/lib/livepatch/test_klp_state3.c @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019 SUSE + +/* The console loglevel fix is the same in the next cumulative patch. */ +#include "test_klp_state2.c" diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile index fd405402c3ff..1cf40a9e7185 100644 --- a/tools/testing/selftests/livepatch/Makefile +++ b/tools/testing/selftests/livepatch/Makefile @@ -4,6 +4,7 @@ TEST_PROGS_EXTENDED := functions.sh TEST_PROGS := \ test-livepatch.sh \ test-callbacks.sh \ - test-shadow-vars.sh + test-shadow-vars.sh \ + test-state.sh include ../lib.mk diff --git a/tools/testing/selftests/livepatch/test-state.sh b/tools/testing/selftests/livepatch/test-state.sh new file mode 100755 index 000000000000..1139c664c11c --- /dev/null +++ b/tools/testing/selftests/livepatch/test-state.sh @@ -0,0 +1,180 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018 Joe Lawrence + +. $(dirname $0)/functions.sh + +MOD_LIVEPATCH=test_klp_state +MOD_LIVEPATCH2=test_klp_state2 +MOD_LIVEPATCH3=test_klp_state3 + +set_dynamic_debug + + +# TEST: Loading and removing a module that modifies the system state + +echo -n "TEST: system state modification ... " +dmesg -C + +load_lp $MOD_LIVEPATCH +disable_lp $MOD_LIVEPATCH +unload_lp $MOD_LIVEPATCH + +check_result "% modprobe test_klp_state +livepatch: enabling patch 'test_klp_state' +livepatch: 'test_klp_state': initializing patching transition +test_klp_state: pre_patch_callback: vmlinux +test_klp_state: allocate_loglevel_state: allocating space to store console_loglevel +livepatch: 'test_klp_state': starting patching transition +livepatch: 'test_klp_state': completing patching transition +test_klp_state: post_patch_callback: vmlinux +test_klp_state: fix_console_loglevel: fixing console_loglevel +livepatch: 'test_klp_state': patching complete +% echo 0 > /sys/kernel/livepatch/test_klp_state/enabled +livepatch: 'test_klp_state': initializing unpatching transition +test_klp_state: pre_unpatch_callback: vmlinux +test_klp_state: restore_console_loglevel: restoring console_loglevel +livepatch: 'test_klp_state': starting unpatching transition +livepatch: 'test_klp_state': completing unpatching transition +test_klp_state: post_unpatch_callback: vmlinux +test_klp_state: free_loglevel_state: freeing space for the stored console_loglevel +livepatch: 'test_klp_state': unpatching complete +% rmmod test_klp_state" + + +# TEST: Take over system state change by a cumulative patch + +echo -n "TEST: taking over system state modification ... " +dmesg -C + +load_lp $MOD_LIVEPATCH +load_lp $MOD_LIVEPATCH2 +unload_lp $MOD_LIVEPATCH +disable_lp $MOD_LIVEPATCH2 +unload_lp $MOD_LIVEPATCH2 + +check_result "% modprobe test_klp_state +livepatch: enabling patch 'test_klp_state' +livepatch: 'test_klp_state': initializing patching transition +test_klp_state: pre_patch_callback: vmlinux +test_klp_state: allocate_loglevel_state: allocating space to store console_loglevel +livepatch: 'test_klp_state': starting patching transition +livepatch: 'test_klp_state': completing patching transition +test_klp_state: post_patch_callback: vmlinux +test_klp_state: fix_console_loglevel: fixing console_loglevel +livepatch: 'test_klp_state': patching complete +% modprobe test_klp_state2 +livepatch: enabling patch 'test_klp_state2' +livepatch: 'test_klp_state2': initializing patching transition +test_klp_state2: pre_patch_callback: vmlinux +test_klp_state2: allocate_loglevel_state: space to store console_loglevel already allocated +livepatch: 'test_klp_state2': starting patching transition +livepatch: 'test_klp_state2': completing patching transition +test_klp_state2: post_patch_callback: vmlinux +test_klp_state2: fix_console_loglevel: taking over the console_loglevel change +livepatch: 'test_klp_state2': patching complete +% rmmod test_klp_state +% echo 0 > /sys/kernel/livepatch/test_klp_state2/enabled +livepatch: 'test_klp_state2': initializing unpatching transition +test_klp_state2: pre_unpatch_callback: vmlinux +test_klp_state2: restore_console_loglevel: restoring console_loglevel +livepatch: 'test_klp_state2': starting unpatching transition +livepatch: 'test_klp_state2': completing unpatching transition +test_klp_state2: post_unpatch_callback: vmlinux +test_klp_state2: free_loglevel_state: freeing space for the stored console_loglevel +livepatch: 'test_klp_state2': unpatching complete +% rmmod test_klp_state2" + + +# TEST: Take over system state change by a cumulative patch + +echo -n "TEST: compatible cumulative livepatches ... " +dmesg -C + +load_lp $MOD_LIVEPATCH2 +load_lp $MOD_LIVEPATCH3 +unload_lp $MOD_LIVEPATCH2 +load_lp $MOD_LIVEPATCH2 +disable_lp $MOD_LIVEPATCH2 +unload_lp $MOD_LIVEPATCH2 +unload_lp $MOD_LIVEPATCH3 + +check_result "% modprobe test_klp_state2 +livepatch: enabling patch 'test_klp_state2' +livepatch: 'test_klp_state2': initializing patching transition +test_klp_state2: pre_patch_callback: vmlinux +test_klp_state2: allocate_loglevel_state: allocating space to store console_loglevel +livepatch: 'test_klp_state2': starting patching transition +livepatch: 'test_klp_state2': completing patching transition +test_klp_state2: post_patch_callback: vmlinux +test_klp_state2: fix_console_loglevel: fixing console_loglevel +livepatch: 'test_klp_state2': patching complete +% modprobe test_klp_state3 +livepatch: enabling patch 'test_klp_state3' +livepatch: 'test_klp_state3': initializing patching transition +test_klp_state3: pre_patch_callback: vmlinux +test_klp_state3: allocate_loglevel_state: space to store console_loglevel already allocated +livepatch: 'test_klp_state3': starting patching transition +livepatch: 'test_klp_state3': completing patching transition +test_klp_state3: post_patch_callback: vmlinux +test_klp_state3: fix_console_loglevel: taking over the console_loglevel change +livepatch: 'test_klp_state3': patching complete +% rmmod test_klp_state2 +% modprobe test_klp_state2 +livepatch: enabling patch 'test_klp_state2' +livepatch: 'test_klp_state2': initializing patching transition +test_klp_state2: pre_patch_callback: vmlinux +test_klp_state2: allocate_loglevel_state: space to store console_loglevel already allocated +livepatch: 'test_klp_state2': starting patching transition +livepatch: 'test_klp_state2': completing patching transition +test_klp_state2: post_patch_callback: vmlinux +test_klp_state2: fix_console_loglevel: taking over the console_loglevel change +livepatch: 'test_klp_state2': patching complete +% echo 0 > /sys/kernel/livepatch/test_klp_state2/enabled +livepatch: 'test_klp_state2': initializing unpatching transition +test_klp_state2: pre_unpatch_callback: vmlinux +test_klp_state2: restore_console_loglevel: restoring console_loglevel +livepatch: 'test_klp_state2': starting unpatching transition +livepatch: 'test_klp_state2': completing unpatching transition +test_klp_state2: post_unpatch_callback: vmlinux +test_klp_state2: free_loglevel_state: freeing space for the stored console_loglevel +livepatch: 'test_klp_state2': unpatching complete +% rmmod test_klp_state2 +% rmmod test_klp_state3" + + +# TEST: Failure caused by incompatible cumulative livepatches + +echo -n "TEST: incompatible cumulative livepatches ... " +dmesg -C + +load_lp $MOD_LIVEPATCH2 +load_failing_mod $MOD_LIVEPATCH +disable_lp $MOD_LIVEPATCH2 +unload_lp $MOD_LIVEPATCH2 + +check_result "% modprobe test_klp_state2 +livepatch: enabling patch 'test_klp_state2' +livepatch: 'test_klp_state2': initializing patching transition +test_klp_state2: pre_patch_callback: vmlinux +test_klp_state2: allocate_loglevel_state: allocating space to store console_loglevel +livepatch: 'test_klp_state2': starting patching transition +livepatch: 'test_klp_state2': completing patching transition +test_klp_state2: post_patch_callback: vmlinux +test_klp_state2: fix_console_loglevel: fixing console_loglevel +livepatch: 'test_klp_state2': patching complete +% modprobe test_klp_state +livepatch: Livepatch patch (test_klp_state) is not compatible with the already installed livepatches. +modprobe: ERROR: could not insert 'test_klp_state': Invalid argument +% echo 0 > /sys/kernel/livepatch/test_klp_state2/enabled +livepatch: 'test_klp_state2': initializing unpatching transition +test_klp_state2: pre_unpatch_callback: vmlinux +test_klp_state2: restore_console_loglevel: restoring console_loglevel +livepatch: 'test_klp_state2': starting unpatching transition +livepatch: 'test_klp_state2': completing unpatching transition +test_klp_state2: post_unpatch_callback: vmlinux +test_klp_state2: free_loglevel_state: freeing space for the stored console_loglevel +livepatch: 'test_klp_state2': unpatching complete +% rmmod test_klp_state2" + +exit 0 -- 2.16.4