projects/linux·blob master · refs

1410 lines · 40.5 KiB

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 */
37struct remap_addresses_key {
38 struct machine *machine;
39 struct dso *dso;
40 u64 invariant;
41 pid_t pid;
42};
43
44struct aslr_mapping {
45 struct list_head node;
46 u64 orig_start;
47 u64 len;
48 u64 remap_start;
49};
50
51struct 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
58static size_t evsel_hash(long key, void *ctx __maybe_unused)
59{
60 return (size_t)key;
61}
62
63static bool evsel_equal(long key1, long key2, void *ctx __maybe_unused)
64{
65 return key1 == key2;
66}
67
68struct process_top_address {
69 u64 remapped_max;
70};
71struct 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
89static const pid_t kernel_pid = -1;
90
91/* Start remapping user processes from a small non-zero offset. */
92static const u64 user_space_start = 0x200000;
93static const u64 kernel_space_start_64 = 0xffff800010000000ULL;
94static const u64 kernel_space_start_32 = 0x80000000ULL;
95
96static 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
104static 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
115struct top_addresses_key {
116 struct machine *machine;
117 pid_t pid;
118};
119
120static 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
127static 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
135static u64 round_up_to_page_size(u64 addr)
136{
137 return (addr + page_size - 1) & ~((u64)page_size - 1);
138}
139
140static 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
202struct aslr_machine_priv {
203 bool kernel_maps_loaded;
204};
205
206static 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
234static void aslr_tool__free_machine_priv(struct machine *machine)
235{
236 free(machine->priv);
237 machine->priv = NULL;
238}
239
240static 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
252static 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
435static 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
491static 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
547static 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
576static 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
605static 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
634static 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
643static 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
701static 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
1149out_put:
1150 thread__put(thread);
1151 return ret;
1152}
1153
1154#undef CHECK_BOUNDS
1155#undef COPY_U64
1156#undef REMAP_U64
1157
1158static 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
1173static 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
1188static 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
1195static 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
1202void 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
1241static 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
1285struct 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
1299void 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
1346int 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
1369void 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
1394void 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}