When ia_cmds.sub_cmd is MEMDUMP_DEV in ia_ioctl, nullify the pointer fields of iadev before copying the whole structure to user space.
Signed-off-by: Fuqian Huang <huangfq.dax...@gmail.com> --- drivers/atm/iphase.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 5278c57dce73..3ca73625fb1a 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -2746,11 +2746,71 @@ static int ia_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags) IF_EVENT(printk(">ia_change_qos\n");) return 0; } + +static void ia_nullify_pointers(IADEV *src, IADEV *dest) +{ + memset(dest, 0, sizeof(IADEV)); + dest->tx_dma_q.qlen = src->tx_dma_q.qlen; + dest->tx_dma_q.lock = src->tx_dma_q.lock; + dest->tx_backlog.qlen = src->tx_backlog.qlen; + dest->tx_backlog.lock = src->tx_backlog.lock; + dest->tx_lock = src->tx_lock; + dest->tx_return_q.data.timestamp = src->tx_return_q.data.timestamp; + dest->close_pending = src->close_pending; + dest->close_wait.lock = src->close_wait.lock; + dest->timeout_wait.lock = src->timeout_wait.lock; + dest->num_tx_desc = src->num_tx_desc; + dest->tx_buf_sz = src->tx_buf_sz; + dest->rate_limit = src->rate_limit; + dest->tx_cell_cnt = src->tx_cell_cnt; + dest->tx_pkt_cnt = src->tx_pkt_cnt; + dest->rx_dma_q.qlen = src->rx_dma_q.qlen; + dest->rx_dma_q.lock = src->rx_dma_q.lock; + dest->rx_lock = src->rx_lock; + dest->num_rx_desc = src->num_rx_desc; + dest->rx_buf_sz = src->rx_buf_sz; + dest->rxing = src->rxing; + dest->rx_pkt_ram = src->rx_pkt_ram; + dest->rx_tmp_cnt = src->rx_tmp_cnt; + dest->rx_tmp_jif = src->rx_tmp_jif; + dest->drop_rxpkt = src->drop_rxpkt; + dest->drop_rxcell = src->drop_rxcell; + dest->rx_cell_cnt = src->rx_cell_cnt; + dest->rx_pkt_cnt = src->rx_pkt_cnt; + dest->mem = src->mem; + dest->real_base = src->real_base; + dest->pci_map_size = src->pci_map_size; + dest->irq = src->irq; + dest->bus = src->bus; + dest->dev_fn = src->dev_fn; + dest->phy_type = src->phy_type; + dest->num_vc = src->num_vc; + dest->memSize = src->memSize; + dest->memType = src->memType; + dest->ffL = src->ffL; + dest->rfL = src->rfL; + dest->carrier_detect = src->carrier_detect; + dest->tx_dma_cnt = src->tx_dma_cnt; + dest->rx_dma_cnt = src->rx_dma_cnt; + dest->NumEnabledCBR = src->NumEnabledCBR; + dest->rx_mark_cnt = src->rx_mark_cnt; + dest->CbrTotEntries = src->CbrTotEntries; + dest->CbrRemEntries = src->CbrRemEntries; + dest->CbrEntryPt = src->CbrEntryPt; + dest->Granularity = src->Granularity; + dest->sum_mcr = src->sum_mcr; + dest->sum_cbr = src->sum_cbr; + dest->LineRate = src->LineRate; + dest->n_abr = src->n_abr; + dest->host_tcq_wr = src->host_tcq_wr; + dest->tx_dle_dma = src->tx_dle_dma; + dest->rx_dle_dma = src->rx_dle_dma; +} static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) { IA_CMDBUF ia_cmds; - IADEV *iadev; + IADEV *iadev, *output; int i, board; u16 __user *tmps; IF_EVENT(printk(">ia_ioctl\n");) @@ -2769,8 +2829,15 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) switch (ia_cmds.sub_cmd) { case MEMDUMP_DEV: if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (copy_to_user(ia_cmds.buf, iadev, sizeof(IADEV))) - return -EFAULT; + output = kmalloc(sizeof(IADEV), GFP_KERNEL); + if (!output) + return -ENOMEM; + ia_nullify_pointers(iadev, output); + if (copy_to_user(ia_cmds.buf, output, sizeof(IADEV))) { + kfree(output); + return -EFAULT; + } + kfree(output); ia_cmds.status = 0; break; case MEMDUMP_SEGREG: -- 2.11.0