Move the check for PTR_TO_MAP_VALUE to check_func_arg, where all other checking is done as well. Move the invocation of process_spin_lock away from the register type checking, to allow a future refactoring.
Unified · Split
| @@ -3828,10 +3828,6 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno, · 3827 unmodified lines | |||
| 3828 | struct bpf_map *map = reg->map_ptr; | 3828 | struct bpf_map *map = reg->map_ptr; |
| 3829 | u64 val = reg->var_off.value; | 3829 | u64 val = reg->var_off.value; |
| 3830 | 3830 | ||
| 3831 | if (reg->type != PTR_TO_MAP_VALUE) { | ||
| 3832 | verbose(env, "R%d is not a pointer to map_value\n", regno); | ||
| 3833 | return -EINVAL; | ||
| 3834 | } | ||
| 3835 | if (!is_const) { | 3831 | if (!is_const) { |
| 3836 | verbose(env, | 3832 | verbose(env, |
| 3837 | "R%d doesn't have constant offset. bpf_spin_lock has to be at the constant offset\n", | 3833 | "R%d doesn't have constant offset. bpf_spin_lock has to be at the constant offset\n", |
| @@ -4040,16 +4036,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, · 202 unmodified lines | |||
| 4040 | if (type != expected_type) | 4036 | if (type != expected_type) |
| 4041 | goto err_type; | 4037 | goto err_type; |
| 4042 | } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) { | 4038 | } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) { |
| 4043 | if (meta->func_id == BPF_FUNC_spin_lock) { | 4039 | expected_type = PTR_TO_MAP_VALUE; |
| 4044 | if (process_spin_lock(env, regno, true)) | 4040 | if (type != expected_type) |
| 4045 | return -EACCES; | 4041 | goto err_type; |
| 4046 | } else if (meta->func_id == BPF_FUNC_spin_unlock) { | ||
| 4047 | if (process_spin_lock(env, regno, false)) | ||
| 4048 | return -EACCES; | ||
| 4049 | } else { | ||
| 4050 | verbose(env, "verifier internal error\n"); | ||
| 4051 | return -EFAULT; | ||
| 4052 | } | ||
| 4053 | } else if (arg_type_is_mem_ptr(arg_type)) { | 4042 | } else if (arg_type_is_mem_ptr(arg_type)) { |
| 4054 | expected_type = PTR_TO_STACK; | 4043 | expected_type = PTR_TO_STACK; |
| 4055 | /* One exception here. In case function allows for NULL to be | 4044 | /* One exception here. In case function allows for NULL to be |
| @@ -4155,6 +4144,17 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, · 99 unmodified lines | |||
| 4155 | err = check_helper_mem_access(env, regno, | 4144 | err = check_helper_mem_access(env, regno, |
| 4156 | meta->map_ptr->value_size, false, | 4145 | meta->map_ptr->value_size, false, |
| 4157 | meta); | 4146 | meta); |
| 4147 | } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) { | ||
| 4148 | if (meta->func_id == BPF_FUNC_spin_lock) { | ||
| 4149 | if (process_spin_lock(env, regno, true)) | ||
| 4150 | return -EACCES; | ||
| 4151 | } else if (meta->func_id == BPF_FUNC_spin_unlock) { | ||
| 4152 | if (process_spin_lock(env, regno, false)) | ||
| 4153 | return -EACCES; | ||
| 4154 | } else { | ||
| 4155 | verbose(env, "verifier internal error\n"); | ||
| 4156 | return -EFAULT; | ||
| 4157 | } | ||
| 4158 | } else if (arg_type_is_mem_ptr(arg_type)) { | 4158 | } else if (arg_type_is_mem_ptr(arg_type)) { |
| 4159 | /* The access to this pointer is only checked when we hit the | 4159 | /* The access to this pointer is only checked when we hit the |
| 4160 | * next is_mem_size argument below. | 4160 | * next is_mem_size argument below. |