Skip to content

Commit 1f0ab40

Browse files
Ananth N Mavinakayanahallifweisbec
authored andcommitted
kprobes: Prevent re-registration of the same kprobe
Prevent re-registration of the same kprobe. This situation, though unlikely, needs to be flagged since it can lead to a system crash if it's not handled. The core change itself is small, but the helper routine needed to be moved around a bit; hence the diffstat. Signed-off-by: Ananth N Mavinakayanahalli<ananth@in.ibm.com> Acked-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Jason Baron <jbaron@redhat.com> Cc: K.Prasad <prasad@linux.vnet.ibm.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <20090915051307.GB26458@in.ibm.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
1 parent 5a0d905 commit 1f0ab40

File tree

1 file changed

+38
-20
lines changed

1 file changed

+38
-20
lines changed

kernel/kprobes.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,40 @@ static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
676676
return (kprobe_opcode_t *)(((char *)addr) + p->offset);
677677
}
678678

679+
/* Check passed kprobe is valid and return kprobe in kprobe_table. */
680+
static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
681+
{
682+
struct kprobe *old_p, *list_p;
683+
684+
old_p = get_kprobe(p->addr);
685+
if (unlikely(!old_p))
686+
return NULL;
687+
688+
if (p != old_p) {
689+
list_for_each_entry_rcu(list_p, &old_p->list, list)
690+
if (list_p == p)
691+
/* kprobe p is a valid probe */
692+
goto valid;
693+
return NULL;
694+
}
695+
valid:
696+
return old_p;
697+
}
698+
699+
/* Return error if the kprobe is being re-registered */
700+
static inline int check_kprobe_rereg(struct kprobe *p)
701+
{
702+
int ret = 0;
703+
struct kprobe *old_p;
704+
705+
mutex_lock(&kprobe_mutex);
706+
old_p = __get_valid_kprobe(p);
707+
if (old_p)
708+
ret = -EINVAL;
709+
mutex_unlock(&kprobe_mutex);
710+
return ret;
711+
}
712+
679713
int __kprobes register_kprobe(struct kprobe *p)
680714
{
681715
int ret = 0;
@@ -688,6 +722,10 @@ int __kprobes register_kprobe(struct kprobe *p)
688722
return -EINVAL;
689723
p->addr = addr;
690724

725+
ret = check_kprobe_rereg(p);
726+
if (ret)
727+
return ret;
728+
691729
preempt_disable();
692730
if (!kernel_text_address((unsigned long) p->addr) ||
693731
in_kprobes_functions((unsigned long) p->addr)) {
@@ -757,26 +795,6 @@ int __kprobes register_kprobe(struct kprobe *p)
757795
}
758796
EXPORT_SYMBOL_GPL(register_kprobe);
759797

760-
/* Check passed kprobe is valid and return kprobe in kprobe_table. */
761-
static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
762-
{
763-
struct kprobe *old_p, *list_p;
764-
765-
old_p = get_kprobe(p->addr);
766-
if (unlikely(!old_p))
767-
return NULL;
768-
769-
if (p != old_p) {
770-
list_for_each_entry_rcu(list_p, &old_p->list, list)
771-
if (list_p == p)
772-
/* kprobe p is a valid probe */
773-
goto valid;
774-
return NULL;
775-
}
776-
valid:
777-
return old_p;
778-
}
779-
780798
/*
781799
* Unregister a kprobe without a scheduler synchronization.
782800
*/

0 commit comments

Comments
 (0)