aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/verifier.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@fb.com>2016-08-11 21:17:16 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-13 00:56:18 -0400
commit6841de8b0d03cc9a4e0e928453623c13ee754f77 (patch)
tree2a35b03ce74494ad8772ed66f4e32a1e3a25a383 /kernel/bpf/verifier.c
parent03ff4979345110d30ecdeab2ae9cb2f451f158bf (diff)
bpf: allow helpers access the packet directly
The helper functions like bpf_map_lookup_elem(map, key) were only allowing 'key' to point to the initialized stack area. That is causing performance degradation when programs need to process millions of packets per second and need to copy contents of the packet into the stack just to pass the stack pointer into the lookup() function. Allow such helpers read from the packet directly. All helpers that expect ARG_PTR_TO_MAP_KEY, ARG_PTR_TO_MAP_VALUE, ARG_PTR_TO_STACK assume byte aligned pointer, so no alignment concerns, only need to check that helper will not be accessing beyond the packet range verified by the prior 'if (ptr < data_end)' condition. For now allow this feature for XDP programs only. Later it can be relaxed for the clsact programs as well. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf/verifier.c')
-rw-r--r--kernel/bpf/verifier.c61
1 files changed, 43 insertions, 18 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index d504722ebfa4..0cc46f1df358 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -930,14 +930,14 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
930 enum bpf_arg_type arg_type, 930 enum bpf_arg_type arg_type,
931 struct bpf_call_arg_meta *meta) 931 struct bpf_call_arg_meta *meta)
932{ 932{
933 struct reg_state *reg = env->cur_state.regs + regno; 933 struct reg_state *regs = env->cur_state.regs, *reg = &regs[regno];
934 enum bpf_reg_type expected_type; 934 enum bpf_reg_type expected_type, type = reg->type;
935 int err = 0; 935 int err = 0;
936 936
937 if (arg_type == ARG_DONTCARE) 937 if (arg_type == ARG_DONTCARE)
938 return 0; 938 return 0;
939 939
940 if (reg->type == NOT_INIT) { 940 if (type == NOT_INIT) {
941 verbose("R%d !read_ok\n", regno); 941 verbose("R%d !read_ok\n", regno);
942 return -EACCES; 942 return -EACCES;
943 } 943 }
@@ -950,16 +950,29 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
950 return 0; 950 return 0;
951 } 951 }
952 952
953 if (type == PTR_TO_PACKET && !may_write_pkt_data(env->prog->type)) {
954 verbose("helper access to the packet is not allowed for clsact\n");
955 return -EACCES;
956 }
957
953 if (arg_type == ARG_PTR_TO_MAP_KEY || 958 if (arg_type == ARG_PTR_TO_MAP_KEY ||
954 arg_type == ARG_PTR_TO_MAP_VALUE) { 959 arg_type == ARG_PTR_TO_MAP_VALUE) {
955 expected_type = PTR_TO_STACK; 960 expected_type = PTR_TO_STACK;
961 if (type != PTR_TO_PACKET && type != expected_type)
962 goto err_type;
956 } else if (arg_type == ARG_CONST_STACK_SIZE || 963 } else if (arg_type == ARG_CONST_STACK_SIZE ||
957 arg_type == ARG_CONST_STACK_SIZE_OR_ZERO) { 964 arg_type == ARG_CONST_STACK_SIZE_OR_ZERO) {
958 expected_type = CONST_IMM; 965 expected_type = CONST_IMM;
966 if (type != expected_type)
967 goto err_type;
959 } else if (arg_type == ARG_CONST_MAP_PTR) { 968 } else if (arg_type == ARG_CONST_MAP_PTR) {
960 expected_type = CONST_PTR_TO_MAP; 969 expected_type = CONST_PTR_TO_MAP;
970 if (type != expected_type)
971 goto err_type;
961 } else if (arg_type == ARG_PTR_TO_CTX) { 972 } else if (arg_type == ARG_PTR_TO_CTX) {
962 expected_type = PTR_TO_CTX; 973 expected_type = PTR_TO_CTX;
974 if (type != expected_type)
975 goto err_type;
963 } else if (arg_type == ARG_PTR_TO_STACK || 976 } else if (arg_type == ARG_PTR_TO_STACK ||
964 arg_type == ARG_PTR_TO_RAW_STACK) { 977 arg_type == ARG_PTR_TO_RAW_STACK) {
965 expected_type = PTR_TO_STACK; 978 expected_type = PTR_TO_STACK;
@@ -967,20 +980,16 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
967 * passed in as argument, it's a CONST_IMM type. Final test 980 * passed in as argument, it's a CONST_IMM type. Final test
968 * happens during stack boundary checking. 981 * happens during stack boundary checking.
969 */ 982 */
970 if (reg->type == CONST_IMM && reg->imm == 0) 983 if (type == CONST_IMM && reg->imm == 0)
971 expected_type = CONST_IMM; 984 /* final test in check_stack_boundary() */;
985 else if (type != PTR_TO_PACKET && type != expected_type)
986 goto err_type;
972 meta->raw_mode = arg_type == ARG_PTR_TO_RAW_STACK; 987 meta->raw_mode = arg_type == ARG_PTR_TO_RAW_STACK;
973 } else { 988 } else {
974 verbose("unsupported arg_type %d\n", arg_type); 989 verbose("unsupported arg_type %d\n", arg_type);
975 return -EFAULT; 990 return -EFAULT;
976 } 991 }
977 992
978 if (reg->type != expected_type) {
979 verbose("R%d type=%s expected=%s\n", regno,
980 reg_type_str[reg->type], reg_type_str[expected_type]);
981 return -EACCES;
982 }
983
984 if (arg_type == ARG_CONST_MAP_PTR) { 993 if (arg_type == ARG_CONST_MAP_PTR) {
985 /* bpf_map_xxx(map_ptr) call: remember that map_ptr */ 994 /* bpf_map_xxx(map_ptr) call: remember that map_ptr */
986 meta->map_ptr = reg->map_ptr; 995 meta->map_ptr = reg->map_ptr;
@@ -998,8 +1007,13 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
998 verbose("invalid map_ptr to access map->key\n"); 1007 verbose("invalid map_ptr to access map->key\n");
999 return -EACCES; 1008 return -EACCES;
1000 } 1009 }
1001 err = check_stack_boundary(env, regno, meta->map_ptr->key_size, 1010 if (type == PTR_TO_PACKET)
1002 false, NULL); 1011 err = check_packet_access(env, regno, 0,
1012 meta->map_ptr->key_size);
1013 else
1014 err = check_stack_boundary(env, regno,
1015 meta->map_ptr->key_size,
1016 false, NULL);
1003 } else if (arg_type == ARG_PTR_TO_MAP_VALUE) { 1017 } else if (arg_type == ARG_PTR_TO_MAP_VALUE) {
1004 /* bpf_map_xxx(..., map_ptr, ..., value) call: 1018 /* bpf_map_xxx(..., map_ptr, ..., value) call:
1005 * check [value, value + map->value_size) validity 1019 * check [value, value + map->value_size) validity
@@ -1009,9 +1023,13 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
1009 verbose("invalid map_ptr to access map->value\n"); 1023 verbose("invalid map_ptr to access map->value\n");
1010 return -EACCES; 1024 return -EACCES;
1011 } 1025 }
1012 err = check_stack_boundary(env, regno, 1026 if (type == PTR_TO_PACKET)
1013 meta->map_ptr->value_size, 1027 err = check_packet_access(env, regno, 0,
1014 false, NULL); 1028 meta->map_ptr->value_size);
1029 else
1030 err = check_stack_boundary(env, regno,
1031 meta->map_ptr->value_size,
1032 false, NULL);
1015 } else if (arg_type == ARG_CONST_STACK_SIZE || 1033 } else if (arg_type == ARG_CONST_STACK_SIZE ||
1016 arg_type == ARG_CONST_STACK_SIZE_OR_ZERO) { 1034 arg_type == ARG_CONST_STACK_SIZE_OR_ZERO) {
1017 bool zero_size_allowed = (arg_type == ARG_CONST_STACK_SIZE_OR_ZERO); 1035 bool zero_size_allowed = (arg_type == ARG_CONST_STACK_SIZE_OR_ZERO);
@@ -1025,11 +1043,18 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
1025 verbose("ARG_CONST_STACK_SIZE cannot be first argument\n"); 1043 verbose("ARG_CONST_STACK_SIZE cannot be first argument\n");
1026 return -EACCES; 1044 return -EACCES;
1027 } 1045 }
1028 err = check_stack_boundary(env, regno - 1, reg->imm, 1046 if (regs[regno - 1].type == PTR_TO_PACKET)
1029 zero_size_allowed, meta); 1047 err = check_packet_access(env, regno - 1, 0, reg->imm);
1048 else
1049 err = check_stack_boundary(env, regno - 1, reg->imm,
1050 zero_size_allowed, meta);
1030 } 1051 }
1031 1052
1032 return err; 1053 return err;
1054err_type:
1055 verbose("R%d type=%s expected=%s\n", regno,
1056 reg_type_str[type], reg_type_str[expected_type]);
1057 return -EACCES;
1033} 1058}
1034 1059
1035static int check_map_func_compatibility(struct bpf_map *map, int func_id) 1060static int check_map_func_compatibility(struct bpf_map *map, int func_id)