Package: qmail-src
Version: 1.03-45
Severity: important

I just started getting MANY complaints about duplicate e-mail delivery
from IMAP users.  Upon investigation, it turns out that Dan Bernstein
doesn't obey his own rules about manipulating Maildirs.

To be precise, qmail-local was doing:

8945  link("tmp/1203363108.8945.science", "new/1203363108.8945.science") = 0
8945  open("new/1203363108.8945.science", O_RDONLY) = -1 ENOENT (No such file 
or directory)
8945  unlink("tmp/1203363108.8945.science") = 0
8945  exit_group(1)                     = ?

This is because dovecot is using inotify to get instant notice of
the file's appearance and yanking the file out of new into cur before
qmail-local can open it to verify that it was copied.

Thus qmail-local returns 111 (temporary delivery failure), and local delivery
is retried... quite a few times before qmail-local wins the race.

It's a narrow race, but it's been a latent bug since forever.
Once the file is linked into new/, it's the proprty of the MUA, and
the MTA can make no further assumptions about what will happen to it.

The problem is in the maildir_child() function and can be neatly avoided
by deleting the if() containing the last open() at the end of that function.
I'm not entirely sure why it's there.  If the goal is to ensure the link()
call hits the disk, on Linux that's done by opening and fsync()ing the
DIRECTORY, not the file.  Alternatively, you can just ignore a failure
to open.  I.e. replace

 if ((fd = open(fnnewtph, O_RDONLY)) < 0 ||
     fsync(fd) < 0 || close(fd) < 0) goto fail;

by

 if ((fd = open(fnnewtph, O_RDONLY)) >= 0)
  {
   fsync(fd);
   close(fd);
  }

If you need to check that the link happened, the race can be widened by
stat()ing the tmp/ file and verifying its link count, but really, the
code shouldn't do anything.



-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to