]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/progs/local_storage.c
Linux 6.14-rc3
[linux.git] / tools / testing / selftests / bpf / progs / local_storage.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * Copyright 2020 Google LLC.
5  */
6
7 #include "vmlinux.h"
8 #include <errno.h>
9 #include <bpf/bpf_helpers.h>
10 #include <bpf/bpf_tracing.h>
11
12 char _license[] SEC("license") = "GPL";
13
14 #define DUMMY_STORAGE_VALUE 0xdeadbeef
15
16 __u32 monitored_pid = 0;
17 int inode_storage_result = -1;
18 int sk_storage_result = -1;
19 int task_storage_result = -1;
20
21 struct local_storage {
22         struct inode *exec_inode;
23         __u32 value;
24 };
25
26 struct {
27         __uint(type, BPF_MAP_TYPE_INODE_STORAGE);
28         __uint(map_flags, BPF_F_NO_PREALLOC);
29         __type(key, int);
30         __type(value, struct local_storage);
31 } inode_storage_map SEC(".maps");
32
33 struct {
34         __uint(type, BPF_MAP_TYPE_SK_STORAGE);
35         __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE);
36         __type(key, int);
37         __type(value, struct local_storage);
38 } sk_storage_map SEC(".maps");
39
40 struct {
41         __uint(type, BPF_MAP_TYPE_SK_STORAGE);
42         __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE);
43         __type(key, int);
44         __type(value, struct local_storage);
45 } sk_storage_map2 SEC(".maps");
46
47 struct {
48         __uint(type, BPF_MAP_TYPE_TASK_STORAGE);
49         __uint(map_flags, BPF_F_NO_PREALLOC);
50         __type(key, int);
51         __type(value, struct local_storage);
52 } task_storage_map SEC(".maps");
53
54 struct {
55         __uint(type, BPF_MAP_TYPE_TASK_STORAGE);
56         __uint(map_flags, BPF_F_NO_PREALLOC);
57         __type(key, int);
58         __type(value, struct local_storage);
59 } task_storage_map2 SEC(".maps");
60
61 SEC("lsm/inode_unlink")
62 int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
63 {
64         __u32 pid = bpf_get_current_pid_tgid() >> 32;
65         struct bpf_local_storage *local_storage;
66         struct local_storage *storage;
67         struct task_struct *task;
68         bool is_self_unlink;
69
70         if (pid != monitored_pid)
71                 return 0;
72
73         task = bpf_get_current_task_btf();
74         if (!task)
75                 return 0;
76
77         task_storage_result = -1;
78
79         storage = bpf_task_storage_get(&task_storage_map, task, 0, 0);
80         if (!storage)
81                 return 0;
82
83         /* Don't let an executable delete itself */
84         is_self_unlink = storage->exec_inode == victim->d_inode;
85
86         storage = bpf_task_storage_get(&task_storage_map2, task, 0,
87                                        BPF_LOCAL_STORAGE_GET_F_CREATE);
88         if (!storage || storage->value)
89                 return 0;
90
91         if (bpf_task_storage_delete(&task_storage_map, task))
92                 return 0;
93
94         /* Ensure that the task_storage_map is disconnected from the storage.
95          * The storage memory should not be freed back to the
96          * bpf_mem_alloc.
97          */
98         local_storage = task->bpf_storage;
99         if (!local_storage || local_storage->smap)
100                 return 0;
101
102         task_storage_result = 0;
103
104         return is_self_unlink ? -EPERM : 0;
105 }
106
107 SEC("lsm.s/inode_rename")
108 int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
109              struct inode *new_dir, struct dentry *new_dentry,
110              unsigned int flags)
111 {
112         struct local_storage *storage;
113         int err;
114
115         /* new_dentry->d_inode can be NULL when the inode is renamed to a file
116          * that did not exist before. The helper should be able to handle this
117          * NULL pointer.
118          */
119         bpf_inode_storage_get(&inode_storage_map, new_dentry->d_inode, 0,
120                               BPF_LOCAL_STORAGE_GET_F_CREATE);
121
122         storage = bpf_inode_storage_get(&inode_storage_map, old_dentry->d_inode,
123                                         0, 0);
124         if (!storage)
125                 return 0;
126
127         if (storage->value != DUMMY_STORAGE_VALUE)
128                 inode_storage_result = -1;
129
130         err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode);
131         if (!err)
132                 inode_storage_result = err;
133
134         return 0;
135 }
136
137 SEC("lsm.s/socket_bind")
138 int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
139              int addrlen)
140 {
141         __u32 pid = bpf_get_current_pid_tgid() >> 32;
142         struct local_storage *storage;
143         struct sock *sk = sock->sk;
144
145         if (pid != monitored_pid || !sk)
146                 return 0;
147
148         storage = bpf_sk_storage_get(&sk_storage_map, sk, 0, 0);
149         if (!storage)
150                 return 0;
151
152         sk_storage_result = -1;
153         if (storage->value != DUMMY_STORAGE_VALUE)
154                 return 0;
155
156         /* This tests that we can associate multiple elements
157          * with the local storage.
158          */
159         storage = bpf_sk_storage_get(&sk_storage_map2, sk, 0,
160                                      BPF_LOCAL_STORAGE_GET_F_CREATE);
161         if (!storage)
162                 return 0;
163
164         if (bpf_sk_storage_delete(&sk_storage_map2, sk))
165                 return 0;
166
167         storage = bpf_sk_storage_get(&sk_storage_map2, sk, 0,
168                                      BPF_LOCAL_STORAGE_GET_F_CREATE);
169         if (!storage)
170                 return 0;
171
172         if (bpf_sk_storage_delete(&sk_storage_map, sk))
173                 return 0;
174
175         /* Ensure that the sk_storage_map is disconnected from the storage. */
176         if (!sk->sk_bpf_storage || sk->sk_bpf_storage->smap)
177                 return 0;
178
179         sk_storage_result = 0;
180         return 0;
181 }
182
183 SEC("lsm.s/socket_post_create")
184 int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
185              int protocol, int kern)
186 {
187         __u32 pid = bpf_get_current_pid_tgid() >> 32;
188         struct local_storage *storage;
189         struct sock *sk = sock->sk;
190
191         if (pid != monitored_pid || !sk)
192                 return 0;
193
194         storage = bpf_sk_storage_get(&sk_storage_map, sk, 0,
195                                      BPF_LOCAL_STORAGE_GET_F_CREATE);
196         if (!storage)
197                 return 0;
198
199         storage->value = DUMMY_STORAGE_VALUE;
200
201         return 0;
202 }
203
204 /* This uses the local storage to remember the inode of the binary that a
205  * process was originally executing.
206  */
207 SEC("lsm.s/bprm_committed_creds")
208 void BPF_PROG(exec, struct linux_binprm *bprm)
209 {
210         __u32 pid = bpf_get_current_pid_tgid() >> 32;
211         struct local_storage *storage;
212
213         if (pid != monitored_pid)
214                 return;
215
216         storage = bpf_task_storage_get(&task_storage_map,
217                                        bpf_get_current_task_btf(), 0,
218                                        BPF_LOCAL_STORAGE_GET_F_CREATE);
219         if (storage)
220                 storage->exec_inode = bprm->file->f_inode;
221
222         storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode,
223                                         0, BPF_LOCAL_STORAGE_GET_F_CREATE);
224         if (!storage)
225                 return;
226
227         storage->value = DUMMY_STORAGE_VALUE;
228 }
This page took 0.043448 seconds and 4 git commands to generate.