linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] bpf: Avoid function casting when calculating immediate
@ 2020-01-29 21:36 Kees Cook
  2020-02-17 15:51 ` Daniel Borkmann
  0 siblings, 1 reply; 3+ messages in thread
From: Kees Cook @ 2020-01-29 21:36 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: linux-kernel, Daniel Borkmann, Martin KaFai Lau, Song Liu,
	Yonghong Song, Andrii Nakryiko, Sami Tolvanen, bpf

In an effort to enable -Wcast-function-type in the top-level Makefile
to support Control Flow Integrity builds, rework the BPF instruction
immediate calculation macros to avoid mismatched function pointers. Since
these calculations are only ever between function address (these are
not function calls, just address calculations), they can be cast to u64
instead, where the result will be assigned to the s32 insn->imm.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/filter.h |  6 +++---
 kernel/bpf/hashtab.c   |  6 +++---
 kernel/bpf/verifier.c  | 21 +++++++--------------
 3 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index f349e2c0884c..b5beee7bf2ea 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -340,8 +340,8 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
 
 /* Function call */
 
-#define BPF_CAST_CALL(x)					\
-		((u64 (*)(u64, u64, u64, u64, u64))(x))
+#define BPF_FUNC_IMM(FUNC)					\
+		((u64)(FUNC) - (u64)__bpf_call_base)
 
 #define BPF_EMIT_CALL(FUNC)					\
 	((struct bpf_insn) {					\
@@ -349,7 +349,7 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
 		.dst_reg = 0,					\
 		.src_reg = 0,					\
 		.off   = 0,					\
-		.imm   = ((FUNC) - __bpf_call_base) })
+		.imm   = BPF_FUNC_IMM(FUNC) })
 
 /* Raw code statement block */
 
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 2d182c4ee9d9..325656a61708 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -517,7 +517,7 @@ static u32 htab_map_gen_lookup(struct bpf_map *map, struct bpf_insn *insn_buf)
 
 	BUILD_BUG_ON(!__same_type(&__htab_map_lookup_elem,
 		     (void *(*)(struct bpf_map *map, void *key))NULL));
-	*insn++ = BPF_EMIT_CALL(BPF_CAST_CALL(__htab_map_lookup_elem));
+	*insn++ = BPF_EMIT_CALL(__htab_map_lookup_elem);
 	*insn++ = BPF_JMP_IMM(BPF_JEQ, ret, 0, 1);
 	*insn++ = BPF_ALU64_IMM(BPF_ADD, ret,
 				offsetof(struct htab_elem, key) +
@@ -558,7 +558,7 @@ static u32 htab_lru_map_gen_lookup(struct bpf_map *map,
 
 	BUILD_BUG_ON(!__same_type(&__htab_map_lookup_elem,
 		     (void *(*)(struct bpf_map *map, void *key))NULL));
-	*insn++ = BPF_EMIT_CALL(BPF_CAST_CALL(__htab_map_lookup_elem));
+	*insn++ = BPF_EMIT_CALL(__htab_map_lookup_elem);
 	*insn++ = BPF_JMP_IMM(BPF_JEQ, ret, 0, 4);
 	*insn++ = BPF_LDX_MEM(BPF_B, ref_reg, ret,
 			      offsetof(struct htab_elem, lru_node) +
@@ -1749,7 +1749,7 @@ static u32 htab_of_map_gen_lookup(struct bpf_map *map,
 
 	BUILD_BUG_ON(!__same_type(&__htab_map_lookup_elem,
 		     (void *(*)(struct bpf_map *map, void *key))NULL));
-	*insn++ = BPF_EMIT_CALL(BPF_CAST_CALL(__htab_map_lookup_elem));
+	*insn++ = BPF_EMIT_CALL(__htab_map_lookup_elem);
 	*insn++ = BPF_JMP_IMM(BPF_JEQ, ret, 0, 2);
 	*insn++ = BPF_ALU64_IMM(BPF_ADD, ret,
 				offsetof(struct htab_elem, key) +
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 1cc945daa9c8..70b4e47c2214 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9054,8 +9054,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
 			    insn->src_reg != BPF_PSEUDO_CALL)
 				continue;
 			subprog = insn->off;
-			insn->imm = BPF_CAST_CALL(func[subprog]->bpf_func) -
-				    __bpf_call_base;
+			insn->imm = BPF_FUNC_IMM(func[subprog]->bpf_func);
 		}
 
 		/* we use the aux data to keep a list of the start addresses
@@ -9429,28 +9428,22 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
 
 			switch (insn->imm) {
 			case BPF_FUNC_map_lookup_elem:
-				insn->imm = BPF_CAST_CALL(ops->map_lookup_elem) -
-					    __bpf_call_base;
+				insn->imm = BPF_FUNC_IMM(ops->map_lookup_elem);
 				continue;
 			case BPF_FUNC_map_update_elem:
-				insn->imm = BPF_CAST_CALL(ops->map_update_elem) -
-					    __bpf_call_base;
+				insn->imm = BPF_FUNC_IMM(ops->map_update_elem);
 				continue;
 			case BPF_FUNC_map_delete_elem:
-				insn->imm = BPF_CAST_CALL(ops->map_delete_elem) -
-					    __bpf_call_base;
+				insn->imm = BPF_FUNC_IMM(ops->map_delete_elem);
 				continue;
 			case BPF_FUNC_map_push_elem:
-				insn->imm = BPF_CAST_CALL(ops->map_push_elem) -
-					    __bpf_call_base;
+				insn->imm = BPF_FUNC_IMM(ops->map_push_elem);
 				continue;
 			case BPF_FUNC_map_pop_elem:
-				insn->imm = BPF_CAST_CALL(ops->map_pop_elem) -
-					    __bpf_call_base;
+				insn->imm = BPF_FUNC_IMM(ops->map_pop_elem);
 				continue;
 			case BPF_FUNC_map_peek_elem:
-				insn->imm = BPF_CAST_CALL(ops->map_peek_elem) -
-					    __bpf_call_base;
+				insn->imm = BPF_FUNC_IMM(ops->map_peek_elem);
 				continue;
 			}
 
-- 
2.20.1


-- 
Kees Cook

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] bpf: Avoid function casting when calculating immediate
  2020-01-29 21:36 [PATCH] bpf: Avoid function casting when calculating immediate Kees Cook
@ 2020-02-17 15:51 ` Daniel Borkmann
  2020-02-17 18:25   ` Kees Cook
  0 siblings, 1 reply; 3+ messages in thread
From: Daniel Borkmann @ 2020-02-17 15:51 UTC (permalink / raw)
  To: Kees Cook, Alexei Starovoitov
  Cc: linux-kernel, Martin KaFai Lau, Song Liu, Yonghong Song,
	Andrii Nakryiko, Sami Tolvanen, bpf

On 1/29/20 10:36 PM, Kees Cook wrote:
> In an effort to enable -Wcast-function-type in the top-level Makefile
> to support Control Flow Integrity builds, rework the BPF instruction
> immediate calculation macros to avoid mismatched function pointers. Since
> these calculations are only ever between function address (these are
> not function calls, just address calculations), they can be cast to u64
> instead, where the result will be assigned to the s32 insn->imm.
> 
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>   include/linux/filter.h |  6 +++---
>   kernel/bpf/hashtab.c   |  6 +++---
>   kernel/bpf/verifier.c  | 21 +++++++--------------
>   3 files changed, 13 insertions(+), 20 deletions(-)
> 
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index f349e2c0884c..b5beee7bf2ea 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -340,8 +340,8 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
>   
>   /* Function call */
>   
> -#define BPF_CAST_CALL(x)					\
> -		((u64 (*)(u64, u64, u64, u64, u64))(x))
> +#define BPF_FUNC_IMM(FUNC)					\
> +		((u64)(FUNC) - (u64)__bpf_call_base)

Looks good to me in general. My only concern is compilation on 32bit archs: I think
the cast needs to be of '(u64)(unsigned long)' to avoid introducing new warnings a la
'cast from pointer to integer of different size'.

Thanks,
Daniel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] bpf: Avoid function casting when calculating immediate
  2020-02-17 15:51 ` Daniel Borkmann
