Hacker Newsnew | comments | show | ask | jobs | submit | jerf's comments login

Don't be in such a hurry to second-guess your brain... it's very good at optimization problems you don't even realize it's solving. If you're using the correction buttons heavily, I'd suggest it's more likely because you're more efficient using them than because of the intellectual slovenliness you seem to so casually assume.

As I learned from Haskell, the correct answer really ought to depend on the domain. I ought to be able to use an unsigned integer to represent things like length, for instance.

However, since apparently we've collectively decided that we're always operating in ring 256/65,536/etc. instead of the real world where we only operate there in rare exceptional circumstances [1], instead of an exception being generated when we under or overflow, which is almost always what we actually want to have happen, the numbers just happily march along, underflowing or overflowing their way to complete gibberish with nary a care in the world.

Consequently the answer is "signed unless you have a good reason to need unsigned", because at least then you are more likely to be able to detect an error condition. I'd like to be able to say "always" detect an error condition, but, alas, we threw that away decades ago. "Hooray" for efficiency over correctness!

[1]: Since this seems to come up whenever I fail to mention this, bear in mind that being able to name the exceptional circumstances does not make those circumstances any less exceptional. Grep for all arithmetic in your choice of program and the vast, vast majority are not deliberately using overflow behavior for some effect. Even in those programs that do use it for hashing or encryption or something you'll find the vast, vast bulk of arithmetic is not. The exceptions leap to mind precisely because, as exceptions, they are memorable.

> the correct answer really ought to depend on the domain

This is correct. However, if you use C, your domain is bits and bytes, not abstract things — because this is what C is created to work with. I love using appropriate abstraction levels for different domains, but if your actual problem has nothing to do with systems programming, you probably shouldn't use C in the first place.

In theory, I agree. I mean that seriously, not as a rhetorical sop. However, in practice, it had wrought endless havoc even in C, suggesting, well, exactly my current feelings, which is that it's really insane in 2015 to use C for much of anything. C is the modern-day programmer's SCP-572 [1], except the sharp blow to the head doesn't usually work on a C programmer.

[1]: http://www.scp-wiki.net/scp-572

I can't get past the hubris involved with this post. First, did you truly need Haskell to learn that number representations have pitfalls? Look back in history. Problems with numbers did not begin with computers. Nor will they end with them.

Second, you imply that this would have been an easily solvable problem. If only those that came before you hadn't been so willing to shout "Hooray" and make a choice you disagree with.

I don't think you have to have respect for those that came before you. But blithely ignoring their context when they made these choices is... rude. At best. (It also ignores that many early computers did not use 2's compliment numbers, so it was possible to keep adding to bigger and bigger numbers, you would just run out of space and cause other problems.)

Finally, over/under flow are pretty much endemic into all physical things. Ever accidentally pour too much water into a cup? Why didn't you pick the correct cup for the domain of liquid you were dealing with? Overfill a laundry machine? Run out of ink in the pen you were using? Reach for a sheet of paper to find you had none left? ...

We have not "decided that we're always operating in ring 256/65,536/etc". We decided that being a little more efficient can save a room in the computer's building. If correctness becomes harder, well, there's an acceptable price. The programmer is always in the building anyway.

An obsolete decision, sure, but I wouldn't call it incorrect.

This begs the question, though, why don't we revert it in new architectures, already incompatible with everything. Tradition, I guess?

Overflow checking all arithmetic is still going to be quite expensive, even with hardware support, because you have to choose between:

A) exception/panic on overflow: this is preferable to overflow but also undesirable behavior.

B) arbitrary precision integers: this is nicer, but even today significantly more expensive than ordinary integers.

> A) exception/panic on overflow: this is preferable to overflow but also undesirable behavior.

I don't find this undesirable at all. I have worked in languages where this is the default (Standard ML) and it's quite nice. You can always explicitly use a word-type if you actually want overflow. With hardware support, it is even fairly cheap to implement, as you just connect the overflow bit of your integer ALUs to something interrupt-triggering.

> With hardware support, it is even fairly cheap to implement, as you just connect the overflow bit of your integer ALUs to something interrupt-triggering.

You can exploit the IEEE-754 inexactness exception with doubles if you're okay with 53 bits of integer precision. Tim Sweeney showed me this trick a long time ago, which he combined with run-time code patching so that an arithmetic operation would be speculatively compiled as either fixnum or bignum based on observed run-time behavior. It'd compile it to fixnum by default with an overflow trap using the FP inexact exception. The trap would patch the fixnum site with the equivalent bignum code and resume. With hindsight inspired by modern trace compilers like LuaJIT, the better approach is probably to compile entire traces speculated on either case, so you can hoist most of the guard predicates and not speculate based solely on the proximate call site but on longer traces.

If your domain is 0..99 for example, using unsigned and <100 is nicer than using signed and two conditionals. Detecting overflows is easier, not harder.

In c, unsigned behavior is also less UB.

And while the enforcement isn't there, it is still better to communicate your intent with the more precise type.

I'm sitting here writing this from a conference about the genetic disease one of my children has. He's lucky... he's of above average intelligence even on a normal scale. Many of his fellow disease sufferers are confined to a wheelchair, unable to speak even in their teens, and literally the only motions they make on their own is some vague twitching motions.

Yes, there is a such thing as true, uncompensated disability, and you should thank your lucky stars that you live a life where you could even entertain the notion that there is no such thing as "disabilities". Tone note: I mean that straight, not angry or something... be thankful. It's a hard thing for all involved.

That needed to be said. Thank you, jerf, I couldn't have said it better. I am sick and tired of people romanticising disabilities, or even worse, denying their existence. I am not surprised that some people on Hackernews are secluded enough that they can delude themselves into thinking that disability is always a tradeoff and the disabled must be a genius in some way.

"there's no need to use switch statements and their associated complexity to map integers back into addresses, when all that's really required is for the "caller" to supply a where-to-go-next address."

There's nothing quite like implementing an abstraction, then turning right around and unimplementing the abstraction as a layer on top. (See also: using relational DBs as key/value stores. Bonus points if it implements a hierarchy that looks like a file system! Implementing unreliable data delivery on top of TCP (which can be done by reconnections). Taking a character/block device and implementing block/character access. Implementing streaming on top of page-based abstractions like HTTP, implemented on top of streaming via TCP; there's "official" ways to do this but for a long time it qualified.) If you're wondering where the CPU cycles are going....

I don't understand what abstraction is being unimplemented with a layer on top here. Whether you use a stack or avoid it with [multiple] link registers, those are both reasonable methods of getting back and neither one builds on top of the other or undoes any work that's already been done. Whether to use tokens or addresses has tradeoffs, but I still don't see any work being unimplemented.

At worst they avoided a stack and made an implementation that was unoptimized in an entirely unrelated manner, not because it unimplemented anything on top.

And the answer is that in the future, "smart phone" will itself fade as a category and you'll have a smart phone that can be plugged in to a laptop body or desktop hardware for when you need the extra power. The body may also have additional processing power like a GPU, additional cores, etc, to turn it into a higher-class machine.

Due to the mobile form factor there are certain use cases that it simply can not fit while still being a "phone". This is not because the phone will lack processing power, it's literally because the form factor just can't have enough input & output options. Barring major battery upgrades, it also literally lacks the power to solve all problems. The extra hardware will also have laptop- or desktop-class heat dissipation capabilities, which a smart phone simply can not solve without, again, being something other than a phone when it's being a phone.

That is all to say, there are real and specific reasons that phones can't eat all the use cases the way minicomputers ate mainframes and desktops ate minicomputers. The only way for phones to eat all the use cases is to hybridize "back" a step and also become the things it is replacing again.

We've seen some abortive attempts at this. I find myself wondering if the fundamentally closed nature of the major phone operating systems is inhibiting the creation of this stuff, because the requisite OS changes to make this work are too hard. While I don't own one I still find myself rooting for the Firefox phone or the Ubuntu phone... they've still got a chance to beat the other guys to this market. And I for one would hate to sacrifice the openness of my entire computing stack because "the phone", which at this point will be little more than "one particular app", is closed. That's an awful lot to sacrifice to an increasingly minor use case.

> And the answer is that in the future, "smart phone" will itself fade as a category and you'll have a smart phone that can be plugged in to a laptop body or desktop hardware for when you need the extra power

And, funnily enough, Windows tablets can do that today, and the phones get it with Windows 10.

And you can find a few other things that go back three or four years; Acer had one, for instance. None of them seem to have quite stuck the landing yet. But I don't say this because I lack faith in the idea; I think it's inevitable. It's just that these things all seem to be ahead of the market. Now we just have to wait for the market to realize it wants this.

