From c9ee69c5e2dc41e4153b3742db1f3dde856d539c Mon Sep 17 00:00:00 2001 From: Zhao Qiang Date: Thu, 21 Jan 2016 09:06:04 +0800 Subject: qe/ic: fix a buffer overflow error and add check elsewhere 127 is the theoretical up boundary of QEIC number, in fact there only be 44 qe_ic_info now. add check to overflow for qe_ic_info Signed-off-by: Zhao Qiang Acked-by: Li Yang Signed-off-by: Scott Wood --- drivers/soc/fsl/qe/qe_ic.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c index b77d01ff8330..ec2ca864b0c5 100644 --- a/drivers/soc/fsl/qe/qe_ic.c +++ b/drivers/soc/fsl/qe/qe_ic.c @@ -259,6 +259,11 @@ static int qe_ic_host_map(struct irq_domain *h, unsigned int virq, struct qe_ic *qe_ic = h->host_data; struct irq_chip *chip; + if (hw >= ARRAY_SIZE(qe_ic_info)) { + pr_err("%s: Invalid hw irq number for QEIC\n", __func__); + return -EINVAL; + } + if (qe_ic_info[hw].mask == 0) { printk(KERN_ERR "Can't map reserved IRQ\n"); return -EINVAL; @@ -407,7 +412,8 @@ int qe_ic_set_priority(unsigned int virq, unsigned int priority) if (priority > 8 || priority == 0) return -EINVAL; - if (src > 127) + if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), + "%s: Invalid hw irq number for QEIC\n", __func__)) return -EINVAL; if (qe_ic_info[src].pri_reg == 0) return -EINVAL; @@ -436,6 +442,9 @@ int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high) if (priority > 2 || priority == 0) return -EINVAL; + if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), + "%s: Invalid hw irq number for QEIC\n", __func__)) + return -EINVAL; switch (qe_ic_info[src].pri_reg) { case QEIC_CIPZCC: -- cgit v1.2.3 From 713df30bd9a036196efd58887c10e0d3ee0928f9 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Tue, 26 Jan 2016 14:22:01 +0530 Subject: qe: Make cpm_muram_alloc_common static as cpm_muram_alloc_common is used only in this file, making it static Signed-off-by: Saurabh Sengar Signed-off-by: Scott Wood --- drivers/soc/fsl/qe/qe_common.c | 66 +++++++++++++++++++++--------------------- include/soc/fsl/qe/qe.h | 2 -- 2 files changed, 33 insertions(+), 35 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c index 419fa5b7be4d..e18159acfe45 100644 --- a/drivers/soc/fsl/qe/qe_common.c +++ b/drivers/soc/fsl/qe/qe_common.c @@ -102,6 +102,39 @@ out_muram: return ret; } +/* + * cpm_muram_alloc_common - cpm_muram_alloc common code + * @size: number of bytes to allocate + * @algo: algorithm for alloc. + * @data: data for genalloc's algorithm. + * + * This function returns an offset into the muram area. + */ +static unsigned long cpm_muram_alloc_common(unsigned long size, + genpool_algo_t algo, void *data) +{ + struct muram_block *entry; + unsigned long start; + + start = gen_pool_alloc_algo(muram_pool, size, algo, data); + if (!start) + goto out2; + start = start - GENPOOL_OFFSET; + memset_io(cpm_muram_addr(start), 0, size); + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + goto out1; + entry->start = start; + entry->size = size; + list_add(&entry->head, &muram_block_list); + + return start; +out1: + gen_pool_free(muram_pool, start, size); +out2: + return (unsigned long)-ENOMEM; +} + /* * cpm_muram_alloc - allocate the requested size worth of multi-user ram * @size: number of bytes to allocate @@ -175,39 +208,6 @@ unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) } EXPORT_SYMBOL(cpm_muram_alloc_fixed); -/* - * cpm_muram_alloc_common - cpm_muram_alloc common code - * @size: number of bytes to allocate - * @algo: algorithm for alloc. - * @data: data for genalloc's algorithm. - * - * This function returns an offset into the muram area. - */ -unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo, - void *data) -{ - struct muram_block *entry; - unsigned long start; - - start = gen_pool_alloc_algo(muram_pool, size, algo, data); - if (!start) - goto out2; - start = start - GENPOOL_OFFSET; - memset_io(cpm_muram_addr(start), 0, size); - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - goto out1; - entry->start = start; - entry->size = size; - list_add(&entry->head, &muram_block_list); - - return start; -out1: - gen_pool_free(muram_pool, start, size); -out2: - return (unsigned long)-ENOMEM; -} - /** * cpm_muram_addr - turn a muram offset into a virtual address * @offset: muram offset to convert diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index c7fa36c335c9..33b29ead3d55 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -103,8 +103,6 @@ int cpm_muram_init(void); unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); int cpm_muram_free(unsigned long offset); unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); -unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo, - void *data); void __iomem *cpm_muram_addr(unsigned long offset); unsigned long cpm_muram_offset(void __iomem *addr); dma_addr_t cpm_muram_dma(void __iomem *addr); -- cgit v1.2.3 From 66923a60ad80a963c0cd5ceecba9ba377cefba47 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Sun, 24 Jan 2016 12:24:06 +0530 Subject: qe: Use GFP_ATOMIC while spin_lock_irqsave is held cpm_muram_alloc_common is called twice and both the times spin_lock_irqsave is held. Using GFP_KERNEL can sleep in spin_lock_irqsave context and cause deadlock Signed-off-by: Saurabh Sengar Signed-off-by: Scott Wood --- drivers/soc/fsl/qe/qe_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c index e18159acfe45..41eff805a904 100644 --- a/drivers/soc/fsl/qe/qe_common.c +++ b/drivers/soc/fsl/qe/qe_common.c @@ -121,7 +121,7 @@ static unsigned long cpm_muram_alloc_common(unsigned long size, goto out2; start = start - GENPOOL_OFFSET; memset_io(cpm_muram_addr(start), 0, size); - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) goto out1; entry->start = start; -- cgit v1.2.3