xref: /linux/tools/perf/util/aslr.c (revision 3d5e48944e824bddc20d7b874e784f7b279636fe)
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