(It's hard to read the market's mind. But every once in a while, you can guess where it's going to go in advance... and get yourself brutally murdered in your financials when you show up to the party years before the money shows up.)

Back on the topic of the original article, it's possible this is Microsoft's core strategic play... if they agree with me that this is inevitable, they've still got the income and the OS resources to stick out the market's slowness, and build an incredible offering on this front out with all their resources. It's at least possible that they could indeed unseat an incumbent Android/Apple duopoly if they can be that much better than the competition once this use case becomes big... and it's not hard to imagine it going down that way. They've got a lot of cards on this front that even now Apple and Google do not, games, for instance.

> They've got a lot of cards on this front that even now Apple and Google do not, games, for instance.

Supporting older hardware, too. The fact every Windows 8 Nokia is getting a Win 8 upgrade contrasts pretty well with the way my Android 5 device won't be getting a patch for a critical security vulnerability.

Right now we call a tablet "mobile," but it seems to be to be more PC-like in function than mobile-phone-like (although more phone-like in form). There truly will be a blurring of the lines. It'll all just be some device that has computing power.

I'll add another slight spin, which is that I'd never run this in production, ever, even if I actually personally trusted you a great deal, because I can't possibly audit this sort of code base. By extension, for the same reasons I can't audit the source very well, neither can anyone else. (i.e., no, I do not personally audit everything I run but I reasonably expect that because it is possible others have. "Many eyes make bugs shallow" may be oversold but it is not simply false.) The only practical way I know to audit this sort of code base at this time is naked-eye inspection, and I don't trust that.

I say "I know" because there may be something out there. I know there exists tools for source code analysis that deal directly with assembler, because I see theses around writing them. I don't know where to get one, though, or how to use it, or how much to trust it. There's a lot more that deal with "C" or "Java" rather than raw assembler, so I can fire several tools, both commercial and open source, at the problem.

And all that said I'm still extremely strongly in the "STOP WRITING C CODE AND PUTTING IT ON THE INTERNET DAMMIT" side, even with that support. Without even that support, I frankly don't care if it's 100 times faster than nginx. nginx is already maxing out my risk tolerance as it is, and I've begun a long, slow program to get it out of my stack too.

I want to emphasize how this is explicitly (but also unapologetically) non-specific, none of this is personal, none of this is directly critical of your code (because if you've gotten the impression I haven't even glanced at it, that is correct), and in particular, please by all means do whatever you like with your spare time. The "problem" here isn't that you have somehow failed to leap my bar, the problem is that the bar is impractically high for code written in raw assembler. I suppose you could provide a math proof but I'd almost argue in that case the server becomes implemented in said proof language rather than assembler anymore.

The related element is this: if the team behind nginx somehow all get by the same bus, I am confident someone appropriate will pick up and maintain the product.

In the case of an ASM project, I would be very surprised if anyone came along with the appropriate knowledge to ever want to touch the codebase. LibreSSL is currently pulling bits of ASM out of the codebase just to remove that factor.

Like Jerf said, I want to be clear that I'm incredibly impressed you got this project over the line, and I can't make any complaint about how you've done things.

How would you replace nginx??

Go's http server. The inside of nginx is an incredible mess of C. I begrudgingly trust it since it is being actively attacked and maintained. The inside of Go's http server is incredibly clearly written. I am confident that it too will be maintained. And it's roughly half the speed of nginx, which is plenty fast. (Few web application servers in the world are sitting there with nginx using all the CPU.)

It's a long slow process partially precisely because I intend to do this carefully, and discarding nginx is not something to be taken lightly, but long term, as I said, I want the C out of my stack.

The problem with asking for better risk management for infosec is that "better risk management" pretty much comes out the same. In security terms, systems are secure when the cost of breaking the protection exceeds the value of what is being protected. In the software world, in the vast majority of cases, once a vulnerability is known, the cost of breaking the protection is indistinguishable from zero. The result is that it superficially appears that we treat things as binary risk, but in fact we are being perfectly rational.

Some of the rare examples of software security bugs where the attacks are practical but not free: Breaking RC4. BEAST. DDoS. The rare arbitrary code executions that require significant time to attempt due to needing to spray the heap just right.

But most of the time, it's click -> own.

The other thing that prevents useful quantification is that we don't have a Gaussian distribution to be seen. Rate of discovery, maybe, but that's it. We do not have Gaussian distribution on size of protected items, density of vulnerabilities, or anything else. Without that most of our good risk estimation techniques don't produce numbers that mean much to managers.

This is, IMHO, the fundamental reason why infosec doesn't get listened to. Our management structures are still highly Gaussian-biased (decades of manufacturing envy). They can't even wrap their head around software engineering schedules and costs after several decades, and infosec risks have even worse distributions! It is, in my very strong and considered opinion, perfectly rational for infosec to be vigorously ringing the bell. Consider exactly the bug we're talking about now... it's a vulnerability that has the potential to destroy the auto industry, were it properly exploited. (It would not just by Chrysler caught in the crossfire! And my use of present tense is considered. I have little reason to believe this is fixed, nor that it is the only such bug.) Our risk management procedures can not even properly express the idea that an engineer drawing a line between two nodes in the car's communications bus could have that result, can not properly express the Black Swan nature of that decision. But that's not infosec's fault, or at least, not infosec's fault alone.

And it's certainly not a solution for infosec to get more realistic about risk, because "more realistic about risk" probably means we ought to be a good factor of magnitude or so more strident, not less! The more I learn about the risks in this world the more horrifying it gets, and it's getting worse, not better, as things get more interconnected. Again, look at this car bug... it's something that could not possibly have existed 20 years ago. None of us, from CEO to engineer to QA, have even begun to properly process what this means, let alone react to it! And we won't until the Black Swan bites and probably not even then!

"but can anyone suggest how much risk is in these risks."

Twenty years ago maybe this argument carried the day. Don't even consider using it today. The tooling, techniques, and skill are far higher than you could dream if you are not in this world.

This is not quite the same thing we are talking about, but let me give you a different example. An obscure cross-site-scripting attack is no big deal, right? Well, courtesy of BeEF [1], if the XSS can be leveraged to get you to download a script, which is a low bar, BeEF can then be used to proxy web access in, allowing an attacker to lever up from "small XSS" to "crawling your intranet with the internal credentials of the compromised user".


Do not ever count on difficulty of exploit as a defense anymore. In many cases the reason why these people aren't providing off-the-shelf exploits for this sort of thing isn't that it's too difficult to make practical, it is that in the security world it is now too trivial to be worth spelling out. Attacker capabilities (and pen testing capabilities) have skyrocketed in the past ten years, but the defense team still for the most part is operating like it's 1995 and the idea that a program might be used on a network is still like some sort of major revelation.

(I'm on the defense side personally. It feels about like this: https://youtu.be/MPt7Kbj2YNM?t=2m11s In theory, I am powerful, in theory I control the field, in theory all the advantages should be mine, but....)

[1]: http://beefproject.com/

I wasn't considering anything, let alone 'making an argument'. Anyone who listens to non-specialists like me to determine security strategy is asking for trouble.

I also wasn't making any comment about 'banking on difficulty of exploit', what I was asking for was relative risk. I think that all code is exploitable. The question I had was, is the exploitation of a particular UAF bug sufficiently easy that it outweighs the base risk of a new exploit being found. If I have finite resources, understanding where to apply them to improve risk is important.

The other responses have answered my question in some detail.

I'm sorry, my tone was not intended as "what are you even talking about!?!". My tone is intended to convey that security penetration skills have become scarily good and "is it theoretical?" is almost no longer a question worth asking, because the skills, techniques, and tools to take what superficially seems to be a hairline crack into full-blown network ownership are unbelievably well developed.

As I said, I am on the defense side myself, and I will freely admit I can get a bit tetchy when doubt of the viability of a vulnerability occurs; I frequently find myself in the position of being a "team captain" trying to explain that, no, seriously y'all, the other team is coming to play, they've been working out, they take illegal steroids, they practice six days a week, they don't play by the rules and they're coming for our scalps and you're on your third beer telling each other how easy this is going to be... it's not exactly game-winning prep you're doing here....

This article is a perfect example of this: http://googleprojectzero.blogspot.com/2014/08/the-poisoned-n...

The author was able to take an off by one error which allowed writing a single null byte all the way to full code execution. These guys are unbelievably good at what they do, and as you state, you can pretty much assume that any vulnerability is exploitable with sufficient effort and skill.

For sufficiently vague definitions of Earth. For the definitions being used in most of these sensationalized stories we've already got 2 more we know about, Venus and Mars, and I'm pretty sure if Mercury was picked up in another solar system we'd hear it described as "Earth-like" too, given some of the stuff that has been described that way. The "Earth-like" idea has been debased to uselessness in press releases like this.

Unless they announce that spectroscopy has revealed a lot of O2 in an atmosphere, at this point I'm primed to be pretty underwhelmed.

(And to be clear, I am specifically complaining about the debasing of the term "Earth-like" for PR purposes. The science and discoveries are as incredible as ever, no matter what garbage PR terms are used to describe them in process releases.)


No. It's de facto impossible. If all I had to worry about was the software alone I would despair of ever correcting this in a reasonable period of time; to also have to overcome fundamental hardware challenges? Not a chance.

For a long time I've wondered what would prove to be Security-Pocalypse that finally convinces everybody that this is a real problem. This is not yet it. But if somebody takes one of these attacks and gets... "creative"... in those ways that aren't really that hard to come up with but I hate to actually spell out online (it's scary to think too hard about this... there's no possible way these vulns could be closed before a bad actor could... be very bad...)... that could become the moment the 21st century finally realized that secure code is no longer optional.

That will be one hell of a shakeup.

It is scary to think about because automated exploits could perhaps be scaled up and cause real mayhem. Hopefully it doesn't have to get that far before some elementary redesign of network architecture inside of vehicles. It's not rocket science. Just separate the safety critical network (which include brakes, steering, etc) from the non critical information and entertainment network.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact