Skip to content

nullmailer-smtpd fails to handle SIGPIPE, closes unexpectedly #97

@schongallam

Description

@schongallam

Brief Description:

Steps to reproduce (see issue #95):

  • Give nullmailer-smtpd a malformed payload, where either the MAIL FROM or the RCPT TO target is invalid
  • For example:
HELO a\n
MAIL FROM:<b>\n
RCPT TO:<c>\n
DATA\n
line 1\r\n
\r\n.\r\n

Expected behavior: any of the following.

  • nullmailer-smtpd should report an SMTP error message.
  • reject invalid MAIL FROM or RCPT TO
  • report to ferr that write to stream has failed

Resulting behavior:

/app# nullmailer-smtpd
220 nullmailer-smtpd ready
HELO a
250 2.3.0 OK
MAIL FROM:<b>
250 2.1.0 Sender accepted
RCPT TO:<[email protected]>
250 2.1.5 Recipient accepted
DATA
354 End your message with a period on a line by itself
line 1
/app# echo $?
141

(141 = 128 + SIGPIPE)

Root cause:
Running in gdb shows that src/smtpd.cc, qwrite attempts to write to a closed file descriptor (line 118). Verified with signal handling patch (see fix below).

Impact:

  • SMTP clients are able to cause failure of nullmailer-smtpd.
  • nullmailer-smtpd exits without providing useful information why.

Fix(es):
Implementing a signal handler to catch SIGPIPE in src/smtpd.cc avoids a program crash. Here is a hacky proof of concept:

@@ -111,9 +111,16 @@
   return fout;
 }
 
+static void pipe_handler(const int signal_num)
+{
+  ferr << "signal " << signal_num << ".\n"; 
+  respond(resp_qwrite_err);
+}
+
 static bool qwrite(int qfd, const char* data, size_t len)
 {
   ssize_t wr;
+  signal(SIGPIPE, pipe_handler);
   while (len > 0) {
     wr = write(qfd, data, len);
     if (wr <= 0)

Resulting behavior, avoiding a crash:

/app# nullmailer-smtpd
220 nullmailer-smtpd ready
HELO me
250 2.3.0 OK
MAIL FROM:<a>
250 2.1.0 Sender accepted
RCPT TO:<[email protected]>
250 2.1.5 Recipient accepted
DATA
354 End your message with a period on a line by itself
line 1
451 4.3.0 Write to nullmailer-queue failed
451 4.3.0 Write to nullmailer-queue failed
signal 13.
nullmailer-smtpd: nullmailer-queue failed: 1
QUIT
221 2.0.0 Good bye
``

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions