aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf
diff options
context:
space:
mode:
authorAndrey Ignatov <rdna@fb.com>2019-02-27 16:28:48 -0500
committerAlexei Starovoitov <ast@kernel.org>2019-04-12 16:54:58 -0400
commit808649fb787d918a48a360a668ee4ee9023f0c11 (patch)
treea58fb657373b8886c6ddf715476f62484edc233d /kernel/bpf
parent7b146cebe30cb481b0f70d85779da938da818637 (diff)
bpf: Introduce bpf_sysctl_get_name helper
Add bpf_sysctl_get_name() helper to copy sysctl name (/proc/sys/ entry) into provided by BPF_PROG_TYPE_CGROUP_SYSCTL program buffer. By default full name (w/o /proc/sys/) is copied, e.g. "net/ipv4/tcp_mem". If BPF_F_SYSCTL_BASE_NAME flag is set, only base name will be copied, e.g. "tcp_mem". Documentation for the new helper is provided in bpf.h UAPI. Signed-off-by: Andrey Ignatov <rdna@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/cgroup.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 610491b5f0aa..a68387043244 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -14,6 +14,7 @@
14#include <linux/filter.h> 14#include <linux/filter.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/sysctl.h> 16#include <linux/sysctl.h>
17#include <linux/string.h>
17#include <linux/bpf.h> 18#include <linux/bpf.h>
18#include <linux/bpf-cgroup.h> 19#include <linux/bpf-cgroup.h>
19#include <net/sock.h> 20#include <net/sock.h>
@@ -806,10 +807,77 @@ int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
806} 807}
807EXPORT_SYMBOL(__cgroup_bpf_run_filter_sysctl); 808EXPORT_SYMBOL(__cgroup_bpf_run_filter_sysctl);
808 809
810static ssize_t sysctl_cpy_dir(const struct ctl_dir *dir, char **bufp,
811 size_t *lenp)
812{
813 ssize_t tmp_ret = 0, ret;
814
815 if (dir->header.parent) {
816 tmp_ret = sysctl_cpy_dir(dir->header.parent, bufp, lenp);
817 if (tmp_ret < 0)
818 return tmp_ret;
819 }
820
821 ret = strscpy(*bufp, dir->header.ctl_table[0].procname, *lenp);
822 if (ret < 0)
823 return ret;
824 *bufp += ret;
825 *lenp -= ret;
826 ret += tmp_ret;
827
828 /* Avoid leading slash. */
829 if (!ret)
830 return ret;
831
832 tmp_ret = strscpy(*bufp, "/", *lenp);
833 if (tmp_ret < 0)
834 return tmp_ret;
835 *bufp += tmp_ret;
836 *lenp -= tmp_ret;
837
838 return ret + tmp_ret;
839}
840
841BPF_CALL_4(bpf_sysctl_get_name, struct bpf_sysctl_kern *, ctx, char *, buf,
842 size_t, buf_len, u64, flags)
843{
844 ssize_t tmp_ret = 0, ret;
845
846 if (!buf)
847 return -EINVAL;
848
849 if (!(flags & BPF_F_SYSCTL_BASE_NAME)) {
850 if (!ctx->head)
851 return -EINVAL;
852 tmp_ret = sysctl_cpy_dir(ctx->head->parent, &buf, &buf_len);
853 if (tmp_ret < 0)
854 return tmp_ret;
855 }
856
857 ret = strscpy(buf, ctx->table->procname, buf_len);
858
859 return ret < 0 ? ret : tmp_ret + ret;
860}
861
862static const struct bpf_func_proto bpf_sysctl_get_name_proto = {
863 .func = bpf_sysctl_get_name,
864 .gpl_only = false,
865 .ret_type = RET_INTEGER,
866 .arg1_type = ARG_PTR_TO_CTX,
867 .arg2_type = ARG_PTR_TO_MEM,
868 .arg3_type = ARG_CONST_SIZE,
869 .arg4_type = ARG_ANYTHING,
870};
871
809static const struct bpf_func_proto * 872static const struct bpf_func_proto *
810sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) 873sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
811{ 874{
812 return cgroup_base_func_proto(func_id, prog); 875 switch (func_id) {
876 case BPF_FUNC_sysctl_get_name:
877 return &bpf_sysctl_get_name_proto;
878 default:
879 return cgroup_base_func_proto(func_id, prog);
880 }
813} 881}
814 882
815static bool sysctl_is_valid_access(int off, int size, enum bpf_access_type type, 883static bool sysctl_is_valid_access(int off, int size, enum bpf_access_type type,