Commit e8c39d0f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'probes-fixes-v6.9-rc3' of...

Merge tag 'probes-fixes-v6.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull probes fixes from Masami Hiramatsu:
 "Fix possible use-after-free issue on kprobe registration.

  check_kprobe_address_safe() uses `is_module_text_address()` and
  `__module_text_address()` separately.

  As a result, if the probed address is in a module that is being
  unloaded, the first `is_module_text_address()` might return true but
  then the `__module_text_address()` call might return NULL if the
  module has been unloaded between the two.

  The result is that kprobe believes the probe is on the kernel text,
  and skips getting a module reference. In this case, when it arms a
  breakpoint on the probe address, it may cause a use-after-free.

  To fix this issue, only use `__module_text_address()` once and get a
  reference to the module then. If it fails, reject the probe"

* tag 'probes-fixes-v6.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  kprobes: Fix possible use-after-free issue on kprobe registration
parents 03a55b63 325f3fb5
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -1567,10 +1567,17 @@ static int check_kprobe_address_safe(struct kprobe *p,
	jump_label_lock();
	preempt_disable();

	/* Ensure it is not in reserved area nor out of text */
	if (!(core_kernel_text((unsigned long) p->addr) ||
	    is_module_text_address((unsigned long) p->addr)) ||
	    in_gate_area_no_mm((unsigned long) p->addr) ||
	/* Ensure the address is in a text area, and find a module if exists. */
	*probed_mod = NULL;
	if (!core_kernel_text((unsigned long) p->addr)) {
		*probed_mod = __module_text_address((unsigned long) p->addr);
		if (!(*probed_mod)) {
			ret = -EINVAL;
			goto out;
		}
	}
	/* Ensure it is not in reserved area. */
	if (in_gate_area_no_mm((unsigned long) p->addr) ||
	    within_kprobe_blacklist((unsigned long) p->addr) ||
	    jump_label_text_reserved(p->addr, p->addr) ||
	    static_call_text_reserved(p->addr, p->addr) ||
@@ -1580,8 +1587,7 @@ static int check_kprobe_address_safe(struct kprobe *p,
		goto out;
	}

	/* Check if 'p' is probing a module. */
	*probed_mod = __module_text_address((unsigned long) p->addr);
	/* Get module refcount and reject __init functions for loaded modules. */
	if (*probed_mod) {
		/*
		 * We must hold a refcount of the probed module while updating