Skip to content

Commit e59089d

Browse files
l0rdg3xplappermaul
authored andcommitted
realtek: l3: skip IPv4 routes without a nexthop device
A blackhole, unreachable or prohibit route has no device behind its nexthop: fib_create_info() refuses one for these types and skips the nexthop check that would find one, so fib_nh_dev stays NULL. otto_l3_fib_add_v4() hands that device to is_vlan_dev() before any test, and otto_l3_fib_check_v4(), which the delete path runs as well, does the same in its variable initialisers. On an RTL9303 with the L3 offload built in, "ip route add blackhole 10.99.8.0/24" oopses in the rtl83xx work queue and panics the box: CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 8070fe3c, ra == 80710594 Workqueue: rtl83xx otto_l3_fib_event_work_do epc : 8070fe3c otto_l3_fib_add_v4+0x1c0/0x794 Kernel panic - not syncing: Fatal exception The faulting load is the priv_flags word is_vlan_dev() tests. Such routes are common on a router, for address space it announces but does not use. Handle them where a route through a nexthop object is already handled, for the same reasons: there is nothing to offload, and the route can still replace one that was, so the entry for its destination is taken out, and a host route is trapped where the host table can hold it. The delete path takes the same exit. Tested on an RTL9303 (Hasivo S1100W-8XGT-SE) with the L3 offload built in. Without this change the command above panics the box; with it, a blackhole /24 stays in the kernel with no entry in hardware, an offloaded /24 replaced by a blackhole loses its entry and gets it back when replaced through the gateway again, a blackhole /32 gets a trap entry in the host table, unreachable and prohibit routes go in as well, and every delete leaves no entry and no oops. RTL839x, which runs this code in a stock build, was not tested. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net> Link: openwrt/openwrt#25513 Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
1 parent db61fd4 commit e59089d

1 file changed

Lines changed: 11 additions & 8 deletions

File tree

  • target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx

‎target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c‎

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,13 +1526,14 @@ static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi
15261526
struct fib_nh *nh;
15271527
int port, vlan;
15281528

1529-
/* A route through a nexthop object is not offloaded and has no
1530-
* nexthop array to read, but it can replace a route that is. An
1531-
* offloaded shorter prefix would forward its traffic, so trap it where
1532-
* the host table can hold it.
1529+
/* A route through a nexthop object has no nexthop array to read, and a
1530+
* blackhole, unreachable or prohibit route has no device behind its
1531+
* nexthop. Neither is offloaded, but either can replace a route that
1532+
* is. An offloaded shorter prefix would forward its traffic, so trap
1533+
* it where the host table can hold it.
15331534
*/
1534-
if (info->fi->nh) {
1535-
dev_dbg(ctrl->dev, "route through a nexthop object, not offloaded\n");
1535+
if (info->fi->nh || !fib_info_nh(info->fi, 0)->fib_nh_dev) {
1536+
dev_dbg(ctrl->dev, "route not offloaded: no device or a nexthop object\n");
15361537
route = otto_l3_route_find(ctrl, info->tb_id, ROUTE_TYPE_IP4UC, info->dst,
15371538
NULL, info->dst_len);
15381539
if (route)
@@ -1646,8 +1647,10 @@ static int otto_l3_fib_del_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi
16461647
struct in6_addr gw;
16471648
struct fib_nh *nh;
16481649

1649-
/* A route through a nexthop object holds at most a trap entry */
1650-
if (info->fi->nh) {
1650+
/* A route through a nexthop object or without a device holds at most a
1651+
* trap entry
1652+
*/
1653+
if (info->fi->nh || !fib_info_nh(info->fi, 0)->fib_nh_dev) {
16511654
route = otto_l3_route_find(ctrl, info->tb_id, ROUTE_TYPE_IP4UC, info->dst,
16521655
NULL, info->dst_len);
16531656
if (route)

0 commit comments

Comments
 (0)