diff --git a/backport-CVE-2015-1197.patch b/backport-CVE-2015-1197.patch new file mode 100644 index 0000000000000000000000000000000000000000..8466133e51110ced7b1453cbabf85db2b4f59a36 --- /dev/null +++ b/backport-CVE-2015-1197.patch @@ -0,0 +1,259 @@ +From 376d663340a9dc91c91a5849e5713f07571c1628 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Thu, 27 Apr 2023 15:14:23 +0300 +Subject: Fix 45b0ee2b407913c533f7ded8d6f8cbeec16ff6ca. + +The commit in question brought in more problems than solutions. To +properly fix the issue, use symlink placeholders, modelled after +delayed symlinks in tar. + +* src/copyin.c (symlink_placeholder) +(replace_symlink_placeholders): New functions. +(copyin_link): Create symlink placeholder if --no-absolute-filenames +was given. +(process_copy_in): Replace placeholders after extraction. +* tests/CVE-2015-1197.at: Update. Don't use /tmp. + +Reference:http://git.savannah.gnu.org/cgit/cpio.git/commit/?id=376d663340a9dc91c91a5849e5713f07571c1628 +Conflict:NA + +--- + src/copyin.c | 173 ++++++++++++++++++++++++++++++++++++++++++------- + tests/CVE-2015-1197.at | 7 +- + 2 files changed, 153 insertions(+), 27 deletions(-) + +diff --git a/src/copyin.c b/src/copyin.c +index 60cef9d..5ed2db6 100644 +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -30,6 +30,7 @@ + #ifndef FNM_PATHNAME + # include + #endif ++#include + + #ifndef HAVE_LCHOWN + # define lchown(f,u,g) 0 +@@ -620,6 +621,136 @@ copyin_device (struct cpio_file_stat* file_hdr) + file_hdr->c_mtime); + } + ++struct delayed_link ++ { ++ /* The device and inode number of the placeholder. */ ++ dev_t dev; ++ ino_t ino; ++ ++ /* The desired link metadata. */ ++ mode_t mode; ++ uid_t uid; ++ gid_t gid; ++ time_t mtime; ++ ++ /* Link source and target names. */ ++ char *source; ++ char target[1]; ++ }; ++ ++static Hash_table *delayed_link_table; ++ ++static size_t ++dl_hash (void const *entry, size_t table_size) ++{ ++ struct delayed_link const *dl = entry; ++ uintmax_t n = dl->dev; ++ int nshift = (sizeof (n) - sizeof (dl->dev)) * CHAR_BIT; ++ if (0 < nshift) ++ n <<= nshift; ++ n ^= dl->ino; ++ return n % table_size; ++} ++ ++static bool ++dl_compare (void const *a, void const *b) ++{ ++ struct delayed_link const *da = a, *db = b; ++ return (da->dev == db->dev) & (da->ino == db->ino); ++} ++ ++static int ++symlink_placeholder (char *oldpath, char *newpath, struct cpio_file_stat *file_stat) ++{ ++ int fd = open (newpath, O_WRONLY | O_CREAT | O_EXCL, 0); ++ struct stat st; ++ struct delayed_link *p; ++ size_t newlen = strlen (newpath); ++ ++ if (fd < 0) ++ { ++ open_error (newpath); ++ return -1; ++ } ++ ++ if (fstat (fd, &st) != 0) ++ { ++ stat_error (newpath); ++ close (fd); ++ return -1; ++ } ++ ++ close (fd); ++ ++ p = xmalloc (sizeof (*p) + strlen (oldpath) + newlen + 1); ++ p->dev = st.st_dev; ++ p->ino = st.st_ino; ++ ++ p->mode = file_stat->c_mode; ++ p->uid = file_stat->c_uid; ++ p->gid = file_stat->c_gid; ++ p->mtime = file_stat->c_mtime; ++ ++ strcpy (p->target, newpath); ++ p->source = p->target + newlen + 1; ++ strcpy (p->source, oldpath); ++ ++ if (!((delayed_link_table ++ || (delayed_link_table = hash_initialize (0, 0, dl_hash, ++ dl_compare, free))) ++ && hash_insert (delayed_link_table, p))) ++ xalloc_die (); ++ ++ return 0; ++} ++ ++static void ++replace_symlink_placeholders (void) ++{ ++ struct delayed_link *dl; ++ ++ if (!delayed_link_table) ++ return; ++ for (dl = hash_get_first (delayed_link_table); ++ dl; ++ dl = hash_get_next (delayed_link_table, dl)) ++ { ++ struct stat st; ++ ++ /* Make sure the placeholder file is still there. If not, ++ don't create a link, as the placeholder was probably ++ removed by a later extraction. */ ++ if (lstat (dl->target, &st) == 0 ++ && st.st_dev == dl->dev ++ && st.st_ino == dl->ino) ++ { ++ if (unlink (dl->target)) ++ unlink_error (dl->target); ++ else ++ { ++ int res = UMASKED_SYMLINK (dl->source, dl->target, dl->mode); ++ if (res < 0 && create_dir_flag) ++ { ++ create_all_directories (dl->target); ++ res = UMASKED_SYMLINK (dl->source, dl->target, dl->mode); ++ } ++ if (res < 0) ++ symlink_error (dl->source, dl->target); ++ else if (!no_chown_flag) ++ { ++ uid_t uid = set_owner_flag ? set_owner : dl->uid; ++ gid_t gid = set_group_flag ? set_group : dl->gid; ++ if (lchown (dl->target, uid, gid) < 0 && errno != EPERM) ++ chown_error_details (dl->target, uid, gid); ++ } ++ } ++ } ++ } ++ ++ hash_free (delayed_link_table); ++ delayed_link_table = NULL; ++} ++ + static void + copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) + { +@@ -645,29 +776,26 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) + link_name = xstrdup (file_hdr->c_tar_linkname); + } + +- cpio_safer_name_suffix (link_name, true, !no_abs_paths_flag, false); +- +- res = UMASKED_SYMLINK (link_name, file_hdr->c_name, +- file_hdr->c_mode); +- if (res < 0 && create_dir_flag) +- { +- create_all_directories (file_hdr->c_name); +- res = UMASKED_SYMLINK (link_name, file_hdr->c_name, file_hdr->c_mode); +- } +- if (res < 0) +- { +- error (0, errno, _("%s: Cannot symlink to %s"), +- quotearg_colon (link_name), quote_n (1, file_hdr->c_name)); +- free (link_name); +- return; +- } +- if (!no_chown_flag) ++ if (no_abs_paths_flag) ++ symlink_placeholder (link_name, file_hdr->c_name, file_hdr); ++ else + { +- uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid; +- gid_t gid = set_group_flag ? set_group : file_hdr->c_gid; +- if ((lchown (file_hdr->c_name, uid, gid) < 0) +- && errno != EPERM) +- chown_error_details (file_hdr->c_name, uid, gid); ++ res = UMASKED_SYMLINK (link_name, file_hdr->c_name, ++ file_hdr->c_mode); ++ if (res < 0 && create_dir_flag) ++ { ++ create_all_directories (file_hdr->c_name); ++ res = UMASKED_SYMLINK (link_name, file_hdr->c_name, file_hdr->c_mode); ++ } ++ if (res < 0) ++ symlink_error (link_name, file_hdr->c_name); ++ else if (!no_chown_flag) ++ { ++ uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid; ++ gid_t gid = set_group_flag ? set_group : file_hdr->c_gid; ++ if (lchown (file_hdr->c_name, uid, gid) < 0 && errno != EPERM) ++ chown_error_details (file_hdr->c_name, uid, gid); ++ } + } + free (link_name); + } +@@ -1425,6 +1553,7 @@ process_copy_in (void) + if (dot_flag) + fputc ('\n', stderr); + ++ replace_symlink_placeholders (); + apply_delayed_set_stat (); + + cpio_file_stat_free (&file_hdr); +diff --git a/tests/CVE-2015-1197.at b/tests/CVE-2015-1197.at +index 57ebe43..74591b1 100644 +--- a/tests/CVE-2015-1197.at ++++ b/tests/CVE-2015-1197.at +@@ -24,18 +24,15 @@ AT_DATA([filelist], + [dir + dir/file + ]) +-ln -s /tmp dir +-touch /tmp/file + cpio -o < filelist > test.cpio +-rm dir /tmp/file ++rm -rf dir $tempdir + cpio --no-absolute-filenames -iv < test.cpio + ], + [2], + [], + [1 block +-cpio: Removing leading `/' from hard link targets + dir +-cpio: dir/file: Cannot open: No such file or directory ++cpio: dir/file: Cannot open: Not a directory + dir/file + 1 block + ]) +-- +cgit v1.1 + + diff --git a/backport-Do-not-set-exit-code-to-2-when-failing-to-create-sym.patch b/backport-Do-not-set-exit-code-to-2-when-failing-to-create-sym.patch new file mode 100644 index 0000000000000000000000000000000000000000..fac0c4527534494cb73eb23accbc10cff73fa245 --- /dev/null +++ b/backport-Do-not-set-exit-code-to-2-when-failing-to-create-sym.patch @@ -0,0 +1,37 @@ +From 388fbb65a2d7244717aaeac2b316b51ee0474dd4 Mon Sep 17 00:00:00 2001 +From: Ziyang Chen +Date: Mon, 10 Jul 2023 20:19:27 +0800 +Subject: [PATCH] Do not set exit code to 2 when failing to create symlink + +Reference:https://lists.gnu.org/archive/html/bug-cpio/2023-07/msg00001.html +Conflict:NA +--- + src/copyin.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/copyin.c b/src/copyin.c +index dc715ff..6fa5699 100644 +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -742,7 +742,7 @@ replace_symlink_placeholders (void) + res = UMASKED_SYMLINK (dl->source, dl->target, dl->mode); + } + if (res < 0) +- symlink_error (dl->source, dl->target); ++ error (0, errno, _("%s: Cannot create symlink to %s"), quotearg_colon (dl->target), quote_n (1, dl->source)); + else if (!no_chown_flag) + { + uid_t uid = set_owner_flag ? set_owner : dl->uid; +@@ -795,7 +795,7 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) + res = UMASKED_SYMLINK (link_name, file_hdr->c_name, file_hdr->c_mode); + } + if (res < 0) +- symlink_error (link_name, file_hdr->c_name); ++ error (0, errno, _("%s: Cannot create symlink to %s"), quotearg_colon (file_hdr->c_name), quote_n (1, link_name)); + else if (!no_chown_flag) + { + uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid; +-- +2.33.0 + + diff --git a/backport-fix-operation-of-no-absolute-filenames-make-director.patch b/backport-fix-operation-of-no-absolute-filenames-make-director.patch new file mode 100644 index 0000000000000000000000000000000000000000..2647fa63fc5b267f191d9ad96415335f66bcd9b8 --- /dev/null +++ b/backport-fix-operation-of-no-absolute-filenames-make-director.patch @@ -0,0 +1,35 @@ +From 06789cf2a6a0121f75fada35926f09ec851a609f Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Thu, 18 May 2023 09:00:12 +0300 +Subject: [PATCH] Fix operation of --no-absolute-filenames --make-directories + +* src/copyin.c (symlink_placeholder): Try to create leading +directories if unable to create placeholder. + +Reference:http://git.savannah.gnu.org/cgit/cpio.git/commit/?id=e3cc782c610729de7622a274e532817c18262a9d +Conflict:NA +--- + src/copyin.c | 6 ++++++ + 2 files changed, 20 insertions(+) + create mode 100644 src/copyin.c.rej + +diff --git a/src/copyin.c b/src/copyin.c +index 69d4ca4..53a84e5 100644 +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -668,6 +668,12 @@ symlink_placeholder (char *oldpath, char *newpath, struct cpio_file_stat *file_s + struct delayed_link *p; + size_t newlen = strlen (newpath); + ++ if (fd < 0 && create_dir_flag) ++ { ++ create_all_directories (newpath); ++ fd = open (newpath, O_WRONLY | O_CREAT | O_EXCL, 0); ++ } ++ + if (fd < 0) + { + open_error (newpath); +-- +2.27.0 + diff --git a/cpio.spec b/cpio.spec index 45bd6d6409d9b1ceda34e8985d00ba015a2494b8..118a111845ebccac5f0515cfb13787412133537d 100644 --- a/cpio.spec +++ b/cpio.spec @@ -1,6 +1,6 @@ Name: cpio Version: 2.13 -Release: 9 +Release: 10 Summary: A GNU archiving program License: GPLv3+ @@ -14,12 +14,13 @@ Patch3: cpio-2.9.90-defaultremoteshell.patch Patch4: cpio-2.10-patternnamesigsegv.patch Patch5: cpio-2.10-longnames-split.patch Patch6: cpio-2.11-crc-fips-nit.patch -Patch7: revert-CVE-2015-1197.patch Patch8: backport-cpio-2.13-mutiple-definition.patch Patch9: backport-0001-CVE-2021-38185-Rewrite-dynamic-string-support.patch Patch10: backport-0002-CVE-2021-38185-Fix-previous-commit.patch Patch11: backport-0003-CVE-2021-38185-Fix-dynamic-string-reallocations.patch - +Patch12: backport-CVE-2015-1197.patch +Patch13: backport-fix-operation-of-no-absolute-filenames-make-director.patch +Patch14: backport-Do-not-set-exit-code-to-2-when-failing-to-create-sym.patch Patch9000: add-option-to-add-metadata-in-copy-out-mode.patch Patch9001: Fix-use-after-free-and-return-appropriate-error.patch @@ -64,6 +65,12 @@ make check %{_datadir}/man/man1/%{name}.1.gz %changelog +* Wed Aug 30 2023 chenziyang - 2.13-10 +- Type:CVE +- ID:CVE-2015-1197 +- SUG:NA +- DESC:backport CVE-2015-1197, delete revert-CVE-2015-1197.patch and backport the following 2 bugfix patches + * Tue Jun 20 2023 fuanan - 2.13-9 - Type:bugfix - ID:NA