0001
0002
0003
0004
0005
0006 #include <kunit/test.h>
0007 #include <asm/unwind.h>
0008 #include <linux/completion.h>
0009 #include <linux/kallsyms.h>
0010 #include <linux/kthread.h>
0011 #include <linux/ftrace.h>
0012 #include <linux/module.h>
0013 #include <linux/timer.h>
0014 #include <linux/slab.h>
0015 #include <linux/string.h>
0016 #include <linux/kprobes.h>
0017 #include <linux/wait.h>
0018 #include <asm/irq.h>
0019
0020 static struct kunit *current_test;
0021
0022 #define BT_BUF_SIZE (PAGE_SIZE * 4)
0023
0024 static bool force_bt;
0025 module_param_named(backtrace, force_bt, bool, 0444);
0026 MODULE_PARM_DESC(backtrace, "print backtraces for all tests");
0027
0028
0029
0030
0031 static void print_backtrace(char *bt)
0032 {
0033 char *p;
0034
0035 while (true) {
0036 p = strsep(&bt, "\n");
0037 if (!p)
0038 break;
0039 kunit_err(current_test, "%s\n", p);
0040 }
0041 }
0042
0043
0044
0045
0046
0047 static noinline int test_unwind(struct task_struct *task, struct pt_regs *regs,
0048 unsigned long sp)
0049 {
0050 int frame_count, prev_is_func2, seen_func2_func1, seen_kretprobe_trampoline;
0051 const int max_frames = 128;
0052 struct unwind_state state;
0053 size_t bt_pos = 0;
0054 int ret = 0;
0055 char *bt;
0056
0057 bt = kmalloc(BT_BUF_SIZE, GFP_ATOMIC);
0058 if (!bt) {
0059 kunit_err(current_test, "failed to allocate backtrace buffer\n");
0060 return -ENOMEM;
0061 }
0062
0063 frame_count = 0;
0064 prev_is_func2 = 0;
0065 seen_func2_func1 = 0;
0066 seen_kretprobe_trampoline = 0;
0067 unwind_for_each_frame(&state, task, regs, sp) {
0068 unsigned long addr = unwind_get_return_address(&state);
0069 char sym[KSYM_SYMBOL_LEN];
0070
0071 if (frame_count++ == max_frames)
0072 break;
0073 if (state.reliable && !addr) {
0074 kunit_err(current_test, "unwind state reliable but addr is 0\n");
0075 ret = -EINVAL;
0076 break;
0077 }
0078 sprint_symbol(sym, addr);
0079 if (bt_pos < BT_BUF_SIZE) {
0080 bt_pos += snprintf(bt + bt_pos, BT_BUF_SIZE - bt_pos,
0081 state.reliable ? " [%-7s%px] %pSR\n" :
0082 "([%-7s%px] %pSR)\n",
0083 stack_type_name(state.stack_info.type),
0084 (void *)state.sp, (void *)state.ip);
0085 if (bt_pos >= BT_BUF_SIZE)
0086 kunit_err(current_test, "backtrace buffer is too small\n");
0087 }
0088 frame_count += 1;
0089 if (prev_is_func2 && str_has_prefix(sym, "unwindme_func1"))
0090 seen_func2_func1 = 1;
0091 prev_is_func2 = str_has_prefix(sym, "unwindme_func2");
0092 if (str_has_prefix(sym, "__kretprobe_trampoline+0x0/"))
0093 seen_kretprobe_trampoline = 1;
0094 }
0095
0096
0097 if (unwind_error(&state)) {
0098 kunit_err(current_test, "unwind error\n");
0099 ret = -EINVAL;
0100 }
0101 if (!seen_func2_func1) {
0102 kunit_err(current_test, "unwindme_func2 and unwindme_func1 not found\n");
0103 ret = -EINVAL;
0104 }
0105 if (frame_count == max_frames) {
0106 kunit_err(current_test, "Maximum number of frames exceeded\n");
0107 ret = -EINVAL;
0108 }
0109 if (seen_kretprobe_trampoline) {
0110 kunit_err(current_test, "__kretprobe_trampoline+0x0 in unwinding results\n");
0111 ret = -EINVAL;
0112 }
0113 if (ret || force_bt)
0114 print_backtrace(bt);
0115 kfree(bt);
0116 return ret;
0117 }
0118
0119
0120 struct unwindme {
0121 int flags;
0122 int ret;
0123 struct task_struct *task;
0124 struct completion task_ready;
0125 wait_queue_head_t task_wq;
0126 unsigned long sp;
0127 };
0128
0129 static struct unwindme *unwindme;
0130
0131
0132 #define UWM_DEFAULT 0x0
0133 #define UWM_THREAD 0x1
0134 #define UWM_REGS 0x2
0135 #define UWM_SP 0x4
0136 #define UWM_CALLER 0x8
0137 #define UWM_SWITCH_STACK 0x10
0138 #define UWM_IRQ 0x20
0139 #define UWM_PGM 0x40
0140 #define UWM_KPROBE_ON_FTRACE 0x80
0141 #define UWM_FTRACE 0x100
0142 #define UWM_KRETPROBE 0x200
0143 #define UWM_KRETPROBE_HANDLER 0x400
0144
0145 static __always_inline struct pt_regs fake_pt_regs(void)
0146 {
0147 struct pt_regs regs;
0148
0149 memset(®s, 0, sizeof(regs));
0150 regs.gprs[15] = current_stack_pointer;
0151
0152 asm volatile(
0153 "basr %[psw_addr],0\n"
0154 : [psw_addr] "=d" (regs.psw.addr));
0155 return regs;
0156 }
0157
0158 static int kretprobe_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
0159 {
0160 struct unwindme *u = unwindme;
0161
0162 if (!(u->flags & UWM_KRETPROBE_HANDLER))
0163 return 0;
0164
0165 u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? regs : NULL,
0166 (u->flags & UWM_SP) ? u->sp : 0);
0167
0168 return 0;
0169 }
0170
0171 static noinline notrace int test_unwind_kretprobed_func(struct unwindme *u)
0172 {
0173 struct pt_regs regs;
0174
0175 if (!(u->flags & UWM_KRETPROBE))
0176 return 0;
0177
0178 regs = fake_pt_regs();
0179 return test_unwind(NULL, (u->flags & UWM_REGS) ? ®s : NULL,
0180 (u->flags & UWM_SP) ? u->sp : 0);
0181 }
0182
0183 static noinline int test_unwind_kretprobed_func_caller(struct unwindme *u)
0184 {
0185 return test_unwind_kretprobed_func(u);
0186 }
0187
0188 static int test_unwind_kretprobe(struct unwindme *u)
0189 {
0190 int ret;
0191 struct kretprobe my_kretprobe;
0192
0193 if (!IS_ENABLED(CONFIG_KPROBES))
0194 kunit_skip(current_test, "requires CONFIG_KPROBES");
0195
0196 u->ret = -1;
0197 unwindme = u;
0198
0199 memset(&my_kretprobe, 0, sizeof(my_kretprobe));
0200 my_kretprobe.handler = kretprobe_ret_handler;
0201 my_kretprobe.maxactive = 1;
0202 my_kretprobe.kp.addr = (kprobe_opcode_t *)test_unwind_kretprobed_func;
0203
0204 ret = register_kretprobe(&my_kretprobe);
0205
0206 if (ret < 0) {
0207 kunit_err(current_test, "register_kretprobe failed %d\n", ret);
0208 return -EINVAL;
0209 }
0210
0211 ret = test_unwind_kretprobed_func_caller(u);
0212 unregister_kretprobe(&my_kretprobe);
0213 unwindme = NULL;
0214 if (u->flags & UWM_KRETPROBE_HANDLER)
0215 ret = u->ret;
0216 return ret;
0217 }
0218
0219 static int kprobe_pre_handler(struct kprobe *p, struct pt_regs *regs)
0220 {
0221 struct unwindme *u = unwindme;
0222
0223 u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? regs : NULL,
0224 (u->flags & UWM_SP) ? u->sp : 0);
0225 return 0;
0226 }
0227
0228 extern const char test_unwind_kprobed_insn[];
0229
0230 static noinline void test_unwind_kprobed_func(void)
0231 {
0232 asm volatile(
0233 " nopr %%r7\n"
0234 "test_unwind_kprobed_insn:\n"
0235 " nopr %%r7\n"
0236 :);
0237 }
0238
0239 static int test_unwind_kprobe(struct unwindme *u)
0240 {
0241 struct kprobe kp;
0242 int ret;
0243
0244 if (!IS_ENABLED(CONFIG_KPROBES))
0245 kunit_skip(current_test, "requires CONFIG_KPROBES");
0246 if (!IS_ENABLED(CONFIG_KPROBES_ON_FTRACE) && u->flags & UWM_KPROBE_ON_FTRACE)
0247 kunit_skip(current_test, "requires CONFIG_KPROBES_ON_FTRACE");
0248
0249 u->ret = -1;
0250 unwindme = u;
0251 memset(&kp, 0, sizeof(kp));
0252 kp.pre_handler = kprobe_pre_handler;
0253 kp.addr = u->flags & UWM_KPROBE_ON_FTRACE ?
0254 (kprobe_opcode_t *)test_unwind_kprobed_func :
0255 (kprobe_opcode_t *)test_unwind_kprobed_insn;
0256 ret = register_kprobe(&kp);
0257 if (ret < 0) {
0258 kunit_err(current_test, "register_kprobe failed %d\n", ret);
0259 return -EINVAL;
0260 }
0261
0262 test_unwind_kprobed_func();
0263 unregister_kprobe(&kp);
0264 unwindme = NULL;
0265 return u->ret;
0266 }
0267
0268 static void notrace __used test_unwind_ftrace_handler(unsigned long ip,
0269 unsigned long parent_ip,
0270 struct ftrace_ops *fops,
0271 struct ftrace_regs *fregs)
0272 {
0273 struct unwindme *u = (struct unwindme *)fregs->regs.gprs[2];
0274
0275 u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? &fregs->regs : NULL,
0276 (u->flags & UWM_SP) ? u->sp : 0);
0277 }
0278
0279 static noinline int test_unwind_ftraced_func(struct unwindme *u)
0280 {
0281 return READ_ONCE(u)->ret;
0282 }
0283
0284 static int test_unwind_ftrace(struct unwindme *u)
0285 {
0286 int ret;
0287 #ifdef CONFIG_DYNAMIC_FTRACE
0288 struct ftrace_ops *fops;
0289
0290 fops = kunit_kzalloc(current_test, sizeof(*fops), GFP_KERNEL);
0291 fops->func = test_unwind_ftrace_handler;
0292 fops->flags = FTRACE_OPS_FL_DYNAMIC |
0293 FTRACE_OPS_FL_RECURSION |
0294 FTRACE_OPS_FL_SAVE_REGS |
0295 FTRACE_OPS_FL_PERMANENT;
0296 #else
0297 kunit_skip(current_test, "requires CONFIG_DYNAMIC_FTRACE");
0298 #endif
0299
0300 ret = ftrace_set_filter_ip(fops, (unsigned long)test_unwind_ftraced_func, 0, 0);
0301 if (ret) {
0302 kunit_err(current_test, "failed to set ftrace filter (%d)\n", ret);
0303 return -1;
0304 }
0305
0306 ret = register_ftrace_function(fops);
0307 if (!ret) {
0308 ret = test_unwind_ftraced_func(u);
0309 unregister_ftrace_function(fops);
0310 } else {
0311 kunit_err(current_test, "failed to register ftrace handler (%d)\n", ret);
0312 }
0313
0314 ftrace_set_filter_ip(fops, (unsigned long)test_unwind_ftraced_func, 1, 0);
0315 return ret;
0316 }
0317
0318
0319 static noinline int unwindme_func4(struct unwindme *u)
0320 {
0321 if (!(u->flags & UWM_CALLER))
0322 u->sp = current_frame_address();
0323 if (u->flags & UWM_THREAD) {
0324 complete(&u->task_ready);
0325 wait_event(u->task_wq, kthread_should_park());
0326 kthread_parkme();
0327 return 0;
0328 } else if (u->flags & (UWM_PGM | UWM_KPROBE_ON_FTRACE)) {
0329 return test_unwind_kprobe(u);
0330 } else if (u->flags & (UWM_KRETPROBE | UWM_KRETPROBE_HANDLER)) {
0331 return test_unwind_kretprobe(u);
0332 } else if (u->flags & UWM_FTRACE) {
0333 return test_unwind_ftrace(u);
0334 } else {
0335 struct pt_regs regs = fake_pt_regs();
0336
0337 return test_unwind(NULL,
0338 (u->flags & UWM_REGS) ? ®s : NULL,
0339 (u->flags & UWM_SP) ? u->sp : 0);
0340 }
0341 }
0342
0343
0344 static noinline int unwindme_func3(struct unwindme *u)
0345 {
0346 u->sp = current_frame_address();
0347 return unwindme_func4(u);
0348 }
0349
0350
0351 static noinline int unwindme_func2(struct unwindme *u)
0352 {
0353 unsigned long flags;
0354 int rc;
0355
0356 if (u->flags & UWM_SWITCH_STACK) {
0357 local_irq_save(flags);
0358 local_mcck_disable();
0359 rc = call_on_stack(1, S390_lowcore.nodat_stack,
0360 int, unwindme_func3, struct unwindme *, u);
0361 local_mcck_enable();
0362 local_irq_restore(flags);
0363 return rc;
0364 } else {
0365 return unwindme_func3(u);
0366 }
0367 }
0368
0369
0370 static noinline int unwindme_func1(void *u)
0371 {
0372 return unwindme_func2((struct unwindme *)u);
0373 }
0374
0375 static void unwindme_timer_fn(struct timer_list *unused)
0376 {
0377 struct unwindme *u = READ_ONCE(unwindme);
0378
0379 if (u) {
0380 unwindme = NULL;
0381 u->task = NULL;
0382 u->ret = unwindme_func1(u);
0383 complete(&u->task_ready);
0384 }
0385 }
0386
0387 static struct timer_list unwind_timer;
0388
0389 static int test_unwind_irq(struct unwindme *u)
0390 {
0391 unwindme = u;
0392 init_completion(&u->task_ready);
0393 timer_setup(&unwind_timer, unwindme_timer_fn, 0);
0394 mod_timer(&unwind_timer, jiffies + 1);
0395 wait_for_completion(&u->task_ready);
0396 return u->ret;
0397 }
0398
0399
0400 static int test_unwind_task(struct unwindme *u)
0401 {
0402 struct task_struct *task;
0403 int ret;
0404
0405
0406 init_completion(&u->task_ready);
0407 init_waitqueue_head(&u->task_wq);
0408
0409
0410
0411
0412
0413 task = kthread_run(unwindme_func1, u, "%s", __func__);
0414 if (IS_ERR(task)) {
0415 kunit_err(current_test, "kthread_run() failed\n");
0416 return PTR_ERR(task);
0417 }
0418
0419
0420
0421
0422 wait_for_completion(&u->task_ready);
0423 kthread_park(task);
0424
0425 ret = test_unwind(task, NULL, (u->flags & UWM_SP) ? u->sp : 0);
0426 kthread_stop(task);
0427 return ret;
0428 }
0429
0430 struct test_params {
0431 int flags;
0432 char *name;
0433 };
0434
0435
0436
0437
0438 #define TEST_WITH_FLAGS(f) { .flags = f, .name = #f }
0439 static const struct test_params param_list[] = {
0440 TEST_WITH_FLAGS(UWM_DEFAULT),
0441 TEST_WITH_FLAGS(UWM_SP),
0442 TEST_WITH_FLAGS(UWM_REGS),
0443 TEST_WITH_FLAGS(UWM_SWITCH_STACK),
0444 TEST_WITH_FLAGS(UWM_SP | UWM_REGS),
0445 TEST_WITH_FLAGS(UWM_CALLER | UWM_SP),
0446 TEST_WITH_FLAGS(UWM_CALLER | UWM_SP | UWM_REGS),
0447 TEST_WITH_FLAGS(UWM_CALLER | UWM_SP | UWM_REGS | UWM_SWITCH_STACK),
0448 TEST_WITH_FLAGS(UWM_THREAD),
0449 TEST_WITH_FLAGS(UWM_THREAD | UWM_SP),
0450 TEST_WITH_FLAGS(UWM_THREAD | UWM_CALLER | UWM_SP),
0451 TEST_WITH_FLAGS(UWM_IRQ),
0452 TEST_WITH_FLAGS(UWM_IRQ | UWM_SWITCH_STACK),
0453 TEST_WITH_FLAGS(UWM_IRQ | UWM_SP),
0454 TEST_WITH_FLAGS(UWM_IRQ | UWM_REGS),
0455 TEST_WITH_FLAGS(UWM_IRQ | UWM_SP | UWM_REGS),
0456 TEST_WITH_FLAGS(UWM_IRQ | UWM_CALLER | UWM_SP),
0457 TEST_WITH_FLAGS(UWM_IRQ | UWM_CALLER | UWM_SP | UWM_REGS),
0458 TEST_WITH_FLAGS(UWM_IRQ | UWM_CALLER | UWM_SP | UWM_REGS | UWM_SWITCH_STACK),
0459 TEST_WITH_FLAGS(UWM_PGM),
0460 TEST_WITH_FLAGS(UWM_PGM | UWM_SP),
0461 TEST_WITH_FLAGS(UWM_PGM | UWM_REGS),
0462 TEST_WITH_FLAGS(UWM_PGM | UWM_SP | UWM_REGS),
0463 TEST_WITH_FLAGS(UWM_KPROBE_ON_FTRACE),
0464 TEST_WITH_FLAGS(UWM_KPROBE_ON_FTRACE | UWM_SP),
0465 TEST_WITH_FLAGS(UWM_KPROBE_ON_FTRACE | UWM_REGS),
0466 TEST_WITH_FLAGS(UWM_KPROBE_ON_FTRACE | UWM_SP | UWM_REGS),
0467 TEST_WITH_FLAGS(UWM_FTRACE),
0468 TEST_WITH_FLAGS(UWM_FTRACE | UWM_SP),
0469 TEST_WITH_FLAGS(UWM_FTRACE | UWM_REGS),
0470 TEST_WITH_FLAGS(UWM_FTRACE | UWM_SP | UWM_REGS),
0471 TEST_WITH_FLAGS(UWM_KRETPROBE),
0472 TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP),
0473 TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_REGS),
0474 TEST_WITH_FLAGS(UWM_KRETPROBE | UWM_SP | UWM_REGS),
0475 TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER),
0476 TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_SP),
0477 TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_REGS),
0478 TEST_WITH_FLAGS(UWM_KRETPROBE_HANDLER | UWM_SP | UWM_REGS),
0479 };
0480
0481
0482
0483
0484 static void get_desc(const struct test_params *params, char *desc)
0485 {
0486 strscpy(desc, params->name, KUNIT_PARAM_DESC_SIZE);
0487 }
0488
0489
0490
0491
0492 KUNIT_ARRAY_PARAM(test_unwind, param_list, get_desc);
0493
0494 static void test_unwind_flags(struct kunit *test)
0495 {
0496 struct unwindme u;
0497 const struct test_params *params;
0498
0499 current_test = test;
0500 params = (const struct test_params *)test->param_value;
0501 u.flags = params->flags;
0502 if (u.flags & UWM_THREAD)
0503 KUNIT_EXPECT_EQ(test, 0, test_unwind_task(&u));
0504 else if (u.flags & UWM_IRQ)
0505 KUNIT_EXPECT_EQ(test, 0, test_unwind_irq(&u));
0506 else
0507 KUNIT_EXPECT_EQ(test, 0, unwindme_func1(&u));
0508 }
0509
0510 static struct kunit_case unwind_test_cases[] = {
0511 KUNIT_CASE_PARAM(test_unwind_flags, test_unwind_gen_params),
0512 {}
0513 };
0514
0515 static struct kunit_suite test_unwind_suite = {
0516 .name = "test_unwind",
0517 .test_cases = unwind_test_cases,
0518 };
0519
0520 kunit_test_suites(&test_unwind_suite);
0521
0522 MODULE_LICENSE("GPL");