1acf61631SYonghong Song // SPDX-License-Identifier: GPL-2.0
2acf61631SYonghong Song /* Copyright (c) 2020 Facebook */
384544f56SYonghong Song #include "bpf_iter.h"
4acf61631SYonghong Song #include <bpf/bpf_helpers.h>
545105c2eSKenny Yu #include <bpf/bpf_tracing.h>
6acf61631SYonghong Song 
7acf61631SYonghong Song char _license[] SEC("license") = "GPL";
8acf61631SYonghong Song 
9*b3e1331eSKui-Feng Lee uint32_t tid = 0;
10*b3e1331eSKui-Feng Lee int num_unknown_tid = 0;
11*b3e1331eSKui-Feng Lee int num_known_tid = 0;
12*b3e1331eSKui-Feng Lee 
13acf61631SYonghong Song SEC("iter/task")
dump_task(struct bpf_iter__task * ctx)14acf61631SYonghong Song int dump_task(struct bpf_iter__task *ctx)
15acf61631SYonghong Song {
16acf61631SYonghong Song 	struct seq_file *seq = ctx->meta->seq;
17acf61631SYonghong Song 	struct task_struct *task = ctx->task;
18b4b638c3SYonghong Song 	static char info[] = "    === END ===";
19acf61631SYonghong Song 
20acf61631SYonghong Song 	if (task == (void *)0) {
21b4b638c3SYonghong Song 		BPF_SEQ_PRINTF(seq, "%s\n", info);
22acf61631SYonghong Song 		return 0;
23acf61631SYonghong Song 	}
24acf61631SYonghong Song 
25*b3e1331eSKui-Feng Lee 	if (task->pid != tid)
26*b3e1331eSKui-Feng Lee 		num_unknown_tid++;
27*b3e1331eSKui-Feng Lee 	else
28*b3e1331eSKui-Feng Lee 		num_known_tid++;
29*b3e1331eSKui-Feng Lee 
30acf61631SYonghong Song 	if (ctx->meta->seq_num == 0)
31acf61631SYonghong Song 		BPF_SEQ_PRINTF(seq, "    tgid      gid\n");
32acf61631SYonghong Song 
33acf61631SYonghong Song 	BPF_SEQ_PRINTF(seq, "%8d %8d\n", task->tgid, task->pid);
34acf61631SYonghong Song 	return 0;
35acf61631SYonghong Song }
3645105c2eSKenny Yu 
3745105c2eSKenny Yu int num_expected_failure_copy_from_user_task = 0;
3845105c2eSKenny Yu int num_success_copy_from_user_task = 0;
3945105c2eSKenny Yu 
4045105c2eSKenny Yu SEC("iter.s/task")
dump_task_sleepable(struct bpf_iter__task * ctx)4145105c2eSKenny Yu int dump_task_sleepable(struct bpf_iter__task *ctx)
4245105c2eSKenny Yu {
4345105c2eSKenny Yu 	struct seq_file *seq = ctx->meta->seq;
4445105c2eSKenny Yu 	struct task_struct *task = ctx->task;
4545105c2eSKenny Yu 	static const char info[] = "    === END ===";
4645105c2eSKenny Yu 	struct pt_regs *regs;
4745105c2eSKenny Yu 	void *ptr;
4845105c2eSKenny Yu 	uint32_t user_data = 0;
4945105c2eSKenny Yu 	int ret;
5045105c2eSKenny Yu 
5145105c2eSKenny Yu 	if (task == (void *)0) {
5245105c2eSKenny Yu 		BPF_SEQ_PRINTF(seq, "%s\n", info);
5345105c2eSKenny Yu 		return 0;
5445105c2eSKenny Yu 	}
5545105c2eSKenny Yu 
5645105c2eSKenny Yu 	/* Read an invalid pointer and ensure we get an error */
5745105c2eSKenny Yu 	ptr = NULL;
5845105c2eSKenny Yu 	ret = bpf_copy_from_user_task(&user_data, sizeof(uint32_t), ptr, task, 0);
5945105c2eSKenny Yu 	if (ret) {
6045105c2eSKenny Yu 		++num_expected_failure_copy_from_user_task;
6145105c2eSKenny Yu 	} else {
6245105c2eSKenny Yu 		BPF_SEQ_PRINTF(seq, "%s\n", info);
6345105c2eSKenny Yu 		return 0;
6445105c2eSKenny Yu 	}
6545105c2eSKenny Yu 
6645105c2eSKenny Yu 	/* Try to read the contents of the task's instruction pointer from the
6745105c2eSKenny Yu 	 * remote task's address space.
6845105c2eSKenny Yu 	 */
6945105c2eSKenny Yu 	regs = (struct pt_regs *)bpf_task_pt_regs(task);
7045105c2eSKenny Yu 	if (regs == (void *)0) {
7145105c2eSKenny Yu 		BPF_SEQ_PRINTF(seq, "%s\n", info);
7245105c2eSKenny Yu 		return 0;
7345105c2eSKenny Yu 	}
7445105c2eSKenny Yu 	ptr = (void *)PT_REGS_IP(regs);
7545105c2eSKenny Yu 
7645105c2eSKenny Yu 	ret = bpf_copy_from_user_task(&user_data, sizeof(uint32_t), ptr, task, 0);
7745105c2eSKenny Yu 	if (ret) {
7845105c2eSKenny Yu 		BPF_SEQ_PRINTF(seq, "%s\n", info);
7945105c2eSKenny Yu 		return 0;
8045105c2eSKenny Yu 	}
8145105c2eSKenny Yu 	++num_success_copy_from_user_task;
8245105c2eSKenny Yu 
8345105c2eSKenny Yu 	if (ctx->meta->seq_num == 0)
8445105c2eSKenny Yu 		BPF_SEQ_PRINTF(seq, "    tgid      gid     data\n");
8545105c2eSKenny Yu 
8645105c2eSKenny Yu 	BPF_SEQ_PRINTF(seq, "%8d %8d %8d\n", task->tgid, task->pid, user_data);
8745105c2eSKenny Yu 	return 0;
8845105c2eSKenny Yu }
89