xref: /linux/tools/testing/selftests/bpf/progs/verifier_vfs_reject.c (revision e9ef810dfee7a2227da9d423aecb0ced35faddbe)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Google LLC. */
3 
4 #include <vmlinux.h>
5 #include <errno.h>
6 #include <bpf/bpf_helpers.h>
7 #include <bpf/bpf_tracing.h>
8 #include <linux/limits.h>
9 
10 #include "bpf_misc.h"
11 #include "bpf_experimental.h"
12 
13 static char buf[PATH_MAX];
14 
15 SEC("lsm.s/file_open")
16 __failure __msg("Possibly NULL pointer passed to trusted arg0")
BPF_PROG(get_task_exe_file_kfunc_null)17 int BPF_PROG(get_task_exe_file_kfunc_null)
18 {
19 	struct file *acquired;
20 
21 	/* Can't pass a NULL pointer to bpf_get_task_exe_file(). */
22 	acquired = bpf_get_task_exe_file(NULL);
23 	if (!acquired)
24 		return 0;
25 
26 	bpf_put_file(acquired);
27 	return 0;
28 }
29 
30 SEC("lsm.s/inode_getxattr")
31 __failure __msg("arg#0 pointer type STRUCT task_struct must point to scalar, or struct with scalar")
BPF_PROG(get_task_exe_file_kfunc_fp)32 int BPF_PROG(get_task_exe_file_kfunc_fp)
33 {
34 	u64 x;
35 	struct file *acquired;
36 	struct task_struct *task;
37 
38 	task = (struct task_struct *)&x;
39 	/* Can't pass random frame pointer to bpf_get_task_exe_file(). */
40 	acquired = bpf_get_task_exe_file(task);
41 	if (!acquired)
42 		return 0;
43 
44 	bpf_put_file(acquired);
45 	return 0;
46 }
47 
48 SEC("lsm.s/file_open")
49 __failure __msg("R1 must be referenced or trusted")
BPF_PROG(get_task_exe_file_kfunc_untrusted)50 int BPF_PROG(get_task_exe_file_kfunc_untrusted)
51 {
52 	struct file *acquired;
53 	struct task_struct *parent;
54 
55 	/* Walking a trusted struct task_struct returned from
56 	 * bpf_get_current_task_btf() yields an untrusted pointer.
57 	 */
58 	parent = bpf_get_current_task_btf()->parent;
59 	/* Can't pass untrusted pointer to bpf_get_task_exe_file(). */
60 	acquired = bpf_get_task_exe_file(parent);
61 	if (!acquired)
62 		return 0;
63 
64 	bpf_put_file(acquired);
65 	return 0;
66 }
67 
68 SEC("lsm.s/file_open")
69 __failure __msg("Unreleased reference")
BPF_PROG(get_task_exe_file_kfunc_unreleased)70 int BPF_PROG(get_task_exe_file_kfunc_unreleased)
71 {
72 	struct file *acquired;
73 
74 	acquired = bpf_get_task_exe_file(bpf_get_current_task_btf());
75 	if (!acquired)
76 		return 0;
77 
78 	/* Acquired but never released. */
79 	return 0;
80 }
81 
82 SEC("lsm.s/file_open")
83 __failure __msg("release kernel function bpf_put_file expects")
BPF_PROG(put_file_kfunc_unacquired,struct file * file)84 int BPF_PROG(put_file_kfunc_unacquired, struct file *file)
85 {
86 	/* Can't release an unacquired pointer. */
87 	bpf_put_file(file);
88 	return 0;
89 }
90 
91 SEC("lsm.s/file_open")
92 __failure __msg("Possibly NULL pointer passed to trusted arg0")
BPF_PROG(path_d_path_kfunc_null)93 int BPF_PROG(path_d_path_kfunc_null)
94 {
95 	/* Can't pass NULL value to bpf_path_d_path() kfunc. */
96 	bpf_path_d_path(NULL, buf, sizeof(buf));
97 	return 0;
98 }
99 
100 SEC("lsm.s/task_alloc")
101 __failure __msg("R1 must be referenced or trusted")
BPF_PROG(path_d_path_kfunc_untrusted_from_argument,struct task_struct * task)102 int BPF_PROG(path_d_path_kfunc_untrusted_from_argument, struct task_struct *task)
103 {
104 	struct path *root;
105 
106 	/* Walking a trusted argument typically yields an untrusted
107 	 * pointer. This is one example of that.
108 	 */
109 	root = &task->fs->root;
110 	bpf_path_d_path(root, buf, sizeof(buf));
111 	return 0;
112 }
113 
114 SEC("lsm.s/file_open")
115 __failure __msg("R1 must be referenced or trusted")
BPF_PROG(path_d_path_kfunc_untrusted_from_current)116 int BPF_PROG(path_d_path_kfunc_untrusted_from_current)
117 {
118 	struct path *pwd;
119 	struct task_struct *current;
120 
121 	current = bpf_get_current_task_btf();
122 	/* Walking a trusted pointer returned from bpf_get_current_task_btf()
123 	 * yields an untrusted pointer.
124 	 */
125 	pwd = &current->fs->pwd;
126 	bpf_path_d_path(pwd, buf, sizeof(buf));
127 	return 0;
128 }
129 
130 SEC("lsm.s/file_open")
131 __failure __msg("kernel function bpf_path_d_path args#0 expected pointer to STRUCT path but R1 has a pointer to STRUCT file")
BPF_PROG(path_d_path_kfunc_type_mismatch,struct file * file)132 int BPF_PROG(path_d_path_kfunc_type_mismatch, struct file *file)
133 {
134 	bpf_path_d_path((struct path *)&file->f_task_work, buf, sizeof(buf));
135 	return 0;
136 }
137 
138 SEC("lsm.s/file_open")
139 __failure __msg("invalid access to map value, value_size=4096 off=0 size=8192")
BPF_PROG(path_d_path_kfunc_invalid_buf_sz,struct file * file)140 int BPF_PROG(path_d_path_kfunc_invalid_buf_sz, struct file *file)
141 {
142 	/* bpf_path_d_path() enforces a constraint on the buffer size supplied
143 	 * by the BPF LSM program via the __sz annotation. buf here is set to
144 	 * PATH_MAX, so let's ensure that the BPF verifier rejects BPF_PROG_LOAD
145 	 * attempts if the supplied size and the actual size of the buffer
146 	 * mismatches.
147 	 */
148 	bpf_path_d_path(&file->f_path, buf, PATH_MAX * 2);
149 	return 0;
150 }
151 
152 SEC("fentry/vfs_open")
153 __failure __msg("calling kernel function bpf_path_d_path is not allowed")
BPF_PROG(path_d_path_kfunc_non_lsm,struct path * path,struct file * f)154 int BPF_PROG(path_d_path_kfunc_non_lsm, struct path *path, struct file *f)
155 {
156 	/* Calling bpf_path_d_path() from a non-LSM BPF program isn't permitted.
157 	 */
158 	bpf_path_d_path(path, buf, sizeof(buf));
159 	return 0;
160 }
161 
162 SEC("lsm.s/inode_rename")
163 __failure __msg("invalid mem access 'trusted_ptr_or_null_'")
BPF_PROG(inode_rename,struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)164 int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
165 	     struct inode *new_dir, struct dentry *new_dentry,
166 	     unsigned int flags)
167 {
168 	struct inode *inode = new_dentry->d_inode;
169 	ino_t ino;
170 
171 	ino = inode->i_ino;
172 	if (ino == 0)
173 		return -EACCES;
174 	return 0;
175 }
176 char _license[] SEC("license") = "GPL";
177