diff --git a/SOURCES/cpio-2.11-retain-symlink-times.patch b/SOURCES/cpio-2.11-retain-symlink-times.patch new file mode 100644 index 0000000..a4e015d --- /dev/null +++ b/SOURCES/cpio-2.11-retain-symlink-times.patch @@ -0,0 +1,92 @@ +From 7a4094d382e74aaed0a0b8356dc24d64952852f9 Mon Sep 17 00:00:00 2001 +From: Pavel Raiskup +Date: Fri, 3 Jul 2020 12:32:58 +0200 +Subject: [PATCH] Extract: retain times for symlinks + +Original report by Pat Riehecky at +https://bugzilla.redhat.com/1486364 + +* src/copyin.c (copyin_device): Don't check for retain_time_flag +global, it's done by set_file_times. +(copyin_link): Call set_file_times to restore symlink times. +* src/util.c (set_perms): Don't check for retain_time_flag global, +done by set_file_times call. +(set_file_times): Do nothing if retain_time_flag global is false. +* src/copypass.c (process_copy_pass): Call set_file_times for +symlinks. +--- + src/copyin.c | 5 ++--- + src/copypass.c | 2 ++ + src/util.c | 6 ++++-- + 3 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/src/copyin.c b/src/copyin.c +index 183b5b5..267ed4b 100644 +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -639,9 +639,7 @@ copyin_device (struct cpio_file_stat* file_hdr) + /* chown may have turned off some permissions we wanted. */ + if (chmod (file_hdr->c_name, file_hdr->c_mode) < 0) + chmod_error_details (file_hdr->c_name, file_hdr->c_mode); +- if (retain_time_flag) +- set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, +- file_hdr->c_mtime); ++ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, file_hdr->c_mtime); + } + + static void +@@ -692,6 +690,7 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) + && errno != EPERM) + chown_error_details (file_hdr->c_name, uid, gid); + } ++ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, file_hdr->c_mtime); + free (link_name); + } + +diff --git a/src/copypass.c b/src/copypass.c +index c5a9899..b4e7169 100644 +--- a/src/copypass.c ++++ b/src/copypass.c +@@ -317,6 +317,8 @@ process_copy_pass () + && errno != EPERM) + chown_error_details (output_name.ds_string, uid, gid); + } ++ set_file_times (-1, output_name.ds_string, ++ in_file_stat.st_atime, in_file_stat.st_mtime); + free (link_name); + } + #endif +diff --git a/src/util.c b/src/util.c +index 6ff6032..11f9c30 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -1389,7 +1389,6 @@ set_perms (int fd, struct cpio_file_stat *header) + we have to refer to it using name+ instead of name. */ + file_hdr->c_name [cdf_char] = '+'; + #endif +- if (retain_time_flag) + set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime); + } + +@@ -1398,6 +1397,8 @@ set_file_times (int fd, + const char *name, unsigned long atime, unsigned long mtime) + { + struct timespec ts[2]; ++ if (!retain_time_flag) ++ return; + + memset (&ts, 0, sizeof ts); + +@@ -1406,7 +1407,8 @@ set_file_times (int fd, + + /* Silently ignore EROFS because reading the file won't have upset its + timestamp if it's on a read-only filesystem. */ +- if (fdutimens (fd, name, ts) < 0 && errno != EROFS) ++ if ((fd >= 0 ? fdutimens (fd, NULL, ts) : lutimens (name, ts)) < 0 ++ && errno != EROFS) + utime_error (name); + } + +-- +2.24.1 + diff --git a/SOURCES/cpio-2.12-improper-input-validation.patch b/SOURCES/cpio-2.12-improper-input-validation.patch new file mode 100644 index 0000000..25c0b4c --- /dev/null +++ b/SOURCES/cpio-2.12-improper-input-validation.patch @@ -0,0 +1,154 @@ +From: Thomas Habets +Subject: [PATCH] Check for size overflow in tar header fields. + +This prevents surprising outputs being created, e.g. this cpio tar +output with more than one file: + +tar cf suffix.tar AUTHORS +dd if=/dev/zero seek=16G bs=1 count=0 of=suffix.tar +echo suffix.tar | cpio -H tar -o | tar tvf - + +-rw-r--r-- 1000/1000 0 2019-08-30 16:40 suffix.tar +-rw-r--r-- thomas/thomas 161 2019-08-30 16:40 AUTHORS +--- + src/copyout.c | 3 +-- + src/extern.h | 2 +- + src/tar.c | 45 ++++++++++++++++++++++++++++++++------------- + 3 files changed, 34 insertions(+), 16 deletions(-) + +diff --git a/src/copyout.c b/src/copyout.c +index dcae449..56416ba 100644 +--- a/src/copyout.c ++++ b/src/copyout.c +@@ -552,8 +552,7 @@ write_out_header (struct cpio_file_stat *file_hdr, int out_des) + error (0, 0, _("%s: file name too long"), file_hdr->c_name); + return 1; + } +- write_out_tar_header (file_hdr, out_des); /* FIXME: No error checking */ +- return 0; ++ return write_out_tar_header (file_hdr, out_des); + + case arf_binary: + return write_out_binary_header (makedev (file_hdr->c_rdev_maj, +diff --git a/src/extern.h b/src/extern.h +index e27d662..47b477a 100644 +--- a/src/extern.h ++++ b/src/extern.h +@@ -145,7 +145,7 @@ int make_path (char *argpath, uid_t owner, gid_t group, + const char *verbose_fmt_string); + + /* tar.c */ +-void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des); ++int write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des); + int null_block (long *block, int size); + void read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des); + int otoa (char *s, unsigned long *n); +diff --git a/src/tar.c b/src/tar.c +index e2b5f45..53dc99a 100644 +--- a/src/tar.c ++++ b/src/tar.c +@@ -93,8 +93,9 @@ stash_tar_filename (char *prefix, char *filename) + sprintf (where, "%*lo ", digits - 2, value); + except that sprintf fills in the trailing NUL and we don't. */ + +-static void +-to_oct (register long value, register int digits, register char *where) ++static int ++to_oct_or_error (register long value, register int digits, register char *where, ++ const char *filename, const char *fieldname) + { + --digits; /* Leave the trailing NUL slot alone. */ + +@@ -105,10 +106,17 @@ to_oct (register long value, register int digits, register char *where) + value >>= 3; + } + while (digits > 0 && value != 0); ++ if (value > 0) ++ { ++ error (0, 0, _("%s: field width not sufficient for storing %s"), ++ filename, fieldname); ++ return 1; ++ } + + /* Add leading zeroes, if necessary. */ + while (digits > 0) + where[--digits] = '0'; ++ return 0; + } + + +@@ -139,7 +147,7 @@ tar_checksum (struct tar_header *tar_hdr) + /* Write out header FILE_HDR, including the file name, to file + descriptor OUT_DES. */ + +-void ++int + write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) + { + int name_len; +@@ -168,11 +176,16 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) + + /* Ustar standard (POSIX.1-1988) requires the mode to contain only 3 octal + digits */ +- to_oct (file_hdr->c_mode & MODE_ALL, 8, tar_hdr->mode); +- to_oct (file_hdr->c_uid, 8, tar_hdr->uid); +- to_oct (file_hdr->c_gid, 8, tar_hdr->gid); +- to_oct (file_hdr->c_filesize, 12, tar_hdr->size); +- to_oct (file_hdr->c_mtime, 12, tar_hdr->mtime); ++ if (to_oct_or_error (file_hdr->c_mode & MODE_ALL, 8, tar_hdr->mode, file_hdr->c_name, _("mode"))) ++ return 1; ++ if (to_oct_or_error (file_hdr->c_uid, 8, tar_hdr->uid, file_hdr->c_name, _("uid"))) ++ return 1; ++ if (to_oct_or_error (file_hdr->c_gid, 8, tar_hdr->gid, file_hdr->c_name, _("gid"))) ++ return 1; ++ if (to_oct_or_error (file_hdr->c_filesize, 12, tar_hdr->size, file_hdr->c_name, _("file size"))) ++ return 1; ++ if (to_oct_or_error (file_hdr->c_mtime, 12, tar_hdr->mtime, file_hdr->c_name, _("modification time"))) ++ return 1; + + switch (file_hdr->c_mode & CP_IFMT) + { +@@ -184,7 +197,8 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) + strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname, + TARLINKNAMESIZE); + tar_hdr->typeflag = LNKTYPE; +- to_oct (0, 12, tar_hdr->size); ++ if (to_oct_or_error (0, 12, tar_hdr->size, file_hdr->c_name, _("file size"))) ++ return 1; + } + else + tar_hdr->typeflag = REGTYPE; +@@ -210,7 +224,8 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) + than TARLINKNAMESIZE. */ + strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname, + TARLINKNAMESIZE); +- to_oct (0, 12, tar_hdr->size); ++ if (to_oct_or_error (0, 12, tar_hdr->size, file_hdr->c_name, _("file size"))) ++ return 1; + break; + #endif /* CP_IFLNK */ + } +@@ -229,13 +244,17 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) + if (name) + strcpy (tar_hdr->gname, name); + +- to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor); +- to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor); ++ if (to_oct_or_error (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor, file_hdr->c_name, _("rdev major"))) ++ return 1; ++ if (to_oct_or_error (file_hdr->c_rdev_min, 8, tar_hdr->devminor, file_hdr->c_name, _("rdev minor"))) ++ return 1; + } + +- to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum); ++ if (to_oct_or_error (tar_checksum (tar_hdr), 8, tar_hdr->chksum, file_hdr->c_name, _("checksum"))) ++ return 1; + + tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE); ++ return 0; + } + + /* Return nonzero iff all the bytes in BLOCK are NUL. +-- +2.26.0 + diff --git a/SPECS/cpio.spec b/SPECS/cpio.spec index 1b8bd78..4a3b745 100644 --- a/SPECS/cpio.spec +++ b/SPECS/cpio.spec @@ -1,7 +1,7 @@ Summary: A GNU archiving program Name: cpio Version: 2.12 -Release: 8%{?dist} +Release: 10%{?dist} License: GPLv3+ URL: http://www.gnu.org/software/cpio/ Source: ftp://ftp.gnu.org/gnu/cpio/cpio-%{version}.tar.bz2 @@ -36,6 +36,16 @@ Patch7: cpio-2.10-longnames-split.patch # Cpio does Sum32 checksum, not CRC (downstream) Patch8: cpio-2.11-crc-fips-nit.patch +# Extract: retain times for symlinks +# downstream patch (#1487673) +# https://www.mail-archive.com/bug-cpio@gnu.org/msg00605.html +Patch9: cpio-2.11-retain-symlink-times.patch + +# Fixed improper input validation when writing tar header fields +# upstream patch (#1766223) +# https://cement.retrofitta.se/tmp/cpio-tar.patch +Patch10: cpio-2.12-improper-input-validation.patch + Provides: bundled(gnulib) Provides: /bin/cpio @@ -96,6 +106,12 @@ make check || { %{_infodir}/*.info* %changelog +* Thu Jan 21 2021 Ondrej Dubaj - 2.12-10 +- Fixed improper input validation when writing tar header fields (#1766223) + +* Mon Jun 15 2020 Ondrej Dubaj - 2.12-9 +- Extract: retain times for symlinks (#1487673) + * Tue Jul 17 2018 Pavel Raiskup - 2.12-8 - cleanup, sync with rawhide