test/integration: add upstream 5.18.0 patches

Add patches rebased on top of upstream 5.18.0.

Integration tests for these can be ran as this:

  $ make PATCH_DIR="linux-5.18.0" KPATCH_BUILD_OPTS="--non-replace --sourcedir /path/to/src/linux-5.18.0" integration-slow

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
This commit is contained in:
Joe Lawrence 2022-06-15 16:39:02 -04:00
parent 7fdbb2561c
commit 30f09bfaa2
16 changed files with 536 additions and 0 deletions

View File

@ -0,0 +1,3 @@
#!/bin/bash
grep "kpatch: 5" /proc/meminfo

View File

@ -0,0 +1,20 @@
diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
--- src.orig/fs/proc/meminfo.c 2022-06-15 10:04:10.540915757 -0400
+++ src/fs/proc/meminfo.c 2022-06-15 10:04:12.104923244 -0400
@@ -29,6 +29,8 @@ static void show_val_kb(struct seq_file
seq_write(m, " kB\n", 4);
}
+static int foo = 5;
+
static int meminfo_proc_show(struct seq_file *m, void *v)
{
struct sysinfo i;
@@ -145,6 +147,7 @@ static int meminfo_proc_show(struct seq_
show_val_kb(m, "CmaFree: ",
global_zone_page_state(NR_FREE_CMA_PAGES));
#endif
+ seq_printf(m, "kpatch: %d\n", foo);
hugetlb_report_meminfo(m);

View File

@ -0,0 +1,22 @@
diff -Nupr src.orig/net/ipv6/netfilter.c src/net/ipv6/netfilter.c
--- src.orig/net/ipv6/netfilter.c 2022-06-15 10:04:10.984917882 -0400
+++ src/net/ipv6/netfilter.c 2022-06-15 10:04:25.898989277 -0400
@@ -97,6 +97,8 @@ static int nf_ip6_reroute(struct sk_buff
return 0;
}
+#include "kpatch-macros.h"
+
int __nf_ip6_route(struct net *net, struct dst_entry **dst,
struct flowi *fl, bool strict)
{
@@ -110,6 +112,9 @@ int __nf_ip6_route(struct net *net, stru
struct dst_entry *result;
int err;
+ if (!jiffies)
+ printk("kpatch nf_ip6_route foo\n");
+
result = ip6_route_output(net, sk, &fl->u.ip6);
err = result->error;
if (err)

View File

@ -0,0 +1,155 @@
diff -Nupr src.orig/drivers/input/joydev.c src/drivers/input/joydev.c
--- src.orig/drivers/input/joydev.c 2022-06-15 10:04:09.640911448 -0400
+++ src/drivers/input/joydev.c 2022-06-15 10:04:37.199043370 -0400
@@ -1096,3 +1096,47 @@ static void __exit joydev_exit(void)
module_init(joydev_init);
module_exit(joydev_exit);
+
+#include <linux/module.h>
+#include "kpatch-macros.h"
+
+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, patch_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 int pre_patch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+ return 0; /* return -ENODEV; */
+}
+KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
+
+static void post_patch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
+
+static void pre_unpatch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
+
+static void post_unpatch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
diff -Nupr src.orig/drivers/input/misc/pcspkr.c src/drivers/input/misc/pcspkr.c
--- src.orig/drivers/input/misc/pcspkr.c 2022-06-15 10:04:09.649911492 -0400
+++ src/drivers/input/misc/pcspkr.c 2022-06-15 10:04:37.200043375 -0400
@@ -134,3 +134,46 @@ static struct platform_driver pcspkr_pla
};
module_platform_driver(pcspkr_platform_driver);
+#include <linux/module.h>
+#include "kpatch-macros.h"
+
+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, patch_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 int pre_patch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+ return 0;
+}
+KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
+
+static void post_patch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
+
+static void pre_unpatch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
+
+static void post_unpatch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
diff -Nupr src.orig/fs/aio.c src/fs/aio.c
--- src.orig/fs/aio.c 2022-06-15 10:04:10.537915743 -0400
+++ src/fs/aio.c 2022-06-15 10:04:37.201043380 -0400
@@ -50,6 +50,50 @@
#define KIOCB_KEY 0
+#include <linux/module.h>
+#include "kpatch-macros.h"
+
+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, patch_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 int pre_patch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+ return 0;
+}
+KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
+
+static void post_patch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
+
+static void pre_unpatch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
+
+static void post_unpatch_callback(patch_object *obj)
+{
+ callback_info(__func__, obj);
+}
+KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
+
#define AIO_RING_MAGIC 0xa10a10a1
#define AIO_RING_COMPAT_FEATURES 1
#define AIO_RING_INCOMPAT_FEATURES 0

