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