]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - kernel/bpf/inode.c
bpf, inode: add support for symlinks and fix mtime/ctime
[karo-tx-linux.git] / kernel / bpf / inode.c
1 /*
2  * Minimal file system backend for holding eBPF maps and programs,
3  * used by bpf(2) object pinning.
4  *
5  * Authors:
6  *
7  *      Daniel Borkmann <daniel@iogearbox.net>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * version 2 as published by the Free Software Foundation.
12  */
13
14 #include <linux/init.h>
15 #include <linux/magic.h>
16 #include <linux/major.h>
17 #include <linux/mount.h>
18 #include <linux/namei.h>
19 #include <linux/fs.h>
20 #include <linux/kdev_t.h>
21 #include <linux/filter.h>
22 #include <linux/bpf.h>
23
24 enum bpf_type {
25         BPF_TYPE_UNSPEC = 0,
26         BPF_TYPE_PROG,
27         BPF_TYPE_MAP,
28 };
29
30 static void *bpf_any_get(void *raw, enum bpf_type type)
31 {
32         switch (type) {
33         case BPF_TYPE_PROG:
34                 raw = bpf_prog_inc(raw);
35                 break;
36         case BPF_TYPE_MAP:
37                 raw = bpf_map_inc(raw, true);
38                 break;
39         default:
40                 WARN_ON_ONCE(1);
41                 break;
42         }
43
44         return raw;
45 }
46
47 static void bpf_any_put(void *raw, enum bpf_type type)
48 {
49         switch (type) {
50         case BPF_TYPE_PROG:
51                 bpf_prog_put(raw);
52                 break;
53         case BPF_TYPE_MAP:
54                 bpf_map_put_with_uref(raw);
55                 break;
56         default:
57                 WARN_ON_ONCE(1);
58                 break;
59         }
60 }
61
62 static void *bpf_fd_probe_obj(u32 ufd, enum bpf_type *type)
63 {
64         void *raw;
65
66         *type = BPF_TYPE_MAP;
67         raw = bpf_map_get_with_uref(ufd);
68         if (IS_ERR(raw)) {
69                 *type = BPF_TYPE_PROG;
70                 raw = bpf_prog_get(ufd);
71         }
72
73         return raw;
74 }
75
76 static const struct inode_operations bpf_dir_iops;
77
78 static const struct inode_operations bpf_prog_iops = { };
79 static const struct inode_operations bpf_map_iops  = { };
80
81 static struct inode *bpf_get_inode(struct super_block *sb,
82                                    const struct inode *dir,
83                                    umode_t mode)
84 {
85         struct inode *inode;
86
87         switch (mode & S_IFMT) {
88         case S_IFDIR:
89         case S_IFREG:
90         case S_IFLNK:
91                 break;
92         default:
93                 return ERR_PTR(-EINVAL);
94         }
95
96         inode = new_inode(sb);
97         if (!inode)
98                 return ERR_PTR(-ENOSPC);
99
100         inode->i_ino = get_next_ino();
101         inode->i_atime = current_time(inode);
102         inode->i_mtime = inode->i_atime;
103         inode->i_ctime = inode->i_atime;
104
105         inode_init_owner(inode, dir, mode);
106
107         return inode;
108 }
109
110 static int bpf_inode_type(const struct inode *inode, enum bpf_type *type)
111 {
112         *type = BPF_TYPE_UNSPEC;
113         if (inode->i_op == &bpf_prog_iops)
114                 *type = BPF_TYPE_PROG;
115         else if (inode->i_op == &bpf_map_iops)
116                 *type = BPF_TYPE_MAP;
117         else
118                 return -EACCES;
119
120         return 0;
121 }
122
123 static void bpf_dentry_finalize(struct dentry *dentry, struct inode *inode,
124                                 struct inode *dir)
125 {
126         d_instantiate(dentry, inode);
127         dget(dentry);
128
129         dir->i_mtime = current_time(dir);
130         dir->i_ctime = dir->i_mtime;
131 }
132
133 static int bpf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
134 {
135         struct inode *inode;
136
137         inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFDIR);
138         if (IS_ERR(inode))
139                 return PTR_ERR(inode);
140
141         inode->i_op = &bpf_dir_iops;
142         inode->i_fop = &simple_dir_operations;
143
144         inc_nlink(inode);
145         inc_nlink(dir);
146
147         bpf_dentry_finalize(dentry, inode, dir);
148         return 0;
149 }
150
151 static int bpf_mkobj_ops(struct inode *dir, struct dentry *dentry,
152                          umode_t mode, const struct inode_operations *iops)
153 {
154         struct inode *inode;
155
156         inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFREG);
157         if (IS_ERR(inode))
158                 return PTR_ERR(inode);
159
160         inode->i_op = iops;
161         inode->i_private = dentry->d_fsdata;
162
163         bpf_dentry_finalize(dentry, inode, dir);
164         return 0;
165 }
166
167 static int bpf_mkobj(struct inode *dir, struct dentry *dentry, umode_t mode,
168                      dev_t devt)
169 {
170         enum bpf_type type = MINOR(devt);
171
172         if (MAJOR(devt) != UNNAMED_MAJOR || !S_ISREG(mode) ||
173             dentry->d_fsdata == NULL)
174                 return -EPERM;
175
176         switch (type) {
177         case BPF_TYPE_PROG:
178                 return bpf_mkobj_ops(dir, dentry, mode, &bpf_prog_iops);
179         case BPF_TYPE_MAP:
180                 return bpf_mkobj_ops(dir, dentry, mode, &bpf_map_iops);
181         default:
182                 return -EPERM;
183         }
184 }
185
186 static struct dentry *
187 bpf_lookup(struct inode *dir, struct dentry *dentry, unsigned flags)
188 {
189         if (strchr(dentry->d_name.name, '.'))
190                 return ERR_PTR(-EPERM);
191
192         return simple_lookup(dir, dentry, flags);
193 }
194
195 static int bpf_symlink(struct inode *dir, struct dentry *dentry,
196                        const char *target)
197 {
198         char *link = kstrdup(target, GFP_USER | __GFP_NOWARN);
199         struct inode *inode;
200
201         if (!link)
202                 return -ENOMEM;
203
204         inode = bpf_get_inode(dir->i_sb, dir, S_IRWXUGO | S_IFLNK);
205         if (IS_ERR(inode)) {
206                 kfree(link);
207                 return PTR_ERR(inode);
208         }
209
210         inode->i_op = &simple_symlink_inode_operations;
211         inode->i_link = link;
212
213         bpf_dentry_finalize(dentry, inode, dir);
214         return 0;
215 }
216
217 static const struct inode_operations bpf_dir_iops = {
218         .lookup         = bpf_lookup,
219         .mknod          = bpf_mkobj,
220         .mkdir          = bpf_mkdir,
221         .symlink        = bpf_symlink,
222         .rmdir          = simple_rmdir,
223         .rename         = simple_rename,
224         .link           = simple_link,
225         .unlink         = simple_unlink,
226 };
227
228 static int bpf_obj_do_pin(const struct filename *pathname, void *raw,
229                           enum bpf_type type)
230 {
231         struct dentry *dentry;
232         struct inode *dir;
233         struct path path;
234         umode_t mode;
235         dev_t devt;
236         int ret;
237
238         dentry = kern_path_create(AT_FDCWD, pathname->name, &path, 0);
239         if (IS_ERR(dentry))
240                 return PTR_ERR(dentry);
241
242         mode = S_IFREG | ((S_IRUSR | S_IWUSR) & ~current_umask());
243         devt = MKDEV(UNNAMED_MAJOR, type);
244
245         ret = security_path_mknod(&path, dentry, mode, devt);
246         if (ret)
247                 goto out;
248
249         dir = d_inode(path.dentry);
250         if (dir->i_op != &bpf_dir_iops) {
251                 ret = -EPERM;
252                 goto out;
253         }
254
255         dentry->d_fsdata = raw;
256         ret = vfs_mknod(dir, dentry, mode, devt);
257         dentry->d_fsdata = NULL;
258 out:
259         done_path_create(&path, dentry);
260         return ret;
261 }
262
263 int bpf_obj_pin_user(u32 ufd, const char __user *pathname)
264 {
265         struct filename *pname;
266         enum bpf_type type;
267         void *raw;
268         int ret;
269
270         pname = getname(pathname);
271         if (IS_ERR(pname))
272                 return PTR_ERR(pname);
273
274         raw = bpf_fd_probe_obj(ufd, &type);
275         if (IS_ERR(raw)) {
276                 ret = PTR_ERR(raw);
277                 goto out;
278         }
279
280         ret = bpf_obj_do_pin(pname, raw, type);
281         if (ret != 0)
282                 bpf_any_put(raw, type);
283 out:
284         putname(pname);
285         return ret;
286 }
287
288 static void *bpf_obj_do_get(const struct filename *pathname,
289                             enum bpf_type *type)
290 {
291         struct inode *inode;
292         struct path path;
293         void *raw;
294         int ret;
295
296         ret = kern_path(pathname->name, LOOKUP_FOLLOW, &path);
297         if (ret)
298                 return ERR_PTR(ret);
299
300         inode = d_backing_inode(path.dentry);
301         ret = inode_permission(inode, MAY_WRITE);
302         if (ret)
303                 goto out;
304
305         ret = bpf_inode_type(inode, type);
306         if (ret)
307                 goto out;
308
309         raw = bpf_any_get(inode->i_private, *type);
310         if (!IS_ERR(raw))
311                 touch_atime(&path);
312
313         path_put(&path);
314         return raw;
315 out:
316         path_put(&path);
317         return ERR_PTR(ret);
318 }
319
320 int bpf_obj_get_user(const char __user *pathname)
321 {
322         enum bpf_type type = BPF_TYPE_UNSPEC;
323         struct filename *pname;
324         int ret = -ENOENT;
325         void *raw;
326
327         pname = getname(pathname);
328         if (IS_ERR(pname))
329                 return PTR_ERR(pname);
330
331         raw = bpf_obj_do_get(pname, &type);
332         if (IS_ERR(raw)) {
333                 ret = PTR_ERR(raw);
334                 goto out;
335         }
336
337         if (type == BPF_TYPE_PROG)
338                 ret = bpf_prog_new_fd(raw);
339         else if (type == BPF_TYPE_MAP)
340                 ret = bpf_map_new_fd(raw);
341         else
342                 goto out;
343
344         if (ret < 0)
345                 bpf_any_put(raw, type);
346 out:
347         putname(pname);
348         return ret;
349 }
350
351 static void bpf_evict_inode(struct inode *inode)
352 {
353         enum bpf_type type;
354
355         truncate_inode_pages_final(&inode->i_data);
356         clear_inode(inode);
357
358         if (S_ISLNK(inode->i_mode))
359                 kfree(inode->i_link);
360         if (!bpf_inode_type(inode, &type))
361                 bpf_any_put(inode->i_private, type);
362 }
363
364 static const struct super_operations bpf_super_ops = {
365         .statfs         = simple_statfs,
366         .drop_inode     = generic_delete_inode,
367         .evict_inode    = bpf_evict_inode,
368 };
369
370 static int bpf_fill_super(struct super_block *sb, void *data, int silent)
371 {
372         static struct tree_descr bpf_rfiles[] = { { "" } };
373         struct inode *inode;
374         int ret;
375
376         ret = simple_fill_super(sb, BPF_FS_MAGIC, bpf_rfiles);
377         if (ret)
378                 return ret;
379
380         sb->s_op = &bpf_super_ops;
381
382         inode = sb->s_root->d_inode;
383         inode->i_op = &bpf_dir_iops;
384         inode->i_mode &= ~S_IALLUGO;
385         inode->i_mode |= S_ISVTX | S_IRWXUGO;
386
387         return 0;
388 }
389
390 static struct dentry *bpf_mount(struct file_system_type *type, int flags,
391                                 const char *dev_name, void *data)
392 {
393         return mount_nodev(type, flags, data, bpf_fill_super);
394 }
395
396 static struct file_system_type bpf_fs_type = {
397         .owner          = THIS_MODULE,
398         .name           = "bpf",
399         .mount          = bpf_mount,
400         .kill_sb        = kill_litter_super,
401 };
402
403 static int __init bpf_init(void)
404 {
405         int ret;
406
407         ret = sysfs_create_mount_point(fs_kobj, "bpf");
408         if (ret)
409                 return ret;
410
411         ret = register_filesystem(&bpf_fs_type);
412         if (ret)
413                 sysfs_remove_mount_point(fs_kobj, "bpf");
414
415         return ret;
416 }
417 fs_initcall(bpf_init);