abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
včera 21:33 | Nová verze

Byla vydána nová major verze 1.8.0 open source systému pro filtrování nevyžádané pošty Rspamd (GitHub, ChangeLog). Z novinek lze zmínit nový framework selectors, optimalizaci modulu ClickHouse nebo vylepšení webového rozhraní.

Ladislav Hagara | Komentářů: 0
včera 18:44 | Bezpečnostní upozornění

Sabri Haddouche vytvořil stránku Browser Reaper, na které demonstruje zranitelnosti současných verzí webových prohlížečů Chrome, Safari i Firefox. Zveřejněné skripty dokážou zahltit nejen webové prohlížeče, ale v závislosti na nastavení, také celé operační systémy.

Ladislav Hagara | Komentářů: 8
23.9. 19:22 | Nová verze

Byla vydána verze 11.3 open source alternativy GitHubu, tj. softwarového nástroje s webovým rozhraním umožňujícího spolupráci na zdrojových kódech, GitLab (Wikipedie). Představení nových vlastností i s náhledy v příspěvku na blogu.

Ladislav Hagara | Komentářů: 0
22.9. 13:00 | Komunita

Do 30. října se lze přihlásit do dalšího kola programu Outreachy (Wikipedie), jehož cílem je přitáhnout do světa svobodného a otevřeného softwaru lidi ze skupin, jež jsou ve světě svobodného a otevřeného softwaru málo zastoupeny. Za 3 měsíce práce, od 4. prosince 2018 do 4. března 2019, v participujících organizacích lze vydělat 5 500 USD.

Ladislav Hagara | Komentářů: 97
21.9. 22:22 | Komunita

Společnost Purism představila kryptografický token Librem Key. Koupit jej lze za 59 dolarů. Token byl vyvinut ve spolupráci se společností Nitrokey a poskytuje jak OpenPGP čipovou kartu, tak zabezpečení bootování notebooků Librem a také dalších notebooků s open source firmwarem Heads.

Ladislav Hagara | Komentářů: 9
21.9. 20:33 | Nová verze

Společnost NVIDIA oficiálně vydala verzi 10.0 toolkitu CUDA (Wikipedie) umožňujícího vývoj aplikací běžících na jejich grafických kartách. Přehled novinek v poznámkách k vydání.

Ladislav Hagara | Komentářů: 0
21.9. 20:00 | Upozornění

Příspěvek Jak přežít plánovanou údržbu DNS na blogu zaměstnanců CZ.NIC upozorňuje na historicky poprvé podepsání DNS root zóny novým klíčem dne 11. října 2018 v 18:00. Software, který nebude po tomto okamžiku obsahovat nový DNSSEC root klíč, nebude schopen resolvovat žádná data. Druhým důležitým datem je 1. února 2019, kdy významní výrobci DNS softwaru, také historicky poprvé, přestanou podporovat servery, které porušují DNS standard

… více »
Ladislav Hagara | Komentářů: 11
21.9. 15:55 | Pozvánky

Spolek OpenAlt zve příznivce otevřených řešení a přístupu na 156. brněnský sraz, který proběhne v pátek 21. září od 18:00 v restauraci Na Purkyňce na adrese Purkyňova 80.

Ladislav Hagara | Komentářů: 0
21.9. 13:22 | Nová verze

Alan Griffiths z Canonicalu oznámil vydání verze 1.0.0 display serveru Mir (GitHub, Wikipedie). Mir byl představen v březnu 2013 jako náhrada X serveru a alternativa k Waylandu. Dnes Mir běží nad Waylandem a cílen je na internet věcí (IoT).

Ladislav Hagara | Komentářů: 0
20.9. 22:00 | Nasazení Linuxu
Stabilní aktualizace Chrome OS 69 (resp. Chromium OS), konkrétně 69.0.3497.95, přináší mj. podporu linuxových aplikací. Implementována je pomocí virtualizace, a proto je tato funkce také omezena na zařízení s dostatkem paměti a podporou hardwarové akcelerace, tudíž nejsou podporovány chromebooky s 32bitovými architekturami ARM, či Intel Bay Trail (tzn. bez Intel VT-x).
Fluttershy, yay! | Komentářů: 6
Na optické médium (CD, DVD, BD aj.) jsem naposledy vypaloval(a) data před méně než
 (14%)
 (14%)
 (20%)
 (23%)
 (24%)
 (4%)
 (0%)
