[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#741118: wheezy-pu: package ruby-passenger/3.0.13debian-1+deb7u2



Package: release.debian.org
Severity: normal
Tags: wheezy
User: release.debian.org@packages.debian.org
Usertags: pu

Hi,

There is another minor security issue in ruby-passenger concerning
insecure usage of temp files.
CVE-2014-1831 and CVE-2014-1832 have been assigned for this issue.

I'd like to fix those by backporting the relevant upstream commits,
see the attached debdiff.

Cheers,
Felix
diff -Nru ruby-passenger-3.0.13debian/debian/changelog ruby-passenger-3.0.13debian/debian/changelog
--- ruby-passenger-3.0.13debian/debian/changelog	2013-10-14 22:43:12.000000000 +0200
+++ ruby-passenger-3.0.13debian/debian/changelog	2014-03-08 19:43:55.000000000 +0100
@@ -1,3 +1,11 @@
+ruby-passenger (3.0.13debian-1+deb7u2) wheezy; urgency=medium
+
+  * Fix CVE-2014-1831 and CVE-2014-1832: insecure use of /tmp.
+    (Closes: #736958)
+    - Backport upstream commits in CVE-2014-1831.patch and CVE-2014-1832.patch
+
+ -- Felix Geyer <fgeyer@debian.org>  Sat, 08 Mar 2014 19:42:03 +0100
+
 ruby-passenger (3.0.13debian-1+deb7u1) wheezy; urgency=low
 
   * Fix CVE-2013-2119 and CVE-2013-4136: insecure tmp files usage.
diff -Nru ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1831.patch ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1831.patch
--- ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1831.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1831.patch	2014-03-08 19:41:41.000000000 +0100
@@ -0,0 +1,100 @@
+From 34b1087870c2bf85ebfd72c30b78577e10ab9744 Mon Sep 17 00:00:00 2001
+From: "Hongli Lai (Phusion)" <hongli@phusion.nl>
+Date: Tue, 28 Jan 2014 19:17:39 +0100
+Subject: [PATCH] Fix low-urgency security vulnerability: writing files to
+ arbitrary directory by hijacking temp directories.
+
+---
+ ext/common/ServerInstanceDir.h |  2 +-
+ ext/common/Utils.cpp           | 29 +++++++++++++++++++++++++++++
+ ext/common/Utils.h             |  8 +++++++-
+ 4 files changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/ext/common/ServerInstanceDir.h b/ext/common/ServerInstanceDir.h
+index 136437a..8da3cf3 100644
+--- a/ext/common/ServerInstanceDir.h
++++ b/ext/common/ServerInstanceDir.h
+@@ -213,7 +213,7 @@ class ServerInstanceDir: public noncopyable {
+ 		 * generations no matter what user they're running as.
+ 		 */
+ 		if (owner) {
+-			switch (getFileType(path)) {
++			switch (getFileTypeNoFollowSymlinks(path)) {
+ 			case FT_NONEXISTANT:
+ 				createDirectory(path);
+ 				break;
+diff --git a/ext/common/Utils.cpp b/ext/common/Utils.cpp
+index 1f3dec5..d1db8d6 100644
+--- a/ext/common/Utils.cpp
++++ b/ext/common/Utils.cpp
+@@ -143,6 +143,35 @@
+ 	}
+ }
+ 
++FileType
++getFileTypeNoFollowSymlinks(const StaticString &filename) {
++	struct stat buf;
++	int ret;
++	
++	ret = lstat(filename.c_str(), &buf);
++	if (ret == 0) {
++		if (S_ISREG(buf.st_mode)) {
++			return FT_REGULAR;
++		} else if (S_ISDIR(buf.st_mode)) {
++			return FT_DIRECTORY;
++		} else if (S_ISLNK(buf.st_mode)) {
++			return FT_SYMLINK;
++		} else {
++			return FT_OTHER;
++		}
++	} else {
++		if (errno == ENOENT) {
++			return FT_NONEXISTANT;
++		} else {
++			int e = errno;
++			string message("Cannot lstat '");
++			message.append(filename);
++			message.append("'");
++			throw FileSystemException(message, e, filename);
++		}
++	}
++}
++
+ void
+ createFile(const string &filename, const StaticString &contents, mode_t permissions, uid_t owner,
+ 	gid_t group, bool overwrite)
+diff --git a/ext/common/Utils.h b/ext/common/Utils.h
+index 41e6214..5cfaf92 100644
+--- a/ext/common/Utils.h
++++ b/ext/common/Utils.h
+@@ -65,6 +65,8 @@
+ 	FT_REGULAR,
+ 	/** A directory. */
+ 	FT_DIRECTORY,
++	/** A symlink. Only returned by getFileTypeNoFollowSymlinks(), not by getFileType(). */
++	FT_SYMLINK,
+ 	/** Something else, e.g. a pipe or a socket. */
+ 	FT_OTHER
+ } FileType;
+@@ -110,7 +112,7 @@ bool fileExists(const StaticString &filename, CachedFileStat *cstat = 0,
+ /**
+  * Check whether 'filename' exists and what kind of file it is.
+  *
+- * @param filename The filename to check.
++ * @param filename The filename to check. It MUST be NULL-terminated.
+  * @param mstat A CachedFileStat object, if you want to use cached statting.
+  * @param throttleRate A throttle rate for cstat. Only applicable if cstat is not NULL.
+  * @return The file type.
+@@ -121,6 +123,10 @@ bool fileExists(const StaticString &filename, CachedFileStat *cstat = 0,
+  */
+ FileType getFileType(const StaticString &filename, CachedFileStat *cstat = 0,
+                      unsigned int throttleRate = 0);
++/**
++ * Like getFileType(), but does not follow symlinks.
++ */
++FileType getFileTypeNoFollowSymlinks(const StaticString &filename);
+ 
+ /**
+  * Create the given file with the given contents, permissions and ownership.
+-- 
+1.8.5.5
diff -Nru ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1832.patch ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1832.patch
--- ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1832.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-passenger-3.0.13debian/debian/patches/CVE-2014-1832.patch	2014-03-08 19:47:38.000000000 +0100
@@ -0,0 +1,145 @@
+From 94428057c602da3d6d34ef75c78091066ecac5c0 Mon Sep 17 00:00:00 2001
+From: "Hongli Lai (Phusion)" <hongli@phusion.nl>
+Date: Wed, 29 Jan 2014 14:19:25 +0100
+Subject: [PATCH] Fix a symlink-related security vulnerability.
+
+The fix in commit 34b10878 and contained a small attack time window in
+between two filesystem operations. This has been fixed.
+---
+ ext/common/ServerInstanceDir.h | 38 ++++++++++++++++++++++----------------
+ ext/common/Utils.cpp           | 29 -----------------------------
+ ext/common/Utils.h             |  6 ------
+ 4 files changed, 40 insertions(+), 51 deletions(-)
+
+diff --git a/ext/common/ServerInstanceDir.h b/ext/common/ServerInstanceDir.h
+index 8da3cf3..1315de5 100644
+--- a/ext/common/ServerInstanceDir.h
++++ b/ext/common/ServerInstanceDir.h
+@@ -193,6 +193,9 @@ class ServerInstanceDir: public noncopyable {
+ 	
+ 	void initialize(const string &path, bool owner) {
+ 		TRACE_POINT();
++		struct stat buf;
++		int ret;
++
+ 		this->path  = path;
+ 		this->owner = owner;
+ 		
+@@ -212,18 +215,25 @@ class ServerInstanceDir: public noncopyable {
+ 		 * rights though, because we want admin tools to be able to list the available
+ 		 * generations no matter what user they're running as.
+ 		 */
++
++		do {
++			ret = lstat(path.c_str(), &buf);
++		} while (ret == -1 && errno == EAGAIN);
+ 		if (owner) {
+-			switch (getFileTypeNoFollowSymlinks(path)) {
+-			case FT_NONEXISTANT:
++			if (ret == 0) {
++				if (S_ISDIR(buf.st_mode)) {
++					verifyDirectoryPermissions(path, buf);
++				} else {
++					throw RuntimeException("'" + path + "' already exists, and is not a directory");
++				}
++			} else if (errno == ENOENT) {
+ 				createDirectory(path);
+-				break;
+-			case FT_DIRECTORY:
+-				verifyDirectoryPermissions(path);
+-				break;
+-			default:
+-				throw RuntimeException("'" + path + "' already exists, and is not a directory");
++			} else {
++				int e = errno;
++				throw FileSystemException("Cannot lstat '" + path + "'",
++					e, path);
+ 			}
+-		} else if (getFileType(path) != FT_DIRECTORY) {
++		} else if (!S_ISDIR(buf.st_mode)) {
+ 			throw RuntimeException("Server instance directory '" + path +
+ 				"' does not exist");
+ 		}
+@@ -259,14 +269,10 @@ class ServerInstanceDir: public noncopyable {
+ 	 * so that an attacker cannot pre-create a directory with too liberal
+ 	 * permissions.
+ 	 */
+-	void verifyDirectoryPermissions(const string &path) {
++	void verifyDirectoryPermissions(const string &path, struct stat &buf) {
+ 		TRACE_POINT();
+-		struct stat buf;
+ 
+-		if (stat(path.c_str(), &buf) == -1) {
+-			int e = errno;
+-			throw FileSystemException("Cannot stat() " + path, e, path);
+-		} else if (buf.st_mode != (S_IFDIR | parseModeString("u=rwx,g=rx,o=rx"))) {
++		if (buf.st_mode != (S_IFDIR | parseModeString("u=rwx,g=rx,o=rx"))) {
+ 			throw RuntimeException("Tried to reuse existing server instance directory " +
+ 				path + ", but it has wrong permissions");
+ 		} else if (buf.st_uid != geteuid() || buf.st_gid != getegid()) {
+diff --git a/ext/common/Utils.cpp b/ext/common/Utils.cpp
+index d1db8d6..1f3dec5 100644
+--- a/ext/common/Utils.cpp
++++ b/ext/common/Utils.cpp
+@@ -143,35 +143,6 @@
+ 	}
+ }
+ 
+-FileType
+-getFileTypeNoFollowSymlinks(const StaticString &filename) {
+-	struct stat buf;
+-	int ret;
+-	
+-	ret = lstat(filename.c_str(), &buf);
+-	if (ret == 0) {
+-		if (S_ISREG(buf.st_mode)) {
+-			return FT_REGULAR;
+-		} else if (S_ISDIR(buf.st_mode)) {
+-			return FT_DIRECTORY;
+-		} else if (S_ISLNK(buf.st_mode)) {
+-			return FT_SYMLINK;
+-		} else {
+-			return FT_OTHER;
+-		}
+-	} else {
+-		if (errno == ENOENT) {
+-			return FT_NONEXISTANT;
+-		} else {
+-			int e = errno;
+-			string message("Cannot lstat '");
+-			message.append(filename);
+-			message.append("'");
+-			throw FileSystemException(message, e, filename);
+-		}
+-	}
+-}
+-
+ void
+ createFile(const string &filename, const StaticString &contents, mode_t permissions, uid_t owner,
+ 	gid_t group, bool overwrite)
+diff --git a/ext/common/Utils.h b/ext/common/Utils.h
+index 5cfaf92..a04e507 100644
+--- a/ext/common/Utils.h
++++ b/ext/common/Utils.h
+@@ -65,8 +65,6 @@
+ 	FT_REGULAR,
+ 	/** A directory. */
+ 	FT_DIRECTORY,
+-	/** A symlink. Only returned by getFileTypeNoFollowSymlinks(), not by getFileType(). */
+-	FT_SYMLINK,
+ 	/** Something else, e.g. a pipe or a socket. */
+ 	FT_OTHER
+ } FileType;
+@@ -123,10 +121,6 @@ bool fileExists(const StaticString &filename, CachedFileStat *cstat = 0,
+  */
+ FileType getFileType(const StaticString &filename, CachedFileStat *cstat = 0,
+                      unsigned int throttleRate = 0);
+-/**
+- * Like getFileType(), but does not follow symlinks.
+- */
+-FileType getFileTypeNoFollowSymlinks(const StaticString &filename);
+ 
+ /**
+  * Create the given file with the given contents, permissions and ownership.
+-- 
+1.8.5.5
diff -Nru ruby-passenger-3.0.13debian/debian/patches/series ruby-passenger-3.0.13debian/debian/patches/series
--- ruby-passenger-3.0.13debian/debian/patches/series	2013-07-21 13:02:52.000000000 +0200
+++ ruby-passenger-3.0.13debian/debian/patches/series	2014-03-08 19:42:00.000000000 +0100
@@ -1,3 +1,5 @@
 fix_install_path.patch
 CVE-2013-2119.patch
 CVE-2013-4136.patch
+CVE-2014-1831.patch
+CVE-2014-1832.patch

Reply to: