cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kprobe_event_gen_test.c (5777B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Test module for in-kernel kprobe event creation and generation.
      4 *
      5 * Copyright (C) 2019 Tom Zanussi <zanussi@kernel.org>
      6 */
      7
      8#include <linux/module.h>
      9#include <linux/trace_events.h>
     10
     11/*
     12 * This module is a simple test of basic functionality for in-kernel
     13 * kprobe/kretprobe event creation.  The first test uses
     14 * kprobe_event_gen_cmd_start(), kprobe_event_add_fields() and
     15 * kprobe_event_gen_cmd_end() to create a kprobe event, which is then
     16 * enabled in order to generate trace output.  The second creates a
     17 * kretprobe event using kretprobe_event_gen_cmd_start() and
     18 * kretprobe_event_gen_cmd_end(), and is also then enabled.
     19 *
     20 * To test, select CONFIG_KPROBE_EVENT_GEN_TEST and build the module.
     21 * Then:
     22 *
     23 * # insmod kernel/trace/kprobe_event_gen_test.ko
     24 * # cat /sys/kernel/debug/tracing/trace
     25 *
     26 * You should see many instances of the "gen_kprobe_test" and
     27 * "gen_kretprobe_test" events in the trace buffer.
     28 *
     29 * To remove the events, remove the module:
     30 *
     31 * # rmmod kprobe_event_gen_test
     32 *
     33 */
     34
     35static struct trace_event_file *gen_kprobe_test;
     36static struct trace_event_file *gen_kretprobe_test;
     37
     38/*
     39 * Test to make sure we can create a kprobe event, then add more
     40 * fields.
     41 */
     42static int __init test_gen_kprobe_cmd(void)
     43{
     44	struct dynevent_cmd cmd;
     45	char *buf;
     46	int ret;
     47
     48	/* Create a buffer to hold the generated command */
     49	buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
     50	if (!buf)
     51		return -ENOMEM;
     52
     53	/* Before generating the command, initialize the cmd object */
     54	kprobe_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN);
     55
     56	/*
     57	 * Define the gen_kprobe_test event with the first 2 kprobe
     58	 * fields.
     59	 */
     60	ret = kprobe_event_gen_cmd_start(&cmd, "gen_kprobe_test",
     61					 "do_sys_open",
     62					 "dfd=%ax", "filename=%dx");
     63	if (ret)
     64		goto free;
     65
     66	/* Use kprobe_event_add_fields to add the rest of the fields */
     67
     68	ret = kprobe_event_add_fields(&cmd, "flags=%cx", "mode=+4($stack)");
     69	if (ret)
     70		goto free;
     71
     72	/*
     73	 * This actually creates the event.
     74	 */
     75	ret = kprobe_event_gen_cmd_end(&cmd);
     76	if (ret)
     77		goto free;
     78
     79	/*
     80	 * Now get the gen_kprobe_test event file.  We need to prevent
     81	 * the instance and event from disappearing from underneath
     82	 * us, which trace_get_event_file() does (though in this case
     83	 * we're using the top-level instance which never goes away).
     84	 */
     85	gen_kprobe_test = trace_get_event_file(NULL, "kprobes",
     86					       "gen_kprobe_test");
     87	if (IS_ERR(gen_kprobe_test)) {
     88		ret = PTR_ERR(gen_kprobe_test);
     89		goto delete;
     90	}
     91
     92	/* Enable the event or you won't see anything */
     93	ret = trace_array_set_clr_event(gen_kprobe_test->tr,
     94					"kprobes", "gen_kprobe_test", true);
     95	if (ret) {
     96		trace_put_event_file(gen_kprobe_test);
     97		goto delete;
     98	}
     99 out:
    100	return ret;
    101 delete:
    102	/* We got an error after creating the event, delete it */
    103	ret = kprobe_event_delete("gen_kprobe_test");
    104 free:
    105	kfree(buf);
    106
    107	goto out;
    108}
    109
    110/*
    111 * Test to make sure we can create a kretprobe event.
    112 */
    113static int __init test_gen_kretprobe_cmd(void)
    114{
    115	struct dynevent_cmd cmd;
    116	char *buf;
    117	int ret;
    118
    119	/* Create a buffer to hold the generated command */
    120	buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
    121	if (!buf)
    122		return -ENOMEM;
    123
    124	/* Before generating the command, initialize the cmd object */
    125	kprobe_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN);
    126
    127	/*
    128	 * Define the kretprobe event.
    129	 */
    130	ret = kretprobe_event_gen_cmd_start(&cmd, "gen_kretprobe_test",
    131					    "do_sys_open",
    132					    "$retval");
    133	if (ret)
    134		goto free;
    135
    136	/*
    137	 * This actually creates the event.
    138	 */
    139	ret = kretprobe_event_gen_cmd_end(&cmd);
    140	if (ret)
    141		goto free;
    142
    143	/*
    144	 * Now get the gen_kretprobe_test event file.  We need to
    145	 * prevent the instance and event from disappearing from
    146	 * underneath us, which trace_get_event_file() does (though in
    147	 * this case we're using the top-level instance which never
    148	 * goes away).
    149	 */
    150	gen_kretprobe_test = trace_get_event_file(NULL, "kprobes",
    151						  "gen_kretprobe_test");
    152	if (IS_ERR(gen_kretprobe_test)) {
    153		ret = PTR_ERR(gen_kretprobe_test);
    154		goto delete;
    155	}
    156
    157	/* Enable the event or you won't see anything */
    158	ret = trace_array_set_clr_event(gen_kretprobe_test->tr,
    159					"kprobes", "gen_kretprobe_test", true);
    160	if (ret) {
    161		trace_put_event_file(gen_kretprobe_test);
    162		goto delete;
    163	}
    164 out:
    165	return ret;
    166 delete:
    167	/* We got an error after creating the event, delete it */
    168	ret = kprobe_event_delete("gen_kretprobe_test");
    169 free:
    170	kfree(buf);
    171
    172	goto out;
    173}
    174
    175static int __init kprobe_event_gen_test_init(void)
    176{
    177	int ret;
    178
    179	ret = test_gen_kprobe_cmd();
    180	if (ret)
    181		return ret;
    182
    183	ret = test_gen_kretprobe_cmd();
    184	if (ret) {
    185		WARN_ON(trace_array_set_clr_event(gen_kretprobe_test->tr,
    186						  "kprobes",
    187						  "gen_kretprobe_test", false));
    188		trace_put_event_file(gen_kretprobe_test);
    189		WARN_ON(kprobe_event_delete("gen_kretprobe_test"));
    190	}
    191
    192	return ret;
    193}
    194
    195static void __exit kprobe_event_gen_test_exit(void)
    196{
    197	/* Disable the event or you can't remove it */
    198	WARN_ON(trace_array_set_clr_event(gen_kprobe_test->tr,
    199					  "kprobes",
    200					  "gen_kprobe_test", false));
    201
    202	/* Now give the file and instance back */
    203	trace_put_event_file(gen_kprobe_test);
    204
    205	/* Now unregister and free the event */
    206	WARN_ON(kprobe_event_delete("gen_kprobe_test"));
    207
    208	/* Disable the event or you can't remove it */
    209	WARN_ON(trace_array_set_clr_event(gen_kprobe_test->tr,
    210					  "kprobes",
    211					  "gen_kretprobe_test", false));
    212
    213	/* Now give the file and instance back */
    214	trace_put_event_file(gen_kretprobe_test);
    215
    216	/* Now unregister and free the event */
    217	WARN_ON(kprobe_event_delete("gen_kretprobe_test"));
    218}
    219
    220module_init(kprobe_event_gen_test_init)
    221module_exit(kprobe_event_gen_test_exit)
    222
    223MODULE_AUTHOR("Tom Zanussi");
    224MODULE_DESCRIPTION("kprobe event generation test");
    225MODULE_LICENSE("GPL v2");