1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
3 #include "bpf_iter.h"
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 
7 char _license[] SEC("license") = "GPL";
8 
9 SEC("iter/task")
10 int dump_task(struct bpf_iter__task *ctx)
11 {
12 	struct seq_file *seq = ctx->meta->seq;
13 	struct task_struct *task = ctx->task;
14 	static char info[] = "    === END ===";
15 
16 	if (task == (void *)0) {
17 		BPF_SEQ_PRINTF(seq, "%s\n", info);
18 		return 0;
19 	}
20 
21 	if (ctx->meta->seq_num == 0)
22 		BPF_SEQ_PRINTF(seq, "    tgid      gid\n");
23 
24 	BPF_SEQ_PRINTF(seq, "%8d %8d\n", task->tgid, task->pid);
25 	return 0;
26 }
27 
28 int num_expected_failure_copy_from_user_task = 0;
29 int num_success_copy_from_user_task = 0;
30 
31 SEC("iter.s/task")
32 int dump_task_sleepable(struct bpf_iter__task *ctx)
33 {
34 	struct seq_file *seq = ctx->meta->seq;
35 	struct task_struct *task = ctx->task;
36 	static const char info[] = "    === END ===";
37 	struct pt_regs *regs;
38 	void *ptr;
39 	uint32_t user_data = 0;
40 	int ret;
41 
42 	if (task == (void *)0) {
43 		BPF_SEQ_PRINTF(seq, "%s\n", info);
44 		return 0;
45 	}
46 
47 	/* Read an invalid pointer and ensure we get an error */
48 	ptr = NULL;
49 	ret = bpf_copy_from_user_task(&user_data, sizeof(uint32_t), ptr, task, 0);
50 	if (ret) {
51 		++num_expected_failure_copy_from_user_task;
52 	} else {
53 		BPF_SEQ_PRINTF(seq, "%s\n", info);
54 		return 0;
55 	}
56 
57 	/* Try to read the contents of the task's instruction pointer from the
58 	 * remote task's address space.
59 	 */
60 	regs = (struct pt_regs *)bpf_task_pt_regs(task);
61 	if (regs == (void *)0) {
62 		BPF_SEQ_PRINTF(seq, "%s\n", info);
63 		return 0;
64 	}
65 	ptr = (void *)PT_REGS_IP(regs);
66 
67 	ret = bpf_copy_from_user_task(&user_data, sizeof(uint32_t), ptr, task, 0);
68 	if (ret) {
69 		BPF_SEQ_PRINTF(seq, "%s\n", info);
70 		return 0;
71 	}
72 	++num_success_copy_from_user_task;
73 
74 	if (ctx->meta->seq_num == 0)
75 		BPF_SEQ_PRINTF(seq, "    tgid      gid     data\n");
76 
77 	BPF_SEQ_PRINTF(seq, "%8d %8d %8d\n", task->tgid, task->pid, user_data);
78 	return 0;
79 }
80