Voor het eerst krijgt bug in Rust-code in Linux-kernel CVE-nummer toegewezen

Voor het eerst is er een bug in de Rust-code in de Linux-kernel gevonden die een CVE-trackingnummer heeft gekregen. Rust zit al sinds 2022 experimenteel in de kernel en wordt gezien als veiliger, met name op geheugengebied.

Greg Kroah-Hartman, een van de hoofdontwikkelaars van de Linux-kernel, schrijft dat er voor het eerst een CVE-nummer is toegekend aan een kwetsbaarheid in een stuk Rust-code in de kernel. Dat betekent niet dat dit de eerste bug is op dat gebied, maar wel de eerste die met zo'n 'Common Vulnerabilities and Exposures'-code te volgen is. De bug wordt getrackt als CVE-2025-68260.

De bug in kwestie kan een crash veroorzaken, zegt Kroah-Hartman, en betreft geen geheugencorruptie. De kwetsbaarheid betreft een race condition in de rust-binderdriver.

Het is de eerste keer dat er een getrackte bug in de Rust-code in de Linux-kernel zit. Dat is redelijk uniek en Kroah-Hartman merkt ook op dat er 159 andere CVE's zijn toegewezen aan kernelcode, maar dat is alleen in C-code. Rust werd in 2022 al experimenteel aan de kernel toegevoegd. De hoofdontwikkelaar van Rust in Linux, Miguel Ojeda, liet eerder deze week al weten dat Rust 'een blijvertje' is voor de kernel. Rust heeft voordelen boven C, waaruit het grootste deel van de kernel nu nog bestaat. Met name op veiligheidsgebied wordt Rust als beter gezien: de kans op geheugenbugs is veel kleiner.

Door Tijs Hofmans

Nieuwscoördinator

18-12-2025 • 19:06

73

Submitter: Vanquish92

Reacties (73)

Sorteer op:

Weergave:

Veel security bugs zijn geheugen gerelateerd, maar natuurlijk niet alles.

Ik vraag me af of Linus Torvalds ook Rust spreekt eigenlijk.
Dit is nog steeds een geheugenbug. Race conditions komen voor wanneer 2 stukken code naar dezelfde geheugen locatie gaan schrijven. Het valt te vergelijken wanneer jij en een collega een document van Dropbox download, ieder afzonderlijk offline die bewerkt, en daarna terug upload. De 1 zal de wijzigingen van de ander overschrijven. Dit valt op te lossen door af te spreken wie de bewerking voor de ander doet (semaphore/mutex).

Nu doet software erg snel z'n taken, dus dat maakt de duur dat een race condition kan voorkomen vaak klein. Maar dat wil niet zeggen dat een aanvaller iets kan proberen te forceren, bijvoorbeeld door kwetsbare code heel vaak uit te voeren (wat op het oog zinloos lijkt).

Als je kijkt in de CVE valt te zien dat het "unsafe" Rust code betreft. Dat is code waarin het mogelijk is om C-style pointers te gebruiken die niet onderhevig zijn aan Rust's borrow checker. Die borrow checker is namelijk een unieke feature van Rust waardoor het zo populair is geworden. En om uit dat artikel het nog even sterker aan te halen: "The borrow checker helps prevent data races" :)

In andere woorden, Rust is nog steeds veilig, maar unsafe code niet. Helaas kan je met low-level programming er niet altijd omheen om unsafe code te schrijven, bijvoorbeeld om met hardware te praten of om IPC objecten te schrijven. Verder kan low-level C code volatile bevatten, memory barriers, vieze impliciete type casts (in C++ gelukkig meer zichtbaar dankzij "reinterpret_cast") en mogelijk zelfs inline assembly.. details die je in high-level programmeertalen het liefst (zo min mogelijk) niet meer terug ziet.
Dit is ook wat imho C voor zo'n lange tijd zo populair heeft gehouden, omdat voor hardware programmeurs de taal niet in de weg zit. Behalve als het gaat om security dus.. ;)

[Reactie gewijzigd door Hans1990 op 18 december 2025 20:41]

Waarom gebruiken ze unsafe code? Als demo voor een “veilige” toekomst is het toch gek dat je “verse” code expliciet met unsafe gebruikt.

In principe zou geen enkele hoofdprogrammeur unsafe mogen toelaten - goed genoeg voor een stukje wegwerpcode maar voor een kernel implementatie of de core libraries zou dat toch niet mogen.
Buiten wat @rjberg al zegt. Dingen als unsafe en volatile en wat andere talen het ook noemen komen ook gewoon voor bij en zijn niet te vermijden als je tegen hardware praat. Onder andere via memory mapped io. De waarde die het ene moment er staat kan het andere moment veranderd zijn. Zeker bij status registers en dergelijke.

Er is altijd een plek waar alle code "unsafe" word, zeker in een kernel, zo dicht bij hardware.
Inderdaad, maar wat is dan de toegevoegde waarde van Rust? Een taal die niet tegen de hardware kan praten heeft geen waarde behalve in een academische omgeving. Eenmaal je “unsafe” zegt is niet alleen de code maar ook alles dat op dat geheugen locatie zit mogelijk een probleem.

Blijkbaar was de code specifiek in een linked list, om een object te verwijderen uit een linked list is volstrekt niet unsafe nodig, behalve dan natuurlijk dat de “veilige code” net zo snel als Ruby of Python wordt on runtime checks en global locks toe te passen.

[Reactie gewijzigd door Guru Evi op 18 december 2025 23:41]

Als jij een Rust-programma op problemen wat betreft bufferoverflows e.d. gaat onderzoeken hoef je je alleen maar op de unsafe-delen te concentreren, terwijl je in C alle code nauwgezet moet bekijken. Dat is een verschil van dag en nacht.
C heeft tegenwoordig ook veilige libraries en compile time opties. Het probleem is, zowel in C, Rust als andere talen dat je altijd iets moet inruilen, grotendeels developer tijd, uitvoertijden en gemak.

De tijd die erin gepropt wordt om Rust te laten werken in Linux met zoals we zien nog steeds grote lekken of zoals we met de Rust versie van GNU Coreutils gezien hebben, gewoon dezelfde functie slechter en trager te implementeren kan beter gebruikt worden gewoon te beginnen met oa safestack en andere compile time en runtime checks op mogelijke problemen en dan de dingen die niet meer compileren repareren. Of herimplementaties met veilige functies, er is genoeg laaghangend fruit om jaren zoet te zijn.
Je kunt in C veel oplossen door goede bibliotheken te gebruiken en goede gewoontes te eerbiedigen, maar de kwestie blijft dat problemen in C niet altijd op het eerste oog gezien worden. Vaak worden beveiligingslekken ontdekt die al jaren in de code zaten.

Ik heb zelf gewerkt aan Free Pascal en die compiler is nog beter in fouten in code vinden dan veel andere compilers. Meldingen dat iemand een bestaande code naar Free Pascal porteert waarmee de compiler dan tientallen bugs ontdekt die ook in de oorspronkelijke code zaten, daar zijn we heel erg gewend aan.
Maar dat is in elke taal, inclusief Rust. Het probleem is de grootte van het Linux ecosysteem, miljoenen lijnen code, je kan vandaag alle garanties aanzetten die een moderne compiler biedt voor Linux, maar je kernel gaat niet (of deels niet) compileren.

Het enige dat Rust kan doen is de hele kernel in Rust omzetten zonder ooit unsafe te gebruiken, dat is praktisch onmogelijk maar tot dan gaan er altijd veiligheidsfouten doorkomen. En (safe) Rust lost enkel maar de problemen gedurende de compile time EN als je aanvaardt dat de Rust Core Libraries EN LibC EN de compiler EN de hardware geen andere exploit hebben.

