Commit 2b79eb73 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull kprobes updates from Masami Hiramatsu:

 - Skip negative return code check for snprintf in eprobe

 - Add recursive call test cases for kprobe unit test

 - Add 'char' type to probe events to show it as the character instead
   of value

 - Update kselftest kprobe-event testcase to ignore '__pfx_' symbols

 - Fix kselftest to check filter on eprobe event correctly

 - Add filter on eprobe to the README file in tracefs

 - Fix optprobes to check whether there is 'under unoptimizing' optprobe
   when optimizing another kprobe correctly

 - Fix optprobe to check whether there is 'under unoptimizing' optprobe
   when fetching the original instruction correctly

 - Fix optprobe to free 'forcibly unoptimized' optprobe correctly

* tag 'probes-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  tracing/eprobe: no need to check for negative ret value for snprintf
  test_kprobes: Add recursed kprobe test case
  tracing/probe: add a char type to show the character value of traced arguments
  selftests/ftrace: Fix probepoint testcase to ignore __pfx_* symbols
  selftests/ftrace: Fix eprobe syntax test case to check filter support
  tracing/eprobe: Fix to add filter on eprobe description in README file
  x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range
  x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
  kprobes: Fix to handle forcibly unoptimized kprobes on freeing_list
parents 0df82189 c96abaec
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -58,7 +58,7 @@ Synopsis of kprobe_events
  NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
  NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
  FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
  FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
		  (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
		  (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
		  (x8/x16/x32/x64), "string", "ustring", "symbol", "symstr"
		  (x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr"
                  and bitfield are supported.
                  and bitfield are supported.


  (\*1) only for the probe on function entry (offs == 0).
  (\*1) only for the probe on function entry (offs == 0).
@@ -82,6 +82,8 @@ Note that the array can be applied to memory type fetchargs, you can not
apply it to registers/stack-entries etc. (for example, '$stack1:x8[8]' is
apply it to registers/stack-entries etc. (for example, '$stack1:x8[8]' is
wrong, but '+8($stack):x8[8]' is OK.)
wrong, but '+8($stack):x8[8]' is OK.)


Char type can be used to show the character value of traced arguments.

String type is a special type, which fetches a "null-terminated" string from
String type is a special type, which fetches a "null-terminated" string from
kernel space. This means it will fail and store NULL if the string container
kernel space. This means it will fail and store NULL if the string container
has been paged out. "ustring" type is an alternative of string for user-space.
has been paged out. "ustring" type is an alternative of string for user-space.
+3 −3
Original line number Original line Diff line number Diff line
@@ -46,8 +46,8 @@ unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
		/* This function only handles jump-optimized kprobe */
		/* This function only handles jump-optimized kprobe */
		if (kp && kprobe_optimized(kp)) {
		if (kp && kprobe_optimized(kp)) {
			op = container_of(kp, struct optimized_kprobe, kp);
			op = container_of(kp, struct optimized_kprobe, kp);
			/* If op->list is not empty, op is under optimizing */
			/* If op is optimized or under unoptimizing */
			if (list_empty(&op->list))
			if (list_empty(&op->list) || optprobe_queued_unopt(op))
				goto found;
				goto found;
		}
		}
	}
	}
@@ -353,7 +353,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe *op)


	for (i = 1; i < op->optinsn.size; i++) {
	for (i = 1; i < op->optinsn.size; i++) {
		p = get_kprobe(op->kp.addr + i);
		p = get_kprobe(op->kp.addr + i);
		if (p && !kprobe_disabled(p))
		if (p && !kprobe_disarmed(p))
			return -EEXIST;
			return -EEXIST;
	}
	}


+2 −0
Original line number Original line Diff line number Diff line
@@ -378,6 +378,8 @@ extern void opt_pre_handler(struct kprobe *p, struct pt_regs *regs);
DEFINE_INSN_CACHE_OPS(optinsn);
DEFINE_INSN_CACHE_OPS(optinsn);


extern void wait_for_kprobe_optimizer(void);
extern void wait_for_kprobe_optimizer(void);
bool optprobe_queued_unopt(struct optimized_kprobe *op);
bool kprobe_disarmed(struct kprobe *p);
#else /* !CONFIG_OPTPROBES */
#else /* !CONFIG_OPTPROBES */
static inline void wait_for_kprobe_optimizer(void) { }
static inline void wait_for_kprobe_optimizer(void) { }
#endif /* CONFIG_OPTPROBES */
#endif /* CONFIG_OPTPROBES */
+12 −15
Original line number Original line Diff line number Diff line
@@ -458,7 +458,7 @@ static inline int kprobe_optready(struct kprobe *p)
}
}


