diff options
author | Oleg Nesterov <oleg@redhat.com> | 2015-07-21 09:40:23 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-07-31 04:38:05 -0400 |
commit | a5b7e1a89b820f2b9b23634ca4c59b555e8d9a0d (patch) | |
tree | 6c15eed109c9cc8982f428dc2d8a6b56b7aeb5fc /kernel/events/uprobes.c | |
parent | 5eeb50de42fd3251845d03c556db012267c72b3f (diff) |
uprobes: Change prepare_uretprobe() to (try to) flush the dead frames
Change prepare_uretprobe() to flush the !arch_uretprobe_is_alive()
return_instance's. This is not needed correctness-wise, but can help
to avoid the failure caused by MAX_URETPROBE_DEPTH.
Note: in this case arch_uretprobe_is_alive() can be false
positive, the stack can grow after longjmp(). Unfortunately, the
kernel can't 100% solve this problem, but see the next patch.
Tested-by: Pratyush Anand <panand@redhat.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Acked-by: Anton Arapov <arapov@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20150721134023.GA4776@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events/uprobes.c')
-rw-r--r-- | kernel/events/uprobes.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 93d939c80cd9..7e61c8ca27e0 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1511,6 +1511,16 @@ static unsigned long get_trampoline_vaddr(void) | |||
1511 | return trampoline_vaddr; | 1511 | return trampoline_vaddr; |
1512 | } | 1512 | } |
1513 | 1513 | ||
1514 | static void cleanup_return_instances(struct uprobe_task *utask, struct pt_regs *regs) | ||
1515 | { | ||
1516 | struct return_instance *ri = utask->return_instances; | ||
1517 | while (ri && !arch_uretprobe_is_alive(ri, regs)) { | ||
1518 | ri = free_ret_instance(ri); | ||
1519 | utask->depth--; | ||
1520 | } | ||
1521 | utask->return_instances = ri; | ||
1522 | } | ||
1523 | |||
1514 | static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs) | 1524 | static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs) |
1515 | { | 1525 | { |
1516 | struct return_instance *ri; | 1526 | struct return_instance *ri; |
@@ -1541,6 +1551,9 @@ static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs) | |||
1541 | if (orig_ret_vaddr == -1) | 1551 | if (orig_ret_vaddr == -1) |
1542 | goto fail; | 1552 | goto fail; |
1543 | 1553 | ||
1554 | /* drop the entries invalidated by longjmp() */ | ||
1555 | cleanup_return_instances(utask, regs); | ||
1556 | |||
1544 | /* | 1557 | /* |
1545 | * We don't want to keep trampoline address in stack, rather keep the | 1558 | * We don't want to keep trampoline address in stack, rather keep the |
1546 | * original return address of first caller thru all the consequent | 1559 | * original return address of first caller thru all the consequent |