Prereq: "3.0.9"
diff -cr --new-file /var/tmp/postfix-3.0.9/src/global/mail_version.h ./src/global/mail_version.h
*** /var/tmp/postfix-3.0.9/src/global/mail_version.h	2017-06-10 16:23:26.000000000 -0400
--- ./src/global/mail_version.h	2017-06-13 13:35:49.000000000 -0400
***************
*** 20,27 ****
    * Patches change both the patchlevel and the release date. Snapshots have no
    * patchlevel; they change the release date only.
    */
! #define MAIL_RELEASE_DATE	"20170610"
! #define MAIL_VERSION_NUMBER	"3.0.9"
  
  #ifdef SNAPSHOT
  #define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
--- 20,27 ----
    * Patches change both the patchlevel and the release date. Snapshots have no
    * patchlevel; they change the release date only.
    */
! #define MAIL_RELEASE_DATE	"20170613"
! #define MAIL_VERSION_NUMBER	"3.0.10"
  
  #ifdef SNAPSHOT
  #define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
diff -cr --new-file /var/tmp/postfix-3.0.9/HISTORY ./HISTORY
*** /var/tmp/postfix-3.0.9/HISTORY	2017-06-10 16:05:12.000000000 -0400
--- ./HISTORY	2017-06-13 13:32:16.000000000 -0400
***************
*** 21857,21859 ****
--- 21857,21872 ----
  	It's supposed to be 7bit, therefore quoted-printable encoding
  	is not expected. Problem reported by Griff. File:
  	bounce/bounce_notify_util.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.
diff -cr --new-file /var/tmp/postfix-3.0.9/src/util/dict_db.c ./src/util/dict_db.c
*** /var/tmp/postfix-3.0.9/src/util/dict_db.c	2014-12-06 20:35:33.000000000 -0500
--- ./src/util/dict_db.c	2017-06-13 12:17:36.000000000 -0400
***************
*** 122,127 ****
--- 122,130 ----
  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
***************
*** 553,558 ****
--- 556,564 ----
      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)
***************
*** 562,567 ****
--- 568,611 ----
      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,
***************
*** 578,583 ****
--- 622,631 ----
      int     db_flags;
  
  #endif
+ #if DB_VERSION_MAJOR > 2
+     DB_ENV *dbenv;
+ 
+ #endif
  
      /*
       * Mismatches between #include file and library are a common cause for
***************
*** 681,692 ****
  	db_flags |= DB_CREATE;
      if (open_flags & O_TRUNC)
  	db_flags |= DB_TRUNCATE;
!     if ((errno = db_create(&db, 0, 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 == 6 || DB_VERSION_MAJOR == 5 || \
--- 729,738 ----
  	db_flags |= DB_CREATE;
      if (open_flags & O_TRUNC)
  	db_flags |= DB_TRUNCATE;
!     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 (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 == 6 || DB_VERSION_MAJOR == 5 || \
***************
*** 743,748 ****
--- 789,797 ----
      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