Make sure that ubpf load/store instructions only access the context
and stack region.

Signed-off-by: He Kuang <heku...@huawei.com>
---
 tools/perf/util/bpf-vm.c | 35 +++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-vm.h |  3 ++-
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/bpf-vm.c b/tools/perf/util/bpf-vm.c
index 23ac784..191ed42 100644
--- a/tools/perf/util/bpf-vm.c
+++ b/tools/perf/util/bpf-vm.c
@@ -2,6 +2,11 @@
 #include "util.h"
 #include "tools/be_byteshift.h"
 #include "bpf-vm.h"
+#include "debug.h"
+#include <linux/filter.h>
+
+#define DST    regs[insn->dst_reg]
+#define SRC    regs[insn->src_reg]
 
 static inline void
 bpf_vm_jmp_call_handler(u64 *regs __maybe_unused, void *ctx __maybe_unused,
@@ -30,5 +35,35 @@ static inline void *bpf_load_pointer(const void *skb 
__maybe_unused,
        return NULL;
 }
 
+static bool
+bounds_check(void *addr, int size, void *ctx, size_t ctx_len, void *stack)
+{
+       if (ctx && (addr >= ctx && (addr + size) <= (ctx + ctx_len))) {
+               /* Context access */
+               return true;
+       } else if (addr >= stack && (addr + size) <= (stack + MAX_BPF_STACK)) {
+               /* Stack access */
+               return true;
+       }
+
+       pr_debug("bpf: bounds_check failed\n");
+       return false;
+}
+
+#define BOUNDS_CHECK_LOAD(size)                                                
\
+       do {                                                            \
+               if (!bounds_check((void *)SRC + insn->off, size,        \
+                                 ctx, ctx_len, stack)) {               \
+                       return -1;                                      \
+               }                                                       \
+       } while (0)
+#define BOUNDS_CHECK_STORE(size)                                       \
+       do {                                                            \
+               if (!bounds_check((void *)DST + insn->off, size,        \
+                                 ctx, ctx_len, stack)) {               \
+                       return -1;                                      \
+               }                                                       \
+       } while (0)
+
 #define UBPF_BUILD
 #include <../../../kernel/bpf/vm.c>
diff --git a/tools/perf/util/bpf-vm.h b/tools/perf/util/bpf-vm.h
index bf96caa..66956fbb 100644
--- a/tools/perf/util/bpf-vm.h
+++ b/tools/perf/util/bpf-vm.h
@@ -2,6 +2,7 @@
 #define _BPF_VM_H
 
 struct bpf_insn;
-unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn);
+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn,
+                           size_t ctx_len);
 
 #endif /* _BPF_VM_H */
-- 
1.8.5.2

Reply via email to