powerpc64/bpf elfv1: Do not load TOC before calling functions
authorNaveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Mon, 14 Feb 2022 10:41:42 +0000 (16:11 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 7 Mar 2022 13:04:58 +0000 (00:04 +1100)
BPF helpers always reside in core kernel and all BPF programs use the
kernel TOC. As such, there is no need to load the TOC before calling
helpers or other BPF functions. Drop code to do the same.

Add a check to ensure we don't proceed if this assumption ever changes
in future.

Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/a3cd3da4d24d95d845cd10382b1af083600c9074.1644834730.git.naveen.n.rao@linux.vnet.ibm.com
arch/powerpc/net/bpf_jit.h
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/net/bpf_jit_comp32.c
arch/powerpc/net/bpf_jit_comp64.c

index e58cf29bb0cf6736ce3533a49ec928d1f3bdca6a..ea384ae836cc9c89c3a32befb6fa9ab1e834903e 100644 (file)
@@ -178,7 +178,7 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
        ctx->seen &= ~(1 << (31 - i));
 }
 
-void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
+int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
                       u32 *addrs, int pass);
 void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
index 141e64585b6458754d705cf8702c37a3a90445db..635f7448ff795200b027f07b702ec59417053e6c 100644 (file)
@@ -59,7 +59,9 @@ static int bpf_jit_fixup_addresses(struct bpf_prog *fp, u32 *image,
                         */
                        tmp_idx = ctx->idx;
                        ctx->idx = addrs[i] / 4;
-                       bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+                       ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+                       if (ret)
+                               return ret;
 
                        /*
                         * Restore ctx->idx here. This is safe as the length
index 8e743b7bf8f51aed07759e77145a0ee2ed394f84..511d2a203e7d62bbc7e1ac2979fdf9a36f1b71c5 100644 (file)
@@ -193,7 +193,7 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
        EMIT(PPC_RAW_BLR());
 }
 
-void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
+int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
 {
        s32 rel = (s32)func - (s32)(image + ctx->idx);
 
@@ -209,6 +209,8 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
                EMIT(PPC_RAW_MTCTR(_R0));
                EMIT(PPC_RAW_BCTRL());
        }
+
+       return 0;
 }
 
 static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
@@ -961,7 +963,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
                                EMIT(PPC_RAW_STW(bpf_to_ppc(ctx, BPF_REG_5), _R1, 12));
                        }
 
-                       bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+                       ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+                       if (ret)
+                               return ret;
 
                        EMIT(PPC_RAW_MR(bpf_to_ppc(ctx, BPF_REG_0) - 1, _R3));
                        EMIT(PPC_RAW_MR(bpf_to_ppc(ctx, BPF_REG_0), _R4));
index 44314ee60155e40c3179aec7309686c90454d6a4..e9fd4694226fe0d312577474f8702ea075a18224 100644 (file)
@@ -147,9 +147,13 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
        EMIT(PPC_RAW_BLR());
 }
 
-static void bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx,
-                                      u64 func)
+static int bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx, u64 func)
 {
+       unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0;
+
+       if (WARN_ON_ONCE(!core_kernel_text(func_addr)))
+               return -EINVAL;
+
 #ifdef PPC64_ELF_ABI_v1
        /* func points to the function descriptor */
        PPC_LI64(b2p[TMP_REG_2], func);
@@ -157,25 +161,23 @@ static void bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx,
        PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_2], 0);
        /* ... and move it to CTR */
        EMIT(PPC_RAW_MTCTR(b2p[TMP_REG_1]));
-       /*
-        * Load TOC from function descriptor at offset 8.
-        * We can clobber r2 since we get called through a
-        * function pointer (so caller will save/restore r2)
-        * and since we don't use a TOC ourself.
-        */
-       PPC_BPF_LL(2, b2p[TMP_REG_2], 8);
 #else
        /* We can clobber r12 */
        PPC_FUNC_ADDR(12, func);
        EMIT(PPC_RAW_MTCTR(12));
 #endif
        EMIT(PPC_RAW_BCTRL());
+
+       return 0;
 }
 
-void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
+int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
 {
        unsigned int i, ctx_idx = ctx->idx;
 
+       if (WARN_ON_ONCE(func && is_module_text_address(func)))
+               return -EINVAL;
+
        /* Load function address into r12 */
        PPC_LI64(12, func);
 
@@ -193,19 +195,14 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
                EMIT(PPC_RAW_NOP());
 
 #ifdef PPC64_ELF_ABI_v1
-       /*
-        * Load TOC from function descriptor at offset 8.
-        * We can clobber r2 since we get called through a
-        * function pointer (so caller will save/restore r2)
-        * and since we don't use a TOC ourself.
-        */
-       PPC_BPF_LL(2, 12, 8);
        /* Load actual entry point from function descriptor */
        PPC_BPF_LL(12, 12, 0);
 #endif
 
        EMIT(PPC_RAW_MTCTR(12));
        EMIT(PPC_RAW_BCTRL());
+
+       return 0;
 }
 
 static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
@@ -890,9 +887,13 @@ emit_clear:
                                return ret;
 
                        if (func_addr_fixed)
-                               bpf_jit_emit_func_call_hlp(image, ctx, func_addr);
+                               ret = bpf_jit_emit_func_call_hlp(image, ctx, func_addr);
                        else
-                               bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+                               ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+
+                       if (ret)
+                               return ret;
+
                        /* move return value from r3 to BPF_REG_0 */
                        EMIT(PPC_RAW_MR(b2p[BPF_REG_0], 3));
                        break;