diff options
author | Ravi Bangoria <ravi.bangoria@linux.ibm.com> | 2018-08-20 00:42:48 -0400 |
---|---|---|
committer | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2018-09-24 04:44:54 -0400 |
commit | 22bad38286d9a652d7061a02f9743bb2ebb84e59 (patch) | |
tree | a43f88655fda4bdaf5470133c9b0fd367f22d3f6 | |
parent | 1cc33161a83d20b5462b1e93f95d3ce6388079ee (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.c | 19 |
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 | ||
682 | static void | ||
683 | ref_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 | |||
682 | static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset, | 692 | static 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. |