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;
 {

Reply via email to