LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (https://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   Kernel panic in a module with sprintf in read function (https://www.linuxquestions.org/questions/linux-kernel-70/kernel-panic-in-a-module-with-sprintf-in-read-function-4175679949/)

afronteau 08-05-2020 10:17 AM

Kernel panic in a module with sprintf in read function
 
Hi,
I want to write a driver that simply signal to user when an interrupt occured. It works most of the time but sometimes there is a kernel panic :
Unable to handle kernel paging request at virtual address 6d904ad8
pgd = a9428000
[6d904ad8] *pgd=38e8f831, *pte=10b1075f, *ppte=10b10c7f
Internal error: Oops: 81f [#1] PREEMPT SMP ARM
Modules linked in: mxc_v4l2_capture ipu_bg_overlay_sdc ipu_still 8723bu(O) ipu_prp_enc ipu_csi_enc ipu_fg_overlay_sdc sbs_battery platformw_fpga_module(O) platformw_adis16488_driver(O) platformw_fpga_fw_loader_mo
CPU: 2 PID: 292 Comm: imajboxwd Tainted: G O 3.14.52 #1
task: a8701300 ti: a9756000 task.ti: a9756000
PC is at number.isra.1+0x314/0x458
LR is at 0x2
pc : [<802069cc>] lr : [<00000002>] psr: 300d0013
sp : a9757df8 ip : a9757e2d fp : a9757e9c
r10: ed904ad7 r9 : a9757f1c r8 : 00000000
r7 : 00000002 r6 : 7f026506 r5 : 7f026506 r4 : 6d904ad9
r3 : fffffffc r2 : 00000031 r1 : 00000020 r0 : 6d904ad9
Flags: nzCV IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c5387d Table: 3942804a DAC: 00000015
Process imajboxwd (pid: 292, stack limit = 0xa9756238)
Stack: (0xa9757df8 to 0xa9758000)
7de0: a8008e40 807c003e
7e00: a9757e44 00000000 00000000 00000000 00000001 00000000 ffffffff 0000000a
7e20: 00000001 00000002 f4a00100 00310001 00000002 00000000 a9757e64 a9757e48
7e40: 8006b164 80587b9c a8008e40 a8008e9c a8008e40 a8008e9c a9756000 0000003d
7e60: 00000000 f4a00100 00000001 00000002 a9757e94 6d904ad8 7f026506 7f026506
7e80: 00000002 ed904ad7 a9757f1c 805ac2d8 a9757ef4 a9757ea0 80208ad4 802066c4
7ea0: 00000002 0000000a ffffffff ffffffff 80008520 6d904ad8 807c00fe 7fffffff
7ec0: ff0a0210 ffffffff a9757f44 00000002 a89c0010 6d904ad8 a89c0094 00000001
7ee0: 00000002 00000000 a9757f10 a9757ef8 80208cc0 80208774 00000001 a9757f18
00000000 a9757f44 a9757f20 7f023a5c 80208ca8 7f026504 00000001 00000000
7f20: a893c300 6d904ad8 a9757f78 7f0239f8 6d904ad8 00000002 a9757f74 a9757f48
7f40: 800e1c88 7f023a04 800fc190 800fc088 a893c301 a893c300 00000000 00000000
7f60: 6d904ad8 00000002 a9757fa4 a9757f78 800e233c 800e1bfc 00000000 00000000
7f80: 00000002 6d904ad8 00000012 00000003 8000e8c4 a9756000 00000000 a9757fa8
7fa0: 8000e740 800e2304 00000002 6d904ad8 00000012 6d904ad8 00000002 00000000
Aug 4 15:44:51 imajboxw user.emerg kernel: [ 252.999664] 7fc0: 00000002 6d904ad8 00000012 00000003 712feb5a 00000000 712feb60 6bcfdf4c
7fe0: 6bcfdbb4 6bcfdbc8 6bcfe8d0 76e65858 800d0010 00000012 f1f79ebf d6dfc8b7
Backtrace:
[<802066b8>] (number.isra.1) from [<80208ad4>] (vsnprintf+0x36c/0x46c)
r10:805ac2d8 r9:a9757f1c r8:ed904ad7 r7:00000002 r6:7f026506 r5:7f026506
r4:6d904ad8
[<80208768>] (vsnprintf) from [<80208cc0>] (sprintf+0x28/0x30)
r10:00000000 r9:00000002 r8:00000001 r7:a89c0094 r6:6d904ad8 r5:a89c0010
r4:00000002
[<80208c9c>] (sprintf) from [<7f023a5c>] (platformw_fpga_stat_read+0x64/0x68 [platformw_fpga_module])
r3:00000000 r2:00000001 r1:7f026504
[<7f0239f8>] (platformw_fpga_stat_read [platformw_fpga_module]) from [<800e1c88>] (vfs_read+0x98/0x140)
r9:00000002 r8:6d904ad8 r7:7f0239f8 r6:a9757f78 r5:6d904ad8 r4:a893c300
[<800e1bf0>] (vfs_read) from [<800e233c>] (SyS_read+0x44/0x98)
r9:00000002 r8:6d904ad8 r7:00000000 r6:00000000 r5:a893c300 r4:a893c301
[<800e22f8>] (SyS_read) from [<8000e740>] (ret_fast_syscall+0x0/0x38)
r9:a9756000 r8:8000e8c4 r7:00000003 r6:00000012 r5:6d904ad8 r4:00000002
Code: e15a0004 e2844001 e24cc001 85dc2001 (85442001)
---[ end trace 6f394a5be0d7261c ]---


The three functions involved are the irq handler, the read function, and the poll one :

unsigned int platformw_fpga_stat_poll(struct file *file, poll_table *wait)
{
struct module_data * pdata = (struct module_data *) file->private_data;

if (pdata->dev_data.new_stats_available == 1)
{
return POLLIN | POLLRDNORM;
}

poll_wait(file, &pdata->dev_data.event_statCollected, wait);
if (pdata->dev_data.new_stats_available == 1)
{
return POLLIN | POLLRDNORM;
}

return 0;
}

ssize_t platformw_fpga_stat_read (struct file * file ,
char __user * buffer, size_t len, loff_t * offset)
{
struct module_data * pdata = (struct module_data *) file->private_data;
unsigned long flags;
uint8_t available = 0;
int ret = 0;

spin_lock_irqsave(&pdata->dev_data.read_stat_lock, flags);
available = pdata->dev_data.new_stats_available;
pdata->dev_data.new_stats_available = 0;
spin_unlock_irqrestore(&pdata->dev_data.read_stat_lock, flags);

if ((len >= 2) && (buffer))
{
ret = sprintf(buffer, "%d\n", available);
}
return ret;
}

static irqreturn_t platformw_fpga_stat_collected_irq(int irq, void * data)
{
struct module_data * pdata = (struct module_data *) data;

spin_lock(&pdata->dev_data.read_stat_lock);
pdata->dev_data.new_stats_available = 1;
spin_unlock(&pdata->dev_data.read_stat_lock);

wake_up_interruptible(&pdata->dev_data.event_statCollected);
return IRQ_HANDLED;
}


The trace indicates the "sprintf" in the read function but I don't see what is wrong, so I would like to know what can cause this kind of issues ?

dracayr 01-18-2021 04:28 AM

You're writing directly from kernel space to user space memory, which is a bad idea for a few reasons such as swapping (which only exists in user space) and potential unhandled kernel mode page faults (as you can see). The kernel provides the function copy_to_user in asm/uaccess.h to do this safely. So, first allocate a buffer from within the module, do sprintf into that buffer, then call copy_to_user to copy the buffer over to the user space address.


All times are GMT -5. The time now is 02:56 PM.