Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2018-01-13 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Follow-up fix to the recent BPF out-of-bounds speculation fix that prevents max_entries overflows and an undefined behavior on 32 bit archs on index_mask calculation, from Daniel. 2) Reject unsupported BPF_ARSH opcode in 32 bit ALU mode that was otherwise throwing an unknown opcode warning in the interpreter, from Daniel. 3) Typo fix in one of the user facing verbose() messages that was added during the BPF out-of-bounds speculation fix, from Colin. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8155aedf51
|
@ -56,7 +56,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
||||||
u32 elem_size, index_mask, max_entries;
|
u32 elem_size, index_mask, max_entries;
|
||||||
bool unpriv = !capable(CAP_SYS_ADMIN);
|
bool unpriv = !capable(CAP_SYS_ADMIN);
|
||||||
struct bpf_array *array;
|
struct bpf_array *array;
|
||||||
u64 array_size;
|
u64 array_size, mask64;
|
||||||
|
|
||||||
/* check sanity of attributes */
|
/* check sanity of attributes */
|
||||||
if (attr->max_entries == 0 || attr->key_size != 4 ||
|
if (attr->max_entries == 0 || attr->key_size != 4 ||
|
||||||
|
@ -74,13 +74,25 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
||||||
elem_size = round_up(attr->value_size, 8);
|
elem_size = round_up(attr->value_size, 8);
|
||||||
|
|
||||||
max_entries = attr->max_entries;
|
max_entries = attr->max_entries;
|
||||||
index_mask = roundup_pow_of_two(max_entries) - 1;
|
|
||||||
|
|
||||||
if (unpriv)
|
/* On 32 bit archs roundup_pow_of_two() with max_entries that has
|
||||||
|
* upper most bit set in u32 space is undefined behavior due to
|
||||||
|
* resulting 1U << 32, so do it manually here in u64 space.
|
||||||
|
*/
|
||||||
|
mask64 = fls_long(max_entries - 1);
|
||||||
|
mask64 = 1ULL << mask64;
|
||||||
|
mask64 -= 1;
|
||||||
|
|
||||||
|
index_mask = mask64;
|
||||||
|
if (unpriv) {
|
||||||
/* round up array size to nearest power of 2,
|
/* round up array size to nearest power of 2,
|
||||||
* since cpu will speculate within index_mask limits
|
* since cpu will speculate within index_mask limits
|
||||||
*/
|
*/
|
||||||
max_entries = index_mask + 1;
|
max_entries = index_mask + 1;
|
||||||
|
/* Check for overflows. */
|
||||||
|
if (max_entries < attr->max_entries)
|
||||||
|
return ERR_PTR(-E2BIG);
|
||||||
|
}
|
||||||
|
|
||||||
array_size = sizeof(*array);
|
array_size = sizeof(*array);
|
||||||
if (percpu)
|
if (percpu)
|
||||||
|
|
|
@ -2493,6 +2493,11 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opcode == BPF_ARSH && BPF_CLASS(insn->code) != BPF_ALU64) {
|
||||||
|
verbose(env, "BPF_ARSH not supported for 32 bit ALU\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if ((opcode == BPF_LSH || opcode == BPF_RSH ||
|
if ((opcode == BPF_LSH || opcode == BPF_RSH ||
|
||||||
opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) {
|
opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) {
|
||||||
int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32;
|
int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32;
|
||||||
|
@ -4472,7 +4477,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
|
||||||
*/
|
*/
|
||||||
map_ptr = env->insn_aux_data[i + delta].map_ptr;
|
map_ptr = env->insn_aux_data[i + delta].map_ptr;
|
||||||
if (map_ptr == BPF_MAP_PTR_POISON) {
|
if (map_ptr == BPF_MAP_PTR_POISON) {
|
||||||
verbose(env, "tail_call obusing map_ptr\n");
|
verbose(env, "tail_call abusing map_ptr\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!map_ptr->unpriv_array)
|
if (!map_ptr->unpriv_array)
|
||||||
|
|
|
@ -272,6 +272,46 @@ static struct bpf_test tests[] = {
|
||||||
.errstr = "invalid bpf_ld_imm64 insn",
|
.errstr = "invalid bpf_ld_imm64 insn",
|
||||||
.result = REJECT,
|
.result = REJECT,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"arsh32 on imm",
|
||||||
|
.insns = {
|
||||||
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||||
|
BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 5),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "BPF_ARSH not supported for 32 bit ALU",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arsh32 on reg",
|
||||||
|
.insns = {
|
||||||
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||||
|
BPF_MOV64_IMM(BPF_REG_1, 5),
|
||||||
|
BPF_ALU32_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "BPF_ARSH not supported for 32 bit ALU",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arsh64 on imm",
|
||||||
|
.insns = {
|
||||||
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||||
|
BPF_ALU64_IMM(BPF_ARSH, BPF_REG_0, 5),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.result = ACCEPT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arsh64 on reg",
|
||||||
|
.insns = {
|
||||||
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||||
|
BPF_MOV64_IMM(BPF_REG_1, 5),
|
||||||
|
BPF_ALU64_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.result = ACCEPT,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"no bpf_exit",
|
"no bpf_exit",
|
||||||
.insns = {
|
.insns = {
|
||||||
|
|
Loading…
Reference in New Issue