[英]misaligned address access crash on linux wifi drivers on arc platform
I am getting a crash on insmod of WIFI Marvell pcie drivers. 我在WIFI Marvell pcie驱动程序的insmod上遇到了崩溃。 i am running WIFI drivers on ARCH=arc OS=linux and little endian.
我在ARCH = arc OS = linux和little endian上运行WIFI驱动程序。 crash back-trace says misaligned address access lead to crash.
崩溃后跟踪说未对齐的地址访问导致崩溃。 I have done some investigation and found the place of crash, below is the code snippet.
我做了一些调查,发现崩溃的地方,下面是代码片段。
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;
crash is at line *((t_u32 *)(psnmp_mib->value)) = wlan_cpu_to_le32((t_u32)ul_temp);
崩溃在行
*((t_u32 *)(psnmp_mib->value)) = wlan_cpu_to_le32((t_u32)ul_temp);
because psnmp_mib->value
is unsigned char and typecast'd to unsigned long int
. 因为
psnmp_mib->value
是unsigned char,并且是unsigned long int
类型转换。 But the value we are assigning from pdata_buf
is 1 byte value only ul_temp = *((t_u32 *)pdata_buf);
但我们从
pdata_buf
分配的值仅为1字节值ul_temp = *((t_u32 *)pdata_buf);
. 。
The strange behavior is, if I initialize the ul_temp (unsigned long int variable)
to zero (any value) and if I run, crash is not seen. 奇怪的行为是,如果我将
ul_temp (unsigned long int variable)
初始化为零(任何值),并且如果我运行,则看不到崩溃。 but PCI command timeout happens for getting the get_hardware_spec command and kernel hangs. 但是PCI命令超时是为了获取get_hardware_spec命令和内核挂起而发生的。
I have no clue to fix this issue. 我无法解决这个问题。 Please provide some inputs to move further.
请提供一些进一步的信息。
Blow is my crash logs, 打击是我的崩溃日志,
[ 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:
Please help. 请帮忙。
Simple. 简单。 Just do the right thing .
做正确的事 。 In general case, one would use
memcpy
: 一般情况下,人们会使用
memcpy
:
t_u32 value = wlan_cpu_to_le32((t_u32)ul_temp);
memcpy(psnmp_mib->value, &value, sizeof (t_u32));
As pointed out by 0andriy , the put_unaligned
could be used here: 正如0andriy所指出的,
put_unaligned
可以在这里使用:
put_unaligned(wlan_cpu_to_le32((t_u32)ul_temp), (t_u32*)psnmp_mib->value);
However this is very worrisome because the C standard does state that the behaviour is undefined when : 然而,这非常令人担忧,因为C标准确实声明在以下情况下行为未定义 :
Conversion between two pointer types produces a result that is incorrectly aligned ( 6.3.2.3 ).
两种指针类型之间的转换会产生错误对齐的结果( 6.3.2.3 )。
Thus even the mere presence of the cast (t_u32*)
can lead to the compiler to "realize" that the pointer psnmp_mib->value
is aligned to the alignment requirement of t_u32
anyway. 因此,即使仅仅存在转换
(t_u32*)
也可以导致编译器“实现”指针psnmp_mib->value
无论如何都与t_u32
的对齐要求对齐。
Unaligned access - or even casting pointers to unaligned structures - has undefined behaviour even on platforms that "supposedly" allow unaligned access "everywhere" . 未对齐访问 - 甚至是指向未对齐结构的指针 - 即使在“据称”允许“无处不在”的未对齐访问的平台上也有未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.