Skip to content

Commit 7b39d90

Browse files
shimodaygregkh
authored andcommitted
serial: sh-sci: Fix NULL pointer dereference if HIGHMEM is enabled
This patch fixes an issue that this driver causes a NULL pointer dereference in the following conditions: - CONFIG_HIGHMEM and CONFIG_SERIAL_SH_SCI_DMA are enabled - This driver runs on the sci_dma_rx_push() This issue was caused by virt_to_page(buf) in the sci_request_dma() because this driver didn't check if the "buf" was valid or not. So, this patch uses the "buf" from dma_alloc_coherent() as is, not page. This patch also fixes a WARNING issue in sci_rx_dma_release(): WARNING: CPU: 0 PID: 1328 at lib/dma-debug.c:1125 check_unmap+0x444/0x848() rcar-dmac e6700000.dma-controller: DMA-API: device driver frees DMA memory with different CPU address [device address=0x000000006dd89000] [size=64 bytes] [cpu alloc address=0x000000016189c000] [cpu free address=0x0000000080000000] WARNING: CPU: 1 PID: 1 at drivers/base/dma-mapping.c:334 dma_common_free_remap+0x48/0x6c() trying to free invalid coherent area: (null) Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> [geert] Rebased [geert] Reworded [geert] Dropped .rx_chunk, as it's always identical to .rx_buf[0] Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ba172c7 commit 7b39d90

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

drivers/tty/serial/sh-sci.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct sci_port {
110110
dma_addr_t tx_dma_addr;
111111
unsigned int tx_dma_len;
112112
struct scatterlist sg_rx[2];
113+
void *rx_buf[2];
113114
size_t buf_len_rx;
114115
struct sh_dmae_slave param_tx;
115116
struct sh_dmae_slave param_rx;
@@ -1301,14 +1302,13 @@ static void sci_dma_tx_complete(void *arg)
13011302
}
13021303

13031304
/* Locking: called with port lock held */
1304-
static int sci_dma_rx_push(struct sci_port *s, struct scatterlist *sg,
1305-
size_t count)
1305+
static int sci_dma_rx_push(struct sci_port *s, void *buf, size_t count)
13061306
{
13071307
struct uart_port *port = &s->port;
13081308
struct tty_port *tport = &port->state->port;
13091309
int copied;
13101310

1311-
copied = tty_insert_flip_string(tport, sg_virt(sg), count);
1311+
copied = tty_insert_flip_string(tport, buf, count);
13121312
if (copied < count) {
13131313
dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
13141314
count - copied);
@@ -1347,7 +1347,7 @@ static void sci_dma_rx_complete(void *arg)
13471347

13481348
active = sci_dma_rx_find_active(s);
13491349
if (active >= 0)
1350-
count = sci_dma_rx_push(s, &s->sg_rx[active], s->buf_len_rx);
1350+
count = sci_dma_rx_push(s, s->rx_buf[active], s->buf_len_rx);
13511351

13521352
mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
13531353

@@ -1370,8 +1370,8 @@ static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
13701370
s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
13711371
spin_unlock_irqrestore(&port->lock, flags);
13721372
dmaengine_terminate_all(chan);
1373-
dma_free_coherent(chan->device->dev, s->buf_len_rx * 2,
1374-
sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
1373+
dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0],
1374+
sg_dma_address(&s->sg_rx[0]));
13751375
dma_release_channel(chan);
13761376
if (enable_pio)
13771377
sci_start_rx(port);
@@ -1464,7 +1464,7 @@ static void work_fn_rx(struct work_struct *work)
14641464
dev_dbg(port->dev, "Read %u bytes with cookie %d\n", read,
14651465
s->active_rx);
14661466

1467-
count = sci_dma_rx_push(s, &s->sg_rx[new], read);
1467+
count = sci_dma_rx_push(s, s->rx_buf[new], read);
14681468

14691469
if (count)
14701470
tty_flip_buffer_push(&port->state->port);
@@ -1756,9 +1756,9 @@ static void sci_request_dma(struct uart_port *port)
17561756
struct scatterlist *sg = &s->sg_rx[i];
17571757

17581758
sg_init_table(sg, 1);
1759-
sg_set_page(sg, virt_to_page(buf), s->buf_len_rx,
1760-
(uintptr_t)buf & ~PAGE_MASK);
1759+
s->rx_buf[i] = buf;
17611760
sg_dma_address(sg) = dma;
1761+
sg->length = s->buf_len_rx;
17621762

17631763
buf += s->buf_len_rx;
17641764
dma += s->buf_len_rx;

0 commit comments

Comments
 (0)