Bug#736666: /usr/lib/sm.bin/mail.local: lockmailbox failed code 75 EX_TEMPFAIL
I now verified that I get good results by changing mail.local.c (within sendmail or sendmail-bin) as per patch below. My patch only addresses the issue of locking the /var/mail/USER file (with minimal changes to code); does not attempt to better handle group quotas, nor to improve security by giving up privileges early. Please consider adopting this patch or some similar change. Please re-assign this bug back to sendmail. --- I am curious as to how does mail ever work for others: am I the last one still using sendmail and mail.local for local delivery? Thanks, Paul Paul Szabo p...@maths.usyd.edu.au http://www.maths.usyd.edu.au/u/psz/ School of Mathematics and Statistics University of SydneyAustralia == diff -r -U10 a/mail.local/mail.local.c b/mail.local/mail.local.c --- a/mail.local/mail.local.c 2015-12-23 13:12:41.0 +1100 +++ b/mail.local/mail.local.c 2015-12-23 21:15:56.0 +1100 @@ -1408,24 +1408,52 @@ */ bool Locked = false; #ifdef MAILLOCK int lockmbox(name) char *name; { int r = 0; +/* + * Often we get here with RUID=0 EUID=user (why?!) and maillock() + * (or /usr/bin/dotlockfile within?) does not like that, can cope + * with RUID=user EUID=0 instead. Swap them... then swap back. + * Wonder whether could (should!) have given up all privileges, + * even setting "correct" GIDs, long ago... + */ + uid_t ruid,euid; + int swapped = 0; if (Locked) return 0; - if ((r = maillock(name, 15)) == L_SUCCESS) + + ruid = getuid(); + euid = geteuid(); + /* syslog(LOG_ERR, "Before maillock had r=%d e=%d", (int)getuid(), (int)geteuid()); */ + if ((int)ruid == 0 && (int)euid != 0) + { + (void)setreuid(euid,ruid); + /* syslog(LOG_ERR, "Swapped, now r=%d e=%d", (int)getuid(), (int)geteuid()); */ + swapped = 1; + } + + r = maillock(name, 15); + + if (swapped) + { + (void)setreuid(ruid,euid); + /* syslog(LOG_ERR, "Swapped back r=%d e=%d", (int)getuid(), (int)geteuid()); */ + } + + if (r == L_SUCCESS) { Locked = true; return 0; } switch (r) { case L_TMPLOCK: /* Can't create tmp file */ case L_TMPWRITE: /* Can't write pid into lockfile */ case L_MAXTRYS: /* Failed after retrycnt attempts */ errno = 0; @@ -1438,22 +1466,41 @@ errno = 0; r = EX_UNAVAILABLE; break; } return r; } void unlockmbox() { + uid_t ruid,euid; + int swapped = 0; + if (Locked) + { + ruid = getuid(); + euid = geteuid(); + /* syslog(LOG_ERR, "Before mailunlock had r=%d e=%d", (int)getuid(), (int)geteuid()); */ + if ((int)ruid == 0 && (int)euid != 0) + { + (void)setreuid(euid,ruid); + /* syslog(LOG_ERR, "Swapped, now r=%d e=%d", (int)getuid(), (int)geteuid()); */ + swapped = 1; + } mailunlock(); + if (swapped) + { + (void)setreuid(ruid,euid); + /* syslog(LOG_ERR, "Swapped back r=%d e=%d", (int)getuid(), (int)geteuid()); */ + } + } Locked = false; } #else /* MAILLOCK */ char LockName[MAXPATHLEN]; int lockmbox(path) char *path; {
Bug#736666: /usr/lib/sm.bin/mail.local: lockmailbox failed code 75 EX_TEMPFAIL
Now at jessie, I find that my "strace trick" does not work anymore. Testing with my cutdown code suggests that the culprit may be the ... setreuid(0,uid) ... in original mail.local, as changing that to either of setreuid(uid,0) setreuid(uid,uid) allows maillock() to succeed. The comments in mail.local were that it changed UID to better handle quota checks. But then: - should not it change GID also? - do quotas go by real or effective IDs? So many questions... more digging required. Test code below: cut down long ago from mail.local, not yet verified whether mail.local code changed since. Cheers, Paul Paul Szabo p...@maths.usyd.edu.au http://www.maths.usyd.edu.au/u/psz/ School of Mathematics and Statistics University of SydneyAustralia = /* Testing code mimicking sendmail mail.local . Compile with cc mytest.c -llockfile Fails if we use ... setreuid(0, uid) ... as in original mail.local, but succeeds with either ... setreuid(uid, 0) ... or ... setreuid(uid, uid) ... so maybe bug is in sendmail, after all. */ #include #include #include #include #include int main(argc, argv) int argc; char *argv[]; { /* name and UID of some plain user */ char *p = "psz"; uid_t uid = 1001; int off; /* use a reasonable umask */ (void) umask(0077); /* This was setreuid(0,uid) in original sendmail mail.local */ /* change UID for quota checks */ if (setreuid(uid, uid) < 0) { printf("450 setreuid(0, %d) errno=%d (r=%d, e=%d)\n", (int) uid, errno, (int) getuid(), (int) geteuid()); exit(1); } /* printf("Before:\n"); system("ls -al /var/mail"); */ if ((off = maillock(p, 15)) != 0) { printf("lockmailbox %s code %d errno=%d\n", p, off, errno); } /* printf("During:\n"); system("ls -al /var/mail"); */ mailunlock(); /* printf("After:\n"); system("ls -al /var/mail"); */ }
Bug#736666: /usr/lib/sm.bin/mail.local: lockmailbox failed code 75 EX_TEMPFAIL
Package: sendmail-bin Version: 8.14.4-4 Severity: normal File: /usr/lib/sm.bin/mail.local The wheezy mail.local is unable to deliver mail. I was getting syslog lines like: Jan 26 07:41:37 bari mail.local[11136]: lockmailbox psz failed; error code 75 Jan 26 07:41:37 bari sm-mta[11135]: s0PKfb67011134: to=p...@bari.maths.usyd.edu.au, delay=00:00:00, xdelay=00:00:00, mailer=local, pri=30977, dsn=4.0.0, stat=Deferred: local mailer (/usr/lib/sm.bin/mail.local) exited with EX_TEMPFAIL Looking into the problem with strace, I noticed that running mail.local with strace -f allowed it to succeed. A possible workaround is to move mail.local to some new name and replacing or wrapping it with a script: #!/bin/bash - # mail.local fails, but behind strace it works just fine... weird??!! # Start by doing: # mv -i /usr/lib/sm.bin/mail.local /usr/lib/sm.bin/mail.local.REAL # then create this script in its place. exec strace -o /dev/null -f /usr/lib/sm.bin/mail.local.REAL $@ = The following short C code demonstrates the issue. /* Testing with code mimicking sendmail mail.local . Compile with cc mytest.c -llockfile Fails when running plain or with strace, but succeeds when running with strace -f as shown below: root# ./a.out lockmailbox psz code 2 errno=1 root# strace -o outx ./a.out lockmailbox psz code 2 errno=1 root# strace -o outy -f ./a.out root# Another oddity: in the output of strace -f I see geteuid32() return 0 within the children (in the execed /usr/bin/dotlockfile): should not that return 1001? */ #include stdlib.h #include unistd.h #include stdio.h #include errno.h #include maillock.h int main(argc, argv) int argc; char *argv[]; { /* name and UID of some plain user */ char *p = psz; uid_t uid = 1001; int off; /* use a reasonable umask */ (void) umask(0077); /* change UID for quota checks */ if (setreuid(0, uid) 0) { printf(450 setreuid(0, %d) errno=%d (r=%d, e=%d)\n, (int) uid, errno, (int) getuid(), (int) geteuid()); exit(1); } if ((off = maillock(p, 15)) != 0) { printf(lockmailbox %s code %d errno=%d\n, p, off, errno); } mailunlock(); } = Thanks, Paul Paul Szabo p...@maths.usyd.edu.au http://www.maths.usyd.edu.au/u/psz/ School of Mathematics and Statistics University of SydneyAustralia -- Package-specific info: Ouput of /usr/share/bug/sendmail-bin/script: ls -alR /etc/mail: /etc/mail: total 124 drwxr-sr-x 7 smmta smmsp 1024 Jan 23 07:41 . drwxr-xr-x 172 root root 10240 Jan 23 11:11 .. -rwxr-xr-- 1 root smmsp 8043 Jan 23 09:00 Makefile -rw--- 1 root root 4261 Jan 22 12:35 access -rw-r- 1 smmta smmsp 3072 Dec 22 2009 access.db -rw-r--r-- 1 root smmsp 0 Dec 22 2009 aliases -rw-r- 1 smmta smmsp 3072 Jan 23 07:41 aliases.db -rw-r--r-- 1 root smmsp 2804 Jan 23 09:00 databases -rw-r--r-- 1 root root 5657 Jul 17 2008 helpfile -rw-r--r-- 1 root smmsp33 Dec 22 2009 local-host-names drwxr-sr-x 2 smmta smmsp 1024 Dec 22 2009 m4 drwxr-xr-x 2 root root 1024 Jan 22 12:35 peers drwxr-xr-x 2 root smmsp 1024 Jul 16 2008 sasl -rw-r--r-- 1 root smmsp 9491 Jan 23 07:41 sendmail.cf -rw-r--r-- 1 root root 8997 Jan 22 12:35 sendmail.cf.old -rw-r--r-- 1 root root 10032 May 6 2002 sendmail.conf -rw-r--r-- 1 root smmsp46 Jan 23 07:41 sendmail.mc drwxr-sr-x 2 smmta smmsp 1024 Dec 22 2009 smrsh -rw-r--r-- 1 root smmsp 8844 Jan 23 07:41 submit.cf -rw-r--r-- 1 root smmsp55 Jan 22 12:35 submit.cf.errors -rw-r--r-- 1 root root 8350 Jan 22 12:35 submit.cf.old -rw-r--r-- 1 root smmsp59 Jan 23 07:41 submit.mc drwxr-xr-x 2 smmta smmsp 1024 Dec 22 2009 tls -rw-r--r-- 1 root smmsp 0 Dec 22 2009 trusted-users /etc/mail/m4: total 2 drwxr-sr-x 2 smmta smmsp 1024 Dec 22 2009 . drwxr-sr-x 7 smmta smmsp 1024 Jan 23 07:41 .. -rw-r- 1 root smmsp0 Dec 22 2009 dialup.m4 -rw-r- 1 root smmsp0 Dec 22 2009 provider.m4 /etc/mail/peers: total 2 drwxr-xr-x 2 root root 1024 Jan 22 12:35 . drwxr-sr-x 7 smmta smmsp 1024 Jan 23 07:41 .. /etc/mail/sasl: total 2 drwxr-xr-x 2 root smmsp 1024 Jul 16 2008 . drwxr-sr-x 7 smmta smmsp 1024 Jan 23 07:41 .. /etc/mail/smrsh: total 2 drwxr-sr-x 2 smmta smmsp 1024 Dec 22 2009 . drwxr-sr-x 7 smmta smmsp 1024 Jan 23 07:41 .. lrwxrwxrwx 1 root smmsp 26 Dec 22 2009 mail.local - /usr/lib/sm.bin/mail.local lrwxrwxrwx 1 root smmsp 17 Dec 22 2009 procmail - /usr/bin/procmail lrwxrwxrwx 1 root smmsp 17 Dec 22 2009 vacation - /usr/bin/vacation /etc/mail/tls: total 23 drwxr-xr-x 2 smmta smmsp 1024 Dec 22 2009 . drwxr-sr-x 7 smmta smmsp 1024 Jan 23 07:41 .. -rw-r--r-- 1 root root 7 Dec 22 2009 no_prompt -rw--- 1 root root 1191 Dec 22 2009 sendmail-client.cfg -rw-r--r--
Bug#736666: /usr/lib/sm.bin/mail.local: lockmailbox failed code 75 EX_TEMPFAIL
Control: reassign -1 liblockfile1 1.09-5 Control: affects -1 + sendmail-bin On 2014-01-25 22:28, Paul Szabo wrote: The wheezy mail.local is unable to deliver mail. I was getting syslog lines like: Jan 26 07:41:37 bari mail.local[11136]: lockmailbox psz failed; error code 75 Jan 26 07:41:37 bari sm-mta[11135]: s0PKfb67011134: to=p...@bari.maths.usyd.edu.au, delay=00:00:00, xdelay=00:00:00, mailer=local, pri=30977, dsn=4.0.0, stat=Deferred: local mailer (/usr/lib/sm.bin/mail.local) exited with EX_TEMPFAIL Looking into the problem with strace, I noticed that running mail.local with strace -f allowed it to succeed. A possible workaround is to move sounds like a race condition, strace will change the timing ... The following short C code demonstrates the issue. /* Testing with code mimicking sendmail mail.local . Compile with cc mytest.c -llockfile Fails when running plain or with strace, but succeeds when running with strace -f as shown below: root# ./a.out lockmailbox psz code 2 errno=1 root# strace -o outx ./a.out lockmailbox psz code 2 errno=1 root# strace -o outy -f ./a.out root# Another oddity: in the output of strace -f I see geteuid32() return 0 within the children (in the execed /usr/bin/dotlockfile): should not that return 1001? */ #include stdlib.h #include unistd.h #include stdio.h #include errno.h #include maillock.h int main(argc, argv) int argc; char *argv[]; { /* name and UID of some plain user */ char *p = psz; uid_t uid = 1001; int off; /* use a reasonable umask */ (void) umask(0077); /* change UID for quota checks */ if (setreuid(0, uid) 0) { printf(450 setreuid(0, %d) errno=%d (r=%d, e=%d)\n, (int) uid, errno, (int) getuid(), (int) geteuid()); exit(1); } if ((off = maillock(p, 15)) != 0) { printf(lockmailbox %s code %d errno=%d\n, p, off, errno); } mailunlock(); } Thanks for the testcase. Reassigning to liblockfile. Andreas -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org