Live data from Hacker News

32-bit x86 Position Independent Code – It's That Bad

ewontfix.com

91–100 of 104 posts

Re: 32-bit x86 Position Independent Code – It's That Bad

#91
post #39
post #2

The more I play around with musl (the author's C library) the more I'm convinced dynamic linking was not worth the trouble.

There is however, an important security benefit from PIC: ASLR. It's not a silver bullet, but can stop a range of vulnerabilities from being reliably exploitable usable unless an memory leak is also available. Even if you so far as control the instruction pointer as an attacker, you might just not know where to jump to in the target address space...

ASLR is a pretty hackish solution to the main problem, which is that the function call stack and parameter stack are combined. The problems that ASLR mitigates don't exist in languages like Forth, where there are two separate stacks - a call stack and a separate parameter stack.

Re: 32-bit x86 Position Independent Code – It's That Bad

#92
post #86

Earlier quoted context omitted.

We still have embedded 8-bit. Expect embedded 32-bit approximately forever.

Yeah, but we all know the embedded 32-bit stuff that's going to be around forever is ARM, not x86.

We hope it's not going to be x86… I dunno. I still see too many embedded 486/686 clones around for my liking, and Intel is now trying to get into the whole IoT business with x86-32 Quark CPUs.

Re: 32-bit x86 Position Independent Code – It's That Bad

#93
post #39

Earlier quoted context omitted.

There is however, an important security benefit from PIC: ASLR. It's not a silver bullet, but can stop a range of vulnerabilities from being reliably exploitable usable unless an memory leak is also available. Even if you so far as control the instruction pointer as an attacker, you might just not know where to jump to in the target address space...

ASLR is a pretty hackish solution to the main problem, which is that the function call stack and parameter stack are combined. The problems that ASLR mitigates don't exist in languages like Forth, where there are two separate stacks - a call stack and a separate parameter stack.

This is really an ABI issue, more than a language one. I'm not sure anything in C requires a combined stack. Plus, processor arches like ARM and POWER use link registers rather than a stack to store the return address. Its the ABI that then chooses to put the LR on the parameter stack. Even on x86 SP could be dedicated as a function stack and separated from BP (or pick another x86_64 register) as the parameter stack.

Of course being an ABI issue, probably makes it really hard to solve, and hence hacky solutions abound. (actually its probably pretty easy to solve given LLVM, just impossible to get anyone to accept).

Re: 32-bit x86 Position Independent Code – It's That Bad

#94
post #71

Earlier quoted context omitted.

"It's a convention." Does Minix use that convention? How about BSD?

"The calling convention of the System V AMD64 ABI is followed on Solaris, Linux, FreeBSD, Mac OS X, and other UNIX-like or POSIX-compliant operating systems." http://en.wikipedia.org/wiki/X86_calling_conventions#System_...

int80h.org

Anyway, the original question was _why_ does Linux use registers to pass arguments. Arguments can be passed on the stack, but Linux chose to use registers. Why this choice over the other option?

Do you know the answer?

Just curious.

Re: 32-bit x86 Position Independent Code – It's That Bad

#95
post #73

Earlier quoted context omitted.

Are you suggesting that the original purpose of shared libraries relates to patching software? Others seem to be suggesting that the emergence of dynamic linking was a response to general limitations in secondary storage and memory. Limitations that no longer exist.

Does it have to be the original purpose to be a useful feature?

Is this supposed to be an answer?

I like marssaxman's comment.

I'm not sure I would call this a "feature" because I think of "features" as being intentional and if marssaxman is correct, this justification for shared library use was an accidental side effect.

But I have limited knowledge of the history behind dynamic linking. Hence my questions. I am just curious.

Re: 32-bit x86 Position Independent Code – It's That Bad

#96

Earlier quoted context omitted.

ASLR is a pretty hackish solution to the main problem, which is that the function call stack and parameter stack are combined. The problems that ASLR mitigates don't exist in languages like Forth, where there are two separate stacks - a call stack and a separate parameter stack.

This is really an ABI issue, more than a language one. I'm not sure anything in C requires a combined stack. Plus, processor arches like ARM and POWER use link registers rather than a stack to store the return address. Its the ABI that then chooses to put the LR on the parameter stack. Even on x86 SP could be dedicated as a function stack and separated from BP (or pick another x86_64 register) as the parameter stack.…

Hm, you may be right that nothing in C requires it. But things like POSIX pthreads do - e.g. pthread_attr_setstack() only lets you set a single stack address and size.

So yes, you'd have to create a new runtime from the ground up, not just a new ABI for an existing API.

Re: 32-bit x86 Position Independent Code – It's That Bad

#97
post #60

Earlier quoted context omitted.

> Instead of PIC, a big tables of places to patch with the final position. Among other things, because that means the text section has to be writeable, and can't have a shared mapping across processes unless it's mapped in the same place in every process, which breaks address-space layout randomization (ASLR).

Off topic, but does anybody know if there's a way to turn off ASLR e.g. while debugging (honestly, i'd be interested if you can do this on any platform)? I'm pretty confident the answer is no, but it can really be a pain sometimes...