Celkem 406 hlasů
 Komentářů: 34, poslední včera 12:54
Rozcestník

Jaderné noviny – 17. 7. 2014: 32bitová systémová volání na x86

5. 8. 2014 | Luboš Doležel | Jaderné noviny | 3003×

Aktuální verze jádra: 3.16-rc5. Citáty týdne: Thomas Gleixner, Ted Ts'o, Grant Likely. Anatomie systémového volání, část druhá: Různé způsoby na x86 - shrnutí; Spuštění systémových volání pro x86_32 na x86_64; Složitější příklad: execve a kompatibilita s 32bitovými aplikacemi; ABI x32; Závěr.

Obsah

Aktuální verze jádra: 3.16-rc5

link

Aktuální vývojová verze jádra je 3.16-rc5 vydaná 13. července. Linus k němu řekl: Věci vypadají normálně a jako obvykle bych byl radši, kdyby tu byl menší šrumec, protože už jde o několikáté rc, ale po pravdě tam není nic, co by člověka zvedlo ze židle.

Stabilní aktualizace: verze 3.15.5, 3.14.12, 3.10.48 a 3.4.98 vyšly 9. července. Aktualizace 3.14.13, 3.10.49 a 3.4.99 se aktuálně revidují; jejich vydání můžeme očekávat 17. července nebo později.

Citáty týdne: Thomas Gleixner, Ted Ts'o, Grant Likely

link

Nejlákavějším nápadem bylo zatím svést se na vlně nejzábavnějšího crowdfundingového nesmyslu:

https://www.kickstarter.com/projects/324283889/potato-salad

Tudíž bychom mohli přetvořit RT na nesmyslný crowdfundovaný projekt, který slouží k účelu řízení stroje na výrobu bramborového salátu, abychom zajistili, že Zack Danger Brown může dodat všechen bramborový salát, na který lidé přispěli.

-- Thomas Gleixner

Člověk musí umět poznat, kdy přišel čas na to říct "Odval se domů checkpatchi, jseš opilej."

-- Ted Ts'o

Mám obavy, že celá tato debata vykazuje pohrdání jakoukoliv stabilitou platformy. Poprvé *v historii* (a možná by se dalo říci, že navzdory našemu úsilí) máme obří ekosystém ISV pro Linux. Ještě úžasnější je to, že je postaven okolo ARM, nikoliv x86! Hurá! Celé roky jsme doufali, že se toto stane. Takže se teď rozhodneme to všechno zahodit tím, že rozhodneme, že na starých binárkách nezáleží? Ostuda.

-- Grant Likely

Anatomie systémového volání, část druhá

link

V minulém článku jsme prozkoumávali jadernou implementaci systémových volání (syscallů) v nejčistší podobě: obyčejné systémové volání na nejběžnější architektuře: x86_64. Završujeme náš pohled na systémová volání variacemi na toto základní téma pohledem na jiné architektury x86 a ostatní mechanismy systémových volání. Začneme průzkumem různých 32bitových variant x86, pro které se může hodit mapa teritoria. Z mapy je možné se prokliknout přes názvy souborů a popisky šipek na zmiňovaný kód:

Systémová volání na x86_32 přes SYSENTER

Běžný způsob provedení systémového volání na 32bitovém systému x86_32 je blízce podobný mechanismu na systémech x86_64, který jsme popisovali minule. Tabulka arch/x86/syscalls/syscall_32.tbl má položku pro sys_read:

    3	i386	read			sys_read

Tato položka značí, že read() pro x86_32 má systémové volání číslo 3 se vstupním bodem sys_read() a konvencí volání i386. Skript zpracovávající tabulky vytvoří makro __SYSCALL_I386(3, sys_read, sys_read), a to do souboru arch/x86/include/generated/asm/syscalls_32.h. Podle tohoto se pak zase sestavuje tabulka volání sys_call_table, stejně jako minule.

Posuneme-li se dále, pak ke sys_call_table je přistupováno ze vstupního bodu ia32_sysenter_targetarch/x86/kernel/entry_32.S. Zde však makro SAVE_ALL vloží na zásobník jinou sadu registrů (EBX/ECX/EDX/ESI/EDI/EBP namísto RDI/RSI/RDX/R10/R8/R9), což odpovídá odlišnosti v ABI systémových volání na této platformě.

