Prereq: "2.5.3"
diff -cr /var/tmp/postfix-2.5.3/src/global/mail_version.h ./src/global/mail_version.h
*** /var/tmp/postfix-2.5.3/src/global/mail_version.h	Fri Jul 25 21:47:08 2008
--- ./src/global/mail_version.h	Thu Aug 14 08:11:37 2008
***************
*** 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	"20080726"
! #define MAIL_VERSION_NUMBER	"2.5.3"
  
  #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	"20080814"
! #define MAIL_VERSION_NUMBER	"2.5.4"
  
  #ifdef SNAPSHOT
  # define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
diff -cr /var/tmp/postfix-2.5.3/HISTORY ./HISTORY
*** /var/tmp/postfix-2.5.3/HISTORY	Sun Jul 27 16:45:34 2008
--- ./HISTORY	Tue Aug  5 14:04:59 2008
***************
*** 14411,14413 ****
--- 14411,14432 ----
  	by the recipient. Requested by Sebastian Krahmer, SuSE.
  	Specify "strict_mailbox_ownership=no" to ignore ownership
  	discrepancies.  Files: local/mailbox.c, virtual/mailbox.c.
+ 
+ 20080804
+ 
+ 	Bugfix: dangling pointer in vstring_sprintf_prepend().
+ 	File: util/vstring.c.
+ 
+ 20080814
+ 
+ 	Security: some systems have changed their link() semantics,
+ 	and will hardlink a symlink, contrary to POSIX and XPG4.
+ 	Sebastian Krahmer, SuSE. File: util/safe_open.c.
+ 
+ 	The solution introduces the following incompatible change:
+ 	when the target of mail delivery is a symlink, the parent
+ 	directory of that symlink must now be writable by root only
+ 	(in addition to the already existing requirement that the
+ 	symlink itself is owned by root).  This change will break
+ 	legitimate configurations that deliver mail to a symbolic
+ 	link in a directory with less restrictive permissions.
diff -cr /var/tmp/postfix-2.5.3/src/util/safe_open.c ./src/util/safe_open.c
*** /var/tmp/postfix-2.5.3/src/util/safe_open.c	Sun Jun  4 19:04:49 2006
--- ./src/util/safe_open.c	Mon Aug  4 16:47:18 2008
***************
*** 83,88 ****
--- 83,89 ----
  #include <msg.h>
  #include <vstream.h>
  #include <vstring.h>
+ #include <stringops.h>
  #include <safe_open.h>
  
  /* safe_open_exist - open existing file */
***************
*** 138,150 ****
       * for symlinks owned by root. NEVER, NEVER, make exceptions for symlinks
       * owned by a non-root user. This would open a security hole when
       * delivering mail to a world-writable mailbox directory.
       */
      else if (lstat(path, &lstat_st) < 0) {
  	vstring_sprintf(why, "file status changed unexpectedly: %m");
  	errno = EPERM;
      } else if (S_ISLNK(lstat_st.st_mode)) {
! 	if (lstat_st.st_uid == 0)
! 	    return (fp);
  	vstring_sprintf(why, "file is a symbolic link");
  	errno = EPERM;
      } else if (fstat_st->st_dev != lstat_st.st_dev
--- 139,167 ----
       * for symlinks owned by root. NEVER, NEVER, make exceptions for symlinks
       * owned by a non-root user. This would open a security hole when
       * delivering mail to a world-writable mailbox directory.
+      * 
+      * Sebastian Krahmer of SuSE brought to my attention that some systems have
+      * changed their semantics of link(symlink, newpath), such that the
+      * result is a hardlink to the symlink. For this reason, we now also
+      * require that the symlink's parent directory is writable only by root.
       */
      else if (lstat(path, &lstat_st) < 0) {
  	vstring_sprintf(why, "file status changed unexpectedly: %m");
  	errno = EPERM;
      } else if (S_ISLNK(lstat_st.st_mode)) {
! 	if (lstat_st.st_uid == 0) {
! 	    VSTRING *parent_buf = vstring_alloc(100);
! 	    const char *parent_path = sane_dirname(parent_buf, path);
! 	    struct stat parent_st;
! 	    int     parent_ok;
! 
! 	    parent_ok = (stat(parent_path, &parent_st) == 0	/* not lstat */
! 			 && parent_st.st_uid == 0
! 			 && (parent_st.st_mode & (S_IWGRP | S_IWOTH)) == 0);
! 	    vstring_free(parent_buf);
! 	    if (parent_ok)
! 		return (fp);
! 	}
  	vstring_sprintf(why, "file is a symbolic link");
  	errno = EPERM;
      } else if (fstat_st->st_dev != lstat_st.st_dev
diff -cr /var/tmp/postfix-2.5.3/src/util/vstring.c ./src/util/vstring.c
*** /var/tmp/postfix-2.5.3/src/util/vstring.c	Sat Jan  7 21:08:16 2006
--- ./src/util/vstring.c	Mon Aug  4 16:23:33 2008
***************
*** 624,629 ****
--- 624,630 ----
      result_len = VSTRING_LEN(vp);
  
      /* Construct: old|new|old|free */
+     VSTRING_SPACE(vp, old_len);
      vstring_memcat(vp, vstring_str(vp), old_len);
  
      /* Construct: new|old|free */