LWN.net Logo

Waiting for perfect appliation code == stupid plan

Waiting for perfect appliation code == stupid plan

Posted Jun 3, 2010 19:17 UTC (Thu) by wahern (subscriber, #37304)
In reply to: Waiting for perfect appliation code == stupid plan by dwheeler
Parent article: Symbolic links in "sticky" directories

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.


(Log in to post comments)

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