Umístění vstupního bodu ia32_sysenter_target se zapisuje do registru specifického pro registr (Model-Specific Register; MSR) při spuštění CPU (v enable_sep_cpu()); v tomto případě se jedná o registr MSR_IA32_SYSENTER_EIP (0x176) používaný pro obsluhu instrukce SYSENTER.

Toto nám ukazuje způsob vyvolání z uživatelského prostoru. Standardní moderní ABI pro vyvolávání systémových volání na x86_32 stanovuje, že číslo volání (3 pro read()) je umístěno do registru EAX, další parametry do konkrétních dalších registrů (EBX, ECX a EDX pro první tři) a pak je vyvolána instrukce SYSENTER.

Tato instrukce způsobí, že se procesor přepne do ring 0 a spustí kód, na který ukazuje registr MSR_IA32_SYSENTER_EIP – konkrétně ia32_sysenter_target. Tento kód vloží registry na (jaderný) zásobník a zavolá ukazatel na funkci v položce dle čísla EAX z tabulky sys_call_table – konkrétně sys_read(), které je tenkým obalením pro skutečnou implementaci SYSC_read().

Systémová volání na x86_32 přes INT 0x80

K tabulce sys_call_table se přistupuje i přes arch/x86/kernel/entry_32.S ze vstupního bodu system_call. I zde se registry vkládají na zásobník, pak se použije EAX pro volbu příslušné položky v sys_call_table a zavolání. V tomto případě se umístění system_call používá v trap_init():

#ifdef CONFIG_X86_32
	set_system_trap_gate(SYSCALL_VECTOR, &system_call);
	set_bit(SYSCALL_VECTOR, used_vectors);
#endif

Toto nastaví obsluhu SYSCALL_VECTOR na system_call; neboli stanoví jej příjemcem softwarového přerušení INT 0x80.

Toto je původní způsob uskutečnění systémových volání, který se už nyní obecně nepoužívá, jelikož je na moderních procesorech pomalejší než instrukce speciálně navržené pro systémová volání (SYSCALL a SYSENTER).

Programy používající toto starší ABI postupují v podstatě stejně jako programy používající SYSENTER. Číslo volání jde opět do EAX, první tři parametry pak do EBX, ECX a EDX.

Různé způsoby na x86 – shrnutí

link

Pro shrnutí jsme doposud viděli tyto mechanismy spouštění systémových volání na x86:

  • 64bitové programy používají instrukci SYSCALL. S touto instrukcí původně přišlo AMD, ale následně byla implementována i na 64bitových procesorech Intel (x86), proto jde o nejlepší volbu pro přenositelnost.
  • Moderní 32bitové programy používají instrukci SYSENTER, která existuje už od uvedení architektury IA-32 (v procesorech Pentium II).
  • Staré 32bitové programy používají instrukci INT 0x80 pro vyvolání obsluhy softwarového přerušení, což je ale na moderních procesorech mnohem pomalejší než SYSENTER.

Spuštění systémových volání pro x86_32 na x86_64

link

Teď tu máme jednu složitější situaci: co se stane spustíme-li 32bitovou binárku na našem x86_64 systému? Z pohledu uživatelského prostoru se nic neliší; po pravdě se ani nic lišit nemůže, protože spouštíme ten samý uživatelský kód.

Pro SYSENTER 64bitové jádro zaregistruje jako obsluhu pro MSR_IA32_SYSENTER_EIP jinou funkci. Tato funkce má stejné jméno (ia32_sysenter_target) jako na x86_32, ale jinou definici (v arch/x86/ia32/ia32entry.S). Sice dává na zásobník ty samé registry, ale používá jinou tabulku ia32_sys_call_table. Tato tabulka je sestavena z 32bitové tabulky položek; například tedy bude mapovat na sys_read() položku 3 (jako je to na 32bitových systémech) namísto 0 (což odpovídá read() na 64bitových systémech).

Pro INT 0x80 kód v trap_init() na x86_64 spouští:

#ifdef CONFIG_IA32_EMULATION
	set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
#endif

