LWN.net Logo

Symbolic links in "sticky" directories

Symbolic links in "sticky" directories

Posted Jun 3, 2010 10:35 UTC (Thu) by nix (subscriber, #2304)
Parent article: Symbolic links in "sticky" directories

But some kernel hackers are not convinced that the core kernel should be fixing badly written applications.
I haven't seen anyone mentioning this, which is good, because anyone who did would be a fool. The 'badly written' code in question works perfectly well and securely everywhere except in writable-by-attacker directories (which pretty much means sticky-bitted ones in practice), so what we really have here is a Unix API which works fine everywhere except in /tmp, and appears to work even there. Are we surprised that developers don't notice this? It's an API that requires extra effort to use correctly, and whose failure is invisible until a malicious attacker exploits it: of course they get it wrong!

Also, as you pointed out, fixing every application (including all the binary-only ones) or educating every single developer is impractical: it hasn't happened in decades and we couldn't get everyone to upgrade even if we did fix it. At least if the kernel was blocking this we'd only need to get people to upgrade to that kernel once, and then this class of problems would be history.

(I just checked at my workplace, where fifty-odd developers write Unix financial server apps. Not one of them knew what TOCTTOU races were. A single one had heard of symlink attacks in /tmp, but wasn't clear how you avoided them. More than half of them had written code that writes to /tmp for one reason or another. If we are trying to fix this by educating developers, we are failing.)


(Log in to post comments)

Symbolic links in "sticky" directories

Posted Jun 3, 2010 10:52 UTC (Thu) by djm (subscriber, #11651) [Link]

> > But some kernel hackers are not convinced that the core kernel should
> > be fixing badly written applications.
>
> I haven't seen anyone mentioning this, which is good, because anyone who did would be a fool

Did you miss the entire wakelocks/suspend blockers discussion? (I do agree with you though)

Waiting for perfect appliation code == stupid plan

Posted Jun 3, 2010 13:47 UTC (Thu) by dwheeler (guest, #1216) [Link]

We've been waiting for several decades for these magical developers who never, ever, ever make a mistake. We will wait forever. After all, information on how to write secure programs on Linux is widely available; see my Secure Programming for Linux and Unix HOWTO, for example.

It's time to change our systems so that the vulnerabilities cannot happen in the first place. Making the system invulnerable to symlink attacks via /tmp, harder to exploit via buffer overflows, Fixing Unix/Linux filenames, are all part of that.

Waiting for perfect appliation code == stupid plan

Posted Jun 3, 2010 19:17 UTC (Thu) by wahern (subscriber, #37304) [Link]

If you really want to protect ignorant or absent-minded developers from TOCTTOU bugs, you'll have to discard signals, threads, shared memory, socket polling, and perhaps pre-emptive multitasking in general.

In fact, TOCTTOU is just a subset of atomicity bugs. Thus, anyone who doesn't know how to avoid symlink attacks is almost certainly committing a litany of other errors. In any multitasking environment one shouldn't try to memorize when and where to worry about atomicity gotchas, but when and where one doesn't need to worry. In other words, developers don't need to remember about "symlink attacks", because unless they can affirmatively exclude the possibility of concurrent operations, it must be assumed, and they should endeavor to prove that their code is appropriately safe.

IMHO, a better approach to this particular problem would be to add a check to valgrind for unsafe sticky-bit-directory operations (e.g. not using O_EXCL with O_CREAT, using a fixed name, etc.). Sadly, too few developers use valgrind, which is an even more pressing issue.

The enduring solution to the problem is something called "open source"--allowing careful users to analyze correctness--and something called "free software"--allowing conscientious users to fix any problem and share his solution with others without encumbrance. Add to this mix tools like valgrind which can--or can be modified to--detect these problems, and you have a reliable and flexible solution for not just this but many others problems.

I'm as pragmatic as the next guy, but papering over these kinds of mistakes is just a bad idea.

Waiting for perfect application code == stupid plan

Posted Jun 4, 2010 5:11 UTC (Fri) by dwheeler (guest, #1216) [Link]

> If you really want to protect ignorant or absent-minded developers from TOCTTOU bugs, you'll have to discard signals, threads, shared memory, socket polling, and perhaps pre-emptive multitasking in general.

"Preventing all possible TOCTTOU bugs" isn't necessary or even relevant for this patch to be useful. You don't have to prevent imperfect developers from making EVERY bug for bug prevention to be useful. Simply find the more common kinds of errors that CAN be prevented, and try to prevent them. After a while there will be diminishing returns, but we aren't there today.

I haven't seen anyone argue that they NEED this particular symlink functionality, other than to implement attacks.

> IMHO, a better approach to this particular problem would be to add a check to valgrind for unsafe sticky-bit-directory operations (e.g. not using O_EXCL with O_CREAT, using a fixed name, etc.). Sadly, too few developers use valgrind, which is an even more pressing issue.

Of course, that "better approach" fails for the reason you gave: It is possible (and likely) that a developer will not use valgrind.

It also fails because valgrind only detects problems if your tests happen to use that functionality. If it's not in the test suite that you use with valgrind, you still miss the problem even IF you use valgrind.

Valgrind definitely has its uses, but it's nowhere near as effective in this case.

> I'm as pragmatic as the next guy, but papering over these kinds of mistakes is just a bad idea.

This is not "papering over". This is "limiting damage" or "preventing disaster". Preventing the opening of symlinks in this case doesn't prevent all problems, of course, and in fact, the software still won't work quite as originally intended. But it greatly reduces damage, giving developers (1) warning that they have a problem, and (2) time to fix it.

Obligatory car analogy: This is like a seat belt in a car. Clearly, it's better to not drive your car run into a wall or another car. But several decades have shown conclusively that we can't prevent all accidents. We should *certainly* try to reduce accidents further when we can. But we need to be reducing the damage caused when accidents happen.

I suggest taking a look at "Normal Accident theory". Increasingly, people are realizing that accidents are NORMAL in complicated systems. We should prevent them where we can, but where we can't, we need to reduce their consequences.

Waiting for perfect appliation code == stupid plan

Posted Jun 4, 2010 5:27 UTC (Fri) by dwheeler (guest, #1216) [Link]

I suggest taking a look at "Security Enhancements in Red Hat Enterprise Linux" by Ulrich Drepper. He describes a set of changes to ELF layouts and various restrictions that end up greatly reducing the vulnerabilities of systems even when programs have bugs (as they always do). "Disruptions are still possible, but the severity of the attacks is significantly reduce[d]".

Waiting for perfect appliation code == stupid plan

Posted Jun 4, 2010 13:24 UTC (Fri) by jschrod (subscriber, #1646) [Link]

Most developers I know don't program signal handling, threads, socket-polling, don't use shared memory, and don't create pre-emptive multitasking applications. (Some of these operations may be done in libraries or frameworks that they are using, but this is safely hidden from them.) But many of them create files in /tmp et.al.

Sorry, but I don't consider it "as pragmatic as the next guy" to argue against stopping the most common class of problems by pointing out that there are multiple similar problem classes that actually happens much less often. (Empirical data: symlink attack is the most common atomicity problem in CVE database.)

Waiting for perfect appliation code == stupid plan

Posted Jun 8, 2010 20:42 UTC (Tue) by nix (subscriber, #2304) [Link]

Quite so. Most of the developers I mentioned above spend much of their time talking to databases. They're used to races (the system is highly concurrent, with the concurrency isolated in separate processes communicating via the database), but they're largely protected from TOCTTOU by the database's transactionality. So they never learnt about it.

I find it hard to believe that this is uncommon.

Waiting for perfect appliation code == stupid plan

Posted Jun 8, 2010 23:46 UTC (Tue) by jschrod (subscriber, #1646) [Link]

Exactly. It's not that there are no atomicity problems in their development work, but the developers are not affected as it is handled by middleware or frameworks.

The only place where I see that they meet concurrency and all its associated problems are Java web applications with session state. And then they mark all methods of the respective session bean classes as "synchronized", without ever analyzing if it's needed or if it's sufficient. Well, most of them wouldn't know how to analyze it in the first place; cargo cult programming at its best.

And that's not limited to specific customers; I make the same observation in finance (not the equity departments, though), automotive, and telco companies.

Waiting for perfect appliation code == stupid plan

Posted Jun 9, 2010 12:07 UTC (Wed) by nix (subscriber, #2304) [Link]

Exactly. Concurrency is hard enough that most people can't handle it. This is surely not news.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds