0001
0002
0003
0004 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0005
0006 #include <linux/module.h>
0007 #include <linux/kernel.h>
0008 #include <linux/list.h>
0009 #include <linux/livepatch.h>
0010 #include <linux/slab.h>
0011
0012
0013
0014
0015
0016
0017
0018 static LIST_HEAD(ptr_list);
0019 struct shadow_ptr {
0020 void *ptr;
0021 int id;
0022 struct list_head list;
0023 };
0024
0025 static void free_ptr_list(void)
0026 {
0027 struct shadow_ptr *sp, *tmp_sp;
0028
0029 list_for_each_entry_safe(sp, tmp_sp, &ptr_list, list) {
0030 list_del(&sp->list);
0031 kfree(sp);
0032 }
0033 }
0034
0035 static int ptr_id(void *ptr)
0036 {
0037 struct shadow_ptr *sp;
0038 static int count;
0039
0040 list_for_each_entry(sp, &ptr_list, list) {
0041 if (sp->ptr == ptr)
0042 return sp->id;
0043 }
0044
0045 sp = kmalloc(sizeof(*sp), GFP_ATOMIC);
0046 if (!sp)
0047 return -ENOMEM;
0048 sp->ptr = ptr;
0049 sp->id = count++;
0050
0051 list_add(&sp->list, &ptr_list);
0052
0053 return sp->id;
0054 }
0055
0056
0057
0058
0059
0060
0061 static void *shadow_get(void *obj, unsigned long id)
0062 {
0063 int **sv;
0064
0065 sv = klp_shadow_get(obj, id);
0066 pr_info("klp_%s(obj=PTR%d, id=0x%lx) = PTR%d\n",
0067 __func__, ptr_id(obj), id, ptr_id(sv));
0068
0069 return sv;
0070 }
0071
0072 static void *shadow_alloc(void *obj, unsigned long id, size_t size,
0073 gfp_t gfp_flags, klp_shadow_ctor_t ctor,
0074 void *ctor_data)
0075 {
0076 int **var = ctor_data;
0077 int **sv;
0078
0079 sv = klp_shadow_alloc(obj, id, size, gfp_flags, ctor, var);
0080 pr_info("klp_%s(obj=PTR%d, id=0x%lx, size=%zx, gfp_flags=%pGg), ctor=PTR%d, ctor_data=PTR%d = PTR%d\n",
0081 __func__, ptr_id(obj), id, size, &gfp_flags, ptr_id(ctor),
0082 ptr_id(*var), ptr_id(sv));
0083
0084 return sv;
0085 }
0086
0087 static void *shadow_get_or_alloc(void *obj, unsigned long id, size_t size,
0088 gfp_t gfp_flags, klp_shadow_ctor_t ctor,
0089 void *ctor_data)
0090 {
0091 int **var = ctor_data;
0092 int **sv;
0093
0094 sv = klp_shadow_get_or_alloc(obj, id, size, gfp_flags, ctor, var);
0095 pr_info("klp_%s(obj=PTR%d, id=0x%lx, size=%zx, gfp_flags=%pGg), ctor=PTR%d, ctor_data=PTR%d = PTR%d\n",
0096 __func__, ptr_id(obj), id, size, &gfp_flags, ptr_id(ctor),
0097 ptr_id(*var), ptr_id(sv));
0098
0099 return sv;
0100 }
0101
0102 static void shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor)
0103 {
0104 klp_shadow_free(obj, id, dtor);
0105 pr_info("klp_%s(obj=PTR%d, id=0x%lx, dtor=PTR%d)\n",
0106 __func__, ptr_id(obj), id, ptr_id(dtor));
0107 }
0108
0109 static void shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor)
0110 {
0111 klp_shadow_free_all(id, dtor);
0112 pr_info("klp_%s(id=0x%lx, dtor=PTR%d)\n", __func__, id, ptr_id(dtor));
0113 }
0114
0115
0116
0117 static int shadow_ctor(void *obj, void *shadow_data, void *ctor_data)
0118 {
0119 int **sv = shadow_data;
0120 int **var = ctor_data;
0121
0122 if (!var)
0123 return -EINVAL;
0124
0125 *sv = *var;
0126 pr_info("%s: PTR%d -> PTR%d\n", __func__, ptr_id(sv), ptr_id(*var));
0127
0128 return 0;
0129 }
0130
0131
0132
0133
0134
0135
0136 static void shadow_dtor(void *obj, void *shadow_data)
0137 {
0138 int **sv = shadow_data;
0139
0140 pr_info("%s(obj=PTR%d, shadow_data=PTR%d)\n",
0141 __func__, ptr_id(obj), ptr_id(sv));
0142 }
0143
0144
0145 #define NUM_OBJS 3
0146
0147
0148 #define SV_ID1 0x1234
0149 #define SV_ID2 0x1235
0150
0151
0152
0153
0154
0155
0156
0157 struct test_object {
0158
0159 struct shadow_ptr sp;
0160
0161
0162
0163
0164 };
0165
0166 static int test_klp_shadow_vars_init(void)
0167 {
0168 struct test_object objs[NUM_OBJS];
0169 char nfields1[NUM_OBJS], *pnfields1[NUM_OBJS], **sv1[NUM_OBJS];
0170 char *pndup[NUM_OBJS];
0171 int nfields2[NUM_OBJS], *pnfields2[NUM_OBJS], **sv2[NUM_OBJS];
0172 void **sv;
0173 int ret;
0174 int i;
0175
0176 ptr_id(NULL);
0177
0178
0179
0180
0181
0182 sv = shadow_get(&objs[0], SV_ID1);
0183 if (!sv)
0184 pr_info(" got expected NULL result\n");
0185
0186
0187 for (i = 0; i < NUM_OBJS; i++) {
0188 pnfields1[i] = &nfields1[i];
0189 ptr_id(pnfields1[i]);
0190
0191 if (i % 2) {
0192 sv1[i] = shadow_alloc(&objs[i], SV_ID1,
0193 sizeof(pnfields1[i]), GFP_KERNEL,
0194 shadow_ctor, &pnfields1[i]);
0195 } else {
0196 sv1[i] = shadow_get_or_alloc(&objs[i], SV_ID1,
0197 sizeof(pnfields1[i]), GFP_KERNEL,
0198 shadow_ctor, &pnfields1[i]);
0199 }
0200 if (!sv1[i]) {
0201 ret = -ENOMEM;
0202 goto out;
0203 }
0204
0205 pnfields2[i] = &nfields2[i];
0206 ptr_id(pnfields2[i]);
0207 sv2[i] = shadow_alloc(&objs[i], SV_ID2, sizeof(pnfields2[i]),
0208 GFP_KERNEL, shadow_ctor, &pnfields2[i]);
0209 if (!sv2[i]) {
0210 ret = -ENOMEM;
0211 goto out;
0212 }
0213 }
0214
0215
0216 for (i = 0; i < NUM_OBJS; i++) {
0217
0218 sv = shadow_get(&objs[i], SV_ID1);
0219 if (!sv) {
0220 ret = -EINVAL;
0221 goto out;
0222 }
0223 if ((char **)sv == sv1[i] && *sv1[i] == pnfields1[i])
0224 pr_info(" got expected PTR%d -> PTR%d result\n",
0225 ptr_id(sv1[i]), ptr_id(*sv1[i]));
0226
0227
0228 sv = shadow_get(&objs[i], SV_ID2);
0229 if (!sv) {
0230 ret = -EINVAL;
0231 goto out;
0232 }
0233 if ((int **)sv == sv2[i] && *sv2[i] == pnfields2[i])
0234 pr_info(" got expected PTR%d -> PTR%d result\n",
0235 ptr_id(sv2[i]), ptr_id(*sv2[i]));
0236 }
0237
0238
0239 for (i = 0; i < NUM_OBJS; i++) {
0240 pndup[i] = &nfields1[i];
0241 ptr_id(pndup[i]);
0242
0243 sv = shadow_get_or_alloc(&objs[i], SV_ID1, sizeof(pndup[i]),
0244 GFP_KERNEL, shadow_ctor, &pndup[i]);
0245 if (!sv) {
0246 ret = -EINVAL;
0247 goto out;
0248 }
0249 if ((char **)sv == sv1[i] && *sv1[i] == pnfields1[i])
0250 pr_info(" got expected PTR%d -> PTR%d result\n",
0251 ptr_id(sv1[i]), ptr_id(*sv1[i]));
0252 }
0253
0254
0255 for (i = 0; i < NUM_OBJS; i++) {
0256 shadow_free(&objs[i], SV_ID1, shadow_dtor);
0257 sv = shadow_get(&objs[i], SV_ID1);
0258 if (!sv)
0259 pr_info(" got expected NULL result\n");
0260 }
0261
0262
0263 for (i = 0; i < NUM_OBJS; i++) {
0264 sv = shadow_get(&objs[i], SV_ID2);
0265 if (!sv) {
0266 ret = -EINVAL;
0267 goto out;
0268 }
0269 if ((int **)sv == sv2[i] && *sv2[i] == pnfields2[i])
0270 pr_info(" got expected PTR%d -> PTR%d result\n",
0271 ptr_id(sv2[i]), ptr_id(*sv2[i]));
0272 }
0273
0274
0275 shadow_free_all(SV_ID2, NULL);
0276 for (i = 0; i < NUM_OBJS; i++) {
0277 sv = shadow_get(&objs[i], SV_ID2);
0278 if (!sv)
0279 pr_info(" got expected NULL result\n");
0280 }
0281
0282 free_ptr_list();
0283
0284 return 0;
0285 out:
0286 shadow_free_all(SV_ID1, NULL);
0287 shadow_free_all(SV_ID2, NULL);
0288 free_ptr_list();
0289
0290 return ret;
0291 }
0292
0293 static void test_klp_shadow_vars_exit(void)
0294 {
0295 }
0296
0297 module_init(test_klp_shadow_vars_init);
0298 module_exit(test_klp_shadow_vars_exit);
0299 MODULE_LICENSE("GPL");
0300 MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
0301 MODULE_DESCRIPTION("Livepatch test: shadow variables");