[ QEMU / chroot : Illegal instruction ]

Pagina: 1
Acties:

Vraag


Acties:
  • +1 Henk 'm!

  • Richum
  • Registratie: Maart 2010
  • Laatst online: 28-03 11:50
Beste mede-tweakers,

Ik probeer de firmware van een D-LINK DCS-1130 camera te emuleren d.m.v QEMU onder Ubuntu 18.0.4 maar ik loop helaas tegen een probleem aan waar ik niet mee verder kom :X ... Hopelijk heeft iemand van jullie de gouden tip .... :*)

(In ieder geval bedankt voor de moeite voor het lezen van dit topic O+ )

Setup


Host
Distributie:Ubuntu 18.0.4 LTS
Kernel:Linux ubuntu 5.0.0-27-generic #28~18.04.1-Ubuntu SMP Thu Aug 22 03:00:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux


Guest (QEMU)
Distributie:Debian SID
Kernel:Linux debian-arm 5.2.0-2-armmp-lpae #1 SMP Debian 5.2.9-2 (2019-08-21) armv7l GNU/Linux
Startup parameters
sudo qemu-system-arm -M virt -m 512 \
-bios bios/QEMU_EFI.fd \
-kernel kernel/vmlinuz-5.2.0-2-armmp-lpae \
-initrd kernel/initrd.img-5.2.0-2-armmp-lpae \
-hda hdd/hda.qcow2 -append "root=/dev/debian-arm-vg/root" \
-netdev tap,id=mynet \
-device virtio-net-device,netdev=mynet \
-nographic


Guest (Docker)Note: Test image
Distributie:Ubuntu 18.0.4
Image:https://hub.docker.com/r/arm32v7/ubuntu/
Kernel:Linux b6364eb9fa9d 4.14.131-linuxkit #1 SMP Fri Jul 19 12:31:17 UTC 2019 armv7l armv7l armv7l GNU/Linux


Firmware


ftp://ftp.dlink.ca/PRODUC...CS-1130_FIRMWARE_1.04.ZIP

Het probleem


Het volgende gebeurd wanneer ik busybox probeer uit te voeren met chroot op mijn Debian/SID image onder QEMU:
code:
1
2
3
user@debian-arm:~/Firmware/DCS-1130$ sudo chroot cramfs-root /bin/busybox
Illegal instruction
user@debian-arm:~/Firmware/DCS-1130$


Nu is het natuurlijk voor de hand liggend dat de executable is gecompileerd voor een andere architectuur dan mijn guest OS (ARMV7). Echter gebeurd het volgende wanneer ik hetzelfde commando uitvoer op mijn Docker image (tevens ARMV7):

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@b6364eb9fa9d:/firmware/_DCS-1130_FIRMWARE_1.04.BIN-1.extracted# chroot cramfs-root /bin/busybox
BusyBox v1.01 (2013.04.12-11:24+0000) multi-call binary

Usage: busybox [function] [arguments]...
   or: [function] [arguments]...

    BusyBox is a multi-call binary that combines many common Unix
    utilities into a single executable.  Most people will create a
    link to busybox for each function they wish to use and BusyBox
    will act like whatever it was invoked as!

