[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAKgT0Udg5hSKnbfnteA8H5vdxqDmxrhT7nH2Ued-J96+4_Te-w@mail.gmail.com>
Date: Wed, 20 Dec 2017 09:46:01 -0800
From: Alexander Duyck <alexander.duyck@...il.com>
To: Ido Schimmel <idosch@...lanox.com>
Cc: Netdev <netdev@...r.kernel.org>,
David Miller <davem@...emloft.net>,
"Duyck, Alexander H" <alexander.h.duyck@...el.com>,
David Ahern <dsahern@...il.com>,
Fengguang Wu <fengguang.wu@...el.com>, mlxsw@...lanox.com
Subject: Re: [PATCH net v3] ipv4: Fix use-after-free when flushing FIB tables
On Wed, Dec 20, 2017 at 9:34 AM, Ido Schimmel <idosch@...lanox.com> wrote:
> 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.
>
> v3: Reworded comment according to Alex's suggestion.
> v2: Add a comment to make the fix more explicit per Dave's and Alex's
> feedback.
>
> Fixes: 0ddcf43d5d4a ("ipv4: FIB Local/MAIN table collapse")
> Signed-off-by: Ido Schimmel <idosch@...lanox.com>
> Reported-by: Fengguang Wu <fengguang.wu@...el.com>
Acked-by: Alexander Duyck <alexander.h.duyck@...el.com>
> ---
> net/ipv4/fib_frontend.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
> index f52d27a422c3..08259d078b1c 100644
> --- a/net/ipv4/fib_frontend.c
> +++ b/net/ipv4/fib_frontend.c
> @@ -1298,14 +1298,19 @@ static int __net_init ip_fib_net_init(struct net *net)
>
> static void ip_fib_net_exit(struct net *net)
> {
> - unsigned int i;
> + int i;
>
> rtnl_lock();
> #ifdef CONFIG_IP_MULTIPLE_TABLES
> RCU_INIT_POINTER(net->ipv4.fib_main, NULL);
> RCU_INIT_POINTER(net->ipv4.fib_default, NULL);
> #endif
> - for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
> + /* Destroy the tables in reverse order to guarantee that the
> + * local table, ID 255, is destroyed before the main table, ID
> + * 254. This is necessary as the local table may contain
> + * references to data contained in the main table.
> + */
> + for (i = FIB_TABLE_HASHSZ - 1; i >= 0; i--) {
> struct hlist_head *head = &net->ipv4.fib_table_hash[i];
> struct hlist_node *tmp;
> struct fib_table *tb;
> --
> 2.14.3
>
Powered by blists - more mailing lists