from eupdatedb: ... tmpfile = "/tmp/esearchdb.py.tmp" ... if exists(tmpfile): print red("Error: "), " there is probably another eupdatedb running already." ... dbfile = open(tmpfile, "w") dbfile.write("db = (") ... obvious race condition there, but you dont have to try to beat it to make a nuisance of yourself :) You can make a file anywhere you like by making a broken symlink to it waiting for root to run eupdatedb... for example, as a non-privileged user run: ln -s /etc/nologin /tmp/esearchdb.py.tmp wait for root to run eupdatedb, and you just stopped everyone logging in :) Reproducible: Always Steps to Reproduce: 1. as normal user, run ln -s /etc/nologin /tmp/esearchdb.py.tmp 2. wait for root to eupdatedb 3. DoS! 4. (race condition as well) Actual Results: eupdatedb has insecure temp file handling procedure.
David -- Can you review/patch as appropriate?
Yes, Thanks a lot for the bug report. I didn't know this problem. What would be the most reasonable way to fix this bug? 1. Delete /tmp/esearchdb.py.tmp, Open new file and write If I use this solution, I have to find an other way to check if there is an instance of eupdatedb running. 2. Check if /tmp/esearchdb.py.tmp is a symlink -> delete or create 3. Other ways? Use a file in an other directory? David
Thanks for a great utility btw David, regarding comment #2 , it looks like python's open() supports O_EXCL and O_CREAT, could you use these flags when opening the tmpfile (and check for failure)? http://www.python.org/doc/current/lib/os-fd-ops.html
I'm not really a python programmer, so forgive me if this is considered very poor :) but, for example: $ diff -u eupdatedb.py.orig eupdatedb.py --- eupdatedb.py.orig 2004-06-29 00:00:03.148734752 +0100 +++ eupdatedb.py 2004-06-29 00:01:29.184655304 +0100 @@ -15,6 +15,7 @@ from output import red, darkgreen, green, bold, nocolor from os import stat, unlink, environ +from os import O_EXCL, O_CREAT, O_WRONLY, open, fdopen from os.path import exists from shutil import copyfile from getopt import * @@ -133,7 +134,12 @@ print " If you're sure there is no other process, remove", tmpfile print "" sys.exit(1) -dbfile = open(tmpfile, "w") +try: + dbfd = open(tmpfile, O_CREAT | O_EXCL | O_WRONLY, 0600) +except OSError: + print red("Error: "), " failed to open temporary file." + sys.exit(1) +dbfile = fdopen(dbfd, "w") dbfile.write("db = (") if not verbose:
another way to 'fix' this would be to manage the file in ${PORTAGE_TMPDIR} since that isnt a world writable directory then you'd just have to 'worry' about attacks from other root users ;)
Thanks for your comments and the patch, I will release esearch-0.6.2 with the fixed bug tomorrow. David
esearch-0.6.2 committed, I was so free to mark it stable for everyone.
GLSA is drafted.
GLSA 200407-01.