0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 #include <linux/kernel.h>
0066 #include <linux/module.h>
0067 #include <linux/sched.h>
0068 #include <linux/slab.h>
0069 #include <linux/stat.h>
0070 #include <linux/workqueue.h>
0071
0072 MODULE_LICENSE("GPL");
0073 MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
0074 MODULE_DESCRIPTION("Buggy module for shadow variable demo");
0075
0076
0077 #define ALLOC_PERIOD 1
0078
0079 #define CLEANUP_PERIOD (3 * ALLOC_PERIOD)
0080
0081 #define EXPIRE_PERIOD (4 * CLEANUP_PERIOD)
0082
0083
0084
0085
0086
0087 static LIST_HEAD(dummy_list);
0088 static DEFINE_MUTEX(dummy_list_mutex);
0089
0090 struct dummy {
0091 struct list_head list;
0092 unsigned long jiffies_expire;
0093 };
0094
0095 static __used noinline struct dummy *dummy_alloc(void)
0096 {
0097 struct dummy *d;
0098 int *leak;
0099
0100 d = kzalloc(sizeof(*d), GFP_KERNEL);
0101 if (!d)
0102 return NULL;
0103
0104 d->jiffies_expire = jiffies +
0105 msecs_to_jiffies(1000 * EXPIRE_PERIOD);
0106
0107
0108 leak = kzalloc(sizeof(*leak), GFP_KERNEL);
0109 if (!leak) {
0110 kfree(d);
0111 return NULL;
0112 }
0113
0114 pr_info("%s: dummy @ %p, expires @ %lx\n",
0115 __func__, d, d->jiffies_expire);
0116
0117 return d;
0118 }
0119
0120 static __used noinline void dummy_free(struct dummy *d)
0121 {
0122 pr_info("%s: dummy @ %p, expired = %lx\n",
0123 __func__, d, d->jiffies_expire);
0124
0125 kfree(d);
0126 }
0127
0128 static __used noinline bool dummy_check(struct dummy *d,
0129 unsigned long jiffies)
0130 {
0131 return time_after(jiffies, d->jiffies_expire);
0132 }
0133
0134
0135
0136
0137
0138
0139
0140 static void alloc_work_func(struct work_struct *work);
0141 static DECLARE_DELAYED_WORK(alloc_dwork, alloc_work_func);
0142
0143 static void alloc_work_func(struct work_struct *work)
0144 {
0145 struct dummy *d;
0146
0147 d = dummy_alloc();
0148 if (!d)
0149 return;
0150
0151 mutex_lock(&dummy_list_mutex);
0152 list_add(&d->list, &dummy_list);
0153 mutex_unlock(&dummy_list_mutex);
0154
0155 schedule_delayed_work(&alloc_dwork,
0156 msecs_to_jiffies(1000 * ALLOC_PERIOD));
0157 }
0158
0159
0160
0161
0162
0163
0164
0165 static void cleanup_work_func(struct work_struct *work);
0166 static DECLARE_DELAYED_WORK(cleanup_dwork, cleanup_work_func);
0167
0168 static void cleanup_work_func(struct work_struct *work)
0169 {
0170 struct dummy *d, *tmp;
0171 unsigned long j;
0172
0173 j = jiffies;
0174 pr_info("%s: jiffies = %lx\n", __func__, j);
0175
0176 mutex_lock(&dummy_list_mutex);
0177 list_for_each_entry_safe(d, tmp, &dummy_list, list) {
0178
0179
0180 if (dummy_check(d, j)) {
0181 list_del(&d->list);
0182 dummy_free(d);
0183 }
0184 }
0185 mutex_unlock(&dummy_list_mutex);
0186
0187 schedule_delayed_work(&cleanup_dwork,
0188 msecs_to_jiffies(1000 * CLEANUP_PERIOD));
0189 }
0190
0191 static int livepatch_shadow_mod_init(void)
0192 {
0193 schedule_delayed_work(&alloc_dwork,
0194 msecs_to_jiffies(1000 * ALLOC_PERIOD));
0195 schedule_delayed_work(&cleanup_dwork,
0196 msecs_to_jiffies(1000 * CLEANUP_PERIOD));
0197
0198 return 0;
0199 }
0200
0201 static void livepatch_shadow_mod_exit(void)
0202 {
0203 struct dummy *d, *tmp;
0204
0205
0206 cancel_delayed_work_sync(&alloc_dwork);
0207 cancel_delayed_work_sync(&cleanup_dwork);
0208
0209
0210 list_for_each_entry_safe(d, tmp, &dummy_list, list) {
0211 list_del(&d->list);
0212 dummy_free(d);
0213 }
0214 }
0215
0216 module_init(livepatch_shadow_mod_init);
0217 module_exit(livepatch_shadow_mod_exit);