aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/cgroup.c92
-rw-r--r--kernel/bpf/syscall.c7
-rw-r--r--kernel/bpf/verifier.c1
3 files changed, 100 insertions, 0 deletions
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index f6cd38746df2..610491b5f0aa 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -11,7 +11,9 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/atomic.h> 12#include <linux/atomic.h>
13#include <linux/cgroup.h> 13#include <linux/cgroup.h>
14#include <linux/filter.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/sysctl.h>
15#include <linux/bpf.h> 17#include <linux/bpf.h>
16#include <linux/bpf-cgroup.h> 18#include <linux/bpf-cgroup.h>
17#include <net/sock.h> 19#include <net/sock.h>
@@ -768,3 +770,93 @@ const struct bpf_verifier_ops cg_dev_verifier_ops = {
768 .get_func_proto = cgroup_dev_func_proto, 770 .get_func_proto = cgroup_dev_func_proto,
769 .is_valid_access = cgroup_dev_is_valid_access, 771 .is_valid_access = cgroup_dev_is_valid_access,
770}; 772};
773
774/**
775 * __cgroup_bpf_run_filter_sysctl - Run a program on sysctl
776 *
777 * @head: sysctl table header
778 * @table: sysctl table
779 * @write: sysctl is being read (= 0) or written (= 1)
780 * @type: type of program to be executed
781 *
782 * Program is run when sysctl is being accessed, either read or written, and
783 * can allow or deny such access.
784 *
785 * This function will return %-EPERM if an attached program is found and
786 * returned value != 1 during execution. In all other cases 0 is returned.
787 */
788int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
789 struct ctl_table *table, int write,
790 enum bpf_attach_type type)
791{
792 struct bpf_sysctl_kern ctx = {
793 .head = head,
794 .table = table,
795 .write = write,
796 };
797 struct cgroup *cgrp;
798 int ret;
799
800 rcu_read_lock();
801 cgrp = task_dfl_cgroup(current);
802 ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], &ctx, BPF_PROG_RUN);
803 rcu_read_unlock();
804
805 return ret == 1 ? 0 : -EPERM;
806}
807EXPORT_SYMBOL(__cgroup_bpf_run_filter_sysctl);
808
809static const struct bpf_func_proto *
810sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
811{
812 return cgroup_base_func_proto(func_id, prog);
813}
814
815static bool sysctl_is_valid_access(int off, int size, enum bpf_access_type type,
816 const struct bpf_prog *prog,
817 struct bpf_insn_access_aux *info)
818{
819 const int size_default = sizeof(__u32);
820
821 if (off < 0 || off + size > sizeof(struct bpf_sysctl) ||
822 off % size || type != BPF_READ)
823 return false;
824
825 switch (off) {
826 case offsetof(struct bpf_sysctl, write):
827 bpf_ctx_record_field_size(info, size_default);
828 return bpf_ctx_narrow_access_ok(off, size, size_default);
829 default:
830 return false;
831 }
832}
833
834static u32 sysctl_convert_ctx_access(enum bpf_access_type type,
835 const struct bpf_insn *si,
836 struct bpf_insn *insn_buf,
837 struct bpf_prog *prog, u32 *target_size)
838{
839 struct bpf_insn *insn = insn_buf;
840
841 switch (si->off) {
842 case offsetof(struct bpf_sysctl, write):
843 *insn++ = BPF_LDX_MEM(
844 BPF_SIZE(si->code), si->dst_reg, si->src_reg,
845 bpf_target_off(struct bpf_sysctl_kern, write,
846 FIELD_SIZEOF(struct bpf_sysctl_kern,
847 write),
848 target_size));
849 break;
850 }
851
852 return insn - insn_buf;
853}
854
855const struct bpf_verifier_ops cg_sysctl_verifier_ops = {
856 .get_func_proto = sysctl_func_proto,
857 .is_valid_access = sysctl_is_valid_access,
858 .convert_ctx_access = sysctl_convert_ctx_access,
859};
860
861const struct bpf_prog_ops cg_sysctl_prog_ops = {
862};
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index d995eedfdd16..92c9b8a32b50 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1888,6 +1888,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1888 case BPF_FLOW_DISSECTOR: 1888 case BPF_FLOW_DISSECTOR:
1889 ptype = BPF_PROG_TYPE_FLOW_DISSECTOR; 1889 ptype = BPF_PROG_TYPE_FLOW_DISSECTOR;
1890 break; 1890 break;
1891 case BPF_CGROUP_SYSCTL:
1892 ptype = BPF_PROG_TYPE_CGROUP_SYSCTL;
1893 break;
1891 default: 1894 default:
1892 return -EINVAL; 1895 return -EINVAL;
1893 } 1896 }
@@ -1966,6 +1969,9 @@ static int bpf_prog_detach(const union bpf_attr *attr)
1966 return lirc_prog_detach(attr); 1969 return lirc_prog_detach(attr);
1967 case BPF_FLOW_DISSECTOR: 1970 case BPF_FLOW_DISSECTOR:
1968 return skb_flow_dissector_bpf_prog_detach(attr); 1971 return skb_flow_dissector_bpf_prog_detach(attr);
1972 case BPF_CGROUP_SYSCTL:
1973 ptype = BPF_PROG_TYPE_CGROUP_SYSCTL;
1974 break;
1969 default: 1975 default:
1970 return -EINVAL; 1976 return -EINVAL;
1971 } 1977 }
@@ -1999,6 +2005,7 @@ static int bpf_prog_query(const union bpf_attr *attr,
1999 case BPF_CGROUP_UDP6_SENDMSG: 2005 case BPF_CGROUP_UDP6_SENDMSG:
2000 case BPF_CGROUP_SOCK_OPS: 2006 case BPF_CGROUP_SOCK_OPS:
2001 case BPF_CGROUP_DEVICE: 2007 case BPF_CGROUP_DEVICE:
2008 case BPF_CGROUP_SYSCTL:
2002 break; 2009 break;
2003 case BPF_LIRC_MODE2: 2010 case BPF_LIRC_MODE2:
2004 return lirc_prog_query(attr, uattr); 2011 return lirc_prog_query(attr, uattr);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index f25b7c9c20ba..20808e3c95a8 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5267,6 +5267,7 @@ static int check_return_code(struct bpf_verifier_env *env)
5267 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: 5267 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
5268 case BPF_PROG_TYPE_SOCK_OPS: 5268 case BPF_PROG_TYPE_SOCK_OPS:
5269 case BPF_PROG_TYPE_CGROUP_DEVICE: 5269 case BPF_PROG_TYPE_CGROUP_DEVICE:
5270 case BPF_PROG_TYPE_CGROUP_SYSCTL:
5270 break; 5271 break;
5271 default: 5272 default:
5272 return 0; 5273 return 0;