summaryrefslogtreecommitdiff
path: root/print/cups/patches/patch-bd
blob: a245fc627308627e24106ca703ce2d9eb466cb6c (plain)
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
132
133
134
135
136
137
138
139
140
$NetBSD: patch-bd,v 1.4 2010/06/16 21:15:18 sbd Exp $

Incorporate str3510.patch from
http://www.cups.org/str.php?L3510
"cups overwrites files as root in a directory with non-root write permission"

--- cups/file.c.orig	2009-05-14 21:18:35.000000000 +0000
+++ cups/file.c
@@ -59,6 +59,7 @@
  */
 
 #include "file-private.h"
+#include <sys/stat.h>
 
 
 /*
@@ -69,6 +70,7 @@
 static ssize_t	cups_compress(cups_file_t *fp, const char *buf, size_t bytes);
 #endif /* HAVE_LIBZ */
 static ssize_t	cups_fill(cups_file_t *fp);
+static int cups_open(const char *filename, int mode);
 static ssize_t	cups_read(cups_file_t *fp, char *buf, size_t bytes);
 static ssize_t	cups_write(cups_file_t *fp, const char *buf, size_t bytes);
 
@@ -827,7 +829,8 @@ cupsFileOpen(const char *filename,	/* I 
   switch (*mode)
   {
     case 'a' : /* Append file */
-        fd = open(filename, O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY, 0666);
+        fd = cups_open(filename,
+	O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY);
         break;
 
     case 'r' : /* Read file */
@@ -835,7 +838,17 @@ cupsFileOpen(const char *filename,	/* I 
 	break;
 
     case 'w' : /* Write file */
-        fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_LARGEFILE | O_BINARY, 0666);
+        fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY);
+ if (fd < 0 && errno == ENOENT)
+ {
+   fd = cups_open(filename,
+		  O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY);
+   if (fd < 0 && errno == EEXIST)
+     fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY);
+ }
+
+ if (fd >= 0)
+   ftruncate(fd, 0);
         break;
 
     case 's' : /* Read/write socket */
@@ -2207,6 +2220,86 @@ cups_fill(cups_file_t *fp)		/* I - CUPS 
   return (bytes);
 }
 
+/*
+ * 'cups_open()' - Safely open a file for writing.
+ *
+ * We don't allow appending to directories or files that are hard-linked or
+ * symlinked.
+ */
+
+static int /* O - File descriptor or -1 otherwise */
+cups_open(const char *filename, /* I - Filename */
+   int        mode) /* I - Open mode */
+{
+  int fd; /* File descriptor */
+  struct stat fileinfo; /* File information */
+#ifndef WIN32
+  struct stat linkinfo; /* Link information */
+#endif /* !WIN32 */
+
+
+ /*
+  * Open the file...
+  */
+
+  if ((fd = open(filename, mode, 0666)) < 0)
+    return (-1);
+
+ /*
+  * Then verify that the file descriptor doesn't point to a directory or hard-
+  * linked file.
+  */
+
+  if (fstat(fd, &fileinfo))
+  {
+    close(fd);
+    return (-1);
+  }
+
+  if (fileinfo.st_nlink != 1)
+  {
+    close(fd);
+    errno = EPERM;
+    return (-1);
+  }
+
+  if (S_ISDIR(fileinfo.st_mode))
+  {
+    close(fd);
+    errno = EISDIR;
+    return (-1);
+  }
+
+#ifndef WIN32
+ /*
+  * Then use lstat to determine whether the filename is a symlink...
+  */
+
+  if (lstat(filename, &linkinfo))
+  {
+    close(fd);
+    return (-1);
+  }
+
+  if (S_ISLNK(linkinfo.st_mode) ||
+      fileinfo.st_dev != linkinfo.st_dev ||
+      fileinfo.st_ino != linkinfo.st_ino ||
+      fileinfo.st_gen != linkinfo.st_gen ||
+      fileinfo.st_nlink != linkinfo.st_nlink ||
+      fileinfo.st_mode != linkinfo.st_mode)
+  {
+   /*
+    * Yes, don't allow!
+    */
+
+    close(fd);
+    errno = EPERM;
+    return (-1);
+  }
+#endif /* !WIN32 */
+
+  return (fd);
+}
 
 /*
  * 'cups_read()' - Read from a file descriptor.