Annotation of /trunk/cpio/patches/cpio-2.6-security_fixes-1.patch
Parent Directory | Revision Log
Revision 144 -
(hide annotations)
(download)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 12970 byte(s)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 12970 byte(s)
-import
1 | niro | 144 | 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 | |||
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 | |||
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 |