/* Return true if the kprobe is disarmed. Note: p must be on hash list */
/* Return true if the kprobe is disarmed. Note: p must be on hash list */
static inline bool kprobe_disarmed(struct kprobe *p)
bool kprobe_disarmed(struct kprobe *p)
{
{
	struct optimized_kprobe *op;
	struct optimized_kprobe *op;


@@ -555,17 +555,15 @@ static void do_unoptimize_kprobes(void)
	/* See comment in do_optimize_kprobes() */
	/* See comment in do_optimize_kprobes() */
	lockdep_assert_cpus_held();
	lockdep_assert_cpus_held();


	/* Unoptimization must be done anytime */
	if (!list_empty(&unoptimizing_list))
	if (list_empty(&unoptimizing_list))
		return;

		arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list);
		arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list);
	/* Loop on 'freeing_list' for disarming */

	/* Loop on 'freeing_list' for disarming and removing from kprobe hash list */
	list_for_each_entry_safe(op, tmp, &freeing_list, list) {
	list_for_each_entry_safe(op, tmp, &freeing_list, list) {
		/* Switching from detour code to origin */
		/* Switching from detour code to origin */
		op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
		op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
		/* Disarm probes if marked disabled */
		/* Disarm probes if marked disabled and not gone */
		if (kprobe_disabled(&op->kp))
		if (kprobe_disabled(&op->kp) && !kprobe_gone(&op->kp))
			arch_disarm_kprobe(&op->kp);
			arch_disarm_kprobe(&op->kp);
		if (kprobe_unused(&op->kp)) {
		if (kprobe_unused(&op->kp)) {
			/*
			/*
@@ -662,7 +660,7 @@ void wait_for_kprobe_optimizer(void)
	mutex_unlock(&kprobe_mutex);
	mutex_unlock(&kprobe_mutex);
}
}


static bool optprobe_queued_unopt(struct optimized_kprobe *op)
bool optprobe_queued_unopt(struct optimized_kprobe *op)
{
{
	struct optimized_kprobe *_op;
	struct optimized_kprobe *_op;


@@ -797,14 +795,13 @@ static void kill_optimized_kprobe(struct kprobe *p)
	op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
	op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;


	if (kprobe_unused(p)) {
	if (kprobe_unused(p)) {
		/* Enqueue if it is unused */
		list_add(&op->list, &freeing_list);
		/*
		/*
		 * Remove unused probes from the hash list. After waiting
		 * Unused kprobe is on unoptimizing or freeing list. We move it
		 * for synchronization, this probe is reclaimed.
		 * to freeing_list and let the kprobe_optimizer() remove it from
		 * (reclaiming is done by do_free_cleaned_kprobes().)
		 * the kprobe hash list and free it.
		 */
		 */
		hlist_del_rcu(&op->kp.hlist);
		if (optprobe_queued_unopt(op))
			list_move(&op->list, &freeing_list);
	}
	}


	/* Don't touch the code, because it is already freed. */
	/* Don't touch the code, because it is already freed. */
+2 −2
Original line number Original line Diff line number Diff line
@@ -5646,7 +5646,7 @@ static const char readme_msg[] =
#ifdef CONFIG_HIST_TRIGGERS
#ifdef CONFIG_HIST_TRIGGERS
	"\t           s:[synthetic/]<event> <field> [<field>]\n"
	"\t           s:[synthetic/]<event> <field> [<field>]\n"
#endif
#endif
	"\t           e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]\n"
	"\t           e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>] [if <filter>]\n"
	"\t           -:[<group>/][<event>]\n"
	"\t           -:[<group>/][<event>]\n"
#ifdef CONFIG_KPROBE_EVENTS
#ifdef CONFIG_KPROBE_EVENTS
	"\t    place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
	"\t    place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
@@ -5663,7 +5663,7 @@ static const char readme_msg[] =
	"\t           $stack<index>, $stack, $retval, $comm,\n"
	"\t           $stack<index>, $stack, $retval, $comm,\n"
#endif
#endif
	"\t           +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
	"\t           +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
	"\t     type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
	"\t     type: s8/16/32/64, u8/16/32/64, x8/16/32/64, char, string, symbol,\n"
	"\t           b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
	"\t           b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
	"\t           symstr, <type>\\[<array-size>\\]\n"
	"\t           symstr, <type>\\[<array-size>\\]\n"
#ifdef CONFIG_HIST_TRIGGERS
#ifdef CONFIG_HIST_TRIGGERS
Loading