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
|
Upstream-Status: Backport
The patch to fix CVE-2009-1214
A security flaw was found in the screen utility in the way it used to create
one particular temporary file. An attacker could use this flaw to perform
a symlink attack.
Fix race condition creating temporary file
Reference:
https://bugzilla.redhat.com/show_bug.cgi?id=492104
Signed-off-by: Chenyang Guo <chenyang.guo@windriver.com>
---
fileio.c | 48 ++++++++++++++++++++++++++++++++----------------
1 file changed, 32 insertions(+), 16 deletions(-)
--- a/fileio.c
+++ b/fileio.c
@@ -414,6 +414,14 @@ int dump;
}
public = !strcmp(fn, DEFAULT_BUFFERFILE);
# ifdef HAVE_LSTAT
+ /*
+ * Note: In the time between lstat() and open()/remove() below are
+ * called, the file can be created/removed/modified. Therefore the
+ * information lstat() returns is taken into consideration, but not
+ * relied upon. In particular, the open()/remove() calls can fail, and
+ * the code must account for that. Symlink attack could be mounted if
+ * the code is changed carelessly. --rdancer 2009-01-11
+ */
exists = !lstat(fn, &stb);
if (public && exists && (S_ISLNK(stb.st_mode) || stb.st_nlink > 1))
{
@@ -432,28 +440,36 @@ int dump;
#ifdef COPY_PASTE
if (dump == DUMP_EXCHANGE && public)
{
+ /*
+ * Setting umask to zero is a bad idea -- the user surely doesn't
+ * expect a publicly readable file in a publicly readable directory
+ * --rdancer 2009-01-11
+ */
+ /*
old_umask = umask(0);
+ */
# ifdef HAVE_LSTAT
if (exists)
- {
- if ((fd = open(fn, O_WRONLY, 0666)) >= 0)
- {
- if (fstat(fd, &stb2) == 0 && stb.st_dev == stb2.st_dev && stb.st_ino == stb2.st_ino)
- ftruncate(fd, 0);
- else
- {
- close(fd);
- fd = -1;
- }
- }
- }
- else
- fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0666);
- f = fd >= 0 ? fdopen(fd, mode) : 0;
+ if (remove(fn) == -1)
+ {
+ /* Error */
+ debug2("WriteFile: File exists and remove(%s) failed: %s\n",
+ fn, strerror(errno));
+ UserReturn(0);
+ }
# else
- f = fopen(fn, mode);
+ (void) remove(fn);
# endif
+ /*
+ * No r/w permissions for anybody but the user, as the file may be in
+ * a public directory -- if the user chooses, they can chmod the file
+ * afterwards. --rdancer 2008-01-11
+ */
+ fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0600);
+ f = fd >= 0 ? fdopen(fd, mode) : 0;
+ /*
umask(old_umask);
+ */
}
else
#endif /* COPY_PASTE */
|