@ 2020-02-17 18:25   ` Kees Cook
  0 siblings, 0 replies; 3+ messages in thread
From: Kees Cook @ 2020-02-17 18:25 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: Alexei Starovoitov, linux-kernel, Martin KaFai Lau, Song Liu,
	Yonghong Song, Andrii Nakryiko, Sami Tolvanen, bpf

On Mon, Feb 17, 2020 at 04:51:46PM +0100, Daniel Borkmann wrote:
> On 1/29/20 10:36 PM, Kees Cook wrote:
> > In an effort to enable -Wcast-function-type in the top-level Makefile
> > to support Control Flow Integrity builds, rework the BPF instruction
> > immediate calculation macros to avoid mismatched function pointers. Since
> > these calculations are only ever between function address (these are
> > not function calls, just address calculations), they can be cast to u64
> > instead, where the result will be assigned to the s32 insn->imm.
> > 
> > Signed-off-by: Kees Cook <keescook@chromium.org>
> > ---
> >   include/linux/filter.h |  6 +++---
> >   kernel/bpf/hashtab.c   |  6 +++---
> >   kernel/bpf/verifier.c  | 21 +++++++--------------
> >   3 files changed, 13 insertions(+), 20 deletions(-)
> > 
> > diff --git a/include/linux/filter.h b/include/linux/filter.h
> > index f349e2c0884c..b5beee7bf2ea 100644
> > --- a/include/linux/filter.h
> > +++ b/include/linux/filter.h
> > @@ -340,8 +340,8 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
> >   /* Function call */
> > -#define BPF_CAST_CALL(x)					\
> > -		((u64 (*)(u64, u64, u64, u64, u64))(x))
> > +#define BPF_FUNC_IMM(FUNC)					\
> > +		((u64)(FUNC) - (u64)__bpf_call_base)
> 
> Looks good to me in general. My only concern is compilation on 32bit archs: I think
> the cast needs to be of '(u64)(unsigned long)' to avoid introducing new warnings a la
> 'cast from pointer to integer of different size'.

Oh, good point. I'll double-check the 32-bit builds. (I also have
another related change that I found several days later.) I'll get this
adjusted/tested and resend the patch.

Thanks!

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-02-17 18:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-29 21:36 [PATCH] bpf: Avoid function casting when calculating immediate Kees Cook
2020-02-17 15:51 ` Daniel Borkmann
2020-02-17 18:25   ` Kees Cook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).