@@ -2294,13 +2294,58 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
2294
2294
return is_trap_insn (& opcode );
2295
2295
}
2296
2296
2297
+ static struct uprobe * find_active_uprobe_speculative (unsigned long bp_vaddr )
2298
+ {
2299
+ struct mm_struct * mm = current -> mm ;
2300
+ struct uprobe * uprobe = NULL ;
2301
+ struct vm_area_struct * vma ;
2302
+ struct file * vm_file ;
2303
+ loff_t offset ;
2304
+ unsigned int seq ;
2305
+
2306
+ guard (rcu )();
2307
+
2308
+ if (!mmap_lock_speculate_try_begin (mm , & seq ))
2309
+ return NULL ;
2310
+
2311
+ vma = vma_lookup (mm , bp_vaddr );
2312
+ if (!vma )
2313
+ return NULL ;
2314
+
2315
+ /*
2316
+ * vm_file memory can be reused for another instance of struct file,
2317
+ * but can't be freed from under us, so it's safe to read fields from
2318
+ * it, even if the values are some garbage values; ultimately
2319
+ * find_uprobe_rcu() + mmap_lock_speculation_end() check will ensure
2320
+ * that whatever we speculatively found is correct
2321
+ */
2322
+ vm_file = READ_ONCE (vma -> vm_file );
2323
+ if (!vm_file )
2324
+ return NULL ;
2325
+
2326
+ offset = (loff_t )(vma -> vm_pgoff << PAGE_SHIFT ) + (bp_vaddr - vma -> vm_start );
2327
+ uprobe = find_uprobe_rcu (vm_file -> f_inode , offset );
2328
+ if (!uprobe )
2329
+ return NULL ;
2330
+
2331
+ /* now double check that nothing about MM changed */
2332
+ if (mmap_lock_speculate_retry (mm , seq ))
2333
+ return NULL ;
2334
+
2335
+ return uprobe ;
2336
+ }
2337
+
2297
2338
/* assumes being inside RCU protected region */
2298
2339
static struct uprobe * find_active_uprobe_rcu (unsigned long bp_vaddr , int * is_swbp )
2299
2340
{
2300
2341
struct mm_struct * mm = current -> mm ;
2301
2342
struct uprobe * uprobe = NULL ;
2302
2343
struct vm_area_struct * vma ;
2303
2344
2345
+ uprobe = find_active_uprobe_speculative (bp_vaddr );
2346
+ if (uprobe )
2347
+ return uprobe ;
2348
+
2304
2349
mmap_read_lock (mm );
2305
2350
vma = vma_lookup (mm , bp_vaddr );
2306
2351
if (vma ) {
0 commit comments