083c7858d4e3e0fee38f719742c887e116ff004b
[people/pmueller/ipfire-2.x.git] / src / patches / cpio-2.6-security_fixes-1.patch
1 Submitted By: Ken Moffat <ken@kenmoffat.uklinux.net>
2 Date: 2005-07-29
3 Initial Package Version: 2.6
4 Upstream Status: Unknown
5 Origin: from Mandrake
6 Description: Vulnerability fixes, rediffed so that they all apply with
7 -p1 and consolidated to single patch. Also applicable to earlier versions.
8 (1.) CAN-1999-1572 (still seems to apply to 2.6) cpio uses a 0 umask when
9 creating files with -O or -F options, which creates the files with mode 0666
10 and allows local users to overwrite them. Fix originally fom debian.
11 (2.) CAN-2005-1111 Race condition in 2.6 and earlier allows local users to
12 modify permissions of arbitrary files via a hard-link attack. Fix
13 originally from fedora.
14 (3.) CAN-2005-1229 Directory traversal vulnerability allows remote
15 attackers to write to arbitrary directories via a dot dot in a cpio file.
16 Fix by Peter Vrabec at RedHat.
17
18 diff -Naur cpio-2.6.vanilla/doc/cpio.1 cpio-2.6/doc/cpio.1
19 --- cpio-2.6.vanilla/doc/cpio.1 2004-08-30 17:21:48.000000000 +0100
20 +++ cpio-2.6/doc/cpio.1 2005-07-29 13:46:42.000000000 +0100
21 @@ -20,7 +20,7 @@
22 [\-\-unconditional] [\-\-verbose] [\-\-block-size=blocks] [\-\-swap-halfwords]
23 [\-\-io-size=bytes] [\-\-pattern-file=file] [\-\-format=format]
24 [\-\-owner=[user][:.][group]] [\-\-no-preserve-owner] [\-\-message=message]
25 -[\-\-force\-local] [\-\-no\-absolute\-filenames] [\-\-sparse]
26 +[\-\-force\-local] [\-\-absolute\-filenames] [\-\-sparse]
27 [\-\-only\-verify\-crc] [\-\-quiet] [\-\-rsh-command=command] [\-\-help]
28 [\-\-version] [pattern...] [< archive]
29
30 diff -Naur cpio-2.6.vanilla/doc/cpio.info cpio-2.6/doc/cpio.info
31 --- cpio-2.6.vanilla/doc/cpio.info 2004-02-27 12:42:01.000000000 +0000
32 +++ cpio-2.6/doc/cpio.info 2005-07-29 13:46:42.000000000 +0100
33 @@ -203,7 +203,7 @@
34 [--swap-halfwords] [--io-size=bytes] [--pattern-file=file]
35 [--format=format] [--owner=[user][:.][group]]
36 [--no-preserve-owner] [--message=message] [--help] [--version]
37 - [-no-absolute-filenames] [--sparse] [-only-verify-crc] [-quiet]
38 + [--absolute-filenames] [--sparse] [-only-verify-crc] [-quiet]
39 [--rsh-command=command] [pattern...] [< archive]
40
41 \1f
42 @@ -358,9 +358,9 @@
43 Show numeric UID and GID instead of translating them into names
44 when using the `--verbose option'.
45
46 -`--no-absolute-filenames'
47 - Create all files relative to the current directory in copy-in
48 - mode, even if they have an absolute file name in the archive.
49 +`--absolute-filenames'
50 + Do not strip leading file name components that contain ".."
51 + and leading slashes from file names in copy-in mode
52
53 `--no-preserve-owner'
54 Do not change the ownership of the files; leave them owned by the
55 diff -Naur cpio-2.6.vanilla/src/copyin.c cpio-2.6/src/copyin.c
56 --- cpio-2.6.vanilla/src/copyin.c 2004-09-08 12:10:02.000000000 +0100
57 +++ cpio-2.6/src/copyin.c 2005-07-29 13:46:42.000000000 +0100
58 @@ -25,6 +25,7 @@
59 #include "dstring.h"
60 #include "extern.h"
61 #include "defer.h"
62 +#include "dirname.h"
63 #include <rmt.h>
64 #ifndef FNM_PATHNAME
65 #include <fnmatch.h>
66 @@ -389,19 +390,26 @@
67 continue;
68 }
69
70 - if (close (out_file_des) < 0)
71 - error (0, errno, "%s", d->header.c_name);
72 -
73 + /*
74 + * Avoid race condition.
75 + * Set chown and chmod before closing the file desc.
76 + * pvrabec@redhat.com
77 + */
78 +
79 /* File is now copied; set attributes. */
80 if (!no_chown_flag)
81 - if ((chown (d->header.c_name,
82 + if ((fchown (out_file_des,
83 set_owner_flag ? set_owner : d->header.c_uid,
84 set_group_flag ? set_group : d->header.c_gid) < 0)
85 && errno != EPERM)
86 error (0, errno, "%s", d->header.c_name);
87 /* chown may have turned off some permissions we wanted. */
88 - if (chmod (d->header.c_name, (int) d->header.c_mode) < 0)
89 + if (fchmod (out_file_des, (int) d->header.c_mode) < 0)
90 error (0, errno, "%s", d->header.c_name);
91 +
92 + if (close (out_file_des) < 0)
93 + error (0, errno, "%s", d->header.c_name);
94 +
95 if (retain_time_flag)
96 {
97 times.actime = times.modtime = d->header.c_mtime;
98 @@ -557,6 +565,25 @@
99 write (out_file_des, "", 1);
100 delayed_seek_count = 0;
101 }
102 +
103 + /*
104 + * Avoid race condition.
105 + * Set chown and chmod before closing the file desc.
106 + * pvrabec@redhat.com
107 + */
108 +
109 + /* File is now copied; set attributes. */
110 + if (!no_chown_flag)
111 + if ((fchown (out_file_des,
112 + set_owner_flag ? set_owner : file_hdr->c_uid,
113 + set_group_flag ? set_group : file_hdr->c_gid) < 0)
114 + && errno != EPERM)
115 + error (0, errno, "%s", file_hdr->c_name);
116 +
117 + /* chown may have turned off some permissions we wanted. */
118 + if (fchmod (out_file_des, (int) file_hdr->c_mode) < 0)
119 + error (0, errno, "%s", file_hdr->c_name);
120 +
121 if (close (out_file_des) < 0)
122 error (0, errno, "%s", file_hdr->c_name);
123
124 @@ -567,18 +594,6 @@
125 file_hdr->c_name, crc, file_hdr->c_chksum);
126 }
127
128 - /* File is now copied; set attributes. */
129 - if (!no_chown_flag)
130 - if ((chown (file_hdr->c_name,
131 - set_owner_flag ? set_owner : file_hdr->c_uid,
132 - set_group_flag ? set_group : file_hdr->c_gid) < 0)
133 - && errno != EPERM)
134 - error (0, errno, "%s", file_hdr->c_name);
135 -
136 - /* chown may have turned off some permissions we wanted. */
137 - if (chmod (file_hdr->c_name, (int) file_hdr->c_mode) < 0)
138 - error (0, errno, "%s", file_hdr->c_name);
139 -
140 if (retain_time_flag)
141 {
142 struct utimbuf times; /* For setting file times. */
143 @@ -589,7 +604,7 @@
144 if (utime (file_hdr->c_name, &times) < 0)
145 error (0, errno, "%s", file_hdr->c_name);
146 }
147 -
148 +
149 tape_skip_padding (in_file_des, file_hdr->c_filesize);
150 if (file_hdr->c_nlink > 1
151 && (archive_format == arf_newascii || archive_format == arf_crcascii) )
152 @@ -1335,6 +1350,53 @@
153 }
154 }
155
156 +/* Return a safer suffix of FILE_NAME, or "." if it has no safer
157 + suffix. Check for fully specified file names and other atrocities. */
158 +
159 +static const char *
160 +safer_name_suffix (char const *file_name)
161 +{
162 + char const *p;
163 +
164 + /* Skip file system prefixes, leading file name components that contain
165 + "..", and leading slashes. */
166 +
167 + size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);
168 +
169 + for (p = file_name + prefix_len; *p;)
170 + {
171 + if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
172 + prefix_len = p + 2 - file_name;
173 +
174 + do
175 + {
176 + char c = *p++;
177 + if (ISSLASH (c))
178 + break;
179 + }
180 + while (*p);
181 + }
182 +
183 + for (p = file_name + prefix_len; ISSLASH (*p); p++)
184 + continue;
185 + prefix_len = p - file_name;
186 +
187 + if (prefix_len)
188 + {
189 + char *prefix = alloca (prefix_len + 1);
190 + memcpy (prefix, file_name, prefix_len);
191 + prefix[prefix_len] = '\0';
192 +
193 +
194 + error (0, 0, _("Removing leading `%s' from member names"), prefix);
195 + }
196 +
197 + if (!*p)
198 + p = ".";
199 +
200 + return p;
201 +}
202 +
203 /* Read the collection from standard input and create files
204 in the file system. */
205
206 @@ -1445,18 +1507,11 @@
207
208 /* Do we have to ignore absolute paths, and if so, does the filename
209 have an absolute path? */
210 - if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
211 + if (!abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0])
212 {
213 - char *p;
214 + const char *p = safer_name_suffix (file_hdr.c_name);
215
216 - p = file_hdr.c_name;
217 - while (*p == '/')
218 - ++p;
219 - if (*p == '\0')
220 - {
221 - strcpy (file_hdr.c_name, ".");
222 - }
223 - else
224 + if (p != file_hdr.c_name)
225 {
226 /* Debian hack: file_hrd.c_name is sometimes set to
227 point to static memory by code in tar.c. This
228 diff -Naur cpio-2.6.vanilla/src/copypass.c cpio-2.6/src/copypass.c
229 --- cpio-2.6.vanilla/src/copypass.c 2004-09-06 13:09:04.000000000 +0100
230 +++ cpio-2.6/src/copypass.c 2005-07-29 13:46:07.000000000 +0100
231 @@ -181,19 +181,25 @@
232 }
233 if (close (in_file_des) < 0)
234 error (0, errno, "%s", input_name.ds_string);
235 - if (close (out_file_des) < 0)
236 - error (0, errno, "%s", output_name.ds_string);
237 -
238 + /*
239 + * Avoid race condition.
240 + * Set chown and chmod before closing the file desc.
241 + * pvrabec@redhat.com
242 + */
243 /* Set the attributes of the new file. */
244 if (!no_chown_flag)
245 - if ((chown (output_name.ds_string,
246 + if ((fchown (out_file_des,
247 set_owner_flag ? set_owner : in_file_stat.st_uid,
248 set_group_flag ? set_group : in_file_stat.st_gid) < 0)
249 && errno != EPERM)
250 error (0, errno, "%s", output_name.ds_string);
251 /* chown may have turned off some permissions we wanted. */
252 - if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
253 + if (fchmod (out_file_des, in_file_stat.st_mode) < 0)
254 + error (0, errno, "%s", output_name.ds_string);
255 +
256 + if (close (out_file_des) < 0)
257 error (0, errno, "%s", output_name.ds_string);
258 +
259 if (reset_time_flag)
260 {
261 times.actime = in_file_stat.st_atime;
262 diff -Naur cpio-2.6.vanilla/src/extern.h cpio-2.6/src/extern.h
263 --- cpio-2.6.vanilla/src/extern.h 2004-09-08 11:49:57.000000000 +0100
264 +++ cpio-2.6/src/extern.h 2005-07-29 13:47:34.000000000 +0100
265 @@ -46,7 +46,7 @@
266 extern int sparse_flag;
267 extern int quiet_flag;
268 extern int only_verify_crc_flag;
269 -extern int no_abs_paths_flag;
270 +extern int abs_paths_flag;
271 extern unsigned int warn_option;
272
273 /* Values for warn_option */
274 @@ -91,6 +91,7 @@
275 extern char input_is_seekable;
276 extern char output_is_seekable;
277 extern char *program_name;
278 +extern mode_t sys_umask;
279 extern int (*xstat) ();
280 extern void (*copy_function) ();
281 \f
282 diff -Naur cpio-2.6.vanilla/src/global.c cpio-2.6/src/global.c
283 --- cpio-2.6.vanilla/src/global.c 2004-09-08 11:23:44.000000000 +0100
284 +++ cpio-2.6/src/global.c 2005-07-29 13:47:34.000000000 +0100
285 @@ -100,7 +100,7 @@
286 int only_verify_crc_flag = false;
287
288 /* If true, don't use any absolute paths, prefix them by `./'. */
289 -int no_abs_paths_flag = false;
290 +int abs_paths_flag = false;
291
292 #ifdef DEBUG_CPIO
293 /* If true, print debugging information. */
294 @@ -195,6 +195,9 @@
295 /* The name this program was run with. */
296 char *program_name;
297
298 +/* Debian hack to make the -d option honor the umask. */
299 +mode_t sys_umask;
300 +
301 /* A pointer to either lstat or stat, depending on whether
302 dereferencing of symlinks is done for input files. */
303 int (*xstat) ();
304 diff -Naur cpio-2.6.vanilla/src/main.c cpio-2.6/src/main.c
305 --- cpio-2.6.vanilla/src/main.c 2004-11-23 00:42:18.000000000 +0000
306 +++ cpio-2.6/src/main.c 2005-07-29 13:47:34.000000000 +0100
307 @@ -41,6 +41,7 @@
308
309 enum cpio_options {
310 NO_ABSOLUTE_FILENAMES_OPTION=256,
311 + ABSOLUTE_FILENAMES_OPTION,
312 NO_PRESERVE_OWNER_OPTION,
313 ONLY_VERIFY_CRC_OPTION,
314 RENAME_BATCH_FILE_OPTION,
315 @@ -134,6 +135,8 @@
316 N_("In copy-in mode, read additional patterns specifying filenames to extract or list from FILE"), 210},
317 {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
318 N_("Create all files relative to the current directory"), 210},
319 + {"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
320 + N_("do not strip leading file name components that contain \"..\" and leading slashes from file names"), 210},
321 {"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
322 N_("When reading a CRC format archive in copy-in mode, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
323 {"rename", 'r', 0, 0,
324 @@ -392,7 +395,11 @@
325 break;
326
327 case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
328 - no_abs_paths_flag = true;
329 + abs_paths_flag = false;
330 + break;
331 +
332 + case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
333 + abs_paths_flag = true;
334 break;
335
336 case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
337 @@ -631,7 +638,7 @@
338 _("--append is used but no archive file name is given (use -F or -O options")));
339
340 CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
341 - CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames", "--create");
342 + CHECK_USAGE(abs_paths_flag, "--absolute-pathnames", "--create");
343 CHECK_USAGE(input_archive_name, "-I", "--create");
344 if (archive_name && output_archive_name)
345 USAGE_ERROR ((0, 0, _("Both -O and -F are used in copy-out mode")));
346 @@ -658,7 +665,7 @@
347 CHECK_USAGE(rename_flag, "--rename", "--pass-through");
348 CHECK_USAGE(append_flag, "--append", "--pass-through");
349 CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
350 - CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames",
351 + CHECK_USAGE(abs_paths_flag, "--absolute-pathnames",
352 "--pass-through");
353 CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
354
355 @@ -740,7 +747,6 @@
356 textdomain (PACKAGE);
357
358 program_name = argv[0];
359 - umask (0);
360
361 #ifdef __TURBOC__
362 _fmode = O_BINARY; /* Put stdin and stdout in binary mode. */
363 @@ -751,6 +757,7 @@
364 #endif
365
366 process_args (argc, argv);
367 + sys_umask = umask (0);
368
369 initialize_buffers ();
370