Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * livepatch-shadow-mod.c - Shadow variables, buggy module demo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Purpose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * -------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * As a demonstration of livepatch shadow variable API, this module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * introduces memory leak behavior that livepatch modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * livepatch-shadow-fix1.ko and livepatch-shadow-fix2.ko correct and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * enhance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * WARNING - even though the livepatch-shadow-fix modules patch the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * memory leak, please load these modules at your own risk -- some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * amount of memory may leaked before the bug is patched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * Usage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * -----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * Step 1 - Load the buggy demonstration module:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *   insmod samples/livepatch/livepatch-shadow-mod.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * Watch dmesg output for a few moments to see new dummy being allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * and a periodic cleanup check.  (Note: a small amount of memory is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * being leaked.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * Step 2 - Load livepatch fix1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  *   insmod samples/livepatch/livepatch-shadow-fix1.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * Continue watching dmesg and note that now livepatch_fix1_dummy_free()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * and livepatch_fix1_dummy_alloc() are logging messages about leaked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * memory and eventually leaks prevented.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * Step 3 - Load livepatch fix2 (on top of fix1):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  *   insmod samples/livepatch/livepatch-shadow-fix2.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * This module extends functionality through shadow variables, as a new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * "check" counter is added to the dummy structure.  Periodic dmesg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * messages will log these as dummies are cleaned up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * Step 4 - Cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * Unwind the demonstration by disabling the livepatch fix modules, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * removing them and the demo module:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  *   echo 0 > /sys/kernel/livepatch/livepatch_shadow_fix2/enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  *   echo 0 > /sys/kernel/livepatch/livepatch_shadow_fix1/enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  *   rmmod livepatch-shadow-fix2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *   rmmod livepatch-shadow-fix1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  *   rmmod livepatch-shadow-mod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) MODULE_DESCRIPTION("Buggy module for shadow variable demo");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) /* Allocate new dummies every second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #define ALLOC_PERIOD	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) /* Check for expired dummies after a few new ones have been allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #define CLEANUP_PERIOD	(3 * ALLOC_PERIOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) /* Dummies expire after a few cleanup instances */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) #define EXPIRE_PERIOD	(4 * CLEANUP_PERIOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * Keep a list of all the dummies so we can clean up any residual ones
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * on module exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static LIST_HEAD(dummy_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static DEFINE_MUTEX(dummy_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) struct dummy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	unsigned long jiffies_expire;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static __used noinline struct dummy *dummy_alloc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	struct dummy *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	int *leak;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	d = kzalloc(sizeof(*d), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	d->jiffies_expire = jiffies +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		msecs_to_jiffies(1000 * EXPIRE_PERIOD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	/* Oops, forgot to save leak! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	leak = kzalloc(sizeof(*leak), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	if (!leak) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		kfree(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	pr_info("%s: dummy @ %p, expires @ %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		__func__, d, d->jiffies_expire);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	return d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static __used noinline void dummy_free(struct dummy *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	pr_info("%s: dummy @ %p, expired = %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		__func__, d, d->jiffies_expire);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	kfree(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static __used noinline bool dummy_check(struct dummy *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 					   unsigned long jiffies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	return time_after(jiffies, d->jiffies_expire);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  * alloc_work_func: allocates new dummy structures, allocates additional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  *                  memory, aptly named "leak", but doesn't keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  *                  permanent record of it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static void alloc_work_func(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static DECLARE_DELAYED_WORK(alloc_dwork, alloc_work_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void alloc_work_func(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	struct dummy *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	d = dummy_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	mutex_lock(&dummy_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	list_add(&d->list, &dummy_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	mutex_unlock(&dummy_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	schedule_delayed_work(&alloc_dwork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		msecs_to_jiffies(1000 * ALLOC_PERIOD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  * cleanup_work_func: frees dummy structures.  Without knownledge of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  *                    "leak", it leaks the additional memory that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  *                    alloc_work_func created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void cleanup_work_func(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static DECLARE_DELAYED_WORK(cleanup_dwork, cleanup_work_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void cleanup_work_func(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	struct dummy *d, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	unsigned long j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	j = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	pr_info("%s: jiffies = %lx\n", __func__, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	mutex_lock(&dummy_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	list_for_each_entry_safe(d, tmp, &dummy_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		/* Kick out and free any expired dummies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		if (dummy_check(d, j)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			list_del(&d->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			dummy_free(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	mutex_unlock(&dummy_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	schedule_delayed_work(&cleanup_dwork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		msecs_to_jiffies(1000 * CLEANUP_PERIOD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int livepatch_shadow_mod_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	schedule_delayed_work(&alloc_dwork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		msecs_to_jiffies(1000 * ALLOC_PERIOD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	schedule_delayed_work(&cleanup_dwork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		msecs_to_jiffies(1000 * CLEANUP_PERIOD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static void livepatch_shadow_mod_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	struct dummy *d, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	/* Wait for any dummies at work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	cancel_delayed_work_sync(&alloc_dwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	cancel_delayed_work_sync(&cleanup_dwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	/* Cleanup residual dummies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	list_for_each_entry_safe(d, tmp, &dummy_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		list_del(&d->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		dummy_free(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) module_init(livepatch_shadow_mod_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) module_exit(livepatch_shadow_mod_exit);