diff options
author | wwang <wei_wang@realsil.com.cn> | 2012-03-27 12:43:11 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-10 20:18:16 +0400 |
commit | 0d05568ac79bfc595f1eadc3e0fd7a20a45f7b69 (patch) | |
tree | d15134080908344c9518d936b98a31f511aa4892 /drivers/staging | |
parent | 4ca5218e3939685c2325fc0a0a1ac8150272c93f (diff) | |
download | linux-0d05568ac79bfc595f1eadc3e0fd7a20a45f7b69.tar.xz |
staging:rts_pstor:Fix possible panic by NULL pointer dereference
rtsx_transport.c (rtsx_transfer_sglist_adma_partial):
pointer struct scatterlist *sg, which is mapped in dma_map_sg,
is used as an iterator in later transfer operation. It is corrupted and
passed to dma_unmap_sg, thus causing fatal unmap of some erroneous address.
Fix it by duplicating *sg_ptr for iterating.
Signed-off-by: wwang <wei_wang@realsil.com.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/rts_pstor/rtsx_transport.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/staging/rts_pstor/rtsx_transport.c b/drivers/staging/rts_pstor/rtsx_transport.c index 4e3d2c106af0..9b2e5c99870f 100644 --- a/drivers/staging/rts_pstor/rtsx_transport.c +++ b/drivers/staging/rts_pstor/rtsx_transport.c @@ -335,6 +335,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, int sg_cnt, i, resid; int err = 0; long timeleft; + struct scatterlist *sg_ptr; u32 val = TRIG_DMA; if ((sg == NULL) || (num_sg <= 0) || !offset || !index) @@ -371,7 +372,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir); resid = size; - + sg_ptr = sg; chip->sgi = 0; /* Usually the next entry will be @sg@ + 1, but if this sg element * is part of a chained scatterlist, it could jump to the start of @@ -379,14 +380,14 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, * the proper sg */ for (i = 0; i < *index; i++) - sg = sg_next(sg); + sg_ptr = sg_next(sg_ptr); for (i = *index; i < sg_cnt; i++) { dma_addr_t addr; unsigned int len; u8 option; - addr = sg_dma_address(sg); - len = sg_dma_len(sg); + addr = sg_dma_address(sg_ptr); + len = sg_dma_len(sg_ptr); RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len); @@ -415,7 +416,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, if (!resid) break; - sg = sg_next(sg); + sg_ptr = sg_next(sg_ptr); } RTSX_DEBUGP("SG table count = %d\n", chip->sgi); |