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 Sydney Australia ====== 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.000000000 +1100 +++ b/mail.local/mail.local.c 2015-12-23 21:15:56.000000000 +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; {