All of lore.kernel.org
 help / color / mirror / Atom feed
From: Russell King - ARM Linux <linux@armlinux.org.uk>
To: Jens Axboe <axboe@kernel.dk>
Cc: Ulf Hansson <ulf.hansson@linaro.org>,
	Shawn Lin <shawn.lin@rock-chips.com>,
	"linux-mmc@vger.kernel.org" <linux-mmc@vger.kernel.org>,
	Christoph Hellwig <hch@lst.de>,
	linux-block@vger.kernel.org
Subject: Re: [PATCH v4] mmc: sdio: check the buffer address for sdio API
Date: Tue, 14 Feb 2017 19:34:57 +0000	[thread overview]
Message-ID: <20170214193457.GZ27312@n2100.armlinux.org.uk> (raw)
In-Reply-To: <3ab69e5c-e661-3011-cab4-3066024ecf36@kernel.dk>

On Tue, Feb 14, 2017 at 09:18:43AM -0700, Jens Axboe wrote:
> The current situation seems like a bit of a mess. Why don't you have two
> entry points, one for DMA and one for PIO. If the caller doesn't know if
> he can use DMA, he'd better call the PIO variant. Either that, or audit
> all callers and ensure they do the right thing wrt having a dma capable
> buffer.

It really shouldn't matter.  MMC interfaces are just like USB - you
have a host controller, which interfaces what is a multi-lane serial
bus to the system.  The SDIO card shouldn't care one bit whether
the host controller is using DMA or PIO.

However, I think that the DMA vs PIO thing is actually misleading here,
that's really not the issue at all.

Looking at the oops, I see it uses sdio_memcpy_toio().  Tracing that
code leads me to here:

                for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
                        sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
                                        min(seg_size, left_size),
                                        offset_in_page(buf + (i * seg_size)));

so the buffer that is passed into sdio_memcpy_toio() gets passed into
virt_to_page().

Firstly, the fact that it's passed to virt_to_page() means that "buf"
must _only_ _ever_ be a lowmem address.  It can't ever be a vmalloc
address (virt_to_page() is invalid on anything but lowmem.)  Just like
certain kernel interfaces, passing pointers to memory of different types
from the one intended by the interface produces invalid results, and
that seems to be what's happening here.

Secondly, it's a scatterlist, and scatterlists can be passed to DMA
mapping operations, which also implies that _if_ a host driver decides
to use DMA on it, the buffer better be DMA-able.

Thirdly, while PIO may work (or even appear to work) because _maybe_
converting a vmalloc address to a ficticious struct page + offset, and
then converting that back again _might_ result in hitting the correct
memory, but it's not guaranteed to.

I suspect that virt_to_page() + kmap_atomic() is likely to try to
dereference a struct page pointer that does not point at a legal entry
in the memmap arrays, and result in scribbling over some random part
of kernel memory.

So every way I look at this, the binary driver that Shawn downloaded
is buggy, whether the host controller uses PIO or DMA.

I bet if Shawn tries running it against a modern kernel with
CONFIG_DEBUG_VIRTUAL enabled, Shawn will get complaints backing up
my claim.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

  reply	other threads:[~2017-02-14 19:34 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-07  0:54 [PATCH v4] mmc: sdio: check the buffer address for sdio API Shawn Lin
2017-02-14  9:17 ` Ulf Hansson
2017-02-14 16:18   ` Jens Axboe
2017-02-14 19:34     ` Russell King - ARM Linux [this message]
2017-02-15  4:12       ` Shawn Lin
2017-02-15  9:55         ` Russell King - ARM Linux
2017-02-14 19:45 ` Christoph Hellwig

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=20170214193457.GZ27312@n2100.armlinux.org.uk \
    --to=linux@armlinux.org.uk \
    --cc=axboe@kernel.dk \
    --cc=hch@lst.de \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=shawn.lin@rock-chips.com \
    --cc=ulf.hansson@linaro.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.