Hacker Newsnew | past | comments | ask | show | jobs | submit | Jach's commentslogin

I don't have a great sample size but I've never thought he was being dismissive or implying something was a stupid question or someone should be ashamed of asking. However I do still think he sounds pompous, purely as a matter of the way he speaks. It's the pace, the cadence, and how he hangs on or stresses certain syllables and words. It's a recognizable style, not unique to him. Leonard Susskind has a similar one, though I'd say not as extreme. You get a more extreme form listening to various philosophers. (An example as parody here: https://www.youtube.com/watch?v=leQ1bczMu7c) It usually doesn't bother me, as I can filter out the information from the presentation, but I still notice something. Reading is better than listening in part for not needing that layer of filtering.

That makes sense. There is a certain honesty to it, not to throttle your speech for tact’s sake. He expresses the level of confidence he has.

I'm glad they mention Wheeler's work briefly in section 7.2, since it provides a general counter to the trusting-trust attack that a lot of people seem to not know about. They dismiss it as not applying in this case, but I'm not really convinced by their argument. It's true if you only replace the compiler and run in the same environment then it won't help, but IIRC Wheeler's approach treats the environment itself as a parameter to diversify on. So not just the compiler, but also the host/OS, and even the hardware. Thus it's trivial to extend it to strip. Build binutils from source with your bad distro toolchain, fixup with your distro strip, call this build A. Then build binutils from source in a diverse environment, which includes fixup with a diverse stripper, call this B. Then do a rebuild (same diverse environment) but with B's toolchain and stripper, call this C, and compare C with A. Mismatch busts the attack.

I’ve never found Wheeler’s approach very satisfying. It says “we can’t trust the compiler, so here’s a second compiler.” But I think it is too literal interpretation of Thompson’s attack and it is just moving goalposts not really stopping the essence of the attack. The viruses of the 1990s got so advanced they regularly intercepted the read calls and stripped their payload from inspection so hiding themselves, and you could imagine in the playpen where we think we trust some other external compiler we must also think we trust the read functions on the compromised machine etc. Thompson was thinking at a higher level than this.

I also think they’ve shortchanged the bootstrap build mitigation. They write:

    A utility such as strip sustains the attack whenever a tampered instance participates in the rebuild, even after the compiler seed shrinks to a few hundred bytes. 
Well, yes, if you presuppose your modified binary is used, then you will find that your attack continues, but that’s only because “P iff P” is a logical tautology. It would be true even when the seed shrinks to 0 bytes, or shrinks to a negative number of bytes, or shrinks into a miniature poodle and tap-dances across your keyboard.

The question that should have been addressed is “does the tampered instance participate in the build?”, and the whole point of these minimal-byte “seed” bootstraps is that they are just enough bytes of executable to do everything else from the source. So, no, the tampered instance won’t be participating in the build. We might even deploy our own tautology and say that if a pre-existing tainted binary participates in a build, then that build was not a bootstrap build, and therefore all bootstrap builds are in fact perfectly and definitionally immune to the attack.

Honestly, this whole paper kinda reads like an academic version of a slop CVE.


The paper is not about implementing a general attack that works on all trusting-trust mitigations.

It is precisely about showing that you can still propagate backdoored code if the compromised binary in your seed is NOT the compiler.


>The paper is not about implementing a general attack that works on all trusting-trust mitigations.

Then why have section 7.3 'Bootstrappable Builds', that briefly surveys a type of trusting-trust mitigation, and concludes that their method "sustains the attack [...], even after the compiler seed shrinks to a few hundred bytes"?

>It is precisely about showing that you can still propagate backdoored code if the compromised binary in your seed is NOT the compiler.

Whatever this paper is about, it is certainly not precisely about it. But quibbles aside, if that truly is what the authors set out to show, they should probably re-read the transcript, where Ken says "[For demonstration purposes], I picked on the C compiler. I could have picked on any program-handling program such as an assembler, a loader, or even hardware microcode."


If you actually read how GUIX (what they talk about in section 7.3) is calling a "full source bootstrap", they have brought down the compiler seed to less than 200 bytes, but also they rely on an execution environment that still has 25 Megabytes of unaudited(-able) binary.

GUIX is unconfortable about that, but as they name the current process "full source bootstrap" implicitly consider this unaudited execution environment out-of-scope and more of an academic blemish, rather than a real problem: https://guix.gnu.org/en/blog/2023/the-full-source-bootstrap-...

After all you rebuild it together with the world immediately after compiler bootstrap is done. And the utilities in your execution environment do not process the compiler source, so this dependency cannot be a problem, right?

The paper precisely addresses this. You cannot handwave away your shell or ELF utilities. They can sustain an attack just like the compiler.

> "[For demonstration purposes], I picked on the C compiler. I could have picked on any program-handling program such as an assembler, a loader, or even hardware microcode."

This is precisely the problem that most people dealing with OPSEC have.

If you get "paranoid enough", your threat model always collapses into an unactionable mess where everything is just toast and your only solution is to quit computing and start doing woodwork or something.

If everything is potentially compromised then of course the results from the paper become obvious. If your environment is compromised, don't trust its output, duh!

If you want to quantify though, under which assumptions, "how much" your environment can be broken without compromising its output, the paper has value. And it seems like real attempts of bootstrapping binaries actually missed a spot.


> It is precisely about showing that you can still propagate backdoored code if the compromised binary in your seed is NOT the compiler.

But that seems like quibbling about semantics. Thompson says that if a compromised binary generates a binary, you cannot trust the generated binary.

This does not even have to be gcc, it could be vim. Or strip. Or cat. Or dd.

Or an iop to write data to persistent storage if the firmware of your SSD is compromised.


Works until AI compromises a bunch of OSes. And wouldn't there be difficulty comparing binaries built from significantly different environments? It sounds like some progress has been made in general for fixed identical builds, but isn't that also still a hard problem? I don't know enough low level C-level stuff about binary generation.

> Works until AI compromises a bunch of OSes.

Just write a new OS. It's a weekend project to get enough groundwork that you can bootstrap a clean system from clean source code.

> And wouldn't there be difficulty comparing binaries built from significantly different environments?

Not really. Starting from stage 0, compile the compiler under test (stage 1), then use the compiled compiler to compile the compiler (stage 2), and compare the stage 2 artefacts. Provided that your comparison program is known-good, and the stage 2 build is deterministic (not the case for some real-world programs, but true for things like tcc), this lets you verify that the two compilation procedures work identically.


Not sure if you're joking. How do you write an OS without these tools that might be compromised? It's the same problem.

Break expectations. Bootstrap it through an esoteric-enough system. Write an Uxn emulator in assembly targeting the cushy environment that UEFI has and you've got a system with graphics, a text editor, a spreadsheet editor, an assembler, games, and maybe even more. I have a Z80-powered email appliance that can be loaded with programs from a connected device. Whoever is breaking my trust in trust surely won't have planned for that.

but now they will via delegation to an automated analyst/systems programmer.

get ready.

the effort required for a complete infiltration has been lowered a great deal.


This automated analyst isn't going to be able to run usefully on hardware that is still otherwise useful, giving you a clear path to choke it out or identify its presence when your hello world is taking 3 months to finish compiling.

insertions can be much smaller than full blown LLMs.

simple single bit changes are enough to blast your private keys out to the ether of the public facing internet.

that big fat LLM does know how to make tentacles and eyes.


Absolutely true, but even tentacles and eyes will struggle to fit in a system compact enough. Even on larger systems, there is an upper limit on how many tentacles you can cram in something before you can't continue the facade that there are none. And an upper limit on how esoteric the tentacle is before it stops being worth it.

You can construct a CPU out of an EEPROM, a clock, and a few latches. Connect it to an immediate mode display with a serial interface that doesn't care about being clocked slowly, connect up a buzzer or some blinkenlights for output when you're exceptionally paranoid and can't trust the display controller, make a basic keyboard with a rubber sheet, some wire, and some glue, poke a keyboard driver and a line editor into memory with your DIP switches, crank the clock up to kilohertz (so the keyboard latency is tolerable), and you too can bootstrap a cross-compiler! (Though be aware that the radio interference will be enough for a committed attacker to figure out what you're computing, unless you take measures against that.)

But they're not going to backdoor an Apple ][e, or a random 80m¢ microcontroller, for basically any value of "they"; so you can just use one of those instead, and save yourself the hassle.


I like the way you think, a true MacGyver-style problem solving.

Write a subleq interpreter with a magnet and a steady hand? (Hopefully the magnet is not compromised)

