patches/Python-06-write_compiled_module-atomic.diff
author rohinis
Tue, 29 Nov 2011 17:32:55 +0000
branchs11express-2010-11
changeset 22234 c23e64da3e06
parent 8258 73b7ea5cfb91
permissions -rw-r--r--
2011-11-29 Rohini S <[email protected]> * patches/Python26-22-audio.diff: Fixes CVE-2010-1634 * specs/SUNWPython26.spec: Fixes CR 7085446

--- Python-2.4.3/Python/import.c.patch6	2006-09-15 14:58:49.716280000 -0400
+++ Python-2.4.3/Python/import.c	2006-09-15 15:47:04.381256000 -0400
@@ -816,19 +816,28 @@
 
 /* Write a compiled module to a file, placing the time of last
    modification of its source into the header.
-   Errors are ignored, if a write error occurs an attempt is made to
-   remove the file. */
+   Write to a temporary file first so that creating the file is atomic.
+   Errors are ignored, if a write/unlink/rename error occurs an attempt
+   is made to remove the temporary file. */
 
 static void
 write_compiled_module(PyCodeObject *co, char *cpathname, long mtime)
 {
 	FILE *fp;
+	char *tmppathname;
 
-	fp = open_exclusive(cpathname);
+	/* the temporary file is called cpathname + ".tmp" */
+        if ((tmppathname = PyMem_Malloc(strlen(cpathname) + strlen(".tmp") + 1))
+     		== NULL) {
+		return;
+	}
+	sprintf (tmppathname, "%s.tmp", cpathname);
+	fp = open_exclusive(tmppathname);
 	if (fp == NULL) {
 		if (Py_VerboseFlag)
 			PySys_WriteStderr(
-				"# can't create %s\n", cpathname);
+				"# can't create %s\n", tmppathname);
+		PyMem_Free(tmppathname);
 		return;
 	}
 	PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION);
@@ -837,10 +846,11 @@
 	PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
 	if (fflush(fp) != 0 || ferror(fp)) {
 		if (Py_VerboseFlag)
-			PySys_WriteStderr("# can't write %s\n", cpathname);
+			PySys_WriteStderr("# can't write %s\n", tmppathname);
 		/* Don't keep partial file */
 		fclose(fp);
-		(void) unlink(cpathname);
+		(void) unlink(tmppathname);
+		PyMem_Free(tmppathname);
 		return;
 	}
 	/* Now write the true mtime */
@@ -848,8 +858,30 @@
 	PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
 	fflush(fp);
 	fclose(fp);
+	/* Delete the old compiled file, if exists */
+	if (unlink (cpathname)) {
+		if ((errno != ENOENT)) {
+			/* the file exists but could not be deleted */
+			if (Py_VerboseFlag)
+				PySys_WriteStderr(
+					"# can't unlink %s\n", cpathname);
+			(void) unlink(tmppathname);
+			PyMem_Free(tmppathname);
+			return;
+		}
+	}
+	/* rename the tmp file to the real file name */
+	if (rename (tmppathname, cpathname)) {
+		if (Py_VerboseFlag)
+			PySys_WriteStderr(
+				"# can't rename %s to %s\n", tmppathname, cpathname);
+		(void) unlink(tmppathname);
+		PyMem_Free(tmppathname);
+		return;
+	}
 	if (Py_VerboseFlag)
 		PySys_WriteStderr("# wrote %s\n", cpathname);
+	PyMem_Free(tmppathname);
 }