Posted by
Hemos
on from the crushing-them-beneath-your-heel dept.
A reader writes:"There's a story on ZDNet that describes how Theo de Raadt & co. are hoping to eliminate buffer-overrun exploits for good. On closer inspection, it's a scheme to stop a buffer-overrun leading to executable code. It doesn't stop the buffer-overrun itself."
47 comments
New idea?
by
Anonymous Coward
·
· Score: 0
Isn't that basically the same as the Linux patch making stack non-executable?
Re:New idea?
by
Anonymous Coward
·
· Score: 3, Informative
Re:What about
by
Anonymous Coward
·
· Score: 1, Insightful
Great! You all fuckin bitch about how Linux is oh-so-safe
every time there's another improvement to OpenBSD!
Then why the fuck Linux fuckin chearleaders
can't say that there was absolutely
no security hole in the last six years in the Linux OS?
You know why? Because there were tons of fucking
truck size holes, that's why!
Now please stop bitching about every innovation in OpenBSD,
until your beloved Linus Torvlads make his OS as
secure as OpenBSD is today.
Until then, please shut the fuck up,
because you seem to know jack shit about security.
Here is 50 cents. Buy some reading comprehension classes.
The parent poster is obviously asking why nobody even uses those libraries or projects with Linux itself--not why don't they use them with OpenBSD. Asking why the OpenBSD project doesn't use a (probably) GPL solution to this problem is like asking why the Pope doesn't buy dungeon porn.
Until then, please shut the jiziont up, because you seem to have jack shat for reading comprehension.
Already slashdotted
by
Anonymous Coward
·
· Score: 3, Informative
Software tweak may make operating systems safer 09:43 Monday 14th April 2003 Robert Lemos, CNET News.com
The OpenBSD project is making changes in its latest operating system release that it believes could eliminate a class of security bugs that has plagued computers for decades
The OpenBSD project hopes new changes to its latest release will eliminate "buffer overflows", a software issue that has been plaguing security experts for more than three decades.
Theo de Raadt, the project leader for the group, believes that the group's latest improvements to the Unix variant, due to be released on 1 May, will make causing a buffer overflow extremely difficult, if not impossible. A buffer overflow is a memory error in software that allows an attacker to run a malicious program.
"I could say that I am killing buffer overflows, but I am in the security community, so I have to put it in quotes," he told attendees at the CanSecWest security show on Thursday.
The memory bugs have resisted extermination for almost 30 years, and de Raadt said that any claims that an open-source group has done so would need to be tested.
Some attendees are already incredulous that the changes will eliminate buffer overflows. "It's just adding another layer" to the security, said Nicolas Fischbach, senior manager for security at Colt Telecom, a European communications provider. "It won't make a huge difference because there are always bugs that are found in software."
An overflow exploit generally works when an attacker sends a program requesting too much information. The data usually includes two components: one that crashes the application and one that's either a program or a memory address that points to a program that the attacker would like to run. When the application crashes due to the first component, the operating system will execute the second.
The OpenBSD team hardened the operating system to this type of attack using three tactics.
The group randomised where in memory the "stack" -- a structure that holds applications and their data -- resides, so that code designed to exploit buffer overflows will have to be tailored to the system's memory layout.
"Buffer overflows take advantage of a certain memory layout," de Raadt said. "It's a tiny waste of memory, with very little overhead, but it makes things a little bit more difficult. We are trying to make the (code) crackers work a little bit more."
In addition, the group restructured how critical addresses are stored on the stack, so that it's harder to get buffer overflows to result in a running program. The team placed a small tag, called a canary, in the memory structure to detect if addresses had been modified, a common method hackers use to get a legitimate program to run malicious code.
Finally, the group found a way to hack the BSD file system and divide main memory into a writable portion and an executable portion. Pieces of programs and data, known as pages, that are stored to memory will be placed into one of the two areas.
"We want to make sure that no page is both executable or writable simultaneously," he said. "The goal is that no hackers should be able to write code and then execute it."
The problem for the OpenBSD group is that while 64-bit processors have such memory protections available, the most-popular 32-bit processors don't. So the group has had to work around the issue and break up a computer's memory into writable and executable areas.
"You can draw a line in the sand -- before that line you can execute, above you can't," de Raadt said.
While the other security features will be available in the 1 May release, the protected memory page structure for 32-bit processors -- such as Intel x86 chips and the PowerPC chips -- won't be ready for another six months, he said.
The research was funded by a $2.3m (about £1.5m) grant from the Defense Advanced Research Projects Agency (DARPA) to the OpenBSD Project, but the latest changes go be
It's a shame that segments work the way they do.
by
wowbagger
·
· Score: 4, Interesting
I'm about to say something I would have never dreamed of saying a couple of years ago.
It is a shame that Intel made segments work the way they do, because a minor tweak and segments would have been the perfect way to prevent buffer overflows in hardware.
Consider: what if, instead of segment descriptors having to live in the GDT and LDT, they could be loaded into a register from a normal memory limit? True, they would then have been useless for OS level protection, but I assert that is what the page map is for (yes, the page mapper didn't exist prior to the 386, and enhanced segments showed up in the 286).
In some of the DSPs that I work with, you have registers to specify a region of memory. When you access off these registers, memory bounds are enforced by the chip (this allows for circular regions of memory, bit reversed addressing, and other weird things you need when doing DSP work).
What if you could have done something like this: buffer:
ds 1024 ; a buffer of stuff buffer_descr:
dd buffer ; where buffer starts
dd 1024 ; sizeof(buffer)...
LDPROT ES,buffer_descr ; set limits checking
LD ES:(ESI),EAX ; store to buffer with checking.
Thus, any access out of bounds would throw a SIGSEGV.
Then, the code could have provided protection against overflows without explicit checking on every array access. True, this would not protect you if all you were given was the buffer address, but in the presense of this sort of hardware, GCC could have been modified to make a char (*a)[] (pointer to array of char) be three elements - base, sizeof(), index.
Great ideas! But what about the "file system"?
by
Hanashi
·
· Score: 2, Interesting
These security measures sound pretty good, though
I think that the memory layout changes and the
segmentation might cause some problems until
developers get used to the new model. It's probably
worth it, though, in the long run. The extra
layers seem like good precautions to take,
especially the randomized layout. Most of the
canned exploits these days come with scads of
pre-computed parameters for all the different
OSes. Randomized memory layouts will make this
sort of thing much more difficult, though I'm
sure the exploit writers will eventually
learn to compensate.
But my real question is about that ZDNet article.
It said that the segmentation measures came from
"hacking the BSD file system". It sounds to
me like the reporter got confused. Can anyone
familiar with the code comment on this?
-- Check out my eclectic infosec blog at InfoSecPotpou
Re:Great ideas! But what about the "file system"?
by
Schubert
·
· Score: 1
The article is referring to the upcoming 3.3 release and the code involved in helping stop buffer overflows is the propolice protection added to gcc and the entire distribution (and most of the ports when you compile them) are done so with propolice (google for it). 3.2 has already added non-exec stack protection to (every?) platform and a massive setuid binary reduction (I think they went from 40 in 3.1 to 9 in 3.2). 3.3 also implements privilege seperation in alot more places, including X Windows.
Now it appears as development for 3.4 is starting up since the release will be coming soon, is a massive audit of the codebase to eliminate dangerous functions (strcpy, strcat, sprintf, etc).
In short... they've set a pretty high standard and I hope a number of other free unixes pick up on the ideas. It'd be nice to hear on a monday morning "Oh look another vulnerability in SomePopularUnixDaemon... but its not exploitable on LongListOfUnixes"
-- -- schubert
quick suggestion ...
by
Anonymous Coward
·
· Score: 0
A simple way for the average programmer: use the "safer" C functions.
Use strncpy instead of strcpy. Use strncat instead of strcat. Use snprintf instead of sprintf.
And so on.
I bet this would fix a huge number of overflow bugs.
better yet, strlcpy and strlcat and their brethren. they're becoming more common on more and more platforms. solaris has them.
-- vodka, straight up, thank you!
Re:quick suggestion ...
by
Anonymous Coward
·
· Score: 0
strncpy() is baaaad. If the source string is too long then the destination doesn't get null-terminated. Someone suggested strlcpy and strlcat(), but that's not ubiquitous. snprintf() is probably a better bet:-)
I really appreciate the effort going into OpenBSD making it more secure and robust, but I hope the option of keeping it a simple BSD without the innovative security features, remains. Part of the reason Ive used BSD in the past is its simplicity and predictability across the versions. OpenBSD, opposed to NetBSD and FreeBSD is the 'simplest' BSD outside of the seccurity changes and I hope users have the option of not using the page protection, encrypted ram and filesystems, chrooted services and other stuff.
Would also be nice to have the drivers of FreeBSD ported to OpenBSD. I had to choose Linux to be able to use my Olicom 3140 tokenring card.
Rants aside, thanks to Theo and the team, for giving us an OS we can be confident, is really secure with no compromises.
-- "Give orange me give eat orange me eat orange give me eat orange give me you."
-Nim Chimpsky
Is the randomization per machine, per build, etc?
by
blinka
·
· Score: 3, Interesting
It's hard to be sure from the article itself (given that reporters are unlikely to understand the distinction, much less care), but in what way is this stack manipulation random? Quoting the article:
The group randomised where in memory the "stack" -- a structure that holds applications and their data -- resides, so that code designed to exploit buffer overflows will have to be tailored to the system's memory layout.
but this is still vague. It could be:
Per kernel. (All processes on this box have the same stack layout)
Per process. (All processes have a different stack layout, though threads and forked versions may have the same.)
Per binary. (Each program's stack layout is determined at compile time and will not change on invocation.)
Completely random (Each program is different every time, or better yet each function call is different each time.)
This would have a very import impact on how well a hacker could brute force your processes. If a given process always has the same stack layout then you can eventually brute force it, just like we currently can brute force offsets. The bar is higher of course - only one variable is being manipulated - and a hacker will probably go to easier machines before too long. But a truly randomized per process invocation or better yet per function call invocation would be such a moving target that it should be extreemly unlikely to succeed. I'm really excited.
'"But it happened because the DARPA grant happened, because when you throw a bunch of... guys into a room and get them drunk, this is what you get." De Raadt was careful to point out that the group paid for its own beer.'
------------ ...beer? I would really like to know what sort of beer is the best inpirational beverage for coding? Is there a different best beer per language/platform? Or do some platforms require liquor instead? I hear Java is much better with Irish cream...
This quote clearly demonstrates that free as in beer is not free at all. Even the most notorius free software developers actually pay money for their beer.
Gates said hardware should be free.
Stallman said software should be free.
I think beer should be free.
beer? I would really like to know what sort of beer is the best inpirational beverage for coding? Is there a different best beer per language/platform? Or do some platforms require liquor instead? I hear Java is much better with Irish cream...
I am firmly of the opinion that assembly requires 190 proof pure grain. Especially on the fucking IBM 360/370. Nothing else dulls the pain.
Actually, there is a more than decent possibility that Big Rock will be donating a KEG to the event... so they probably will have free beer - at least at the BBQ.
buffer over flow exploits not truly eliminated
by
mzs
·
· Score: 3, Interesting
It is clear from gems like this from the article that the reporter was confused so that it is impossible from the article itself to really undrestand how the three approaches would work:
"An overflow exploit generally works when an attacker sends a program requesting too much information. The data usually includes two components: one that crashes the application and one that's either a program or a memory address that points to a program that the attacker would like to run. When the application crashes due to the first component, the operating system will execute the second.
It is important to point out that this looks to be yet another in the attempts at making buffer over flow exploits difficult yet not quite impossible. Once you put return addresses on the stack (the same stack with an over flow) an exploit can jump to any place it likes in text even without an executable stack.
The details about the tag around import addresses and the random stack offsets could make exploits _very_ difficult. If the base of the stack is random from one invocation of the program to the next that does not give much more once you cannot execute on the stack so it is probably more than that. Also if the tag around important addresses (say the address of the buffer to system(3C)) incorpates randomness from one invocation of the program to the next then it would be hard to over flow a buffer and exploit it.
In any case even if you had a sytem where a buffer over flow could not be exploited to run arbitrary code but almost any random junk will still crash the broken prorgam, that does not do much to prevent DoS now does it.
Re:buffer over flow exploits not truly eliminated
by
cdn-programmer
·
· Score: 2, Informative
I think you are mistaken. They have put in "canary" values in the call. The function prologue and epilog code has been modified. What happens is that there is a random value placed essentually as an "extra" parameter in the call. When the function does a return this value is tested and if the value has changed then the function stops instead of returning. Yes a DOS is still possible but you cannot smash the stack and expect to succeed.
The reason you cannot smash the stack is that when you overflow it you have no way of knowing what the canary value is, so the function will stop before it even executes the altered return.
Its a very good and painless feature and one that adds a MINIMAL amount of overhead.
IMHO the explaination that is quoted is misleading or just plain rong. I have never heard of a crash being able to cause an operating system to "execute the second". Well - perhaps in a debugger... but in the case of a debugger we are not in a normal environment.
Re:Is the randomization per machine, per build, et
by
Anonymous Coward
·
· Score: 0
I just ass/u/me it's per process. No?
Includes ProPolice
by
dwheeler
·
· Score: 4, Informative
The buffer overflow work is based on StackGuard,
which was originally developed as a gcc extension
and tried out in Immunix (a Linux distribution).
However, instead of StackGuard, they're using
IBM's ProPolice. ProPolice implements the same
basic idea, but the patch itself works more cleanly
across CPU architectures. Also, ProPolice has
a simple optimization - it only enables the
canary protection if the function has a
char (like) array. This is a heuristic, but
a reasonable one - most buffer overflow attacks
exploit such arrays, and by doing this
ProPolice has a lower performance overhead
(without losing much in the way of protection).
Libsafe only protects a few built-in functions;
it's not a bad idea, but it's FAR less
effective than StackGuard or ProPolice.
The Openwall kernel patch is actually a
collection of nifty capabilities.
The "no executable stack" option is probably
what you mean, but it turns out that there's
a trivial way around it... so that part is
only effective BECAUSE few people use it.
Openwall has other stuff that's nice, though.
I think the reason these capabilities aren't
in use everywhere (yet) is the
conservatism of most distributions.
Many distributions worry about any performance
loss or compatibility loss. OpenBSD's
primary focus is on security, so losing
performance or backwards compatibility is
not as serious an issue for them.
I have hopes that these features will become
more mainstream.
Mandrake has provided these for a while
by
OneInEveryCrowd
·
· Score: 2, Informative
The Mandrake distribution provides the Grsecurity package in 9.1. Prior to that they had the openwall patch with some others. These aren't in the standard kernel but you can compile them in yourself or use the kernel-secure rpm. The libsafe package has been provided at least since 8.1, all you have to do is type "urpmi libsafe". Libsafe used to break the hardware clock reset feature in the shutdown scripts but they may have fixed it.
I used all this stuff in Mandrake 8.1 and there was a noticeable performance hit in some situations but I left in it anyway.
No, it;'s a shame how kernel developers use them
by
AHumbleOpinion
·
· Score: 1
It's not Intel, it's the kernel developers. The developers choose to make the code and data segments overlap, that is the error.
No, it is not the kernel devs fault.
by
wowbagger
·
· Score: 2, Interesting
If I can overwrite a buffer, I can screw you machine. I don't care if the stack is not executable - I can modify the return address and fake a call to exec with "/bin/bash" as the args.
If auto storage is removed from the call/return stack, I can overwrite another variable somewhere else, perhaps tricking your program into thinking it is debug mode. It gets harder, but not impossible.
What I was discussing was fine-grained memory bounds checking - which you simply cannot do when all you have is 8192 LDT and 8192 GDT entries, some of which have to be IDT gates, system call gates, task state segments, etc.
Overlapped code/data a mistake. BOUND instr. avail
by
AHumbleOpinion
·
· Score: 2, Interesting
I understand your point, I understand it's usage, it does not change the fact that kernel developers made a mistake with overlapped code and data. "It gets harder, but not impossible" is a weak rationalization. Furthermore Intel's BOUND instruction does much of what you suggest. It verifies an address is in a particular range and throws an exception if it is out of range.
Re:Overlapped code/data a mistake. BOUND instr. av
by
wowbagger
·
· Score: 2, Interesting
My statement about "it gets hard" was for a seperate hardware stack and auto data storage, not seperate code and data spaces.
Even if the program space and the data space were completely seperate I can trivially smash the stack and get a shell - again, all I have to do is overwrite the current function return address with the address of execv, and the preceeding addresses with a bogus return address and pointer to the strings "/bin/sh", 0, and 0. No code segment overlap needed.
Secondly, the BOUND instruction would have to occur before EVERY potential operation, bloating code size (bu-bye cache) and slowing the machine down.
Your assertion that seperate code and data spaces in the kernel is like locking the doors on a convertable - it may make you feel good, but it does not really do anything.
Lastly, most stack smashes happen in user space, not kernel space. If you wish to critizize anybody, criticize the developers of GCC and libc.
Re:Overlapped code/data a mistake. BOUND instr. av
by
AHumbleOpinion
·
· Score: 2, Interesting
Secondly, the BOUND instruction would have to occur before EVERY potential operation, bloating code size (bu-bye cache) and slowing the machine down
No, it is not needed globally. It can be selectively used just like the code you suggested previously. Secondly, your solution bloats the code as well, your LDPROT instruction and segment override prefix consumes cache space as well.
Your assertion that seperate code and data spaces in the kernel is like locking the doors on a convertable - it may make you feel good, but it does not really do anything
Lastly, most stack smashes happen in user space, not kernel space...
You misunderstand. I would have preferred code and data segments that did not overlap. That applies to both the kernel and user mode.
What this would do is prevent an entire class of attack where arbitrary code is introduced by an overrun and then executed.
... If you wish to critizize anybody, criticize the developers of GCC and libc
Not for code/data overlapping, the kernel developers are the ones who decided the segmentation model. Possibly for the lack of an option to insert BOUNDS instructions, but gcc may actually have a "check array bounds" option.
Re:Overlapped code/data a mistake. BOUND instr. av
by
wowbagger
·
· Score: 2, Interesting
Actually, my solution does not bloat the code as much - you would incur the penalty of loading the protection once per scope - after that all subsiquent accesses via that register are "free". With the BOUND instruction, you have to insert it before every access, unless you can somehow insure that the check is unneeded (e.g. a loop index where you can BOUND the start and the end value of the loop var).
As for the code/data space issue - the issue at hand is stack-smashing and array bounds violations - neither of which is measurably affected by seperation of code and data space.
As for "who's to blame" for the current code/data overlap - it's a bit of a toss-up: GCC has some of the blame, LIBC some of the blame, the kernel some of the blame. But having done development in an environment where the code and data segments did not overlap I can tell you that you get bit by all SORTS of problems - const char *'s that the compiler wants to put in the code segment, pointer conversions from void * to void (*)(), and so on.
Re:Overlapped code/data a mistake. BOUND instr. av
by
AHumbleOpinion
·
· Score: 2
you would incur the penalty of loading the protection once per scope - after that all subsiquent accesses via that register are "free"
You had a segment override prefix on every data access. That is not free, space of performance.
... const char *'s that the compiler wants to put in the code segment... It ain't as easy as it sounds, trust me.
Been there, done that. I wrote a custom kernel for a telecommunication product. We used a commercial compiler and linker that targets embedded environments and did not have any problems with non-overlapped code and data.
Again, the problems you cite are due to the kernel developers choice of following the *NIX tradition. If non-overlapped segments were chosen gcc and other tools would have been adapted long ago.
Re:Overlapped code/data a mistake. BOUND instr. av
by
wowbagger
·
· Score: 2
A segment override is a lot cheaper than a seperate instruction on every test.
And protecting the code from modification is much better done by protecting the pages themselves in the page table than by using segementation tricks.
Re:No, it;'s a shame how kernel developers use the
by
kasperd
·
· Score: 1
It's not Intel, it's the kernel developers.
Nonexecutable read-write pages would have helped a lot in some cases. AFAIK that is not supported by the CPU. Only through nasty hacks doing stuff with undefined behaviour has it been possible to implement it.
The developers choose to make the code and data segments overlap, that is the error.
No that is certainly not an error. It is the way to go if you want to use a paged memory model on IA32. You cannot blame the kernel developers for some security feature being available in the segmented memory model but not in the paged memory model.
Re:Is the randomization per machine, per build, et
by
Geekboy(Wizard)
·
· Score: 1
Completely random, each function call.
Re:No, it;'s a shame how kernel developers use the
by
AHumbleOpinion
·
· Score: 1
No that is certainly not an error. It is the way to go if you want to use a paged memory model on IA32. You cannot blame the kernel developers for some security feature being available in the segmented memory model but not in the paged memory model.
I don't see where having code and data segments being aliases for one another has anything to do with paging. IA32 is always segmented, a flat memory model means one code segment and one data segment, and basing code and data at the same logical address is merely one special case of the flat model. There are three levels of addressing. At the program level, OS or app, we have segment+offset. The segment/offset pair is translated by the CPU into a logical address. If paging is not enabled this logical address is also the physical address. If paging is enabled the logical address is remapped into a physical address. Segments do not play a role in paging. The special case of the flat model with code and data based at logical address zero is merely a historical convention of UNIX, it may be a requirement on other architectures but it is not under IA32. It was just convenient.
Re:No, it;'s a shame how kernel developers use the
by
kasperd
·
· Score: 1
I don't see where having code and data segments being aliases for
one another has anything to do with paging.
It simply means that you can ignore the little usable segmentation and
use the pure paging that is below the segmentation.
At the program level, OS or app, we have segment+offset.
That is actually not the case in Linux IA32. A pointer is merely an
integer.
The special case of the flat model with code and data based at
logical address zero is merely a historical convention of UNIX, it may
be a requirement on other architectures but it is not under IA32. It
was just convenient.
Segmentation is really not that useful. If you have segmentation
without paging you will loose some efficiency as you are forced to
read/write complete segments to your swap partition rather than single
pages. Paged segments does allow you to swap single pages in and out,
but that is not what IA32 offers, it has reversed the order of the
segmentation and paging layers, a horrible design which is probably
due to the requirement of 286 compatibility.
The UNIX API is not designed with segmentation in mind. When a program
mmap a file there is no indication whether this is code or data except
from the initial protection mask which can be changed later. At this
early point you cannot decide whether the file would go in data or code
page, in fact it might as well be some of each. Security is not a
valid argument for using segmentation, the UNIX API offers the same
security in the paged model, it is just not implemented by the IA32
hardware.
Another of the arguments in favor of segmentation is address space. It
is claimed that with segmentation you are less likely to run out of
address space because you can have independent segments for each type
of data you store. I say it is an incorrect argument, they are
comparing a segment+offset address with a linear address the size of
the offset itself. So the observation really would be that with more
bits in the addressing you are less likely to run out of address
space. Obviously that is true, but a large linear address would help
even more. At the same size of addresses the linear model will beat
the segmented any time because of the flexibility offered by the
linear model. With IA32 it is even worse because not only do you need
larger pointers in the segmented model without getting enough from
them, but at the same time it all has to be mapped into the single
linear address space which is no larger than it used to be.
Re:No, it;'s a shame how kernel developers use the
by
AHumbleOpinion
·
· Score: 1
At the program level, OS or app, we have segment+offset.
That is actually not the case in Linux IA32. A pointer is merely an integer
You are mistaken. Linux, Win32, or any other OS has no say in the matter, there is always segmentation in IA32. You are confusing a special case of the flat memory model where all segment are based at zero with the lack of segmentation. From the CPUs perspective a pointer is always an offset into a segment. A segment base address defined in the descriptor table is always added to this offset. With a base address of zero this offset, what you referred to as a pointer, is also the logical address formed from segment+offset. I think your confusion lies in the loose language used when the windows world went from Win16 to Win32. Win32 was said to have no segmentation, but all that really meant was that the programmer did not have to deal with segments. The CPU still used segments behind the scene.
With IA32 it is even worse because not only do you need larger pointers in the segmented model without getting enough from them, but at the same time it all has to be mapped into the single linear address space which is no larger than it used to be
You have fundamentally misunderstood my point. I am not advocating a DOS/Win16'ish memory model where there are multiple code or data segments. I advocate the flat memory model that Win32, Linux, *BSD, etc. are currently using. My disagreement is only with the special case where code and data segments are based at zero. I merely prefer different bases so that code and data do not overlap in the logical address space. This would be transparent to the programmer, pointers would still be the 32-bit offsets you know and love.
Re:No, it;'s a shame how kernel developers use the
by
kasperd
·
· Score: 1
You are mistaken. Linux, Win32, or any other OS has no say in the matter, there is always segmentation in IA32.
The CPU might see it as segmentation, but at the program and OS levels there is no segmentation. In fact most Linux programs never touch a segment register, from the programs point of view the segment registers could as well be nonexistent. And those parts of Linux actually dealing with segment registers are few.
I merely prefer different bases so that code and data do not overlap in the logical address space. This would be transparent to the programmer, pointers would still be the 32-bit offsets you know and love.
By doing that you would run into at the very least four different problems:
As I already pointed out you would not know where to place mappings when a mmap call was done.
You would have problems with trampolines.
You might need to use 32-bit pointers, but you would not get 32-bit address space because it would have to be split between different segments.
You would get problems with JIT compilers.
With four disadvantages and no advantages known to me, I consider it a bad idea.
Re:No, it;'s a shame how kernel developers use the
by
AHumbleOpinion
·
· Score: 1
The CPU might see it as segmentation, but at the program and OS levels there is no segmentation. In fact most Linux programs never touch a segment register, from the programs point of view the segment registers could as well be nonexistent. And those parts of Linux actually dealing with segment registers are few.
Again, your use of the word "segmentation" is different than the use of this word in the original discussion. I.e. you are off on a tangent all alone. One last time, segmentation is always on in IA32, code and data references always use segment registers. What is confusing you is that there are is only one code segment and one data segment, that there is no need to change segment registers at runtime, and that no segment overrides are needed. Segmentation is always on and active through default segment registes. Secondly your comment "The CPU might see it as segmentation" effectively ends the discussion. Your original misunderstanding, see "... some security feature being available in the segmented memory model but not in the paged memory model", seems to be cleared up. The CPU is what this discussion is about, whether or not code and data segments should share the same base address.
By doing that you would run into at the very least four different problems:
As I already pointed out you would not know where to place mappings when a mmap call was done.
You would have problems with trampolines.
You might need to use 32-bit pointers, but you would not get 32-bit address space because it would have to be split between different segments.
You would get problems with JIT compilers.
With four disadvantages and no advantages known to me, I consider it a bad idea.
Ignoring the technical errors of your points, #3 is nonsense, you misunderstand the original discussion. The discussion involved the decision made before any such tools existed, when the core of the kernel was at it's earliest moments. You merely point out issues involved in retrofitting the kernel, a tangent no one else is discussing. The opportunity to prevent a buffer overrun from introducing malicious code was lost long ago.
Isn't that basically the same as the Linux patch making stack non-executable?
What about stackguard? Why isn't it in use everywhere? Or libsafe for that matter? Or Openwall Project kernel patch for Linux? Can anyone please tell me why no one uses it?
Software tweak may make operating systems safer
09:43 Monday 14th April 2003
Robert Lemos, CNET News.com
The OpenBSD project is making changes in its latest operating system release that it believes could eliminate a class of security bugs that has plagued computers for decades
The OpenBSD project hopes new changes to its latest release will eliminate "buffer overflows", a software issue that has been plaguing security experts for more than three decades.
Theo de Raadt, the project leader for the group, believes that the group's latest improvements to the Unix variant, due to be released on 1 May, will make causing a buffer overflow extremely difficult, if not impossible. A buffer overflow is a memory error in software that allows an attacker to run a malicious program.
"I could say that I am killing buffer overflows, but I am in the security community, so I have to put it in quotes," he told attendees at the CanSecWest security show on Thursday.
The memory bugs have resisted extermination for almost 30 years, and de Raadt said that any claims that an open-source group has done so would need to be tested.
Some attendees are already incredulous that the changes will eliminate buffer overflows. "It's just adding another layer" to the security, said Nicolas Fischbach, senior manager for security at Colt Telecom, a European communications provider. "It won't make a huge difference because there are always bugs that are found in software."
An overflow exploit generally works when an attacker sends a program requesting too much information. The data usually includes two components: one that crashes the application and one that's either a program or a memory address that points to a program that the attacker would like to run. When the application crashes due to the first component, the operating system will execute the second.
The OpenBSD team hardened the operating system to this type of attack using three tactics.
The group randomised where in memory the "stack" -- a structure that holds applications and their data -- resides, so that code designed to exploit buffer overflows will have to be tailored to the system's memory layout.
"Buffer overflows take advantage of a certain memory layout," de Raadt said. "It's a tiny waste of memory, with very little overhead, but it makes things a little bit more difficult. We are trying to make the (code) crackers work a little bit more."
In addition, the group restructured how critical addresses are stored on the stack, so that it's harder to get buffer overflows to result in a running program. The team placed a small tag, called a canary, in the memory structure to detect if addresses had been modified, a common method hackers use to get a legitimate program to run malicious code.
Finally, the group found a way to hack the BSD file system and divide main memory into a writable portion and an executable portion. Pieces of programs and data, known as pages, that are stored to memory will be placed into one of the two areas.
"We want to make sure that no page is both executable or writable simultaneously," he said. "The goal is that no hackers should be able to write code and then execute it."
The problem for the OpenBSD group is that while 64-bit processors have such memory protections available, the most-popular 32-bit processors don't. So the group has had to work around the issue and break up a computer's memory into writable and executable areas.
"You can draw a line in the sand -- before that line you can execute, above you can't," de Raadt said.
While the other security features will be available in the 1 May release, the protected memory page structure for 32-bit processors -- such as Intel x86 chips and the PowerPC chips -- won't be ready for another six months, he said.
The research was funded by a $2.3m (about £1.5m) grant from the Defense Advanced Research Projects Agency (DARPA) to the OpenBSD Project, but the latest changes go be
I'm about to say something I would have never dreamed of saying a couple of years ago.
...
It is a shame that Intel made segments work the way they do, because a minor tweak and segments would have been the perfect way to prevent buffer overflows in hardware.
Consider: what if, instead of segment descriptors having to live in the GDT and LDT, they could be loaded into a register from a normal memory limit? True, they would then have been useless for OS level protection, but I assert that is what the page map is for (yes, the page mapper didn't exist prior to the 386, and enhanced segments showed up in the 286).
In some of the DSPs that I work with, you have registers to specify a region of memory. When you access off these registers, memory bounds are enforced by the chip (this allows for circular regions of memory, bit reversed addressing, and other weird things you need when doing DSP work).
What if you could have done something like this:
buffer:
ds 1024 ; a buffer of stuff
buffer_descr:
dd buffer ; where buffer starts
dd 1024 ; sizeof(buffer)
LDPROT ES,buffer_descr ; set limits checking
LD ES:(ESI),EAX ; store to buffer with checking.
Thus, any access out of bounds would throw a SIGSEGV.
Then, the code could have provided protection against overflows without explicit checking on every array access. True, this would not protect you if all you were given was the buffer address, but in the presense of this sort of hardware, GCC could have been modified to make a char (*a)[] (pointer to array of char) be three elements - base, sizeof(), index.
www.eFax.com are spammers
But my real question is about that ZDNet article. It said that the segmentation measures came from "hacking the BSD file system". It sounds to me like the reporter got confused. Can anyone familiar with the code comment on this?
Check out my eclectic infosec blog at InfoSecPotpou
A simple way for the average programmer: use the "safer" C functions.
Use strncpy instead of strcpy. Use strncat instead of strcat. Use snprintf instead of sprintf.
And so on.
I bet this would fix a huge number of overflow bugs.
I really appreciate the effort going into OpenBSD making it more secure and robust, but I hope the option of keeping it a simple BSD without the innovative security features, remains. Part of the reason Ive used BSD in the past is its simplicity and predictability across the versions. OpenBSD, opposed to NetBSD and FreeBSD is the 'simplest' BSD outside of the seccurity changes and I hope users have the option of not using the page protection, encrypted ram and filesystems, chrooted services and other stuff.
Would also be nice to have the drivers of FreeBSD ported to OpenBSD. I had to choose Linux to be able to use my Olicom 3140 tokenring card.
Rants aside, thanks to Theo and the team, for giving us an OS we can be confident, is really secure with no compromises.
"Give orange me give eat orange me eat orange give me eat orange give me you." -Nim Chimpsky
duh.
but this is still vague. It could be:
- Per kernel. (All processes on this box have the same stack layout)
- Per process. (All processes have a different stack layout, though threads and forked versions may have the same.)
- Per binary. (Each program's stack layout is determined at compile time and will not change on invocation.)
- Completely random (Each program is different every time, or better yet each function call is different each time.)
This would have a very import impact on how well a hacker could brute force your processes. If a given process always has the same stack layout then you can eventually brute force it, just like we currently can brute force offsets. The bar is higher of course - only one variable is being manipulated - and a hacker will probably go to easier machines before too long. But a truly randomized per process invocation or better yet per function call invocation would be such a moving target that it should be extreemly unlikely to succeed. I'm really excited.'"But it happened because the DARPA grant happened, because when you throw a bunch of... guys into a room and get them drunk, this is what you get." De Raadt was careful to point out that the group paid for its own beer.'
...beer? I would really like to know what sort of beer is the best inpirational beverage for coding? Is there a different best beer per language/platform? Or do some platforms require liquor instead? I hear Java is much better with Irish cream...
------------
This quote clearly demonstrates that free as in beer is not free at all. Even the most notorius free software developers actually pay money for their beer.
Gates said hardware should be free. Stallman said software should be free. I think beer should be free.
It is clear from gems like this from the article that the reporter was confused so that it is impossible from the article itself to really undrestand how the three approaches would work:
"An overflow exploit generally works when an attacker sends a program requesting too much information. The data usually includes two components: one that crashes the application and one that's either a program or a memory address that points to a program that the attacker would like to run. When the application crashes due to the first component, the operating system will execute the second.
It is important to point out that this looks to be yet another in the attempts at making buffer over flow exploits difficult yet not quite impossible. Once you put return addresses on the stack (the same stack with an over flow) an exploit can jump to any place it likes in text even without an executable stack.
The details about the tag around import addresses and the random stack offsets could make exploits _very_ difficult. If the base of the stack is random from one invocation of the program to the next that does not give much more once you cannot execute on the stack so it is probably more than that. Also if the tag around important addresses (say the address of the buffer to system(3C)) incorpates randomness from one invocation of the program to the next then it would be hard to over flow a buffer and exploit it.
In any case even if you had a sytem where a buffer over flow could not be exploited to run arbitrary code but almost any random junk will still crash the broken prorgam, that does not do much to prevent DoS now does it.
I just ass/u/me it's per process. No?
Libsafe only protects a few built-in functions; it's not a bad idea, but it's FAR less effective than StackGuard or ProPolice. The Openwall kernel patch is actually a collection of nifty capabilities. The "no executable stack" option is probably what you mean, but it turns out that there's a trivial way around it... so that part is only effective BECAUSE few people use it. Openwall has other stuff that's nice, though.
I think the reason these capabilities aren't in use everywhere (yet) is the conservatism of most distributions. Many distributions worry about any performance loss or compatibility loss. OpenBSD's primary focus is on security, so losing performance or backwards compatibility is not as serious an issue for them. I have hopes that these features will become more mainstream.
- David A. Wheeler (see my Secure Programming HOWTO)
The Mandrake distribution provides the Grsecurity package in 9.1. Prior to that they had the openwall patch with some others. These aren't in the standard kernel but you can compile them in yourself or use the kernel-secure rpm. The libsafe package has been provided at least since 8.1, all you have to do is type "urpmi libsafe". Libsafe used to break the hardware clock reset feature in the shutdown scripts but they may have fixed it.
I used all this stuff in Mandrake 8.1 and there was a noticeable performance hit in some situations but I left in it anyway.
It's not Intel, it's the kernel developers. The developers choose to make the code and data segments overlap, that is the error.
If I can overwrite a buffer, I can screw you machine. I don't care if the stack is not executable - I can modify the return address and fake a call to exec with "/bin/bash" as the args.
If auto storage is removed from the call/return stack, I can overwrite another variable somewhere else, perhaps tricking your program into thinking it is debug mode. It gets harder, but not impossible.
What I was discussing was fine-grained memory bounds checking - which you simply cannot do when all you have is 8192 LDT and 8192 GDT entries, some of which have to be IDT gates, system call gates, task state segments, etc.
www.eFax.com are spammers
I understand your point, I understand it's usage, it does not change the fact that kernel developers made a mistake with overlapped code and data. "It gets harder, but not impossible" is a weak rationalization. Furthermore Intel's BOUND instruction does much of what you suggest. It verifies an address is in a particular range and throws an exception if it is out of range.
My statement about "it gets hard" was for a seperate hardware stack and auto data storage, not seperate code and data spaces.
Even if the program space and the data space were completely seperate I can trivially smash the stack and get a shell - again, all I have to do is overwrite the current function return address with the address of execv, and the preceeding addresses with a bogus return address and pointer to the strings "/bin/sh", 0, and 0. No code segment overlap needed.
Secondly, the BOUND instruction would have to occur before EVERY potential operation, bloating code size (bu-bye cache) and slowing the machine down.
Your assertion that seperate code and data spaces in the kernel is like locking the doors on a convertable - it may make you feel good, but it does not really do anything.
Lastly, most stack smashes happen in user space, not kernel space. If you wish to critizize anybody, criticize the developers of GCC and libc.
www.eFax.com are spammers
Secondly, the BOUND instruction would have to occur before EVERY potential operation, bloating code size (bu-bye cache) and slowing the machine down
...
... If you wish to critizize anybody, criticize the developers of GCC and libc
No, it is not needed globally. It can be selectively used just like the code you suggested previously. Secondly, your solution bloats the code as well, your LDPROT instruction and segment override prefix consumes cache space as well.
Your assertion that seperate code and data spaces in the kernel is like locking the doors on a convertable - it may make you feel good, but it does not really do anything
Lastly, most stack smashes happen in user space, not kernel space
You misunderstand. I would have preferred code and data segments that did not overlap. That applies to both the kernel and user mode.
What this would do is prevent an entire class of attack where arbitrary code is introduced by an overrun and then executed.
Not for code/data overlapping, the kernel developers are the ones who decided the segmentation model. Possibly for the lack of an option to insert BOUNDS instructions, but gcc may actually have a "check array bounds" option.
Actually, my solution does not bloat the code as much - you would incur the penalty of loading the protection once per scope - after that all subsiquent accesses via that register are "free". With the BOUND instruction, you have to insert it before every access, unless you can somehow insure that the check is unneeded (e.g. a loop index where you can BOUND the start and the end value of the loop var).
As for the code/data space issue - the issue at hand is stack-smashing and array bounds violations - neither of which is measurably affected by seperation of code and data space.
As for "who's to blame" for the current code/data overlap - it's a bit of a toss-up: GCC has some of the blame, LIBC some of the blame, the kernel some of the blame. But having done development in an environment where the code and data segments did not overlap I can tell you that you get bit by all SORTS of problems - const char *'s that the compiler wants to put in the code segment, pointer conversions from void * to void (*)(), and so on.
It ain't as easy as it sounds, trust me.
www.eFax.com are spammers
you would incur the penalty of loading the protection once per scope - after that all subsiquent accesses via that register are "free"
... const char *'s that the compiler wants to put in the code segment ... It ain't as easy as it sounds, trust me.
You had a segment override prefix on every data access. That is not free, space of performance.
Been there, done that. I wrote a custom kernel for a telecommunication product. We used a commercial compiler and linker that targets embedded environments and did not have any problems with non-overlapped code and data.
Again, the problems you cite are due to the kernel developers choice of following the *NIX tradition. If non-overlapped segments were chosen gcc and other tools would have been adapted long ago.
A segment override is a lot cheaper than a seperate instruction on every test.
And protecting the code from modification is much better done by protecting the pages themselves in the page table than by using segementation tricks.
www.eFax.com are spammers
It's not Intel, it's the kernel developers.
Nonexecutable read-write pages would have helped a lot in some cases. AFAIK that is not supported by the CPU. Only through nasty hacks doing stuff with undefined behaviour has it been possible to implement it.
The developers choose to make the code and data segments overlap, that is the error.
No that is certainly not an error. It is the way to go if you want to use a paged memory model on IA32. You cannot blame the kernel developers for some security feature being available in the segmented memory model but not in the paged memory model.
Do you care about the security of your wireless mouse?
Completely random, each function call.
No that is certainly not an error. It is the way to go if you want to use a paged memory model on IA32. You cannot blame the kernel developers for some security feature being available in the segmented memory model but not in the paged memory model.
I don't see where having code and data segments being aliases for one another has anything to do with paging. IA32 is always segmented, a flat memory model means one code segment and one data segment, and basing code and data at the same logical address is merely one special case of the flat model. There are three levels of addressing. At the program level, OS or app, we have segment+offset. The segment/offset pair is translated by the CPU into a logical address. If paging is not enabled this logical address is also the physical address. If paging is enabled the logical address is remapped into a physical address. Segments do not play a role in paging. The special case of the flat model with code and data based at logical address zero is merely a historical convention of UNIX, it may be a requirement on other architectures but it is not under IA32. It was just convenient.
I don't see where having code and data segments being aliases for one another has anything to do with paging.
It simply means that you can ignore the little usable segmentation and use the pure paging that is below the segmentation.
At the program level, OS or app, we have segment+offset.
That is actually not the case in Linux IA32. A pointer is merely an integer.
The special case of the flat model with code and data based at logical address zero is merely a historical convention of UNIX, it may be a requirement on other architectures but it is not under IA32. It was just convenient.
Segmentation is really not that useful. If you have segmentation without paging you will loose some efficiency as you are forced to read/write complete segments to your swap partition rather than single pages. Paged segments does allow you to swap single pages in and out, but that is not what IA32 offers, it has reversed the order of the segmentation and paging layers, a horrible design which is probably due to the requirement of 286 compatibility.
The UNIX API is not designed with segmentation in mind. When a program mmap a file there is no indication whether this is code or data except from the initial protection mask which can be changed later. At this early point you cannot decide whether the file would go in data or code page, in fact it might as well be some of each. Security is not a valid argument for using segmentation, the UNIX API offers the same security in the paged model, it is just not implemented by the IA32 hardware.
Another of the arguments in favor of segmentation is address space. It is claimed that with segmentation you are less likely to run out of address space because you can have independent segments for each type of data you store. I say it is an incorrect argument, they are comparing a segment+offset address with a linear address the size of the offset itself. So the observation really would be that with more bits in the addressing you are less likely to run out of address space. Obviously that is true, but a large linear address would help even more. At the same size of addresses the linear model will beat the segmented any time because of the flexibility offered by the linear model. With IA32 it is even worse because not only do you need larger pointers in the segmented model without getting enough from them, but at the same time it all has to be mapped into the single linear address space which is no larger than it used to be.
Do you care about the security of your wireless mouse?
At the program level, OS or app, we have segment+offset.
That is actually not the case in Linux IA32. A pointer is merely an integer
You are mistaken. Linux, Win32, or any other OS has no say in the matter, there is always segmentation in IA32. You are confusing a special case of the flat memory model where all segment are based at zero with the lack of segmentation. From the CPUs perspective a pointer is always an offset into a segment. A segment base address defined in the descriptor table is always added to this offset. With a base address of zero this offset, what you referred to as a pointer, is also the logical address formed from segment+offset. I think your confusion lies in the loose language used when the windows world went from Win16 to Win32. Win32 was said to have no segmentation, but all that really meant was that the programmer did not have to deal with segments. The CPU still used segments behind the scene.
With IA32 it is even worse because not only do you need larger pointers in the segmented model without getting enough from them, but at the same time it all has to be mapped into the single linear address space which is no larger than it used to be
You have fundamentally misunderstood my point. I am not advocating a DOS/Win16'ish memory model where there are multiple code or data segments. I advocate the flat memory model that Win32, Linux, *BSD, etc. are currently using. My disagreement is only with the special case where code and data segments are based at zero. I merely prefer different bases so that code and data do not overlap in the logical address space. This would be transparent to the programmer, pointers would still be the 32-bit offsets you know and love.
The CPU might see it as segmentation, but at the program and OS levels there is no segmentation. In fact most Linux programs never touch a segment register, from the programs point of view the segment registers could as well be nonexistent. And those parts of Linux actually dealing with segment registers are few.
I merely prefer different bases so that code and data do not overlap in the logical address space. This would be transparent to the programmer, pointers would still be the 32-bit offsets you know and love.
By doing that you would run into at the very least four different problems:
- As I already pointed out you would not know where to place mappings when a mmap call was done.
- You would have problems with trampolines.
- You might need to use 32-bit pointers, but you would not get 32-bit address space because it would have to be split between different segments.
- You would get problems with JIT compilers.
With four disadvantages and no advantages known to me, I consider it a bad idea.Do you care about the security of your wireless mouse?
The CPU might see it as segmentation, but at the program and OS levels there is no segmentation. In fact most Linux programs never touch a segment register, from the programs point of view the segment registers could as well be nonexistent. And those parts of Linux actually dealing with segment registers are few.
Again, your use of the word "segmentation" is different than the use of this word in the original discussion. I.e. you are off on a tangent all alone. One last time, segmentation is always on in IA32, code and data references always use segment registers. What is confusing you is that there are is only one code segment and one data segment, that there is no need to change segment registers at runtime, and that no segment overrides are needed. Segmentation is always on and active through default segment registes. Secondly your comment "The CPU might see it as segmentation" effectively ends the discussion. Your original misunderstanding, see "... some security feature being available in the segmented memory model but not in the paged memory model", seems to be cleared up. The CPU is what this discussion is about, whether or not code and data segments should share the same base address.
By doing that you would run into at the very least four different problems: As I already pointed out you would not know where to place mappings when a mmap call was done. You would have problems with trampolines. You might need to use 32-bit pointers, but you would not get 32-bit address space because it would have to be split between different segments. You would get problems with JIT compilers. With four disadvantages and no advantages known to me, I consider it a bad idea.
Ignoring the technical errors of your points, #3 is nonsense, you misunderstand the original discussion. The discussion involved the decision made before any such tools existed, when the core of the kernel was at it's earliest moments. You merely point out issues involved in retrofitting the kernel, a tangent no one else is discussing. The opportunity to prevent a buffer overrun from introducing malicious code was lost long ago.