Hacker News new | ask | show | jobs
by departure 2535 days ago
And?

It's kind of like how I've seen you comment multiple times about how software shouldn't be written in C. You even said it during the DNS fuzzing thread earlier today.

You saying that is just as pointless. You would be very surprised at how much new stuff is written in C!

1 comments

No, software written in C is and will continue to be replaced by software written in modern memory safe languages; the trend is strong and growing, to the point where we tend to look askance at (1) new software written in C and (2) popular software written in C that doesn't need to be written in C.

The opposite is the case for network connectivity: the trend is demonstrably and decisively towards increased connectivity, and "air-gapping" is not taken seriously in the industry. There is no indication of that changing.

The comparison you're making is invalid. I'm not trying to score points; I'm observing that the litany of "this should be air-gapped" complaints isn't productive, because things are not going to be air-gapped.

(My full-time job is assessing software security and my background is in C software vulnerability research, so it's less likely that I'd be "surprised" by a new C package than that I'd warn my clients to avoid it, and flunk it in vendorsec assessments.)

>I'm observing that the litany of "this should be air-gapped" complaints isn't productive, because things are not going to be air-gapped.

So, how would one be productive about it?

Your post seems to say, and please correct me if I am wrong, that because things aren't currently happening and there are some barriers to making it happen, we should all give up on pushing for it? To me, that seems like a rather fatalist attitude to have. Do we apply this line of thinking to everything? Or just air-gapping?

Well, I guess I'm going to say something challenging here: give up on air-gapping, since it's not going to happen. Revise your premises to assume technology that can be connected will be connected, and proceed accordingly.

I am not, by the way, happy about this, but I've also spent essentially a lifetime (minus maybe 13-14 years at the beginning) having all the surprise on this particular issue knocked out of me.

Sure, companies won't air gap willingly. But legislation can fix that. I see no reason why this world (or this country) is one where such legislation necessarily cannot happen.
It's really a shame that a (relatively easy to implement) solution exists to a problem, that could potentially save lives in this case, should be left to the wayside and a new solution needs to be invented. Which, that solution may also not be implemented.

I guess I have a little bit of surprise left in me on this issue.

It's not a solution, it's a layer. Vulnerabilities still matter behind an airgap. A hospital is a large, semi-public facility. Patients are left alone in their rooms with network drops. There are legitimate business needs to transfer records in from and out to other institutions; who's to say they can't contain exploit payloads? There are contractors, vendors, and high-turnover low-skilled staff circulating every day. And even if there weren't, if you've been thinking of the airgap as a "solution" and not keeping up with patches, the first person to cross will have a ridiculously easy time with whatever's inside.

It's good to raise the bar from drive-by internet strangers to people and organizations willing to take mild physical risks, but it's not a panacea.

I suppose I could have been more precise in my wording, and clarified that I see it as a solution to a piece of the puzzle. Indeed, you do word it better in saying it is a layer. I agree. It is a solution to facet of a problem which exists at a certain layer.

I don't quite know how my comment led you to believe that I think airgapping is a pancea which solves all the existing computer woes in the world.

I certainly don't think, and didn't intend to imply, that airgapping removes the risk from contractors or a reason to not keep up on patches. Again, I'm confused how you reached that conclusion based on my comment.

Think beyond your scope. IT is a tool.

The risks of compromise of an anesthesia machine are scary. It’s also scary that without EMR integration, a dosage might be misreported or an allergy missed.

It’s possible to securely segment a network to defend against these types of risks. The bigger problem here is that the professional practice of IT is such a garbage fire, it’s assumed that the LAN is compromised and airgapping is the responsible choice.

> So, how would one be productive about it?

One might start by observing that there are reasons these things aren't air-gapped. A person could go on to note which of these reasons continue to apply and are considered compelling by those who make the relevant decisions, and thus that air-gapping is likely to persist.

I wasn't being facetious with my question, it was made in good faith. As I'm not familiar with hospital infrastructure, nor hospital equipment, could you explain to me what reason (other than updates, which is being debated here) an anesthesia machine should not be air-gapped?
Updates, remote monitoring and remote management all come to mind. Further, integration with other instruments is something that is sometimes considered valuable and difficult to do when everything is airgapped from everything else.
Updates should not happen while a patient is under treatment using the machine. Remote monitoring can be done through an airgap (one way optical bridge) that does not have the ability to influence the machine. Remote management while a patient is being treated sounds wildly irresponsible.

So maybe the system could be connected to the network except for when it is treating a patient. A big red slider with 'On Air/Isolated' could be present which would lock out the patient treating options as soon as the machine is networked. Now, this would still leave some gaps: an update could be faulty, a malicious actor could install something that triggers only after a while or when the machine is used to treat a patient. But it would remove a lot of the concern I have with equipment like this being online all the time.

This is true, and important (air-gapping isn't, for the most part, going to happen)

Specifically speaking to medical devices, there is a bit of systemic bias. Early hospital networks were isolated, and this led to some naive thinking about security (e.g. DICOM protocol has no auth provisions). Many early machines weren't connected to anything at all, then they were but only "safe" networks so not much care taken. Development lifecycles on complicated devices is incremental over sometimes even decades. But now hospitals etc. have lots of pressure to connect all the things, for all kinds of good and productive reasons, and air-gapping just isn't a realistic solution.

It's not an easy problem to solve, especially quickly.

You are starting to see some partial hardening of devices, which will probably be the practical solution.

More to the point: almost every safety device installed in medical systems can be over-ridden during emergencies.

So even if you can't normally access certain records or data, if you claim it is an emergency you suddenly can!

This isn't true of most hardware devices at least - there are emergency shutdown procedures etc. But, to the original question, there isn't an "emergency override" that would let me change the dose or override the interlocks on received dose.

There are sometimes calibration modes or research keys that let you do odd things to, say, imaging machines. But there are also processes in place to disallow clinical use.

> No, software written in C is and will continue to be replaced by software written in modern memory safe languages; the trend is strong and growing, to the point where we tend to look askance at (1) new software written in C and (2) popular software written in C that doesn't need to be written in C.

When will we get an ANSI standard for one of these new fangled languages?

Go is captive to Google, and Rust is more akin to C++ than C -- neither have an actual standard with competing compilers.

Until that changes, I think plenty of new software will be written in C, especially freestanding and embedded software.

Rust will displace C in embedded applications, and Mozilla will gradually POC out its displacement in browser software as well. Swift is and will continue to displace C/ObjC in client application software on Apple platforms. Java is displacing C on other mobile platforms. Go is already displacing C in serverside software. And, of course, languages like Python have overwhelmingly replaced most of what C used to be used for in conventional CRUD applications.

C is on the way out. It's not gone, but it's going. There will not be a revitalization of the language. It'll be good to know, because some things (OS kernels and device drivers) will continue to be written in C for the foreseeable future. But that's a very small niche relative to the industry as a whole.

Nobody cares, and nobody should care, about ANSI standards.

Why would you use Rust on embedded hardware? Seems like C is a better match for embedded considering it has no borrow checker to complicate things, and the borrow checker is less useful when you do not have a heap.
The borrow checker isn't nearly as big a deal as you make it out to be from a complexity perspective. You have to take some time to learn the paradigm but when you do it's easy. The challenge is people assume it writes like C because it looks like C, and are frustrated when it doesn't. After a couple of months, you'll realize the borrow checker is your friend, you just need to feed it stuff in a way it understands.

The borrow checker is great for all sorts of things, like ensuring that you only have a single mutable reference or an arbitrary number of immutable references to objects (to prevent corruption) and for the pseudo-threaded model interrupts entail. Memory safety matters in embedded systems, too. You can encode state cleanly with ADT enums [2] where the language can statically detect invalid state transitions.

It's also a much more expressive language, providing you with great abstractions with no added cost. The ergonomics are pretty great compared to dealing with C once your peripherals / register accesses are wrapped, as often are already. For instance, check out the stm32 package [1].

Being able to rely on the compiler more means you get correct code faster, and debugging on embedded systems can be absolute hell. Anything that helps me avoid it is a massive win in my books.

[1] https://github.com/stm32-rs/stm32-rs

[2] https://hoverbear.org/2016/10/12/rust-state-machine-pattern/

First of all, the borrow checker is useful any time you have data that's potentially being accessed from multiple "places" in the code. At a bare minimum, it forces you to mark such data with type constructors such as Cell<> that make it clear where error-prone shared state can occur. Secondly, Rust is an appealing alternative to C++ as a "better C" language. C++ used to be quite acceptable as such, but recent C++ standards come with a huge amount of incidental complexity, so moving to something cleaner can make sense at least for "greenfield" projects.
Because Rust is memory-safe and C isn't. I agree that C is easier to write on embedded platforms and kind of enjoy writing that kind of code myself. But shipping a product requires more than just writing the code; it also entails all the verification work you have to do after the code is working to keep the product in the market, and the verification burdens on embedded software are only going to increase as people generally get more clueful about security. Memory-safe languages will (if they aren't already) be a less expensive way to get a product to market.
Protip: look at the tooling requirements for safety critical software (aviation, automotive, industrial, medical...). Nobody is going to allow you to use tools that are not certified for these use cases. Certification of compilers, static checkers etc. Is a huge undertaking that only a few commercial vendors perform on their offerings. Open source is out because nobody even attempts yo run them through that process. What you are left with is highly priced toolchains for Ada, C or C++. The cheapest offerings I know start at high four figures per developer. Validating a new toolchain would likely be to the tune of high 6 up to 7 figures. Don't hold your breath.
I fail to see how a borrow checker can even be remotely useful when there is only one kind of lifetime for everything: until the power to the device is shut off. The only memory-related issues you can have then are out of bounds accesses and using uninitialized or stale data.
Session types. Managing hardware state via the type itself, such that it is not possible to create code that does something with (e.g. an IO pin) unless it has first been properly set up, and it's guaranteed at compile time with no runtime checks.

Guarding against mutable aliasing with respect to hardware state could be enormously valuable.

What are you talking about? You can certainly have memory related errors on an embedded system.... and the lifetime of memory can often be shorter than the full on cycle of the device.... you can use memory within a function that is not needed outside of it, etc.

Borrow checking is unrelated to whether you are on an embedded device or not.

This is a misunderstanding of how Rust's borrow check works. It is necessary for avoiding numerous memory safety issues, not just use after free. For example:

    let mut x: Result<i32,f32> = Ok(1);
    let y = x.as_ref().unwrap();
    x = Err(1.0);
    println!("{}", y); // unsafe cast of float to int
This issue was first described to my knowledge by Dan Grossman in "Existential Types for Imperative Languages". The context was trying to make unions work in a safe dialect of C (Cyclone).
I don't know why we're arguing about the utility of the borrow checker in static memory systems since the borrow checker is obviously not the only difference between Rust and C in that setting; we talk about Rust in embedded systems because it doesn't have a heavyweight runtime that requires (in practice) garbage collection to function, and so is suitable for environments where Java and Go aren't tenable.
Go has a battle-tested specification and multiple implementations.
There's llgo [1] too, which in my opinion is how Go should have been developed in the first place, instead of on the decrepit plan 9 toolchain, but hey, at least we have it haha.

[1] https://github.com/llvm-mirror/llgo

> Rust is more akin to C++ than C -- neither have an actual standard with competing compilers.

C++ doesn't have an actual standard? Are you sure about that?

Rust and Go is what I was referring to in that case -- sorry for the confusion.

Yes both C and C++ have standards, and I consider that to be a good thing, though apparently tptacek says I shouldn't care.

Ah, I see. My error.