backport CVE-2015-1197 and following 2 bugfix patches. Delete revert-CVE-2015-1197.patch

because new CVE patch will fix the problem of old CVE patch, so we don't need to revert old
CVE patch.

(cherry picked from commit bdaa060cf319507a37e75c5b96c647d2fd2bc9bd)
This commit is contained in:
ziyangc 2023-09-11 11:25:00 +08:00 committed by openeuler-sync-bot
parent 14ec7171e9
commit 7370c39eae
5 changed files with 343 additions and 111 deletions

View File

@ -0,0 +1,259 @@
From 376d663340a9dc91c91a5849e5713f07571c1628 Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@gnu.org>
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 <fnmatch.h>
#endif
+#include <hash.h>
#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

View File

@ -0,0 +1,37 @@
From 388fbb65a2d7244717aaeac2b316b51ee0474dd4 Mon Sep 17 00:00:00 2001
From: Ziyang Chen <chenziyang4@huawei.com>
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

View File

@ -0,0 +1,35 @@
From 06789cf2a6a0121f75fada35926f09ec851a609f Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@gnu.org>
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

View File

@ -1,6 +1,6 @@
Name: cpio
Version: 2.13
Release: 6
Release: 7
Summary: A GNU archiving program
License: GPLv3+
@ -14,10 +14,12 @@ 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-0001-CVE-2021-38185-Rewrite-dynamic-string-support.patch
Patch9: backport-0002-CVE-2021-38185-Fix-previous-commit.patch
Patch10: backport-0003-CVE-2021-38185-Fix-dynamic-string-reallocations.patch
Patch11: backport-CVE-2015-1197.patch
Patch12: backport-fix-operation-of-no-absolute-filenames-make-director.patch
Patch13: 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
@ -63,6 +65,14 @@ make check
%{_datadir}/man/man1/%{name}.1.gz
%changelog
* Mon Sep 11 2023 chenziyang <chenziyang4@huawei.com> - 2.13-7
- Type:CVE
- ID:CVE-2015-1197
- SUG:NA
- DESC:Fix CVE-2015-1197, delete revert-CVE-2015-1197.patch because new patch
will fix the problem brought by old-CVE-2015-1197.patch, so we delete
revert-CVE-2015-1197.patch
* Tue Jun 20 2023 fuanan <fuanan3@h-partners.com> - 2.13-6
- Type:bugfix
- ID:NA

View File

@ -1,109 +0,0 @@
From 250cae97153b438f5644e5d96814a7f5cb8c80e5 Mon Sep 17 00:00:00 2001
From: Liquor <lirui130@huawei.com>
Date: Thu, 26 Nov 2020 19:13:13 +0800
Subject: [PATCH] revert "CVE-2015-1197"
reason:https://lists.gnu.org/archive/html/bug-cpio/2019-11/msg00016.html
---
src/copyin.c | 5 ++---
tests/CVE-2015-1197.at | 43 ------------------------------------------
tests/Makefile.am | 1 -
tests/testsuite.at | 1 -
4 files changed, 2 insertions(+), 48 deletions(-)
delete mode 100644 tests/CVE-2015-1197.at
diff --git a/src/copyin.c b/src/copyin.c
index de31636..bf3b0a8 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -645,14 +645,13 @@ 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);
+ res = UMASKED_SYMLINK (link_name, file_hdr->c_name,
+ file_hdr->c_mode);
}
if (res < 0)
{
diff --git a/tests/CVE-2015-1197.at b/tests/CVE-2015-1197.at
deleted file mode 100644
index 6079af7..0000000
--- a/tests/CVE-2015-1197.at
+++ /dev/null
@@ -1,43 +0,0 @@
-# Process this file with autom4te to create testsuite. -*- Autotest -*-
-# Copyright (C) 2009-2019 Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-AT_SETUP([CVE-2015-1197 (--no-absolute-filenames for symlinks)])
-AT_CHECK([
-tempdir=$(pwd)/tmp
-mkdir $tempdir
-touch $tempdir/file
-ln -s $tempdir dir
-AT_DATA([filelist],
-[dir
-dir/file
-])
-ln -s /tmp dir
-touch /tmp/file
-cpio -o < filelist > test.cpio
-rm dir /tmp/file
-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
-dir/file
-1 block
-])
-AT_CLEANUP
-
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 65bf470..a71c057 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -56,7 +56,6 @@ TESTSUITE_AT = \
symlink-to-stdout.at\
version.at\
big-block-size.at\
- CVE-2015-1197.at\
CVE-2019-14866.at
TESTSUITE = $(srcdir)/testsuite
diff --git a/tests/testsuite.at b/tests/testsuite.at
index aa56bb9..58ed1d2 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -44,5 +44,4 @@ m4_include([setstat04.at])
m4_include([setstat05.at])
m4_include([big-block-size.at])
-m4_include([CVE-2015-1197.at])
m4_include([CVE-2019-14866.at])
--
2.27.0