|
@@ -522,3 +522,70 @@ int __cgroup_bpf_run_filter_sock_ops(struct sock *sk,
|
|
|
return ret == 1 ? 0 : -EPERM;
|
|
|
}
|
|
|
EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_ops);
|
|
|
+
|
|
|
+int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
|
|
|
+ short access, enum bpf_attach_type type)
|
|
|
+{
|
|
|
+ struct cgroup *cgrp;
|
|
|
+ struct bpf_cgroup_dev_ctx ctx = {
|
|
|
+ .access_type = (access << 16) | dev_type,
|
|
|
+ .major = major,
|
|
|
+ .minor = minor,
|
|
|
+ };
|
|
|
+ int allow = 1;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ cgrp = task_dfl_cgroup(current);
|
|
|
+ allow = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], &ctx,
|
|
|
+ BPF_PROG_RUN);
|
|
|
+ rcu_read_unlock();
|
|
|
+
|
|
|
+ return !allow;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(__cgroup_bpf_check_dev_permission);
|
|
|
+
|
|
|
+static const struct bpf_func_proto *
|
|
|
+cgroup_dev_func_proto(enum bpf_func_id func_id)
|
|
|
+{
|
|
|
+ switch (func_id) {
|
|
|
+ case BPF_FUNC_map_lookup_elem:
|
|
|
+ return &bpf_map_lookup_elem_proto;
|
|
|
+ case BPF_FUNC_map_update_elem:
|
|
|
+ return &bpf_map_update_elem_proto;
|
|
|
+ case BPF_FUNC_map_delete_elem:
|
|
|
+ return &bpf_map_delete_elem_proto;
|
|
|
+ case BPF_FUNC_get_current_uid_gid:
|
|
|
+ return &bpf_get_current_uid_gid_proto;
|
|
|
+ case BPF_FUNC_trace_printk:
|
|
|
+ if (capable(CAP_SYS_ADMIN))
|
|
|
+ return bpf_get_trace_printk_proto();
|
|
|
+ default:
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static bool cgroup_dev_is_valid_access(int off, int size,
|
|
|
+ enum bpf_access_type type,
|
|
|
+ struct bpf_insn_access_aux *info)
|
|
|
+{
|
|
|
+ if (type == BPF_WRITE)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (off < 0 || off + size > sizeof(struct bpf_cgroup_dev_ctx))
|
|
|
+ return false;
|
|
|
+ /* The verifier guarantees that size > 0. */
|
|
|
+ if (off % size != 0)
|
|
|
+ return false;
|
|
|
+ if (size != sizeof(__u32))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+const struct bpf_prog_ops cg_dev_prog_ops = {
|
|
|
+};
|
|
|
+
|
|
|
+const struct bpf_verifier_ops cg_dev_verifier_ops = {
|
|
|
+ .get_func_proto = cgroup_dev_func_proto,
|
|
|
+ .is_valid_access = cgroup_dev_is_valid_access,
|
|
|
+};
|