summaryrefslogtreecommitdiffstats
path: root/samples/livepatch/livepatch-shadow-fix2.c
diff options
context:
space:
mode:
authorSalah Triki <salah.triki@gmail.com>2026-09-17 14:00:52 +0100
committerJonathan Cameron <jonathan.cameron@oss.qualcomm.com>2026-09-30 18:59:55 +0100
commite8dd273d199f5bbe295a8e3d8b777c5505b6b2e1 (patch)
tree767c7e109d3e6b9ec6549e99dfec9085d01318ad /samples/livepatch/livepatch-shadow-fix2.c
downloadlinux-stable-e8dd273d199f5bbe295a8e3d8b777c5505b6b2e1.tar.gz
linux-stable-e8dd273d199f5bbe295a8e3d8b777c5505b6b2e1.zip
iio: proximity: isl29501: Fix return type of isl29501_register_writegrafted
isl29501_register_write() was returning a u32 instead of an int. Since the function returns negative error codes (such as -ERANGE or return values from i2c_smbus_write_byte_data()), returning an unsigned integer type prevents callers from correctly checking for negative error conditions. Fix this by changing the function return type from u32 to int. This was found through manual code review. Fixes: 1c28799257bc ("iio: light: isl29501: Add support for the ISL29501 ToF sensor.") Signed-off-by: Salah Triki <salah.triki@gmail.com> Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Diffstat (limited to 'samples/livepatch/livepatch-shadow-fix2.c')
-rw-r--r--samples/livepatch/livepatch-shadow-fix2.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/samples/livepatch/livepatch-shadow-fix2.c b/samples/livepatch/livepatch-shadow-fix2.c
new file mode 100644
index 000000000..b99122cb2
--- /dev/null
+++ b/samples/livepatch/livepatch-shadow-fix2.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com>
+ */
+
+/*
+ * livepatch-shadow-fix2.c - Shadow variables, livepatch demo
+ *
+ * Purpose
+ * -------
+ *
+ * Adds functionality to livepatch-shadow-mod's in-flight data
+ * structures through a shadow variable. The livepatch patches a
+ * routine that periodically inspects data structures, incrementing a
+ * per-data-structure counter, creating the counter if needed.
+ *
+ *
+ * Usage
+ * -----
+ *
+ * This module is not intended to be standalone. See the "Usage"
+ * section of livepatch-shadow-mod.c.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/livepatch.h>
+#include <linux/slab.h>
+
+/* Shadow variable enums */
+#define SV_LEAK 1
+#define SV_COUNTER 2
+
+struct dummy {
+ struct list_head list;
+ unsigned long jiffies_expire;
+};
+
+static bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies)
+{
+ int *shadow_count;
+
+ /*
+ * Patch: handle in-flight dummy structures, if they do not
+ * already have a SV_COUNTER shadow variable, then attach a
+ * new one.
+ */
+ shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER,
+ sizeof(*shadow_count), GFP_NOWAIT,
+ NULL, NULL);
+ if (shadow_count)
+ *shadow_count += 1;
+
+ return time_after(jiffies, d->jiffies_expire);
+}
+
+static void livepatch_fix2_dummy_leak_dtor(void *obj, void *shadow_data)
+{
+ void *d = obj;
+ int **shadow_leak = shadow_data;
+
+ pr_info("%s: dummy @ %p, prevented leak @ %p\n",
+ __func__, d, *shadow_leak);
+ kfree(*shadow_leak);
+}
+
+static void livepatch_fix2_dummy_free(struct dummy *d)
+{
+ int **shadow_leak;
+ int *shadow_count;
+
+ /* Patch: copy the memory leak patch from the fix1 module. */
+ shadow_leak = klp_shadow_get(d, SV_LEAK);
+ if (shadow_leak)
+ klp_shadow_free(d, SV_LEAK, livepatch_fix2_dummy_leak_dtor);
+ else
+ pr_info("%s: dummy @ %p leaked!\n", __func__, d);
+
+ /*
+ * Patch: fetch the SV_COUNTER shadow variable and display
+ * the final count. Detach the shadow variable.
+ */
+ shadow_count = klp_shadow_get(d, SV_COUNTER);
+ if (shadow_count) {
+ pr_info("%s: dummy @ %p, check counter = %d\n",
+ __func__, d, *shadow_count);
+ klp_shadow_free(d, SV_COUNTER, NULL);
+ }
+
+ kfree(d);
+}
+
+static struct klp_func funcs[] = {
+ {
+ .old_name = "dummy_check",
+ .new_func = livepatch_fix2_dummy_check,
+ },
+ {
+ .old_name = "dummy_free",
+ .new_func = livepatch_fix2_dummy_free,
+ }, { }
+};
+
+static struct klp_object objs[] = {
+ {
+ .name = "livepatch_shadow_mod",
+ .funcs = funcs,
+ }, { }
+};
+
+static struct klp_patch patch = {
+ .mod = THIS_MODULE,
+ .objs = objs,
+};
+
+static int livepatch_shadow_fix2_init(void)
+{
+ return klp_enable_patch(&patch);
+}
+
+static void livepatch_shadow_fix2_exit(void)
+{
+ /* Cleanup any existing SV_COUNTER shadow variables */
+ klp_shadow_free_all(SV_COUNTER, NULL);
+}
+
+module_init(livepatch_shadow_fix2_init);
+module_exit(livepatch_shadow_fix2_exit);
+MODULE_DESCRIPTION("Live patching demo for shadow variables");
+MODULE_LICENSE("GPL");
+MODULE_INFO(livepatch, "Y");