All of lore.kernel.org
 help / color / mirror / Atom feed
From: duoming@zju.edu.cn
To: linux-hams@vger.kernel.org, pabeni@redhat.com
Cc: ralf@linux-mips.org, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v5] net: rose: fix null-ptr-deref caused by rose_kill_by_neigh
Date: Sun, 10 Jul 2022 21:52:06 +0800 (GMT+08:00)	[thread overview]
Message-ID: <56319300.38660.181e861b71b.Coremail.duoming@zju.edu.cn> (raw)

Hello,

On Tue, 05 Jul 2022 10:43:44 +0200 pabeni@redhat.com wrote:

> On Sat, 2022-07-02 at 15:57 +0800, Duoming Zhou wrote:
> > When the link layer connection is broken, the rose->neighbour is
> > set to null. But rose->neighbour could be used by rose_connection()
> > and rose_release() later, because there is no synchronization among
> > them. As a result, the null-ptr-deref bugs will happen.
> > 
> > One of the null-ptr-deref bugs is shown below:
> > 
> >     (thread 1)                  |        (thread 2)
> >                                 |  rose_connect
> > rose_kill_by_neigh              |    lock_sock(sk)
> >   spin_lock_bh(&rose_list_lock) |    if (!rose->neighbour)
> >   rose->neighbour = NULL;//(1)  |
> >                                 |    rose->neighbour->use++;//(2)
> > 
> > The rose->neighbour is set to null in position (1) and dereferenced
> > in position (2).
> > 
> > The KASAN report triggered by POC is shown below:
> > 
> > KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f]
> > ...
> > RIP: 0010:rose_connect+0x6c2/0xf30
> > RSP: 0018:ffff88800ab47d60 EFLAGS: 00000206
> > RAX: 0000000000000005 RBX: 000000000000002a RCX: 0000000000000000
> > RDX: ffff88800ab38000 RSI: ffff88800ab47e48 RDI: ffff88800ab38309
> > RBP: dffffc0000000000 R08: 0000000000000000 R09: ffffed1001567062
> > R10: dfffe91001567063 R11: 1ffff11001567061 R12: 1ffff11000d17cd0
> > R13: ffff8880068be680 R14: 0000000000000002 R15: 1ffff11000d17cd0
> > ...
> > Call Trace:
> >   <TASK>
> >   ? __local_bh_enable_ip+0x54/0x80
> >   ? selinux_netlbl_socket_connect+0x26/0x30
> >   ? rose_bind+0x5b0/0x5b0
> >   __sys_connect+0x216/0x280
> >   __x64_sys_connect+0x71/0x80
> >   do_syscall_64+0x43/0x90
> >   entry_SYSCALL_64_after_hwframe+0x46/0xb0
> > 
> > This patch adds lock_sock() in rose_kill_by_neigh() in order to
> > synchronize with rose_connect() and rose_release().
> > 
> > Meanwhile, this patch adds sock_hold() protected by rose_list_lock
> > that could synchronize with rose_remove_socket() in order to mitigate
> > UAF bug caused by lock_sock() we add.
> > 
> > What's more, there is no need using rose_neigh_list_lock to protect
> > rose_kill_by_neigh(). Because we have already used rose_neigh_list_lock
> > to protect the state change of rose_neigh in rose_link_failed(), which
> > is well synchronized.
> > 
> > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> > Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
> > ---
> > Changes in v5:
> >   - v5: Use socket lock to protect comparison in rose_kill_by_neigh.
> > 
> >  net/rose/af_rose.c    | 12 ++++++++++++
> >  net/rose/rose_route.c |  2 ++
> >  2 files changed, 14 insertions(+)
> > 
> > diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
> > index bf2d986a6bc..6d5088b030a 100644
> > --- a/net/rose/af_rose.c
> > +++ b/net/rose/af_rose.c
> > @@ -165,14 +165,26 @@ void rose_kill_by_neigh(struct rose_neigh *neigh)
> >  	struct sock *s;
> >  
> >  	spin_lock_bh(&rose_list_lock);
> > +again:
> >  	sk_for_each(s, &rose_list) {
> >  		struct rose_sock *rose = rose_sk(s);
> >  
> > +		sock_hold(s);
> > +		spin_unlock_bh(&rose_list_lock);
> > +		lock_sock(s);
> >  		if (rose->neighbour == neigh) {
> >  			rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
> >  			rose->neighbour->use--;

I am sorry for the delay.

> Note that the code can held different socket lock while updating
> 'neighbour->use'. That really means that such updates can really race
> each other, with bad results.

Thank you for your time and suggestions! I agree with you and I will improve
this patch.

> I think the only safe way out is using an atomic_t for 'neighbour->use'
> (likely a refcount_t would be a better option).

I will use refcount_t to manage the 'neighbour->use'.

> All the above deserves a separate patch IMHO.
> 
> >  			rose->neighbour = NULL;
> > +			release_sock(s);
> > +			sock_put(s);
> > +			spin_lock_bh(&rose_list_lock);
> > +			goto again;
> 
> This chunk is dup of the following lines, it could be dropped...
> 
> >  		}
> > +		release_sock(s);
> > +		sock_put(s);
> > +		spin_lock_bh(&rose_list_lock);
> > +		goto again;
> 
> ... if this would be correct, which apparently is not.
> 
> What happens when 'rose->neighbour' is different from 'neigh' for first
> socket in rose_list?

I understand. If the 'rose->neighbour' is different from 'neigh' for the first socket
in the rose_list, the code will goto again and re-search the list. This will cause
infinite loop. I will improve this.

Best regards,
Duoming Zhou

             reply	other threads:[~2022-07-10 13:52 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-10 13:52 duoming [this message]
2022-07-11 17:49 ` [PATCH net v5] net: rose: fix null-ptr-deref caused by rose_kill_by_neigh Jakub Kicinski
2022-07-12  0:08   ` duoming
  -- strict thread matches above, loose matches on Subject: below --
2022-07-02  7:57 Duoming Zhou
2022-07-05  8:43 ` Paolo Abeni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56319300.38660.181e861b71b.Coremail.duoming@zju.edu.cn \
    --to=duoming@zju.edu.cn \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-hams@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=ralf@linux-mips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.