Toto mapuje IA32_SYSCALL_VECTOR (které je stále 0x80) na ia32_syscall. Vstupní bod v assembleru (v arch/x86/ia32/ia32entry.S používá místo 64bitové tabulky sys_call_table tabulku ia32_sys_call_table.

Složitější příklad: execve a kompatibilita s 32bitovými aplikacemi

link

Podívejme se na systémové volání, které s sebou nese další komplikace: execve(). Pro přehled oblasti, kterou budeme prozkoumávat, je tu opět klikací mapa:

Definice execve()fs/exec.c se podobá read(), ale hned po ní se v souboru nachází zajímavá dodatečná funkce (alespoň tehdy, když je definováno CONFIG_COMPAT):

SYSCALL_DEFINE3(execve,
		const char __user *, filename,
			const char __user *const __user *, argv,
			const char __user *const __user *, envp)
{
		return do_execve(getname(filename), argv, envp);
}
#ifdef CONFIG_COMPAT
asmlinkage long compat_sys_execve(const char __user * filename,
		const compat_uptr_t __user * argv,
		const compat_uptr_t __user * envp)
{
		return compat_do_execve(getname(filename), argv, envp);
}
#endif

Tyto dvě implementace se nakonec sejdou v do_execve_common(), kde je samotná implementace volání (sys_execve()do_execve()do_execve_common() versus compat_sys_execve()compat_do_execve()do_execve_common()), cestou vytváří struktury user_arg_ptr. Tyto struktury obsahují ty argumenty systémových volání, které jsou ukazatelem na ukazatel spolu s údajem, zda pocházejí z 32bitového ABI; pokud ano, pak je hodnota, na kterou se ukazuje, 32bitovou adresou v uživatelském prostoru, nikoliv 64bitová hodnota, a kód pro kopírování hodnot argumentů musí s tímto počítat.

Na rozdíl od read(), kde implementace nemusela rozlišovat mezi 32bitovým a 64bitovým volajícím, protože argumenty byly ukazatelem na hodnoty, execve() toto rozlišovat musí, neboť má argumenty, které jsou ukazatelem na ukazatel. Toto je vcelku běžné – najdeme i další funkce compat_sys_name, které řeší argumenty s ukazatelem na ukazatel (nebo ukazatelem na strukturu obsahující ukazatel, například struct iovec nebo struct aiocb).

ABI x32

link

Komplikace způsobené dvěma variantami implementace execve() se šíří od kódu až do tabulek volání. Pro x86_64 má 64bitová tabulka pro execve() hned dvě položky:

59	64	execve			stub_execve
...
520	x32	execve			stub_x32_execve

Dodatečná položka s číslem 520 je určena pro programy používající x32 ABI, které běží na procesorech x86_64 v 64bitovém režimu, ale používají 32bitové ukazatele. Kvůli tomu pak máme pro execve() položky dvě.

I když je toto naše první zmínka o x32 ABI, předchozí příklad s read() už kompatibilitu s x32 nenápadně obsahoval. Jelikož nebyl zapotřebí žádný překlad adres ukazatele na ukazatel, cesta spouštění systémového volání (stejně jako číslo volání) může být sdílena se 64bitovou verzí.

stub_execve i stub_x32_execve jsou obě definovány v arch/x86/kernel/entry_64.S. Tyto vstupní body volají sys_execve a compat_sys_execve, ale také na jaderný zásobník ukládají dodatečné registry (R12-R15, RBX a RBP). Podobná obalení stub_* jsou v arch/x86/kernel/entry_64.S i pro ostatní volání (rt_sigreturn(), clone(), fork() a vfork()), kde může být potenciálně nutnost obnovit spouštění kódu v uživatelském prostoru na jiné adrese nebo s jiným zásobníkem než v době spuštění volání.

Pro x86_32 má 32bitová tabulka položku pro execve v trochu jiném formátu než pro read():

11	i386	execve			sys_execve			stub32_execve

Z ní se dozvídáme, že execve() je na 32bitových systémech volání číslo 11, na rozdíl od 59 (nebo 520) na 64bitových systémech. Zajímavější ovšem je to, že se tam nachází dodatečné sloupeček, kde je vstupní bod stub32_execve pro kompatibilitu. Pro nativní 32bitové sestavení jádra je toto dodatečné pole ignorováno a sys_call_tablesys_execve() jako položku 11 – jako obvykle.

Pro 64bitové sestavení jádra ale kód pro kompatibilitu s IA-32 vkládá stub32_execve() jako vstupní bod do tabulky ia32_sys_call_table. Tento bod je definován v arch/x86/ia32/ia32entry.S jako:

PTREGSCALL stub32_execve, compat_sys_execve

Makro PTREGSCALL připraví vstupní bod stub32_execve, který volá compat_sys_execve() a ukládá do jaderného zásobníku dodatečné registry (R12-R15, RBX a RBP), podobně jako stub_execve() výše.

gettimeofday(): vDSO

Některá systémová volání čtou z jádra jen malý objem informací a pro ně představuje plný přechod mezi ringy příliš velkou režii. Mechanismus vDSO (Virtual Dynamically-linked Shared Object; virtuální dynamicky linkovaný objekt) urychluje některá z těchto volání, která nedělají žádné změny, tím, že mapuje stránku se souvisejícími informacemi (spolu s kódem pro jejich čtení) do uživatelského prostoru (jen ke čtení). Stránka má formát sdílené knihovny ELF, tudíž je možné ji přímo linkovat do uživatelských programů.

Pokud spustíme ldd na obyčejné binárce používající glibc, pak uvidíme vDSO jakožto závislost na linux-vdso.so.1 nebo linux-gate.so.1 (ke kterému ldd nedokáže najít příslušný soubor); je vidět i v mapě paměťového prostoru ([vdso]cat /proc/PID/maps).

Dříve se používalo vsyscall, které dělalo cosi podobného, ale nyní je vsyscall zastaralé kvůli bezpečnostním obavám. Tento starší článek od Johana Peterssona podrobně rozebírá, jak se stránka příslušící k vsyscall objeví jako ELF objekt v uživatelském prostoru.

Funkčnost vDSO popisuje tento článek na Linux Journalu (i když už není úplně aktuální), takže si tu popíšeme jen základy na příkladu se systémovým voláním gettimeofday().

gettimeofday() v první řadě potřebuje přistupovat k datům. Aby to bylo možné, tak je příslušná struktura vsyscall_gtod_data exportována do speciální datové sekce .vvar_vsyscall_gtod_data. Povely pro linker se pak postarají o to, aby sekce .vvar_vsyscall_gtod_data byla slinkována do jádra do sekce __vvar_page a při spuštění jádra funkce setup_arch() zavolá map_vsyscall(), aby bylo pro __vvar_page připraveno fixní mapování.

Kód poskytující implementaci gettimeofday() pro vDSO je v __vdso_gettimeofday(). Je označen jako notrace, aby kompilátory nikdy nepřidávaly profilování funkcí, a má také slabý alias na gettimeofday().

Aby byla stránka s vDSO přístupná nově spuštěnému programu, kód v setup_additional_pages() nastaví umístění stránky s vDSO na náhodnou adresu zvolenou v vdso_addr() při spuštění procesu. Používání náhodné adresy potlačuje bezpečnostní problémy dřívější implementace vsyscall, ale znamená také to, že program potřebuje mít jak vDSO najít. Umístění je sděleno pomocí dodatečné hodnoty ELF (auxiliary value). Program pak může najít stránku pomocí funkce getauxval(), i když toto běžně řeší libc.

Doplňme, že mechanismus vDSO je používán i pro jinou důležitou věc související se systémovými voláními ve 32bitových programech. Při bootu jádro zjistí, který z různých způsobů volání jádra je nejlepší a umístí příslušnou obalující funkci (pro SYSENTER, INT 0x80 nebo dokonce SYSCALL na 64bitových CPU AMD) do funkce __kernel_vsyscall. Uživatelské programy pak mohou spustit tuto obalující funkci a mají jistotu, že pro uskutečnění systémových volání používají ten nejrychlejší způsob.

Závěr

link

Systémová volání jsou už desítky let standardním způsobem, jak uživatelské programy komunikují s unixovými jádry. Proto Linux obsahuje sadu nástrojů usnadňujících jejich definici a používání. Navzdory odlišnostem mezi různými architekturami jsou systémová volání stále velmi jednotným mechanismem – tato stabilita umožňuje všemožným nástrojům, od strace až po seccomp-bpf, pracovat obecným způsobem.

       

Hodnocení: 100 %

        špatnédobré        

Nástroje: Tisk bez diskuse

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Vložit další komentář

18.8.2014 22:37 zde
Rozbalit Rozbalit vše Re: Jaderné noviny – 17. 7. 2014: 32bitová systémová volání na x86
: Uživatelské programy pak mohou spustit tuto obalující funkci a mají jistotu, že pro uskutečnění systémových volání používají ten nejrychlejší způsob.

Jo, obalující funkce jsou jako pruhy na adidasu.
ISSN 1214-1267   www.czech-server.cz
© 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.