Hintsbd: fix locking
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 9 Jun 2024 13:22:20 +0000 (14:22 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 9 Jun 2024 14:34:37 +0000 (15:34 +0100)
Broken-by: 627391cbcaf3
src/src/exim_dbutil.c
src/src/hintsdb.h
test/stderr/0398
test/stderr/0432

index b152df14587086147c9c46b687f078b6cf2aabaa..c466ae380dc7bfdbab63741bfbbab8f849548329 100644 (file)
@@ -292,18 +292,21 @@ dbfn_open(const uschar * name, int flags, open_db * dbblock,
 {
 int rc;
 struct flock lock_data;
-BOOL read_only = flags & O_RDONLY;
+BOOL read_only = (flags & (O_WRONLY|O_RDWR)) == O_RDONLY;
 uschar * dirname, * filename;
 
 /* The first thing to do is to open a separate file on which to lock. This
 ensures that Exim has exclusive use of the database before it even tries to
-open it. If there is a database, there should be a lock file in existence. */
+open it. If there is a database, there should be a lock file in existence;
+if no lockfile we infer there is no database and error out.  We open the
+lockfile using the r/w mode requested for the DB, users lacking permission
+for the DB access mode will error out here. */
 
 if (  asprintf(CSS &dirname, "%s/db", spool_directory) < 0
    || asprintf(CSS &filename, "%s/%s.lockfile", dirname, name) < 0)
   return NULL;
 
-if ((dbblock->lockfd = Uopen(filename, O_RDWR|O_CREAT, 0)) < 0)
+if ((dbblock->lockfd = Uopen(filename, flags, 0)) < 0)
   {
   printf("** Failed to open database lock file %s: %s\n", filename,
     strerror(errno));
index 7335ef842851a6d4715e0c994ad36a98d95fc912..12c370dba7661403aa32865e574ed9d4f0329f14 100644 (file)
@@ -558,8 +558,7 @@ if (db_create(&b, dbp, 0) == 0)
   if (b->open(b, NULL, CS name, NULL,
              flags & O_CREAT ? DB_HASH : DB_UNKNOWN,
              flags & O_CREAT ? DB_CREATE
-             : flags & O_RDONLY ? DB_RDONLY
-             : 0,              /*XXX is there a writeable if exists option? */
+             : flags & (O_WRONLY|O_RDWR) ? 0 : DB_RDONLY,
              mode) == 0
          )
     return dbp;
@@ -694,8 +693,7 @@ return db_create(&dbp, NULL, 0) == 0
        dbp->open(dbp, CS name, NULL,
          flags & O_CREAT ? DB_HASH : DB_UNKNOWN,
          flags & O_CREAT ? DB_CREATE
-         : flags & O_RDONLY ? DB_RDONLY
-         : 0,          /*XXX*/
+         : flags & (O_WRONLY|O_RDWR) ? 0 : DB_RDONLY,
          mode)
      ) == 0
   ? dbp : NULL;
@@ -842,8 +840,7 @@ if (dbp)
   dbp->lkey.dptr = NULL;
   dbp->gdbm = gdbm_open(CS name, 0,
     flags & O_CREAT ? GDBM_WRCREAT
-    : flags & (O_RDWR|O_WRONLY) ? GDBM_WRITER
-    : GDBM_READER,
+    : flags & (O_RDWR|O_WRONLY) ? GDBM_WRITER : GDBM_READER,
     mode, 0);
   if (dbp->gdbm) return dbp;
   free(dbp);
index 00ce934bdf1b90f68f30c99ed1f15af51b35dcf1..853ffbad3b8e0366209250980d6c18ab9b174ac5 100644 (file)
@@ -179,9 +179,9 @@ cmd buf flush ddd bytes
 cmdlog: '220:EHLO:250:MAIL:250:RCPT:550:QUIT:250'
  locking TESTSUITE/spool/db/callout.lockfile
  locked  TESTSUITE/spool/db/callout.lockfile
- EXIM_DBOPEN: file <TESTSUITE/spool/db/callout> dir <TESTSUITE/spool/db> flags=O_RDWR|O_CREAT
+ EXIM_DBOPEN: file <TESTSUITE/spool/db/callout> dir <TESTSUITE/spool/db> flags=O_RDWR
  returned from EXIM_DBOPEN: 0xAAAAAAAA
- opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT
+ opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR
  dbfn_write: key=remote datalen NNN
  wrote callout cache domain record for remote:
    result=1 postmaster=0 random=0
index a4dc904ce0e1921f5f1470bf9fead44769fa09f9..ef8cb9889d14ba0b9e06a2a7000f416a235e6b45 100644 (file)
@@ -132,9 +132,9 @@ cmd buf flush ddd bytes
 cmdlog: '220:EHLO:250:MAIL:250:RCPT:250:QUIT:220'
  locking TESTSUITE/spool/db/callout.lockfile
  locked  TESTSUITE/spool/db/callout.lockfile
- EXIM_DBOPEN: file <TESTSUITE/spool/db/callout> dir <TESTSUITE/spool/db> flags=O_RDWR|O_CREAT
+ EXIM_DBOPEN: file <TESTSUITE/spool/db/callout> dir <TESTSUITE/spool/db> flags=O_RDWR
  returned from EXIM_DBOPEN: 0xAAAAAAAA
- opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT
+ opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR
  dbfn_write: key=y datalen NNN
  wrote callout cache domain record for y:
    result=1 postmaster=0 random=0