fix large file support, archive >4GiB, archive members <4GiB (#160056) fix

race condition holes, use mode 0700 for dir creation
This commit is contained in:
Peter Vrabec 2005-07-01 14:37:24 +00:00
parent 64a788323f
commit 501abeb43f
3 changed files with 211 additions and 53 deletions

View File

@ -1,18 +1,34 @@
--- cpio-2.6/src/copyin.c.chmodRaceC 2005-04-25 13:19:34.079310381 +0200
+++ cpio-2.6/src/copyin.c 2005-04-25 14:09:32.514889697 +0200
@@ -389,19 +389,26 @@
--- cpio-2.6/src/copyin.c.chmodRaceC 2005-07-01 14:23:04.000000000 +0200
+++ cpio-2.6/src/copyin.c 2005-07-01 14:46:34.000000000 +0200
@@ -184,11 +184,12 @@
static int
try_existing_file(struct new_cpio_header* file_hdr, int in_file_des,
- int *existing_dir)
+ int *existing_dir, mode_t *existing_mode)
{
struct stat file_stat;
*existing_dir = false;
+ *existing_mode = 0;
if (lstat (file_hdr->c_name, &file_stat) == 0)
{
if (S_ISDIR (file_stat.st_mode)
@@ -198,6 +199,7 @@
we are trying to create, don't complain about
it. */
*existing_dir = true;
+ *existing_mode = file_stat.st_mode;
return 0;
}
else if (!unconditional_flag
@@ -389,19 +391,20 @@
continue;
}
- if (close (out_file_des) < 0)
- error (0, errno, "%s", d->header.c_name);
-
+ /*
+ * Avoid race condition.
+ * Set chown and chmod before closing the file desc.
+ * pvrabec@redhat.com
+ */
+
/* File is now copied; set attributes. */
if (!no_chown_flag)
- if ((chown (d->header.c_name,
@ -24,25 +40,19 @@
/* chown may have turned off some permissions we wanted. */
- if (chmod (d->header.c_name, (int) d->header.c_mode) < 0)
+ if (fchmod (out_file_des, (int) d->header.c_mode) < 0)
+ error (0, errno, "%s", d->header.c_name);
error (0, errno, "%s", d->header.c_name);
+
+ if (close (out_file_des) < 0)
error (0, errno, "%s", d->header.c_name);
+ error (0, errno, "%s", d->header.c_name);
+
if (retain_time_flag)
{
times.actime = times.modtime = d->header.c_mtime;
@@ -557,6 +564,25 @@
@@ -557,6 +560,19 @@
write (out_file_des, "", 1);
delayed_seek_count = 0;
}
+
+ /*
+ * Avoid race condition.
+ * Set chown and chmod before closing the file desc.
+ * pvrabec@redhat.com
+ */
+
+ /* File is now copied; set attributes. */
+ if (!no_chown_flag)
+ if ((fchown (out_file_des,
@ -58,7 +68,7 @@
if (close (out_file_des) < 0)
error (0, errno, "%s", file_hdr->c_name);
@@ -567,18 +593,6 @@
@@ -567,18 +583,6 @@
file_hdr->c_name, crc, file_hdr->c_chksum);
}
@ -77,7 +87,7 @@
if (retain_time_flag)
{
struct utimbuf times; /* For setting file times. */
@@ -589,7 +603,7 @@
@@ -589,7 +593,7 @@
if (utime (file_hdr->c_name, &times) < 0)
error (0, errno, "%s", file_hdr->c_name);
}
@ -86,8 +96,81 @@
tape_skip_padding (in_file_des, file_hdr->c_filesize);
if (file_hdr->c_nlink > 1
&& (archive_format == arf_newascii || archive_format == arf_crcascii) )
@@ -603,7 +607,7 @@
}
static void
-copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
+copyin_directory(struct new_cpio_header* file_hdr, int existing_dir, mode_t existing_mode)
{
int res; /* Result of various function calls. */
#ifdef HPUX_CDF
@@ -646,14 +650,23 @@
cdf_flag = 1;
}
#endif
- res = mkdir (file_hdr->c_name, file_hdr->c_mode);
+ res = mkdir (file_hdr->c_name, file_hdr->c_mode & ~077);
}
- else
- res = 0;
+ else
+ {
+ if (!no_chown_flag && (existing_mode & 077) != 0
+ && chmod (file_hdr->c_name, existing_mode & 07700) < 0)
+ {
+ error (0, errno, "%s: chmod", file_hdr->c_name);
+ return;
+ }
+ res = 0;
+ }
+
if (res < 0 && create_dir_flag)
{
create_all_directories (file_hdr->c_name);
- res = mkdir (file_hdr->c_name, file_hdr->c_mode);
+ res = mkdir (file_hdr->c_name, file_hdr->c_mode & ~077);
}
if (res < 0)
{
@@ -742,12 +755,12 @@
return;
}
- res = mknod (file_hdr->c_name, file_hdr->c_mode,
+ res = mknod (file_hdr->c_name, file_hdr->c_mode & ~077,
makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min));
if (res < 0 && create_dir_flag)
{
create_all_directories (file_hdr->c_name);
- res = mknod (file_hdr->c_name, file_hdr->c_mode,
+ res = mknod (file_hdr->c_name, file_hdr->c_mode & ~077,
makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min));
}
if (res < 0)
@@ -826,9 +839,10 @@
copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
{
int existing_dir;
+ mode_t existing_mode;
if (!to_stdout_option
- && try_existing_file (file_hdr, in_file_des, &existing_dir) < 0)
+ && try_existing_file (file_hdr, in_file_des, &existing_dir, &existing_mode) < 0)
return;
/* Do the real copy or link. */
@@ -839,7 +853,7 @@
break;
case CP_IFDIR:
- copyin_directory(file_hdr, existing_dir);
+ copyin_directory(file_hdr, existing_dir, existing_mode);
break;
case CP_IFCHR:
--- cpio-2.6/src/copypass.c.chmodRaceC 2004-09-06 14:09:04.000000000 +0200
+++ cpio-2.6/src/copypass.c 2005-04-25 14:09:38.135076926 +0200
+++ cpio-2.6/src/copypass.c 2005-07-01 14:50:46.000000000 +0200
@@ -181,19 +181,25 @@
}
if (close (in_file_des) < 0)
@ -111,11 +194,54 @@
/* chown may have turned off some permissions we wanted. */
- if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
+ if (fchmod (out_file_des, in_file_stat.st_mode) < 0)
+ error (0, errno, "%s", output_name.ds_string);
error (0, errno, "%s", output_name.ds_string);
+
+ if (close (out_file_des) < 0)
error (0, errno, "%s", output_name.ds_string);
+ error (0, errno, "%s", output_name.ds_string);
+
if (reset_time_flag)
{
times.actime = in_file_stat.st_atime;
@@ -240,15 +246,24 @@
cdf_flag = 1;
}
#endif
- res = mkdir (output_name.ds_string, in_file_stat.st_mode);
+ res = mkdir (output_name.ds_string, in_file_stat.st_mode & ~077);
}
else
- res = 0;
+ {
+ if (!no_chown_flag && (out_file_stat.st_mode & 077) != 0
+ && chmod (output_name.ds_string, out_file_stat.st_mode & 07700) < 0)
+ {
+ error (0, errno, "%s: chmod", output_name.ds_string);
+ continue;
+ }
+ res = 0;
+ }
+
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
- res = mkdir (output_name.ds_string, in_file_stat.st_mode);
+ res = mkdir (output_name.ds_string, in_file_stat.st_mode & ~077);
}
if (res < 0)
{
@@ -311,12 +326,12 @@
if (link_res < 0)
{
- res = mknod (output_name.ds_string, in_file_stat.st_mode,
+ res = mknod (output_name.ds_string, in_file_stat.st_mode & ~077,
in_file_stat.st_rdev);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
- res = mknod (output_name.ds_string, in_file_stat.st_mode,
+ res = mknod (output_name.ds_string, in_file_stat.st_mode & ~077,
in_file_stat.st_rdev);
}
if (res < 0)

View File

@ -1,31 +1,43 @@
--- cpio-2.6/src/extern.h.lfs 2004-09-08 10:49:57.000000000 +0000
+++ cpio-2.6/src/extern.h 2005-01-14 14:10:09.006784175 +0000
--- cpio-2.6/src/copyin.c.lfs 2005-07-01 13:48:05.000000000 +0200
+++ cpio-2.6/src/copyin.c 2005-07-01 13:48:18.000000000 +0200
@@ -106,7 +106,7 @@
header type. */
static void
-tape_skip_padding (int in_file_des, int offset)
+tape_skip_padding (int in_file_des, unsigned long offset)
{
int pad;
--- cpio-2.6/src/extern.h.lfs 2004-09-08 12:49:57.000000000 +0200
+++ cpio-2.6/src/extern.h 2005-07-01 13:47:20.000000000 +0200
@@ -161,13 +161,13 @@
void tape_empty_output_buffer P_((int out_des));
void disk_empty_output_buffer P_((int out_des));
void swahw_array P_((char *ptr, int count));
-void tape_buffered_write P_((char *in_buf, int out_des, long num_bytes));
+void tape_buffered_write P_((char *in_buf, int out_des, off_t num_bytes));
+void tape_buffered_write P_((char *in_buf, int out_des, unsigned long num_bytes));
void tape_buffered_read P_((char *in_buf, int in_des, long num_bytes));
int tape_buffered_peek P_((char *peek_buf, int in_des, int num_bytes));
void tape_toss_input P_((int in_des, long num_bytes));
-void tape_toss_input P_((int in_des, long num_bytes));
-void copy_files_tape_to_disk P_((int in_des, int out_des, long num_bytes));
-void copy_files_disk_to_tape P_((int in_des, int out_des, long num_bytes, char *filename));
-void copy_files_disk_to_disk P_((int in_des, int out_des, long num_bytes, char *filename));
+void copy_files_tape_to_disk P_((int in_des, int out_des, off_t num_bytes));
+void copy_files_disk_to_tape P_((int in_des, int out_des, off_t num_bytes, char *filename));
+void copy_files_disk_to_disk P_((int in_des, int out_des, off_t num_bytes, char *filename));
+void tape_toss_input P_((int in_des, unsigned long num_bytes));
+void copy_files_tape_to_disk P_((int in_des, int out_des, unsigned long num_bytes));
+void copy_files_disk_to_tape P_((int in_des, int out_des, unsigned long num_bytes, char *filename));
+void copy_files_disk_to_disk P_((int in_des, int out_des, unsigned long num_bytes, char *filename));
void warn_if_file_changed P_((char *file_name, unsigned long old_file_size,
unsigned long old_file_mtime));
void create_all_directories P_((char *name));
--- cpio-2.6/src/util.c.lfs 2004-09-08 10:44:49.000000000 +0000
+++ cpio-2.6/src/util.c 2005-01-14 14:30:33.448133098 +0000
--- cpio-2.6/src/util.c.lfs 2004-09-08 12:44:49.000000000 +0200
+++ cpio-2.6/src/util.c 2005-07-01 13:56:49.000000000 +0200
@@ -207,7 +207,7 @@
Exit with an error if end of file is reached. */
static int
-disk_fill_input_buffer (int in_des, int num_bytes)
+disk_fill_input_buffer (int in_des, off_t num_bytes)
+disk_fill_input_buffer (int in_des, unsigned long num_bytes)
{
in_buff = input_buffer;
num_bytes = (num_bytes < DISK_IO_BLOCK_SIZE) ? num_bytes : DISK_IO_BLOCK_SIZE;
@ -34,10 +46,10 @@
void
-tape_buffered_write (char *in_buf, int out_des, long num_bytes)
+tape_buffered_write (char *in_buf, int out_des, off_t num_bytes)
+tape_buffered_write (char *in_buf, int out_des, unsigned long num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
+ register off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ register unsigned long bytes_left = num_bytes; /* Bytes needing to be copied. */
register long space_left; /* Room left in output buffer. */
while (bytes_left > 0)
@ -46,22 +58,38 @@
void
-disk_buffered_write (char *in_buf, int out_des, long num_bytes)
+disk_buffered_write (char *in_buf, int out_des, off_t num_bytes)
+disk_buffered_write (char *in_buf, int out_des, unsigned long num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
+ register off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ register unsigned long bytes_left = num_bytes; /* Bytes needing to be copied. */
register long space_left; /* Room left in output buffer. */
while (bytes_left > 0)
@@ -407,9 +407,9 @@
write_nuls_to_file (long num_bytes, int out_des,
@@ -376,9 +376,9 @@
/* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
void
-tape_toss_input (int in_des, long num_bytes)
+tape_toss_input (int in_des, unsigned long num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
+ register unsigned long bytes_left = num_bytes; /* Bytes needing to be copied. */
register long space_left; /* Bytes to copy from input buffer. */
while (bytes_left > 0)
@@ -404,12 +404,12 @@
}
static void
-write_nuls_to_file (long num_bytes, int out_des,
+write_nuls_to_file (unsigned long num_bytes, int out_des,
void (*writer) (char *in_buf, int out_des, long num_bytes))
{
- long blocks;
+ off_t blocks;
+ unsigned long blocks;
long extra_bytes;
- long i;
+ off_t i;
+ unsigned long i;
blocks = num_bytes / 512;
extra_bytes = num_bytes % 512;
@ -70,12 +98,12 @@
void
-copy_files_tape_to_disk (int in_des, int out_des, long num_bytes)
+copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes)
+copy_files_tape_to_disk (int in_des, int out_des, unsigned long num_bytes)
{
- long size;
- long k;
+ off_t size;
+ off_t k;
+ unsigned long size;
+ unsigned long k;
while (num_bytes > 0)
{
@ -84,16 +112,16 @@
void
-copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
+copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes,
+copy_files_disk_to_tape (int in_des, int out_des, unsigned long num_bytes,
char *filename)
{
- long size;
- long k;
+ off_t size;
+ off_t k;
+ unsigned long size;
+ unsigned long k;
int rc;
- long original_num_bytes;
+ off_t original_num_bytes;
+ unsigned long original_num_bytes;
original_num_bytes = num_bytes;
@ -115,15 +143,15 @@
void
-copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
+copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes,
+copy_files_disk_to_disk (int in_des, int out_des, unsigned long num_bytes,
char *filename)
{
- long size;
- long k;
- long original_num_bytes;
+ off_t size;
+ off_t k;
+ off_t original_num_bytes;
+ unsigned long size;
+ unsigned long k;
+ unsigned long original_num_bytes;
int rc;
original_num_bytes = num_bytes;

View File

@ -6,7 +6,7 @@
Summary: A GNU archiving program.
Name: cpio
Version: 2.6
Release: 7
Release: 8
License: GPL
Group: Applications/Archiving
URL: http://www.gnu.org/software/cpio/
@ -101,6 +101,10 @@ fi
%{_infodir}/*.info*
%changelog
* Fri Jul 01 2005 Peter Vrabec <pvrabec@redhat.com> 2.6-8
- fix large file support, archive >4GiB, archive members <4GiB (#160056)
- fix race condition holes, use mode 0700 for dir creation
* Tue May 17 2005 Peter Vrabec <pvrabec@redhat.com> 2.6-7
- fix #156314 (CAN-2005-1229) cpio directory traversal issue
- fix some gcc warnings