aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/uprobes.h3
-rw-r--r--kernel/events/uprobes.c11
2 files changed, 14 insertions, 0 deletions
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index b0507f24eeb0..06f28beed7c2 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -38,6 +38,8 @@ struct inode;
#define UPROBE_HANDLER_REMOVE 1
#define UPROBE_HANDLER_MASK 1
+#define MAX_URETPROBE_DEPTH 64
+
enum uprobe_filter_ctx {
UPROBE_FILTER_REGISTER,
UPROBE_FILTER_UNREGISTER,
@@ -72,6 +74,7 @@ struct uprobe_task {
struct arch_uprobe_task autask;
struct return_instance *return_instances;
+ unsigned int depth;
struct uprobe *active_uprobe;
unsigned long xol_vaddr;
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 65429ad2ce51..6ab00e090c87 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1404,6 +1404,13 @@ static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
if (!utask)
return;
+ if (utask->depth >= MAX_URETPROBE_DEPTH) {
+ printk_ratelimited(KERN_INFO "uprobe: omit uretprobe due to"
+ " nestedness limit pid/tgid=%d/%d\n",
+ current->pid, current->tgid);
+ return;
+ }
+
ri = kzalloc(sizeof(struct return_instance), GFP_KERNEL);
if (!ri)
goto fail;
@@ -1439,6 +1446,8 @@ static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
ri->orig_ret_vaddr = orig_ret_vaddr;
ri->chained = chained;
+ utask->depth++;
+
/* add instance to the stack */
ri->next = utask->return_instances;
utask->return_instances = ri;
@@ -1681,6 +1690,8 @@ static bool handle_trampoline(struct pt_regs *regs)
if (!chained)
break;
+ utask->depth--;
+
BUG_ON(!ri);
}