From: Ido Schimmel <ido...@mellanox.com> Date: Mon, 18 Dec 2017 10:13:20 +0200
> Since commit 0ddcf43d5d4a ("ipv4: FIB Local/MAIN table collapse") the > local table uses the same trie allocated for the main table when custom > rules are not in use. > > When a net namespace is dismantled, the main table is flushed and freed > (via an RCU callback) before the local table. In case the callback is > invoked before the local table is iterated, a use-after-free can occur. > > Fix this by iterating over the FIB tables in reverse order, so that the > main table is always freed after the local table. > > Fixes: 0ddcf43d5d4a ("ipv4: FIB Local/MAIN table collapse") > Signed-off-by: Ido Schimmel <ido...@mellanox.com> > Reported-by: Fengguang Wu <fengguang...@intel.com> This is really too clever of a fix I think :-) I would prefer if we fixed things more explicitly. In struct fib_table you can add a "data_ref" integer. Any pointer reference created to fib_table->__data increases this counter. It is always done inside of RTNL locking, so should be doable without atomics or extra locking. For a non-aliased fib_table we go: if (!--fib_table->data_ref) kfree(fib_table); And for aliased ones we do something like: if (fib_table->tb_data != fib_table->__data) { void *data = fib_table->fb_data; struct fib_table *alias; alias = container_of(data, struct fib_table, __data[0]); if (!--alias->data_ref) kfree(alias); kfree(fib_table); } Something like that.