aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events/uprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/events/uprobes.c')
-rw-r--r--kernel/events/uprobes.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 26bc2e24e9e3..ca9012930ce7 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -173,6 +173,20 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
173 return *insn == UPROBE_SWBP_INSN; 173 return *insn == UPROBE_SWBP_INSN;
174} 174}
175 175
176/**
177 * is_trap_insn - check if instruction is breakpoint instruction.
178 * @insn: instruction to be checked.
179 * Default implementation of is_trap_insn
180 * Returns true if @insn is a breakpoint instruction.
181 *
182 * This function is needed for the case where an architecture has multiple
183 * trap instructions (like powerpc).
184 */
185bool __weak is_trap_insn(uprobe_opcode_t *insn)
186{
187 return is_swbp_insn(insn);
188}
189
176static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode) 190static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode)
177{ 191{
178 void *kaddr = kmap_atomic(page); 192 void *kaddr = kmap_atomic(page);
@@ -185,6 +199,15 @@ static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
185 uprobe_opcode_t old_opcode; 199 uprobe_opcode_t old_opcode;
186 bool is_swbp; 200 bool is_swbp;
187 201
202 /*
203 * Note: We only check if the old_opcode is UPROBE_SWBP_INSN here.
204 * We do not check if it is any other 'trap variant' which could
205 * be conditional trap instruction such as the one powerpc supports.
206 *
207 * The logic is that we do not care if the underlying instruction
208 * is a trap variant; uprobes always wins over any other (gdb)
209 * breakpoint.
210 */
188 copy_opcode(page, vaddr, &old_opcode); 211 copy_opcode(page, vaddr, &old_opcode);
189 is_swbp = is_swbp_insn(&old_opcode); 212 is_swbp = is_swbp_insn(&old_opcode);
190 213
@@ -204,7 +227,7 @@ static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
204 * Expect the breakpoint instruction to be the smallest size instruction for 227 * Expect the breakpoint instruction to be the smallest size instruction for
205 * the architecture. If an arch has variable length instruction and the 228 * the architecture. If an arch has variable length instruction and the
206 * breakpoint instruction is not of the smallest length instruction 229 * breakpoint instruction is not of the smallest length instruction
207 * supported by that architecture then we need to modify is_swbp_at_addr and 230 * supported by that architecture then we need to modify is_trap_at_addr and
208 * write_opcode accordingly. This would never be a problem for archs that 231 * write_opcode accordingly. This would never be a problem for archs that
209 * have fixed length instructions. 232 * have fixed length instructions.
210 */ 233 */
@@ -550,7 +573,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
550 goto out; 573 goto out;
551 574
552 ret = -ENOTSUPP; 575 ret = -ENOTSUPP;
553 if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) 576 if (is_trap_insn((uprobe_opcode_t *)uprobe->arch.insn))
554 goto out; 577 goto out;
555 578
556 ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); 579 ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
@@ -1431,7 +1454,7 @@ static void mmf_recalc_uprobes(struct mm_struct *mm)
1431 clear_bit(MMF_HAS_UPROBES, &mm->flags); 1454 clear_bit(MMF_HAS_UPROBES, &mm->flags);
1432} 1455}
1433 1456
1434static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) 1457static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
1435{ 1458{
1436 struct page *page; 1459 struct page *page;
1437 uprobe_opcode_t opcode; 1460 uprobe_opcode_t opcode;
@@ -1452,7 +1475,8 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
1452 copy_opcode(page, vaddr, &opcode); 1475 copy_opcode(page, vaddr, &opcode);
1453 put_page(page); 1476 put_page(page);
1454 out: 1477 out:
1455 return is_swbp_insn(&opcode); 1478 /* This needs to return true for any variant of the trap insn */
1479 return is_trap_insn(&opcode);
1456} 1480}
1457 1481
1458static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) 1482static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
@@ -1472,7 +1496,7 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
1472 } 1496 }
1473 1497
1474 if (!uprobe) 1498 if (!uprobe)
1475 *is_swbp = is_swbp_at_addr(mm, bp_vaddr); 1499 *is_swbp = is_trap_at_addr(mm, bp_vaddr);
1476 } else { 1500 } else {
1477 *is_swbp = -EFAULT; 1501 *is_swbp = -EFAULT;
1478 } 1502 }