Na čem pracují vývojáři webového prohlížeče Ladybird (GitHub)? Byl publikován přehled vývoje za duben (YouTube).
Provozovatel čínské sociální sítě TikTok dostal v Evropské unii pokutu 530 milionů eur (13,2 miliardy Kč) za nedostatky při ochraně osobních údajů. Ve svém oznámení to dnes uvedla irská Komise pro ochranu údajů (DPC), která jedná jménem EU. Zároveň TikToku nařídila, že pokud správu dat neuvede do šesti měsíců do souladu s požadavky, musí přestat posílat data o unijních uživatelích do Číny. TikTok uvedl, že se proti rozhodnutí odvolá.
Společnost JetBrains uvolnila Mellum, tj. svůj velký jazykový model (LLM) pro vývojáře, jako open source. Mellum podporuje programovací jazyky Java, Kotlin, Python, Go, PHP, C, C++, C#, JavaScript, TypeScript, CSS, HTML, Rust a Ruby.
Vývojáři Kali Linuxu upozorňují na nový klíč pro podepisování balíčků. K původnímu klíči ztratili přístup.
V březnu loňského roku přestal být Redis svobodný. Společnost Redis Labs jej přelicencovala z licence BSD na nesvobodné licence Redis Source Available License (RSALv2) a Server Side Public License (SSPLv1). Hned o pár dní později vznikly svobodné forky Redisu s názvy Valkey a Redict. Dnes bylo oznámeno, že Redis je opět svobodný. S nejnovější verzí 8 je k dispozici také pod licencí AGPLv3.
Oficiální ceny Raspberry Pi Compute Modulů 4 klesly o 5 dolarů (4 GB varianty), respektive o 10 dolarů (8 GB varianty).
Byla vydána beta verze openSUSE Leap 16. Ve výchozím nastavení s novým instalátorem Agama.
Devadesátková hra Brány Skeldalu prošla portací a je dostupná na platformě Steam. Vyšel i parádní blog autora o portaci na moderní systémy a platformy včetně Linuxu.
Lidi dělají divné věci. Například spouští Linux v Excelu. Využít je emulátor RISC-V mini-rv32ima sestavený jako knihovna DLL, která je volaná z makra VBA (Visual Basic for Applications).
Revolut nabídne neomezený mobilní tarif za 12,50 eur (312 Kč). Aktuálně startuje ve Velké Británii a Německu.
Jádro 2.6.39 je venku; přesně podle předpovědi bylo vydáno okamžitě po vydání Jaderných novin z minulého týdne (originálu, pozn. překl.) Linus naznačil trochu nejistoty ohledně toho, jestli by bylo vhodné ještě jedno -rc:
Mezi význačné vlastnosti této verze patří IPset, subsystém pro řízení multimédií, pár nových plánovačů síťového toku, přepracování zátkování blokových zařízení, dlouho očekávané odstranění velkého jaderného zámku [Big Kernel Lock] a další. Více informací o této verzi vizte na stránce o 2.6.39 na KernelNewbies, ve shrnutí na LWN (1. část, 2. část a 3. část) a ve shrnutí od Thorstena Leemhuise na The H.
Stabilní aktualizace: 21. května vyšlo 2.6.38.7, následováno jádry 2.6.32.41 a 2.6.33.14 23. května. Každé obsahuje obvyklou řádku důležitých oprav.
-- Rusty Russel
-- Alan Cox
napsal Jonathan Corbet, 25. května 2011
Článek z minulého týdne týkající se nápadu rozšířit „bezpečné zpracování“ jeho integrací s mechanismem perf/ftrace zmínil nepřekvapující fakt, že vývojáři existujícího mechanismu bezpečnostních modulů nebyli zcela nadšeni z toho, že by se měl objevit nový a zcela odlišný bezpečnostní framework. Od té doby diskuze o patchi pokračovala a opozice se objevila z úplně jiné strany: od vývojářů sledování a osazení sledovacími nástroji.
Peter Zijlstra začal novou diskuzi krátkou poznámkou: Silně oponuji tomu, aby se jádro perfu mixovalo s nějakým bezpečnostním voodoo (nebo mělo jinou aktivní roli, když jsme u toho.) Thomas Gleixner skočil do diskuze s detailnějším popisem námitek – podle jeho pohledu by přidání záležitostí spojených s bezpečnostní do sledovacího systému přidalo režii navíc, ztížilo v budoucnu změny a obecně by to míchalo úlohy, které se míchat nemají. Podle něj by bylo lepší ponechat seccomp jako samostatnou vlastnost, která bude filtrovací mechanismus sdílet až tehdy, když se vytvoří vhodná sada interních API.
Ingo Molnára, velkého podporovatele patche, to neodradilo; věří, že silněji integrované mechanismy vytvoří mocnější a užitečnější nástroj. Vzhledem k tomu, že bezpečnostní rozhodnutí se někde musí udělat tak jako tak, rád by viděl, kdyby se k tomu v nejvyšší možné míře využívala existující infrastruktura. Tento argument ale zjevně nepomůže; Peter odpověděl:
Tak si věci stojí v době psaní tohoto článku. Rozšířený mechanismus bezpečného zpracování – který ve své původní podobě perf nepoužíval – prošvihne začleňovací okno a nemá žádnou jasnou cestu do hlavní řady. Vzhledem k tomu, že Linusovi se původní myšlenka také nelíbila, není jasné, jestli má vůbec nějakou budoucnost.
napsal Jonathan Corbet, 25. května 2011
V době psaní tohoto článku bylo do budoucí verze jádra přetaženo 5400 neslučovacích sad změn. Zpočátku se zdálo, že tento vývojový cyklus nebude mít velký počet vzrušujících nových vlastností, ale nějaké zajímavé přírůstky tu jsou. Mezi změnami viditelnými pro uživatele je následující:
Nové typy POSIXových hodin: CLOCK_REALTIME_ALARM a CLOCK_BOOTTIME_ALARM; lze je použít k nastavení časovačů, které systém probudí z uspaného stavu. Více informacích o těchto nových hodinách vizte v tomto článku.
Do síťového stacku byl přidán Plánovač paketů Rychlá férová fronta [Quick Fair Queue packet scheduler]
Byl přidán just-in-time překladač pro BPF paketové filtry; zatím je podporována pouze architektura x86-64
Síťování má nové systémové volání:
int sendmmsg(int fd, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags);
Je to protějšek recvmmsg(), umožňuje procesu odeslat více zpráv jedním systémovým voláním.
Byly začleněny ICMP sockety; jejich hlavním účelem je poskytnout neprivilegovaným programům možnost posílat datagramy echo-request.
Nový knoflík v sysctl umožňuje omezit kvalifikace předané pomocným programům v uživatelském prostoru [user-mode helpers], které spouští jádro; detaily vizte v commitu.
Souborový systém tmpfs získal podporu pro rozšířené atributy.
Byl začleněn ovladač Xen block backend (umožňuje hostu exportovat blokové zařízení k jiným hostům)
Do stromu staging byl přidán kód pro podporu subsystému USB/IP pro uživatelský prostor; tento subsystém umožňuje „exportovat“ USB zařízení přes síť.
Mezi změny viditelné pro vývojáře jádra patří:
Při procházení spojového seznamu [linked list] a hlist se již nepoužívá přednačítání [prefetch]; může se to stát počátkem rozsáhlé snahy odstranit explicitní operace přednačítání. Více informací vizte v článku níže.
Nová funkce strtobool(), která konvertuje uživatelem zadané řetězce na pravdivostní hodnoty:
int strtobool(const char *s, bool *res);
Všechno, co začíná [yY1], se převede na true, řetězce začínající na [nN0] se převedou na false, všechno statní dostane chybu -EINVAL.
Jde zde celá nová série funkcí pro konverzi řetězců v uživatelském prostoru na číselné hodnoty v jádře; všechny se řídí tímto vzorem:
int kstrtol_from_user(const char __user *s, size_t count, unsigned int base, long *res);
Tyto funkce se postarají o bezpečné zkopírování řetězce z uživatelského prostoru a o jejich převod na číslo.
Jádro má novou obecnou funkci pro binární hledání:
void *bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp)(const void *key, const void *elt));
Tato funkce bude hledat key v poli začínajícím na pozici base, které má num položek velikosti size.
Používání vláken pro obsluhu přerušení na specifických linkách lze řídit pomocí funkcí irq_set_thread() a irq_set_thread()
Bylo začleněno rozhraní static_branch() pro mechanismus návěští skoku
Sledování funkcí může nyní využívat více uživatelů, z nichž každý sleduje jinou sadu funkcí.
Byl začleněn mechanismus pro časovač – budík [alarm timer]; ten umožňuje nastavit časovače, které se spustí, i když je systém uspán.
Objekt předaný kfree_rcu() bude po následujícím klidovém období read-copy-update předán kfree(). Jádro obsahuje spoustu zpětných volání RCU které jenom volají kfree(); mělo by být možné je nahradit pomocí volání kfree_rcu()
Pro překlad jádra již není výchozí -Os (optimalizace pro velikost); náklady v podobě ztráty kvality kódu spojené s touto volbou byly považovány za příliš vysoké. Linus řekl: Stále si myslím, že cena za chybějící I$ je závažná záležitost, ale bohužel -Os nevypadá jako řešení. S touto volbou i bez ní gcc přehlédne některé zjevné zlepšení kódu a když je povolena, gcc se občas rozhodně udělat něco, co není dobré ani při vysokých poměrech chybějících I$
Bylo začleněno první kolo pročišťovacích patchů pro architekturu ARM. Bylo zkonsolidováno mnoho duplicitních funkcionalit a odstraněna podpora pro mnoho (pravděpodobně) nikdy nevyužívaných konfigurací platforem a desek.
Parametr W= pro překlad jádra nyní přijímá hodnoty od 1 do 3. Na první úrovni se vypisují pouze varování, která jsou považována za relevantní; kompletní překlad jádra jich vypíše „jenom“ 4800. Při W=3 vývojář obdrží celých 86 000 varování. Berte na vědomí, že pokud chcete všechna varování, musíte říct W=123.
Začleňovací okno pro tento vývojový cyklus pravděpodobně skončí 29. května těsně předtím, než Linus nastoupí do letadla do Japonska. Tou dobou se pravděpodobně dozvíme i to, jak se bude příští verze jmenovat; Linus dal jasně najevo, že si myslí, že čísla v 2.6.x jsou příliš vysoká a že je čas na změnu. Příští týden zde najdete závěr začleňovacího okna a konec napětí o číslu verze jádra.
napsal Jonathan Corbet, 24. května 2011
V minulých jaderných novinách se objevil krátký článek o skrývání jaderných adres před uživatelským prostorem. Toto skrývání se dostalo pod palbu od mnoha vývojářů, kteří říkají, že to rozbíjí programy (například perf), a přitom to neposkytuje žádné skutečné zabezpečení navíc. Nezdá se, že by tu byl konsenzus o tom, jestli je lepší, když útočníci neví, kde jádro uchovává své datové struktury. Ukazuje se, že zde může být ještě lepší způsob, než hodnoty ukazatelů prostě skrýt.
Není pochyb o tom, že mít přístup k rozvržení jaderné paměti je pro útočníky užitečné. Jak to řekl Dan Rosenberg:
Skrývání jaderných adres má útočníka o tyto informace navíc připravit, což mu ztíží práci. Jedním velkým problémem tohoto přístupu je to, že většina systémů používá distribuční jádra. Získat potřebné informace o adresách z balíčku s jádrem od distributora není nijak výrazně náročné. Na takových systémech tedy rozvržení paměti jádra není žádným tajemstvím bez ohledu na to, jestli se hodnotám ukazatelů umožní prosáknout do uživatelského prostoru.
Když se tohle všechno diskutovalo, objevil se další nápad: proč při bootu nerozvrhnout jadernou paměť náhodně? Náhodné rozvržení adresového prostoru se používá pro zvýšení odolnosti proti útokům již dlouho, ale ne pro jádro. Vzhledem k tomu, že obraz jádra lze přestěhovat, není důvod, proč ho vždycky nahrát na stejné místo. Pokud pro sebe jádro vypočítá při každém bootu jiný offset, může tento offset odečíst od hodnot ukazatelů předtím, než je předá uživatelskému prostoru. Tyto ukazatele by pak mohly používat nástroje jako perf, ale už by nebyly nijak užitečné pro toho, kdo se pokouší přepsat jaderné datové struktury.
Dan znáhodnění adresového prostoru jádra zkoušel s určitým úspěchem; ukazuje se, že jednoduše přestěhovat jádro není tak těžké. Narazil přitom ale na pár potenciálních problémů. Prvním z nich je, že při bootování není k dispozici příliš mnoho entropie, takže vygenerovat dostatečně náhodnou základní adresu není tak jednoduché. Zdá se, že z real-time hodin a čítače časových značek [time stamp counter] lze získat dost bitů entropie, aby to útočníkovi později zabránilo jednoduše uhodnout základní adresu, ale skutečně náhodné číslo by bylo lepší.
Poté, na což upozornil Linus, jádro nelze stěhovat neomezeně. Pro umístění jádra je mnoho omezení kvůli zarovnání, takže podle Linuse je k dispozici maximálně 8-12 bitů náhodnosti. To znamená, že exploit by mohl najít správný offset maximálně po několika tisících pokusech. Vzhledem k tomu, že počítače umí dělat věci rychle, to správci systému nedává mnoho času zareagovat.
Jak ale upozornili ostatní, toto je pravděpodobně dostatečně náhodné. Neúspěšný pokus o zneužití chyby s velkou pravděpodobností způsobí oops; i když si ho správce nevšimne hned, časem by měl a ztrácí se tak možnost tiše převzít kontrolu nad strojem. Krom toho nepovedené pokusy mohou snadno systém zcela shodit (obzvláště když je nastaven příznak „panic on oops“, což platí pro mnoho RHEL systémů) nebo alespoň zanechat systém ve stavu, kde další pokusy zneužít chybu nebudou moci fungovat. Podle všeho je hodně užitečné donutit útočníka hádat.
Tato výhoda se nicméně ztrácí, když útočník nějak přijde na offset, který systém při bootu použil. Dan si všiml jednoho způsobu, jak to lze udělat: neprivilegovaná instrukce SIDT může najít tabulku popisovačů přerušení v systému. Z této pozice by se následně vypočítal offset. Tento problém lze vyřešit dynamickou alokací tabulky při bootu, ale za cenu hrabání se ve velmi záludném kódu pro počáteční fáze bootu. Dynamická alokace by nicméně měla i další výhody; pokud by se vložila do oblastí specifických pro jednotlivá CPU, systém by byl o něco málo škálovatelnější.
Problém lze tedy určitě vyřešit, ale není pochyb o tom, že budou i jiná místa, odkud bude útočník moci získat skutečné adresy v adresovém prostoru jádra. Jednoduše je příliš mnoho způsobů, jakým tato informace může do uživatelského prostoru prosáknout. Ucpat všechny tyto díry vypadá jako jeden z těch dlouhotrvajících úkolů, který nikdo nikdy neudělá. Mělo by nicméně být možné zacpat jich dost na to, aby útočníci nemohli počítat s tím, že vždycky přijdou na skutečné umístění jádra na běžícím systému. Je to trocha zabezpečení zatajováním, kterou stojí za to mít.
napsal Jonathan Corbet, 24. května 2011
Postupem času většina vývojářů software zjistí, že snaha o mikrooptimalizace většinou nestojí za to, obzvlášť když chybí pevná data ukazující na specifický problém. Problémy s výkonností často nejsou tam, kde si myslíme, že jsou, špatně mířené pokusy věci vyladit k rychlejšímu běhu tedy mohou být naprosto neefektivní. Nebo mohou dokonce stav zhoršit. To je lekce, které se právě dostalo jaderným vývojářům.
Na úrovni jádra výkonnost často závisí na chování cache. Odkazování na paměť, které je potřeba vyřešit skutečným přístupem do paměti, je extrémně pomalé; dobrá výkonnost závisí na tom, že potřebná data budou po většinu času v cache CPU. Jádro se hodně snaží používat čerstvě nacachovanou paměť, když je to možné; spousta práce byla také věnována reorganizaci datových struktur tak, aby se pole, ke kterým se často přistupuje zároveň, nacházela ve stejné řádce v cache. Obecným pravidlem je, že tyto optimalizace výkonnost měřitelně zlepšily.
Práci s daty, která v cache nejsou, se často vyhnout nelze, ale někdy je možné pokusit se omezit její cenu. Pokud jádro ví, že bude v blízké budoucnosti přistupovat k paměti na konkrétním místě, může použít pro CPU specifickou instrukci pro přednačtení, která zahájí proces kopírování dat do cache. Tato instrukce je jadernému kódu k dispozici v podobě obecné funkce prefetch(); vývojáři ji používají výrazně. Vezměme například toto běžně používané makro z <linux/list.h>:
#define list_for_each(pos, head) \ for (pos = (head)->next; prefetch(pos->next), pos != (head); \ pos = pos->next)
Toto makro (a jeho varianty) se používá k procházení spojového seznamu. prefetch() se volá, aby načítání dalšího záznamu začalo už v době, kdy se zpracovává aktuální záznam. Při troše štěstí budou data v době, kdy začne další opakování smyčky, již načtená – přinejmenším budou alespoň na cestě. Spojové seznamy jsou známy tím, že jsou to pro cache nepřívětivé datové struktury, takže dává smysl, že taková optimalizace může pomoci věci zrychlit.
Až na to, že to není pravda – přinejmenším ne na x86.
Andi Kleen byl pravděpodobně první, kdo tuto optimalizaci zpochybnil, když se pokusil z operací se seznamy přednačítání odstranit loni v září. Jeho patch ale vygeneroval nějakou diskuzi a nakonec zmizel. Linus nedávno zkoušel nějaké profilování na jedné ze svých oblíbených pracovních zátěží (překlad jádra) a zjistil, že instrukce přednačítání jsou na vrcholu seznamu. Přednačítání stálo čas a tento čas nebyl splacen lepším chováním cache; jednoduché odstranění volání prefetch() věci zrychlilo.
Ingo Molnár, protože je Ingo, skočil do diskuze a provedl během hodiny týdenní výzkum. S použitím perfu a lehce poupraveného jádra byl schopen ověřit, že používání instrukcí přednačítání způsobilo ztrátu výkonnosti o přibližně 0.5 %. To rozhodně není výkonnostní regrese, která by si vyžádala první stránku novin a palcové titulky, ale rozhodně je tu prostor pro optimalizaci, která by věci mohla urychlit. Něco tu zjevně nefunguje tak, jak si lidé mysleli.
Linus na jeden problém upozornil hned zezačátku: jeho test obsahoval spoustu průchodů jednosměrně spojených hlist seznamů hashových tabulek. Tyto seznamy bývají krátké, takže tu není moc prostoru pro přednačítání; ve skutečnosti se většinou prefetch pokoušel použít nulový ukazatel, který znamená konec seznamu. Přednačítání nulového ukazatele vypadá hloupě, ale také je to nákladné: každá taková operace na x86 (a podle všeho i na ARM) narazí na chybějící hodnotu v TLB a způsobí zastavení pipeline [pipeline stall]. Ingo tento efekt změřil a dospěl k závěru, že každé přednačtení null stojí přibližně 20 cyklů procesoru.
Přednačítání nuly je zjevně špatný nápad. Bylo by pěkné, kdyby CPU jednoduše ignorovalo pokusy přednačíst nulový ukazatel, ale tak věci nestojí a – jak je to běžné – je potřeba to upravit v software. Ingo testoval s verzí prefetch(), která by instrukci přednačtení zadávala pouze pro nenulové ukazatele; tato verze se opravdu chovala lépe, ale stále měřitelně hůře, než když se přednačítání jednoduše vynechalo.
Návrháři CPU si jsou velmi dobře vědomi ceny za čekání na paměť; spoustu snahy věnovali tomu, aby se tato cena minimalizovala všude, kde je to možné. Mezi jinými věcmi tedy současná CPU mají svoji vlastní jednotku pro přednačítání paměti. Ta se pokouší předpovědět, která pozice v paměti bude příště zapotřebí, aby se její načtení zahájilo dříve. Jedna z věcí, které si Ingo během svých testů všiml, byla, že i bez operace přednačtení zadaných softwarově byl počet operací přednačtení na CPU přibližně stejný. Hardwarový přednačítač se tedy v daném čase činil – a co se týče rozhodnutí o tom, co načíst, fungoval lépe než software. Explicitní operace pro přednačtení podle všeho akorát rušily to, co se pokoušel dělat hardware.
Ingo své výsledky shrnul takto:
Okamžitým výsledkem je to, že pro 2.6.40 (ať už se bude jmenovat jakkoliv) byla volání prefetch() odstraněna z procházení spojových seznamů, hlist a seznamů sk_buff – přesně to, o co se pokoušel Andi Kleen v září. Je dost možné, že budou odstraněny i další operace přednačítání. prefetch() bude mít v jádře nadále své místo, ale jenom ve specifických situacích, kde bude možné zjevně dokázat, že to pomáhá výkonnosti. Stejně jako u dalších nízkoúrovňových optimalizací (na mysl přichází likely()) vhodit do kódu prefetch(), protože to vypadá jako dobrý nápad, není často správně.
Z této zkušenosti vychází ještě jedna lekce, a sice, že na číslech záleží. Andi měl pravdu, když se pokoušel tyto operace odstranit, ale neuspěl ve snaze patch začlenit. Proč věci nyní dopadly jinak má asi více důvodů, prvním z nich je fakt, že tentokrát o danou záležitost projevil zájem Linus. Je ale také pravda, že patche orientované na výkonnost musí být doprovázeny čísly, které ukazují, že se opravdu dosáhne požadovaného efektu; kdyby si Andi našel čas kvantifikovat dopad svých změn, měl by silnější pozici pro jejich začlenění.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej: