1 // SPDX-License-Identifier: GPL-2.0 2 #include "aslr.h" 3 4 #include "addr_location.h" 5 #include "debug.h" 6 #include "event.h" 7 #include "evsel.h" 8 #include "evlist.h" 9 #include "machine.h" 10 #include "map.h" 11 #include "thread.h" 12 #include "tool.h" 13 #include "session.h" 14 #include "data.h" 15 #include "dso.h" 16 #include "pmus.h" 17 18 #include <internal/lib.h> /* page_size */ 19 #include <linux/compiler.h> 20 #include <linux/zalloc.h> 21 #include <errno.h> 22 #include <inttypes.h> 23 #include <unistd.h> 24 #include <byteswap.h> 25 26 /** 27 * struct remap_addresses_key - Key for mapping original addresses to remapped ones. 28 * @dso: Pointer to the DSO (Dynamic Shared Object) associated with the mapping. 29 * @invariant: Unique offset invariant within the VMA (Virtual Memory Area). 30 * Calculated as `start - pgoff`. This value remains constant when 31 * perf's internal `maps__fixup_overlap_and_insert` splits a map into 32 * fragmented VMA pieces due to overlapping events, allowing us to 33 * resolve split maps consistently back to the original VMA. 34 * @pid: Process ID associated with the mapping. 35 */ 36 struct remap_addresses_key { 37 struct machine *machine; 38 struct dso *dso; 39 u64 invariant; 40 pid_t pid; 41 }; 42 43 struct aslr_mapping { 44 struct list_head node; 45 u64 orig_start; 46 u64 len; 47 u64 remap_start; 48 }; 49 50 struct aslr_evsel_priv { 51 u64 orig_sample_type; 52 u64 orig_sample_regs_user; 53 u64 orig_sample_regs_intr; 54 int orig_sample_size; 55 }; 56 57 static size_t evsel_hash(long key, void *ctx __maybe_unused) 58 { 59 return (size_t)key; 60 } 61 62 static bool evsel_equal(long key1, long key2, void *ctx __maybe_unused) 63 { 64 return key1 == key2; 65 } 66 67 struct process_top_address { 68 u64 remapped_max; 69 }; 70 struct aslr_tool { 71 /** @tool: The tool implemented here and a pointer to a delegate to process the data. */ 72 struct delegate_tool tool; 73 /** @machines: The machines with the input, not remapped, virtual address layout. */ 74 struct machines machines; 75 /** @event_copy: Buffer used to create an event to pass to the delegate. */ 76 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); 77 /** @remap_addresses: mapping from remap_addresses_key to remapped address. */ 78 struct hashmap remap_addresses; 79 /** @top_addresses: mapping from process to max remapped address. */ 80 struct hashmap top_addresses; 81 /** 82 * @evsel_orig_attrs: mapping from evsel pointer to its original 83 * unstripped sample_type and registers bitmasks. 84 */ 85 struct hashmap evsel_orig_attrs; 86 }; 87 88 static const pid_t kernel_pid = -1; 89 90 /* Start remapping user processes from a small non-zero offset. */ 91 static const u64 user_space_start = 0x200000; 92 static const u64 kernel_space_start_64 = 0xffff800010000000ULL; 93 static const u64 kernel_space_start_32 = 0x80000000ULL; 94 95 static size_t remap_addresses__hash(long _key, void *ctx __maybe_unused) 96 { 97 struct remap_addresses_key *key = (struct remap_addresses_key *)_key; 98 void *dso_ptr = key->dso ? RC_CHK_ACCESS(key->dso) : NULL; 99 100 return (size_t)key->machine ^ (size_t)dso_ptr ^ key->invariant ^ key->pid; 101 } 102 103 static bool remap_addresses__equal(long _key1, long _key2, void *ctx __maybe_unused) 104 { 105 struct remap_addresses_key *key1 = (struct remap_addresses_key *)_key1; 106 struct remap_addresses_key *key2 = (struct remap_addresses_key *)_key2; 107 108 return key1->machine == key2->machine && 109 RC_CHK_EQUAL(key1->dso, key2->dso) && 110 key1->invariant == key2->invariant && 111 key1->pid == key2->pid; 112 } 113 114 struct top_addresses_key { 115 struct machine *machine; 116 pid_t pid; 117 }; 118 119 static size_t top_addresses__hash(long _key, void *ctx __maybe_unused) 120 { 121 struct top_addresses_key *key = (struct top_addresses_key *)_key; 122 123 return (size_t)key->machine ^ key->pid; 124 } 125 126 static bool top_addresses__equal(long _key1, long _key2, void *ctx __maybe_unused) 127 { 128 struct top_addresses_key *key1 = (struct top_addresses_key *)_key1; 129 struct top_addresses_key *key2 = (struct top_addresses_key *)_key2; 130 131 return key1->machine == key2->machine && key1->pid == key2->pid; 132 } 133 134 static u64 round_up_to_page_size(u64 addr) 135 { 136 return (addr + page_size - 1) & ~((u64)page_size - 1); 137 } 138 139 static u64 aslr_tool__remap_address(struct aslr_tool *aslr, 140 struct thread *aslr_thread, 141 u8 cpumode, 142 u64 addr) 143 { 144 struct addr_location al; 145 struct remap_addresses_key key; 146 u64 *remapped_invariant_ptr = NULL; 147 u64 remap_addr = 0; 148 u8 effective_cpumode = cpumode; 149 struct dso *dso; 150 const char *dso_name; 151 152 if (!aslr_thread) 153 return 0; /* No thread. */ 154 155 addr_location__init(&al); 156 if (!thread__find_map(aslr_thread, cpumode, addr, &al)) { 157 /* 158 * If lookup fails with specified cpumode, try fallback to the other space 159 * to be robust against bad cpumode in samples. 160 */ 161 if (cpumode == PERF_RECORD_MISC_KERNEL) 162 effective_cpumode = PERF_RECORD_MISC_USER; 163 else if (cpumode == PERF_RECORD_MISC_USER) 164 effective_cpumode = PERF_RECORD_MISC_KERNEL; 165 else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL) 166 effective_cpumode = PERF_RECORD_MISC_GUEST_USER; 167 else if (cpumode == PERF_RECORD_MISC_GUEST_USER) 168 effective_cpumode = PERF_RECORD_MISC_GUEST_KERNEL; 169 170 if (!thread__find_map(aslr_thread, effective_cpumode, addr, &al)) { 171 addr_location__exit(&al); 172 return 0; /* No mmap. */ 173 } 174 } 175 176 dso = map__dso(al.map); 177 dso_name = dso ? dso__long_name(dso) : NULL; 178 179 key.machine = maps__machine(thread__maps(aslr_thread)); 180 key.dso = dso; 181 if (dso && !is_anon_memory(dso_name) && !is_no_dso_memory(dso_name)) 182 key.invariant = map__start(al.map) - map__pgoff(al.map); 183 else 184 key.invariant = map__start(al.map); 185 key.pid = (effective_cpumode == PERF_RECORD_MISC_KERNEL || 186 effective_cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ? 187 kernel_pid : thread__pid(aslr_thread); 188 189 if (hashmap__find(&aslr->remap_addresses, &key, &remapped_invariant_ptr)) { 190 remap_addr = *remapped_invariant_ptr + map__pgoff(al.map) + 191 (addr - map__start(al.map)); 192 } else { 193 pr_debug("Cannot find a remapped entry for address %" PRIx64 " in mapping %" PRIx64 "(%zu) for pid=%d\n", 194 addr, map__start(al.map), map__size(al.map), key.pid); 195 } 196 197 addr_location__exit(&al); 198 return remap_addr; 199 } 200 201 struct aslr_machine_priv { 202 bool kernel_maps_loaded; 203 }; 204 205 static int aslr_tool__preload_kernel_maps(struct machine *machine) 206 { 207 struct aslr_machine_priv *mpriv = machine->priv; 208 209 if (!mpriv) { 210 mpriv = zalloc(sizeof(*mpriv)); 211 if (!mpriv) 212 return -ENOMEM; 213 machine->priv = mpriv; 214 } 215 216 if (!mpriv->kernel_maps_loaded) { 217 struct maps *kmaps = machine__kernel_maps(machine); 218 219 if (kmaps) { 220 int err = maps__load_maps(kmaps); 221 222 if (err < 0) { 223 pr_err("ASLR: Failed to preload kernel maps for machine pid %d\n", 224 machine->pid); 225 return err; 226 } 227 } 228 mpriv->kernel_maps_loaded = true; 229 } 230 return 0; 231 } 232 233 static void aslr_tool__free_machine_priv(struct machine *machine) 234 { 235 free(machine->priv); 236 machine->priv = NULL; 237 } 238 239 static void aslr_tool__destroy_machines_priv(struct machines *machines) 240 { 241 struct rb_node *nd; 242 243 aslr_tool__free_machine_priv(&machines->host); 244 for (nd = rb_first_cached(&machines->guests); nd; nd = rb_next(nd)) { 245 struct machine *machine = rb_entry(nd, struct machine, rb_node); 246 247 aslr_tool__free_machine_priv(machine); 248 } 249 } 250 251 static u64 aslr_tool__findnew_mapping(struct aslr_tool *aslr, 252 struct machine *session_machine, 253 struct thread *aslr_thread, 254 u8 cpumode, u64 start, 255 u64 len, u64 pgoff) 256 { 257 /* Address location for dso lookup. */ 258 struct addr_location al; 259 /* Original ASLR address based key for the remap table. */ 260 struct remap_addresses_key remap_key; 261 /* The address in the ASLR sanitized address space less pg_off. */ 262 u64 *remapped_invariant_ptr; 263 /* Key for the maximum address in a process. */ 264 struct top_addresses_key top_addr_key; 265 /* Value in top address table. */ 266 struct process_top_address *top = NULL; 267 /* Address in ASLR sanitized address space. */ 268 u64 remap_addr; 269 /* Potentially allocated remap table key. */ 270 struct remap_addresses_key *new_remap_key = NULL; 271 /* 272 * Potentially allocated remap table key. 273 * TODO: Avoid allocation necessary for perf 32-bit binary support. 274 */ 275 u64 *new_remap_val = NULL; 276 int err; 277 278 if (!aslr_thread) 279 return 0; 280 281 /* The key to look up an incoming address to the outgoing value. */ 282 addr_location__init(&al); 283 remap_key.machine = maps__machine(thread__maps(aslr_thread)); 284 remap_key.pid = (cpumode == PERF_RECORD_MISC_KERNEL || 285 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ? 286 kernel_pid : thread__pid(aslr_thread); 287 if (thread__find_map(aslr_thread, cpumode, start, &al)) { 288 struct dso *dso = map__dso(al.map); 289 const char *dso_name = dso ? dso__long_name(dso) : NULL; 290 291 remap_key.dso = dso; 292 if (dso && !is_anon_memory(dso_name) && !is_no_dso_memory(dso_name)) 293 remap_key.invariant = map__start(al.map) - map__pgoff(al.map); 294 else 295 remap_key.invariant = map__start(al.map); 296 } else { 297 remap_key.dso = NULL; 298 remap_key.invariant = start; 299 } 300 301 /* The key to look up top allocated address. */ 302 top_addr_key.machine = remap_key.machine; 303 top_addr_key.pid = remap_key.pid; 304 305 if (hashmap__find(&aslr->remap_addresses, &remap_key, &remapped_invariant_ptr)) { 306 /* Mmap already exists. */ 307 u64 calculated_max; 308 309 if (al.map) { 310 /* 311 * The cached value is the base of the invariant. We add the 312 * offset into the VMA (start - map__start), plus the map's 313 * pgoff, to get the precise virtual address within this chunk. 314 */ 315 remap_addr = *remapped_invariant_ptr + map__pgoff(al.map) + 316 (start - map__start(al.map)); 317 } else { 318 /* 319 * For unmapped memory (e.g. kernel anonymous), the cached value 320 * was stored offset by pgoff. Adding pgoff yields the true remap_addr. 321 */ 322 remap_addr = *remapped_invariant_ptr + pgoff; 323 } 324 325 calculated_max = remap_addr + len; 326 327 /* See if top mapping was expanded. */ 328 if (hashmap__find(&aslr->top_addresses, &top_addr_key, &top)) { 329 if (calculated_max > top->remapped_max) 330 top->remapped_max = calculated_max; 331 } 332 addr_location__exit(&al); 333 return remap_addr; 334 } 335 /* No mmap, create an entry from the top address. */ 336 if (hashmap__find(&aslr->top_addresses, &top_addr_key, &top)) { 337 struct addr_location prev_al; 338 bool is_contiguous = false; 339 340 /* Current max allocated mmap address within the process. */ 341 remap_addr = top->remapped_max; 342 343 addr_location__init(&prev_al); 344 if (thread__find_map(aslr_thread, cpumode, start - 1, &prev_al)) { 345 if (map__end(prev_al.map) == start) 346 is_contiguous = true; 347 } 348 addr_location__exit(&prev_al); 349 350 if (is_contiguous) { 351 /* Contiguous mapping, do not add 1 page gap! */ 352 remap_addr = round_up_to_page_size(remap_addr); 353 } else { 354 /* Give 1 page gap from current max page. */ 355 remap_addr = round_up_to_page_size(remap_addr); 356 remap_addr += page_size; 357 } 358 if (remap_addr + len > top->remapped_max) 359 top->remapped_max = remap_addr + len; 360 } else { 361 /* First address of the process, allocate key and first top address. */ 362 struct top_addresses_key *tk; 363 struct process_top_address *top_val; 364 struct perf_env *env = session_machine ? session_machine->env : NULL; 365 bool is_64 = env ? perf_env__kernel_is_64_bit(env) : (sizeof(void *) == 8); 366 u64 kernel_start_addr = is_64 ? kernel_space_start_64 : kernel_space_start_32; 367 368 remap_addr = (cpumode == PERF_RECORD_MISC_KERNEL || 369 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ? 370 kernel_start_addr : user_space_start; 371 remap_addr = round_up_to_page_size(remap_addr); 372 373 tk = malloc(sizeof(*tk)); 374 top_val = malloc(sizeof(*top_val)); 375 if (!tk || !top_val) { 376 err = -ENOMEM; 377 } else { 378 *tk = top_addr_key; 379 top_val->remapped_max = remap_addr + len; 380 err = hashmap__insert(&aslr->top_addresses, tk, top_val, 381 HASHMAP_ADD, NULL, NULL); 382 } 383 if (err) { 384 errno = -err; 385 pr_err("Failure to add ASLR process top address %m\n"); 386 free(tk); 387 free(top_val); 388 addr_location__exit(&al); 389 return 0; 390 } 391 } 392 /* Create rmeapping entry. */ 393 new_remap_key = malloc(sizeof(*new_remap_key)); 394 new_remap_val = malloc(sizeof(u64)); 395 if (!new_remap_key || !new_remap_val) { 396 err = -ENOMEM; 397 } else { 398 *new_remap_key = remap_key; 399 new_remap_key->dso = dso__get(remap_key.dso); 400 if (cpumode == PERF_RECORD_MISC_KERNEL || 401 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) { 402 if (al.map) { 403 *new_remap_val = remap_addr - 404 (start - map__start(al.map)) - 405 map__pgoff(al.map); 406 } else { 407 /* 408 * Subtract pgoff from the base virtual address so that 409 * when the lookup path adds pgoff back, it perfectly 410 * cancels out and returns remap_addr. 411 */ 412 *new_remap_val = remap_addr - pgoff; 413 } 414 } else { 415 *new_remap_val = remap_addr - (al.map ? (start - map__start(al.map)) + 416 map__pgoff(al.map) : pgoff); 417 } 418 err = hashmap__add(&aslr->remap_addresses, new_remap_key, new_remap_val); 419 if (err) 420 dso__put(new_remap_key->dso); 421 } 422 if (err) { 423 errno = -err; 424 pr_err("Failure to add ASLR remapping %m\n"); 425 free(new_remap_key); 426 free(new_remap_val); 427 addr_location__exit(&al); 428 return 0; 429 } 430 addr_location__exit(&al); 431 return remap_addr; 432 } 433 434 static int aslr_tool__process_mmap(const struct perf_tool *tool, 435 union perf_event *event, 436 struct perf_sample *sample, 437 struct machine *machine) 438 { 439 struct delegate_tool *del_tool; 440 struct aslr_tool *aslr; 441 struct perf_tool *delegate; 442 union perf_event *new_event; 443 u8 cpumode; 444 struct thread *thread; 445 struct machine *aslr_machine; 446 int err; 447 448 del_tool = container_of(tool, struct delegate_tool, tool); 449 aslr = container_of(del_tool, struct aslr_tool, tool); 450 delegate = aslr->tool.delegate; 451 new_event = (union perf_event *)aslr->event_copy; 452 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 453 454 aslr_machine = machines__findnew(&aslr->machines, machine->pid); 455 if (!aslr_machine) 456 return -ENOMEM; 457 if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) 458 return -ENOMEM; 459 460 /* Create the thread, map, etc. in the ASLR before virtual address space. */ 461 err = perf_event__process_mmap(tool, event, sample, aslr_machine); 462 if (err) 463 return err; 464 465 thread = machine__findnew_thread(aslr_machine, event->mmap.pid, event->mmap.tid); 466 if (!thread) 467 return -ENOMEM; 468 memcpy(&new_event->mmap, &event->mmap, event->mmap.header.size); 469 /* Remaps the mmap.start. */ 470 new_event->mmap.start = aslr_tool__findnew_mapping(aslr, machine, thread, cpumode, 471 event->mmap.start, 472 event->mmap.len, 473 event->mmap.pgoff); 474 /* 475 * For anonymous memory (and kernel maps), the kernel populates the 476 * event's pgoff field with the original un-obfuscated virtual address 477 * in bytes (i.e. (addr >> PAGE_SHIFT) << PAGE_SHIFT). 478 * We must overwrite pgoff with the new remapped byte address to prevent 479 * leaking the original ASLR layout. 480 */ 481 if (is_anon_memory(event->mmap.filename) || is_no_dso_memory(event->mmap.filename) || 482 ((cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && 483 !is_kernel_module(event->mmap.filename, cpumode))) 484 new_event->mmap.pgoff = new_event->mmap.start; 485 err = delegate->mmap(delegate, new_event, sample, machine); 486 thread__put(thread); 487 return err; 488 } 489 490 static int aslr_tool__process_mmap2(const struct perf_tool *tool, 491 union perf_event *event, 492 struct perf_sample *sample, 493 struct machine *machine) 494 { 495 struct delegate_tool *del_tool; 496 struct aslr_tool *aslr; 497 struct perf_tool *delegate; 498 union perf_event *new_event; 499 u8 cpumode; 500 struct thread *thread; 501 struct machine *aslr_machine; 502 int err; 503 504 del_tool = container_of(tool, struct delegate_tool, tool); 505 aslr = container_of(del_tool, struct aslr_tool, tool); 506 delegate = aslr->tool.delegate; 507 new_event = (union perf_event *)aslr->event_copy; 508 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 509 510 aslr_machine = machines__findnew(&aslr->machines, machine->pid); 511 if (!aslr_machine) 512 return -ENOMEM; 513 if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) 514 return -ENOMEM; 515 516 /* Create the thread, map, etc. in the ASLR before virtual address space. */ 517 err = perf_event__process_mmap2(tool, event, sample, aslr_machine); 518 if (err) 519 return err; 520 521 thread = machine__findnew_thread(aslr_machine, event->mmap2.pid, event->mmap2.tid); 522 if (!thread) 523 return -ENOMEM; 524 memcpy(&new_event->mmap2, &event->mmap2, event->mmap2.header.size); 525 /* Remaps the mmap.start. */ 526 new_event->mmap2.start = aslr_tool__findnew_mapping(aslr, machine, thread, cpumode, 527 event->mmap2.start, 528 event->mmap2.len, 529 event->mmap2.pgoff); 530 /* 531 * For anonymous memory (and kernel maps), the kernel populates the 532 * event's pgoff field with the original un-obfuscated virtual address 533 * in bytes (i.e. (addr >> PAGE_SHIFT) << PAGE_SHIFT). 534 * We must overwrite pgoff with the new remapped byte address to prevent 535 * leaking the original ASLR layout. 536 */ 537 if (is_anon_memory(event->mmap2.filename) || is_no_dso_memory(event->mmap2.filename) || 538 ((cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && 539 !is_kernel_module(event->mmap2.filename, cpumode))) 540 new_event->mmap2.pgoff = new_event->mmap2.start; 541 err = delegate->mmap2(delegate, new_event, sample, machine); 542 thread__put(thread); 543 return err; 544 } 545 546 static int aslr_tool__process_comm(const struct perf_tool *tool, 547 union perf_event *event, 548 struct perf_sample *sample, 549 struct machine *machine) 550 { 551 struct delegate_tool *del_tool; 552 struct aslr_tool *aslr; 553 struct perf_tool *delegate; 554 struct machine *aslr_machine; 555 int err; 556 557 del_tool = container_of(tool, struct delegate_tool, tool); 558 aslr = container_of(del_tool, struct aslr_tool, tool); 559 delegate = aslr->tool.delegate; 560 561 aslr_machine = machines__findnew(&aslr->machines, machine->pid); 562 if (!aslr_machine) 563 return -ENOMEM; 564 if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) 565 return -ENOMEM; 566 567 /* Create the thread, map, etc. in the ASLR before virtual address space. */ 568 err = perf_event__process_comm(tool, event, sample, aslr_machine); 569 if (err) 570 return err; 571 572 return delegate->comm(delegate, event, sample, machine); 573 } 574 575 static int aslr_tool__process_fork(const struct perf_tool *tool, 576 union perf_event *event, 577 struct perf_sample *sample, 578 struct machine *machine) 579 { 580 struct delegate_tool *del_tool; 581 struct aslr_tool *aslr; 582 struct perf_tool *delegate; 583 struct machine *aslr_machine; 584 int err; 585 586 del_tool = container_of(tool, struct delegate_tool, tool); 587 aslr = container_of(del_tool, struct aslr_tool, tool); 588 delegate = aslr->tool.delegate; 589 590 aslr_machine = machines__findnew(&aslr->machines, machine->pid); 591 if (!aslr_machine) 592 return -ENOMEM; 593 if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) 594 return -ENOMEM; 595 596 /* Create the thread, map, etc. in the ASLR before virtual address space. */ 597 err = perf_event__process_fork(tool, event, sample, aslr_machine); 598 if (err) 599 return err; 600 601 return delegate->fork(delegate, event, sample, machine); 602 } 603 604 static int aslr_tool__process_exit(const struct perf_tool *tool, 605 union perf_event *event, 606 struct perf_sample *sample, 607 struct machine *machine) 608 { 609 struct delegate_tool *del_tool; 610 struct aslr_tool *aslr; 611 struct perf_tool *delegate; 612 struct machine *aslr_machine; 613 int err; 614 615 del_tool = container_of(tool, struct delegate_tool, tool); 616 aslr = container_of(del_tool, struct aslr_tool, tool); 617 delegate = aslr->tool.delegate; 618 619 aslr_machine = machines__findnew(&aslr->machines, machine->pid); 620 if (!aslr_machine) 621 return -ENOMEM; 622 if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) 623 return -ENOMEM; 624 625 /* Create the thread, map, etc. in the ASLR before virtual address space. */ 626 err = perf_event__process_exit(tool, event, sample, aslr_machine); 627 if (err) 628 return err; 629 630 return delegate->exit(delegate, event, sample, machine); 631 } 632 633 static int aslr_tool__process_text_poke(const struct perf_tool *tool __maybe_unused, 634 union perf_event *event __maybe_unused, 635 struct perf_sample *sample __maybe_unused, 636 struct machine *machine __maybe_unused) 637 { 638 /* Drop in case the instruction encodes an ASLR revealing address. */ 639 return 0; 640 } 641 642 static int aslr_tool__process_ksymbol(const struct perf_tool *tool, 643 union perf_event *event, 644 struct perf_sample *sample, 645 struct machine *machine) 646 { 647 struct delegate_tool *del_tool; 648 struct aslr_tool *aslr; 649 struct perf_tool *delegate; 650 union perf_event *new_event; 651 struct thread *thread; 652 struct machine *aslr_machine; 653 bool is_unregister; 654 int err; 655 656 del_tool = container_of(tool, struct delegate_tool, tool); 657 aslr = container_of(del_tool, struct aslr_tool, tool); 658 delegate = aslr->tool.delegate; 659 new_event = (union perf_event *)aslr->event_copy; 660 661 aslr_machine = machines__findnew(&aslr->machines, machine->pid); 662 if (!aslr_machine) 663 return -ENOMEM; 664 if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) 665 return -ENOMEM; 666 667 thread = machine__findnew_thread(aslr_machine, kernel_pid, 0); 668 if (!thread) 669 return -ENOMEM; 670 671 is_unregister = (event->ksymbol.flags & PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER); 672 673 memcpy(&new_event->ksymbol, &event->ksymbol, event->ksymbol.header.size); 674 675 if (is_unregister) { 676 new_event->ksymbol.addr = aslr_tool__findnew_mapping(aslr, machine, thread, 677 PERF_RECORD_MISC_KERNEL, 678 event->ksymbol.addr, 679 event->ksymbol.len, 680 /*pgoff=*/0); 681 err = perf_event__process_ksymbol(tool, event, sample, aslr_machine); 682 } else { 683 err = perf_event__process_ksymbol(tool, event, sample, aslr_machine); 684 new_event->ksymbol.addr = aslr_tool__findnew_mapping(aslr, machine, thread, 685 PERF_RECORD_MISC_KERNEL, 686 event->ksymbol.addr, 687 event->ksymbol.len, 688 /*pgoff=*/0); 689 } 690 if (err) { 691 thread__put(thread); 692 return err; 693 } 694 695 err = delegate->ksymbol(delegate, new_event, sample, machine); 696 thread__put(thread); 697 return err; 698 } 699 700 static int aslr_tool__process_sample(const struct perf_tool *tool, 701 union perf_event *event, 702 struct perf_sample *sample, 703 struct machine *machine) 704 { 705 struct evsel *evsel = sample->evsel; 706 struct delegate_tool *del_tool; 707 struct aslr_tool *aslr; 708 struct perf_tool *delegate; 709 int ret; 710 int orig_sample_size; 711 u64 sample_type; 712 struct thread *thread; 713 struct machine *aslr_machine; 714 __u64 max_i; 715 __u64 max_j; 716 union perf_event *new_event; 717 struct perf_sample new_sample; 718 __u64 *in_array, *out_array; 719 u8 cpumode; 720 u64 addr; 721 size_t i; 722 size_t j; 723 struct aslr_evsel_priv *priv = NULL; 724 u64 orig_sample_type; 725 u64 orig_regs_user; 726 u64 orig_regs_intr; 727 728 del_tool = container_of(tool, struct delegate_tool, tool); 729 aslr = container_of(del_tool, struct aslr_tool, tool); 730 delegate = aslr->tool.delegate; 731 732 if (evsel__is_dummy_event(evsel)) 733 return delegate->sample(delegate, event, sample, machine); 734 735 ret = -EFAULT; 736 737 if (hashmap__find(&aslr->evsel_orig_attrs, evsel, &priv)) { 738 orig_sample_type = priv->orig_sample_type; 739 orig_regs_user = priv->orig_sample_regs_user; 740 orig_regs_intr = priv->orig_sample_regs_intr; 741 } else { 742 orig_sample_type = evsel->core.attr.sample_type; 743 orig_regs_user = evsel->core.attr.sample_regs_user; 744 orig_regs_intr = evsel->core.attr.sample_regs_intr; 745 } 746 747 orig_sample_size = evsel->sample_size; 748 749 sample_type = orig_sample_type; 750 sample_type &= ~PERF_SAMPLE_REGS_USER; 751 sample_type &= ~PERF_SAMPLE_REGS_INTR; 752 sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; 753 754 max_i = (event->header.size - sizeof(struct perf_event_header)) / sizeof(__u64); 755 max_j = (PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_event_header)) / sizeof(__u64); 756 new_event = (union perf_event *)aslr->event_copy; 757 cpumode = sample->cpumode; 758 i = 0; 759 j = 0; 760 761 aslr_machine = machines__findnew(&aslr->machines, machine->pid); 762 if (!aslr_machine) 763 return -ENOMEM; 764 if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) 765 return -ENOMEM; 766 767 thread = machine__findnew_thread(aslr_machine, sample->pid, sample->tid); 768 769 if (!thread) 770 return -ENOMEM; 771 772 if (max_i > PERF_SAMPLE_MAX_SIZE / sizeof(u64)) 773 goto out_put; 774 775 new_event->sample.header = event->sample.header; 776 777 in_array = &event->sample.array[0]; 778 out_array = &new_event->sample.array[0]; 779 780 #define CHECK_BOUNDS(required_i, required_j) \ 781 (i + (required_i) > max_i || j + (required_j) > max_j) 782 783 #define COPY_U64() \ 784 do { \ 785 if (CHECK_BOUNDS(1, 1)) { \ 786 ret = -EFAULT; \ 787 goto out_put; \ 788 } \ 789 out_array[j++] = in_array[i++]; \ 790 } while (0) 791 792 #define REMAP_U64(addr_field) \ 793 do { \ 794 u64 remapped; \ 795 if (CHECK_BOUNDS(1, 1)) { \ 796 ret = -EFAULT; \ 797 goto out_put; \ 798 } \ 799 remapped = aslr_tool__remap_address(aslr, thread, cpumode, addr_field); \ 800 out_array[j++] = remapped; \ 801 i++; \ 802 } while (0) 803 804 if (orig_sample_type & PERF_SAMPLE_IDENTIFIER) 805 COPY_U64(); /* id */ 806 if (orig_sample_type & PERF_SAMPLE_IP) 807 REMAP_U64(sample->ip); 808 if (orig_sample_type & PERF_SAMPLE_TID) { 809 union { 810 u64 val64; 811 u32 val32[2]; 812 } u; 813 814 if (CHECK_BOUNDS(1, 1)) { 815 ret = -EFAULT; 816 goto out_put; 817 } 818 u.val32[0] = sample->pid; 819 u.val32[1] = sample->tid; 820 out_array[j++] = u.val64; 821 i++; 822 } 823 if (orig_sample_type & PERF_SAMPLE_TIME) 824 COPY_U64(); /* time */ 825 if (orig_sample_type & PERF_SAMPLE_ADDR) 826 REMAP_U64(sample->addr); 827 if (orig_sample_type & PERF_SAMPLE_ID) 828 COPY_U64(); /* id */ 829 if (orig_sample_type & PERF_SAMPLE_STREAM_ID) 830 COPY_U64(); /* stream_id */ 831 if (orig_sample_type & PERF_SAMPLE_CPU) 832 COPY_U64(); /* cpu, res */ 833 if (orig_sample_type & PERF_SAMPLE_PERIOD) 834 COPY_U64(); /* period */ 835 if (orig_sample_type & PERF_SAMPLE_READ) { 836 if ((evsel->core.attr.read_format & PERF_FORMAT_GROUP) == 0) { 837 COPY_U64(); /* value */ 838 if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 839 COPY_U64(); /* time_enabled */ 840 if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 841 COPY_U64(); /* time_running */ 842 if (evsel->core.attr.read_format & PERF_FORMAT_ID) 843 COPY_U64(); /* id */ 844 if (evsel->core.attr.read_format & PERF_FORMAT_LOST) 845 COPY_U64(); /* lost */ 846 } else { 847 u64 nr; 848 849 if (CHECK_BOUNDS(1, 1)) { 850 ret = -EFAULT; 851 goto out_put; 852 } 853 nr = in_array[i]; 854 COPY_U64(); 855 if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 856 COPY_U64(); /* time_enabled */ 857 if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 858 COPY_U64(); /* time_running */ 859 for (u64 cntr = 0; cntr < nr; cntr++) { 860 COPY_U64(); /* value */ 861 if (evsel->core.attr.read_format & PERF_FORMAT_ID) 862 COPY_U64(); /* id */ 863 if (evsel->core.attr.read_format & PERF_FORMAT_LOST) 864 COPY_U64(); /* lost */ 865 } 866 } 867 } 868 if (orig_sample_type & PERF_SAMPLE_CALLCHAIN) { 869 u64 nr; 870 871 if (CHECK_BOUNDS(1, 1)) { 872 ret = -EFAULT; 873 goto out_put; 874 } 875 nr = in_array[i]; 876 COPY_U64(); 877 878 for (u64 cntr = 0; cntr < nr; cntr++) { 879 if (CHECK_BOUNDS(1, 1)) { 880 ret = -EFAULT; 881 goto out_put; 882 } 883 addr = in_array[i++]; 884 if (addr >= PERF_CONTEXT_MAX) { 885 out_array[j++] = addr; 886 switch (addr) { 887 case PERF_CONTEXT_HV: 888 cpumode = PERF_RECORD_MISC_HYPERVISOR; 889 break; 890 case PERF_CONTEXT_KERNEL: 891 cpumode = PERF_RECORD_MISC_KERNEL; 892 break; 893 case PERF_CONTEXT_USER: 894 cpumode = PERF_RECORD_MISC_USER; 895 break; 896 case PERF_CONTEXT_GUEST: 897 cpumode = PERF_RECORD_MISC_GUEST_KERNEL; 898 break; 899 case PERF_CONTEXT_GUEST_KERNEL: 900 cpumode = PERF_RECORD_MISC_GUEST_KERNEL; 901 break; 902 case PERF_CONTEXT_GUEST_USER: 903 cpumode = PERF_RECORD_MISC_GUEST_USER; 904 break; 905 case PERF_CONTEXT_USER_DEFERRED: 906 if (cntr + 1 >= nr) { 907 pr_debug("Truncated callchain deferred cookie context\n"); 908 ret = 0; 909 goto out_put; 910 } 911 /* 912 * Immediately followed by a 64-bit 913 * stitching cookie. Skip/Copy it! 914 */ 915 if (CHECK_BOUNDS(1, 1)) { 916 ret = -EFAULT; 917 goto out_put; 918 } 919 out_array[j++] = in_array[i++]; 920 cntr++; 921 cpumode = PERF_RECORD_MISC_USER; 922 break; 923 default: 924 pr_debug("invalid callchain context: %"PRIx64"\n", addr); 925 ret = 0; 926 goto out_put; 927 } 928 continue; 929 } 930 addr = aslr_tool__remap_address(aslr, thread, cpumode, addr); 931 out_array[j++] = addr; 932 } 933 } 934 if (orig_sample_type & PERF_SAMPLE_RAW) { 935 size_t bytes = sizeof(u32) + sample->raw_size; 936 size_t u64_words = (bytes + 7) / 8; 937 938 if (i + u64_words > max_i || j + u64_words > max_j) { 939 ret = -EFAULT; 940 goto out_put; 941 } 942 memcpy(&out_array[j], &in_array[i], bytes); 943 i += u64_words; 944 j += u64_words; 945 /* 946 * TODO: certain raw samples can be remapped, such as 947 * tracepoints by examining their fields. 948 */ 949 pr_debug("Dropping raw samples as possible ASLR leak\n"); 950 ret = 0; 951 goto out_put; 952 } 953 if (orig_sample_type & PERF_SAMPLE_BRANCH_STACK) { 954 u64 nr; 955 956 if (CHECK_BOUNDS(1, 1)) { 957 ret = -EFAULT; 958 goto out_put; 959 } 960 nr = in_array[i]; 961 COPY_U64(); 962 963 if (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) 964 COPY_U64(); /* hw_idx */ 965 966 if (nr > (ULLONG_MAX / 3)) { 967 ret = -EFAULT; 968 goto out_put; 969 } 970 if (nr * 3 > max_i - i || nr * 3 > max_j - j) { 971 ret = -EFAULT; 972 goto out_put; 973 } 974 for (u64 cntr = 0; cntr < nr; cntr++) { 975 u64 from = in_array[i++]; 976 u64 to = in_array[i++]; 977 978 from = aslr_tool__remap_address(aslr, thread, sample->cpumode, from); 979 to = aslr_tool__remap_address(aslr, thread, sample->cpumode, to); 980 981 out_array[j++] = from; 982 out_array[j++] = to; 983 out_array[j++] = in_array[i++]; /* flags */ 984 } 985 if (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS) { 986 if (nr > max_i - i || nr > max_j - j) { 987 ret = -EFAULT; 988 goto out_put; 989 } 990 for (u64 cntr = 0; cntr < nr; cntr++) 991 COPY_U64(); 992 } 993 } 994 if (orig_sample_type & PERF_SAMPLE_REGS_USER) { 995 u64 abi; 996 997 if (CHECK_BOUNDS(1, 0)) { 998 ret = -EFAULT; 999 goto out_put; 1000 } 1001 abi = in_array[i++]; 1002 if (abi != PERF_SAMPLE_REGS_ABI_NONE) { 1003 u64 nr = hweight64(orig_regs_user); 1004 1005 if (nr > max_i - i) { 1006 ret = -EFAULT; 1007 goto out_put; 1008 } 1009 i += nr; 1010 } 1011 } 1012 if (orig_sample_type & PERF_SAMPLE_STACK_USER) { 1013 u64 size; 1014 1015 if (CHECK_BOUNDS(1, 1)) { 1016 ret = -EFAULT; 1017 goto out_put; 1018 } 1019 size = in_array[i]; 1020 COPY_U64(); 1021 if (size > 0) { 1022 size_t u64_words = size / 8 + (size % 8 ? 1 : 0); 1023 1024 if (u64_words > max_i - i || u64_words > max_j - j) { 1025 ret = -EFAULT; 1026 goto out_put; 1027 } 1028 memcpy(&out_array[j], &in_array[i], size); 1029 if (size % 8) { 1030 size_t pad = 8 - (size % 8); 1031 1032 memset(((char *)&out_array[j]) + size, 0, pad); 1033 } 1034 i += u64_words; 1035 j += u64_words; 1036 } 1037 /* TODO: can this be less conservative? */ 1038 pr_debug("Dropping stack user sample as possible ASLR leak\n"); 1039 ret = 0; 1040 goto out_put; 1041 } 1042 if (orig_sample_type & PERF_SAMPLE_WEIGHT_TYPE) 1043 COPY_U64(); /* perf_sample_weight */ 1044 if (orig_sample_type & PERF_SAMPLE_DATA_SRC) 1045 COPY_U64(); /* data_src */ 1046 if (orig_sample_type & PERF_SAMPLE_TRANSACTION) 1047 COPY_U64(); /* transaction */ 1048 if (orig_sample_type & PERF_SAMPLE_REGS_INTR) { 1049 u64 abi; 1050 1051 if (CHECK_BOUNDS(1, 0)) { 1052 ret = -EFAULT; 1053 goto out_put; 1054 } 1055 abi = in_array[i++]; 1056 if (abi != PERF_SAMPLE_REGS_ABI_NONE) { 1057 u64 nr = hweight64(orig_regs_intr); 1058 1059 if (nr > max_i - i) { 1060 ret = -EFAULT; 1061 goto out_put; 1062 } 1063 i += nr; 1064 } 1065 } 1066 if (orig_sample_type & PERF_SAMPLE_PHYS_ADDR) { 1067 COPY_U64(); /* phys_addr */ 1068 /* TODO: can this be less conservative? */ 1069 pr_debug("Dropping physical address sample as possible ASLR leak\n"); 1070 ret = 0; 1071 goto out_put; 1072 } 1073 if (orig_sample_type & PERF_SAMPLE_CGROUP) 1074 COPY_U64(); /* cgroup */ 1075 if (orig_sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) 1076 COPY_U64(); /* data_page_size */ 1077 if (orig_sample_type & PERF_SAMPLE_CODE_PAGE_SIZE) 1078 COPY_U64(); /* code_page_size */ 1079 1080 if (orig_sample_type & PERF_SAMPLE_AUX) { 1081 u64 size; 1082 1083 if (CHECK_BOUNDS(1, 1)) { 1084 ret = -EFAULT; 1085 goto out_put; 1086 } 1087 out_array[j] = in_array[i]; 1088 size = out_array[j++]; 1089 i++; 1090 if (size > 0) { 1091 size_t u64_words = size / 8 + (size % 8 ? 1 : 0); 1092 1093 if (u64_words > max_i - i || u64_words > max_j - j) { 1094 ret = -EFAULT; 1095 goto out_put; 1096 } 1097 memcpy(&out_array[j], &in_array[i], size); 1098 if (size % 8) { 1099 size_t pad = 8 - (size % 8); 1100 1101 memset(((char *)&out_array[j]) + size, 0, pad); 1102 } 1103 i += u64_words; 1104 j += u64_words; 1105 } 1106 /* TODO: can this be less conservative? */ 1107 pr_debug("Dropping aux sample as possible ASLR leak\n"); 1108 ret = 0; 1109 goto out_put; 1110 } 1111 1112 if (evsel__is_offcpu_event(evsel)) { 1113 /* TODO: can this be less conservative? */ 1114 pr_debug("Dropping off-CPU sample as possible ASLR leak\n"); 1115 ret = 0; 1116 goto out_put; 1117 } 1118 1119 new_event->sample.header.size = sizeof(struct perf_event_header) + j * sizeof(u64); 1120 /* Temporarily override evsel attributes to match the stripped new_event format! */ 1121 evsel->sample_size = __evsel__sample_size(sample_type); 1122 evsel->core.attr.sample_type = sample_type; 1123 evsel->core.attr.sample_regs_user = 0; 1124 evsel->core.attr.sample_regs_intr = 0; 1125 perf_sample__init(&new_sample, /*all=*/ true); 1126 ret = __evsel__parse_sample(evsel, new_event, &new_sample, /*needs_swap=*/false); 1127 1128 if (ret) { 1129 /* Restore original attributes immediately if parsing fails */ 1130 evsel->sample_size = orig_sample_size; 1131 evsel->core.attr.sample_type = orig_sample_type; 1132 evsel->core.attr.sample_regs_user = orig_regs_user; 1133 evsel->core.attr.sample_regs_intr = orig_regs_intr; 1134 perf_sample__exit(&new_sample); 1135 goto out_put; 1136 } 1137 1138 new_sample.evsel = evsel; 1139 ret = delegate->sample(delegate, new_event, &new_sample, machine); 1140 perf_sample__exit(&new_sample); 1141 1142 /* Restore original attributes so trace ingestion never desynchronizes! */ 1143 evsel->sample_size = orig_sample_size; 1144 evsel->core.attr.sample_type = orig_sample_type; 1145 evsel->core.attr.sample_regs_user = orig_regs_user; 1146 evsel->core.attr.sample_regs_intr = orig_regs_intr; 1147 1148 out_put: 1149 thread__put(thread); 1150 return ret; 1151 } 1152 1153 #undef CHECK_BOUNDS 1154 #undef COPY_U64 1155 #undef REMAP_U64 1156 1157 static int skipn(int fd, off_t n) 1158 { 1159 char buf[4096]; 1160 ssize_t ret; 1161 1162 while (n > 0) { 1163 ret = read(fd, buf, min_t(off_t, n, (off_t)sizeof(buf))); 1164 if (ret <= 0) 1165 return ret; 1166 n -= ret; 1167 } 1168 1169 return 0; 1170 } 1171 1172 static s64 aslr_tool__process_auxtrace(const struct perf_tool *tool __maybe_unused, 1173 struct perf_session *session, 1174 union perf_event *event) 1175 { 1176 pr_warning_once("ASLR: Dropping auxtrace data as it cannot be obfuscated.\n"); 1177 if (perf_data__is_pipe(session->data)) { 1178 /* Copy behavior of the stub by reading all pipe data. */ 1179 int err = skipn(perf_data__fd(session->data), event->auxtrace.size); 1180 1181 if (err < 0) 1182 return err; 1183 } 1184 return event->auxtrace.size; 1185 } 1186 1187 static int aslr_tool__process_auxtrace_info(const struct perf_tool *tool __maybe_unused, 1188 struct perf_session *session __maybe_unused, 1189 union perf_event *event __maybe_unused) 1190 { 1191 return 0; 1192 } 1193 1194 static int aslr_tool__process_auxtrace_error(const struct perf_tool *tool __maybe_unused, 1195 struct perf_session *session __maybe_unused, 1196 union perf_event *event __maybe_unused) 1197 { 1198 return 0; 1199 } 1200 1201 void aslr_tool__strip_attr_event(union perf_event *event, struct evlist *evlist) 1202 { 1203 u32 attr_size; 1204 1205 if (!evlist) 1206 return; 1207 1208 attr_size = event->attr.attr.size ?: PERF_ATTR_SIZE_VER0; 1209 1210 if (attr_size >= (offsetof(struct perf_event_attr, sample_type) + sizeof(u64))) { 1211 event->attr.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; 1212 1213 if (attr_size >= (offsetof(struct perf_event_attr, sample_regs_user) + sizeof(u64))) 1214 event->attr.attr.sample_regs_user = 0; 1215 if (attr_size >= (offsetof(struct perf_event_attr, sample_regs_intr) + sizeof(u64))) 1216 event->attr.attr.sample_regs_intr = 0; 1217 } 1218 1219 if (attr_size >= (offsetof(struct perf_event_attr, type) + sizeof(u32))) { 1220 u32 type = event->attr.attr.type; 1221 1222 if (type == PERF_TYPE_BREAKPOINT && 1223 attr_size >= (offsetof(struct perf_event_attr, bp_addr) + sizeof(u64))) { 1224 event->attr.attr.bp_addr = 0; 1225 } else if (type >= PERF_TYPE_MAX) { 1226 struct perf_pmu *pmu; 1227 1228 pmu = perf_pmus__find_by_type(type); 1229 if (pmu && (!strcmp(pmu->name, "kprobe") || 1230 !strcmp(pmu->name, "uprobe"))) { 1231 if (attr_size >= (offsetof(struct perf_event_attr, config1) + sizeof(u64))) 1232 event->attr.attr.config1 = 0; 1233 if (attr_size >= (offsetof(struct perf_event_attr, config2) + sizeof(u64))) 1234 event->attr.attr.config2 = 0; 1235 } 1236 } 1237 } 1238 } 1239 1240 static int aslr_tool__init(struct aslr_tool *aslr, struct perf_tool *delegate) 1241 { 1242 delegate_tool__init(&aslr->tool, delegate); 1243 aslr->tool.tool.ordered_events = true; 1244 1245 if (machines__init(&aslr->machines)) 1246 return -ENOMEM; 1247 1248 hashmap__init(&aslr->remap_addresses, 1249 remap_addresses__hash, remap_addresses__equal, 1250 /*ctx=*/NULL); 1251 hashmap__init(&aslr->top_addresses, 1252 top_addresses__hash, top_addresses__equal, 1253 /*ctx=*/NULL); 1254 hashmap__init(&aslr->evsel_orig_attrs, 1255 evsel_hash, evsel_equal, 1256 /*ctx=*/NULL); 1257 1258 aslr->tool.tool.sample = aslr_tool__process_sample; 1259 /* read - reads a counter, okay to delegate. */ 1260 aslr->tool.tool.mmap = aslr_tool__process_mmap; 1261 aslr->tool.tool.mmap2 = aslr_tool__process_mmap2; 1262 aslr->tool.tool.comm = aslr_tool__process_comm; 1263 aslr->tool.tool.fork = aslr_tool__process_fork; 1264 aslr->tool.tool.exit = aslr_tool__process_exit; 1265 /* namesspaces, cgroup, lost, lost_sample, aux, */ 1266 /* itrace_start, aux_output_hw_id, context_switch, throttle, unthrottle */ 1267 /* - no virtual addresses. */ 1268 aslr->tool.tool.ksymbol = aslr_tool__process_ksymbol; 1269 /* bpf - no virtual address. */ 1270 aslr->tool.tool.text_poke = aslr_tool__process_text_poke; 1271 /* 1272 * event_update, tracing_data, finished_round, build_id, id_index, 1273 * auxtrace_info, auxtrace_error, time_conv, thread_map, cpu_map, 1274 * stat_config, stat, feature, finished_init, bpf_metadata, compressed, 1275 * auxtrace - no virtual addresses. 1276 */ 1277 aslr->tool.tool.auxtrace = aslr_tool__process_auxtrace; 1278 aslr->tool.tool.auxtrace_info = aslr_tool__process_auxtrace_info; 1279 aslr->tool.tool.auxtrace_error = aslr_tool__process_auxtrace_error; 1280 1281 return 0; 1282 } 1283 1284 struct perf_tool *aslr_tool__new(struct perf_tool *delegate) 1285 { 1286 struct aslr_tool *aslr = zalloc(sizeof(*aslr)); 1287 1288 if (!aslr) 1289 return NULL; 1290 1291 if (aslr_tool__init(aslr, delegate)) { 1292 free(aslr); 1293 return NULL; 1294 } 1295 return &aslr->tool.tool; 1296 } 1297 1298 void aslr_tool__delete(struct perf_tool *tool) 1299 { 1300 struct delegate_tool *del_tool; 1301 struct aslr_tool *aslr; 1302 struct hashmap_entry *cur; 1303 size_t bkt; 1304 struct rb_node *nd; 1305 1306 if (!tool) 1307 return; 1308 1309 del_tool = container_of(tool, struct delegate_tool, tool); 1310 aslr = container_of(del_tool, struct aslr_tool, tool); 1311 1312 hashmap__for_each_entry(&aslr->remap_addresses, cur, bkt) { 1313 struct remap_addresses_key *key = (struct remap_addresses_key *)cur->pkey; 1314 1315 if (key) 1316 dso__put(key->dso); 1317 zfree(&cur->pkey); 1318 zfree(&cur->pvalue); 1319 } 1320 hashmap__for_each_entry(&aslr->top_addresses, cur, bkt) { 1321 zfree(&cur->pkey); 1322 zfree(&cur->pvalue); 1323 } 1324 hashmap__for_each_entry(&aslr->evsel_orig_attrs, cur, bkt) { 1325 zfree(&cur->pvalue); 1326 } 1327 1328 hashmap__clear(&aslr->remap_addresses); 1329 hashmap__clear(&aslr->top_addresses); 1330 hashmap__clear(&aslr->evsel_orig_attrs); 1331 aslr_tool__destroy_machines_priv(&aslr->machines); 1332 machines__destroy_kernel_maps(&aslr->machines); 1333 1334 while ((nd = rb_first_cached(&aslr->machines.guests)) != NULL) { 1335 struct machine *machine = rb_entry(nd, struct machine, rb_node); 1336 1337 rb_erase_cached(nd, &aslr->machines.guests); 1338 machine__delete(machine); 1339 } 1340 1341 machines__exit(&aslr->machines); 1342 free(aslr); 1343 } 1344 1345 int aslr_tool__cache_orig_attrs(struct perf_tool *tool, struct evsel *evsel) 1346 { 1347 struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); 1348 struct aslr_tool *aslr = container_of(del_tool, struct aslr_tool, tool); 1349 struct aslr_evsel_priv *priv = zalloc(sizeof(*priv)); 1350 int err; 1351 1352 if (!priv) 1353 return -ENOMEM; 1354 1355 priv->orig_sample_type = evsel->core.attr.sample_type; 1356 priv->orig_sample_regs_user = evsel->core.attr.sample_regs_user; 1357 priv->orig_sample_regs_intr = evsel->core.attr.sample_regs_intr; 1358 priv->orig_sample_size = evsel->sample_size; 1359 1360 err = hashmap__add(&aslr->evsel_orig_attrs, evsel, priv); 1361 if (err) { 1362 free(priv); 1363 return err; 1364 } 1365 return 0; 1366 } 1367 1368 void aslr_tool__strip_evlist(const struct perf_tool *tool __maybe_unused, struct evlist *evlist) 1369 { 1370 struct evsel *evsel; 1371 1372 evlist__for_each_entry(evlist, evsel) { 1373 evsel->core.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; 1374 evsel->core.attr.sample_regs_user = 0; 1375 evsel->core.attr.sample_regs_intr = 0; 1376 evsel->sample_size = __evsel__sample_size(evsel->core.attr.sample_type); 1377 evsel__calc_id_pos(evsel); 1378 1379 if (evsel->core.attr.type == PERF_TYPE_BREAKPOINT) { 1380 evsel->core.attr.bp_addr = 0; 1381 } else if (evsel->core.attr.type >= PERF_TYPE_MAX) { 1382 struct perf_pmu *pmu = perf_pmus__find_by_type(evsel->core.attr.type); 1383 1384 if (pmu && (!strcmp(pmu->name, "kprobe") || 1385 !strcmp(pmu->name, "uprobe"))) { 1386 evsel->core.attr.config1 = 0; 1387 evsel->core.attr.config2 = 0; 1388 } 1389 } 1390 } 1391 } 1392 1393 void aslr_tool__restore_evlist(const struct perf_tool *tool, struct evlist *evlist) 1394 { 1395 const struct delegate_tool *del_tool = container_of(tool, const struct delegate_tool, tool); 1396 const struct aslr_tool *aslr = container_of(del_tool, const struct aslr_tool, tool); 1397 struct evsel *evsel; 1398 struct aslr_evsel_priv *priv; 1399 1400 evlist__for_each_entry(evlist, evsel) { 1401 if (hashmap__find(&aslr->evsel_orig_attrs, evsel, &priv)) { 1402 evsel->core.attr.sample_type = priv->orig_sample_type; 1403 evsel->core.attr.sample_regs_user = priv->orig_sample_regs_user; 1404 evsel->core.attr.sample_regs_intr = priv->orig_sample_regs_intr; 1405 evsel->sample_size = priv->orig_sample_size; 1406 evsel__calc_id_pos(evsel); 1407 } 1408 } 1409 } 1410