The Death of the Von Neumann Architecture
codersnotes.com
codersnotes.com
The reasons for Apple, Microsoft, and other vendors for restricting execution of native code are various, but mostly related to security and maintaining control of the ecosystem.
It is fine to complain about that desire for control. But it is not necessary to view this as a computer architecture issue at another level.
I'm not complaining about desire for control at all. I'm complaining about the inability for a program to treat it's code and data as the same medium.
That is very much the key tenet of a Von Neumann architecture.
Also, digital watches of all sorts have pretty much always been Harvard architecture for the past N years. From a use case perspective, the iWatch should be treated as a glorified digital watch, not a minified iPhone. Seen from this angle, I disagree that the iWatch is a "step backward". But I do agree with you that in general, Apple is annoying for deliberately limiting freedom.
As far as the iwatch being just a watch, the same thing could have said of the iphone. It was a phone, only cooler. Almost a decade later, ios devices are the platforms where many users do a significant fraction of their computing. And while ios devices may not require on bitcode submission, they limit the users freedom in a way that is fundamental. Image a world were every x86 computer sold post 1995 (outside of the server space) could only run Windows.
Besides, even if you own a "creation machine", you'll often be catering to the market of restricted devices (case and point: gecko on ios).
EDIT: I'll grant you may be right in the specific sector of non-computing electronics (watches, calculators, etc).
Never mind that iOS is getting more "desktop-ish" by the release.
You might as well argue that Linux isn't really a Von Neumann architecture because you can only execute files that have the executable bit set.
The concepts that I would categorize as the von Neumann architecture are incredibly basic. Equating his plan for computer design with a difference between storing program/data vs. just program misses the mark. Von Neumann wasn't at all concerned with this difference.
Take this quote from "The Computer and the Brain": "Large digital machines are made up of 'active' organs and of organs serving memory functions-I will include among the latter the 'input' and 'output' organs.."
You can see how basic his thinking is by today's standards, and why Dijkstra later criticized him, and other American computer scientists for anthropomorphizing machines. He talks about 'an organ serving a memory function', he doesn't even talk about main memory because that word isn't in use yet.
You're interpreting von Neumann from a modern context. You don't understand just how basic and fundamental his ideas were.
You don't like closed systems? Fine, but calling those systems "Harvard" architecture(s) is kind of misleading.
In Microchip PIC land, that would be especially inconvenient, because of the different data vs. instruction size.
Now there is a pretty sound reason for making your code segment read only, and the author touches on it, which is that if you are running third party code, because it limits the attack surface for security exploits somewhat.
But then he goes off the rails with this claim, "What really struck me was that there was no flexibility here; no way to for a program to make changes to itself or build new subprograms, even if Microsoft approved it."
The next topic on the required reading list should be "Turing complete" :-) It is entirely possible to write a piece of code which is both a core interpreter, and the byte codes on which that interpreter is operating. And including in the byte codes a means to read, modify, and re-execute any previous byte codes. The sum of actions of course will be constrained by what can be expressed in a byte code but given that, you are free to do what ever you want.
And of course any interpreter which was interspersing its data and executable byte codes in the same chunk of memory, well that would be a Von Neumann architecture :-)
[1] Harvard machines ultimately fell out of favor because you could end up with left over code store and not enough data store for an application.
> Now there is a pretty sound reason for making your code segment read only
Sure, but I've had enough situations where ability to generate code made inner loop 2-3x faster, by removing branches and constant folding. Difficult? Yes! Error prone? Yes! Fast? Hell yes!
> It is entirely possible to write a piece of code which is both a core interpreter
Yes, but it's going to be 10-100x slower.
Collected together for one response ...
> On a machine where programs are supplied as bytecode,
> there are indeed two disjoint regions.
> The bytecode sits in it's own region. You can't
> touch it from the data region.
Doesn't that depend on how you define the byte code? If I define byte codes as follows, 0x01 0xnn 0xmm load a byte from offset 0xnnmm in memory.
0x02 0xqq load qq into accumulator immediate
0x03 0xnn 0xmm store accumulator into 0xnnmm in memory
0x04 0xnn 0xmm set program counter to 0xnnmm
0x05 increment accumulator
Then I put 02 00 05 03 00 01 04 00 00
Into memory, and "run" my byte code, This program self modifies the load immediate value continuously.When Java defined its byte code it went out of its way to avoid 'pointer arithmetic' to make the language safer but even in Java's heap model the memory to store data and executable content is the same memory, it is an artifact of the Java byte code definition that it doesn't allow for self modifying Java code, it has nothing to say about byte code in general. And the point where things get confusing for me is that architecture is reasoning about structure in general, where as implementation is reasoning about structure in specifics. So there is nothing architecturally significant about byte codes with respect to computer architecture, other than you can simulate a variety of architectural choices by how you define your byte codes.
> So every program needs to be wrapped in an
> additional VM?
No. The point was that your blog post conflated computer architecture with an implementation choice made by a particular vendor. Many vendors have chosen to create implementations which make implementing self modifying code difficult. They have their reasons, and you elucidated on two of them, rights management and security.That they have done so, gives them some benefit, and it comes at some cost to you, the developer.
When looked at from a cost / benefit point of view, I would be interested to read about how those design choices constrain your ability to deliver a compelling game experience, or a needed capability. To often these things are only discussed in terms of what they do for party A or party B and rarely do we get some thinking on what we cannot have because of the constraints imposed by their implementation choice.
I guess I'm using the term 'bytecode' to refer to systems such as Java, where they don't let you mess around with it much. It's almost always the case for any implementation of a bytecode system that they don't treat it as writeable data.
On a machine where programs are supplied as bytecode, there are indeed two disjoint regions.
The bytecode sits in it's own region. You can't touch it from the data region.
Every modern machine is a Modified Harvard Architecture.
http://en.wikipedia.org/wiki/Modified_Harvard_architecture#M...
Well, this is just not true if you consider all modern computing systems rather than just desktop computing.
Every modern microcontroller is either Harvard, or pure Von Neumann. And there are billions upon billions of these shipped every year: ARM microcontrollers ship at a rate of 35Hz! Generally the lower power parts tend to be Von Neumann.
"The Coming Civil War over General Purpose Computing": http://boingboing.net/2012/08/23/civilwar.html
"The Right to Read": https://www.gnu.org/philosophy/right-to-read.en.html
Or perhaps you’re running on an OS that doesn’t have any support for hot-patching a running executable with new code. And you think “I know how to write a programming language runtime that can do that.” Perhaps you’d seen how Erlang can do it, and wanted to try it yourself.
Dynamic code upgrade is really rare in general. The most that's usually done in mainstream practice is to pass socket fds to a newly exec()ed child instance, or some other form of superserver/pre-opening, a la inetd, UCSPI or whatnot.
What if you were on a system that didn’t support DLLs or shared libraries, and you thought it’d be kinda useful to invent something like that?
Depends on what your purpose for shared libraries are. If you just want a plugin system, then the traditional way w/o shared libs is to use some form of RPC so as to coordinate forked OS processes.
Finally, the majority of our programming languages are firmly in a von Neumann model, so it isn't quite dead yet. Not sure if read-only code segments are enough to deliver its eulogy, either.
How many years will it take for an antitrust regulator to level this playing field?
Are you trying to say that not being able to run the faster JIT version of LuaJIT on iOS is anticompetitive?
If a regulator took action, Apple would have a choice of giving up JIT on Safari or permitting JIT for all apps on the platform. Practically speaking, they could not impose a JS performance penalty on every user of mobile Safari. It is more likely that Apple would permit JIT for all iOS apps. This would then benefit LuaJIT and all other dynamic languages on iOS.
I'm still not sure you could bring an antitrust case against them- to apply antitrust law they have to be abusing monopoly power, and they don't have a monopoly on mobile computing- but it makes more sense. Thanks.
Apple can either:
• give up their iOS app distribution monopoly (allow other app stores)
• give up their iOS browser monopoly (allow other performant browser apps)You can monopolize your own ecosystem all you like, so long as your platform doesn't have monopoly power.
If iOS eats up all Android's marketshare and becomes the only platform worth a hoot, then you can start filing antitrust cases for this kind of thing.
The only reason Microsoft's IE bundling with Windows was antitrust was because Windows owned just about the entire personal computing market. Otherwise it would have been fine.
Some say Intel tolerates the existence of AMD, because if AMD completely disappears Intel suddenly becomes a true monopoly power and vulnerable to all kinds of antitrust suits.
We know the formula now, which Microsoft ignores since their market is companies. The formula for selling computers to people seems to be "be in control of both hardware and software to provide the best native experience". It's not a secret, anyone that wants to can start a company and compete with Apple. All regulators can do is make Apple's job harder for themselves which will result in bad products and cost taxpayers money, a lose-lose situation.
Unlike the oil companies of yesteryear, or even a browser that is supposedly "baked into" an operating system, the remedy here is not logistically complex: the backdoor is already known to exist -- it can be extended to some competitive products.
I'm talking about the formula that seduced the customer. "Factory financing" did not seduce the customer - one company in charge of the whole computer (as opposed to one company making the hardware and another making the software) is what seduced the consumer. The fact that company makes computers for end users, not company employees, is what seduced the consumer.
> Careful intervention can help to restore balance.
Like non-violent spanking, careful intervention is an oxymoron. Unless you can show an example where no one was harmed by government anti-trust laws being applied.
Restrictions on code execution strike me more as business controls (and yes, assaults on freedom) than real security measures.
The presence of a JIT makes things trivially abusable for the attacker and is a big security risk.
I also agree you have the freedom to complain about things over and over endlessly but yawn
The only power we have is buying power. Ranting and politically complaining as the article does won't change anything.
Yes it does, it educates readers, it can convince others not to buy iOS devices.
Other articles have certainly convinced me of that, for which I am very thankful to the authors.
These articles are not for Apple, they are for the people. People like us in Internet forums, who then discuss them, learn something (or not), and then make a decision (or not).
That's what this article is trying to fix.
In case of Microsoft IE, every other company was able to provide software for Windows without MS vetoing it. This situation is different - Apple is 100% controlling the entry into market for other entities.
Another commenter also had a good point about global markets... Apple has that market share in the us... It's actually very small globally.
You make valid points though... Just saying that this stuff moves very fast.
I think that we, software developers have a moral obligation to make ethically right decisions. Supporting or ignoring app store business model(1) is in my opinion not one of them.
(1) this is, having one entity to control entry into market for everyone else - this creates monopolies - no, it does not matter that Apple has only 42% of the smart phone market share - it has 100% of iOS market share and is using its monopoly power to control this market.
With good ASLR, ROP is not possible without relying on information leak bugs which are finite. So the cost for the attacker increases and it gets harder and more time intensive for reliable exploits to be written.
Allowing JIT for everything is a TREMENDOUS security violation, since it's trivially abusable and page permissions are irrelevant. There are just too many ways for clever attackers to abuse it.
> It's not that simple. ROP relies on known or predictable addresses and pretty much all modern OSes have some form of address space layout randomization (which keeps getting better and more sophisticated).
> With good ASLR, ROP is not possible without relying on information leak bugs which are finite. So the cost for the attacker increases and it gets harder and more time intensive for reliable exploits to be written.
> Allowing JIT for everything is a TREMENDOUS security violation, since it's trivially abusable and page permissions are irrelevant. There are just too many ways for clever attackers to abuse it.
Of course ASLR makes ROP harder. It makes all exploits harder. I still don't agree with your last paragraph. As someone else mentioned, good JIT implementations never leave code both writable and executable. It's simply not the case that "page permissions are irrelevant". Page permissions are central because they defeat the specific attacks you have in mind. A JIT is no more vulnerable to them than the dynamic loader is.
I still don't buy that banning PROT_EXEC buys you any protection from attackers exploiting applications.
On the other hand, banning PROT_EXEC provides plenty of protection against uppity application developers trying to "abuse" the platform you "own" by attempting to program in unapproved ways.
To add, nothing prevents from allocating pages from random addresses to get protection similar to ASLR.
It can actually be harder to attack dynamically generated code, because instruction offsets and instructions used will vary from application invocation to another. You could even do intentional variations to ensure no relative instruction offsets are deterministic. So dynamically generated code can have not only have random address (ASLR) but also random relative offsets. Obviously statically compiled code must have those offsets static, known by the attacker.
ASLR just means you don't necessarily know where. But once the attacker knows where or has some clever trick so it doesn't matter, it's game over. Unfortunately the creativity of attackers getting around ASLR seems to be endless.
That's like saying there's no point in locking your doors because thieves can go in through the window. Instead, you're better off applying separate defenses against separate attacks: read-only code against code injection and other defenses (like CFI or randomization) against ROP.
> Besides, any secure JIT will only keep a page either writable or executable, but not both in the same time.
Sure, but it's amazing how few actual JITs do that. V8, for example, actually maps its entire code cache as RWX.
We can take this a step further and say that if IBM locked down its PC back in the 80s, we wouldn't have Linux!
Not really. Windows 10 apparently allows universal Windows apps to call VirtualAlloc() and VirtualProtect().
http://blogs.msdn.com/b/chuckw/archive/2012/09/17/dual-use-c...
Yes, but they're useless for this purpose. VirtualAlloc is mapped to VirtualAllocFromApp. Which means you can't allocate executable pages.
You can't make a page executable. Nor can you make executable pages writable.
So you can't run dynamically generated code at all in a Windows 10 universal app.
Actually it benefits Apple, which is why they did it. Or is the author arguing it doesn't benefit Apple? However, I didn't see anything substantiating that in the article.
I would consider this article's content far more substantial if there was an example of this architecture being used in, say, Linux 4.
It used to be that the owner of the operating system did not have any say about what other developers can write to that platform.
It used to be that "online lobbyist" was not a job description, http://www.washingtonpost.com/blogs/monkey-cage/wp/2014/06/0...