Je kan nog steeds slechte data aanvaarden, de meeste bugs in Linux zijn dan ook niet beveiligingslekken waardoor je willekeurig toegang krijgt op het systeem via een memory leak, maar een reeks exploits die meestal beginnen met een fout in de logica, exploit via memory leak of race condition is raar, en blijkbaar is Rust ook niet immuun, vooral als je iets herschrijft in Rust waar in de C code geen fout was om te beginnen, wat in dit geval ook waar was, Linux heeft genoeg voorbeelden van veilige implementaties voor wat ze aan het proberen waren te doen.

[Reactie gewijzigd door Guru Evi op 19 december 2025 21:58]

Je kan nog steeds slechte data aanvaarden, maar de programmeertaal kan je wel helpen om minder makkelijk slechte data te aanvaarden door te zorgen dat foute data niet in de datatypen past. Stel ik parse een commandregeoptie --kleur (rood,groen,blauw). Een (veel te) simpel codefragment:
type kleur=rood,groen,blauw;

var code:integer;
k:kleur;

begin
  if paramcount<>2 then goto error;
  if paramstr(1)='--kleur' then
    begin
    val(paramstr(2),kleur,code);
    if code<>0 then goto error;
  end;
  writeln('Parsen voltooid');
end;
Wat hier eerstens arbeid bespaart, is dat ik met "val" een string naar een enumeratie kan converteren, in C moet je daar met de hand code voor kloppen. Maar omdat de betreffende kleur daarna in een variabele zit die alleen maar de juiste waarden kan bevatten, kan ik ook simpelweg geen verkeerde data aanvaarden.

Niets verhindert je om bugvrije code in C te schrijven, maar het is handwerk. Veilige code gaat dan ook om meer dan alleen geheugenbugs. Exploits hebben vaak te maken met dat iemand door middel van ongewenste data de code andere afslagen laat volgen dan de programmeur in gedachten had. Door te zorgen dat je vroeg in het proces maximale controle hebt, kun je problemen sterk verminderen.

Noch Pascal, noch Rust zijn immuun omdat ze als praktijktalen die voor systeemprogrammering gebruikt worden alle mechanismen hebben om alsnog stoute dingen te doen, maar als ik maar een fractie van de code hoef te onderzoeken op problemen, is het veel makkelijker om veiligheid af te dwingen.

Ik ben van mening dat Rust in de Linuxkernel wel degelijk de kans op bugs kan verminderen in de modules daar waar het gebruikt wordt. Dat het effect kleiner is dan als de hele kernel geconverteerd wordt, spreekt voor zich.
Maar een functie zoals val komt dan ook van een hogere programmeertaal. C en Rust moeten dit beiden met code doen omdat dit lagere talen zijn, bedoeld voor snelheid. Rust is juist bedoeld als de veiligheden van C++ met C semantiek.

Specifiek in Rust kun je zoiets niet doen zonder unsafe te gebruiken, of een trage implementatie (lees byte per byte totdat je een nul karakter tegenkomt, reserveer dan geheugen, etc). De C versie moet je als je veilig wilt zijn, eerst controleren, dan converteren, wat Pascal in de achtergrond “voor de developer” doet.

De bug in dit geval was het verwijderen van een object uit een linked list, klinkt simpel maar de basis implementatie van een linked list kan dit in Rust niet zonder unsafe gedaan worden (je moet geheugen aanpassen zonder de rest van de code te laten weten dat je geheugen aanpast). Dit staat gewoon als een nota in de documentatie, of je moet een trage implementatie gebruiken dat o.a. Python of JavaScript gebruikt en veel geheugen reserveren zelfs voor kleine structuren en de hele geheugenblok kopieëren naar ander geheugen (of andere trucs, Python doet het slimmer, maar nog steeds traag), en dan moet iedereen (ook de hardware) akkoord gaan met “jouw” implementatie en reference counting en adresseringen van linked lists.

[Reactie gewijzigd door Guru Evi op 19 december 2025 23:44]

Dat klinkt mij als muziek als muziek in de oren, want in Pascal programmeren voelt voor mij ook als in hogere taal programmeren dan als ik in C programmeer. Toch zit je net zo dicht op de hardware. C is in praktijk wel sneller omdat compilers als GCC meer optimalisaties hebben dan Free Pascal.

Een belangrijk onderscheid tussen Pascal en Rust is dat Rust controle probeert te houden op dynamisch gealloceerd geheugen, terwijl Pascal dat niet doet. Een gelinkte lijst kan dan ook gewoon gemanipuleerd worden zoals in C, maar dat betekent dus ook dat je een gelinkte lijst als programmeur kun vernaggelen (vicieuze cirkels in de lijst aanleggen bijvoorbeeld). Op dat punt gaat Rust gewoon een stap verder dan Pascal.
Een hogere programmeertaal zoals Pascal of Rust gaat ALTIJD trager zijn, ofwel moet je compile-time en/of runtime checks doen om bepaalde garanties te kunnen geven. Dat gaat niet over optimalisaties, Pascal is een taal voor relatief kleine applicaties, niet voor grote projecten, en Pascal en Rust hebben grotendeels gelijkaardig taalontwerp qua veiligheid.

Maar er is een reden dat mensen na 50 jaar of zo Pascal nog steeds weinig gebruiken, mensen willen dit niet geloven, maar het blijft waarheid, het is niet gemakkelijk te leren, het heeft restricties (die je optioneel kunt wegsmijten, maar dan houd je gewoon een kloon van C over), je kunt geen gedeeltelijke compilaties en binary-only interfaces maken, je kan geen type casten (zonder unsafe), elk programma heeft een gecentraliseerde hiërarchie nodig (reference counters, mutex, …) en de ‘basis’ van beide talen is een beetje een rommeltje, in Pascal is er geen ‘standaard’ library, het is afhankelijk van implementatie, in Rust ben je afhankelijk van LibC (dus waarom gebruiken we Rust?) en alles die verder gaat en veilige implementaties biedt zit in Cargo, maar dan trek je continu nieuwe code van het openbaar Internet waar, net als NPM waarschijnlijk potentieel gevaarlijke dingen zitten.

[Reactie gewijzigd door Guru Evi op 20 december 2025 02:47]

Ik acht Pascal veel beter geschikt voor grote projecten als C, omdat de voordelen in grote applicaties naar voren komen. De Free Pascal-compiler is in Pascal geschreven en de compiler zelf is ongeveer 30MB aan broncode, het is een enorme berg code. Ik durf met vrij grote zekerheid te zeggen dat er bijvoorbeeld geen geheugenlekken in zitten, omdat de heapchecker die zou vinden, de kans dat iets door de mazen glipt als de compiler 's nachts met alle checks aan zichzelf compileert en de testsuite doorloopt is klein. Garanderen dat een project van 30 MB aan broncode in C, of C++ geen geheugenlekken heeft, ik zie niet 1-2-3 hoe ik dat aan zou moeten pakken...

Wat betreft gescheiden compilatie zijn Pascal-units superieur boven de include-bestanden van C.

Dan de kwestie runtime-checks: Zowel Pascal als Rust hebben doen aan range-checking, een array buiten zijn grenzen indexeren leidt tot een runtime-error. Ook hier is er een verschil in aanpak tussen Pascal en Rust: In Pascal zijn range-checks een optie om tijdens het ontwikkelen van je code ingeschakeld te hebben, zodra je je programma bug-vrij acht zal je range-checks uitschakelen voor productie. Rust is ambitieuzer en gaat er vanuit dat een programma nimmer bugvrij zal zijn en zal (tenzij unsafe) te allen tijde range-checks uitvoeren en vertrouwt op de compiler deze zoveel mogelijk weg te optimaliseren.

Wat betreft optimalities, code als dit kon bij naïeve compilers als Turbo Pascal tot grote overhead leiden:
for i:=low(c) to high(c) do
    c[i]:=a[i]+b[i];
