Re: [PATCH v14 net-next 10/11] bpf: verifier (add verifier core)

2014-09-25 Thread Alexei Starovoitov
On Thu, Sep 25, 2014 at 9:40 PM, David Miller  wrote:
> From: Alexei Starovoitov 
> Date: Sun, 21 Sep 2014 17:06:50 -0700
>
>> +#define _(OP) ({ int ret = (OP); if (ret < 0) return ret; })
>
> Please do not hide program control flow inside of a macro.

ok.
I'm pretty sure it will be less readable, but I'll get rid off it.
I'm assuming you considered my arguments about it here:
https://lkml.org/lkml/2014/7/2/656
No problem. It's a minor thing.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v14 net-next 10/11] bpf: verifier (add verifier core)

2014-09-25 Thread David Miller
From: Alexei Starovoitov 
Date: Sun, 21 Sep 2014 17:06:50 -0700

> +#define _(OP) ({ int ret = (OP); if (ret < 0) return ret; })

Please do not hide program control flow inside of a macro.

Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v14 net-next 10/11] bpf: verifier (add verifier core)

2014-09-25 Thread David Miller
From: Alexei Starovoitov a...@plumgrid.com
Date: Sun, 21 Sep 2014 17:06:50 -0700

 +#define _(OP) ({ int ret = (OP); if (ret  0) return ret; })

Please do not hide program control flow inside of a macro.

Thank you.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v14 net-next 10/11] bpf: verifier (add verifier core)

2014-09-25 Thread Alexei Starovoitov
On Thu, Sep 25, 2014 at 9:40 PM, David Miller da...@davemloft.net wrote:
 From: Alexei Starovoitov a...@plumgrid.com
 Date: Sun, 21 Sep 2014 17:06:50 -0700

 +#define _(OP) ({ int ret = (OP); if (ret  0) return ret; })

 Please do not hide program control flow inside of a macro.

ok.
I'm pretty sure it will be less readable, but I'll get rid off it.
I'm assuming you considered my arguments about it here:
https://lkml.org/lkml/2014/7/2/656
No problem. It's a minor thing.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v14 net-next 10/11] bpf: verifier (add verifier core)

2014-09-21 Thread Alexei Starovoitov
This patch adds verifier core which simulates execution of every insn and
records the state of registers and program stack. Every branch instruction seen
during simulation is pushed into state stack. When verifier reaches BPF_EXIT,
it pops the state from the stack and continues until it reaches BPF_EXIT again.
For program:
1: bpf_mov r1, xxx
2: if (r1 == 0) goto 5
3: bpf_mov r0, 1
4: goto 6
5: bpf_mov r0, 2
6: bpf_exit
The verifier will walk insns: 1, 2, 3, 4, 6
then it will pop the state recorded at insn#2 and will continue: 5, 6

This way it walks all possible paths through the program and checks all
possible values of registers. While doing so, it checks for:
- invalid instructions
- uninitialized register access
- uninitialized stack access
- misaligned stack access
- out of range stack access
- invalid calling convention
- instruction encoding is not using reserved fields

Kernel subsystem configures the verifier with two callbacks:

- bool (*is_valid_access)(int off, int size, enum bpf_access_type type);
  that provides information to the verifer which fields of 'ctx'
  are accessible (remember 'ctx' is the first argument to eBPF program)

- const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id func_id);
  returns argument constraints of kernel helper functions that eBPF program
  may call, so that verifier can checks that R1-R5 types match the prototype

More details in Documentation/networking/filter.txt and in kernel/bpf/verifier.c

Signed-off-by: Alexei Starovoitov 
---
 include/linux/bpf.h   |   47 +++
 kernel/bpf/verifier.c | 1003 -
 2 files changed, 1049 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 9dfeb36f8971..3cf91754a957 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -46,6 +46,31 @@ void bpf_register_map_type(struct bpf_map_type_list *tl);
 void bpf_map_put(struct bpf_map *map);
 struct bpf_map *bpf_map_get(struct fd f);
 
+/* function argument constraints */
+enum bpf_arg_type {
+   ARG_ANYTHING = 0,   /* any argument is ok */
+
+   /* the following constraints used to prototype
+* bpf_map_lookup/update/delete_elem() functions
+*/
+   ARG_CONST_MAP_PTR,  /* const argument used as pointer to bpf_map */
+   ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */
+   ARG_PTR_TO_MAP_VALUE,   /* pointer to stack used as map value */
+
+   /* the following constraints used to prototype bpf_memcmp() and other
+* functions that access data on eBPF program stack
+*/
+   ARG_PTR_TO_STACK,   /* any pointer to eBPF program stack */
+   ARG_CONST_STACK_SIZE,   /* number of bytes accessed from stack */
+};
+
+/* type of values returned from helper functions */
+enum bpf_return_type {
+   RET_INTEGER,/* function returns integer */
+   RET_VOID,   /* function doesn't return anything */
+   RET_PTR_TO_MAP_VALUE_OR_NULL,   /* returns a pointer to map elem value 
or NULL */
+};
+
 /* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF 
programs
  * to in-kernel helper functions and for adjusting imm32 field in BPF_CALL
  * instructions after verifying
@@ -53,11 +78,33 @@ struct bpf_map *bpf_map_get(struct fd f);
 struct bpf_func_proto {
u64 (*func)(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
bool gpl_only;
+   enum bpf_return_type ret_type;
+   enum bpf_arg_type arg1_type;
+   enum bpf_arg_type arg2_type;
+   enum bpf_arg_type arg3_type;
+   enum bpf_arg_type arg4_type;
+   enum bpf_arg_type arg5_type;
+};
+
+/* bpf_context is intentionally undefined structure. Pointer to bpf_context is
+ * the first argument to eBPF programs.
+ * For socket filters: 'struct bpf_context *' == 'struct sk_buff *'
+ */
+struct bpf_context;
+
+enum bpf_access_type {
+   BPF_READ = 1,
+   BPF_WRITE = 2
 };
 
 struct bpf_verifier_ops {
/* return eBPF function prototype for verification */
const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id 
func_id);
+
+   /* return true if 'size' wide access at offset 'off' within bpf_context
+* with 'type' (read or write) is allowed
+*/
+   bool (*is_valid_access)(int off, int size, enum bpf_access_type type);
 };
 
 struct bpf_prog_type_list {
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index effab7d1c7e8..663d02c6e23c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -125,6 +125,72 @@
  * are set to NOT_INIT to indicate that they are no longer readable.
  */
 
+#define _(OP) ({ int ret = (OP); if (ret < 0) return ret; })
+
+/* types of values stored in eBPF registers */
+enum bpf_reg_type {
+   NOT_INIT = 0,/* nothing was written into register */
+   UNKNOWN_VALUE,   /* reg doesn't contain a valid pointer */
+   PTR_TO_CTX,  /* reg points to bpf_context */

[PATCH v14 net-next 10/11] bpf: verifier (add verifier core)

2014-09-21 Thread Alexei Starovoitov
This patch adds verifier core which simulates execution of every insn and
records the state of registers and program stack. Every branch instruction seen
during simulation is pushed into state stack. When verifier reaches BPF_EXIT,
it pops the state from the stack and continues until it reaches BPF_EXIT again.
For program:
1: bpf_mov r1, xxx
2: if (r1 == 0) goto 5
3: bpf_mov r0, 1
4: goto 6
5: bpf_mov r0, 2
6: bpf_exit
The verifier will walk insns: 1, 2, 3, 4, 6
then it will pop the state recorded at insn#2 and will continue: 5, 6

This way it walks all possible paths through the program and checks all
possible values of registers. While doing so, it checks for:
- invalid instructions
- uninitialized register access
- uninitialized stack access
- misaligned stack access
- out of range stack access
- invalid calling convention
- instruction encoding is not using reserved fields

Kernel subsystem configures the verifier with two callbacks:

- bool (*is_valid_access)(int off, int size, enum bpf_access_type type);
  that provides information to the verifer which fields of 'ctx'
  are accessible (remember 'ctx' is the first argument to eBPF program)

- const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id func_id);
  returns argument constraints of kernel helper functions that eBPF program
  may call, so that verifier can checks that R1-R5 types match the prototype

More details in Documentation/networking/filter.txt and in kernel/bpf/verifier.c

Signed-off-by: Alexei Starovoitov a...@plumgrid.com
---
 include/linux/bpf.h   |   47 +++
 kernel/bpf/verifier.c | 1003 -
 2 files changed, 1049 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 9dfeb36f8971..3cf91754a957 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -46,6 +46,31 @@ void bpf_register_map_type(struct bpf_map_type_list *tl);
 void bpf_map_put(struct bpf_map *map);
 struct bpf_map *bpf_map_get(struct fd f);
 
+/* function argument constraints */
+enum bpf_arg_type {
+   ARG_ANYTHING = 0,   /* any argument is ok */
+
+   /* the following constraints used to prototype
+* bpf_map_lookup/update/delete_elem() functions
+*/
+   ARG_CONST_MAP_PTR,  /* const argument used as pointer to bpf_map */
+   ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */
+   ARG_PTR_TO_MAP_VALUE,   /* pointer to stack used as map value */
+
+   /* the following constraints used to prototype bpf_memcmp() and other
+* functions that access data on eBPF program stack
+*/
+   ARG_PTR_TO_STACK,   /* any pointer to eBPF program stack */
+   ARG_CONST_STACK_SIZE,   /* number of bytes accessed from stack */
+};
+
+/* type of values returned from helper functions */
+enum bpf_return_type {
+   RET_INTEGER,/* function returns integer */
+   RET_VOID,   /* function doesn't return anything */
+   RET_PTR_TO_MAP_VALUE_OR_NULL,   /* returns a pointer to map elem value 
or NULL */
+};
+
 /* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF 
programs
  * to in-kernel helper functions and for adjusting imm32 field in BPF_CALL
  * instructions after verifying
@@ -53,11 +78,33 @@ struct bpf_map *bpf_map_get(struct fd f);
 struct bpf_func_proto {
u64 (*func)(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
bool gpl_only;
+   enum bpf_return_type ret_type;
+   enum bpf_arg_type arg1_type;
+   enum bpf_arg_type arg2_type;
+   enum bpf_arg_type arg3_type;
+   enum bpf_arg_type arg4_type;
+   enum bpf_arg_type arg5_type;
+};
+
+/* bpf_context is intentionally undefined structure. Pointer to bpf_context is
+ * the first argument to eBPF programs.
+ * For socket filters: 'struct bpf_context *' == 'struct sk_buff *'
+ */
+struct bpf_context;
+
+enum bpf_access_type {
+   BPF_READ = 1,
+   BPF_WRITE = 2
 };
 
 struct bpf_verifier_ops {
/* return eBPF function prototype for verification */
const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id 
func_id);
+
+   /* return true if 'size' wide access at offset 'off' within bpf_context
+* with 'type' (read or write) is allowed
+*/
+   bool (*is_valid_access)(int off, int size, enum bpf_access_type type);
 };
 
 struct bpf_prog_type_list {
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index effab7d1c7e8..663d02c6e23c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -125,6 +125,72 @@
  * are set to NOT_INIT to indicate that they are no longer readable.
  */
 
+#define _(OP) ({ int ret = (OP); if (ret  0) return ret; })
+
+/* types of values stored in eBPF registers */
+enum bpf_reg_type {
+   NOT_INIT = 0,/* nothing was written into register */
+   UNKNOWN_VALUE,   /* reg doesn't contain a valid pointer */
+   PTR_TO_CTX,  /* reg points