Re: Exploitable bugs in AF_VSOCK implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 31.03.2021 18:26, Dan Carpenter wrote:
> Hi Alexander,
> 
> I enjoyed reading your blog entries for CVE-2017-2636 and CVE-2019-18683.

Hello Dan, thanks!

> https://lore.kernel.org/lkml/20210201084719.2257066-1-alex.popov@xxxxxxxxx/
> 
> My understanding is that you were able to write a privilege escalataion
> bug for this?  Are you going to do a write up for this one as well?

Yes, I will give a talk about my exploit for CVE-2021-26708 at Zer0Con and
publish the article next week:
https://zer0con.org/#speaker-section

I'm finishing the article right now.

> Was the trick to exploiting it to use the free in vsock_deassign_transport()?

Yes!

> I've wanted to look for these in Smatch (my static analysis tool) for a
> long time.  I wrote a very naive first draft implementation.  What it
> looks for is when we access struct sock members before calling
> lock_sock().  It generated 8 warnings.  Six were false positives but I
> think that two were probably real bugs.

Cool!

> net/nfc/llcp_sock.c:313 nfc_llcp_getsockopt() warn: unlocked access 'llcp_sock->local' expected lock '&sk->sk_lock.slock'
> net/nfc/llcp_sock.c:597 llcp_sock_release() warn: unlocked access 'llcp_sock->local' expected lock '&sk->sk_lock.slock'
> 
> But I think it would be hard to exploit those because the race is very
> tiny.

I can't say about these two cases, but for CVE-2021-26708 the race window is huge.

To hit the race condition I have two pthreads that work in parallel:
 - 1st pthread calls lock_sock() and performs some work with the virtual socket;
 - 2nd pthread saves the value to a local variable and hangs on lock_sock(),
since the lock is already acquired.

When the first pthread finishes the work and releases the lock, the second
pthread is able to finish lock_sock() and proceed with the out-of-date value in
the local variable.

Maybe this strategy can be used in the cases that you detected.

> Several people (maybe most recently Lukas Bulwahn but someone else at
> Linux Plumbers) suggested that a way to find race conditions is to look
> at the line directly after taking a lock.  So if you have:
> 
> 	mutex_lock(&dsp->pwr_lock);
> 	if (!dsp->wmfw_file_name || !dsp->booted)
> 
> Then that means that the ->pwr_lock is protecting ->wmfw_file_name and
> ->booted.  So I wrote a check that made a list of these sorts of
> pairings.  Then I wrote a check that said:
> 
> If you take save a "protected" struct member and then take the lock
> print a warning that the access should have been inside the lock.  So a
> warning looks like this:
> 
> sound/pci/cs46xx/cs46xx_lib.c:2148 snd_cs46xx_spdif_default_get() warn: unlocked access 'ins' (line 2146) expected lock '&chip->spos_mutex'
>   2142  static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol,
>   2143                                          struct snd_ctl_elem_value *ucontrol)
>   2144  {
>   2145          struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
>   2146          struct dsp_spos_instance * ins = chip->dsp_spos_instance;
>                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Smatch is saying this assignment should have been done
> 
>   2147  
>   2148          mutex_lock(&chip->spos_mutex);
>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> inside this lock.
> 
>   2149          ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);
>   2150          ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);
>   2151          ucontrol->value.iec958.status[2] = 0;
>   2152          ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);
>   2153          mutex_unlock(&chip->spos_mutex);
>   2154  
>   2155          return 0;
>   2156  }
> 
> That seems probably true but also a pretty harmless.  I've attached a
> sample of the output just in case you're curious.
> 
> Do you have any idea how I could get more worthwhile results than this?

I would also propose to use your approach and search for access to "protected"
struct fields after UNlock functions.

Best regards,
Alexander



[Index of Archives]     [Kernel Development]     [Kernel Announce]     [Kernel Newbies]     [Linux Networking Development]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Device Mapper]

  Powered by Linux