aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRavi Bangoria <ravi.bangoria@linux.ibm.com>2018-08-20 00:42:48 -0400
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2018-09-24 04:44:54 -0400
commit22bad38286d9a652d7061a02f9743bb2ebb84e59 (patch)
treea43f88655fda4bdaf5470133c9b0fd367f22d3f6
parent1cc33161a83d20b5462b1e93f95d3ce6388079ee (diff)
uprobes/sdt: Prevent multiple reference counter for same uprobe
We assume to have only one reference counter for one uprobe. Don't allow user to register multiple uprobes having same inode+offset but different reference counter. Link: http://lkml.kernel.org/r/20180820044250.11659-3-ravi.bangoria@linux.ibm.com Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Song Liu <songliubraving@fb.com> Tested-by: Song Liu <songliubraving@fb.com> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
-rw-r--r--kernel/events/uprobes.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 934feb39f6be..96fb51f3994f 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -679,6 +679,16 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe)
679 return u; 679 return u;
680} 680}
681 681
682static void
683ref_ctr_mismatch_warn(struct uprobe *cur_uprobe, struct uprobe *uprobe)
684{
685 pr_warn("ref_ctr_offset mismatch. inode: 0x%lx offset: 0x%llx "
686 "ref_ctr_offset(old): 0x%llx ref_ctr_offset(new): 0x%llx\n",
687 uprobe->inode->i_ino, (unsigned long long) uprobe->offset,
688 (unsigned long long) cur_uprobe->ref_ctr_offset,
689 (unsigned long long) uprobe->ref_ctr_offset);
690}
691
682static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset, 692static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset,
683 loff_t ref_ctr_offset) 693 loff_t ref_ctr_offset)
684{ 694{
@@ -698,6 +708,12 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset,
698 cur_uprobe = insert_uprobe(uprobe); 708 cur_uprobe = insert_uprobe(uprobe);
699 /* a uprobe exists for this inode:offset combination */ 709 /* a uprobe exists for this inode:offset combination */
700 if (cur_uprobe) { 710 if (cur_uprobe) {
711 if (cur_uprobe->ref_ctr_offset != uprobe->ref_ctr_offset) {
712 ref_ctr_mismatch_warn(cur_uprobe, uprobe);
713 put_uprobe(cur_uprobe);
714 kfree(uprobe);
715 return ERR_PTR(-EINVAL);
716 }
701 kfree(uprobe); 717 kfree(uprobe);
702 uprobe = cur_uprobe; 718 uprobe = cur_uprobe;
703 } 719 }
@@ -1112,6 +1128,9 @@ static int __uprobe_register(struct inode *inode, loff_t offset,
1112 uprobe = alloc_uprobe(inode, offset, ref_ctr_offset); 1128 uprobe = alloc_uprobe(inode, offset, ref_ctr_offset);
1113 if (!uprobe) 1129 if (!uprobe)
1114 return -ENOMEM; 1130 return -ENOMEM;
1131 if (IS_ERR(uprobe))
1132 return PTR_ERR(uprobe);
1133
1115 /* 1134 /*
1116 * We can race with uprobe_unregister()->delete_uprobe(). 1135 * We can race with uprobe_unregister()->delete_uprobe().
1117 * Check uprobe_is_active() and retry if it is false. 1136 * Check uprobe_is_active() and retry if it is false.