diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/bpf/cgroup.c | 92 | ||||
-rw-r--r-- | kernel/bpf/syscall.c | 7 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 1 |
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 | */ | ||
788 | int __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 | } | ||
807 | EXPORT_SYMBOL(__cgroup_bpf_run_filter_sysctl); | ||
808 | |||
809 | static const struct bpf_func_proto * | ||
810 | sysctl_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 | |||
815 | static 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 | |||
834 | static 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 | |||
855 | const 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 | |||
861 | const 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; |