the djb way

qmail


batches o' patches

qmail is a very unique piece of software. Mature, secure, stable and reliable, it has proven its merits in the network wilds for well over 6 years now. Prodded, poked at, hacked and stressed, the original qmail-1.03 source code, released in June 1998, has withstood a test of time rarely achieved by any piece of software, much less a network application.

Because of its longevity, widespread usage, and source code availability, the behaviour of qmail is very well understood. With such long-lived software, any remaining quirks and limitations generally come to be considered as part of its specification. On many platforms and in most common applications, qmail can simply be used as is, right out of the box, with excellent results.

In some cases, though, users have found that modifications to qmail are occasionally necessary and/or desireable. Modifications to qmail are implemented through the application of third-party "patches": little bits of source code prepared by others that change the source code of the original qmail. As we have seen in the qmail installation procedure, patches have become a common feature encountered on what may be called "the qmail way".

There are three general reasons for modifying qmail:

  1. [bug]: to fix a programming error in qmail.
  2. [port]: to compile/run qmail on an "unsupported" platform.
  3. [feat]: to add a feature, capability or extension to qmail.

Before we consider specific patches, let us emphasize again: patches modify qmail. This shifts your trust from qmail onto the author of the patch, and is a measure not to be taken lightly. In the strictest sense, when qmail is modified it is no longer qmail.

Here are some guidelines to consider before applying any patches to qmail:

qmail patches have become a veritable cottage industry. Dozens and dozens of patches have been released by numerous contributors, as you will find whenever you peruse http://www.qmail.org/.

But please don't let yourself be confused or overwhelmed by all this. qmail isn't "broken", defective, or lacking in essential features. It is just that some users have developed modifications useful for highly specific environments and applications. And others have contributed modifications simply in the pursuit of theoretical perfection. For qmail installations easily and reliably serving hundreds of users, you will be fine without any patches at all.

Generally speaking, the shorter and simpler the patch, the better. Many patches simply change one or two lines in one or two files, and are easy to understand. As patches become more extensive, they become more complex and you are moving further away from what is known as qmail.

The use of patches may introduce other issues as well. If you need/want to apply multiple patches, these patches may conflict with one another. In such cases, you may then need to hunt down yet another "cocktail" type of patch, incorporating the multiple patches you want into a single patch.

Patches are generally not self-documenting. That is, you will need to describe your installation in some way, so that all current and future administrators will know how it may deviate from standard qmail.

With these warnings out of the way, let's look at some of the patches to consider.

[Note: in the descriptions that follow, the links refer to patches archived locally with local naming conventions. For the original source, please refer to the qmail patch directory at the end of this page.]

• qmail-1.03.qmail_local.patch [bug]

As far as we can determine, this is the only undisputed programming error found within qmail. We'll use it as an illustration of a typical patch. Here's the source:


diff -u qmail-1.03.old/qmail-local.c qmail-1.03/qmail-local.c
--- qmail-1.03.old/qmail-local.c	1998-06-15 05:52:55.000000000 -0500
+++ qmail-1.03/qmail-local.c	2003-01-09 14:22:48.000000000 -0600
@@ -645,7 +645,7 @@
     {
      cmds.s[j] = 0;
      k = j;
-     while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))
+     while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
        cmds.s[--k] = 0;
      switch(cmds.s[i])
       {

This patch affects a single file, qmail-local.c, starting at line 645. The line beginning with '-' indicates a line to be deleted; the line beginning with '+' indicates a line to be added. The other surrounding lines will be unchanged, and are shown only for context.

The intent of the code is to strip any trailing spaces and tabs from the instruction lines in .qmail files. With a little study, though, one can see that the original while() condition could evaluate a cmds.s[-1] == '\t' test --with an out-of-bounds array reference-- in the case of an empty/blank first line. The correction fixes the problem by grouping the space and tab tests in parentheses, ensuring that the white-space test is done only when safe to do so, and protecting against an undefined array access. The discovery of this error is attributed to Eric Sjolund; see the original post for reference.

Is this patch necessary? The man page for dot-qmail(5) states:

.qmail may contain extra spaces and tabs at the end of a line. Blank lines are allowed, but not for the first line of .qmail. [emphasis added]

So one could assert that the problematic condition is clearly documented and proscribed as "illegal input". Also, since the discovery of this error appeared over two years after qmail's last release, manifestations of this bug in actual practice would seem to be very uncommon.

On the other hand, this patch is so simple, and fixes such an apparent flaw, that it is hard to resist. And of course it is sensible to defend against bad input within the code itself, insofar as it is possible, especially when the results may otherwise produce undefined behavior that could possibly affect the whole system.

• qmail-1.03.smtpd-blast.patch [bug]

Ok, so here is another programming error. This one was discovered by Georgi Guninski --so it is sometimes referred to as the "Guninski" bug-- in January 2004. He found he could crash a qmail-smtpd session by sending it an extremely large single header line (more than 2GB before newline).

The crash brings down only the current SMTP connection, and no other exploit of the behavior has yet been reported.

For more information about the bug, see the original report at http://www.guninski.com/qmailcrash.html.

This patch makes a simple one-line fixup to the blast() function in the file "qmail-smtpd.c". After the patch is applied and installed, qmail-smptd will be able to receive header lines of any length. More details are noted in the header of the patch.

Once again, this is a small, simple fix, mostly suitable for perfectionists, Virgos, and other qmail obsessives. Otherwise, not worth getting in a FUD about.

The issue does point up an interesting weakness in the processing logic of the qmail-smtpd server, however. Even though you can setup effective message size and resource constraints with control/databytes and softlimit -f parameters, qmail-smtpd itself still does not actually terminate the session with the error, until after it has chewed its way through the entire message from the network. That is, you don't get to short-circuit the waste of bandwidth. Dang! (BTW, the ofmipd server behaves the same way.)

Note: the fix in this patch is attributed to James Craig Burley, who includes it in his much larger "ISO C" patch discussed below. The patch referenced here is only for the "Guninski" bug fix. You can choose between one or the other; you don't need both.

• qmail-1.03.errno.patch [port]

This simple patch is necessary to compile qmail on platforms such as Linux using the GNU C Library, version 2.3.x and later. We discuss this issue --common to most of Bernstein's packages-- on its own page: errno patches.

If you have any recent Linux distribution, you will need this patch.

• qmail-0.0.0.0.patch [port]

Scott Gifford encountered an incident where his qmail server was duped by a bogus MX record to relay delivery to IP address 0.0.0.0. On some platforms (such as Solaris and Linux), 0.0.0.0 is interpreted as the local host address 127.0.0.1, while qmail itself had no reason to recognize 0.0.0.0 as a local address. The result was a mail loop, as the bogus message was delivered repeatedly to the same server.

His patch affects the file ipme.c, so that qmail does recognize 0.0.0.0 as a local address.

Why is this called a portability fix here and not a bug? The call could really go either way. Bernstein developed qmail on an OpenBSD platform, which won't route to address 0.0.0.0. Try this on an OpenBSD box:

$ ping 0.0.0.0
PING 0.0.0.0 (0.0.0.0): 56 data bytes
ping: sendto: No route to host
ping: wrote 0.0.0.0 64 chars, ret=-1

While on a Linux box:

$ ping 0.0.0.0
PING 0.0.0.0 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.038ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.006ms

The patch is simple and makes qmail conformant to RFC 1122. Although not required for some platforms, it can help protect qmail from a type of denial of service attack. See also this documentation.

(Bernstein has since noted the anomalous behavior of OpenBSD in his UNIX portablility notes.)

• qmail-1.03.sendmail-f.patch [port]

The qmail distribution includes a sendmail binary intended to emulate local mail injection with sendmail.

This patch by David Phillips improves the emulation of sendmail's -f flag, using only the name argument to the flag, and unsetting all the other local MAIL-related environmental variables.

If applications residing on your qmail server will require local injection compatible with sendmail and the -f flag, well then here's your patch. Otherwise, this one is easy to pass.

• qmail-1.03.isoc.patch [port]

qmail is written in a dialect of C known as "K&R", sometimes referred to as "traditional C". The K&R dialect precedes and is less formally specified than what is now known as Standard C or ISO C.

Time marches on. Since qmail was released we have new formal standards, updated compilers, and new platforms. Not only are K&R idioms considered deprecated, they may be problematic on some platforms when the default int types implied by K&R may be a different size than pointers.

James Craig Burley has developed this patch to remove some ambiguities of argument types in the K&R idioms used by qmail. This patch may be required to run qmail safely on the latest 64-bit platforms, where the default int is 32-bit, but pointers are 64-bit. See also this document for more information. Otherwise, on 32-bit platforms this patch is not necessary.

Note: this patch also includes Burley's simple fix to the "Guninski" bug, discussed above as "qmail-1.03.smtpd-blast.patch". If you need only the one-liner Guninski bug fix, the patch mentioned earlier will do the trick as well; you don't need both.

• qmail-1.03.qmailqueue.patch [feat]

This patch by Bruce Guenter affects qmail.c and lets qmail recognize an environmental variable named QMAILQUEUE. If set, its value is used in place of the qmail-queue binary.

This provides a mechanism for various filters and pre-processors --such as anti-spam and virus protections-- to handle a message before being introduced into the queue.

Note that, as an alternative to patching, this feature may instead be provided by a simple shell script wrapper used for the qmail-queue binary. But the patch is very simple, efficient, easy to install, and provides the better solution if you need it.

Of course, this patch is only necessary if you will actually be running any add-on spam or virus filters that require it.


sidebar: "netqmail"

First released in the fall of 2003, the netqmail distribution is the collaborative effort of Charles Cazabon, Russell Nelson, Dave Sill and others to integrate a set of patches into a single formal "enhanced" qmail package.

As of this writing, the netqmail project has released netqmail-1.05 (2004.01.21); check qmail.org for the latest. We mention it here because it includes a single "meta-patch" that provides all the separate patches discussed above.

In addition to the patches listed above, the meta-patch also updates the documentation files, and indicates netqmail in the place of qmail.

The netqmail distribution is interesting for several reasons:

Of course with every good thing there may also be some downsides:

Because this is "the djb way" --straight, no chaser-- we think users will prefer and can handle their own patch decisions. So we'll stick to describing the basic qmail installation, with some informed discussion about a few patches that may be easily added as necessary.

But we do think netqmail is a nice choice to have!


• qmail-1.03.qmtpd-netstring.patch [bug]

This patch is for another bug documented by George Guninski at http://www.guninski.com/qmail-qmtpd.html.

The bug is in the code for the qmail-qmtpd server, which uses netstrings to safely and efficiently communicate over network connections. Unfortunately, the implementation fails to perform validity checks to ensure that input actually conforms to the netstring protocol. It is possible for an attacker to design netstring input that forces a buffer overflow in an unpatched qmail-qmtpd service.

This simple patch provides a fix. Of course, it is only necessary if you will actually be running a qmail-qmtpd service. We usually do, so this patch is one we recommend.

• qmail-1.03.qmtpc.patch [feat]

The purpose of this patch by Russell Nelson is to enable qmail-remote to attempt and conduct QMTP dialogues with QMTP-willing servers. The Quick Mail Transport Protocol and qmail-qmtpd service is discussed at greater length here.

This is one of the larger patches described on this page, as it adds in a capability the original qmail was lacking. But if you like the idea of QMTP as much as we do, this patch will help you join the qmtp cognoscenti.

• qmail-1.03.link-sync.patch [port]

We mentioned this patch by Frank Denis on the installation page. It provides a solution for making qmail more reliable on the filesystems commonly used on Linux platforms. Frank has some additional documentation available at http://www.jedi.claranet.fr/qmail-reiserfs-howto.html.

You can see that this is a fairly simple and straightforward patch, and the procedure to use it is slightly easier than the alternative syncdir fix.

On the downside, this patch affects the files qmail-local.c and qmail-queue.c, and so may conflict with other patches one may wish to apply.

• qmail-1.03.big-dns.patch [port]

We mention this patch by Christopher K. Davis because it is commonly referred to in other qmail "howto" instructions around the 'net, and incorporated with qmail port builds on some platforms.

It patches the dns.c file in qmail, allowing it to safely receive responses to DNS queries exceeding 512 bytes.

Of course, this patch is necessary only if using a DNS resolver such as (ahem) BIND.

Otherwise this patch is never needed for qmail servers built "the djb way", with DNS services provided by the dnscache resolver from the djbdns package.


qmail patch directory

locally archived original source
qmail-1.03.qmail_local.patch ftp://moni.csi.hu/pub/glibc-2.3.1/qmail-1.03.qmail_local.patch
qmail-1.03.smtpd-blast.patch http://www.thedjbway.org/qmail/patches/qmail-1.03.smtpd-blast.patch
qmail-1.03.errno.patch ftp://moni.csi.hu/pub/glibc-2.3.1/qmail-1.03.errno.patch
qmail-0.0.0.0.patch http://www.suspectclass.com/~sgifford/qmail/qmail-0.0.0.0.patch
qmail-1.03.sendmail-f.patch http://david.acz.org/software/sendmail-flagf.patch
qmail-1.03.isoc.patch http://www.jcb-sc.com/qmail/patches/qmail-isoc.patch
qmail-1.03.qmailqueue.patch http://qmail.org/qmailqueue-patch
qmail-1.03.qmtpd-netstring.patch http://www.thedjbway.org/qmail/patches/qmail-1.03.qmtpd-netstring.patch
qmail-1.03.qmtpc.patch http://www.qmail.org/qmail-1.03-qmtpc.patch
qmail-1.03.link-sync.patch http://www.jedi.claranet.fr/qmail-link-sync.patch
qmail-1.03.big-dns.patch http://www.ckdhr.com/ckd/qmail-103.patch

For some download convenience, the locally archived qmail patches listed above are collected into this tarball: qmail-1.03.patches.tar.gz. Of course, the usual warnings, disclaimers, and CYAs apply: NO WARRANTY, use at your own risk, etc., etc.


Copyright © 2002, 2003, 2004, Wayne Marshall.
All rights reserved.

Last edit 2004.10.04, wcm.