!50 [sync] PR-48: Fix CVE-2015-1197

From: @openeuler-sync-bot 
Reviewed-by: @znzjugod 
Signed-off-by: @ziyangc
This commit is contained in:
openeuler-ci-bot 2023-08-30 06:17:41 +00:00 committed by Gitee
commit fc262b289f
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 341 additions and 3 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: 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 <chenziyang4@huawei.com> - 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 <fuanan3@h-partners.com> - 2.13-9
- Type:bugfix
- ID:NA