Currently defined functions:
    [, addr, arping, ash, awk, basename, busybox, cat, chgrp, chmod, chown, chroot, clear, cp, cpuload, cut, date, dd, df, dirname, dmesg, du, echo, egrep, env, expr, false, find, free, getopt,
    getty, grep, halt, head, hexdump, hostname, hwclock, id, ifconfig, ifdown, ifup, init, insmod, install, kill, killall, klogd, linuxrc, ln, login, logread, ls, lsmod, md5sum, mesg, mkdir,
    mkfifo, mknod, mktemp, modprobe, more, mount, mv, netstat, nslookup, pidof, ping, pivot_root, poweroff, ps, pwd, read1, read2, read4, reboot, reset, rm, rmdir, rmmod, route, run-parts, sed,
    sh, sleep, start-stop-daemon, stty, sync, syslogd, tail, tar, telnetd, test, tftp, time, top, touch, true, tty, udhcpc, umount, uname, uniq, uptime, usleep, vi, wc, which, whoami, write1,
    write2, write4, yes, zcip


Volgens file en readelf betreft het hier een 32-bit ARM executable in little endian byte order. De binary is gestript dus het is niet mogelijk om architecture specifieke kenmerken vast te stellen met readelf.

code:
1
busybox: ELF 32-bit LSB executable, ARM, version 1 (ARM), dynamically linked, interpreter /lib/ld-, stripped

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            ARM
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0xc9d4
  Start of program headers:          52 (bytes into file)
  Start of section headers:          397416 (bytes into file)
  Flags:                             0x202, GNU EABI, software FP, <unknown>
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         5
  Size of section headers:           40 (bytes)
  Number of section headers:         21
  Section header string table index: 20


Als ik de output van lscpu vergelijk van mijn Debian guest met mijn Docker image dan hebben we beide een armv7l 32 bit little endian kernel:

lscpu (QEMU/Debian)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Architecture:        armv7l
Byte Order:          Little Endian
CPU(s):              1
On-line CPU(s) list: 0
Thread(s) per core:  1
Core(s) per socket:  1
Socket(s):           1
Vendor ID:           ARM
Model:               1
Model name:          Cortex-A15
Stepping:            r2p1
BogoMIPS:            125.00
Flags:               half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae e
                     vtstrm


lscpu (Docker/Ubuntu)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Architecture:        armv7l
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  1
Core(s) per socket:  1
Socket(s):           4
Vendor ID:           GenuineIntel
CPU family:          6
Model:               70
Model name:          Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz
Stepping:            1
CPU MHz:             2791.459
BogoMIPS:            5582.91
L1d cache:           32K
L1i cache:           32K
L2 cache:            256K
L3 cache:            6144K
L4 cache:            131072K
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht pbe syscall nx pdpe1gb lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid pni pclmulqdq dtes64 ds_cpl ssse3 sdbg fma cx16 xtpr pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm pti fsgsbase bmi1 avx2 bmi2 erms xsaveopt arat


Dus mijn vraag is eigenlijk ... waarom wordt de executable wel uitgevoerd onder de Docker/Ubuntu image en niet onder QEMU/Debian? De reden dat ik niet gewoon gebruik maak van de Docker image is omdat in de versie van QEMU, waarvan Docker onderliggend gebruik maakt, geen ptrace functionaliteit is geïmplementeerd waardoor het gebruik van GDB niet triviaal is.

Ik heb natuurlijk geprobeerd de instructie op te sporen die de fout geeft maar helaas wil dat niet lukken met GDB. Ook niet na het kopiëren van de libraries naar /lib en /usr/lib waarna in de executable naar verwezen wordt:

code:
1
2
3
Starting program: /home/user/Firmware/DCS-1130/cramfs-root/bin/busybox 
/bin/bash: /home/user/Firmware/DCS-1130/cramfs-root/bin/busybox: No such file or directory
During startup program exited with code 127.


Iemand een idee ... :F ? Ik vermoed dat mijn Debian image een instructieset mist die wel aanwezig is op mijn Docker image ... maar hoe kom ik er achter welke dat is ?

Beste antwoord (via Richum op 18-10-2019 09:31)


  • Thralas
  • Registratie: December 2002
  • Laatst online: 08:07
Richum schreef op donderdag 5 september 2019 @ 23:14:
Als ik de output van lscpu vergelijk van mijn Debian guest met mijn Docker image dan hebben we beide een armv7l 32 bit little endian kernel:
Dat is niet zo. In het tweede geval ('docker') is de output opmerkelijk: alle details zijn van een reguliere x86 CPU, enkel de architecture claimt armv7. Hoewel ik niet bekend ben met exacte manier waarop je qemu/docker hier gebruikt kan dat maar op één manier werken: qemu's user mode emulation.

Dat werkt héél anders dan de eerste variant: het vertaalt simpelweg alle syscalls naar hun equivalent in de x86 kernel. Appels en peren dus. In het ene geval emuleer je een hele arm kernel, in het andere geval neem je een shortcut.
De reden dat ik niet gewoon gebruik maak van de Docker image is omdat in de versie van QEMU, waarvan Docker onderliggend gebruik maakt, geen ptrace functionaliteit is geïmplementeerd waardoor het gebruik van GDB niet triviaal is.
Het is sowieso raadzaam om docker aan de kant te leggen en direct qemu (user) te gebruiken. Daar zou gewoon een variant van strace (zie de -strace-optie) en een gdbserver (-g) in moeten zitten.

Als je een gdb uit een arm toolchain gebruikt kun je die aan laatstgenoemde attachen en debuggen alsof het geheel op arm draaide. Veel handiger dan een volledig systeem emuleren, dan zou ik enkel doen als je een hele goede reden hebt.
code:
1
2
3
Starting program: /home/user/Firmware/DCS-1130/cramfs-root/bin/busybox 
/bin/bash: /home/user/Firmware/DCS-1130/cramfs-root/bin/busybox: No such file or directory
During startup program exited with code 127.
Dat gaat zo inderdaad niet. Die busybox heeft dependencies op libraries binnen de cramfs-root, maar hij zoekt ze nu op het host filesystem. Echter kun je library search paths niet zomaar aanpassen want gdb zelf heeft die wel nodig.

Oplossing: een gdb gebruiken die in de chroot werkt, maar die krijg je meestal niet cadeau. Het handigste alternatief is een statisch gecompileerde versie van gdb: die werkt ook binnen de chroot.

Had ik al gezegd dat je eigenlijk beter qemu-user kunt gebruiken? Doe dat.

Alle reacties


Acties:
  • +1 Henk 'm!

  • vanaalten
  • Registratie: September 2002
  • Laatst online: 12:38
Even disclaimers eerst: ik heb er weinig verstand van en, als ik je TS zo lees, ben jij met dit soort dingen een stuk behendiger dan ik. Desondanks een idee:
code:
1
2
3
user@debian-arm:~/Firmware/DCS-1130$ sudo chroot cramfs-root /bin/busybox
Illegal instruction
user@debian-arm:~/Firmware/DCS-1130$

Wat nou als die 'illegal instruction' niet slaat op de CPU instructieset, maar gewoon output is van busybox zelf? Immers:
BusyBox is a multi-call binary that combines many common Unix
utilities into a single executable. Most people will create a
link to busybox for each function they wish to use and BusyBox
will act like whatever it was invoked as!
...wat nou als busybox start en terugtraceert en het commando 'sudo' ziet - en concludeert dat dat geen geldige instructie is?

Dat is ook het verschil in hoe je de QEMU en Docker versie aanroept: eentje met sudo, eentje zonder sudo.

Dus, als je nou op QEMU eerst 'sudo su' doet en dan 'chroot cramfs-root /bin/busybox'?

En ter controle, op Docker versie 'sudo chroot cramfs-root /bin/busybox'?

(en hierna haak ik hoogstwaarschijnlijk af door een gebrek aan ideeën, maar wens ik je wel vast veel succes toe.)

(oh, erg goede, gedetailleerde en helder TS trouwens - complimenten daarvoor!)

Acties:
  • 0 Henk 'm!

  • Richum
  • Registratie: Maart 2010
  • Laatst online: 28-03 11:50
Bedankt voor de snelle reactie! Dat had ik inderdaad nog niet uitgesloten, helaas geeft busybox een andere foutmelding bij een niet bestaand commando :'( :

code:
1
2
root@b6364eb9fa9d:/firmware/_DCS-1130_FIRMWARE_1.04.BIN-1.extracted# chroot cramfs-root /bin/busybox ditcommandobestaatniet
ditcommandobestaatniet: applet not found


Ik heb het gebruik van sudo ook getest maar dit maakte geen verschil.

Het volgende topic op stackoverflow heeft exact hetzelfde probleem:

https://stackoverflow.com...hroot-illegal-instruction

Hier emuleert iemand een "versatilepb" bord wat volgens de documentatie van QEMU een ARM926EJ-S is:

https://wiki.qemu.org/Documentation/Platforms/ARM

En die draait dus op ARMv9 ipv ARMv7:

https://en.wikipedia.org/...fferences_from_ARM7_cores

Ik gebruik zelf het profiel "virt" (dat wordt aangeraden door QEMU zelf) en die emuleert volgens lscpu een Cortex-A15 met als instructieset ARMv7-A:

Wikipedia: ARM Cortex-A15

Ik zal eens proberen uit te zoeken op welke hardware de DCS-1130 normaliter draait en welk profiel van QEMU daar het meeste bij in de buurt zit 8)7