... want als je iedere array-indexering gaat rangechecken, dat wordt de lus vele malen trager (een orde) dan zonder rangechecks. De compiler kan evenwel vrij makkelijk bewijzen dat in een lus als deze geen fouten kunnen optreden, de overhead in Free Pascal voor een lus als deze is dan ook nul, zelfs al staan range-checks aan. (Benchmarks laten zien dat GCC nog steeds grofweg dubbel zo snel is in een lus als deze, maar dat is omdat de compiler beter is in het vectoriseren van de lus.)

Omdat range-checks in Rust niet uitgezet kunnen worden, is de taal sterk afhankelijk van dit soort optimalisaties, maar de compiler is er best wel goed in, ze zijn op dit punt verder dan wij met Free Pascal zijn.
En hier zie ik al snel een probleem: in een multithreaded programma kan de data in de lus/array wel degelijk veranderen waardoor mutex nodig zijn.

Waarom worden die in Pascal of Rust zoveel maal trager? Als je de structuur van het geheugen kent en de architectuur van het geheugen echter is een range check maar 1 CPU cycle (een pointer vergelijking), echter Pascal of Rust stelt dat je geheugen niet extern aangepast kunnen worden, wat in hardware nooit aangenomen mag worden.

Het vectoriseren van de lus kan in principe in Pascal ook geïmplementeerd worden, zoiets als for (…) { a[i] = a[i] + b[i] } en de hele loop is 1 SIMD instructie, echter in Pascal/Rust is dit onmogelijk, omdat je altijd moet zorgen dat a+b terug in a past en geen problemen met b veroorzaakt, in C kan de compiler dat voor jouw ook aanwijzen en veilig doen, net als Rust, maar er is geen garantie dat je programma niet crasht of de data verkeerd is als je die dingen nalaat. Dat is wat Wirth in Pascal juist wou vermijden, het is een hogere taal voor wiskundigen.

[Reactie gewijzigd door Guru Evi op 20 december 2025 14:10]

Ik kan je niet volgen: "altijd moet zorgen dat a+b terug in a past"

Waarom? De expressie a[i]+b[i] heeft hetzelfde type als a[i] en dus is er geen hindernis voor vectorisatie?
Omdat registers niet noodzakelijk de grootte van je variabele omvatten. De taal vangt dit af in hogere talen, niet in C of Rust, maar als je 2 integers samenvoegt, krijg je een getal dat mogelijk groter is dan wat terug in de originele type past, maar mogelijk past het wel in het register.

Dus als a een uint8 dichtbij het maximum (allemaal 1s) en je voegt b toe, en dat overflows, wat is het resultaat na een SIMD instructie die enkel maar over 64 bit resultaten bezit?

In C kun je dus “zeuren” en je verplaatst een 64 bit variabele naar het geheugen, maar beschouwt het in code als een 8 of 16 bit nummer, in assembler worden dit 2-3 instructies. Mogelijk heb je een fout als je niet verwacht dat de nummers zo groot worden, maar mogelijk weet je dat en handel je dat elders af.

Pascal en Rust (zonder unsafe) kennen dit niet want je moet de variabele buiten het uint8 resultaat gaan bekijken want het verwacht dat types niet veranderen. Dus kun je ofwel nooit een SIMD instructie gebruiken (behalve als je kunt garanderen dat de variabele nooit overflows), of je moet veel grotere variabelen gebruiken (8-bit variabelen zijn intern altijd 64 bit zoals Python dat doet) of je moet de resultaten een per een kopiëren naar geheugen en controleren, de 3 instructies voor alle resultaten te verplaatsen van CPU naar RAM in C worden 5-6 instructies per resultaat in de matrix wat snel oploopt.

[Reactie gewijzigd door Guru Evi op 20 december 2025 20:22]

Dus als a een uint8 dichtbij het maximum (allemaal 1s) en je voegt b toe, en dat overflows, wat is het resultaat na een SIMD instructie die enkel maar over 64 bit resultaten bezit?
Ik citeer uit Jensen & Wirth. Een integerbewerking dient correct te zijn indien:

abs(a op b ) <= maxint
abs(a) <= maxint
abs(b) <= maxint

Kortom, volgens de originele specificatie is het resultaat in zo'n geval ongedefinieerd. Een compiler mag daarom vectoriseren zonder de specificatie te schenden. Iedere fatsoenlijke compiler kan runtimechecks genereren, maar de specificatie verplicht dat nergens, die verplicht enkel wat er tijdens compilatie gecontroleerd moet worden. Er zijn twee soorten checks die hier relevant zijn: Range-checking en overflow-checking.
var a:integer;
      b:0..9;
      c:0..99;
Indien noch range-checks noch overflow-checking aan staat zijn er geen runtime-checks, de compiler controleert alleen de typen tijdens compilatie.

Nu de situatie als range-checking aan staat. Bij:
a:=b+c;
... geldt dat b en c een subrangetype van integer zijn. Bij een expressie tussen twee verschillende subrangetypen van hetzelfde "moedertype" is het resultaat van de expressie het "moedertype". b+c heeft dus als type integer, en wordt aan een variabele van het type integer toegewezen. Typen zijn identiek, dus de compiler genereert geen range-check. Bij:

b:=c;

... wordt een subrange aan een andere subrange toegwezen. Type is niet gelijk, dus er vindt een range-check tijdens runtime plaats.

Range-checking staat vectorisatie nog steeds niet in de weg. Maar waar je gelijk hebt, is dat vectorisatie problematisch gaat worden als ook overflow-checking ingeschakeld gaat worden. Bij overflowchecking moet de compiler controleren of iedere rekenkundige bewerking tot een overflow leidt.

Bij:
a:=b+c;
.... is er nog niet zoveel aan de hand, want b+c is bewijsbaar kleiner dan high(integer), maar bij:
c:=c+b;
... is er een overflow-check tijdens runtime nodig.

Is dat in praktijk een probleem? Niet echt, want zowel range-checking als overflow-checking zijn hulpmiddelen om te gebruiken tijdens het ontwikkelen van je software. Zodra je je release-versie gaat bouwen, wil je maximale performance en zet je de runtime-checks uit.

[Reactie gewijzigd door dmantione op 20 december 2025 21:30]

Opnieuw, interessant voor hogere talen. Op kernel niveau is casten vaak nodig (int to string voor ASCII bijvoorbeeld). Je hebt geen luxe zoals “ongedefinieerd” er staat altijd een resultaat en die checks uitschakelen werkt totdat je met user of netwerk input te maken krijgt, dus moet je die checks nagenoeg altijd inlaten. Wie zegt dat je nooit een getal zoals 65535 gaat krijgen.
Ik weet niet of je volledig op runtime-checks wilt vertrouwen om gebruikers- of netwerkvalidatie te doen, terug naar het eerdere codefragment:
   val(paramstr(2),kleur,code);
    if code<>0 then goto error;
Dat if-statement staat er niet zonder reden... we willen een foutconditie netjes afhandelen, niet zorgen dat de boel er met een rangecheck uitknalt.

Maar... als je volledig op de runtime-checks wilt vertrouwen voor invoervalidatie, kan zelfs dat, want we hebben tegenwoordig exception handling; Je zou iets kunnen doen als:
{$push} {Compilerdirectives bewaren.}
{$R+,Q+} {Rangecheck + overflowchecks tijdelijk aan.}
try
{Hier je code waar te allen tijde runtime checks moeten plaatsvinden.}
except
{Fout opgetreden.}
end;
{$pop} {Herstel compileropties.}
Dan heb je dus een klein stukje code waar ze altijd aan staan en kun je voor de rest van je programma de boel nog steeds uitzetten zodra je gaat releasen.

Omgekeerd komt trouwens vaker voor: In low-level code is het wel een gewenst dat een integer een overflow heeft, dus met enige regelmaat zul je met een dergelijke constructie lokaal uitschakelen.

