]>
Commit | Line | Data |
---|---|---|
ad9d4caf MT |
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, ×) < 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 |