I am trying to imagine how the magnet could be compromised. Could you theoretically embed an electromagnetic and a controller within a decoy magnet and somehow detect what was being recorded and subvert it? Probably not but... No, just probably not.

At that point maybe they'll just knock you out and torture you for whatever secrets instead

By doing it.

Individual cpu instructions, even of a crude old 8-bit cpu with no embedded minix os like today, are both simple enough for a human to manually understand what they do, and useful enough to build crude versions of useful things like an editor, interpreter, or compiler.

You can write a forth-like language or even a c-like language starting from individual cpu instructions that a human can read, understand, and write totally manually, and then use that to build up rapidly all the way to a full modern desktop.

If you were really paranoid about the very act of the initial typing-in, there are any number of ways to store data in a totally brainless eprom or record it to tape or something, and examine it with nothing but some leds, no cpu at all, to verify the bytes are the bytes you want. And you only need to do that for a pretty small number of initial bytes. After that it's all just regular source code which could be written on paper.

Bootstrapping is only an inconvenience problem, not a real problem.

It's not convenient for most people to assemble some bytes into some storage medium and then verify them without simply using a normal untrust-able computer to do it. But it's no problem really if you had some reason to be that careful.


We have tons and tons of backups of clean Linux isos, compilers, etc. The idea that we are going to lose the ability to easily have an uncompromised system is a fairy tale told by the people pushing bootstrapable builds.

