Repository navigation
Stack overflow on FreeBSD #100
Description
Hi,
I'm using dma on a FreeBSD 13 machine with a smarthost (smtp.migadu.com), but dma crashes with a stack overflow after consuming 100% cpu for a few minutes. I've seen this on two machines, on older releases of FreeBSD as well.
I've tried both with the dma in the base system, and installing the latest dma from pkg. I'm not too familiar with how this is really used, but I can reproduce the issue like this (or by just trying to use mail):
echo "test!" |/usr/local/libexec/dma -D -r 'test@prutt.party' 'oscar@prutt.party'
If I try to press ctrl-t in FreeBSD when running the above, I get some minor useful data:
# Removed a bunch of these: load: 1.82 cmd: dma 91917 [running] 230.39r 58.55u 111.70s 100% 5884k
mac_socket_check_receive+0x7a soo_read+0x19 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
amd64_syscall+0x10c fast_syscall_common+0xf8
soreceive_generic+0xe7 soreceive+0x44 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
soreceive_generic+0xe7 soreceive+0x44 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
soo_read+0x19 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
soreceive_generic+0xe7 soreceive+0x44 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
soreceive_generic+0xe7 soreceive+0x44 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
sys_read+0x99 amd64_syscall+0x10c fast_syscall_common+0xf8
soreceive_generic+0xe7 soreceive+0x44 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8
Any ideas?
This is a typical case, from /var/log/maillog:
Jun 30 13:13:50 hilda dma[181e2][60585]: new mail from user=root uid=26 envelope_from=<root@hilda>
Jun 30 13:13:50 hilda dma[181e2][60585]: mail to=<oscar@prutt.party> queued as 181e2.800e48050
Jun 30 13:13:50 hilda dma[181e2.800e48050][61054]: <oscar@prutt.party> trying delivery
Jun 30 13:13:50 hilda dma[181e2.800e48050][61054]: using smarthost (smtp.migadu.com:465)
Jun 30 13:13:51 hilda dma[181e2.800e48050][61054]: trying remote delivery to smtp.migadu.com [2001:41d0:2:863f::] pref 0
Jun 30 13:13:51 hilda dma[181e2.800e48050][61054]: connect to smtp.migadu.com [2001:41d0:2:863f::] failed: No route to host
Jun 30 13:13:51 hilda dma[181e2.800e48050][61054]: trying remote delivery to smtp.migadu.com [2001:41d0:2:aacc::] pref 0
Jun 30 13:13:51 hilda dma[181e2.800e48050][61054]: connect to smtp.migadu.com [2001:41d0:2:aacc::] failed: No route to host
Jun 30 13:13:51 hilda dma[181e2.800e48050][61054]: trying remote delivery to smtp.migadu.com [2001:41d0:2:267::] pref 0
Jun 30 13:13:51 hilda dma[181e2.800e48050][61054]: connect to smtp.migadu.com [2001:41d0:2:267::] failed: No route to host
Jun 30 13:13:51 hilda dma[181e2.800e48050][61054]: trying remote delivery to smtp.migadu.com [94.23.1.103] pref 0
# snip
Jun 30 13:18:51 hilda dma[181e2.800e48050][61054]: stack overflow detected; terminated
Here's my /etc/dma/dma.conf:
SMARTHOST smtp.migadu.com
PORT 465
AUTHPATH /etc/dma/auth.conf
SECURETRANSFER
STARTTLS
My /etc/dma/auth.conf looks valid, user@domain.tld|smtp.migadu.com:password.
My /usr/local/etc/mail/mailer.conf looks like this, currently configured for the dma from pkg:
sendmail /usr/local/libexec/dma
mailq /usr/local/libexec/dma
newaliases /usr/local/libexec/dma
rmail /usr/local/libexec/dma
Activity
oscarcarlsson commentedon Jun 30, 2021
I've tried removing STARTTLS from my configuration (as recommended by others) but it doesn't fix the issue. It's still crashing from a stack overflow.
Could it be something as silly as permission denied?Nope.corecode commentedon Jun 30, 2021
oscarcarlsson commentedon Jun 30, 2021
I got it working after some help - I changed port (to 587/tcp, from the provider recommended port 465/tcp) and added masquerade. But I guess that the stack overflow should still be looked into.
This is a full crash from my
/var/log/maillog:That's it.
tuffnatty commentedon Oct 2, 2021
Also getting stack overflow in port 465; seemingly fixed by switching the port to 587.
corecode commentedon Oct 2, 2021
you need to remove STARTTLS if you use port 465. 587 + STARTTLS should be preferred.
The stack overflow is definitely a bug though.
corecode commentedon Oct 3, 2021
could you attach with gdb and show a backtrace? It's not clear what leads to the stack overflow.
emaste commentedon Feb 3, 2022
You might need to set
sysctl kern.sugid_coredump=1to get a core file that you can open in gdb or lldbegwynn commentedon Jun 19, 2026
I'm running into this too. @oscarcarlsson's minimal reproducible example triggers it for my config. GDB does give good insights. I wasn't able to start it up with gdb, but was able to attach post-init. Here's the stack:
This corresponds with the return statement from do_timeout (although I'm running a slightly older version, I don't think this code has changed). Here we see that it's the stack protector which is intervening to kill the process during function return. The sequence appears to be:
I don't generally write C code, but my reading of the related source tells me that we could be seeing conflicts between the
sigsetjmp/siglongjmpusage and the stack protector. I suspect thatdo_timeoutmight be clobbering the stack canary.egwynn commentedon Jun 19, 2026
Confirmed. I extracted
do_timeoutand its supporting code and wrote a tiny function that sets the timeout and then sleeps. When compiled with the stack protector, I get the same error:Here it is with / without stack protection.
corecode commentedon Jun 19, 2026
caseyandgina commentedon Oct 7, 2026
Another data point, with a different trigger from the port-465 misconfiguration earlier in this thread: this still occurs with the dma in FreeBSD 15.1-RELEASE-p4 base (
contrib/dmathere and onmainstill have thesigsetjmpinsidedo_timeout()).Our trigger was a correctly configured smarthost (port 25, STARTTLS) whose per-IP connection rate limit stalls connections over the limit instead of refusing them. A host's daily
periodicmail plus adma -qretry opened more connections in one second than the limit allowed. Each stalled delivery sat inread_remote()untilCON_TIMEOUT, then aborted withstack overflow detected; terminatedexactly 300 s aftertrying remote delivery.The practical consequence is worse than a crash: the timeout path never runs, so the message is never deferred or bounced, and it stays queued. The next queue run resends the whole queue at once, so the same messages hit the same limit and abort again in lockstep every day. We had messages stuck for three days with nothing logged anywhere except the sending host's
maillog.We worked around it on the server side by not throttling our own hosts. Any peer that stalls a read for five minutes will still trigger it. Thanks for confirming the cause above. Keeping the
sigsetjmpin a frame that outlives the read (or usingpoll()/SO_RCVTIMEOwith nolongjmpat all) would fix it.