linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lukasz Majewski <lukma@denx.de>
To: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Colin Ian King <colin.king@canonical.com>,
	Mark Brown <broonie@kernel.org>,
	linux-spi <linux-spi@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: spi: Add call to spi_slave_abort() function when spidev driver is released
Date: Thu, 26 Sep 2019 16:06:45 +0200	[thread overview]
Message-ID: <20190926160645.0a2623fa@jawa> (raw)
In-Reply-To: <CAMuHMdXm+vUB4iRTsTq64Kg2KC2p7AA1TwFgjc7FuCeiS9EG=Q@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4400 bytes --]

Hi Geert,

> Hi Lukasz,
> 
> On Thu, Sep 26, 2019 at 2:49 PM Lukasz Majewski <lukma@denx.de> wrote:
> > > On Thu, Sep 26, 2019 at 12:14 PM Lukasz Majewski <lukma@denx.de>
> > > wrote:  
> > > > > Static analysis with Coverity has detected an potential
> > > > > dereference of a free'd object with commit:
> > > > >
> > > > > commit 9f918a728cf86b2757b6a7025e1f46824bfe3155
> > > > > Author: Lukasz Majewski <lukma@denx.de>
> > > > > Date:   Wed Sep 25 11:11:42 2019 +0200
> > > > >
> > > > >     spi: Add call to spi_slave_abort() function when spidev
> > > > > driver is released  
> 
> > > > > The call to spi_slave_abort() on spidev is reading an earlier
> > > > > kfree'd spidev.  
> > > >
> > > > Thanks for spotting this issue - indeed there is a possibility
> > > > to use spidev after being kfree'd.  
> > >
> > > Worse, this makes me realize spidev->spi may be a NULL pointer,
> > > which will be dereferenced by spi_slave_abort(), so caching it
> > > before the call to kfree() won't work.  
> >
> > The patch as it is now can be fixed as follows:
> >
> > static int spidev_release(struct inode *inode, struct file *filp)
> > {
> >         struct spidev_data      *spidev;
> >
> >         mutex_lock(&device_list_lock);
> >         spidev = filp->private_data;
> >         filp->private_data = NULL;
> >
> > #ifdef CONFIG_SPI_SLAVE
> >         if (spidev->spi)
> >                 spi_slave_abort(spidev->spi);
> > #endif
> >
> >         /* last close? */
> >         spidev->users--;
> >         if (!spidev->users) {
> >                 int dofree;
> >
> >                 /* free buffers */
> >
> >                 spin_lock_irq(&spidev->spi_lock);
> >                 if (spidev->spi)
> >                         spidev->speed_hz =
> > spidev->spi->max_speed_hz;
> >
> >                 /* ... after we unbound from the underlying device?
> > */ //
> >                 // [*]
> >                 //
> >                 dofree = (spidev->spi == NULL);
> >                 spin_unlock_irq(&spidev->spi_lock);
> >
> >                 if (dofree)
> >                         kfree(spidev);
> >         }
> >
> >         mutex_unlock(&device_list_lock);
> >
> >         return 0;
> > }
> >
> > The question is if we shall call the spi_slave_abort() when
> > cleaning up spi after releasing last reference, or each time
> > release callback is called ?  
> 
> TBH, I don't know.  Is it realistic that there are multiple opens?

I'm using on my setup only one test program to use /dev/spidevX.Y and
/dev/spidevA.B (loopback with wired connection).

However, you also shall be able to connect via ssh and run the same
setup in parallel...

> 
> > > > However, Geert (CC'ed) had some questions about placement of
> > > > this function call, so I will wait with providing fix until he
> > > > replies.  
> > >
> > > Seems like this needs more thought...  
> >
> > Could you be more specific?
> >
> > Do you mean to move the spi_slave_abort() call just before dofree
> > evaluation ? ([*]).  
> 
> That means the abort is called only for the last user.
> And only if the underlying device still exists.  Which means that if
> it has disappeared (how can that happen? spidev unbind?),

In my case, I just disconnect some SPI signals and the test program
just hangs. I do need to ctrl+c to stop it (or use timeout). 

From my debugging the .release callback is called each time the program
is aborted (either with ctrl+c or timeout).

> the slave
> was never aborted.  Non-spidev slaves can do the abort in their
> .remove() callbacks (at least my two sample slave drivers do).
> So probably we need some explicit slave abort in the unbind case too?

As I've described above - after "introducing" distortion to SPI I need
to explicitly exit the hung test program with ctrl+c.

> 
> The more I think about it, the more things I see that can go wrong...

But for now we don't have any way to recover the slave after corruption
on SPI transmission.

> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

  reply	other threads:[~2019-09-26 14:06 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-26 10:00 spi: Add call to spi_slave_abort() function when spidev driver is released Colin Ian King
2019-09-26 10:14 ` Lukasz Majewski
2019-09-26 10:15   ` Colin Ian King
2019-09-26 10:32   ` Geert Uytterhoeven
2019-09-26 12:49     ` Lukasz Majewski
2019-09-26 13:51       ` Geert Uytterhoeven
2019-09-26 14:06         ` Lukasz Majewski [this message]
2019-09-26 15:17           ` Mark Brown
2019-09-26 22:38             ` Lukasz Majewski
2019-10-07 17:02               ` Mark Brown

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=20190926160645.0a2623fa@jawa \
    --to=lukma@denx.de \
    --cc=broonie@kernel.org \
    --cc=colin.king@canonical.com \
    --cc=geert@linux-m68k.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-spi@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).