> nachází se v unsafe kódu.
A bude jich víc, protože invarianty ohledně aliasingu jsou v Rust unsafe kódu komplexnější než v C.
Takže, pokud code review kódu v C nenašla všechny problémy, tak u unsafe Rust to bude ještě horší. Jediné, co by pomohlo, je snížit množství unsafe Rustu. Což je otázka, jestli v jádře půjde.
Nejvíc nebezpečně je to, že změna nebo chyba v safe kódu může právě způsobit chybu v unsafe kódu - ta oprava nemění unsafe část, ale právě tu safe.
No a realita je taková, že bez unsafe nemá v jádře rust šanci (protože jádro je unsafe a rust musí koexistovat s tím co je napsané v C).
Toto vlastně znamená, že argument, že je potřeba dělat důkladný review jen té unsafe části neplatí. Jakmile se v kódu objeví unsafe část, tak už není záruka, že změna v té safe části nezpůsobí podobnou chybu.
18. 12. 2025, 09:43 editováno autorem komentáře
@cc 18.12.2025 09:41
"chyba v safe kódu může právě způsobit chybu v unsafe kódu" - hmm, pokrok nezastavíš, všichni přecházíme na rust. A kdo nepřechází, je zpátečník. </konec_ironie>
Já nemám nic proti rustu a už jsem ho použil několikrát (ale pořád se učím, že jo...). Je to dobrý jazyk, ale na druhou stranu obhájci rustu mají růžové brýle a šíří bludy, takže je potřeba trochu demystifikace.
Stejně jako fanatičtí odpůrci.
Chyba v C může způsobit problém kdekoliv. Rozdíl je jen v tom, že lidi to u C očekávají.
Nikoli, rozdil je predevsim v tom, ze v Ccku se pise 40 let. A tudiz tu je 40let zkusenosti.
Michat ruzne jazyky dohromady je pak zcela vzdy totalni pohroma.
C jako jazyk je primitivní. Problém je, že "standardní knihovna nástrojů" je v každém větším projektu unikát.
Koukněte někdy na zdrojáky GCC. To je samé makro, tam se v čistém C skoro nepíše. To samé primitiva v kernelu. Voláte různé interní funkce, ale samotná syntaxe není ničím zajímavá ani speciální.
Tak ono kdyby melo jadro nejakou normalni dokumentaci.. posledne me trvalo 5-6 rebuildu a doplnovani printk zjistit, proc pada nejaka vec.
Pokud pod DSA switchem nadefinuji dva uplink porty nazvane "cpu" (moje cast), tak jenom prvni v nasledne interni strukture dostane prirazenou referenci na interface ... a nekde tam hluboko za sedmero funkcema, je kod, ktery ocekava predpoklady, ale samotny kod jadra na jinem miste ty same veci vesele porusuje (zpracuje jen jeden "cpu" port, na ostatni kasle bez varovani/chyby).
A poslal jsi do příslušného mailing listu bug report, aby to mohl někdo opravit? Často tyto chyby opravují přímo správci daných subsystémů.
Neni to bug ale "featura" :D ze to nepodporuje vicero linku - byt neni explicitne zakazana (ve FreeBSD je dana vec hw/sw funkcni).
Zatim jsem to nerozjel cely, takze az bude hotovo urcite poslu patche do mainline. Tipy uz od maintaneru dostavam, to zas jo - jsou vzorne napomocni, jen ten hw je trocha exotika tak to neni tak lehky otestovat.
Btw je to kousek hw koupeny zde na foru, jen jsem blbe udelal research, ze to nema diskretni sitovky, ale switch skrze DSA. A jak to neni OF/DT based, tak se to rozchazi ponekud hur (na x86-64).
Až po odoslaní mi došlo, že tým určite nemyslíte nikoho, z bežných účastníkov takýchto diskusií na týchto stránkach ;-)
Chyba v C může způsobit problém kdekoliv. Rozdíl je jen v tom, že lidi to u C očekávají.
Ne, chyby v unsafe lide ocekavaji uplne stejne. V soucasnosti je hlavni rozdil v tom, ze za pul stoleti existence Ccka a pres 30 let existence Linuxu se objevila spousta nastroju, ktere chyby v C dokazi odhalit, ktere v Rustu v soucasnosti chybi. Kdyz jsem se na to naposledy koukal, tak pro jaderny kod nebylo mozne pouzivat rustove sanitizery, ktere jsou dostupne pro userspace, protoze proste nemely jaderne alternativy. V soucasnosti proste clovek musi byt v unsafe Rustu opatrnejsi nez v C, protoze min chyb najdou stroje.
Jsem docela optimista - pokud takové nástroje již existují pro user-space rust, určitě bude snaha je maximálně využít i pro kernel.
Jenze to prave nejde tak snadno, budou se vpodstate muset napsat znovu. Proto je ted bezpecnejsi psat kod v C nez v unsafe Rustu. Tim nemyslim, ze zacleneni Rustu byla nejaka chyba, jen upozornuju, ze je naivni si myslet, ze to je bezpecnejsi nez C, protoze to nejspis jeste nekolik let nebude pravda.
Nebude to zdaleka tak bezpečné jako "normální" Rust kód, ale už teď jde vidět, že se dá postavit spousta bezpečných a efektivních abstrakcí nad Linux API, které opravdu budou bezpečnější, než céčko. Takže bych řekl, že už od začátku to bude mít spoustu výhod (ale zatím samozřejmě i spoustu mezer).
Toto vlastně znamená, že argument, že je potřeba dělat důkladný review jen té unsafe části neplatí.
Platí. Ale musíte udělat nový review unsafe částí, i když zasáhnete do čehokoliv (safe i unsafe), co se v tom unsafe používá. Mohly totiž přestat platit nějaké invarianty.
Říkáme zhruba to samé, ale z jiného úhlu pohledu.
Unsafe je totiž jen označení kódu, kde (některá) pravidla hlídá a garantuje programátor.
Je to přesně naopak. Chyba v unsafe kódu může rozbít safe kód, ne naopak. Pokud jsou všechny unsafe bloky v pořádku, tak nejde v safe kódu způsobit UB, to je ta obrovská výhoda Rustu oproti C nebo C++.
> Pokud jsou všechny unsafe bloky v pořádku, tak nejde v safe kódu způsobit UB.
Bohužel tohle neplatí. Viz třeba
fn index(idx: usize, arr: &[u8]) -> Option<u8> {
if idx <= arr.len() {
unsafe {
Some(*arr.get_unchecked(idx))
}
} else {
None
}
}
kde špatně je menší nebo rovno, v safe kódu. Unsafe část je naprosto v pořádku. Když to budete opravovat, tak do unsafe části nemusíte vůbec šahat.
Za mě je tohle jen technikálie - hraní si se slovíčky. Pokud dělám unsafe operaci, musím (měl bych) zajistit, že budou splněny všechny podmínky pro správnost. Tzn. v tomhle případě bych bral kontrolu vstupních parametrů jako součást unsafe operace, byť technicky nemusí být ta kontrola v unsafe bloku.
Pokud bych se na ten unsafe blok koukal izolovaně tak je za mě špatně, protože nekontroluje nic - dělá unchecked indexaci indexem kdo ví odkud, to je prostě chyba.
Možná v kódu, kde je unsafe operací hodně, tak se můžou invarianty kontrolovat na vzdálenějších místech od unsafe bloků, ale to bych považoval za dost nešťastné a minimálně by se to mělo omezovat na privátní rozhraní. A jak jsem psal, pak bych celou strukturu/modul považoval za "unsafe", protože chtěně (by design) ovlivňuje unsafe kód. Ale to je speciální situace a očekával bych, že je pro to dost dobrý důvod, že se invarianty nekontrolují přímo v unsafe bloku (nebo těsně před ním jako v příkladu).
Z vlastní zkušenosti napíšu tak 1 unsafe blok na cca 5k řádků (a pravděpodobně bych se dokázal obejít i bez něj). A ve wrapech C knihoven, kterých jsem se dotknul, byl IIRC každý unsafe blok "ucelený". Takže nemám zkušenost s kódem, kde by se divoce míchal safe/unsafe.
Samozřejmě může takový být, jenom 1) říkám, že na "divoký" unsafe kód nejsem expert a 2) dávám příklad z praxe, že jsem takový kód zatím ani nepotkal a je to z mého pohledu okrajová záležitost (to jen aby někdo nenabyl dojmu, že rustí kód je nutně protkaný unsafe a nemá tak smysl safe a unsafe rozlišovat).
Technikálie to je a není. Jde o to, že tvrzení " Pokud jsou všechny unsafe bloky v pořádku, tak nejde v safe kódu způsobit UB." je zákeřné a zavádějící.
Začátečníkovi určitě nedojde, že pod ty unsafe bloky spadají i kusy safe kódu kolem. A ty kusy safe kódu navíc nejsou nijak jasně ohraničené.
Dává to falešný pocit bezpečí.
Tohle by platilo, pokud by normální Rust programy obsahovaly spoustu unsafe bloků/funkcí. Ale ve valné většině Rust programů žádný unsafe není (myšleno přímo v user kódu, samozřejmě je v knihovnách, ale tam to obvykle nevadí). A zejména začátečníci nebudou s unsafe obvykle vůbec pracovat. Programuju v Rustu 7 let, pracuju v něm na webových aplikacích, překladačích, HPC apod., a unsafe jsem potřeboval přesně jednou na zavolání Linux syscallu :)
A jinak bych teda řekl, že pro většinu unsafe operací ty invarianty jsou docela dobře ohraničené okolním kódem, i když to samozřejmě nebude platit vždy, obzvláště u paralelního přístupu ke sdíleným datům. Nicméně pořád je to o hodně lepší než v C nebo C++, kde UB může vzniknout úplně všude. V Rustu stačí "grep unsafe".
> A jinak bych teda řekl, že pro většinu unsafe operací ty invarianty jsou docela dobře ohraničené okolním kódem
U datových struktur je to většinou ohraničeno celou strukturou. Takže to může být několik tisíc řádků.
Navíc hodně balíčků obsahuje unsafe. Je docela těžké najít balík bez unsafe.
> Je docela těžké najít balík bez unsafe.
Tak to fakt není pravda :) Loni mělo cca 20 % balíčků na crates.io unsafe (https://rustfoundation.org/media/unsafe-rust-in-the-wild-notes-on-the-current-state-of-unsafe-rust/), tj. každý pátý. To je včetně všech crate pokusů, které nikdo nikdy nepoužije.
Navíc v knihovnách je použití unsafe mnohem častější, než v aplikacích, takže u reálně používaných aplikací to bude mnohem méně. Jak už jsem psal výše, za 7 let používání Rustu jsem použil unsafe jednou (jen letos mám 1000+ mergnutých Rust pull requestů, píšu toho v Rustu hodně). V praxi to prostě není obvykle potřeba.
19. 12. 2025, 16:23 editováno autorem komentáře
Platí to. V té unsafe části máte bug, v tom je problém. Nebyly zkontrolovány invarianty při volání unsafe funkce. Abych to opravil, musel jsem se podívat jen na unsafe kód, ne "všude". To je pointa memory safety v Rustu. Pokud máte korektně vše unsafe (a ve většině programů není v user kódu unsafe nikde), tak zbytek nemůže způsobit UB (modulo compiler bugy, ale na ty nenarazíte omylem obvykle). Kdyby to tak nebylo, tak se Rust neprezentuje jako memory safe a nebyl by v tomto o moc lepší, než C nebo C++.
Googme nedávno měl blog post, kde řekli, že v Androidu mají v Rust kódu 1000x méně zranitelností na řádky kódu, než v C++. To fakt není náhoda :)
Tohle je teoreticky neprůstřelné, ale prakticky nepoužitelné. Znamená to, že každý unsafe blok musí zkontrolovat úplně všechno a navíc to ošetřit stylem, aby safe kód neměl šanci nic podělat.
Tenhle přístup povede k tomu, že unsafe bloky budou růst a požírat veškerý kód, co na ně může mít nějaký vliv.
Nebo by se to dalo přeformulovat i tak, že za každý bug v safe části kódu může unsafe kód, který to tomu safe kódu dovolil. V důsledku by byl každý unsafe blok buď nekompletní nebo chybný ;)
Stačí kouknout pod čím diskutujeme. Opravili safe kód. Nepřesunuli všechny kontroly do unsafe kódu. Protože by to mimo jiné kolidovalo s požadavkem mít unsafe kódu co možná nejmíň.
19. 12. 2025, 14:58 editováno autorem komentáře
No, já bych to spíše řekl naopak. Teoreticky to může být velký problém, ale v praxi to není pro většinu programů žádný problém, a pro ten zbytek je to o několik řádů menší problém, než v C nebo C++.
Teoreticky je opravdu možné, že by to takto fungovalo. V praxi tomu ale tak není (což je skvělá zpráva :) ). Většina Rust programů žádný unsafe blok přímo ve svém kódu nemá, a ten zbytek, co ano, tak často používá unsafe, který má pouze lokální požadavky, a není tak těžké ověřit, že ty invarianty jsou splněny. To neznamená, že v Rustu (při použití unsafe) nebudou vznikat zranitelnosti. Ale znamená to, že těch zranitelností bude řádově méně, než v C nebo C++, a to je to, oč tu běží. A v kernelu, který je velmi speciální, a prošpikovaný těmito low-level věcmi, tak na místech, kde nebylo možné vymyslet bezpečné API, bude k UB i v Rustu docházet. Ale ze zkušenosti to zatím vypadá, že jich bude mnohem méně, než v C, a to je ta důležitá věc.
Je hodně těžké tohle předat lidem, co v Rustu neprogramovali, protože dokud si to člověk nezkusí, tak opravdu nejde jen tak z papíru poznat, jak to v praxi vypadá :) Pokud (v tomhle) věříte Googlu, tak zde je zkušenost z praxe: https://security.googleblog.com/2025/11/rust-in-android-move-fast-fix-things.html V Rustu mají 1000x méně zranitelností na jednotku kódu, než v C nebo C++. To je ten důvod, proč spousta firem, které řeší paměťové zranitelnosti, na Rust přechází.
Bohužel bez unsafe nenapíšete ani jednoduché datové struktury, pokud chcete aby měly použitelný výkon. To je rozdíl třeba oproti C# a tamnímu unsafe.
S tím víceméně souhlasím, ale jak často si většina programátorů píše vlastní datové struktury :) To 99% Rust programátorů nedělá, protože to nedává smysl, a hlavně nemusí, prostě si stáhnou už hotové datové struktury z crates.io.
Ad „Tohle je teoreticky neprůstřelné, ale prakticky nepoužitelné. Znamená to, že každý unsafe blok musí zkontrolovat úplně všechno a navíc to ošetřit stylem, aby safe kód neměl šanci nic podělat. Tenhle přístup povede k tomu, že unsafe bloky budou růst a požírat veškerý kód, co na ně může mít nějaký vliv.“
Rozumné by asi bylo, aby unsafe kód nebyl běžně používaný a volal se jen z jednoho místa – z vrstvy safe kódu, která ho obaluje a které se dá věřit. Ovšem to nabourává tu pohádku o tom, že chyby můžou být jen v unsafe kódu, kterého je málo.
> Ovšem to nabourává tu pohádku o tom, že chyby můžou být jen v unsafe kódu, kterého je málo.
No, nenabourává, protože přesně to, co píšete ("unsafe kód není běžně používaný, a volá se pouze z bezpečného safe API") je situace, která v praxi většinově platí, a 99 % veškerého Rust kódu takto funguje. Unsafe kódu, kterého by běžní Rust programátoři museli psát, je opravdu málo (až bych řekl, že pro velkou řadu Rust programátorů je to v podstatě nic, protože nikdy unsafe nepotřebují).
Linux kernel je v tomhle samozřejmě dost specifický, a bude potřeba ještě stabilizovat řadu jazykových featur, aby šlo pro všechny kernel use-casy postavit bezpečné API.
Viz komentář výše – pokud by ten unsafe kód měl počítat s tím, že bude volán jakkoli, musel by kontrolovat všechny podmínky, což je jednak hromada kódu navíc a jednak to má dopad na výkon. Proto dává smysl mít kombinaci unsafe a safe kódu, která dohromady funguje dobře – ovšem za předpokladu, že ten safe napsaný specifickým způsobem, aby pasoval na ten unsafe tzn. ty dvě vrstvy se musí vyvíjet koordinovaně a pokud možno by je měl psát jeden člověk, který přesně ví, co dělá a jak je ta unsafe část implementovaná. A až za touto první vrstvou „safe“ kódu lze říct, že je to bezpečné a že to může používat relativně kdokoli.
Nemám s tím problém a za mne je to dobrý přístup. Jen, jak jsem psal, ten prostor, ve kterém lze udělat fatální chybu, je větší, než kód formálně označený jako „unsafe“.
Podívej se na ten fix a přestaň blábolit:
Nikdo se unsafe části ani nedotkl, ta unsafe část je naprosto v pořádku.
Jakmile dovolíš v jazyku unsafe, už nikdy nebudou safe ani ty "safe" části, a tato chyba to jasně dokazuje. Je to reálná chyba a ne teorie. Taky máš nasazené ty růžové brýle a opakuješ 1000x vyvrácené mýty.
Troufám si tvrdit, že neblábolím, jen se snažím věci uvádět na pravou míru :) Netvrdím, že v Rustu nemůže být UB, pokud se použije unsafe, tak tam samozřejmě UB být může. To důležité není, že bug v unsafe kódu může způsobit UB, to je jasné, ale že bug v safe části (opakuji v safe části, ne nic co používá unsafe blok) NEMŮŽE způsobit UB, to je ta celá pointa.
Rozumím poznámce, že oprava byla v safe části, ale to nic nemění na tom, kde byl ten bug. Když je bug na místě A, tak ho můžu opravit na místě A, nebo ho můžu opravit i tak, že změním místo B, a tím mi zmízí bug z místa A. To nic nemění na tom, že abych našel, co *způsobuje* UB, tak k tomu může dojít pouze v unsafe částech kódu. Tady opravdu k bugu došlo v unsafe části kódu, což je to, co jsem tvrdil, i když ten problém, co způsoboval rozbití invariantu, byl jinde v kódu, a byl v safe kódu, ale to není až tak extra důležité.
Taky bych řekl, že vlastně tímhle fixem nic moc neopravili. Stejný bug může kdykoliv vzniknout v budoucnu, pokud jinde v kódu budou zase něco dělat paralelně nad tou datovou strukturou. Ideálně by to API mělo být navržené tak, aby tam tenhle unsafe blok být nemusel, a aby to nešlo použít špatně. Ne vždycky to jde - tohle možná bude jeden případ, kdy to nejde, a v tu chvíli tam budou vznikat další a další zranitelnosti i v budoucnu, dokud někdo neudělá lepší API, a tím pádem tenhle konkrétní kus kódu nebude v bezpečnosti o moc lepší, než C nebo C++. Na tom nic nepopírám :)
Tohle ale byla chyba souběhu. Celkem klasický problém vícenásobného přístupu, kterého si někdo nevšiml.
Takže sice ohledně aliasingu máte obecně pravdu (v každé diskuzi, do které jste to napsal), ale je to irelevantní k popisovanému případu.
Já jsem to důkladně nestudoval, ale řekl bych, že souběh u lock-free double-linked listu je tak nějak očekávaný :)
Takže do troch dní, to naozaj predčilo moje očakávania :)
Ale to upokojovanie kultu, ktorým začína oznámenie pána Kroah-Hartmana je celkom vtipné. Asi sa chudák bál, že jeho hlava bude ďalšia, na ktorú vypíšu odmenu.
Pravděpodobně to bylo myšleno od prohlášení, že rust v jádře už není žádný experiment. Holt klasický famous last words
efekt. :-)