Received: by 10.223.185.116 with SMTP id b49csp1189114wrg; Fri, 23 Feb 2018 13:36:04 -0800 (PST) X-Google-Smtp-Source: AH8x225bC7uFWMhn7JslKzlmK7BD7NkRSrhtzDasLvVnuz5rQvPcE48wGVtS9c7rVRrWrhaPzJyN X-Received: by 10.98.159.85 with SMTP id g82mr3034496pfe.15.1519421764699; Fri, 23 Feb 2018 13:36:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519421764; cv=none; d=google.com; s=arc-20160816; b=lMWKbde9fCSioVNFC+ZebGACYF3DZA4AS53YyPXONoQ6KMQ+6+4YFT+oA6wss7gaz5 RmUwKQms63ZW/1Y9Ck3cXNqPlIyhk5hoMpatAlF4BuYvluU91d6kUTE3vwVxIm5NadmO yGn7GNNj4kw05ADsPLi0xw+fVzAYYWDQ26sHS4bEs1mN+XJxoCo3yQQ9zzK1f+nwN/qS Dm9cDj1cnsJwRhiO9YTsWWPVqepOibhwKrCEGXZg5//3ccwoSm7E4PEsnGoxZVrEf4zg WMBP3uAdmy5a2FgvBR/I5q/1lCY/6mZmcgkDwAlanUcXFzeBXGh/NH0Tg60WLsL3X/n/ drBQ== 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:arc-authentication-results; bh=myTg+/I+fZTKBJOB7gdJHwWVkdaIgZXyzFOTu5yForM=; b=YE8SwaiVMOLv4enLx85tlK5AuDDf4ucqTvej43iOz41Nwn+FuSfFMqK27i1jnlFrqt 93vkPqY3El2Ff/VhF9MKk7RqOB/hHvUZRCpnK/0XNfo6fuGpUQWuTEc1PX+wpvlnEy9O rF0/Zcn/gFdoPxBfNZQ96QEssgGOdqKarIb14WnPT71VY+BTnZG7TOyU+gT1jJ7W+99q J/kGMP9ywxP/LHDif1EPyYhkYg9xjujry//u5SslgkASid0MIEhCgLxNWm36DyFnnicy 5USGonn+GmtcG2BOj36RPce71/GVlrelNbywLgC12tXq3SHjeTWHAF3lwdXrLqOLL7xW lgRg== 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 l19si1972845pgc.239.2018.02.23.13.35.50; Fri, 23 Feb 2018 13:36:04 -0800 (PST) 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 S1752445AbeBWVe3 (ORCPT + 99 others); Fri, 23 Feb 2018 16:34:29 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33006 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752083AbeBWVd4 (ORCPT ); Fri, 23 Feb 2018 16:33:56 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 508D6818AAEB; Fri, 23 Feb 2018 21:33:55 +0000 (UTC) Received: from jlaw-desktop.bos.com (dhcp-17-208.bos.redhat.com [10.18.17.208]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1438010AF9EF; Fri, 23 Feb 2018 21:33:55 +0000 (UTC) From: Joe Lawrence To: live-patching@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Josh Poimboeuf , Jessica Yu , Jiri Kosina , Miroslav Benes , Petr Mladek , Jason Baron , Evgenii Shatokhin Subject: [PATCH v0 1/3] livepatch: add sample cumulative patch Date: Fri, 23 Feb 2018 16:33:48 -0500 Message-Id: <1519421630-12025-2-git-send-email-joe.lawrence@redhat.com> In-Reply-To: <1519421630-12025-1-git-send-email-joe.lawrence@redhat.com> References: <1519421630-12025-1-git-send-email-joe.lawrence@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 23 Feb 2018 21:33:55 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 23 Feb 2018 21:33:55 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'joe.lawrence@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a simple atomic replace / cumulative livepatch example. Signed-off-by: Joe Lawrence --- samples/livepatch/Makefile | 1 + samples/livepatch/livepatch-cumulative.c | 216 +++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 samples/livepatch/livepatch-cumulative.c diff --git a/samples/livepatch/Makefile b/samples/livepatch/Makefile index 2472ce39a18d..dd0e2a8af1af 100644 --- a/samples/livepatch/Makefile +++ b/samples/livepatch/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-fix2.o obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-demo.o obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-mod.o obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-busymod.o +obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-cumulative.o diff --git a/samples/livepatch/livepatch-cumulative.c b/samples/livepatch/livepatch-cumulative.c new file mode 100644 index 000000000000..ab036439e08c --- /dev/null +++ b/samples/livepatch/livepatch-cumulative.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2018 Joe Lawrence + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * livepatch-callbacks-cumulative.c - atomic replace / cumulative livepatch demo + * + * + * Purpose + * ------- + * + * Demonstration of atomic replace / cumulative livepatching. + * + * + * Usage + * ----- + * + * Step 1 - Load the sample livepatch demo + * + * insmod samples/livepatch/livepatch-sample.ko + * + * Notice that /proc/cmdline was modified by the patch. For the moment, + * /proc/meminfo remains unmodified. + * + * head /proc/cmdline /proc/meminfo + * ==> /proc/cmdline <== + * this has been live patched + * + * ==> /proc/meminfo <== + * MemTotal: 4041368 kB + * MemFree: 3323504 kB + * MemAvailable: 3619968 kB + * Buffers: 2108 kB + * Cached: 484696 kB + * SwapCached: 0 kB + * Active: 297960 kB + * Inactive: 262964 kB + * Active(anon): 74296 kB + * Inactive(anon): 8300 kB + * + * + * Step 2 - Load a second patch (on top of sample) + * + * insmod samples/livepatch/livepatch-cumulative.ko replace=0 + * + * The second livepatch adds a modification to meminfo_proc_show(), + * changing the output of /proc/meminfo. In this case, the second + * livepatch *supplements* the features of the first: + * + * head /proc/cmdline /proc/meminfo + * ==> /proc/cmdline <== + * this has been live patched + * + * ==> /proc/meminfo <== + * this has been live patched + * + * and module references and livepatch enable counts reflect both + * livepatches accordingly: + * + * lsmod | grep livepatch + * livepatch_cumulative 16384 1 + * livepatch_sample 16384 1 + * + * head /sys/kernel/livepatch/livepatch_{cumulative,sample}/enabled + * ==> /sys/kernel/livepatch/livepatch_cumulative/enabled <== + * 1 + * + * ==> /sys/kernel/livepatch/livepatch_sample/enabled <== + * 1 + * + * + * Step 3 - Remove the second patch + * + * echo 0 > /sys/kernel/livepatch/livepatch_cumulative/enabled + * rmmod livepatch-cumulative + * + * + * Step 4 - Load a second patch in atomic replace mode + * + * insmod samples/livepatch/livepatch-cumulative.ko replace=1 + * + * This time, notice that the second patch has *replaced* the features of + * the first place: + * + * head /proc/cmdline /proc/meminfo + * ==> /proc/cmdline <== + * BOOT_IMAGE=/vmlinuz-4.16.0-rc2+ root=/dev/mapper/centos-root ro console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8 + * + * ==> /proc/meminfo <== + * this has been live patched + * + * The first patch is automatically disabled: + * + * lsmod | grep livepatch + * livepatch_cumulative 16384 1 + * livepatch_sample 16384 0 + * + * head /sys/kernel/livepatch/livepatch_{cumulative,sample}/enabled + * ==> /sys/kernel/livepatch/livepatch_cumulative/enabled <== + * 1 + * + * ==> /sys/kernel/livepatch/livepatch_sample/enabled <== + * 0 + * + * + * Step 5 - Clean up + * + * Since the first patch was replaced, it is already disabled and its + * module may be removed: + * + * rmmod livepatch_sample + * echo 0 > /sys/kernel/livepatch/livepatch_cumulative/enabled + * rmmod livepatch-cumulative + */ + + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Joe Lawrence "); +MODULE_DESCRIPTION("Livepatch atomic replace demo"); + +static int replace; +module_param(replace, int, 0644); +MODULE_PARM_DESC(replace, "replace (default=0)"); + +#if 0 +/* Cumulative patches don't need to re-introduce original functions in + * order to "revert" them from previous livepatches. + * + * - If this module is loaded in atomic replace mode, the ftrace + * handlers (and therefore previous livepatches) will be removed from + * cmdline_proc_show(). The latest cumulative patch contains all + * modified code. + * + * - Otherwise, by default livepatches supplement each other, and we'd + * need to provide a fresh copy of cmdline_proc_show() to revert its + * behavior. + */ +static int livepatch_cmdline_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%s\n", saved_command_line); + return 0; +} +#endif + +#include +static int livepatch_meminfo_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%s\n", "this has been live patched"); + return 0; +} + +static struct klp_func funcs[] = { + { + .old_name = "meminfo_proc_show", + .new_func = livepatch_meminfo_proc_show, + }, { } +}; + +static struct klp_object objs[] = { + { + /* name being NULL means vmlinux */ + .funcs = funcs, + }, { } +}; + +static struct klp_patch patch = { + .mod = THIS_MODULE, + .objs = objs, + /* set .replace in the init function below for demo purposes */ +}; + +static int livepatch_init(void) +{ + int ret; + + patch.replace = replace; + + ret = klp_register_patch(&patch); + if (ret) + return ret; + ret = klp_enable_patch(&patch); + if (ret) { + WARN_ON(klp_unregister_patch(&patch)); + return ret; + } + return 0; +} + +static void livepatch_exit(void) +{ + WARN_ON(klp_unregister_patch(&patch)); +} + +module_init(livepatch_init); +module_exit(livepatch_exit); +MODULE_LICENSE("GPL"); +MODULE_INFO(livepatch, "Y"); -- 1.8.3.1