It's kind of a fun, albeit also kind of a pointless, thing to do, huh? This week I took a student project game I made with 3 others back in 2010 and made it live again. I'm cheap, I only have the $20 plan for this month (likely to pause again for next month) and used Opus 5, and I'm visibly hamstringing it by running claude code in a firejail and not using yolo mode on permissions. Still, without much effort/oversight, it took the old C game that only ran in windows' cmd.exe terminal (a class constraint -- we still made a side scrolling shoot-em-up rather than a text adventure like many others), wrote the new version in Common Lisp as I asked (somewhat following the style of some other Lisp code I've written), implemented both a simple SDL2 "software" renderer along with an even faster OpenGL renderer, and didn't touch the original assets which were in a quirky binary format with a bug on one level in the C code. And now it runs great on Linux (and Windows, though only briefly tested it, building it with wine). Having its own graphics window lets it run at thousands of FPS when we were struggling to hit 30 back then. Last night on a whim I had it take a crack at porting to Android, and it did that as well. Still using SBCL, just one little C file shim for some things, no Java code was needed. Now I can easily show it to a few people in person. And it was kind of fun to play it again after so many years in an archives folder.

Your game looks cool. It's a full, real game! And while I now think that there's no longer strong "platform convenience" reasons to choose any tech stack if these AIs can just bulldoze their way through difficulties, I'm sure running in Godot still made a lot of things easier for it.


Why pointless?

Only kind of pointless. A few reasons come to mind. For one, they're games. (I say as an avid lifelong gamer.) For another, it's indulging nostalgia. (I say as an indulger.) To be clear, I think both things are fine, but of course to all things moderation, even moderation. When trying to rank things by pointlessness, many specific forms of entertainment and nostalgia are higher up than other activities or categories. Not as high as watching paint dry. And the more general category of, say, "having fun" is lower; some might even claim that to be the least pointless thing of all. I'd caution with "Amusing Ourselves to Death".

More reasons come from trying to predict where AIs and our interactions with them will be in 6 months, 1 year, 2 years, 5 years. Will we even be alive? Other reasons from wondering about alternative actions: is asking the magic box to do this particular thing, rather than some other particular thing, the thing that will actually bring you (or others) joy right now? Or money? Satisfaction? Fame? Upvotes? Some other things you want to feel or experience or do? (And in the OP's case, I think there's actually quite a good case of actions matching motivations, given the full history, and especially as earlier pre-AI-tooling ports were well-received enough to get a couple million downloads. Still, what about something new?) For my own small efforts this week, the main things I got out of it, besides the nostalgia (which is quite valuable to me), were similar to what I've been getting out of any AI-using projects this year, which is a strange mix of satisfaction, a bit of fun, a bit more awe at these magic boxes (even the dumber ones like Opus and Sonnet), anticipation of showing/telling a few people in person about this particular kind of pointless adventure, and a bit more melancholy about a few things, like the makeup of some of my online hangouts, or that my programming skills have been rapidly decreasing in their having a point to exist, or that my revealed preferences in this case are that I'm happier to let the AI do all the coding for this project and barely look at the code myself (there's a bit of disgust/gross feelings here too). I last thought of doing this work in 2019/2020, never got very far, now it's suddenly done, and even more than I thought of doing. (I still keep the AI out of some other projects, as programming the old fashioned way is in general still pretty fun to me at least.) Now it's on to the next project, when I decide that will be more fun than playing a game (I have such a backlog after all), and I'm sure it'll also be relatively pointless. More the honor to people doing bigger things impacting the world, with or without these tools.

This whole comment is also kind of pointless, I'd rank it as probably more so than the other mentioned things (except I guess watching paint dry), and yet it's here.


It obviously depends on the project and the scale and duration of a donation, but plenty of open source projects have benefited from donations. Donations can and do pay for developers, as well, part time or full time. With LibreOffice, you can answer your questions directly by browsing https://www.libreoffice.org/donate/ and as a non-profit you can easily find more detailed reports: https://www.documentfoundation.org/financials-and-reports/

Pretty much any book or long paper that decides to take a historical turn is going to be at least as good if not better than these talks. There are a lot of historical resources out there that go into different parts of "computing history" more generally. I don't know what would meet your criteria for computer science or software engineering more narrowly. To me they are all very interconnected. I couldn't say whether it'd be more important to have a nice presentation that includes Babbage and his machines vs. a neat presentation that covers Codd's work going directly into Chamberlin and Boyce's work on System R. A historical presentation has to decide what it includes and excludes. In recent times I've enjoyed Fabien Sanglard and his work on the histories of Wolfenstein 3D, Doom, the hardware environments behind them (development and deployment), and the CP-System. Lots of "lost" technical knowledge in them. Of course the earlier and higher level Masters of Doom book contains a lot of neat history as well, though less technical. The HOPL (History of Programming Language) papers are always insightful and contain a lot more "plain" computer science, though of course with a focus on programming language things. Richard Gabriel could write a lot more of history than he already has; here's one of his papers that (among other things) details a history of mixins in object oriented languages, and how they were "rediscovered" poorly in a way that obscured their actual historical nature, demonstrating an idea of incommensurability. https://dreamsongs.com/Files/Incommensurability.pdf

I should also add that even interviews are valuable. Coders at Work is fantastic at that and drawing out technical opinions and reasoning; notably the subjects interviewed don't all agree and have sometimes drastically different work styles and preferences. (And also adding from another comment, Turing Award Lectures are great history, and Uncle Bob even has a history book out now on influential programmers.)


And people still come out of the woodwork with a parade of excuses, and sometimes he addresses those too. But it's no wonder that he gets a bit brisk or blunt with people, and turns off others who haven't been following along.


One of the principles of structured programming is that you organize your code into functions, and that they have single points of entry, and single points of exit. We still have a lot of multiple points of exit in functions these days, but the reasons for them usually fall into either those of clarity (less nesting/branching) or performance by skipping unnecessary work, and the consequences of them are less dire in modern high level languages because such languages have GC (no fear of skipping a memory cleanup step) and features like try..finally to ensure code closing file handlers or logging or whatever is executed at the end. But we have largely eliminated multiple points of entry from most code. The main remnant I can think of is in the form of coroutines, though they are structured and limited enough (like modern gotos) and have well defined lifecycles that it's more forgivable.


This is my objection as well. His talk last year on OOP was heavily focused purely on the style of OOP that led to C++'s version. It completely ignored everything else going on outside that historical thread. As history it was interesting but doesn't inform much outside of a C++ view of the world and it missed so much relevant history about OOP more generally.

While I suspect he could do research, he also just isn't personally experienced in large tracts of SWE culture as others. Others have worked a far larger variety of jobs in the software industry and thus tend to have a broader idea of the cultures and how they've evolved. In a recent clip I saw of him and others discussing how BS are various phrases engineers say (the root of all evil phrase being one of them), he hadn't heard of the YAGNI acronym/idea before. That's no fault on him, programmers live in different worlds. But regardless of one's feelings about such ideas, or whether they've heard of them or not, a history of SWE would have to cover them and the schools of thought that originated them. And this is just one minor thing in living memory and recent careers, there is so much from before he was born that has to be researched and if possible also talked about with the older practitioners who are still around and remember things. If you don't already have some awareness of things that should be covered in a history, whether from personal experience or just general curiosity about history that has led you to see such things before somewhere, the only hope is further research uncovering them, and I don't trust his researching that much.

Reading The Psychology of Computer Programming from the 70s was such an interesting read for me from a historical perspective as well as being able to see how some ideas they were thinking about back then came to fruition in some way or another. (e.g. Stack Overflow.) It's just one small part of history. A "complete" history as the top comment suggests would be better as a multi-author endeavor, would probably need many books, and that's if it could be done at all. In the meantime at least one can always go read primary sources and develop an idea of the history on one's own.


If you know this stuff, please make videos / talks yourself going through it. Casey doesn’t have the background for a lot of this. He’s doing great as a C++ dev but as you say, he’s just one guy with one perspective.


I really think videos and talks are the least effective ways to get these things out there. I'd rather just point people to references I've read myself about specific topics rather than try to create a structured synthesis or presentation. I tend to think that's sort of best anyway for a curious individual: go read primary sources about some topic, and if interested further, citations or other related works. Every Turing Award Lecture transcription I've read has been insightful. I just recalled that Uncle Bob was writing a book about influential programmers, he was calling for suggestions on names a few years ago: https://x.com/unclebobmartin/status/1714972421269119190 One could just read through those names and the names of those the comments added (I had several more) and the work they are most known for, and by the time one is done with that, one will have a very nice historical picture of computer science up to the 70s. Nowhere near complete, of course. It seems he did publish his book at the end of 2024 (https://www.amazon.com/We-Programmers-Chronicle-Coders-Rober...), I'll have to check it out at some point. (Edit: and I'm reminded of another funny thing. Early in the book Clean Code, he asked some other programmers what they thought was meant by the idea. I remember penciling in some objections in the margins that he should have asked x,y,z other people who I would rather have read from than some of his sample.)

It's just absurd to me to point at Casey, of all people, as the most informed person who would be best positioned to publish something containing all of the history of anything broad.


There's a selection effect here in that smart-enough users won't bother contacting support if they work around an issue on their own, or if something is actually a non-issue for 99%+ of the user base. The ratio of usage and support contacts can be monitored. I fear a lot of devs develop unproductive mental models of the user purely from a minority sample.


Smart users forced to use work arounds may also find the workaround is to switch to your competitors product !


Designing for the stupid users also makes life easier for the smart users. No matter what you are designing. It makes your product better.


That's trivially false. There's a large difference between products designed primarily to have a low learning curve, and products designed to maximize the efficiency of users that have been trained in its use.

The only products which should have any mandatory learning curve are products which actually allow an expert to do something out of the ordinarily, which simply could not be done with an easy to use product. Such as some musical instruments.

Otherwise, you can most of the time make a product which can be easy to use for novices while retaining maximum efficiency for experts.


Compare a professional trader's UI to something consumer-grade like Robinhood, or analytics UIs designed for marketers (exposing only a few cute graphs with a handful of predefined parameters) to the dashboards used in physics labs, or simple graphics programs vs. Blenders.

Maximum efficiency for experts requires removing information that would be distracting and redundant for them, but essential for novices to understand the working model of the program, so you're pretty much wrong.


Sometimes, not always.

It may result in power users losing some features.


Not necessarily. Interface design is a communication medium. A skilled designer can often communicate to multiple types of users solving different types of problems. When an interface is “dumbed down,” it’s usually because a non-designer was trying to ‘clean it up’ or make it pretty by removing what they didn’t need and ignoring what everybody else needs. It’s difficult, and that’s why it’s a distinct field with its own degrees and professional programs.


The claim was broader, specifically "Designing for the stupid users also makes life easier for the smart users. No matter what you are designing"

it can be in fact improvement for both but in many cases it is not


Sure, but whenever you can make life easier for those who have are having hard time without making life harder for those who aren't, you should do it.

For example, no power user benefits from having to use work arounds to make a product function. It's an annoyance to them, and it's an insurmountable obstacle to others.


Oh, I agree with that. Just dispute claim that any improvement for newbies is improving things also for experts.

Wild to me and speaks volumes of HN/SWEs that this is getting downvoted.


Watching bits of videos from this guy's series on beating every N64 game (including JP-only releases) is a fun way to find out about interesting games I missed from back then. https://www.youtube.com/playlist?list=PLrwJXOVKrLbIDAiT9b4Lk...


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: