blokkeszköz emulálása úgy, hogy menjen a HDIO_GET_IDENTITY ioctl

Fórumok

Van egy 32 bites alkalmazás amit szeretnék szóra bírni egy modern rendszeren.

Eredetileg egy VirtualBox image-ben egy yocto alapú disztró amit nem tudok bootolni.

Ezt a rootfst-t lementettem, bechrootoltam rá.

Segmentation faulttal áll meg, de strace barátunk segített:

open("/dev/sda", O_RDONLY|O_NONBLOCK)   = -1 ENOENT (Nincs ilyen fájl vagy könyvtár)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
Szegmentálási hiba (core készült)

Próbáltam alátenni egy USB pendrive-ot de azon nem megy a HDIO_GET_IDENTITY ioctl:

open("/dev/sda", O_RDONLY|O_NONBLOCK)   = 3
ioctl(3, HDIO_GET_IDENTITY, 0x80c4660)  = -1 EINVAL (Érvénytelen argumentum)
close(3)                                = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
Szegmentálási hiba (core készült)

Van esetleg valami módszer arra, hogy specifikus ioctl-eket "eltérítsek", esetlegesen létezik valamilyen blokkeszköz emulátor amivel be tudnám csapni a programot?

Hozzászólások

hat lehet irni egy egyszeru wrappert C-ben es LD_LIBRARY_PRELOAD-al betolteni, igy lehet atverni pl. a vinyo sorozatszamot ellenorzo programokat

vagy futtasd qemu-val az mindent is tud emulalni :)

Mivel volt pár szabad percem, összedobtam neked:

Teszt program erre: https://mcsiv.com/ldpreload_ioctl/test.c
shared object forrás erre: https://mcsiv.com/ldpreload_ioctl/ioctl_override.c

Lefordítani őket a következővel tudod:

$ gcc -Wall test.c -o test
$ gcc -Wall -fPIC -shared -o ioctl_override.so ioctl_override.c -ldl

Részlegesen teszteltem, a HDIO_GET_IDENTITY nem működött sehol, ahol próbálni tudtam volna (most kizárólag virtuális környezetben vannak linuxok körülöttem).
A kód nem szép, nem "multiplatform" és az ABI-t is kőbaltával faragja, a teljes device identity-t sem tölti fel, de minimális célját ellátja és ha szükséges tovább tudod faragni:

# ./test
IOCTL failed (Invalid argument)
# LD_PRELOAD=./ioctl_override.so ./test
Hard Disk Model: FakeModel
Serial Number: 123456789

// Happy debugging, suckers
#define true (rand() > 10)

Igen, lehetne igy is csinalni, de az errno-varázslás miatt mindig van libc wrapper, és az adott függvény nem 1:1-ben egy syscall() alias. Pedig tényleg lehetne az, ha a C/libc standard ne ilyen nyomi lenne, márami az error handlinget érinti... 

a kernel hívás része itt nem probléma, lévén az override továbbpasszolja az eredeti implementáció irányába a hívást, így lényegében a stack emelésen kívűl transzparens. Ha statikusan be van forgatva, az már más, de ott egy disassembler jó szolgálatot tud tenni és viszonylag gyorsan visszakövethető mi történik. Ha pedig megvan, akár jöhet a live patching is: LD_PRELOAD -ban hook-olható a __libc_start_main, így mielőtt a programban lévő main lefutna, szépen el lehet helyezni a statikusan beforgatott fgv-re egy trampoline-t, így közbe tudsz ékelődni pontosan úgy, ahogy a dinamikus esetben is tennéd

// Happy debugging, suckers
#define true (rand() > 10)

Egy socketcan interfészhez hozzá kellene férnie a programnak, nem tudom mennyire egyszerű qemu alól.

Ugy latom hogy a virtio-can egy letezo dolog. Eleg sokmindent hasznaltam mar Linux + CAN temakorben, de ezt meg pont nem. Majd kiprobalom :) 

Szerk: kiprobaltam, mukodik:

qemu    ... \
        -object can-bus,id=canbus0 \
        -device kvaser_pci,canbus=canbus0 \
        -object can-host-socketcan,id=canhost0,if=vcan0,canbus=canbus0 \
        ... 

szepen osszekoti (mint egy bridge) a host es a guest CAN interface-eit.

Pontosan mit is csinálnál? A yocto image-n van egy progi (valamiféle célprogram) amit a host rendszeren futtatnál, és ez a progi akarna megnyitni valami miatt a /dev/sda-t? Ami bele van vasalva ebbe a célprogramba?

Akar meg a loopback-ot is kiprobalhatod, es ha nincs /dev/sda akkor csinalsz egy symlinket ezen a neven ami a /dev/loopx-re mutat. Nem adnek sok eselyt hogy pont tudja ezt az ioctl-t, de hátha. 

Na akkor elmesélem a teljes történetet, mert az említett probléma kb. 15 nyúlüreggel fentebb kezdődött.

Létezik egy ún. IsoBus VT szabvány ami kvázi egy mezőgazdasági Android auto/Carplay megoldás.

