730-11-v6.3-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. From: Felix Fietkau <[email protected]>
  2. Date: Thu, 17 Nov 2022 11:58:21 +0100
  3. Subject: [PATCH] net: ethernet: mtk_eth_soc: fix flow_offload related refcount
  4. bug
  5. Since we call flow_block_cb_decref on FLOW_BLOCK_UNBIND, we need to call
  6. flow_block_cb_incref unconditionally, even for a newly allocated cb.
  7. Fixes a use-after-free bug
  8. Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support")
  9. Signed-off-by: Felix Fietkau <[email protected]>
  10. ---
  11. --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  12. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  13. @@ -554,6 +554,7 @@ mtk_eth_setup_tc_block(struct net_device
  14. struct mtk_eth *eth = mac->hw;
  15. static LIST_HEAD(block_cb_list);
  16. struct flow_block_cb *block_cb;
  17. + bool register_block = false;
  18. flow_setup_cb_t *cb;
  19. if (!eth->soc->offload_version)
  20. @@ -568,16 +569,20 @@ mtk_eth_setup_tc_block(struct net_device
  21. switch (f->command) {
  22. case FLOW_BLOCK_BIND:
  23. block_cb = flow_block_cb_lookup(f->block, cb, dev);
  24. - if (block_cb) {
  25. - flow_block_cb_incref(block_cb);
  26. - return 0;
  27. + if (!block_cb) {
  28. + block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
  29. + if (IS_ERR(block_cb))
  30. + return PTR_ERR(block_cb);
  31. +
  32. + register_block = true;
  33. }
  34. - block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
  35. - if (IS_ERR(block_cb))
  36. - return PTR_ERR(block_cb);
  37. - flow_block_cb_add(block_cb, f);
  38. - list_add_tail(&block_cb->driver_list, &block_cb_list);
  39. + flow_block_cb_incref(block_cb);
  40. +
  41. + if (register_block) {
  42. + flow_block_cb_add(block_cb, f);
  43. + list_add_tail(&block_cb->driver_list, &block_cb_list);
  44. + }
  45. return 0;
  46. case FLOW_BLOCK_UNBIND:
  47. block_cb = flow_block_cb_lookup(f->block, cb, dev);