* Ik had het topic op stack overflow al wel eerder gezien maar het leek mij niet relevant omdat mijn instructieset van de kernel overeenkwam, maar ik heb (nog) niet gekeken naar de "hardware" :+

Acties:
  • +1 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 28-09 21:59

Hero of Time

Moderator LNX

There is only one Legend

Is er een reden om Debian Sid te nemen ipv Stable? Ik zou anders denken aan een nieuwere libc waar het niet lekker mee wil werken. De firmware is natuurlijk voor/met een veel oudere versie gecompileerd en het zou zomaar kunnen dat in de versie van Sid dat wat het wil gebruiken niet meer bestaat.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Richum
  • Registratie: Maart 2010
  • Laatst online: 28-03 11:50
Ik heb voor SID gekozen omdat het een rolling release is, dus gemak :9
De executable is gelinked met de volgende libraries:
code:
1
2
3
4
5
6
7
8
root@b6364eb9fa9d:/firmware/_DCS-1130_FIRMWARE_1.04.BIN-1.extracted# rabin2 -l cramfs-root/bin/busybox 
[Linked libraries]
libm.so.0
libcrypt.so.0
libfloat.so.1
libc.so.0

4 libraries

Deze leven in /lib van de firmware:
code:
1
2
3
4
5
root@b6364eb9fa9d:/firmware/_DCS-1130_FIRMWARE_1.04.BIN-1.extracted/cramfs-root/lib# ls -alh libm.so.0 libcrypt.so.0 libfloat.so.1 libc.so.0
lrwxr-xr-x 1 root root   19 Aug 31 16:12 libc.so.0 -> libuClibc-0.9.28.so
lrwxr-xr-x 1 root root   18 Aug 31 16:12 libcrypt.so.0 -> libcrypt-0.9.28.so
-rwxr-xr-x 1 root root 101K Jan  1  1970 libfloat.so.1
lrwxr-xr-x 1 root root   14 Aug 31 16:12 libm.so.0 -> libm-0.9.28.so


Door chroot te gebruiken pakt hij zijn eigen libraries in plaats van de system libraries. Zonder chroot krijg je namelijk de volgende melding:

Docker/Ubuntu
code:
1
2
root@b6364eb9fa9d:/firmware/_DCS-1130_FIRMWARE_1.04.BIN-1.extracted# ./cramfs-root/bin/busybox 
/lib/ld-uClibc.so.0: No such file or directory

Dezelfde fout doet dit zich voor onder QEMU/Debian maar dan zonder de naam van de library (alleen "No such file or directory"). Ik kan momenteel even niet bij mijn VM om dit netjes te copy/pasten O-)

Bedankt voor het meedenken!

Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • Thralas
  • Registratie: December 2002
  • Laatst online: 08:07
Richum schreef op donderdag 5 september 2019 @ 23:14:
Als ik de output van lscpu vergelijk van mijn Debian guest met mijn Docker image dan hebben we beide een armv7l 32 bit little endian kernel:
Dat is niet zo. In het tweede geval ('docker') is de output opmerkelijk: alle details zijn van een reguliere x86 CPU, enkel de architecture claimt armv7. Hoewel ik niet bekend ben met exacte manier waarop je qemu/docker hier gebruikt kan dat maar op één manier werken: qemu's user mode emulation.

Dat werkt héél anders dan de eerste variant: het vertaalt simpelweg alle syscalls naar hun equivalent in de x86 kernel. Appels en peren dus. In het ene geval emuleer je een hele arm kernel, in het andere geval neem je een shortcut.
De reden dat ik niet gewoon gebruik maak van de Docker image is omdat in de versie van QEMU, waarvan Docker onderliggend gebruik maakt, geen ptrace functionaliteit is geïmplementeerd waardoor het gebruik van GDB niet triviaal is.
Het is sowieso raadzaam om docker aan de kant te leggen en direct qemu (user) te gebruiken. Daar zou gewoon een variant van strace (zie de -strace-optie) en een gdbserver (-g) in moeten zitten.

Als je een gdb uit een arm toolchain gebruikt kun je die aan laatstgenoemde attachen en debuggen alsof het geheel op arm draaide. Veel handiger dan een volledig systeem emuleren, dan zou ik enkel doen als je een hele goede reden hebt.
code:
1
2
3
Starting program: /home/user/Firmware/DCS-1130/cramfs-root/bin/busybox 
/bin/bash: /home/user/Firmware/DCS-1130/cramfs-root/bin/busybox: No such file or directory
During startup program exited with code 127.
Dat gaat zo inderdaad niet. Die busybox heeft dependencies op libraries binnen de cramfs-root, maar hij zoekt ze nu op het host filesystem. Echter kun je library search paths niet zomaar aanpassen want gdb zelf heeft die wel nodig.

Oplossing: een gdb gebruiken die in de chroot werkt, maar die krijg je meestal niet cadeau. Het handigste alternatief is een statisch gecompileerde versie van gdb: die werkt ook binnen de chroot.

Had ik al gezegd dat je eigenlijk beter qemu-user kunt gebruiken? Doe dat.

  • Thralas
  • Registratie: December 2002
  • Laatst online: 08:07
Hoe is dit geëeindigd? Duidelijkheid kunnen krijgen over de illegal instruction?

Acties:
  • +1 Henk 'm!

  • Richum
  • Registratie: Maart 2010
  • Laatst online: 28-03 11:50
Ik ben momenteel niet in NL dus kan niet helemaal inhoudelijk reageren. Gedeeltelijk duidelijkheid, het is een illegal instruction en ik kan niet vinden in welke ARM instructieset hij thuis hoort. In user mode emuleren werkt maar brengt nieuwe uitdagingen met zich mee. Ik vul dit topic volgende week aan!

Acties:
  • 0 Henk 'm!

  • Richum
  • Registratie: Maart 2010
  • Laatst online: 28-03 11:50
Helaas is het mij niet gelukt om de laatste twee weken tijd vrij te maken om de casus goed te debuggen en hier te posten.

De binary gebruikt in ieder geval een ARM-instructieset die niet volledig wordt ondersteund door mijn QEMU host. User mode emulatie zorgt ervoor dat ik de binary kan draaien, dus in dat opzicht is het probleem opgelost.

Bedankt iedereen voor het meedenken, @Thralas ik heb jouw antwoord gemarkeerd als beste antwoord. ;)
Pagina: 1