Slashdot Mirror


Libsafe: Protecting Critical Elements of Stacks

pomac writes "Check out Libsafe for a great effort in protecting outdated systems against stack attacks or buffer overflows. I would love to see some constructive opinions on this. " You and me both.

52 of 114 comments (clear)

  1. Go two steps farther by FascDot+Killed+My+Pr · · Score: 2

    OK, so they've put wrappers around calls that are known to be vulnerable. Why not:

    1) Contact the glibc people with patches for those functions (assuming the problems are patchable, which not all of them are)

    2) Check for bad args in the wrapper and log it so defective programs are easier to find.
    --

    --
    Linux MAPI Server!
    http://www.openone.com/software/MailOne/
    (Exchange Migration HOWTO coming soon)
    1. Re:Go two steps farther by Anonymous Coward · · Score: 2

      I asked some people why this isn't integrated into the glic code and they said that this patch does things which are not compatible with every program out there so it wouldn't work good as a default. Regarding logging, this wrapper does log to syslog before terminating the program. It can even email you if so configured.

    2. Re:Go two steps farther by viktor · · Score: 2
      Why not: 1) Contact the glibc people with patches for those functions (assuming the problems are patchable, which not all of them are)

      Because buffer overruns is a problem on all UNIX systems and not only Linux? :-)

      I haven't checked it, but I guess they use LD_PRELOAD to load their versions of the calls? In that case it should work on any UNIX that supports some kind of LD_PRELOAD, which makes it much more usable than if the changes were made solely to glibc.

  2. Re:you and me both? by Wire+Tap · · Score: 2

    No.
    You and I both does not make sense in this situation, or many for that matter.

    You and me both is the correct way of saying this. Just take the comparative word out, and the "you", and you are left with: Me too.

    Gotta love the English language. :-) My grandfather is an English teacher, and he's always teaching me grammar.

    And MODEREATORS, PLEASE DO NOT MODERATE ME DOWN! I was trying to promote good English. Thanks. :-)
    Fran Frisina (franf@hhs.net)
    http://www.zero-productions.com/money

    --

    Man is born free; and everywhere he is in chains.

  3. Now THAT's innovation... by ch-chuck · · Score: 2

    ...not the MickyMouse themePark B.S. 'innovation' of those other guys.

    "...the performance overhead of libsafe is negligible. "

    It doesn't slow you down much either.

    --
    try { do() || do_not(); } catch (JediException err) { yoda(err); }
  4. Not just for outdated systems... by Ed+Random · · Score: 2

    Your description suggests that libsafe is for protecting *outdated* systems against *stack* overflows.

    Actually it provides wrappers around potentially dangerous system calls ( e.g. strcpy() ), so it helps protect against buffer overruns in all the (dynamically linked) software running on the system.

    IMHO, the biggest feature is, that it does not require code instrumentation or even re-linking of the software, something that other solutions do usually require.

    This means that problems can be prevented in many cases.

    All in all, a nice piece of work...

    --
    Greetings,
    Ed.

    --
    -- Gxis! Ed.
  5. This is obsolete for Open Source. by zCyl · · Score: 3

    We've had a tool that protects open source programs from calling known bad calls for some time now. It's called grep. Grep your code for bad calls, find them, fix them, then don't waste 4 metric tons of overhead running all your software with a wrapper.

    The ideal solution would be to make a tiny little perl script that pattern matched code for all these known bad calls, and then printed out the file, line number, and reason why the call is known to be bad.

    1. Re:This is obsolete for Open Source. by technos · · Score: 3

      Okay.. Let's put it this way. I have a mission critical program. We'll call it Midnight Modeller. Now, this program is the only one with the particular feature set I need. Unfortunatly, its been so long unmaintained that all I can get functioning is a binary that is known vunerable.

      I have two options; Install the wrappers, or slog through 18,000 lines of code to modernize it.

      Or another:
      I have a commercial application. Let's call it Microsoft Office 2001 for Linux. Am I to trust that in that huge, behemoth of Microsoftian bloat there isn't some exploitable code?

      I have two options; Install the wrappers, or pay the vendor BIG MONEY for a copy of the source and audit it.

      --
      .sig: Now legally binding!
    2. Re:This is obsolete for Open Source. by howardjp · · Score: 2

      I have a commercial application. Let's call it Microsoft Office 2001 for Linux. Am I to trust that in that huge, behemoth of Microsoftian bloat there isn't some exploitable code?

      Why are you running it is root? :)

    3. Re:This is obsolete for Open Source. by Raven667 · · Score: 2

      Uh, why would it have to run as root to have an exploit? Being able to run arbitrary code as a priviledged user (as opposed to unpriviledged, like "nobody") gives much greater access to the system than many network services, also it is often trivial to elevate your privileges once you have shell access to a system (rootkits anyone?). And how devistating would it be to have your home directory blown away, sure the "system" is ok but your data has gone to heaven. Systems can be reinstalled from CD very easily, data cannot.

      I am playing with libsafe right now and haven't as yet suffered any adverse effects. It is a good stopgap measure until libc is fixed and/or the development environment is fixed because asking every programmer, big and small, to manually check these function calls every time is just asking for things to be missed through incompetance, ignorance or just plain mistakes. I mean how come we still have buffer overflow problems in this day and age, this should have been fixed 10 years ago. The current system of every program manually having to implement this stuff for every call of a function doesn't work.

      Rant mode off please. . . please.

      --
      -- Remember: Wherever you go, there you are!
    4. Re:This is obsolete for Open Source. by Cramer · · Score: 3

      Actually, it's much simpler than that... Linux has had, in one form or another, a "non-executable stack" patch for some time now. There has been heated debates on it's usefulness, however. Most buffer overflow tricks overwrite the return address on the stack as well as stick there own instructions there. If the stack is not executable then it's a hell of alot harder to get the program to do what you want it to -- unless "crash" is what you want it to do. It would be very difficult to implant your own instructions; and very few programs have something like 'system("/bin/sh");' in them.

      Such patches also cause a problem for programs that legitimately alter their code -- self-modifying code. Granted, there are very few such programs and there are ways to make them work. (The Distributed.Net client has a self-modifying core.)

    5. Re:This is obsolete for Open Source. by rlk · · Score: 3

      Grep's great for finding calls to gets that are basically unsafe under virtually any conditions. It can find calls to other dangerous functions (strcat, strcpy, sprintf for example) if you have the source handy, but it doesn't help you decide whether each call is dangerous or not. For example, strcpy is dangerous, but if the length of the string being copied is provably bounded, it may be quite safe.

      I consider gets to be essentially unsafe in all circumstances because it relies upon good external behavior. I suppose one can always come up with a safe example -- a program pipes, forks, and the child rebinds stdin to the pipe -- but that's contrived. It would be nice to replace the substitute function for gets with one that aborts if gets (and probably also scanf) is ever called.

      The real advantage of libsafe is that it catches problems that happen at runtime with calls that might otherwise be reasonable. It's a backstop. The fact that stack smashes still happen is clear evidence that grepping source isn't sufficient.

    6. Re:This is obsolete for Open Source. by Signail11 · · Score: 2

      I won't even bother responding to the first part of your posting (the ability to audit code is not the same as the actual auditing code). But your "ideal solution" is so utterly unrealistic that I think it deserves some comment. Are you aware of the halting problem? Then I suppose you realize that the determination of whether a specific invocation of a black box function (ie. we can neglect the behavior/side effects of the function and the result still holds) is "safe" or "unsafe" is reducable to a more general decision problem that is known to be undecidable in the deterministic Turing machine model of computation. Translation: if you think this "tiny little perl script" is so easy, please write it (or even a plausible prototype) and earn everlasting fame for disproving the Church-Turing thesis. Just remember, your perl script does not know anything more about the flow of the program than your C compiler (and probably a good deal less). It cannot determine what input will be presented to a given function or program unless you resort to alternate or supplemental descriptive formal languges, but if you're going to go the route to theorem proving and validation, why bother with C?

    7. Re:This is obsolete for Open Source. by hanway · · Score: 2
      Many errors cannot be detected by trivial source code inspection, which is all that grep could ever accomplish. Show me a regexp that will tell me whether

      printf(fmtString, a, b, c);

      is valid without knowing what fmtString is at run time.

    8. Re:This is obsolete for Open Source. by technos · · Score: 2

      It is a library, but no. Libsafe uses the LD_PRELOAD mechanism to subvert the normal calls.. Binaries are fine!

      --
      .sig: Now legally binding!
    9. Re:This is obsolete for Open Source. by zCyl · · Score: 2

      I'm well aware of the halting problem. I went back to reread my post to make sure it wasn't worded as stupidly as you said, and it wasn't. I am not referring to solving the halting problem, and if I were attempting to even present a close approximate solution that can sometimes solve the halting problem, perl wouldn't be my first choice for such. No, what I said was "these known bad calls". There are a number of things that are clearly stupid to use in a program which a simple grep would catch, that end up in some open source programs and a lot of commercial products.

    10. Re:This is obsolete for Open Source. by zCyl · · Score: 2

      printf(fmtString, a, b, c);

      If you screw up your fmtString, you will get bad output, but that's all. This isn't dangerous, just annoying. What you could have brought up is:

      sprintf(dest, fmtString, a, b, c);

      Here, however, libsafe could not help anyway, because I really doubt they've found a way to make a library that can determine how much you really want to store in dest before overwriting something important nearby on your data segment, such as a function pointer, etc.

    11. Re:This is obsolete for Open Source. by Brian+Feldman · · Score: 2
      FreeBSD has a pretty good solution here, much like your suggestion of "aborts if gets":

      {"/home/green"}$ cat foo.c
      #include
      void foo(void) { char x[1]; gets(x); }
      int main(void) { fclose(stdin); foo(); exit(0); }
      {"/home/green"}$ cc -o foo foo.c
      /home/green/tmp/ccMD6705.o: In function `foo':
      /home/green/tmp/ccMD6705.o(.text+0xe): warning: this program uses gets(), which is unsafe.
      {"/home/green"}$ ./foo
      warning: this program uses gets(), which is unsafe.

      This is something you can easily make use of in libc, with a nice __warn_references() macro to define them :)

      It's not a perfect solution, but it certainly lets people know that they're REALLY out of line with their code =)

      --

      --
      Brian Fundakowski Feldman
    12. Re:This is obsolete for Open Source. by SimonK · · Score: 2

      But you suggested things like libsafe are unnecessary, because you can grep programs for things that are known to be unsafe.

      That isn't true. More complex uses of functions that are *sometimes* unsafe cannot be found in this way, and as the poster points out, that is a fundamental law of nature, not just a requirement for a cleverer perl script.

  6. Uhhh by Signal+11 · · Score: 2
    There's better solutions out there - like StackGuard. Basic theory is this - buffer overflows write over the data segment and then write into the adjacent data segment. By placing a small amount of space between the two and writing a known value to it, you can detect when a buffer overflow occurs before executing that segment. Of course, this method has it's drawbacks in the form of additional memory, alittle more latency, and trusting that the attacker doesn't know the "magic numbers" in the mystery segment.

    The best method is simply to code your programs from the ground up with security in mind to begin with - and then have alot of people audit your code. Is it foolproof? No. Then again, is anything?

    Libsafe is a nice idea.. but a simple 'grep -H "strcpy(" *' would do the same thing.

    1. Re:Uhhh by Pike · · Score: 2

      You can keep the attacker from knowing the magic numbers by using a randomly generated value and writing it into the stackguard space. Then do a one way hash on it and store that in a seperate place to check the original against...also, make the size of the spacer vary slightly (randomly) to keep them from knowing exactly how much farther they have to go to cross into the stack.

      -JD

  7. Happened to me... by zpengo · · Score: 2
    We had some software here at work that was suffering from overflows caused by new employees who were entering data "incorrectly"; i.e., the system wasn't idiotproofed.

    What I did was program a new interface to the system, which had buffer overflow checking. The users entered the data, the program warned them if it was too long or the wrong format, and then when everything worked we passed it to the actual system.

    A bit tricky to program in this particular case, but the idea could work very well for some systems.

    --


    Got Rhinos?
  8. Not completely safe by dsplat · · Score: 2

    According to the man page, libsafe implements versions of several library functions (strcpy, etc.) in such a way that any data written is limited to the current stack frame. Yes, that does prevent overwriting return addresses and the like. However, it does not prevent overwriting other arguments to the same function. If the object of the attack is merely denial of service, that may well be sufficient. Data that you can access, you can corrupt, this just limits your reach somewhat.

    --
    The net will not be what we demand, but what we make it. Build it well.
  9. Re:GPLed? by (void*) · · Score: 2

    Sorry about my mistake! It is LPGL! I misread!

  10. Not 100% secure? by larien · · Score: 2
    I note that the main install method is to use LD_PRELOAD, but this won't protect against all overflow attacks. All a cracker has to do is unset LD_PRELOAD before running the exploit.

    Using /etc/ld.so.conf (which the man page admits is dangerous) will prevent this, though.

    Secondly, it only works on certain system calls...
    --

    1. Re:Not 100% secure? by rlk · · Score: 2

      The attack it tries to protect against is where the attacker tries to feed very specific bad data to a running program. This data is actually code, with some stack hackery to force the executable to run the desired code. If libsafe prevents the necessary action from taking place (specifically, smashing the stack frame in the inappropriate fashion), then the attacker can never run the code in the first place.

      Unsetting LD_PRELOAD won't affect a running executable even if it could be done by the attacker, which hopefully it can't do now anyway.

      Libsafe is not designed to protect against someone who already has independent means of running an executable (although it might protect against someone who tries to crack a local setuid program, issues of forcing the LD_PRELOAD aside). Someone who has a shell can create their own executable anyway, and doesn't need a stack smash. It's intended to protect network daemons, where the attacker doesn't already have system access.

  11. Re:Rather ironic... by howardjp · · Score: 2

    Being open source does not automatically make a program bug free. Look at XMMS for instance (why on Earth does it suddenly become silent when I turn on the equalizer?). Or ext2fs (why is it I lose a partition every time I pull the plug?). Or KDE (the window manager should not be using more resources than the windows it managers...yes, that is a bug). Or GAIM (why does my computer lock up for 10 minutes or so when I shut gaim down?). Do I need to continue?

  12. Libsafe works with closed-source by Wreck · · Score: 2
    If you read their white paper, you will see (claimed) advantages to libsafe over stackguard. In particular, libsafe does not require source/recompilation. A second, minor benefit is that in their tests at least, libsafe was faster, taking essentially no extra time, whereas stackguard's effect was at least measurable in two of their four real-world-program benchmarks.

    Regarding the point that many are making here about grepping for strcpy: well, that is all fine and good for open source thingies. But we need to keep in mind our ultimate goal: Linux world domination! Among other things, that means:

    • Closed source games running on Linux
    • Closed source "productivity" programs, like Office 2005, running on Linux
    • Open source thingies running on Linux, used by people like my gramma, who will not run grep by themselves and not even get updated software when security problems are found.
    • More closed source games running on Linux!
    In all these cases, it is unrealistic to expect to be able to grep or recompile when needed.

  13. Benchmarks with apache by Blue+Lang · · Score: 4

    Well, the docs say the impact is negligible, so I decided to give it a shot.

    Box is a celery, 450mhz, 128MB RAM, intel i810 chipset, kernel is 2.2.12-20 (stock RH 6.1)

    Apache is 1.3.12, freshly compiled just for this benchmark.

    Without:

    Running 15,000 requests over three iterations:

    1: 373 req/sec - 677 kb/sec
    2: 374 req/sec - 675 kb/sec
    3: 375 req/sec - 679 kb/sec

    With libsafe:

    1: 334 req/sec - 605 kb/sec
    2: 343 req/sec - 621 kb/sec
    3: 355 req/sec - 642 kb/sec

    Benchmark command line was:

    ./ab -n5000 -c100 -k http://cobalt/index.html

    So, not bad, it it does what it says it does. The box was loaded to the gills, so every little extra makes a difference.

    I'll probly be putting this to at least some serious testing in our production environment.

    --
    blue

    --
    i browse at -1 because they're funnier than you are.
  14. Re:So lemme get this straight... by spotter · · Score: 2

    Insightfull??? The poster displayed a horrible lack of horrible lack of knowledge about how linux's dynamic loader works. libsafe works by LD_PRELOAD, what this means is that while normally the program would look in libc.so.whatever for the function, it will first look in this program for functions to resolve. Also, it only has to do this once per program execution, once it resolves a function to the new libsafe library, it knows to use that for the rest of the program's execution. Therefore, the performance overhead is only the overhead of the extra code in the functions.

  15. It's part of Red Hat powertools 6.2 by XNormal · · Score: 2

    Download the RPM


    ----

    --
    Stop worrying about the risks of nuclear power and start worrying about the risks of not using nuclear power.
  16. Possible Problems with Libsafe by lamontg · · Score: 2
    The first and obvious problems is that it only protects these library functions. It will not prevent the case of someone doing a roll-your-own strcpy() and overflowing a buffer that way.

    Another problem is that it caps the length of the buffer at the size of the stack frame. While I can appreciate why this is the only realistic way to figure out the buffer size without incuring penalties, it doesn't prevent attacks against other data (e.g. pointers, function pointers) in the same stack frame as the buffer.

    It also doesn't prevent heap overflows.

    Also, I've got some concerns about the way that they've re-implimented some of these function calls. I haven't seen any reports yet from people that have thoroughly audited their functions for compatibility against the libc functions. Since they've reimplimented them differently, they may not have exactly the same side effects.

    Still, since non-exec stacks on x86 are worthless and StackGuard has not yet been ported to egcs/RH6.x I'm seriously considering deploying this library to crucial systems.

  17. Re:Rather ironic... by Raven667 · · Score: 2

    Open Source means that the security bugs in most programs are fixable, not that they don't happen. For some people who have the time to audit every line of code of every program installed on the system this may just be a belt-and-suspenders approach.

    Look at the errata or security page for any Linux or UNIX distro, look at the history of BIND or Sendmail. It is better/easier to wrap these library calls than audit every line of software (including closed sourse stuff you may have??) or blindly trust that every programmer is perfect and never makes a mistake that comprimises security.

    --
    -- Remember: Wherever you go, there you are!
  18. Re:which system calls are bad? by daviddennis · · Score: 2

    Any call that does copying without requiring a copy of what's counted. Best examples are sprintf() and strcpy(). sprintf is particularly insideous since it's a great temptation to use it, and you might not think of its fundemental function as copying.

    D

    ----

  19. Re:which system calls are bad? by coyote-san · · Score: 2

    There are several different types of errors; the most commonly abused ones are all library functions that use a user-specified buffer of unspecified size. This is why strncpy() and vnprintf() safe (they can truncate the copy once the buffer is full), but strcpy() and vprintf() are not.

    A more subtle version of the same error can occur if you pass the wrong structure to a function that fills out a passed structure. This can happen if the user redefines the structure locally, or forces the issue with an explicit cast.

    In all of these cases, the library call will overwrite unrelated data. If it's in the heap, some of your data will be bogus and if you're lucky you'll soon SEGV on a bad pointer. If it's on the stack (as an "auto" variable) it can overwrite the return address, possibly resulting in execution of arbitrary code.

    --
    For every complex problem there is an answer that is clear, simple, and wrong. -- H L Mencken
  20. Useful, but hokey. by Animats · · Score: 3
    The concept seems useful, but hokey. It only checks for a few standard bugs, and even then, the checking isn't airtight. It won't catch non-library overflows. It may encourage people to think unsafe programs are safe. Incidentally, if you're not familiar with how buffer overflow bugs are found and exploited, the classic The Tao of Windows Buffer Overflow from Cult of the Dead Cow is a good tutorial.

    I'm amazed that people are still using the old unchecked C library functions. There are checked versions for all of them. I stopped using the unchecked versions in the early 1980s. As was suggested in 1995, it's time to pull all those functions out of the standard library and move them to something called "deprecated". The open-source community should try this; it would break lots of programs at compile time, but they'd be easy to fix. And you've got the source.

  21. Re:Buffer overruns are inexcusable by Just+Some+Guy · · Score: 2

    <me too&gt&lt/me too&gt

    I never did understand why people insist on using old programming ideas for new code. Consider the following arenas:

    • System calls
    • Large apps
    • Device drivers or other time-critical code

    Theoretically, libc et al are well-checked and "safe". At the other extreme, it should be pretty easy to write a stripped-down and low-overhead set of functions for a device driver with minimalist parameter checking while maintaining a set of hard limits on input data.

    That leaves larger programs, such as mailers, browsers, editors, etc. In those systems, why are so many unwilling to use the tools already in front of them? Why roll your own string handler when C++ has it already? Need a stack class? Got it! Array? Check! I can't imagine one single time, ever, when your average coder would need (or want!) to be using libraries with potentially unsafe calls. Wake up, fellow hackers! You are free to not be bothered with these problems anymore if only you'll be willing to answer the call and learn about the options that available to you.

    --
    Dewey, what part of this looks like authorities should be involved?
  22. Re:which system calls are bad? by mikpos · · Score: 2

    OK first off, I think you mean snprintf() and sprintf(), not vnprintf() and vprintf(). Secondly, strcpy() and sprintf() are very useful, and I don't find them dangerous at all.

    In fact, strncpy() I'd say is one of the most useless functions described in the standard. There are contexts where strcpy() makes sense, and there are contexsts where memcpy() makes sense, but never have I found a situation where strncpy() makes sense.

    snprintf() is also pretty bad BTW. Using snprintf() is so awkward that it's far easier to just use sprintf() (properly, though!).

    Anyway, gets() and scanf() seem to be the worst for buffer corruption. There are many other ways to kill yourself with standard calls, but not too many that will cause buffer corruption.

  23. Re:non executable stack by Lifewolf · · Score: 2

    On Digital UNIX I believe it's possible to make the stack non-executable when a process is running as root. Can this be done in Linux?

    No, and this is the topic of seemingly continual discussion on the kernel development list. See http://kt.linuxcare.com/ kernel-traffic/kt20000117_51.epl#1.

    Those for a non-executable stack argue it is one more level of protection on the system. Those against it argue the protection is illusionary (it just changes the form the attack takes) so all a non-executable stack adds is kernel bloat. I won't go further into either side here. Please see the aforementioned link for more detail.

    --
    "Be Happy or Die." -- AoN
  24. Re:which system calls are bad? by Malc · · Score: 2

    "OK first off, I think you mean snprintf() and sprintf(), not vnprintf() and vprintf(). "

    I think that you'll find that they're all valid. Here is the information from MSDN

    "but never have I found a situation where strncpy() makes sense. "

    I guess you haven't needed it for copying a sub-string, or when you're dealing with binary data that you know is a valid string but might not be termintated.

  25. How libsafe works... by Deven · · Score: 4
    This is great stuff! (Bell Labs rocks!)

    I downloaded the code and looked through their whitepaper and the source code a bit. Here's the basic technique:
    • Install the libsafe library in /lib/libsafe.so.1.3. (Red Hat Linux 6.2 users might want to get the RPM .)
    • Set the environment variable LD_PRELOAD to point to the libsafe library. (The RPM installs shell init scripts into /etc/profile.d for Red Hat 6.2 shells to do this.)
    • Calls to "unsafe" C library routines (e.g. strcpy(3)) will be trapped by libsafe, which will figure out the size of the stack frame and reimplement the "unsafe" function safely (e.g. with memcpy(3)).
    • If the program attempts to overflow the stack frame (presumably from a stack-smashing attack), a message is logged with syslog (into /var/log/secure) and the process group is killed with the SIGKILL signal.
    • This interception is done at runtime, and works without source code or recompiling
    • This technique can guard against stack-smashing exploits that haven't even been discovered yet. (And might even help discover them earlier!)
    There are a few caveats here:
    • There is a performance impact, but the overhead appears to be relatively low.
    • Since this technique relies on the dynamic linker (ld.so) to intercept the unsafe calls, statically-linked programs cannot be protected with this technique.
    • If LD_PRELOAD is used, setuid programs will not be protected because ld.so (properly) doesn't trust the environment variables when running setuid, and thus ignores LD_PRELOAD.
    • For system-wide protection, it is safer to use /etc/ld.so.preload instead of LD_PRELOAD; it will apply to all (dynamically-linked) programs, including setuid programs, and cannot be accidently lost from the environment.
    To the packager of the RPM: how about using /etc/ld.so.preload instead of LD_PRELOAD? Maybe in libsafe-1.3-3.*.rpm?
    --

    Deven

    "Simple things should be simple, and complex things should be possible." - Alan Kay

  26. Libsafe and StackGuard by Crispin+Cowan · · Score: 4
    Perry Wagle (principle StackGuard developer) has done some analysis comparing libsafe to stackguard. Here's the short version:

    • Use StackGuard when you can, because it's safer:
      • Libsafe only protects selected library string functions, while StackGuard protects all potential sources of stack overflow.
      • Libsafe depends on the existance of the frame pointer in the stack frame to parse/detect the stack frame. Unfortunately, the frame pointer may not be there, either because of a compile option to remove it, or because the optimizer took it out.
    • Use libsafe where you cannot use StackGuard. It's better than nothing, and it can protect closed-source apps where StackGuard cannot.
    The long version of the analysis is here.

    My further comment on libsafe: the paper that the authors will be presenting at USENIX in June presents two forms of defense ("library intercept" and binary-rewrite (BRW)) and only the library intercept appears to be embodied in the publicly available libsafe, which is why libsafe only protects against overflows that use particular string library functions.

    The BRW method is a pseudo-compiler that can transform binaries into "safe" programs by transforming the binary. It copies program onto the heap, inserting checks as it goes. The copy-to-the-heap is to make space for the additional checks. I really like the BRW method, and hope it becomes available.

    If my understanding is mistaken, and BRW is actually in the distributed libsafe, please correct me.

    Crispin
    -------
    CTO, WireX Communciations, Inc.
    Immunix: Free Hardened Linux

  27. Kernel patch for 2.0.x by kevlar · · Score: 2

    I remember there being a non-executable stack patch for the 2.0.x kernel, but for one reason or another it was upgraded for newer kernels. Anyone know if anyone has been working on something like this? There were some problems with it, for example, I believe JDK wouldn't work, and other such things that manipulate the stack in weird ways would have the same problem. I don't know if they were just issues that could be worked out, or if the system was fundamentally flawed in that area.

  28. Re:Buffer overruns are inexcusable by Malc · · Score: 2

    I was recently having problems with inexplicable access violations. I tracked it down to an sprintf and a buffer on the heap that wasn't big enough (I had tried to allocate the correct buffer size but I mixed up a couple of variables when calculating the lengths). This should have been the first point in the code that I looked as I use very few news/deletes... everywhere else I have STL and experienced no problems. I guess I assumed it was safe as I had already fixed a more obvious problem for the same sprintf about a month before. The whole experience just reinforces my believe that we're better off allowing the system to handle memory... or reuseing code such as the STL.

  29. Non-executable stacks are no solution. by Deven · · Score: 4

    Making the stack non-executable can intefere with valid code (e.g. signal handlers, nested function calls and trampoline functions) while leaving other stack-smashing exploits open to exploit. The libsafe library comes with an example exploit that will give you a shell despite a non-executable stack. Using libsafe will protect you from this attack without harming valid code. Making the stack non-executable remains vulnerable to this attack while breaking otherwise-valid code; the Linux kernel folks were right to reject the non-executable-stack "fix" to the problem.

    --

    Deven

    "Simple things should be simple, and complex things should be possible." - Alan Kay

  30. Re:The stack generally grows downwards. by Malc · · Score: 2

    Ahhh, so if the implementation were reversed, buffer overruns on the stack would overflow into unallocated memory (or if enough memory were in use, into the heap.)

  31. Bell Labs' press release by Deven · · Score: 2

    Bell Labs has a press release from April 20 about this...

    --

    Deven

    "Simple things should be simple, and complex things should be possible." - Alan Kay

  32. A different solution when you can fix the code by dsplat · · Score: 2

    When fixing the code is an option, there is a solution that eliminates most of the issues involved with buffer sizes. It can allow values of arbitrary length to be handled in cases where you don't want to set an upper limit, such as free-form text fields. And it has been around in glibc for ages. Obstacks! If libsafe is an airbag, then obstacks is a tank. Each makes the road safer (for you) in its own way.

    --
    The net will not be what we demand, but what we make it. Build it well.
  33. Protecting SUID programs via recompilation by lamontg · · Score: 2
    Instead of sticking libsafe in /etc/ld.so.preload and risking a bug taking out applications that you don't really want libsafe'd (I'm ignoring for the moment entirely valid arguments that all code is potentially privaleged and should be protected) there is another way to protect SUIDs. If you put libsafe in /lib with appropriate symlinks, and recompile suid programs with -lsafe then the programs will be dynamically linked against libsafe and will be protected without having to libsafe your entire distribution.

    Ex:

    % ls -1F /lib/libsafe*
    /lib/libsafe.so@
    /lib/libsafe.so.1@
    /lib/libsafe.so.1.3*
    % cat foo.c
    #include

    void foo(char *string) {
    char buffer[1024];
    strcpy(buffer, string);
    }

    int main(int argc, char *argv[]) {
    foo(argv[1]);
    }
    % gcc -o foo foo.c -lsafe
    % ldd foo
    libsafe.so.1 => /lib/libsafe.so.1 (0x4001c000)
    libc.so.6 => /lib/libc.so.6 (0x40021000)
    libdl.so.2 => /lib/libdl.so.2 (0x40116000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
    % ./foo `perl -e '{ print "A" x 1040 }'`
    Detected an attempt to write across stack boundary.
    Terminating /home/lamont/security/non-exec/foo.

    You can make that executable suid root and it works the same.

  34. Huh? by p3d0 · · Score: 2

    Making the stack non-executable can intefere with valid code (e.g. signal handlers, nested function calls and trampoline functions)

    What are you talking about? None of these things need an executable stack. And the example exploit does need an executable stack. The code is loaded into a local variable (ie. on the stack) and then executed.

    Normal C code does not provide any way to execute the stack. You have to do abnormal things like cast the address of a local variable as a function pointer and execute it; not something that normal C programs do. Or (of course) overrun the return address.
    --
    Patrick Doyle

    --
    Patrick Doyle
    I mod down every jackass who puts his moderation policy in his sig. Oh, wait a sec....
  35. Excellent point! by p3d0 · · Score: 2

    Here, however, libsafe could not help anyway, because I really doubt they've found a way to make a library that can determine how much you really want to store in dest before overwriting something important nearby on your data segment, such as a function pointer, etc.

    Hey, moderate this up! Even though libsafe can prevent you from overwriting the return address, it can't prevent you from overwriting a function pointer in the current stack frame. The latter could be just as good as the former for buffer overflow attacks.

    --
    Patrick Doyle

    --
    Patrick Doyle
    I mod down every jackass who puts his moderation policy in his sig. Oh, wait a sec....
  36. Re:Rather ironic... by howardjp · · Score: 2

    I think what I did wrong was installing Linux. After I replaced it with another Unix, life was good :)