Introduction. ------------ Every now and then a new "exploit" turns up of some program that uses tmp files. The first solution was "sticky bits", but since links exist (that''s a LONG time), that solution is inadequate. Discussion. ---------- The problem is that you put an object (link/pipe) in the place where you expect a program to put its tempfile, and wait for another user to open the tempfile. Usually a method can be found that would allow you to gain access to rights of the user opening the tempfile. Sometimes a program already checks for the existence of the file, and creates it if its not there. This is not atomic, and cannot easily be made secure. The standard trick is to create a symlink that you move back and forth between the "expected" file name and some "storage place". On operating systems, like HPUX and SunOS, this has a much better than 50% chance of success because they have synchronous directory updates. On operating systems that have an efficient buffer cache, like Linux, the chances are much worse. But that won''t save your machine from someone gaining root access: the bad guys simply write a program to try it 100 times. The Unix philosophy is that things that should be easy also -=are=- easy. So, a program that has setuid rights might need to be careful not to give those rights away. A non-setuid program should not have to worry about buffer overruns (you can crash the program, wow!). It should similarly not have to worry about temporary files. Solutions. --------- 1) Have a libc function that securely creates a file and passes a file descriptor to that file. 2) Have all programs respect an environment variable $TMP that says where to put temporary files. Make the distributions set this to $HOME/tmp, and make the "create a user" script add that directory. 3) A special file system (option) that doesn''t allow symlinks or hardlinks to files that you don''t own. This has been suggested in the past. 4) A special "/tmp" directory, that''s private for every userid. Solution 1 is not really adequate: It doesn''t solve the problem for: - programs that use the "get me a temp file -=name=-" function. - Shell scripts. - programs that use their own algorithms to generate a temporary file name. Solution 2 doesn''t really work for all existing programs. It doesn''t work for ad-hoc shell scripts. Solution 3 has the problem is that it sometimes doesn''t solve the problem: can I create a symlink to a symlink? Can I then change the second symlink (which can be on a "tolerant" filesystem!)? Ad 4: Some have suggested a "special case" for the use in "/tmp". I dislike special cases, and would prefer a general solution that is also capable of solving this. Suggestion. ---------- How about allowing symlinks with "variable expansion"? A /tmp that is a symlink to /.tmp/$euid would do the trick. The kernel should maintain a small set of these variables (euid, uid, pid) without user-intervention. A general way of adding these variables on a per-process basis would make this a much more general feature. How about: echo "cad_version 5.0" > /proc/self/variables ln -s ''/usr/cad_$cad_version'' /usr/cad Note that /proc/self is a symlink to /proc/$pid, it is no longer a special case! I think that the general "process symlink" code should be modified for this. This would allow NFS clients to process the dynamic symlinks, allowing for more control, besides the fact that then you can have an ignorant host serving a full-featured Linux host. Questions. --------- - Does this really solve the problem at hand? - Do people find this general variable symlinks useful? - Does anybody want to volunteer writing the code? - Does anybody want to beta-test the written code? - What would get more testing: a patch for 2.1.x or 2.0.x? - How many people would get bitten by the functionality change of symlinks with $s in them? Suggestions for another character? Regards, Roger Wolff. -- If it''s there and you can see it, it''s REAL |___R.E.Wolff@BitWizard.nl | If it''s there and you can''t see it, it''s TRANSPARENT | Tel: +31-15-2137555 | If it''s not there and you can see it, it''s VIRTUAL |__FAX:_+31-15-2138217 | If it''s not there and you can''t see it, it''s GONE! -- Roy Wilks, 1983 |_____|
Olaf Kirch
1998-Mar-11 09:50 UTC
Re: [linux-security] Towards a solution of tmp-file problems.
On Mon, 09 Mar 1998 10:59:10 +0100, Rogier Wolff wrote:> How about allowing symlinks with "variable expansion"? A /tmp that is > a symlink to /.tmp/$euid would do the trick. The kernel should > maintain a small set of these variables (euid, uid, pid) without > user-intervention. A general way of adding these variables on a > per-process basis would make this a much more general feature.AFAIK, there was a patch by Thomas Schoebel-Theuer in some 2.1.x kernels that did somethng like this. I think it was removed again later, though. Also, I put some experimental stuff into unfsd a while back that would expand special tokens in a file name, including the uid (obtained from the client credentials). The setup for a `secure'' /tmp directory would involve a loopback NFS mount similar to amd''s. The details can be found in a README file in the source distribution. However in the end I figured this kind of trick is too complicated and kludgy and didn''t pursue it any further. My preferred approach to solving /tmp races is to fix these in the source. A promising first step in that direction might be a patched libc that checks for potentially dangerous uses of /tmp files, and use that for >6 months on a variety of systems and see what pops up. This is no substitute for an audit, but since no-one seems to find the time, it appears a reasonable compromise. Had we done this earlier, the problems with sort and perl would have been discovered long ago. Olaf -- Olaf Kirch | --- o --- Nous sommes du soleil we love when we play okir@monad.swb.de | / | \ sol.dhoop.naytheet.ah kin.ir.samse.qurax For my PGP public key, finger okir@brewhq.swb.de.
Pavel Kankovsky
1998-Mar-12 12:48 UTC
Re: [linux-security] Towards a solution of tmp-file problems.
I can''t resist the temptation to add my two cents... :) On Wed, 11 Mar 1998, Aleph One wrote:> This touches on the core problem of why even though the /tmp problem is as > old as UNIX is has never been fixed. There has just never been a standard > definition of what /tmp is used for. Every solution everyone has proposed > break one of the uses of /tmp. It used for temporary disk space, temporary > files, interprocess communication between process of the same uid, > IPC between processes of different uids, etc. Why one do you want to give > up?You hit the nail, Aleph. The problem is /tmp is used/misused/abused in many different ways: 1) temporary files generated by programs (ex: sort, man, perl -e) 2) temporary files created by users (ex: ls -lR / > /tmp/allfiles) 3) "well-known" place for caching, IPC, locks (ex: pine, X11) (and God knows what else) IMHO, world-writable /tmp ought to be abolished because: Number 3 is a true abuse. When you avoid Scylla (symlinks and friends) you get caught by Charibdis (denial of service) because the software relies on an ability to work with files having a certain name. I have no easy universal solution for this (I doubt such a solution exists at all). Number 2 is misuse. It makes sense to allow the users create their temporary files on a separate filesystem but they do not need a shared directory. I think a private temporary area for each user is a perfect solution. For number 1, the private temp areas would probably work as well, plus it provides a good deal of protection to all programs, even the stupid ones (gcc, sort). On the other hand, I do not think a magic "varlinked" /tmp is a good idea because it would cause quite a lot of confusion among users ("Joe, the file''s in /tmp/xyz." Joe: "Where? I can''t find it!") as well as among set[ug]id programs. On Thu, 12 Mar 1998, Nick Andrew wrote:> Because programs that _were_ privileged but have set euid == ruid will put > the tmpfile into a directory to which the user has access, I guess - and > that''s the root of the problem; the tmpfile _must_ be inaccessible to all > but the processes which actually need it.The program will create a _file_ to which the user has access (unless it plays a tricky game with directories). A function creating a completely anonymous file could help here, nevertheless, a privileged program using the credentials of the user to create a _sensitive_ file is lame. --Pavel Kankovsky aka Peak [ Boycott Microsoft -- http://www.vcnet.com/bms ] P.S. Off-topic comment to the original post: On Mon, 9 Mar 1998, Rogier Wolff wrote:> not to give those rights away. A non-setuid program should not have to > worry about buffer overruns (you can crash the program, wow!). ItOf course it SHOULD worry. Any network client is a good example.