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