[Zope3-dev] DoS problem in zope.sendmail.maildir
Marius Gedminas
mgedmin at b4net.lt
Wed Jun 6 17:36:25 EDT 2007
Hi,
On Wed, Jun 06, 2007 at 06:04:50PM +0200, Sascha Ottolski wrote:
> I discovered a problem with the maildir implementation, that is
> triggered when trying to use the QueuedDelivery with many (read: more
> than current filedescriptor limit of the zope process) mails at once:
...
> OSError: [Errno 24] Too many open files: '/home/so/sandbox/var/zope/lib/python/lalisio/app/site/../../../../var/zope/var/mqueue/new'
Oh, wow. I'd forgotted that this causes the data manager to keep an
open file descriptor for every email. Ouch.
Suggestion: introduce IMaildirMessageWriter.close() and call it in
QueuedMailDelivery.createDataManager.
> I need to kill -9 the server after that, SIGTERM seems to be ignored.
Ouch.
> The reason for that to happen is clear to me, however, I'm not sure how
> a fix could look like.
Did you create an bug in launchpad? I could attach a patch that I think
would fix the problem, but I don't currently have the time and energy to
test myself.
> One source of the problem is
>
>
> try:
> fd = os.open(filename, os.O_CREAT|os.O_EXCL|os.O_WRONLY, 0600)
> except OSError:
> # File exists
>
>
> OSError is obviously to broad to catch as a test if the unique filename
> could be created. May be use os.path.exists(filename) instead? But I'm
> not sure if this is equivalent in a platform independant way.
That solution would have a race condition. Better
try:
fd = os.open(filename, os.O_CREAT|os.O_EXCL|os.O_WRONLY, 0600)
except OSError, e:
import errno # actually put this at the very top
if e.errno != errno.EEXIST:
raise
# File exists
but would it work on Windows? Could anyone test that by running this
little program on Windows:
import os, errno
file('tempfile', 'w').close()
try:
fd = os.open('tempfile', os.O_CREAT|os.O_EXCL|os.O_WRONLY, 0600)
except OSError, e:
print e.errno == errno.EEXIST # prints True on Linux
> The real source of the problem lies in the MaildirMessageWriter: The
> passed-in filedescriptor remains open until commit() is called. No
> problem for sending some mails only, but when sending lots of
> messages in one transaction, the filedescriptor limit kicks in.
It's scary to see the problems in zope.sendmail, given that I'm
at least partially responsible for all of them.
> A dirty solution might be to change the write() and writeline() to open
> and close the file on every call. But there's probably a saner way.
Yes.
> BTW, I'm wondering if it is really safe to assume that
> os.rename(self._filename, self._new_filename) in the commit() message
> never fails?
Nothing is really safe. Renaming a file is much safer than creating a
file.
> Although I believe that it's almost impossible that it
> really could :-)
Sudden filesystem corruption, the kernel remounts it as read-only, and
you cannot rename anything. But then you have bigger problems than an
exception in the second phase of a commit.
Marius Gedminas
--
For Sale: Parachute. Only used once, never opened, small stain.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mail.zope.org/pipermail/zope3-dev/attachments/20070607/2944ff09/attachment.bin
More information about the Zope3-dev
mailing list