Er is wel wat ervaring met besturingssystemen geschreven in Pascal. Met een aantal van die projecten heb ik contact gehad. Afgezien van MacOS Classic heeft er nog geen eentje de wereld veroverd, maar technisch is er niet zoveel reden waarom een besturingssyteem in C geschreven moet worden.
C standaard is cleaner en leaner en full cross platform en dicht op assembler en dus ASM meer voorspelbaar.

C++ is bloated er is elke release hoop bijgekomen en ivm legacy code heel weinig weg. Dus je heb dozijn old way en er komen nieuwe bij. Dus guidline schuift. En als je nu C++ library code bekijkt is enorm bloated.

Om moderne C++ 2x te doorgronden moet jaren intensief C++ programmeren onder goede begeleiding van mentor die safety en moderne safe practices toepast. C is daar in tegen puur .

Kijk je naar hoe dingen in STD library geïmplementeerd is. Is vanilla C++ zoiets als basic engels en wat ze in library header doen chinees.

Ik vind C++ nogal bloated programmeer taal. War je core code decoreert met hoop keywords en dan bloated template er boven op.

En daarmee zijn er miljoen redelijke tot goede intermediate C++ programmeurs , maar paar 1000 C++ guru’s. Omdat C++ per gen complexer is geworden.

Voor mij casual periodiek wat C++ hobby programmeren krijg je die routine van die complexiteit te doorgronden niet. Ik hou de nieuwe standaard in de gaten en pas de new way to in mijn meer C like gebruik van C++.

Ik denk dat de kracht van C hier in ligt het ultieme crossplatform. En daarmee kan makkelijker andere platformen ondersteunen X86 IA32 AMD64 IA64 ARM risc-V.

Mac linux windows verschillen al in C++ 20 /23 support per feature.

Zo is er verschil in module support
Behalve in een academische omgeving? Heb je wel eens van Java en JavaScript gehoord toevallig? Beide kunnen niet direct tegen hardware praten.
Ooit al eens van JavaOS/JavaStations gehoord?
Je snapt zelf ook dat je daar totaal geen punt mee maakt hé?

Jouw opmerking "Een taal die niet tegen de hardware kan praten heeft geen waarde behalve in een academische omgeving" slaat gewoon nergens op. Als je het over talen hebt om een OS in te schrijven dan klopt het, maar dat is maar een fractie van de totale hoeveelheid software die leeft.
De meeste talen kunnen tegen hardware praten. JavaOS was een kernel in Java. Rust kan per definitie geen OS schrijven zonder unsafe (C) te gebruiken. De taal (zonder unsafe) is niet eens Turing kompleet omdat de compiler in een oneindige loop zou terecht komen om de oneindige band van een Turing machine te checken.
Sorry dan begreep ik je verkeerd. Maar dan klopt het toch niet, want JavaOS had een klein laagje kernel in C/Assembly. En voor JavaScript gaat het al helemaal niet op. Mijn punt was dat een taal echt niet rechtstreeks hardware hoeft aan te spreken om niet alleen academisch nuttig te zijn.
JavaOS had een native micro kernel, specifieke platform assembly die de JVM boot. De AI zegt iets van C/C++ maar dat zijn latere Java-gebaseerde OS projecten (open source) gebaseerd of andere kernels.

Het probleem met Rust is de kwalificatie dat het een veilige vervanger voor C is, mijn punt is dat het niet eens Turing compleet is zonder unsafe, dus het kan geen OS implementeren, het kan geen andere talen implementeren, er is dus geen plaats voor Rust in de Linux kernel omdat je met unsafe evengoed in C++ aan het schrijven kunt.
"Blijkbaar was de code specifiek in een linked list, om een object te verwijderen uit een linked list is volstrekt niet unsafe nodig, behalve dan natuurlijk dat de “veilige code” net zo snel als Ruby of Python wordt on runtime checks en global locks toe te passen."

Een linked list kan denk ik op zich met "veilige" code worden geschreven, zolang die lijst "eigenaar" is van die data. Anders moeten runtime checks in de vorm van reference counting gebeuren. Aangezien de oorspronkelijke bug multi-threaded code betreft moet hiervoor een Arc (Atomic Reference Counter) worden gebruikt, en ik weet niet eens of die er zijn op kernelniveau.

Bovendien zitten er achter de schermen van Rust denk ik in een heleboel data structuren "unsafe" code. Het verschil is dat die code is gecheckt zodat het wel veilige code is. Zelfs Box, een simpele, veilige en basale datastructuur moet "unsafe" code bevatten om bepaalde functionaliteit mogelijk te maken. Zie regel 780:

https://doc.rust-lang.org/stable/src/alloc/boxed.rs.html#780

Lijn 781 is unsafe, maar omdat de checks in de vorige regels code gedaan zijn is de functie nog steeds veilig. Regel 243 die naar externe code verwijst en wordt gebruikt voor de new functie in 261 wordt ook niet door de compiler gecontroleerd, aangezien het syscalls naar het besturingssysteem betreft die per systeem verschillen en waarvan de compiler niet direct kan weten wat het doet. (Het LLVM deel van de compiler handelt die code af denk ik.)

[Reactie gewijzigd door rjberg op 19 december 2025 09:44]

Het probleem met unsafe is management van life time en dus allocatie beheer en pointer valid te houden.

Bepaalde talen hebben hiervoor garbage collectors waar dit managen wordt weg genomen. Maar deze general purpouse aanpak past niet altijd bij jouw soort van applicatie zoals games. Of welk andere realtime app. In C C++ heb je best practices. Wat elke programmeur zich eigen moet maken. Maar de legacy raw pointer blijft beschikbaar. Sommige in de C++ committee willen ook default GC in C++ met opt out voor zelf managen.

Link list werkte goed voor game programming patroon. Toen CPU 25Mhz 80386 waren en er heap limiet was en zuinig met ram moet zijn.

Dus in die tijd malloc of new je de next node. En verwijderen draai je de allocatie terug.

Pointer jagen was in die tijd dat ram stick net zo snel waren als de real klok en sipp of dimm socket in die tijd dicht bij de cpu is. In tegen stelling in 5ghz tijd perk waar laag real geklokte ddr5 ver van de CPU is.

In heden waar performance afhankelijk is van goed efficient multithreaden en cache utilisatie en prefetcher.

Wat zwaar rust op andere keuze van algoritmes die multithread vriendelijker zijn en data in containers .

GC en object lifetime hoeft feen probleem te zijn. In heden is allocatie in critical loop iets wat je moet mijden.

Dus los staande new in game loop. Mijd je. Pre allocatie mijd dit plus werkt allocatie fragmentatie tegen.

GC hoeft dus geen probleem te zijn als array van objecten alive houd. Met boolean in use of free to use.

C++ std::vector zal bij resize zich opnieuw alloceren. Dus in dat geval zou je pointer interface juist mijden en de index methode prefereren. En als vervanger voor stack based std::array voor in heap. Zou ik voor fixed size use gaan.

Zelf ben ik verdiepen in multithreaded. En ben zelf tot hypothese gekomen dat job base threadpool beste is tov conventionele ,maar nog steed iets dat niet cache en prefetch vriendelijk is. Dus dat zou veel beter kunnen. Ik kijk dan naar de meer data oriented aanpak. In pure vorm ga ook minder met pointer maar meer met index gebruiken.
En linked list op een plek waar de rust code tegen oude c code praat.

Het voordeel van rust is dat in die code in tegenstelling tot c 99% van de situaties zonder unsafe kan. In tegenstelling tot c waar alles in principe altijd unsafe is.
Enkel dan omdat Rust de functies niet heeft om multithreaded lists te benaderen. En dan maakt dit een taal zoals Python, zet een global lock, doe alles single threaded.
Of misschien omdat 99% van de kernel voorlopig nog in C is.
Nope, dit was allemaal in de Rust code, de unsafe was niet voor syscalls naar de kernel (dat wel safe gedaan kan worden).

De unsafe was nodig om de transactie te laten draaien zonder na te denken over de mogelijke condities waar de code verkeerd kan gaan (wie doet er vandaag multithreading?), of afgewaaid als "dat gaat nooit verkeerd gaan", wat inderdaad waar is, zolang alle gebruikers zich netjes gedragen gaat er niets verkeerd gaan, de code draait, er is een race conditie en eventueel wordt dat afgewikkelt.

Het probleem is dat als je dit veilig wilt doen, dit niet in Rust gedaan kan worden zonder te doen wat Python doet - lock, kopieer, sorteer, verplaats het geheugenadres voor alle deelnemers, unlock. En dat is relatief traag.

Ipv daarvan deden ze lock, kopieer, unlock, sorteer, verplaats het geheugen, maar in een multi-threaded omgeving heb je geen garantie wat er gebeurt na een unlock. In veilige C is het gewoon lock - sorteer op de stack - unlock, maar in Rust (of Python) kun je geheugen niet zomaar aanpassen.

[Reactie gewijzigd door Guru Evi op 19 december 2025 22:20]

Er zijn goede redenen om geheugen niet zomaar te kunnen aanpassen.

Dat kan in een managed language als .net ook niet. Nu is rust geen managed language, maar de redenen zijn veelal hetzelfde. Veiligheid.

Je verliest en klein beetje performance. Dat is op kernel niveau wat belangrijker dan op desktop of server niveau. Maar toch is met de hardware van vandaag en beetje performance verlies voor betere code het wel waard denk ik.

Type checking in Python is continue, maar bij rust is het de compiler die het werk doet. Er is geen garbage collector of zoiets. Dus de performance zou bij runtime na compilatie eigenlijk net zo hoog moeten zijn als voor C. Maar rust is een relatief jonge taal. Mogelijk missen er nog wat optimalisaties.

Maar goed rust is ook niet perfect en in elke taal kan je fouten maken.
Wel ja, en dat is nu juist het probleem. Rust aanhangers stellen dat Rust een C vervanger is, geen .NET, want dan kun je gewoon C# of ObjC of C++ gebruiken. Je kunt inderdaad alles veilig doen, echter dan verlies je de snelheid van C en dat is in veel gevallen gewoon onaanvaardbaar. Veilige Rust is dan ook stukken trager dan veilige C, er is geen toegevoegde waarde.
Unsafe is vaak nodig als interface met C. Dat komt omdat zodra je C code aanroept uit bijvoorbeeld een bibliotheek de compiler niet kan zien wat je doet.

Unsafe code kan op zich nog steeds veilig zijn, maar is niet gegarandeerd door de compiler.

https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html

Verder betekent het ownership systeem van Rust dat veel datastructuren zoals gebruikt in de Linux kernel niet makkelijk in Rust kunnen worden vertaald. Zodra meerdere pointers naar dezelfde data wijzen heb je of een real-time reference counter nodig (overhead), of een manier op compile tijd om een pointer de eigenaar te maken, en die moet langer leven dan de andere pointers.
Dit valt op te lossen door af te spreken wie de bewerking voor de ander doet (semaphore/mutex).
Semaforen zijn ontzettend krachtig en door wiskunde pionier Edsger Dijkstra bedacht, al noemde hij het nog "seinpalen". Zijn EWD74 document van begin 60-er jaren beschrijft het heel mooi. (beter leesbare versie hier)
Race condition houd in dat shared data waar minstens 1 write is en dat 2 threads wachten op elkaar.

Dit gaat dus om multithread savety en correctheid.
Nee. Als threads wachten is er geen race conditie. En als twee threads wachten op elkaar is het een deadlock.
Nee, dat noem je een deadlock, dat ze allebei "oneindig" op elkaar wachten. Maar dan heb je dus wel een mechanisme gebruikt om thread safe data te benaderen.

[Reactie gewijzigd door jDuke op 19 december 2025 10:38]

Een voorbeeld van een race condition is een bijvoorbeeld een list met een aantal items. Vervolgens zijn er twee threads welke controleren of een object bestaat in de list en zo niet deze toevoegen.

met een lock { if not exist { add item }} block voorkom je dit al, maar dan heb je wel altijd een context sync item welke de code aanzienlijk kan vertragen.

Daarom past men vaker de check-lock-check methode toe. Beide threads kunnen nog steeds door de eerste check heen komen, maar slechts een van de twee krijgt de lock en de ander moet wachten. Op het moment dat thead #1 het object heeft toegevoegd gaat de lock out of scope en krijgt thread #2 toegang tot de lock en ziet dan bij de tweede check dat het item toch al bestaat.

Nu zal een double add wel voor een error, maar niet een memory corruption zorgen. Echter is het ook mogelijk dat thread #1 een object verwijderd uit de list en een free doet en thread #2 hierop juist een actie probeert uit te voeren op dat object en dan krijg je dus een use-after-free.

Currency issues zijn en blijven altijd lastig en al helemaal op kernel niveau. Je wilt zoveel mogelijk locks voorkomen en daarom verzind men vaak 'slimme' trucjes. Vaak is dan die refactoring op zich wel goed, maar later maakt iemand nog een andere verandering en dan kan er ineens een race condition ontstaan.

Ik doe development in Rust, C(++) en C#, maar ik blijf heel erg ver weg van de kernel code.
Heb ik het verleden (25 jaar geleden) wel aan KDE gewerkt, maar die kernel code (2.3.x) was abracadabra voor mij en dan zat ik alleen nog maar in de ipchains (voorloper van iptables) code te wroeten...
Je hebt altijd plekken waar dingen gedeeld moeten worden. Vaak weliswaar n-readers (parallel) en 1 writer (de owner), maar dat soort zaken komt altijd met een prijs (locks/mutex).

Ik ken Rust verder onvoldoende, maar als de taal met de kernel interacteert (of dat nu C, C++ of ook Rust delen zijn), dan heb je gedeelde data (of je moet overal een copy van maken, waarmee je andere problemen krijgt, nl. de copy is direct na de copy geen actuele data meer). Als gedeelde data actueel moet zijn, dan heb je daarvoor extra zaken nodig, die CPU ticks kosten.

In C++ heb je ook gewoon shared pointers etc. Zeker in de laatste versies van de standaarden zijn - voorheen zeer specifieke platform zaken, zoals bijv. de verschillen tussen Windows threads en Linux pthreads) meer geharmoniseerd en is ook parallel processing meer onderdeel van de taal geworden. Het is niet zo - wat een ander ook schreef - dat een taal met unsafe mogelijkheden (dat lijjkt me een correctere voorstelling dan een unsafe taal) per definitie unsafe is. Idem is een safe taal (waar de syntax en concept al meer helpt om safe te werken) inherent safe (al is, dankzij het doel van de ontwerpers, lastiger om unsafe te zijn). Je had voorheen weinig andere mogelijkheden dan 'unsafe' te werken (in C en C++) en je kunt niet altijd over naar een andere taal (ivm codebase, de benodigde investering).

Rust is van veel later datum als C en C++ en het is niet meer dan logisch dat daar voortschrijdend inzicht in verwerkt is. Daarmee is het utopie dat - ondanks de mogelijke meerwaarde van de taal - alles en-mass over zal gaan. Je loopt best kans dat er weer nieuwere talen komen, die manco's (iedere taal heeft die) van Rust opgelost worden. Je codebase en je omvang van het team en het beschikbare budget bepalen of gebruik van een nieuwe taal zal plaatsvinden. Waar tijd vaak geld is, zal overstap op iets nieuws goed onderbouwd moeten zijn, voordat dit plaatsvindt. Initieel zal (een deel van) het team programmeurs ook moeten investeren in kennis opbouw.

En er is niets nieuws onder de zon: ook in een nieuwe taal zullen CVE's ontdekt worden. De programmeur en de gebruiker maakt fouten, c.q. komen er nieuwe use-cases, waardoor code op een andere manier gebruikt wordt. In 1980 had niemand kunnen bedenken dat anno nu zo'n beetje ieder systeem aan internet (kan) hangen. En ook niet dat er script-kiddies (zonder kennis, maar met tools) hacks uitvoeren. CVE's zijn ook tijd/context gebonden en geen mens kan alles voorzien. Zolang er tijd en/of geldsdruk zit op het afronden van (programmeer)taken, zal code nooit de staat van perfectie bereiken (met inperfecte mensen).
Een race condition heeft helemaal niet perse iets met geheugen issues te maken. Google het maar.
M'Linux
In een video op LTT laatst zei hij Fedora te gebruiken.
edit:
Video: YouTube: Building the PERFECT Linux PC with Linus Torvalds
Op 45:00 vraagt Linus aan Linus "Fedora is still your distro of choice?" waarna Linus wat verteld over waarom.

[Reactie gewijzigd door Heedless op 19 december 2025 10:09]

Gaat dit over de YouTuber of de bedenker van linux
Tja, Linus kwam bij Linus langs dus die grap maakten ze zelf.
Linus bouwde een PC voor Linus en daarop werd Fedora Gnome geinstalleerd.
Ja, ik geloof dat ie Rust kent, maar niet erg goed en laat dat daarom liever aan anderen over.
Ik meen dat hij dit vooral aan anderen overal laat. Dacht uit een interview begrepen te hebben dat hij het wel eens tegenkomt in code reviews maar er verder niet actief mee bezig is. Het is en blijft natuurlijk een C mastermind :).
Nee hij spreekt engels
Fins lijkt me logischer….
Linus is een Zweedstalige Fin, een linguïstische minderheid van +/- 10% (afhankelijk van de bron), maar het is er wel een officiële taal.
Iedereen roept maar rust is beter, rust is veiliger. Wat ik wel eens zou willen weten is hoeveel CVE's er toegekend zijn aan C code die de laatste 3 jaar geschreven is.

Tooling is er namelijk ook enorm op vooruit gegaan. Fuzzing, chaos engineering zijn allemaal gewoon goed geworden. Linters en static checkers vangen al enorm veel fouten af voor ze gecommit worden.

Ik zou alleen niet weten waar je zoiets zou kunnen opzoeken.
Het lijkt ook een vrij grove stap om maar een hele andere taal te gaan gebruiken. Ik zie meer heil in de ontwikkeling van FIL-C om bestaande C code beter veilig te kunnen maken zodat je wel kunt blijven leunen op de decennia aan ervaring van C programmeurs om fouten in de code te kunnen herkennen.

Puntje bij paaltje is Rust alleen rust-gevend als alle code Rust is. Rust introduceren in een zee van C... dapper hoor. We moeten maar gaan zien hoe vaak Low Level volgend jaar iets mag gaan uitleggen wat er 100% veilig uitziet maar exact het tegengestelde blijkt te zijn.
In de kernel (in het "C" deel) wordt tegenwoordig alles via "devm" wrappers geregeld. Daarmee koppel je de ownership van geheugen, clocks, GPIOs en dat soort dingen aan je device. Als je device wordt verwijderd, dan worden al die objecten ook automatisch opgeruimd. Eigenlijk kun je stellen dat de Linux kernel gewoon een RAII pattern gebruikt. De meeste moderne drivers hebben geen "remove" callback, omdat alles al via devm geregeld is.

Ondanks dat het allemaal plat "C" is, is vrijwel alle code in de kernel object oriented. Omdat de taal niet native classes ondersteunt (zoals C++) worden de method tables gewoon uitgeschreven. Het eindeffect is wel hetzelfde. Ook zijn er bijvoorbeeld scoped mutexen,

Een heel praktisch voordeel aan dat de kernel geen C++ gebruikt is wel dat compileren dan niet zo lang duurt. Een kernel compileren voor een ARM64 duurt pakweg 2 minuten. Vergelijk dat met het compileren van bijvoorbeeld QtBase (heel veel C++) wat ongeveer 45 minuten duurt op dezelfde machine.
Het is wel grappig en ironisch, omdat Rust juist bedacht is om zulke fouten te voorkomen. En dan zit het er toch in! En nu komt men massaal met de meme die je anders ook zou krijgen:
Herschrijf het in rust, dan heb je dit probleem niet.
:Y)

Een uitleg over de bug.
Ach tis ook beetje de reden net zoals alles wat polariseert. Dat nu elk stukje code in Rust in de kernel onder een 100x vergrootglas ligt. Omdat er zoveel tegenstanders zijn vooral mensen die techniek en politiek graag mengen.

Natuurlijk kan Rust code nog steeds bugs en problemen bevatten. De kans erop is alleen een stuk kleiner. Maar niet 0%. En niemand beweert dat behalve mensen die er tegen zijn beweren dat de andere kant het beweert. Het zeg maar in de mond legt.

[Reactie gewijzigd door Immutable op 19 december 2025 02:07]

De kans op specifieke gevaarlijke bugs in Rust is kleiner. De kans op bugs in het algemeen lijkt me niet veel kleiner. Misschien enigszins ten opzichte van C/in de context van Systems programming maar ik schat dat dat verschil niet gigantisch zal zijn. Ten opzichte van andere soorten projecten waarin performance van een regel code al minder uitmaakt ten opzichte van I/O zoals grote online backends die al geschreven zijn in memory-safe talen zal Rust niet opeens minder bugs tot gevolg hebben.
Je hebt deels gelijk. Maar het dekt niet 100% de lading. Het is niet 1 op 1. Rust zorgt wel degelijk door strenge regels dat daardoor de programmeur gedwongen word om bijvoorbeelde bepaalde zaken te implementeren en niet te vergeten. Het gaat er hierbij om dat de programmeur zoals jij en ik dus bepaalde zaken expliciet moet afhandelen voordat de compiler zegt: OK zonder short cuts. Dit zorgt daarbij voor een verhoogde kans op goed werkende code/logic vanuit design onder dwang.

Bijvoorbeeld, rust compileert niet bij de volgende zaken. Maar C wel:

Buiten memory safety om heb je namelijk nog veel meer dingen zoals:

Concurrency
  • Data races (twee threads schrijven naar dezelfde data)
  • Mutable data delen tussen threads zonder synchronisatie
Type Safety
  • Impliciete lossy conversies (bv. int naar char)
  • Void pointer casten naar willekeurig type
  • Unions zonder discriminant (type confusion)
  • Format string mismatch (printf("%d", een_string))
Control Flow / Logica
  • switch zonder alle enum-cases af te handelen
  • Fallthrough in switch zonder expliciete break
  • Return value negeren (bv. foutcode van read())
  • Ongeïnitialiseerde variabele gebruiken
  • Functie zonder return statement terwijl dat wel moet
Numeriek
  • Signed integer overflow (undefined behavior in C)
  • Impliciete integer truncatie
Strings
  • Null terminator vergeten
  • String buffer te klein voor inhoud + terminator
Er is een reden waarom Rust al 80% van MISRA C dekt. En dat is geen grap, en dan SIL4 veel makkelijker te bereiken is met Rust dan C of C++.
Dat is ook de reden waarom alle kritische apparaten en software over gaan op Rust. Straks zal alle software in het leger, het ziekenhuis. Kerncentrales over gaan op Rust. Dat is een no-brainer. Gewoon simpele logica.

[Reactie gewijzigd door Immutable op 20 december 2025 11:57]

Rust enforced good practice. Maar dit houd in dat legacy C C++ moet omzetten naar RUST.

De kracht van C en C++ is legacy. Wat ooit werkte doet nu nog. Maar good practice wordt niet enforced.

Daar heb je code guidlines en nieuwste C++ 23 features voor. En performance wordt niet opgeoffert aan safety. Daar is safety verschoven naar de caller. O.a. bijvoorbeeld Concepts.

