mirror of https://github.com/OpenIPC/firmware.git
100 lines
2.4 KiB
Diff
100 lines
2.4 KiB
Diff
diff -drupN a/kernel/bpf/inode.c b/kernel/bpf/inode.c
|
|
--- a/kernel/bpf/inode.c 2018-08-06 17:23:04.000000000 +0300
|
|
+++ b/kernel/bpf/inode.c 2022-06-12 05:28:14.000000000 +0300
|
|
@@ -255,7 +255,7 @@ out:
|
|
}
|
|
|
|
static void *bpf_obj_do_get(const struct filename *pathname,
|
|
- enum bpf_type *type)
|
|
+ enum bpf_type *type, int flags)
|
|
{
|
|
struct inode *inode;
|
|
struct path path;
|
|
@@ -267,7 +267,7 @@ static void *bpf_obj_do_get(const struct
|
|
return ERR_PTR(ret);
|
|
|
|
inode = d_backing_inode(path.dentry);
|
|
- ret = inode_permission(inode, MAY_WRITE);
|
|
+ ret = inode_permission(inode, ACC_MODE(flags));
|
|
if (ret)
|
|
goto out;
|
|
|
|
@@ -286,18 +286,23 @@ out:
|
|
return ERR_PTR(ret);
|
|
}
|
|
|
|
-int bpf_obj_get_user(const char __user *pathname)
|
|
+int bpf_obj_get_user(const char __user *pathname, int flags)
|
|
{
|
|
enum bpf_type type = BPF_TYPE_UNSPEC;
|
|
struct filename *pname;
|
|
int ret = -ENOENT;
|
|
+ int f_flags;
|
|
void *raw;
|
|
|
|
+ f_flags = bpf_get_file_flag(flags);
|
|
+ if (f_flags < 0)
|
|
+ return f_flags;
|
|
+
|
|
pname = getname(pathname);
|
|
if (IS_ERR(pname))
|
|
return PTR_ERR(pname);
|
|
|
|
- raw = bpf_obj_do_get(pname, &type);
|
|
+ raw = bpf_obj_do_get(pname, &type, f_flags);
|
|
if (IS_ERR(raw)) {
|
|
ret = PTR_ERR(raw);
|
|
goto out;
|
|
@@ -306,7 +311,7 @@ int bpf_obj_get_user(const char __user *
|
|
if (type == BPF_TYPE_PROG)
|
|
ret = bpf_prog_new_fd(raw);
|
|
else if (type == BPF_TYPE_MAP)
|
|
- ret = bpf_map_new_fd(raw);
|
|
+ ret = bpf_map_new_fd(raw, f_flags);
|
|
else
|
|
goto out;
|
|
|
|
@@ -317,6 +322,42 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+static struct bpf_prog *__get_prog_inode(struct inode *inode, enum bpf_prog_type type)
|
|
+{
|
|
+ struct bpf_prog *prog;
|
|
+ int ret = inode_permission(inode, MAY_READ | MAY_WRITE);
|
|
+ if (ret)
|
|
+ return ERR_PTR(ret);
|
|
+
|
|
+ if (inode->i_op == &bpf_map_iops)
|
|
+ return ERR_PTR(-EINVAL);
|
|
+ if (inode->i_op != &bpf_prog_iops)
|
|
+ return ERR_PTR(-EACCES);
|
|
+
|
|
+ prog = inode->i_private;
|
|
+
|
|
+ ret = security_bpf_prog(prog);
|
|
+ if (ret < 0)
|
|
+ return ERR_PTR(ret);
|
|
+
|
|
+ return bpf_prog_inc(prog);
|
|
+}
|
|
+
|
|
+struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type)
|
|
+{
|
|
+ struct bpf_prog *prog;
|
|
+ struct path path;
|
|
+ int ret = kern_path(name, LOOKUP_FOLLOW, &path);
|
|
+ if (ret)
|
|
+ return ERR_PTR(ret);
|
|
+ prog = __get_prog_inode(d_backing_inode(path.dentry), type);
|
|
+ if (!IS_ERR(prog))
|
|
+ touch_atime(&path);
|
|
+ path_put(&path);
|
|
+ return prog;
|
|
+}
|
|
+EXPORT_SYMBOL(bpf_prog_get_type_path);
|
|
+
|
|
static void bpf_evict_inode(struct inode *inode)
|
|
{
|
|
enum bpf_type type;
|