test_kprobes.c 7.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * test_kprobes.c - simple sanity test for *probes
 *
 * Copyright IBM Corp. 2008
 *
 * This program is free software;  you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 */

17 18
#define pr_fmt(fmt) "Kprobe smoke test: " fmt

19 20 21 22 23 24 25 26
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/random.h>

#define div_factor 3

static u32 rand1, preh_val, posth_val, jph_val;
static int errors, handler_errors, num_tests;
27
static u32 (*target)(u32 value);
28
static u32 (*target2)(u32 value);
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

static noinline u32 kprobe_target(u32 value)
{
	return (value / div_factor);
}

static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
	preh_val = (rand1 / div_factor);
	return 0;
}

static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
		unsigned long flags)
{
	if (preh_val != (rand1 / div_factor)) {
		handler_errors++;
46
		pr_err("incorrect value in post_handler\n");
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
	}
	posth_val = preh_val + div_factor;
}

static struct kprobe kp = {
	.symbol_name = "kprobe_target",
	.pre_handler = kp_pre_handler,
	.post_handler = kp_post_handler
};

static int test_kprobe(void)
{
	int ret;

	ret = register_kprobe(&kp);
	if (ret < 0) {
63
		pr_err("register_kprobe returned %d\n", ret);
64 65 66
		return ret;
	}

67
	ret = target(rand1);
68 69 70
	unregister_kprobe(&kp);

	if (preh_val == 0) {
71
		pr_err("kprobe pre_handler not called\n");
72 73 74 75
		handler_errors++;
	}

	if (posth_val == 0) {
76
		pr_err("kprobe post_handler not called\n");
77 78 79 80 81 82
		handler_errors++;
	}

	return 0;
}

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
static noinline u32 kprobe_target2(u32 value)
{
	return (value / div_factor) + 1;
}

static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
{
	preh_val = (rand1 / div_factor) + 1;
	return 0;
}

static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
		unsigned long flags)
{
	if (preh_val != (rand1 / div_factor) + 1) {
		handler_errors++;
99
		pr_err("incorrect value in post_handler2\n");
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
	}
	posth_val = preh_val + div_factor;
}

static struct kprobe kp2 = {
	.symbol_name = "kprobe_target2",
	.pre_handler = kp_pre_handler2,
	.post_handler = kp_post_handler2
};

static int test_kprobes(void)
{
	int ret;
	struct kprobe *kps[2] = {&kp, &kp2};

115 116 117
	/* addr and flags should be cleard for reusing kprobe. */
	kp.addr = NULL;
	kp.flags = 0;
118 119
	ret = register_kprobes(kps, 2);
	if (ret < 0) {
120
		pr_err("register_kprobes returned %d\n", ret);
121 122 123 124 125 126 127 128
		return ret;
	}

	preh_val = 0;
	posth_val = 0;
	ret = target(rand1);

	if (preh_val == 0) {
129
		pr_err("kprobe pre_handler not called\n");
130 131 132 133
		handler_errors++;
	}

	if (posth_val == 0) {
134
		pr_err("kprobe post_handler not called\n");
135 136 137 138 139 140 141 142
		handler_errors++;
	}

	preh_val = 0;
	posth_val = 0;
	ret = target2(rand1);

	if (preh_val == 0) {
143
		pr_err("kprobe pre_handler2 not called\n");
144 145 146 147
		handler_errors++;
	}

	if (posth_val == 0) {
148
		pr_err("kprobe post_handler2 not called\n");
149 150 151 152 153 154 155 156
		handler_errors++;
	}

	unregister_kprobes(kps, 2);
	return 0;

}

157 158 159 160
static u32 j_kprobe_target(u32 value)
{
	if (value != rand1) {
		handler_errors++;
161
		pr_err("incorrect value in jprobe handler\n");
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
	}

	jph_val = rand1;
	jprobe_return();
	return 0;
}

static struct jprobe jp = {
	.entry		= j_kprobe_target,
	.kp.symbol_name = "kprobe_target"
};

static int test_jprobe(void)
{
	int ret;

	ret = register_jprobe(&jp);
	if (ret < 0) {
180
		pr_err("register_jprobe returned %d\n", ret);
181 182 183
		return ret;
	}

184
	ret = target(rand1);
185 186
	unregister_jprobe(&jp);
	if (jph_val == 0) {
187
		pr_err("jprobe handler not called\n");
188 189 190 191 192 193
		handler_errors++;
	}

	return 0;
}

194 195 196 197 198 199 200 201 202 203
static struct jprobe jp2 = {
	.entry          = j_kprobe_target,
	.kp.symbol_name = "kprobe_target2"
};

