summaryrefslogtreecommitdiffstats
path: root/runtime/uprobes2/uprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/uprobes2/uprobes.c')
-rw-r--r--runtime/uprobes2/uprobes.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c
index af187fc9..07ad3984 100644
--- a/runtime/uprobes2/uprobes.c
+++ b/runtime/uprobes2/uprobes.c
@@ -29,6 +29,12 @@
#include <linux/utrace.h>
#include <linux/regset.h>
#define UPROBES_IMPLEMENTATION 1
+
+/* PR9974: Adapt to struct renaming. */
+#ifdef UTRACE_API_VERSION
+#define utrace_attached_engine utrace_engine
+#endif
+
#include "uprobes.h"
#include <linux/tracehook.h>
#include <linux/mm.h>
@@ -949,10 +955,15 @@ static int defer_registration(struct uprobe *u, int regflag,
*/
static struct pid *uprobe_get_tg_leader(pid_t p)
{
- struct pid *pid;
+ struct pid *pid = NULL;
rcu_read_lock();
- pid = find_vpid(p);
+ /*
+ * We need this check because unmap_u[ret]probe() can be called
+ * from a report_death callback, where current->proxy is NULL.
+ */
+ if (current->nsproxy)
+ pid = find_vpid(p);
if (pid) {
struct task_struct *t = pid_task(pid, PIDTYPE_PID);
if (t)
@@ -1132,8 +1143,7 @@ fail_tsk:
}
EXPORT_SYMBOL_GPL(register_uprobe);
-/* See Documentation/uprobes.txt. */
-void unregister_uprobe(struct uprobe *u)
+void __unregister_uprobe(struct uprobe *u, bool remove_bkpt)
{
struct pid *p;
struct uprobe_process *uproc;
@@ -1187,10 +1197,13 @@ void unregister_uprobe(struct uprobe *u)
if (!list_empty(&ppt->uprobe_list))
goto done;
- /*
- * The last uprobe at ppt's probepoint is being unregistered.
- * Queue the breakpoint for removal.
- */
+ /* The last uprobe at ppt's probepoint is being unregistered. */
+ if (!remove_bkpt) {
+ uprobe_free_probept(ppt);
+ goto done;
+ }
+
+ /* Queue the breakpoint for removal. */
ppt->state = UPROBE_REMOVING;
list_add_tail(&ppt->pd_node, &uproc->pending_uprobes);
@@ -1215,8 +1228,20 @@ done:
up_write(&uproc->rwsem);
uprobe_put_process(uproc, false);
}
+
+/* See Documentation/uprobes.txt. */
+void unregister_uprobe(struct uprobe *u)
+{
+ __unregister_uprobe(u, true);
+}
EXPORT_SYMBOL_GPL(unregister_uprobe);
+void unmap_uprobe(struct uprobe *u)
+{
+ __unregister_uprobe(u, false);
+}
+EXPORT_SYMBOL_GPL(unmap_uprobe);
+
/* Find a surviving thread in uproc. Runs with uproc->rwsem locked. */
static struct task_struct *find_surviving_thread(struct uprobe_process *uproc)
{
@@ -2214,7 +2239,8 @@ static u32 uprobe_report_exit(enum utrace_resume_action action,
}
}
up_read(&uproc->rwsem);
- if (utask->state == UPTASK_TRAMPOLINE_HIT)
+ if (utask->state == UPTASK_TRAMPOLINE_HIT ||
+ utask->state == UPTASK_BP_HIT)
uprobe_decref_process(uproc);
}
@@ -2712,6 +2738,14 @@ void unregister_uretprobe(struct uretprobe *rp)
}
EXPORT_SYMBOL_GPL(unregister_uretprobe);
+void unmap_uretprobe(struct uretprobe *rp)
+{
+ if (!rp)
+ return;
+ unmap_uprobe(&rp->u);
+}
+EXPORT_SYMBOL_GPL(unmap_uretprobe);
+
/*
* uproc->ssol_area has been successfully set up. Establish the
* uretprobe trampoline in the next available slot following the