hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/arch/x86/kernel/kprobes/opt.c
....@@ -15,6 +15,7 @@
1515 #include <linux/extable.h>
1616 #include <linux/kdebug.h>
1717 #include <linux/kallsyms.h>
18
+#include <linux/kgdb.h>
1819 #include <linux/ftrace.h>
1920 #include <linux/objtool.h>
2021 #include <linux/pgtable.h>
....@@ -45,8 +46,8 @@
4546 /* This function only handles jump-optimized kprobe */
4647 if (kp && kprobe_optimized(kp)) {
4748 op = container_of(kp, struct optimized_kprobe, kp);
48
- /* If op->list is not empty, op is under optimizing */
49
- if (list_empty(&op->list))
49
+ /* If op is optimized or under unoptimizing */
50
+ if (list_empty(&op->list) || optprobe_queued_unopt(op))
5051 goto found;
5152 }
5253 }
....@@ -277,19 +278,6 @@
277278 return ret;
278279 }
279280
280
-static bool is_padding_int3(unsigned long addr, unsigned long eaddr)
281
-{
282
- unsigned char ops;
283
-
284
- for (; addr < eaddr; addr++) {
285
- if (get_kernel_nofault(ops, (void *)addr) < 0 ||
286
- ops != INT3_INSN_OPCODE)
287
- return false;
288
- }
289
-
290
- return true;
291
-}
292
-
293281 /* Decode whole function to ensure any instructions don't jump into target */
294282 static int can_optimize(unsigned long paddr)
295283 {
....@@ -317,6 +305,8 @@
317305 addr = paddr - offset;
318306 while (addr < paddr - offset + size) { /* Decode until function end */
319307 unsigned long recovered_insn;
308
+ int ret;
309
+
320310 if (search_exception_tables(addr))
321311 /*
322312 * Since some fixup code will jumps into this function,
....@@ -326,16 +316,19 @@
326316 recovered_insn = recover_probed_instruction(buf, addr);
327317 if (!recovered_insn)
328318 return 0;
329
- kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
330
- insn_get_length(&insn);
331
- /*
332
- * In the case of detecting unknown breakpoint, this could be
333
- * a padding INT3 between functions. Let's check that all the
334
- * rest of the bytes are also INT3.
335
- */
336
- if (insn.opcode.bytes[0] == INT3_INSN_OPCODE)
337
- return is_padding_int3(addr, paddr - offset + size) ? 1 : 0;
338319
320
+ ret = insn_decode(&insn, (void *)recovered_insn, MAX_INSN_SIZE, INSN_MODE_KERN);
321
+ if (ret < 0)
322
+ return 0;
323
+#ifdef CONFIG_KGDB
324
+ /*
325
+ * If there is a dynamically installed kgdb sw breakpoint,
326
+ * this function should not be probed.
327
+ */
328
+ if (insn.opcode.bytes[0] == INT3_INSN_OPCODE &&
329
+ kgdb_has_hit_break(addr))
330
+ return 0;
331
+#endif
339332 /* Recover address */
340333 insn.kaddr = (void *)addr;
341334 insn.next_byte = (void *)(addr + insn.length);
....@@ -358,7 +351,7 @@
358351
359352 for (i = 1; i < op->optinsn.size; i++) {
360353 p = get_kprobe(op->kp.addr + i);
361
- if (p && !kprobe_disabled(p))
354
+ if (p && !kprobe_disarmed(p))
362355 return -EEXIST;
363356 }
364357