Hello,
In omap_crypto_cleanup(),:
if (orig && (flags & OMAP_CRYPTO_COPY_MASK))
scatterwalk_map_and_copy(buf, orig, offset, len, 1);
implies that scatterwalk_map_and_copy() is called if flag is set to
OMAP_CRYPTO_SG_COPIED.
If the output buffer crosses a page boundary, the second and subsequent
pages are overwritten.
The test should be : if(orig && (flags & OMAP_CRYPTO_DATA_COPIED))
The variable buf is always assigned but not used if flags ==
OMAP_CRYPTO_SG_COPIED.
In:
buf = sg_virt(sg);
sg_page(sg) can be NULL, leading to a kernel crash:
[ 37.624352] Unable to handle kernel NULL pointer dereference at
virtual address 00000000
[ 37.632502] pgd = ec150000
[ 37.635238] [00000000] *pgd=00000000
[ 37.638842] Internal error: Oops: 5 [#1] SMP ARM
Entering kdb (current=0xec173080, pid 1125) on processor 0 Oops: (null)
due to oops @ 0xc02c04f4
CPU: 0 PID: 1125 Comm: ping Tainted: G C 4.14.13-ti-r25 #62
Hardware name: Generic DRA74X (Flattened Device Tree)
task: ec173080 task.stack: ec0a8000
PC is at pa> <ge_address+0x18/0xf4
LR is at omap_crypto_cleanup+0x44/0x110
pc : [<c02c04f4>] lr : [<c0b33b78>] psr: 40080113
sp : ec0a9cf8 ip : ec0a9d20 fp : ec0a9d1c
r10: 00000000 r9 : ec1918c0 r8 : 00000100
r7 : 0000000a r6 : ec0c6780 r5 : 00000000 r4 : 00000002
r3 : 00000100 r2 : 00000000 r1 : ec1918c0 r0 : 00000000
Flags: nZcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
Control: 10c5387d Table: ac15006a DAC: 00000051
CPU: 0 PID: 1125 Comm: ping Tainted: G C 4.14.13-ti-r25 #62
Hardware name: Generic DRA74X (Flattened Device Tree)
[<c0d87df8>] (__dabt_svc) from [<c02c04f4>] (page_address+0x18/0xf4)
[<c02c04f4>] (page_address) from [<c0b33b78>]
(omap_crypto_cleanup+0x44/0x110)
[<c0b33b78>] (omap_crypto_cleanup) from [<c0b371f4>]
(omap_aes_done_task+0x1a0/0x440)
[<c0b371f4>] (omap_aes_done_task) from [<c0149388>]
(tasklet_action+0x70/0x104)
[<c0149388>] (tasklet_action) from [<c0101704>]
(__do_softirq+0x124/0x378)
[<c0101704>] (__do_softirq) from [<c0148d68>] (irq_exit+0xe8/0x150)
[<c0148d68>] (irq_exit) from [<c01acd5c>]
(__handle_domain_irq+0x70/0xc4)
[<c01acd5c>] (__handle_domain_irq) from [<c01015a0>]
(gic_handle_irq+0x4c/0x88)
[<c01015a0>] (gic_handle_irq) from [<c0d87e8c>] (__irq_svc+0x6c/0x90)
Here it is simpler to reorder the code to fix the issues.
Signed-off-by: Francis Le Bourse<francis.lebourse@xxxxxx>
---
drivers/crypto/omap-crypto.c | 24 +++++++++++-----------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c
index 2c42e4b..5056c4b 100644
--- a/drivers/crypto/omap-crypto.c
+++ b/drivers/crypto/omap-crypto.c
@@ -161,24 +161,24 @@ void omap_crypto_cleanup(struct scatterlist *sg, struct scatterlist *orig,
int offset, int len, u8 flags_shift,
unsigned long flags)
{
- void *buf;
- int pages;
-
flags >>= flags_shift;
- flags &= OMAP_CRYPTO_COPY_MASK;
- if (!flags)
- return;
+ if (flags & OMAP_CRYPTO_DATA_COPIED) {
+ void *buf;
+ int pages;
- buf = sg_virt(sg);
- pages = get_order(len);
+ if (WARN_ON(sg_page(sg) == NULL))
+ return;
- if (orig && (flags & OMAP_CRYPTO_COPY_MASK))
- scatterwalk_map_and_copy(buf, orig, offset, len, 1);
+ buf = sg_virt(sg);
+ pages = get_order(len);
- if (flags & OMAP_CRYPTO_DATA_COPIED)
+ if (orig)
+ scatterwalk_map_and_copy(buf, orig, offset, len, 1);
free_pages((unsigned long)buf, pages);
- else if (flags & OMAP_CRYPTO_SG_COPIED)
+ }
+
+ if (flags & OMAP_CRYPTO_SG_COPIED)
kfree(sg);
}
EXPORT_SYMBOL_GPL(omap_crypto_cleanup);