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