[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <c482c66b-a455-ff6e-7a6a-a8c5d717c457@huawei.com>
Date: Tue, 18 Oct 2022 09:48:15 +0800
From: shaozhengchao <shaozhengchao@...wei.com>
To: Eric Dumazet <edumazet@...gle.com>
CC: <netdev@...r.kernel.org>, <davem@...emloft.net>,
<yoshfuji@...ux-ipv6.org>, <dsahern@...nel.org>, <kuba@...nel.org>,
<pabeni@...hat.com>, <weiyongjun1@...wei.com>,
<yuehaibing@...wei.com>
Subject: Re: [PATCH net] ip6mr: fix UAF issue in ip6mr_sk_done() when
addrconf_init_net() failed
On 2022/10/17 23:58, Eric Dumazet wrote:
> On Mon, Oct 17, 2022 at 12:55 AM Zhengchao Shao
> <shaozhengchao@...wei.com> wrote:
>>
>> If the initialization fails in calling addrconf_init_net(), devconf_all is
>> the pointer that has been released. Then ip6mr_sk_done() is called to
>> release the net, accessing devconf->mc_forwarding directly causes invalid
>> pointer access.
>>
>> The process is as follows:
>> setup_net()
>> ops_init()
>> addrconf_init_net()
>> all = kmemdup(...) ---> alloc "all"
>> ...
>> net->ipv6.devconf_all = all;
>> __addrconf_sysctl_register() ---> failed
>> ...
>> kfree(all); ---> ipv6.devconf_all invalid
>> ...
>> ops_exit_list()
>> ...
>> ip6mr_sk_done()
>> devconf = net->ipv6.devconf_all;
>> //devconf is invalid pointer
>> if (!devconf || !atomic_read(&devconf->mc_forwarding))
>>
>>
>> Fixes: 7d9b1b578d67 ("ip6mr: fix use-after-free in ip6mr_sk_done()")
>
> Hmmm. I wonder if you are not masking a more serious bug.
>
> When I wrote this patch ( 7d9b1b578d67) I was following the standard
> rule of ops->exit() being called
> only if the corresponding ops->init() function had not failed.
>
> net/core/net_namespace.c:setup_net() even has some comments about this rule:
>
> out_undo:
> /* Walk through the list backwards calling the exit functions
> * for the pernet modules whose init functions did not fail.
> */
> list_add(&net->exit_list, &net_exit_list);
> saved_ops = ops;
> list_for_each_entry_continue_reverse(ops, &pernet_list, list)
> ops_pre_exit_list(ops, &net_exit_list);
>
> synchronize_rcu();
>
> ops = saved_ops;
> list_for_each_entry_continue_reverse(ops, &pernet_list, list)
> ops_exit_list(ops, &net_exit_list);
>
> ops = saved_ops;
> list_for_each_entry_continue_reverse(ops, &pernet_list, list)
> ops_free_list(ops, &net_exit_list);
>
> rcu_barrier();
> goto out;
>
>
Hi Eric:
Thank you for your reply. I wonder if fixing commit
e0da5a480caf ("[NETNS]: Create ipv6 devconf-s for namespaces")
would be more appropriate?
Zhengchao Shao
>
>> Signed-off-by: Zhengchao Shao <shaozhengchao@...wei.com>
>> ---
>> net/ipv6/addrconf.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
>> index 417834b7169d..9c3f5202a97b 100644
>> --- a/net/ipv6/addrconf.c
>> +++ b/net/ipv6/addrconf.c
>> @@ -7214,9 +7214,11 @@ static int __net_init addrconf_init_net(struct net *net)
>> __addrconf_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL);
>> err_reg_all:
>> kfree(dflt);
>> + net->ipv6.devconf_dflt = NULL;
>> #endif
>> err_alloc_dflt:
>> kfree(all);
>> + net->ipv6.devconf_all = NULL;
>> err_alloc_all:
>> kfree(net->ipv6.inet6_addr_lst);
>> err_alloc_addr:
>> --
>> 2.17.1
>>
Powered by blists - more mailing lists