View File

@ -0,0 +1,13 @@
#!/bin/bash
set -o errexit
sudo modprobe nfsd
sleep 5
grep -q kpatch /proc/fs/nfs/exports
# TODO: This will trigger a printk on newer kernels which have the .klp.arch
# removal. Don't actually do the grep until running on a newer kernel.
echo "file fs/nfsd/export.c +p" > /sys/kernel/debug/dynamic_debug/control
cat /proc/fs/nfs/exports > /dev/null
# dmesg | grep -q "kpatch: pr_debug"

View File

@ -0,0 +1,79 @@
kpatch module integration test
This tests several things related to the patching of modules:
- 'kpatch_string' tests the referencing of a symbol which is outside the
.o, but inside the patch module.
- alternatives patching (.altinstructions)
- paravirt patching (.parainstructions)
- jump labels (5.8+ kernels only) -- including dynamic printk
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c
--- src.orig/fs/nfsd/export.c 2022-06-15 10:04:10.582915958 -0400
+++ src/fs/nfsd/export.c 2022-06-15 10:04:48.309096555 -0400
@@ -1294,6 +1294,10 @@ static void exp_flags(struct seq_file *m
}
}
+#include <linux/version.h>
+extern char *kpatch_string(void);
+
+__attribute__((optimize("-fno-optimize-sibling-calls")))
static int e_show(struct seq_file *m, void *p)
{
struct cache_head *cp = p;
@@ -1301,12 +1305,36 @@ static int e_show(struct seq_file *m, vo
struct cache_detail *cd = m->private;
bool export_stats = is_export_stats_file(m);
+#ifdef CONFIG_X86_64
+ alternative("ud2", "call single_task_running", X86_FEATURE_ALWAYS);
+ alternative("call single_task_running", "ud2", X86_FEATURE_IA64);
+
+ __flush_tlb_local(); /* paravirt call */
+#endif
+
+ pr_debug("kpatch: pr_debug() test\n");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
+{
+ static DEFINE_STATIC_KEY_TRUE(kpatch_key);
+
+ if (static_branch_unlikely(&memcg_kmem_enabled_key))
+ printk("kpatch: memcg_kmem_enabled_key\n");
+
+ BUG_ON(!static_branch_likely(&kpatch_key));
+ static_branch_disable(&kpatch_key);
+ BUG_ON(static_branch_likely(&kpatch_key));
+ static_branch_enable(&kpatch_key);
+}
+#endif
+
if (p == SEQ_START_TOKEN) {
seq_puts(m, "# Version 1.1\n");
if (export_stats)
seq_puts(m, "# Path Client Start-time\n#\tStats\n");
else
seq_puts(m, "# Path Client(Flags) # IPs\n");
+ seq_puts(m, kpatch_string());
return 0;
}
diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c
--- src.orig/net/netlink/af_netlink.c 2022-06-15 10:04:11.011918011 -0400
+++ src/net/netlink/af_netlink.c 2022-06-15 10:04:48.312096569 -0400
@@ -2908,4 +2908,9 @@ panic:
panic("netlink_init: Cannot allocate nl_table\n");
}
+char *kpatch_string(void)
+{
+ return "# kpatch\n";
+}
+
core_initcall(netlink_proto_init);

View File

@ -0,0 +1,7 @@
#!/bin/bash
SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
declare -a blacklist=(meminfo-string-LOADED.test)
source ${SCRIPTDIR}/../common/multiple.template

View File

@ -0,0 +1,25 @@
diff -Nupr src.orig/drivers/tty/n_tty.c src/drivers/tty/n_tty.c
--- src.orig/drivers/tty/n_tty.c 2022-06-15 10:04:10.454915345 -0400
+++ src/drivers/tty/n_tty.c 2022-06-15 10:04:59.142148413 -0400
@@ -2213,7 +2213,7 @@ more_to_be_read:
* (note that the process_output*() functions take this lock themselves)
*/
-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
+static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t nr)
{
const unsigned char *b = buf;
@@ -2300,6 +2300,12 @@ break_out:
return (b - buf) ? b - buf : retval;
}
+static ssize_t __attribute__((optimize("-fno-optimize-sibling-calls"))) n_tty_write(struct tty_struct *tty, struct file *file,
+ const unsigned char *buf, size_t nr)
+{
+ return kpatch_n_tty_write(tty, file, buf, nr);
+}
+
/**
* n_tty_poll - poll method for N_TTY
* @tty: terminal device

View File

@ -0,0 +1,34 @@
diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
--- src.orig/fs/proc/cmdline.c 2022-06-15 10:04:10.539915752 -0400
+++ src/fs/proc/cmdline.c 2022-06-15 10:05:10.193201315 -0400
@@ -17,3 +17,10 @@ static int __init proc_cmdline_init(void
return 0;
}
fs_initcall(proc_cmdline_init);
+
+#include <linux/printk.h>
+void kpatch_print_message(void)
+{
+ if (!jiffies)
+ printk("hello there!\n");
+}
diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
--- src.orig/fs/proc/meminfo.c 2022-06-15 10:04:10.540915757 -0400
+++ src/fs/proc/meminfo.c 2022-06-15 10:05:10.193201315 -0400
@@ -19,6 +19,8 @@
#include <asm/page.h>
#include "internal.h"
+void kpatch_print_message(void);
+
void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
{
}
@@ -55,6 +57,7 @@ static int meminfo_proc_show(struct seq_
sreclaimable = global_node_page_state_pages(NR_SLAB_RECLAIMABLE_B);
sunreclaim = global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B);
+ kpatch_print_message();
show_val_kb(m, "MemTotal: ", i.totalram);
show_val_kb(m, "MemFree: ", i.freeram);
show_val_kb(m, "MemAvailable: ", available);

View File

@ -0,0 +1,3 @@
#!/bin/bash
grep -q newpid: /proc/$$/status

View File

@ -0,0 +1,75 @@
diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c
--- src.orig/fs/proc/array.c 2022-06-15 10:04:10.539915752 -0400
+++ src/fs/proc/array.c 2022-06-15 10:05:21.025253168 -0400
@@ -394,12 +394,19 @@ static inline void task_seccomp(struct s
seq_putc(m, '\n');
}
+#include <linux/livepatch.h>
static inline void task_context_switch_counts(struct seq_file *m,
struct task_struct *p)
{
+ int *newpid;
+
seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw);
seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw);
seq_putc(m, '\n');
+
+ newpid = klp_shadow_get(p, 0);
+ if (newpid)
+ seq_printf(m, "newpid:\t%d\n", *newpid);
}
static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c
--- src.orig/kernel/exit.c 2022-06-15 10:04:10.881917389 -0400
+++ src/kernel/exit.c 2022-06-15 10:05:21.025253168 -0400
@@ -733,6 +733,7 @@ static void check_stack_usage(void)
static inline void check_stack_usage(void) {}
#endif
+#include <linux/livepatch.h>
void __noreturn do_exit(long code)
{
struct task_struct *tsk = current;
@@ -795,6 +796,8 @@ void __noreturn do_exit(long code)
exit_task_work(tsk);
exit_thread(tsk);
+ klp_shadow_free(tsk, 0, NULL);
+
/*
* Flush inherited counters to the parent - before the parent
* gets woken up by child-exit notifications.
diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
--- src.orig/kernel/fork.c 2022-06-15 10:04:10.879917380 -0400
+++ src/kernel/fork.c 2022-06-15 10:05:21.026253173 -0400
@@ -2595,6 +2595,7 @@ struct task_struct *create_io_thread(int
*
* args->exit_signal is expected to be checked for sanity by the caller.
*/
+#include <linux/livepatch.h>
pid_t kernel_clone(struct kernel_clone_args *args)
{
u64 clone_flags = args->flags;
@@ -2603,6 +2604,8 @@ pid_t kernel_clone(struct kernel_clone_a
struct task_struct *p;
int trace = 0;
pid_t nr;
+ int *newpid;
+ static int ctr = 0;
/*
* For legacy clone() calls, CLONE_PIDFD uses the parent_tid argument
@@ -2642,6 +2645,11 @@ pid_t kernel_clone(struct kernel_clone_a
if (IS_ERR(p))
return PTR_ERR(p);
+ newpid = klp_shadow_get_or_alloc(p, 0, sizeof(*newpid), GFP_KERNEL,
+ NULL, NULL);
+ if (newpid)
+ *newpid = ctr++;
+
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.

View File

@ -0,0 +1,22 @@
diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
--- src.orig/kernel/fork.c 2022-06-15 10:04:10.879917380 -0400
+++ src/kernel/fork.c 2022-06-15 10:05:31.745304485 -0400
@@ -1676,10 +1676,18 @@ static void posix_cpu_timers_init_group(
posix_cputimers_group_init(pct, cpu_limit);
}
+void kpatch_foo(void)
+{
+ if (!jiffies)
+ printk("kpatch copy signal\n");
+}
+
static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
{
struct signal_struct *sig;
+ kpatch_foo();
+
if (clone_flags & CLONE_THREAD)
return 0;

View File

@ -0,0 +1,46 @@
From 2d6b7bce089e52563bd9c67df62f48e90b48047d Mon Sep 17 00:00:00 2001
From: Julien Thierry <jthierry@redhat.com>
Date: Wed, 6 May 2020 14:30:57 +0100
Subject: [PATCH] Symbol version change
This change causes:
1) Some exported symbols in drivers/base/core.c to see their CRCs
change.
2) Changes usb_get_dev() referencing a get_device() whose CRC has
changed, causing the symbol and the new CRC to be included in the
__version section of the final module.
This makes the final module unloadable for the target kernel.
See "Exported symbol versioning" of the patch author guide for more
detail.
---
drivers/base/core.c | 2 ++
drivers/usb/core/usb.c | 2 ++
2 files changed, 4 insertions(+)
diff -Nupr src.orig/drivers/base/core.c src/drivers/base/core.c
--- src.orig/drivers/base/core.c 2022-06-15 10:04:08.806907456 -0400
+++ src/drivers/base/core.c 2022-06-15 10:05:42.555356233 -0400
@@ -34,6 +34,8 @@
#include "base.h"
#include "power/power.h"
+#include <linux/blktrace_api.h>
+
#ifdef CONFIG_SYSFS_DEPRECATED
#ifdef CONFIG_SYSFS_DEPRECATED_V2
long sysfs_deprecated = 1;
diff -Nupr src.orig/drivers/usb/core/usb.c src/drivers/usb/core/usb.c
--- src.orig/drivers/usb/core/usb.c 2022-06-15 10:04:10.469915417 -0400
+++ src/drivers/usb/core/usb.c 2022-06-15 10:05:42.556356238 -0400
@@ -697,6 +697,8 @@ EXPORT_SYMBOL_GPL(usb_alloc_dev);
*/
struct usb_device *usb_get_dev(struct usb_device *dev)
{
+ barrier();
+
if (dev)
get_device(&dev->dev);
return dev;

View File

@ -0,0 +1,3 @@
#!/bin/bash
uname -s | grep -q kpatch

View File

@ -0,0 +1,20 @@
diff -Nupr src.orig/kernel/sys.c src/kernel/sys.c
--- src.orig/kernel/sys.c 2022-06-15 10:04:10.881917389 -0400
+++ src/kernel/sys.c 2022-06-15 10:05:53.708409623 -0400
@@ -1278,13 +1278,15 @@ static int override_release(char __user
return ret;
}
-SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
+#include "kpatch-syscall.h"
+KPATCH_SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
{
struct new_utsname tmp;
down_read(&uts_sem);
memcpy(&tmp, utsname(), sizeof(tmp));
up_read(&uts_sem);
+ strcat(tmp.sysname, ".kpatch");
if (copy_to_user(name, &tmp, sizeof(tmp)))
return -EFAULT;

View File

@ -0,0 +1,9 @@
diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
--- src.orig/arch/x86/kvm/x86.c 2022-06-15 10:04:08.731907097 -0400
+++ src/arch/x86/kvm/x86.c 2022-06-15 10:06:04.480461189 -0400
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
+
/*
* Kernel-based Virtual Machine driver for Linux
*