File Index
Files and directories
Sign in
FILE

bpf_iter_tasks.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/bpf_iter_tasks.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2020 Facebook */
  3#include <vmlinux.h>
  4#include <bpf/bpf_helpers.h>
  5#include <bpf/bpf_tracing.h>
  6
  7char _license[] SEC("license") = "GPL";
  8
  9uint32_t tid = 0;
 10int num_unknown_tid = 0;
 11int num_known_tid = 0;
 12void *user_ptr = 0;
 13void *user_ptr_long = 0;
 14uint32_t pid = 0;
 15
 16static char big_str1[5000];
 17static char big_str2[5005];
 18static char big_str3[4996];
 19
 20SEC("iter/task")
 21int dump_task(struct bpf_iter__task *ctx)
 22{
 23	struct seq_file *seq = ctx->meta->seq;
 24	struct task_struct *task = ctx->task;
 25	static char info[] = "    === END ===";
 26
 27	if (task == (void *)0) {
 28		BPF_SEQ_PRINTF(seq, "%s\n", info);
 29		return 0;
 30	}
 31
 32	if (task->pid != (pid_t)tid)
 33		num_unknown_tid++;
 34	else
 35		num_known_tid++;
 36
 37	if (ctx->meta->seq_num == 0)
 38		BPF_SEQ_PRINTF(seq, "    tgid      gid\n");
 39
 40	BPF_SEQ_PRINTF(seq, "%8d %8d\n", task->tgid, task->pid);
 41	return 0;
 42}
 43
 44int num_expected_failure_copy_from_user_task = 0;
 45int num_expected_failure_copy_from_user_task_str = 0;
 46int num_success_copy_from_user_task = 0;
 47int num_success_copy_from_user_task_str = 0;
 48
 49SEC("iter.s/task")
 50int dump_task_sleepable(struct bpf_iter__task *ctx)
 51{
 52	struct seq_file *seq = ctx->meta->seq;
 53	struct task_struct *task = ctx->task;
 54	static const char info[] = "    === END ===";
 55	struct pt_regs *regs;
 56	char task_str1[10] = "aaaaaaaaaa";
 57	char task_str2[10], task_str3[10];
 58	char task_str4[20] = "aaaaaaaaaaaaaaaaaaaa";
 59	void *ptr;
 60	uint32_t user_data = 0;
 61	int ret;
 62
 63	if (task == (void *)0) {
 64		BPF_SEQ_PRINTF(seq, "%s\n", info);
 65		return 0;
 66	}
 67
 68	/* Read an invalid pointer and ensure we get an error */
 69	ptr = NULL;
 70	ret = bpf_copy_from_user_task(&user_data, sizeof(uint32_t), ptr, task, 0);
 71	if (ret) {
 72		++num_expected_failure_copy_from_user_task;
 73	} else {
 74		BPF_SEQ_PRINTF(seq, "%s\n", info);
 75		return 0;
 76	}
 77
 78	/* Try to read the contents of the task's instruction pointer from the
 79	 * remote task's address space.
 80	 */
 81	regs = (struct pt_regs *)bpf_task_pt_regs(task);
 82	if (regs == (void *)0) {
 83		BPF_SEQ_PRINTF(seq, "%s\n", info);
 84		return 0;
 85	}
 86	ptr = (void *)PT_REGS_IP(regs);
 87
 88	ret = bpf_copy_from_user_task(&user_data, sizeof(uint32_t), ptr, task, 0);
 89	if (ret) {
 90		BPF_SEQ_PRINTF(seq, "%s\n", info);
 91		return 0;
 92	}
 93
 94	++num_success_copy_from_user_task;
 95
 96	/* Read an invalid pointer and ensure we get an error */
 97	ptr = NULL;
 98	ret = bpf_copy_from_user_task_str((char *)task_str1, sizeof(task_str1), ptr, task, 0);
 99	if (ret >= 0 || task_str1[9] != 'a' || task_str1[0] != '\0') {
100		BPF_SEQ_PRINTF(seq, "%s\n", info);
101		return 0;
102	}
103
104	/* Read an invalid pointer and ensure we get error with pad zeros flag */
105	ptr = NULL;
106	ret = bpf_copy_from_user_task_str((char *)task_str1, sizeof(task_str1),
107					  ptr, task, BPF_F_PAD_ZEROS);
108	if (ret >= 0 || task_str1[9] != '\0' || task_str1[0] != '\0') {
109		BPF_SEQ_PRINTF(seq, "%s\n", info);
110		return 0;
111	}
112
113	++num_expected_failure_copy_from_user_task_str;
114
115	/* Same length as the string */
116	ret = bpf_copy_from_user_task_str((char *)task_str2, 10, user_ptr, task, 0);
117	/* only need to do the task pid check once */
118	if (bpf_strncmp(task_str2, 10, "test_data\0") != 0 || ret != 10 || task->tgid != pid) {
119		BPF_SEQ_PRINTF(seq, "%s\n", info);
120		return 0;
121	}
122
123	/* Shorter length than the string */
124	ret = bpf_copy_from_user_task_str((char *)task_str3, 2, user_ptr, task, 0);
125	if (bpf_strncmp(task_str3, 2, "t\0") != 0 || ret != 2) {
126		BPF_SEQ_PRINTF(seq, "%s\n", info);
127		return 0;
128	}
129
130	/* Longer length than the string */
131	ret = bpf_copy_from_user_task_str((char *)task_str4, 20, user_ptr, task, 0);
132	if (bpf_strncmp(task_str4, 10, "test_data\0") != 0 || ret != 10
133	    || task_str4[sizeof(task_str4) - 1] != 'a') {
134		BPF_SEQ_PRINTF(seq, "%s\n", info);
135		return 0;
136	}
137
138	/* Longer length than the string with pad zeros flag */
139	ret = bpf_copy_from_user_task_str((char *)task_str4, 20, user_ptr, task, BPF_F_PAD_ZEROS);
140	if (bpf_strncmp(task_str4, 10, "test_data\0") != 0 || ret != 10
141	    || task_str4[sizeof(task_str4) - 1] != '\0') {
142		BPF_SEQ_PRINTF(seq, "%s\n", info);
143		return 0;
144	}
145
146	/* Longer length than the string past a page boundary */
147	ret = bpf_copy_from_user_task_str(big_str1, 5000, user_ptr, task, 0);
148	if (bpf_strncmp(big_str1, 10, "test_data\0") != 0 || ret != 10) {
149		BPF_SEQ_PRINTF(seq, "%s\n", info);
150		return 0;
151	}
152
153	/* String that crosses a page boundary */
154	ret = bpf_copy_from_user_task_str(big_str1, 5000, user_ptr_long, task, BPF_F_PAD_ZEROS);
155	if (bpf_strncmp(big_str1, 4, "baba") != 0 || ret != 5000
156	    || bpf_strncmp(big_str1 + 4996, 4, "bab\0") != 0) {
157		BPF_SEQ_PRINTF(seq, "%s\n", info);
158		return 0;
159	}
160
161	for (int i = 0; i < 4999; ++i) {
162		if (i % 2 == 0) {
163			if (big_str1[i] != 'b') {
164				BPF_SEQ_PRINTF(seq, "%s\n", info);
165				return 0;
166			}
167		} else {
168			if (big_str1[i] != 'a') {
169				BPF_SEQ_PRINTF(seq, "%s\n", info);
170				return 0;
171			}
172		}
173	}
174
175	/* Longer length than the string that crosses a page boundary */
176	ret = bpf_copy_from_user_task_str(big_str2, 5005, user_ptr_long, task, BPF_F_PAD_ZEROS);
177	if (bpf_strncmp(big_str2, 4, "baba") != 0 || ret != 5000
178	    || bpf_strncmp(big_str2 + 4996, 5, "bab\0\0") != 0) {
179		BPF_SEQ_PRINTF(seq, "%s\n", info);
180		return 0;
181	}
182
183	/* Shorter length than the string that crosses a page boundary */
184	ret = bpf_copy_from_user_task_str(big_str3, 4996, user_ptr_long, task, 0);
185	if (bpf_strncmp(big_str3, 4, "baba") != 0 || ret != 4996
186	    || bpf_strncmp(big_str3 + 4992, 4, "bab\0") != 0) {
187		BPF_SEQ_PRINTF(seq, "%s\n", info);
188		return 0;
189	}
190
191	++num_success_copy_from_user_task_str;
192
193	if (ctx->meta->seq_num == 0)
194		BPF_SEQ_PRINTF(seq, "    tgid      gid     data\n");
195
196	BPF_SEQ_PRINTF(seq, "%8d %8d %8d\n", task->tgid, task->pid, user_data);
197	return 0;
198}
~/ Read-only file preview.