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