]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.11.10 v2.11.10
authorWietse Venema <wietse@porcupine.org>
Tue, 13 Jun 2017 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Wed, 12 Jul 2017 05:53:25 +0000 (01:53 -0400)
postfix/HISTORY
postfix/src/global/mail_version.h
postfix/src/util/dict_db.c

index 7738a494ffb154526fe232ae7fce44166b672397..11f035d93bdeb080f2d6ba71c1295d883b932875 100644 (file)
@@ -19780,3 +19780,16 @@ Apologies for any names omitted.
        senders with "smtpd_reject_unlisted_recipient = yes" or
        with reject_unlisted_sender.  Stephen R. van den Berg (Mr.
        procmail).  Files: smtpd/smtpd.c, smtpd/smtpd_check.c.
+
+20170611
+
+       Security: Berkeley DB 2 and later try to read settings from
+       a file DB_CONFIG in the current directory.  This undocumented
+       feature may introduce undisclosed vulnerabilities resulting
+       in privilege escalation with Postfix set-gid programs
+       (postdrop, postqueue) before they chdir to the Postfix queue
+       directory, and with the postmap and postalias commands
+       depending on whether the user's current directory is writable
+       by other users. This fix does not change Postfix behavior
+       for Berkeley DB < 3, but reduces file create performance
+       for Berkeley DB 3 .. 4.6.  File: util/dict_db.c.
index 2047081717e88e80586ff15cd0212d4d61646950..2f918db5456e57f0682669acc5f22b98f5cb2c0d 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20170101"
-#define MAIL_VERSION_NUMBER    "2.11.9"
+#define MAIL_RELEASE_DATE      "20170613"
+#define MAIL_VERSION_NUMBER    "2.11.10"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index 93ee48098fa4025db936a167abee13eb35d5a306..9a3c53dd04f8d5233619d64ed7b5162018c9420f 100644 (file)
 typedef struct {
     DICT    dict;                      /* generic members */
     DB     *db;                                /* open db file */
+#if DB_VERSION_MAJOR > 2
+    DB_ENV *dbenv;
+#endif
 #if DB_VERSION_MAJOR > 1
     DBC    *cursor;                    /* dict_db_sequence() */
 #endif
@@ -558,6 +561,9 @@ static void dict_db_close(DICT *dict)
     if (DICT_DB_CLOSE(dict_db->db) < 0)
        msg_info("close database %s: %m (possible Berkeley DB bug)",
                 dict_db->dict.name);
+#if DB_VERSION_MAJOR > 2
+    dict_db->dbenv->close(dict_db->dbenv, 0);
+#endif
     if (dict_db->key_buf)
        vstring_free(dict_db->key_buf);
     if (dict_db->val_buf)
@@ -567,6 +573,44 @@ static void dict_db_close(DICT *dict)
     dict_free(dict);
 }
 
+#if DB_VERSION_MAJOR > 2
+
+/* dict_db_new_env - workaround for undocumented ./DB_CONFIG read */
+
+static DB_ENV *dict_db_new_env(const char *db_path)
+{
+    VSTRING *db_home_buf;
+    DB_ENV *dbenv;
+    u_int32_t cache_size_gbytes;
+    u_int32_t cache_size_bytes;
+    int     ncache;
+
+    if ((errno = db_env_create(&dbenv, 0)) != 0)
+       msg_fatal("create DB environment: %m");
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 7)
+    if ((errno = dbenv->get_cachesize(dbenv, &cache_size_gbytes,
+                                     &cache_size_bytes, &ncache)) != 0)
+       msg_fatal("get DB cache size: %m");
+    if (cache_size_gbytes == 0 && cache_size_bytes < dict_db_cache_size) {
+       if ((errno = dbenv->set_cache_max(dbenv, cache_size_gbytes,
+                                         dict_db_cache_size)) != 0)
+           msg_fatal("set DB max cache size %d: %m", dict_db_cache_size);
+       if ((errno = dbenv->set_cachesize(dbenv, cache_size_gbytes,
+                                         dict_db_cache_size, ncache)) != 0)
+           msg_fatal("set DB cache size %d: %m", dict_db_cache_size);
+    }
+#endif
+    /* XXX db_home is also the default directory for the .db file. */
+    db_home_buf = vstring_alloc(100);
+    if ((errno = dbenv->open(dbenv, sane_dirname(db_home_buf, db_path),
+                          DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE, 0)) != 0)
+       msg_fatal("open DB environment: %m");
+    vstring_free(db_home_buf);
+    return (dbenv);
+}
+
+#endif
+
 /* dict_db_open - open data base */
 
 static DICT *dict_db_open(const char *class, const char *path, int open_flags,
@@ -582,6 +626,10 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
 #if DB_VERSION_MAJOR > 1
     int     db_flags;
 
+#endif
+#if DB_VERSION_MAJOR > 2
+    DB_ENV *dbenv;
+
 #endif
 
     /*
@@ -685,12 +733,10 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
        db_flags |= DB_CREATE;
     if (open_flags & O_TRUNC)
        db_flags |= DB_TRUNCATE;
-    if ((errno = db_create(&db, 0, 0)) != 0)
+    if ((errno = db_create(&db, dbenv = dict_db_new_env(db_path), 0)) != 0)
        msg_fatal("create DB database: %m");
     if (db == 0)
        msg_panic("db_create null result");
-    if ((errno = db->set_cachesize(db, 0, dict_db_cache_size, 0)) != 0)
-       msg_fatal("set DB cache size %d: %m", dict_db_cache_size);
     if (type == DB_HASH && db->set_h_nelem(db, DICT_DB_NELM) != 0)
        msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM);
 #if DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0)
@@ -745,6 +791,9 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
     if (dict_flags & DICT_FLAG_FOLD_FIX)
        dict_db->dict.fold_buf = vstring_alloc(10);
     dict_db->db = db;
+#if DB_VERSION_MAJOR > 2
+    dict_db->dbenv = dbenv;
+#endif
 #if DB_VERSION_MAJOR > 1
     dict_db->cursor = 0;
 #endif