Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .packit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ _:
# In this case (no build), it is a bug, see packit/packit-service#2841
# Yet, the `rawhide` has no effect as there is no Copr build happening.
fedora-rawhide-x86_64:
distros: [Fedora-37-Updated]
distros: [Fedora-43-Updated]
fedora-rawhide-s390x:
distros: [Fedora-37-Updated]
distros: [Fedora-43-Updated]
fedora-rawhide-ppc64le:
distros: [Fedora-37-Updated]
distros: [Fedora-43-Updated]
fedora-rawhide-aarch64:
distros: [Fedora-43-Updated]
skip_build: true
manual_trigger: true
manual_trigger: false
tmt_plan: kpatch-integration-upstream
fmf_url: https://gitlab.com/redhat/centos-stream/tests/kernel/test-plans.git
fmf_ref: main
Expand All @@ -40,7 +42,7 @@ _:
# rhel+epel-10-ppc64le:
# distros: [RHEL-10.0-Nightly]
skip_build: true
manual_trigger: true
manual_trigger: false
tmt_plan: kpatch-integration-rhel
fmf_url: https://gitlab.com/redhat/centos-stream/tests/kernel/test-plans.git
fmf_ref: main
Expand Down
3 changes: 3 additions & 0 deletions test/integration/linux-6.17.0/data-new-LOADED.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

grep "kpatch: 5" /proc/meminfo
20 changes: 20 additions & 0 deletions test/integration/linux-6.17.0/data-new.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
--- src.orig/fs/proc/meminfo.c 2025-11-03 16:25:30.873267824 -0500
+++ src/fs/proc/meminfo.c 2025-11-03 16:25:32.043279011 -0500
@@ -31,6 +31,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;
@@ -155,6 +157,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);

#ifdef CONFIG_UNACCEPTED_MEMORY
show_val_kb(m, "Unaccepted: ",
22 changes: 22 additions & 0 deletions test/integration/linux-6.17.0/gcc-static-local-var-6.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
diff -Nupr src.orig/net/ipv6/netfilter.c src/net/ipv6/netfilter.c
--- src.orig/net/ipv6/netfilter.c 2025-11-03 16:25:28.713247170 -0500
+++ src/net/ipv6/netfilter.c 2025-11-03 16:25:43.105384786 -0500
@@ -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)
155 changes: 155 additions & 0 deletions test/integration/linux-6.17.0/macro-callbacks.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
diff -Nupr src.orig/drivers/input/joydev.c src/drivers/input/joydev.c
--- src.orig/drivers/input/joydev.c 2025-11-03 16:25:30.138260796 -0500
+++ src/drivers/input/joydev.c 2025-11-03 16:25:51.415464246 -0500
@@ -1095,3 +1095,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 2025-11-03 16:25:30.145260862 -0500
+++ src/drivers/input/misc/pcspkr.c 2025-11-03 16:25:51.415464246 -0500
@@ -132,3 +132,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 2025-11-03 16:25:30.841267518 -0500
+++ src/fs/aio.c 2025-11-03 16:25:51.415464246 -0500
@@ -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
9 changes: 9 additions & 0 deletions test/integration/linux-6.17.0/module-LOADED.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

set -o errexit

sudo modprobe xfs
sleep 5
echo "file fs/xfs/xfs_stats.c +p" > /sys/kernel/debug/dynamic_debug/control
grep -q kpatch /sys/fs/xfs/stats/stats
dmesg | grep -q "kpatch: pr_debug"
75 changes: 75 additions & 0 deletions test/integration/linux-6.17.0/module.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
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/xfs/xfs_stats.c src/fs/xfs/xfs_stats.c
--- src.orig/fs/xfs/xfs_stats.c 2025-11-03 16:25:30.831267422 -0500
+++ src/fs/xfs/xfs_stats.c 2025-11-03 16:25:57.359521082 -0500
@@ -16,6 +16,8 @@ static int counter_val(struct xfsstats _
return val;
}

+extern char *kpatch_string(void);
+
int xfs_stats_format(struct xfsstats __percpu *stats, char *buf)
{
int i, j;
@@ -90,6 +92,34 @@ int xfs_stats_format(struct xfsstats __p
0);
#endif

+ /* Reference a symbol outside the .o yet inside the patch module: */
+ len += scnprintf(buf + len, PATH_MAX-len, "%s\n", kpatch_string());
+
+#ifdef CONFIG_X86_64
+ /* Test alternatives patching: */
+ alternative("ud2", "nop", X86_FEATURE_ALWAYS);
+ alternative("nop", "ud2", X86_FEATURE_IA64);
+
+ /* Test paravirt patching: */
+ slow_down_io(); /* paravirt call */
+#endif
+
+ /* Test pr_debug: */
+ pr_debug("kpatch: pr_debug() test\n");
+
+{
+ /* Test static branches: */
+ static DEFINE_STATIC_KEY_TRUE(kpatch_key);
+
+ if (static_branch_unlikely(&memcg_kmem_online_key))
+ printk("kpatch: memcg_kmem_online_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);
+}
+
return len;
}

diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c
--- src.orig/net/netlink/af_netlink.c 2025-11-03 16:25:28.759247610 -0500
+++ src/net/netlink/af_netlink.c 2025-11-03 16:25:57.359521082 -0500
@@ -2952,4 +2952,9 @@ panic:
panic("netlink_init: Cannot allocate nl_table\n");
}

+char *kpatch_string(void)
+{
+ return "kpatch";
+}
+
core_initcall(netlink_proto_init);
7 changes: 7 additions & 0 deletions test/integration/linux-6.17.0/multiple.test
Original file line number Diff line number Diff line change
@@ -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
25 changes: 25 additions & 0 deletions test/integration/linux-6.17.0/new-function.patch
Original file line number Diff line number Diff line change
@@ -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 2025-11-03 16:25:29.659256215 -0500
+++ src/drivers/tty/n_tty.c 2025-11-03 16:26:05.536599271 -0500
@@ -2343,7 +2343,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 u8 *buf, size_t nr)
{
const u8 *b = buf;
@@ -2428,6 +2428,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
34 changes: 34 additions & 0 deletions test/integration/linux-6.17.0/new-globals.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
--- src.orig/fs/proc/cmdline.c 2025-11-03 16:25:30.873267824 -0500
+++ src/fs/proc/cmdline.c 2025-11-03 16:26:10.350645302 -0500
@@ -22,3 +22,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 2025-11-03 16:25:30.873267824 -0500
+++ src/fs/proc/meminfo.c 2025-11-03 16:26:10.350645302 -0500
@@ -21,6 +21,8 @@
#include <asm/page.h>
#include "internal.h"

+void kpatch_print_message(void);
+
void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
{
}
@@ -57,6 +59,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);
3 changes: 3 additions & 0 deletions test/integration/linux-6.17.0/shadow-newpid-LOADED.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

grep -q newpid: /proc/$$/status
Loading