static int test_jprobes(void)
{
	int ret;
	struct jprobe *jps[2] = {&jp, &jp2};

204 205 206
	/* addr and flags should be cleard for reusing kprobe. */
	jp.kp.addr = NULL;
	jp.kp.flags = 0;
207 208
	ret = register_jprobes(jps, 2);
	if (ret < 0) {
209
		pr_err("register_jprobes returned %d\n", ret);
210 211 212 213 214 215
		return ret;
	}

	jph_val = 0;
	ret = target(rand1);
	if (jph_val == 0) {
216
		pr_err("jprobe handler not called\n");
217 218 219 220 221 222
		handler_errors++;
	}

	jph_val = 0;
	ret = target2(rand1);
	if (jph_val == 0) {
223
		pr_err("jprobe handler2 not called\n");
224 225 226 227 228 229
		handler_errors++;
	}
	unregister_jprobes(jps, 2);

	return 0;
}
230 231 232
#ifdef CONFIG_KRETPROBES
static u32 krph_val;

233 234 235 236 237 238
static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	krph_val = (rand1 / div_factor);
	return 0;
}

239 240 241 242 243 244
static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	unsigned long ret = regs_return_value(regs);

	if (ret != (rand1 / div_factor)) {
		handler_errors++;
245
		pr_err("incorrect value in kretprobe handler\n");
246
	}
247 248
	if (krph_val == 0) {
		handler_errors++;
249
		pr_err("call to kretprobe entry handler failed\n");
250
	}
251

252
	krph_val = rand1;
253 254 255 256 257
	return 0;
}

static struct kretprobe rp = {
	.handler	= return_handler,
258
	.entry_handler  = entry_handler,
259 260 261 262 263 264 265 266 267
	.kp.symbol_name = "kprobe_target"
};

static int test_kretprobe(void)
{
	int ret;

	ret = register_kretprobe(&rp);
	if (ret < 0) {
268
		pr_err("register_kretprobe returned %d\n", ret);
269 270 271
		return ret;
	}

272
	ret = target(rand1);
273
	unregister_kretprobe(&rp);
274
	if (krph_val != rand1) {
275
		pr_err("kretprobe handler not called\n");
276 277 278 279 280
		handler_errors++;
	}

	return 0;
}
281 282 283 284 285 286 287

static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	unsigned long ret = regs_return_value(regs);

	if (ret != (rand1 / div_factor) + 1) {
		handler_errors++;
288
		pr_err("incorrect value in kretprobe handler2\n");
289 290 291
	}
	if (krph_val == 0) {
		handler_errors++;
292
		pr_err("call to kretprobe entry handler failed\n");
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
	}

	krph_val = rand1;
	return 0;
}

static struct kretprobe rp2 = {
	.handler	= return_handler2,
	.entry_handler  = entry_handler,
	.kp.symbol_name = "kprobe_target2"
};

static int test_kretprobes(void)
{
	int ret;
	struct kretprobe *rps[2] = {&rp, &rp2};

310 311 312
	/* addr and flags should be cleard for reusing kprobe. */
	rp.kp.addr = NULL;
	rp.kp.flags = 0;
313 314
	ret = register_kretprobes(rps, 2);
	if (ret < 0) {
315
		pr_err("register_kretprobe returned %d\n", ret);
316 317 318 319 320 321
		return ret;
	}

	krph_val = 0;
	ret = target(rand1);
	if (krph_val != rand1) {
322
		pr_err("kretprobe handler not called\n");
323 324 325 326 327 328
		handler_errors++;
	}

	krph_val = 0;
	ret = target2(rand1);
	if (krph_val != rand1) {
329
		pr_err("kretprobe handler2 not called\n");
330 331 332 333 334
		handler_errors++;
	}
	unregister_kretprobes(rps, 2);
	return 0;
}
335 336 337 338 339 340
#endif /* CONFIG_KRETPROBES */

int init_test_probes(void)
{
	int ret;

341
	target = kprobe_target;
342
	target2 = kprobe_target2;
343

344
	do {
345
		rand1 = prandom_u32();
346 347
	} while (rand1 <= div_factor);

348
	pr_info("started\n");
349 350 351 352 353
	num_tests++;
	ret = test_kprobe();
	if (ret < 0)
		errors++;

354 355 356 357 358
	num_tests++;
	ret = test_kprobes();
	if (ret < 0)
		errors++;

359 360 361 362 363
	num_tests++;
	ret = test_jprobe();
	if (ret < 0)
		errors++;

364 365 366 367 368
	num_tests++;
	ret = test_jprobes();
	if (ret < 0)
		errors++;

369 370 371 372 373
#ifdef CONFIG_KRETPROBES
	num_tests++;
	ret = test_kretprobe();
	if (ret < 0)
		errors++;
374 375 376 377 378

	num_tests++;
	ret = test_kretprobes();
	if (ret < 0)
		errors++;
379 380 381
#endif /* CONFIG_KRETPROBES */

	if (errors)
382
		pr_err("BUG: %d out of %d tests failed\n", errors, num_tests);
383
	else if (handler_errors)
384
		pr_err("BUG: %d error(s) running handlers\n", handler_errors);
385
	else
386
		pr_info("passed successfully\n");
387 388 389

	return 0;
}