I've been testing file uploads and I am noticing that most operations result in junk left in files/tmp or other places.
At best, an upload will leave a copy of the file in files/tmp instead of "moving" the file to the final destination. Some operations result in a file being created with the name of the destination directory (e.g., "files", "issues", "images").
I am looking into this but more eyes on this would be good.
Specifically, I don't understand why file_move() does a copy/delete operation instead of move. It seems like we should be using the PHP move_uploaded_file() function. If locking is the issue then it needs to be handled better than it is now.
Comments
Comment #1
dopry commentedis your files/tmp the same as php's upload_tmp?
Comment #2
tangent commentedNope. My php temp is set to a path outside of the webspace (/home/blah/tmp or something like that) but files/tmp is drupal/files/tmp.
Comment #3
tangent commentedI guess it's also important to say that I'm using "public files" mode.
Comment #4
dopry commentedDo you have any modules besides core modules? Are you testing against a current head. I'm not seeing this behavior.
Comment #5
moshe weitzman commentedmaybe your apache lacks delete permission on the tmp dir?
Comment #6
tangent commentedSorry about the delay. I wasn't able to get back on this immediately.
I have taken my install back to square one and as vanilla as I can make it. It looks like everything works fine if you visit admin/settings before doing any uploads (so files/tmp is created before). Trying to upload a file without doing this creates a file called "tmp" instead of auto creating the tmp dir. I'm still calling this a bug (though others might disagree) but not a critical one.
If the file is being saved as "tmp" then it appears as if the "tmp" directory was intended to be created but was not and is returned as the filename instead. I'll try to submit a patch shortly.
Comment #7
dopry commentedanyword on the patch, or whether this is still an issue?
Comment #8
tangent commentedI believe this was resolved by another patch. I haven't been testing recently though so I'm afraid I can't confirm at the moment.
Comment #9
dopry commentedI have some hanging files in drupal's private tmp dir on a local installation.
Could anyone running a 4.7 site live, check their drupal tmp dir for hanging files? This could be big issue for sites upgrading to 4.7 after the release. I want to be certain this is nto an issue before the final release. If it is I have a garbage collection patch I can reroll against head.
upgrading to critical. since it could affect quotas and and be a real headache in shared hosting environments...
(Check drupal's tmp dir, not php's)
.darrel.
Comment #10
killes@www.drop.org commentedI've checked on drupal.org and there is indeed a number of dangling files in /tmp. It is a significant number of files after the data of the update. Most of them are however empty.
-rw------- 1 apache apache 0 Apr 5 23:30 tmp_gN4zbR
Comment #11
killes@www.drop.org commenteddowngrading, shoudl be no problem to write a cron based cleanup thingie.
Comment #12
dopry commentedI'm bumping back to critical just to get people to check their temp directories for hanging files. If they're there I'll get the cron based GC patch rerolled ASAP so it can be tested.
Comment #13
jakeg commentedI found this same bug last week and discussed it with killes and chx on IRC, due to the potential security nature of it. However it was generally decided to be a sysadmin issue rather than a Drupal issue, though I don't completely agree with this prognosis.
Basically, its possible for a single user with permission to upload files to upload an infinite number of files to the temporary directory, and those files will never be deleted by Drupal. This happens because on uploading a file (whether with upload.module or not - this applies to uploads to issues on drupal.org too) it first uploads to the temp directory on previewing a node or validating a node. But a session variable remembers that the file is there and later deletes it when the same user session visits a new node form or successfully submits the current node.
In theory, a script kiddie could write a script which fills up a server's tmp dir with unlimited files in the time it takes their bandwidth to upload that many files. This has the potential to fill up disks and hence cause database errors, lost files etc etc... not a fun idea at all!
To reproduce (on your own testing server):
- enable upload.module (though any file uploads will do the same)
- node/add/page and attach a file using AJAX (or upload normally and preview/validate the node without submitting it)
- without submitting the node, logout
- login, do the same again
- watch your temp directory fill up with files which will never get deleted now
Some ideas killes, chx and I came up with:
- a cron script to delete old files (though if a script kiddie fills up your disk before the cron run, this is no good)
- deleting files on closing sessions/deleting session info from the sessions db table
- stopping a user doing x y and z more than a certain number of times per x (e.g. flood control)
- ... i think we had more, but can't remember them now
None of the ideas seemed that great though.
To me, this has the potential to be a serious issue. I can just imagine a script kiddie writing a script which logs them in and out, in and out, uploading a file each time, until eventually the tmp directory is so full that the web server has no space left and mysql craps out and all kinds of things go wrong.
Comment #14
killes@www.drop.org commentedThe right way to fix such problems is to have the tmp directory on its own partition so that even if that runs full the only bad thing that happens is that you cant upload more files.
The only other usefull way to counter such a DoS attack is to build in a throttle mechanism so that a given user account can only leave so many dangling files.
Comment #15
dopry commentedI think drupal should al least make an attempt to clean up hanging files over a day old. Not everyone has access to create a unique tmp partition, and a lot of the open basedir code were just to cater to the demographic stuck with shared hosting. We shold at least be considerate in cleaning up our tmp space. Even on my servers drupal's tmp is seperate from php's tmp, and only php's tmp has its own partition.
Comment #16
chx commentedI am firm on this: write a five line shell script which deletes the oldest files from your tmp directory until you have enough space. Run this from cron. Nothing to see here, move on.
Comment #17
moshe weitzman commentedi agree with dopry that drupal should attempt to keep things tidy. we already do cleanup of watchdog entries - why are files different from Db records?
If for some reason the cron script is preferred over hook_cron(), then we should ship with such a script in /scripts.
Comment #18
dwwi'm with moshe and others. drupal should do it's own garbage collection. however, i don't think this is critical for 6.7.0. i could see us fixing this in the code (or adding the suggested cron script into scripts) in either 6.7.1 or even putting it off until 6.8, but i don't think drupal should leave junk in /tmp on the assumption that sysadmins will clear it out for us. re-opening the issue and downgrading it so it's not forgotten completely.
Comment #19
jakeg commentedHmm, I don't think its critical for 6.7.0 either... but I think 3D electron-ray-defribulas will be by then.
I do however think that it is Drupal's job to clean up these files. As I said earlier, otherwise they don't get deleted at all. How often do you look in your tmp directory/ies?
Comment #20
jakeg commentedblimin' b'llocks... 4.7.0 is out already!
Comment #21
magico commentedFollowing #13, #17 and #18 Drupal should try to keep things tidy. If it's Drupal's data, Drupal should have control hover it.
Comment #22
dwwthanks for the bump on this issue. however, it's still a bug, not a feature. ;) drupal is leaking files. that's incorrect behavior.
Comment #23
ricabrantes commentedbump, any news??
Comment #24
magico commentedThe file system changed meanwhile, but the issue still exists. The cron should clear the temp folder the same way it does to the watchdog table.
Comment #25
floretan commentedThe upload module handles temporary files cleanly. The only way to have drupal leave junk files was when uploading a new logo on the theme settings page. When looking at the code for the theme settings form in system.admin.inc, I found this:
I'm not sure what "garbage collector" is referred to here, but it's definitely not working when using a tmp folder other than php's upload_tmp.
The validation and saving of uploaded logo and favicon files also happens in the form itself rather than in the submit handler (probably so that if the upload fails the other settings are still saved), but this inconsistent behavior should be fixed.
Comment #26
dopry commented@magico: This should be resolved in D6.
@flobruit: The garbage collector being referenced is in system_cron().
This issue should be resolved as far as D6 core is concerned. Temp files will be kept for at least 24 hours or mins(I can't remember which offhand), until the garbage collection in system_cron remove them. Note: garbage collection requires cron running on your site.
If you are still experiencing issues with dangling temp files in Drupal 6, please open a new issue with step by step directions to reproduce the issue on a clean Drupal 6 install.
Comment #27
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.