diff options
-rw-r--r-- | drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 7 | ||||
-rw-r--r-- | drivers/net/tun.c | 10 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 21 | ||||
-rw-r--r-- | lib/test_rhashtable.c | 53 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 28 |
6 files changed, 96 insertions, 28 deletions
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index b3d0c2e6347a..e588a0cdb074 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -22,6 +22,7 @@ #include <linux/if_vlan.h> #include <linux/reset.h> #include <linux/tcp.h> +#include <linux/interrupt.h> #include "mtk_eth_soc.h" @@ -947,6 +948,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, RX_DMA_FPORT_MASK; mac--; + if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || + !eth->netdev[mac])) + goto release_desc; + netdev = eth->netdev[mac]; if (unlikely(test_bit(MTK_RESETTING, ð->state))) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 383fef5a8e24..4b2e0fd7d51e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -1512,6 +1512,10 @@ mlxsw_sp_nexthop_group_mac_update(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib_entry *fib_entry); +static bool +mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node, + const struct mlxsw_sp_fib_entry *fib_entry); + static int mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop_group *nh_grp) @@ -1520,6 +1524,9 @@ mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp, int err; list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) { + if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node, + fib_entry)) + continue; err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry); if (err) return err; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3d4c24572ecd..32ad87345f57 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2598,8 +2598,16 @@ static int __init tun_init(void) goto err_misc; } - register_netdevice_notifier(&tun_notifier_block); + ret = register_netdevice_notifier(&tun_notifier_block); + if (ret) { + pr_err("Can't register netdevice notifier\n"); + goto err_notifier; + } + return 0; + +err_notifier: + misc_deregister(&tun_miscdev); err_misc: rtnl_link_unregister(&tun_link_ops); err_linkops: diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index af9e84a4944e..664d93972373 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -1865,10 +1865,12 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env, * do our normal operations to the register, we need to set the values * to the min/max since they are undefined. */ - if (min_val == BPF_REGISTER_MIN_RANGE) - dst_reg->min_value = BPF_REGISTER_MIN_RANGE; - if (max_val == BPF_REGISTER_MAX_RANGE) - dst_reg->max_value = BPF_REGISTER_MAX_RANGE; + if (opcode != BPF_SUB) { + if (min_val == BPF_REGISTER_MIN_RANGE) + dst_reg->min_value = BPF_REGISTER_MIN_RANGE; + if (max_val == BPF_REGISTER_MAX_RANGE) + dst_reg->max_value = BPF_REGISTER_MAX_RANGE; + } switch (opcode) { case BPF_ADD: @@ -1879,10 +1881,17 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env, dst_reg->min_align = min(src_align, dst_align); break; case BPF_SUB: + /* If one of our values was at the end of our ranges, then the + * _opposite_ value in the dst_reg goes to the end of our range. + */ + if (min_val == BPF_REGISTER_MIN_RANGE) + dst_reg->max_value = BPF_REGISTER_MAX_RANGE; + if (max_val == BPF_REGISTER_MAX_RANGE) + dst_reg->min_value = BPF_REGISTER_MIN_RANGE; if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE) - dst_reg->min_value -= min_val; + dst_reg->min_value -= max_val; if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE) - dst_reg->max_value -= max_val; + dst_reg->max_value -= min_val; dst_reg->min_align = min(src_align, dst_align); break; case BPF_MUL: diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index 64e899b63337..16949d219291 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c @@ -56,8 +56,13 @@ static bool enomem_retry = false; module_param(enomem_retry, bool, 0); MODULE_PARM_DESC(enomem_retry, "Retry insert even if -ENOMEM was returned (default: off)"); +struct test_obj_val { + int id; + int tid; +}; + struct test_obj { - int value; + struct test_obj_val value; struct rhash_head node; }; @@ -72,7 +77,7 @@ static struct test_obj array[MAX_ENTRIES]; static struct rhashtable_params test_rht_params = { .head_offset = offsetof(struct test_obj, node), .key_offset = offsetof(struct test_obj, value), - .key_len = sizeof(int), + .key_len = sizeof(struct test_obj_val), .hashfn = jhash, .nulls_base = (3U << RHT_BASE_SHIFT), }; @@ -109,24 +114,26 @@ static int __init test_rht_lookup(struct rhashtable *ht) for (i = 0; i < entries * 2; i++) { struct test_obj *obj; bool expected = !(i % 2); - u32 key = i; + struct test_obj_val key = { + .id = i, + }; - if (array[i / 2].value == TEST_INSERT_FAIL) + if (array[i / 2].value.id == TEST_INSERT_FAIL) expected = false; obj = rhashtable_lookup_fast(ht, &key, test_rht_params); if (expected && !obj) { - pr_warn("Test failed: Could not find key %u\n", key); + pr_warn("Test failed: Could not find key %u\n", key.id); return -ENOENT; } else if (!expected && obj) { pr_warn("Test failed: Unexpected entry found for key %u\n", - key); + key.id); return -EEXIST; } else if (expected && obj) { - if (obj->value != i) { + if (obj->value.id != i) { pr_warn("Test failed: Lookup value mismatch %u!=%u\n", - obj->value, i); + obj->value.id, i); return -EINVAL; } } @@ -195,7 +202,7 @@ static s64 __init test_rhashtable(struct rhashtable *ht) for (i = 0; i < entries; i++) { struct test_obj *obj = &array[i]; - obj->value = i * 2; + obj->value.id = i * 2; err = insert_retry(ht, &obj->node, test_rht_params); if (err > 0) insert_retries += err; @@ -218,7 +225,7 @@ static s64 __init test_rhashtable(struct rhashtable *ht) for (i = 0; i < entries; i++) { u32 key = i * 2; - if (array[i].value != TEST_INSERT_FAIL) { + if (array[i].value.id != TEST_INSERT_FAIL) { obj = rhashtable_lookup_fast(ht, &key, test_rht_params); BUG_ON(!obj); @@ -242,18 +249,21 @@ static int thread_lookup_test(struct thread_data *tdata) for (i = 0; i < entries; i++) { struct test_obj *obj; - int key = (tdata->id << 16) | i; + struct test_obj_val key = { + .id = i, + .tid = tdata->id, + }; obj = rhashtable_lookup_fast(&ht, &key, test_rht_params); - if (obj && (tdata->objs[i].value == TEST_INSERT_FAIL)) { - pr_err(" found unexpected object %d\n", key); + if (obj && (tdata->objs[i].value.id == TEST_INSERT_FAIL)) { + pr_err(" found unexpected object %d-%d\n", key.tid, key.id); err++; - } else if (!obj && (tdata->objs[i].value != TEST_INSERT_FAIL)) { - pr_err(" object %d not found!\n", key); + } else if (!obj && (tdata->objs[i].value.id != TEST_INSERT_FAIL)) { + pr_err(" object %d-%d not found!\n", key.tid, key.id); err++; - } else if (obj && (obj->value != key)) { - pr_err(" wrong object returned (got %d, expected %d)\n", - obj->value, key); + } else if (obj && memcmp(&obj->value, &key, sizeof(key))) { + pr_err(" wrong object returned (got %d-%d, expected %d-%d)\n", + obj->value.tid, obj->value.id, key.tid, key.id); err++; } @@ -272,7 +282,8 @@ static int threadfunc(void *data) pr_err(" thread[%d]: down_interruptible failed\n", tdata->id); for (i = 0; i < entries; i++) { - tdata->objs[i].value = (tdata->id << 16) | i; + tdata->objs[i].value.id = i; + tdata->objs[i].value.tid = tdata->id; err = insert_retry(&ht, &tdata->objs[i].node, test_rht_params); if (err > 0) { insert_retries += err; @@ -295,7 +306,7 @@ static int threadfunc(void *data) for (step = 10; step > 0; step--) { for (i = 0; i < entries; i += step) { - if (tdata->objs[i].value == TEST_INSERT_FAIL) + if (tdata->objs[i].value.id == TEST_INSERT_FAIL) continue; err = rhashtable_remove_fast(&ht, &tdata->objs[i].node, test_rht_params); @@ -304,7 +315,7 @@ static int threadfunc(void *data) tdata->id); goto out; } - tdata->objs[i].value = TEST_INSERT_FAIL; + tdata->objs[i].value.id = TEST_INSERT_FAIL; cond_resched(); } diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index af7d173910f4..addea82f76c9 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c @@ -5980,6 +5980,34 @@ static struct bpf_test tests[] = { .result = REJECT, .result_unpriv = REJECT, }, + { + "subtraction bounds (map value)", + .insns = { + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), + BPF_LD_MAP_FD(BPF_REG_1, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, + BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9), + BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0), + BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 7), + BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1), + BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 5), + BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3), + BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 56), + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), + BPF_EXIT_INSN(), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .fixup_map1 = { 3 }, + .errstr_unpriv = "R0 pointer arithmetic prohibited", + .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", + .result = REJECT, + .result_unpriv = REJECT, + }, }; static int probe_filter_length(const struct bpf_insn *fp) |