setarch x86_64 --addr-no-randomize myprogram args...

(or -R for short)

Re: 32-bit x86 Position Independent Code – It's That Bad

#98
post #40
post #36

Earlier quoted context omitted.

mincore is a system call and does not take a pid parameter. This means it has to be executed by each process individually, which would require injecting code into each running process and executing it in some way. Unless there's a tool which makes this extremely simple (maybe Intel's pin?), I believe that writing a kernel module is simpler. The module's init function tallies up the pages and writes out the result int…

You don't need to run mincore() on target pids - you just need to write a tool that opens(O_RDONLY) and mmaps(PROT_READ) each library file, then calls mincore() on each page in the mapping to find out which pages of the library are loaded shared. The results of mincore() in one process with a shared mapping of a file are enough to tell you how much of that file is loaded shared system-wide.

Just found out that physical page information is exposed through /proc: https://www.kernel.org/doc/Documentation/vm/pagemap.txt

Re: 32-bit x86 Position Independent Code – It's That Bad

#99
post #94

Earlier quoted context omitted.

"The calling convention of the System V AMD64 ABI is followed on Solaris, Linux, FreeBSD, Mac OS X, and other UNIX-like or POSIX-compliant operating systems." http://en.wikipedia.org/wiki/X86_calling_conventions#System_...

int80h.org Anyway, the original question was _why_ does Linux use registers to pass arguments. Arguments can be passed on the stack, but Linux chose to use registers. Why this choice over the other option? Do you know the answer? Just curious.

It's because in theory, it's faster to copy the values to registers than to have to push them all to the stack and then have the callee pop them. At least that was the thought behind Microsoft's __fastcall, which was their original version of a calling convention using registers, though in that case it seems the benchmarks aren't conclusively in support of the theory.

Re: 32-bit x86 Position Independent Code – It's That Bad

#100
post #79
post #5

Earlier quoted context omitted.

As a programmer who unfortunately is suckered into doing devops at times, the more I get to just update the openssl library instead of the whole OS whenever a security flaw in openssl is announced, the more I'm convinced that dynamic linking was very well worth the trouble. Funny how perceptions change depending on the angle you're looking at a problem.

I personally would like to see a distribution have a mixed policy -- dynamic linking against core libraries that are part of the default / basic OS install, and static linking against low usage libraries. That way, you keep the "update one library package to fix a bunch of programs", yet you also reduce cross dependency issues by limiting the number of library packages a given program is dependant on.

IIRC Snowflake[0] does that (but also has a very experimental per-process view of /usr -- pretty cool stuff, really, but takes some getting used to).

[0]: https://github.com/GregorR/snowflake

Post reply on HN