A valóságban valahogy úgy néz ki, hogy a gépekben (traktorban/kombányban/akármiben) van egy beépített kijelző, a gép végén egy szabvány csati amire rá lehet dugni a vetőgépet/ekét/bálázót/hígtrágyaszórót/bármit ami CAN-en keresztül feltol egy GUI-t a terminálra és onnantól lehet a vontatványt piszkálni a kabinból.

Van egy open source projekt ami implementált egy ilyen terminált PC-re ami működik mindenféle random CAN eszközökkel:

https://github.com/Open-Agriculture/AgIsoVirtualTerminal

Ezt elkezdtem szögelgetni mert nagyon jól jönne automatizált UI tesztekhez mert a cégnél fejlesztünk túloldali (implement) eszközt.
De ha már patkolom akkor úgy akarom patkolni, hogy fasza legyen, ezért elkezdtem végigdugdosni a nálunk lévő egyéb IsoBusos implementekre.

Az első egy Kverneland-os vetőgép volt aminél azért jöttek elő problémák: gombokról ikon 45 fokban elkezd száguldani a jobb alsó sarokba, stb.
Egyéb okokból  elkezdtem dokumentációt keresni a cucchoz majd szembe jött ez és innen kezdtek a nyúlüregek megnyílni:

https://www.youtube.com/watch?v=sAeUWckWsxs

https://www.kvgportal.com/Api/QUEST/api/Medias/UqQ4e8NJB2NsdZxke4ZE/595…

Ez mint kiderült egy C#-ban írt alkalmazás ami egy VirtualBoxos VM-ben futó linuxxal kommunikál VNC-n meg SOAP-on keresztül. (Véletlenül beleesett az app a dotpeekbe és szétnéztem.)
Lehet vele szimulálni a terminált, illetve hozzá mindenféle Kvernelandos vontatmányt.

Feltelepítettem egy Windowsos VM-be, az app elindul de panaszkodik a Virtualbox hiányára.

A Virtualboxot feltelepítette, de az külön nem indítható el mert a Windows 10 alatt a 5.1.28 virtualbox le van tiltva valami PAC megoldással.

Ezt próbáltam kihekkelni de nem sikerült, a vége az lett, hogy telepítettem egy 5.2.44-et.
Ez már elindul, be is lehet húzni bele a VM-et de a VM bootloásakor a host Virtualbox hanyattesik.

Próbáltam a virtuális gépet áthúzni natív Linux-ra de ennyivel megáll a bootolása:

https://imgur.com/d9Ssxf3

Egy másik kollégámnál Windows hoston ugyanezzel a Virtualbox verzióval a VM elindul de a C#-os app itt sem tud kommunikálni a VM-el.

A rootfs-t már sikerült kihámoznom a virtuális gépből az látszik, hogy vannak felhúzva virtuális CAN interfészek, illetve az opkg csomaglista alapján kb. megvannak milyen appok mennek rajta.
Azt szeretném elérni, hogy az implementeket emuláló appot ki tudjam valahogy drótozni egy fizikai CAN interfészre (igazából egy virtual CAN is jó csak az a natív Linuxomon legyen) és össze tudjam kötni az AgIsoVirtualTerminal-al.

Ha ez menne akkor lehetne bugokat vadászni az AgIsoVirtualTerminal-ban a meleg irodában :D.

A következő lépés valószínűleg az lesz, hogy fogok egy natív W7-es gépet és megnézem, hogy elindulnak-e az emulált eszközök, mert elég abandonware: a frissítéseket biztosító szerver már nem elérhető és van bennem egy kis félsz, hogy lehet, hogy az emulált eszközök nincsenek benne a VM image-ban hanem a netről szedte őket dinamikusan.

Koszi az osszefoglalot, tenyleg szep projekt :) A CAN interfacinggal kapcsolatosan meg lasd fentebb. Jol megy ez fizikai CAN buszok eseten is, nemcsak virtualisokra hasznalhato. Latja a guest a host CAN eszkozeit, azaz a guest-en latom azokat CAN frame-eket amiket egy kulso eszkoz kuld 1Mbit-es drotmadzagon. 

Leértem a nyúlüregek aljára: sikerült megrootolni a VM-et, valóban vcan-en kommunikál a terminál program és az implement szimulátorok. Cannellonival kipipeoltam a forgalmat a VMből, viszont a forgalom nem standard IsoBus formátumú. Mondom nincs az az isten, hogy nagyon feltalálják újra a spanyol viaszt ezért behúztam ghidra-ba, nézegettem egy kicsit, majd kigyaktam a CAN encryption-t (na meg hamár ott jártam akkor a disk id ellenőrzést is)..8

https://imgur.com/a/fSgwTdv

Jó munkát végeztek a Kvernelandos fiúk, mert a fizikai implementtel előjött problémák itt is jelen vannak. Viszont így lehet az irodában debugolni minden fizikai gear nélkül, nem kell a műhelyben szívni.

... és erre gyári támogatásnak kellene lennie.

Az a helyzet, hogy van ilyen, csak ilyen 450 EUR-ba kerül darabja:

https://hu.kvernelandgroup.com/markak-es-termekek/iM-FARMING/IsoMatch/I…

Aztán nem lopom én a pénzt, meg hát csak egy open source projekt ez.