From de531e70dc0e5aa94cf6fba35afa1cd23c36bf1f Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 9 Jun 2024 14:22:20 +0100 Subject: [PATCH] Hintsbd: fix locking Broken-by: 627391cbcaf3 --- src/src/exim_dbutil.c | 9 ++++++--- src/src/hintsdb.h | 9 +++------ test/stderr/0398 | 4 ++-- test/stderr/0432 | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/src/exim_dbutil.c b/src/src/exim_dbutil.c index b152df145..c466ae380 100644 --- a/src/src/exim_dbutil.c +++ b/src/src/exim_dbutil.c @@ -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)); diff --git a/src/src/hintsdb.h b/src/src/hintsdb.h index 7335ef842..12c370dba 100644 --- a/src/src/hintsdb.h +++ b/src/src/hintsdb.h @@ -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); diff --git a/test/stderr/0398 b/test/stderr/0398 index 00ce934bd..853ffbad3 100644 --- a/test/stderr/0398 +++ b/test/stderr/0398 @@ -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 dir flags=O_RDWR|O_CREAT + EXIM_DBOPEN: file dir 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 diff --git a/test/stderr/0432 b/test/stderr/0432 index a4dc904ce..ef8cb9889 100644 --- a/test/stderr/0432 +++ b/test/stderr/0432 @@ -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 dir flags=O_RDWR|O_CREAT + EXIM_DBOPEN: file dir 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 -- 2.30.2