2017-10-19 3 views
3

Ich bekomme einen Absturz auf insmod von WIFI Marvell pcie Treiber. Ich betreibe WLAN-Treiber auf ARCH = Arc OS = Linux und Little Endian. Absturz Rückverfolgung bedeutet falscher Adresszugriff führen zu Absturz. Ich habe einige Nachforschungen angestellt und den Ort des Absturzes gefunden, unten ist das Code-Snippet.fehlausgerichtete Adresse Zugang Absturz auf Linux Wifi Treiber auf Bogenplattform

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; 

Absturz ist in Zeile *((t_u32 *)(psnmp_mib->value)) = wlan_cpu_to_le32((t_u32)ul_temp); weil psnmp_mib->value unsigned char ist und typecast'd zu unsigned long int. Aber der Wert, den wir von pdata_buf zuweisen, ist nur 1 Byte Wert ul_temp = *((t_u32 *)pdata_buf);.

Das seltsame Verhalten ist, wenn ich die ul_temp (unsigned long int variable) auf Null (einen beliebigen Wert) initialisiert und wenn ich laufe, Crash nicht gesehen wird. Das Zeitlimit für den PCI-Befehl tritt jedoch auf, wenn der Befehl get_hardware_spec abgerufen wird und der Kernel hängen bleibt.

Ich habe keine Ahnung, um dieses Problem zu beheben. Bitte stellen Sie einige Eingaben zur Verfügung, um weiter zu gehen.

Schlag ist mein Absturzprotokolle,

[ 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: 

Bitte helfen.

+0

* "Ich habe keine Ahnung, um dieses Problem zu beheben ..." * - Wahrscheinlich werden Sie dies in eine Kernel-Mailingliste aufnehmen müssen, um es zu beheben. [Linux Kernel Newbies] (https://kernelnewbies.org/) ist ein großartiger Ort, weil Kernel-Entwickler dort hängen und relativ sanft sind. Die Seite enthält auch einen Abschnitt zu [Fehler gefunden] (https://kernelnewbies.org/FoundBug). Ihr nächster Schritt ist wahrscheinlich, es auf der richtigen Mailingliste zu melden. – jww

Antwort

3

Einfach. Tun Sie einfach die richtige Sache. Im allgemeinen Fall würde man verwenden memcpy:

t_u32 value = wlan_cpu_to_le32((t_u32)ul_temp); 
memcpy(psnmp_mib->value, &value, sizeof (t_u32)); 

Wie 0andriy weist darauf hin, könnte die put_unaligned hier verwendet werden:

put_unaligned(wlan_cpu_to_le32((t_u32)ul_temp), (t_u32*)psnmp_mib->value); 

Dies ist jedoch sehr Besorgnis erregend, weil der C-Standard Zustand tut, dass die behaviour is undefined when :

Konvertierung zwischen zwei Zeigertypen führt zu einem Ergebnis, das falsch ausgerichtet ist (6.3.2.3).

somit auch die bloße Anwesenheit der gegossenen (t_u32*)kann führen zu den Compiler zu „erkennen“, daß der Zeiger psnmp_mib->value ohnehin auf die Ausrichtungsanforderung von t_u32 ausgerichtet ist.


Unaligned Zugang - oder sogar Guss Zeiger auf nicht ausgerichtete Strukturen - hat Verhalten auch auf Plattformen nicht definiert, dass "supposedly" allow unaligned access "everywhere".

+1

Wir haben * get_unicalled() * und * put_unicalled() * Helfer im Kernel. Besser, sie zu verwenden und Patch stromaufwärts zu senden. – 0andriy

+0

Ich lese nochmal den Beitrag und kann jetzt sogar sagen, dass * memcpy() * Ansatz Overhead ist. – 0andriy

+0

@ 0andriy Ich schaute auf die "put_unaligned" API ... was ist * sehr * besorgniserregend ist, dass es * auch * (in https://www.kernel.org/doc/Documentation/unaligned-memory-access.txt) hat undefiniertes Verhalten; 'put_unaligned (value, (u32 *) data);' - Die Umwandlung ist ungültig, wenn 'data' nicht ausgerichtet ist. –

Verwandte Themen