【问题标题】:misaligned address access crash on linux wifi drivers on arc platformarc 平台上的 linux wifi 驱动程序上未对齐的地址访问崩溃
【发布时间】:2018-03-31 03:27:54
【问题描述】:

我在 WIFI Marvell pcie 驱动程序的 insmod 上遇到崩溃。 我在 ARCH=arc OS=linux 和 little endian 上运行 WIFI 驱动程序。 崩溃回溯说未对齐的地址访问导致崩溃。 我做了一些调查,找到了崩溃的地方,下面是代码sn-p。

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 发生在*((t_u32 *)(psnmp_mib->value)) = wlan_cpu_to_le32((t_u32)ul_temp); 行,因为psnmp_mib->value 是无符号字符并且类型转换为unsigned long int。但是我们从pdata_buf 分配的值只是ul_temp = *((t_u32 *)pdata_buf); 的1 字节值。

奇怪的行为是,如果我将ul_temp (unsigned long int variable) 初始化为零(任何值)并且如果我运行,则不会看到崩溃。但是获取 get_hardware_spec 命令和内核挂起时发生 PCI 命令超时。

我不知道如何解决这个问题。请提供一些输入以进一步推进。

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:

请帮忙。

【问题讨论】:

  • “我不知道如何解决这个问题...” - 你可能不得不把它带到内核邮件列表来修复它。 Linux Kernel Newbies 是个好地方,因为内核开发人员挂在那里并且相对温和。该网站还有一个关于Found a Bug 的部分。您的下一步可能是在适当的邮件列表中报告它。

标签: c linux wifi linux-device-driver


【解决方案1】:

简单。只做正确的事。一般情况下,会使用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:

两种指针类型之间的转换会产生错误对齐的结果 (6.3.2.3)。

因此,即使只是存在演员(t_u32*) 可以导致编译器“意识到”指针psnmp_mib->value与对齐要求对齐t_u32 反正。


未对齐的访问 - 甚至是指向未对齐结构的指针 - 即使在 "supposedly" allow unaligned access "everywhere" 的平台上也具有未定义的行为。

【讨论】:

  • 我们在内核中有 get_unaligned()put_unaligned() 助手。最好使用它们并向上游发送补丁。
  • 我再次阅读了这篇文章,现在甚至可以说 memcpy() 方法是开销。
  • @0andriy 我查看了“put_unaligned”API...非常令人担忧的是它kernel.org/doc/Documentation/unaligned-memory-access.txt)有未定义的行为; put_unaligned(value, (u32 *) data); - 当data 未对齐时,转换无效。
  • @0andriy 还是添加了
猜你喜欢
  • 2010-12-29
  • 1970-01-01
  • 2021-05-15
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多