File: php5-pear-CVE-2011-1144.patch

package info (click to toggle)
php5 5.3.3-7%2Bsqueeze19
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 122,836 kB
  • ctags: 55,742
  • sloc: ansic: 633,963; php: 19,620; sh: 11,344; xml: 5,816; cpp: 2,400; yacc: 1,745; exp: 1,514; makefile: 1,019; pascal: 623; awk: 537; sql: 22
file content (131 lines) | stat: -rw-r--r-- 5,105 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
Subject: Introduce a time-of-check-time-of-use (TOCTOU) save file
  handler, this makes sure that from the time we check it is available
  until we get the file handler that no one attempted to put in a
  soft / hard link instead of what we checked for.
Origin: http://svn.php.net/viewvc?view=revision&revision=309042

CVE-2011-1144

Index: PEAR/REST.php
===================================================================
--- PEAR/REST.php	(revision 309041)
+++ PEAR/REST.php	(revision 309042)
@@ -228,59 +228,75 @@
         $cacheidfile = $d . 'rest.cacheid';
         $cachefile   = $d . 'rest.cachefile';
 
+        if (!is_dir($cache_dir)) {
+            if (System::mkdir(array('-p', $cache_dir) === false)) {
+              return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
+            }
+        }
+
         if ($cacheid === null && $nochange) {
             $cacheid = unserialize(implode('', file($cacheidfile)));
         }
 
-        if (is_link($cacheidfile)) {
-            return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $cacheidfile . ' as it is symlinked to ' . readlink($cacheidfile) . ' - Possible symlink attack');
-        }
+        $idData = serialize(array(
+            'age'        => time(),
+            'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
+        ));
 
-        if (is_link($cachefile)) {
-            return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $cacheidfile . ' as it is symlinked to ' . readlink($cacheidfile) . ' - Possible symlink attack');
+        $result = $this->saveCacheFile($cacheidfile, $idData);
+        if (PEAR::isError($result)) {
+            return $result;
+        } elseif ($nochange) {
+            return true;
         }
 
-        $cacheidfile_fp = @fopen($cacheidfile, 'wb');
-        if (!$cacheidfile_fp) {
-            if (is_dir($cache_dir)) {
-                return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory. ");
+        $result = $this->saveCacheFile($cachefile, serialize($contents));
+        if (PEAR::isError($result)) {
+            if (file_exists($cacheidfile)) {
+              @unlink($cacheidfile);
             }
 
-            System::mkdir(array('-p', $cache_dir));
-            $cacheidfile_fp = @fopen($cacheidfile, 'wb');
-            if (!$cacheidfile_fp) {
-                return PEAR::raiseError("Could not open $cacheidfile for writing.");
-            }
+            return $result;
         }
 
-        if ($nochange) {
-            fwrite($cacheidfile_fp, serialize(array(
-                'age'        => time(),
-                'lastChange' => $cacheid['lastChange'],
-                ))
-            );
+        return true;
+    }
 
-            fclose($cacheidfile_fp);
-            return true;
-        }
+    function saveCacheFile($file, $contents)
+    {
+        $len = strlen($contents);
 
-        fwrite($cacheidfile_fp, serialize(array(
-            'age'        => time(),
-            'lastChange' => $lastmodified,
-            ))
-        );
-        fclose($cacheidfile_fp);
+        $cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
+        if ($cachefile_fp !== false) { // create file
+            if (fwrite($cachefile_fp, $contents, $len) < $len) {
+                fclose($cachefile_fp);
+                return PEAR::raiseError("Could not write $file.");
+            }
+        } else { // update file
+            $cachefile_lstat = lstat($file);
+            $cachefile_fp = @fopen($file, 'wb');
+            if (!$cachefile_fp) {
+                return PEAR::raiseError("Could not open $file for writing.");
+            }
 
-        $cachefile_fp = @fopen($cachefile, 'wb');
-        if (!$cachefile_fp) {
-            if (file_exists($cacheidfile)) {
-                @unlink($cacheidfile);
+            $cachefile_fstat = fstat($cachefile_fp);
+            if (
+              $cachefile_lstat['mode'] == $cachefile_fstat['mode'] &&
+              $cachefile_lstat['ino']  == $cachefile_fstat['ino'] &&
+              $cachefile_lstat['dev']  == $cachefile_fstat['dev'] &&
+              $cachefile_fstat['nlink'] === 1
+            ) {
+                if (fwrite($cachefile_fp, $contents, $len) < $len) {
+                    fclose($cachefile_fp);
+                    return PEAR::raiseError("Could not write $file.");
+                }
+            } else {
+                fclose($cachefile_fp);
+                $link = function_exists('readlink') ? readlink($file) : $file;
+                return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
             }
-
-            return PEAR::raiseError("Could not open $cacheidfile for writing.");
         }
 
-        fwrite($cachefile_fp, serialize($contents));
         fclose($cachefile_fp);
         return true;
     }
@@ -464,4 +480,4 @@
 
         return $data;
     }
-}
\ No newline at end of file
+}