Safety is dit dat compiler mekkert als foutieve argument type worden gepast in functie cq template.

Maar je kan dus gewoon wild gaan met C style pointer magic en old way zoals in C.
Niemand zegt dat je goedwerkende C en C++ code moet omzetten. Zeker als de code heel oud is en battle tested is. Ik zou dat nooit in de mond durven nemen. Greenfield is het wel 100% zeker dat je gewoon start met Rust. Zeker in zeer belangrijke code. Ik zou geen reden kunnen bedenken waarom je in een greenfield project niet met Rust zou beginnen.

Als ik jou was zou ik het MISRA C document eens doorlezen. Elke C/C++ programmeur zou dat moeten doen. En dan kijken hoe Rust werkt... Ik daag elke C/C++ programmeur uit dat te doen.
Als ik jou aanneem om code te schrijven voor een kerncentrale. Zul je dan ook kritische houding aan nemen? Want het gaat om de veiligheid van veel mensen he?
  • Toyota — Race conditions Incident: Onbedoelde acceleratie, ~89 doden, auto gaf gas zonder input bestuurder.
    Rust preventie: Ownership + Send/Sync traits
  • Toyota — Buffer overflow Incident: Zelfde ramp, spaghetti-code met 7.134 MISRA-C overtredingen.
    Rust preventie: Bounds checking
  • Toyota — 11.000 globale variabelen Incident: NASA noemde code "ononderhoudbaar", enkele bit-flip kon gas geven.
    Rust preventie: Ownership voorkomt gedeelde muteerbare state
  • Boeing MCAS — Geen input validatie Incident: 346 doden in twee crashes, software vertrouwde op één sensor zonder controle.
    Rust preventie: Option/Result dwingen afhandeling af
  • Boeing MCAS — Enkele sensor zonder sanity check Incident: Sensor ging van 12° naar 70° in één seconde, software accepteerde dit blindelings.
    Rust preventie: Type systeem kan redundantie afdwingen
  • Uber — Classificatie state machine bugs Incident: Eerste dodelijke ongeluk met zelfrijdende auto, voetganger niet herkend buiten zebrapad.
    Rust preventie: Uitputtende match op enums
  • Therac-25 — Race condition Incident: Bestralingsmachine gaf 100x te hoge dosis, 3-6 patiënten overleden.
    Rust preventie: Borrow checker voorkomt data races
  • Patriot Missile — Floating-point precisie Incident: 28 soldaten gedood, afrondingsfout na 100 uur uptime veroorzaakte 0,34 seconde afwijking.
    Rust preventie: Expliciete numerieke types, geen impliciete conversie
  • Horizon — Boekhoudkundige rekenfouten Incident: 900+ postmasters onterecht veroordeeld voor diefstal, 13+ zelfmoorden, grootste gerechtelijke dwaling in UK geschiedenis.
    Rust preventie: Sterke typing, geen impliciete conversies
Mensen praten alleen over de "memory safety". Maar dat is maar een KLEIN onderdeeltje wat de taal beter maken zoals je ziet. Zorgt het er voor dat heel veel dingen NIET KUNNEN GEBEUREN. Geforceerd door de compiler. MISRA C, lees het maar eens.
Gelukkig blijkt hier uit dat rust niet beter is dan c, c++, pascal, modula-2 of welke andere te compileren taal dan ook. Om te beginnen gaat het om de functionaliteit die er in/mee gebakken moet worden. Daarnaast is het hoe soepel dat gaat en de kwaliteit van het resultaat.

Of iets beter is, hangt af van je eigen definitie van beter. Neem de hardware van 30 of 40 jaar geleden en zie of de rust-code kan worden gecompileerd voor die hardware en hoe dat dan werkt. Voorlopig ga ik er van uit dat het resultaat een stuk slechter is omdat het veel minder goed vooruit te branden is. Juist omdat er zoveel 'beveiliging' in zit.

Aan de andere kant: Is de hele gnu-toolset al in rust herschreven? En werkt het ook net zo goed en soepel?
De GNU tool chain die ze herschreven hebben in Rust zit momenteel in de onstabiele Ubuntu. Heeft ook een reeks CVEs en werkt volstrekt niet als een drop-in replacement voor de GNU tool chain, dus Ubuntu wordt meer als Sun Solaris die een “gnu” en een Unix smaak had van alle tools zoals awk en grep - de meeste scripts werken op het eerste zicht maar als je het dagelijks gebruikt is het net een beetje anders waardoor de hele zooi van oudere scripts in de soep draait.

Daarnaast is de licentie ook niet langer GPL, ze gebruiken de MIT (een copyright, geen copyleft) licentie, zodat vb RedHat is niet verplicht de code te delen als ze veranderingen maken.

En hoe slecht is het: simpele functies zoals mv, cp en cat werken nog steeds niet zoals de originele tools, mv heeft zelfs geen concept van eigenaarschap/permissies van een bestand - als je een bestand verplaatst worden de bestanden eigendom van de gebruiker, zelfs als de gebruiker toelating heeft om de eigenaar en toelating te behouden/veranderen, een chown/chmod test is gewoon niet aan gedacht.

[Reactie gewijzigd door Guru Evi op 19 december 2025 13:46]

Op zich al mooi dat de rust-gnu-tools in de pen zitten. Wel vreemd dat mv, cp, ln en rm er nog niet zijn, dat is (in c in ieder geval) wel heel simpele code. Dat mv geen concept van permissies en eigenaarschap heeft hoeft niet, het is alleen maar een nieuwe link en een oude opruimen. Of als het over filesystemen heen is, dan een cp en een rm. Voor het basis concept heb ik hier nog het boek van Tanenbaum liggen met de c-code. In mijn beleving/ervaring is jouw beschreven chmod en chown geen standaard onderdeel. Als ik dat nodig heb, dan gebruik ik een archief programma zoals ar, tar of zo iets waarbij ik zeker weet dat de rechten mee gaan.

Dat van die rechten geeft wel aan dat het geen vrije jongens zijn die er aan werken, maar dat er toch een zekere commerciële kracht duwt. Hoe vrij is de taal rust eigenlijk?
In C is dit inderdaad simpele code. mv die enkel maar een inode aanpast is relatief modern filesysteem design en werkt natuurlijk niet over verschillende mountpoints. Daarom dat mv inderdaad cp + chown + chmod + rm doet indien een inode aanpassen niet kan, de midden 2 details dat Rust niet geimplementeerd heeft.

De chmod/chown is wel degelijk een standaard onderdeel van mv ALS je de rechten hebt. Dat betekent dus als je root bent of als je specifiek de rechten hebt om bestanden voor andere mensen aan te maken of aan te passen. Die test gebeurt dan ook met elk bestand als je recursief werkt (en niet gewoon if uid=0). Als gewone gebruiker werkt de mv implementatie in Rust als in C hetzelfde, een omdat de test zegt dat de gebruiker de rechten niet heeft, een omdat het gewoon niet geimplementeerd is. Dat is gewoon toeval, niet een bewuste implementatie.

En daar wringt het nu zich, nieuwe programmeurs (de meeste Rust programmeurs zijn < 30) denken niet aan de grofweg 50 jaar aan verbeteringen en implementatiedetails in tools zoals cp en mv, ze kunnen zich niet inbeelden dat je in 2025 nog steeds van een NFS naar FAT16 systeem wilt gaan, de extra calls naar chmod/chown worden als 'traag' en 'onnodig' beschouwt omdat in 90% van de gevallen heb je dat toch niet nodig.

Het probleem is niet dat ze een alternatieve coreutils willen maken, maar ze zeggen dat het een drop-in replacement is. Drop-in betekent dat zelfs al heb ik scripts geschreven die 'beter' kunnen zijn als ik ze aanpas, ze nog altijd draaien met dezelfde resultaten ongeacht de opinie van de programmeur van de tool.

De Rust taal zelf is niet vrij in de zin dat het copyleft is, het is eigendom van de Rust Foundation, alhoewel een VZW (op papier) is alles MIT-licentie, dus de code is beschikbaar maar niet noodzakelijk open, Rust reserveert de optie dit in te trekken in de toekomst (vb als ze een grote geldschieter krijgen). Je mag bijvoorbeeld het woord rust niet gebruiken als deel van de naam van je project die in Rust gebouwd worden (dus coreutils-rust mag niet), je mag geen vereniging of vergadering van Rust mensen houden zonder toelating en overzicht van de Rust Foundation alsook adoptie van hun idee van open discussie.

[Reactie gewijzigd door Guru Evi op 19 december 2025 21:48]

Een paar correcties: mv is binnen het filesysteem juist geen aanpassing van de inode. Die blijft juist mooi staan. Het is de directory-entry die veranderd. En omdat het aantal niet wijzigt, verandert de inode helemaal niet. Dat is overigens geen nieuwigheid maar al onderdeel van unix systemen sinds het begin zo ongeveer.

Een mv is overigens geen cp + chown +chmod. Het is de cp die de chown en chmod altijd al doet. mv is meer een cp + rm als ze over filesystemen heen werkt. Binnen een filesysteem is het een ln + rm. Uiteindelijk is het in veel gevallen 1 executable met meer namen.

Dat van de chmod en chown als je de rechten hebt klopt inderdaad wel. Het mooie van het unix concept is dat die dus gewoon gebruikt kunnen en mogen worden. Ofwel als externe aanroep (de makkelijkste implementatie) ofwel als mee gelinkte code. De code voor chmod en chown moet beslist niet herschreven worden in andere commando's. Er zijn zelfs shell executables waar deze commando's ingebakken zitten, dan is het helemaal 1 set code.

Dat programmeurs van dit soort tools problemen hebben met gebruikte filesystemen bewijst dat het geen unix/linux programmeurs zijn maar dat ze uit een andere wereld komen. Geef ze een opleiding, richt ze af of stuur ze terug. Een tool zoals cp, mv en ln (dat is meestal 1 executable) werkt niet rechtstreeks op het filesysteem maar doet dat via de libraries en kernel. Dat een filesysteem mogelijk geen rechten of eigenaarschap heeft (zoals FAT) of juist een heel andere set (zoals nfs) wordt door die libarries en kernel afgehandeld.

Dat de commando's en programma's drop-in replacements worden klinkt wel reëel, daar heb je een mooi basis ontwerp. Maar bij die drop-in mag wel degelijk gesteld worden dat het een complete drop-in is of helemaal niet. Geen halfslachtige zaak als wel een cp maar geen chmod of zo iets. Onder de unix-implementaties van toen was het ook ofwel de unix tools of de gnu-tools. En natuurlijk gebruiken ze waar nodig de aanwezige libraries. Die ook deels wel en deels niet onderdeel zijn van de drop-in.

Voor de huidige wereld is het wel reëel als de details rond opties en gebruik zo dicht mogelijk bij de gnu-toolset ligt. In de unix - gnu tijd was er nog wel wat verschil tussen de verschillende unix implementaties (SunOS, Solaris, HP-UX, AIX, Dec-Ultirx) als je naar deze details kijkt. Tegenwoordig is het vooral gnu-linux (de meeste distributies) en bsd (open-, net-, free- en ook MacOS)

[Reactie gewijzigd door beerse op 20 december 2025 16:40]

Wel, hier wringt het nu juist. Rust wilt juist een volledige herimplementatie. Dus ze gebruiken bijvoorbeeld niet de C implementatie die zoveel talen (zoals Python etc) aanbieden en ook in Rust is de LibC beschikbaar, maar ze herimplementeren code die al decennia lang goed werken omdat het niet 'volledig Rust' is. Deel ervan is zodra je C-code moet aanroepen, ben je verplicht 'unsafe' te gebruiken en dan repliceer je dus gewoon de problemen en bugs van de C-code.

En daar komen de problemen bij. Zoals je zegt, ze komen uit een andere wereld, grotendeels studenten of net afgestudeerd, terwijl Linux/Unix al decennia aan ontwerp heeft, ze smijten het allemaal buiten, de baby en het badwater omdat "Rust beter is" en dan inderdaad gebruiken ze de macht van het Internet en de sociale media om andere bedrijven, waaronder Canonical en Red Hat proberen forceren hun 'betere' code te gebruiken alhoewel wat ze zelf drop-in replacement noemen maar grofweg 500 testen passeert, terwijl GNU coreutils >600 test suites heeft (dus een test waar 1 of meerdere, soms tientallen) testen zitten. En daarnaast zijn testen voor C code meestal plaatsen waar vroeger bugs zaten, niet noodzakelijk bugs in een nieuwe implementatie. Er zijn zat dingen die geimplementeerd zijn 50 jaar geleden zonder tests en perfect werken, die misschien niet POSIX-compatible zijn of primitieven in andere talen niet ondersteunen.

Een voorbeeld: stel dat je een optie heeft die waardes aanvaardt - zeg nu chmod - je kunt dus 0600, 600 of u+rw zetten als optie. ECHTER 0600 != 600 - in Python is 0600 expliciet een octaal nummer, terwijl 600 een base10 nummer is. In Rust is 0o600 een octaal nummer etc. Echter in C is de 0600 die je meegeeft een octaal bitmask, geen nummer, je cast de integer naar een bitmask en zet dat op de bestaande rechten zodat 0600 de sticky bit overschrijven en 600 niet - representeer dat maar eens in Rust wat gewoon een bitmask is in C, inderdaad, als je het 'niet goed doet' is er een mogelijke exploit waar je dus input aanvaard die niet 'mag' of dingen verkeerd interpreteert wat vroeger misschien aanvaard werdt kan de code er nu niets mee doen, en er moet maar 1 persoon in de wereld zijn die een script had die een typo had die misschien wel werkte maar eenmaal de 'drop in replacement' komt verandert het gedrag.

[Reactie gewijzigd door Guru Evi op 20 december 2025 17:10]

Tja, wat wil je... Vanaf de hardware gezien, draait de kernel. Die wordt al in rust opgebouwd en de interface zou het zelfde zijn, want drop-in replacement.

Daarnaast heeft een operating systeem libraries. Ook hier: Drop-in replacement dus is het goed: De interface werkt en alles er achter is rust omdat je dat zo definieert.

En de code van de applicaties en programma's zelf, ook die zijn rust en werken als drop-in replacement.

Over de commandline van de codes: Je respecteert het nummer systeem van wat je implementeert. Dat rust 0o600 notatie heeft als octaal: Jammer. De drop-in replacement schrijft voor dat de cijfers die je als opties aan chmod geeft niet als waarde geïnterpreteerd worden maar als bit-mask: 0600 of 600 zijn voor chmod wel degelijk verschillend: Met 0600 reset je volgens mij ook de stickybits en zo: De +s en +t bits.

Als een cijfer combinatie met een voorloop 0 begint, dan is het in heel unix en linux en octaal nummer. Gebruik je 0x als voorloop, dan wordt het een hexadecimaal nummer. Gebruik je punten tussen de cijfers dan zijn het byte-codes: 172.24.16.8 is een 32-bits getal met de waarde 0xAC181008 oftewel 2887258120. Ja, in unix en linux zijn getallen in de regel hele getallen en in ieder geval tot 32 bits en/of de woordbreedte van de cpu hebben ze hun waarde onafhankelijk van de representatie. Ja, de extenties van chmod zijn octaal. Ja het zijn bitmasks. Als rust daar niet netjes mee om kan gaan, dan is dat een minpuntje van rust en moet dat in rust uitgeschreven worden zodat het wel drop-in werkt.

Om te kunnen reageren moet je ingelogd zijn