我在 WIFI Marvell pcie 驱动程序的 insmod 上遇到崩溃。 我在 ARCH=arc OS=linux 和 little endian 上运行 WIFI 驱动程序。 崩溃回溯表明未对齐的地址访问导致崩溃。 我做了一些调查,找到了崩溃的地方,下面是代码片段。
case NullPktPeriod_i:
/** keep alive null data pkt interval in full power mode */
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)NullPktPeriod_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u32));
ul_temp = *((t_u32 *)pdata_buf);
*((t_u32 *)(psnmp_mib->value)) =
wlan_cpu_to_le32((t_u32)ul_temp);
cmd->size += sizeof(t_u32);
}
break;
崩溃发生在行 *((t_u32 *)(psnmp_mib->value)) = wlan_cpu_to_le32((t_u32)ul_temp);
因为 psnmp_mib->value
是无符号的char 并类型转换为 unsigned long int
。但是我们从 pdata_buf
分配的值仅为 1 字节值 ul_temp = *((t_u32 *)pdata_buf);
。
奇怪的行为是,如果我将 ul_temp(unsigned long int 变量)
初始化为零(任何值)并且如果我运行,则不会出现崩溃。但是 PCI 命令超时发生在获取 get_hardware_spec 命令和内核挂起。
我不知道如何解决这个问题。请提供一些意见以进一步推进。
Blow 是我的崩溃日志,
[ 29.920000] Path: (null)
[ 29.930000] CPU: 0 PID: 1047 Comm: kworker/u3:1 Tainted: P O 3.12.0 #103
[ 29.930000] Workqueue: MOAL_WORK_QUEUE woal_main_work_queue [pcie8xxx]
[ 29.940000] task: 9f0e02c0 ti: 9d192000 task.ti: 9d192000
[ 29.940000]
[ECR ]: 0x00230400 => Misaligned r/w from 0x9d451072
[ 29.950000] [EFA ]: 0x9d451072
[ 29.950000] [BLINK ]: wlan_prepare_cmd+0x1be/0x478 [mlan]
[ 29.950000] [ERET ]: wlan_ops_sta_prepare_cmd+0x1fe0/0x37dc [mlan]
[ 29.950000] [STAT32]: 0x00000a06 : E2 E1
[ 29.970000] BTA: 0x78571ccc SP: 0x9d193c34 FP: 0x00000000
[ 29.980000] LPS: 0x982de26c LPE: 0x982de270 LPC: 0x00000000
[ 29.980000] r00: 0x00000000 r01: 0x00000016 r02: 0x00000012
r03: 0x0000001e r04: 0x00000000 r05: 0x9d193cb4
r06: 0x9d451064 r07: 0x7857129c r08: 0xfffffffe
r09: 0x00000000 r10: 0x000004cf r11: 0x00000002
r12: 0x00000000
[ 29.990000]
[ 29.990000] Stack Trace:
请帮忙。
最佳答案
简单。只做正确的事。在一般情况下,人们会使用 memcpy
:
t_u32 value = wlan_cpu_to_le32((t_u32)ul_temp);
memcpy(psnmp_mib->value, &value, sizeof (t_u32));
正如 0andriy 指出的那样, put_unaligned
可以在这里使用:
put_unaligned(wlan_cpu_to_le32((t_u32)ul_temp), (t_u32*)psnmp_mib->value);
然而,这非常令人担忧,因为 C 标准确实声明 behaviour is undefined when :
Conversion between two pointer types produces a result that is incorrectly aligned (6.3.2.3).
因此,即使只是 存在 类型转换 (t_u32*)
也可以 导致编译器“意识到”指针 psnmp_mib->value
无论如何都符合 t_u32
的对齐要求。
未对齐访问 - 甚至将指针转换为未对齐结构 - 即使在平台上也有未定义的行为 "supposedly" allow unaligned access "everywhere" .
关于c - arc 平台上的 linux wifi 驱动程序上的未对齐地址访问崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46824013/