Update software to v2.13

This commit is contained in:
chengquan 2020-08-03 11:41:38 +08:00
parent 15343c91c7
commit 10f3af93c9
11 changed files with 546 additions and 447 deletions

View File

@ -1,322 +0,0 @@
From 7293fc357b13ba490daf0b99b505b3a019f1eb2a Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@gnu.org>
Date: Sun, 3 Nov 2019 23:59:39 +0200
Subject: [PATCH] Fix CVE-2019-14866
* src/copyout.c (to_ascii): Additional argument nul controls whether
to add the terminating nul character.
(field_width_error): Improve diagnostics: print the actual and the
maximum allowed field value.
* src/extern.h (to_ascii, field_width_error): New prototypes.
* src/tar.c (to_oct): Remove.
(to_oct_or_error): New function.
(TO_OCT): New macro.
(write_out_tar_header): Use TO_OCT and to_ascii. Return 0 on
success, 1 on error.
backport from http://git.savannah.gnu.org/cgit/cpio.git/commit/?id=7554e3e42cd72f6f8304410c47fe6f8918e9bfd7
---
src/copyout.c | 49 +++++++++++++++++++++--------------
src/extern.h | 15 +++++++++--
src/tar.c | 72 +++++++++++++++++++++++----------------------------
3 files changed, 76 insertions(+), 60 deletions(-)
diff --git a/src/copyout.c b/src/copyout.c
index dcae449..1ae5477 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -269,26 +269,32 @@ writeout_final_defers (int out_des)
so it should be moved to paxutils too.
Allowed values for logbase are: 1 (binary), 2, 3 (octal), 4 (hex) */
int
-to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase)
+to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase, bool nul)
{
static char codetab[] = "0123456789ABCDEF";
- int i = digits;
-
- do
+
+ if (nul)
+ where[--digits] = 0;
+ while (digits > 0)
{
- where[--i] = codetab[(v & ((1 << logbase) - 1))];
+ where[--digits] = codetab[(v & ((1 << logbase) - 1))];
v >>= logbase;
}
- while (i);
return v != 0;
}
-static void
-field_width_error (const char *filename, const char *fieldname)
+void
+field_width_error (const char *filename, const char *fieldname,
+ uintmax_t value, size_t width, bool nul)
{
- error (1, 0, _("%s: field width not sufficient for storing %s"),
- filename, fieldname);
+ char valbuf[UINTMAX_STRSIZE_BOUND + 1];
+ char maxbuf[UINTMAX_STRSIZE_BOUND + 1];
+ error (0, 0, _("%s: value %s %s out of allowed range 0..%s"),
+ filename, fieldname,
+ STRINGIFY_BIGINT (value, valbuf),
+ STRINGIFY_BIGINT (MAX_VAL_WITH_DIGITS (width - nul, LG_8),
+ maxbuf));
}
static void
@@ -303,7 +309,7 @@ to_ascii_or_warn (char *where, uintmax_t n, size_t digits,
unsigned logbase,
const char *filename, const char *fieldname)
{
- if (to_ascii (where, n, digits, logbase))
+ if (to_ascii (where, n, digits, logbase, false))
field_width_warning (filename, fieldname);
}
@@ -312,9 +318,9 @@ to_ascii_or_error (char *where, uintmax_t n, size_t digits,
unsigned logbase,
const char *filename, const char *fieldname)
{
- if (to_ascii (where, n, digits, logbase))
+ if (to_ascii (where, n, digits, logbase, false))
{
- field_width_error (filename, fieldname);
+ field_width_error (filename, fieldname, n, digits, false);
return 1;
}
return 0;
@@ -371,7 +377,7 @@ write_out_new_ascii_header (const char *magic_string,
_("name size")))
return 1;
p += 8;
- to_ascii (p, file_hdr->c_chksum & 0xffffffff, 8, LG_16);
+ to_ascii (p, file_hdr->c_chksum & 0xffffffff, 8, LG_16, false);
tape_buffered_write (ascii_header, out_des, sizeof ascii_header);
@@ -388,7 +394,7 @@ write_out_old_ascii_header (dev_t dev, dev_t rdev,
char ascii_header[76];
char *p = ascii_header;
- to_ascii (p, file_hdr->c_magic, 6, LG_8);
+ to_ascii (p, file_hdr->c_magic, 6, LG_8, false);
p += 6;
to_ascii_or_warn (p, dev, 6, LG_8, file_hdr->c_name, _("device number"));
p += 6;
@@ -492,7 +498,10 @@ write_out_binary_header (dev_t rdev,
short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
if (short_hdr.c_namesize != file_hdr->c_namesize)
{
- field_width_error (file_hdr->c_name, _("name size"));
+ char maxbuf[UINTMAX_STRSIZE_BOUND + 1];
+ error (0, 0, _("%s: value %s %s out of allowed range 0..%u"),
+ file_hdr->c_name, _("name size"),
+ STRINGIFY_BIGINT (file_hdr->c_namesize, maxbuf), 0xFFFFu);
return 1;
}
@@ -502,7 +511,10 @@ write_out_binary_header (dev_t rdev,
if (((off_t)short_hdr.c_filesizes[0] << 16) + short_hdr.c_filesizes[1]
!= file_hdr->c_filesize)
{
- field_width_error (file_hdr->c_name, _("file size"));
+ char maxbuf[UINTMAX_STRSIZE_BOUND + 1];
+ error (0, 0, _("%s: value %s %s out of allowed range 0..%lu"),
+ file_hdr->c_name, _("file size"),
+ STRINGIFY_BIGINT (file_hdr->c_namesize, maxbuf), 0xFFFFFFFFlu);
return 1;
}
@@ -552,8 +564,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..f9ef56a 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -117,6 +117,10 @@ void print_name_with_quoting (char *p);
/* copyout.c */
int write_out_header (struct cpio_file_stat *file_hdr, int out_des);
void process_copy_out (void);
+int to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase,
+ bool nul);
+void field_width_error (const char *filename, const char *fieldname,
+ uintmax_t value, size_t width, bool nul);
/* copypass.c */
void process_copy_pass (void);
@@ -145,7 +149,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);
@@ -204,9 +208,16 @@ void cpio_safer_name_suffix (char *name, bool link_target,
int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir);
void change_dir (void);
-/* FIXME: These two defines should be defined in paxutils */
+/* FIXME: The following three should be defined in paxutils */
#define LG_8 3
#define LG_16 4
+/* The maximum uintmax_t value that can be represented with DIGITS digits,
+ assuming that each digit is BITS_PER_DIGIT wide. */
+#define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \
+ ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \
+ ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \
+ : (uintmax_t) -1)
+
uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase);
diff --git a/src/tar.c b/src/tar.c
index e2b5f45..1a1f8c8 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -1,6 +1,5 @@
/* tar.c - read in write tar headers for cpio
- Copyright (C) 1992, 2001, 2004, 2006-2007, 2010, 2014-2015 Free
- Software Foundation, Inc.
+ Copyright (C) 1992-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
@@ -81,36 +80,17 @@ stash_tar_filename (char *prefix, char *filename)
return hold_tar_filename;
}
-/* Convert a number into a string of octal digits.
- Convert long VALUE into a DIGITS-digit field at WHERE,
- including a trailing space and room for a NUL. DIGITS==3 means
- 1 digit, a space, and room for a NUL.
-
- We assume the trailing NUL is already there and don't fill it in.
- This fact is used by start_header and finish_header, so don't change it!
-
- This is be equivalent to:
- 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 (uintmax_t value, size_t digits, char *where, char const *field,
+ char const *file)
{
- --digits; /* Leave the trailing NUL slot alone. */
-
- /* Produce the digits -- at least one. */
- do
+ if (to_ascii (where, value, digits, LG_8, true))
{
- where[--digits] = '0' + (char) (value & 7); /* One octal digit. */
- value >>= 3;
+ field_width_error (file, field, value, digits, true);
+ return 1;
}
- while (digits > 0 && value != 0);
-
- /* Add leading zeroes, if necessary. */
- while (digits > 0)
- where[--digits] = '0';
+ return 0;
}
-
/* Compute and return a checksum for TAR_HDR,
@@ -136,10 +116,22 @@ tar_checksum (struct tar_header *tar_hdr)
return sum;
}
+#define TO_OCT(file_hdr, c_fld, digits, tar_hdr, tar_field) \
+ do \
+ { \
+ if (to_oct_or_error (file_hdr -> c_fld, \
+ digits, \
+ tar_hdr -> tar_field, \
+ #tar_field, \
+ file_hdr->c_name)) \
+ return 1; \
+ } \
+ while (0)
+
/* 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 +160,11 @@ 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);
+ 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);
switch (file_hdr->c_mode & CP_IFMT)
{
@@ -184,7 +176,7 @@ 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);
+ to_ascii (tar_hdr->size, 0, 12, LG_8, true);
}
else
tar_hdr->typeflag = REGTYPE;
@@ -210,7 +202,7 @@ 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);
+ to_ascii (tar_hdr->size, 0, 12, LG_8, true);
break;
#endif /* CP_IFLNK */
}
@@ -229,13 +221,15 @@ 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);
+ TO_OCT (file_hdr, c_rdev_maj, 8, tar_hdr, devmajor);
+ TO_OCT (file_hdr, c_rdev_min, 8, tar_hdr, devminor);
}
- to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum);
+ to_ascii (tar_hdr->chksum, tar_checksum (tar_hdr), 8, LG_8, true);
tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE);
+
+ return 0;
}
/* Return nonzero iff all the bytes in BLOCK are NUL.
--
2.18.1

View File

@ -1,71 +0,0 @@
From 7d55037f89ab630125c37e6fc571cf36bb0a94c3 Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@gnu.org.ua>
Date: Thu, 10 Nov 2016 12:48:19 +0200
Subject: [PATCH 02/15] Fix out-of-bounds read
* src/copyin.c (process_copy_in): Skip records with zero filename length.
---
src/copyin.c | 41 +++++++++++++++++++++++------------------
1 file changed, 23 insertions(+), 18 deletions(-)
diff --git a/src/copyin.c b/src/copyin.c
index cde911e..05279d2 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -1378,30 +1378,35 @@ process_copy_in ()
}
#endif
- /* Is this the header for the TRAILER file? */
- if (strcmp (CPIO_TRAILER_NAME, file_hdr.c_name) == 0)
+ if (file_hdr.c_namesize == 0)
+ skip_file = true;
+ else
{
- done = true;
- break;
- }
+ /* Is this the header for the TRAILER file? */
+ if (strcmp (CPIO_TRAILER_NAME, file_hdr.c_name) == 0)
+ {
+ done = true;
+ break;
+ }
- cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag,
- false);
+ cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag,
+ false);
- /* Does the file name match one of the given patterns? */
- if (num_patterns <= 0)
- skip_file = false;
- else
- {
- skip_file = copy_matching_files;
- for (i = 0; i < num_patterns
- && skip_file == copy_matching_files; i++)
+ /* Does the file name match one of the given patterns? */
+ if (num_patterns <= 0)
+ skip_file = false;
+ else
{
- if (fnmatch (save_patterns[i], file_hdr.c_name, 0) == 0)
- skip_file = !copy_matching_files;
+ skip_file = copy_matching_files;
+ for (i = 0; i < num_patterns
+ && skip_file == copy_matching_files; i++)
+ {
+ if (fnmatch (save_patterns[i], file_hdr.c_name, 0) == 0)
+ skip_file = !copy_matching_files;
+ }
}
}
-
+
if (skip_file)
{
/* If we're skipping a file with links, there might be other
--
1.8.3.1

View File

@ -1,25 +0,0 @@
From 404600ebb4d417238bfabf7ec1561a62dc83c168 Mon Sep 17 00:00:00 2001
From: grajagandev <dmoorefo@gmail.com>
Date: Mon, 8 Feb 2016 07:58:45 -0800
Subject: [PATCH 04/15] Fix signed integer overflow - big block sizes
---
src/main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/main.c b/src/main.c
index a13861f..5a30a7b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -321,7 +321,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case BLOCK_SIZE_OPTION: /* --block-size */
io_block_size = atoi (arg);
- if (io_block_size < 1)
+ if (io_block_size < 1 || io_block_size > INT_MAX/512)
USAGE_ERROR ((0, 0, _("invalid block size")));
io_block_size *= 512;
break;
--
1.8.3.1

View File

@ -0,0 +1,61 @@
From 356ad51812edb47fd76aa59b8c935d55b879541a Mon Sep 17 00:00:00 2001
From: Roberto Sassu <roberto.sassu@huawei.com>
Date: Thu, 2 Jul 2020 10:23:44 +0200
Subject: [PATCH] cpio: fix use after free and return appropriate errors
---
src/copyout.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/copyout.c b/src/copyout.c
index 29d2198..7feed00 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -600,15 +600,19 @@ write_xattrs (int metadata_fd, char *path)
list_ptr = xattr_list = malloc(list_len);
if (!list_ptr) {
error (0, 0, _("out of memory"));
- return ret;
+ return -ENOMEM;
}
len = llistxattr(path, xattr_list, list_len);
- if (len != list_len)
+ if (len != list_len) {
+ ret = -EIO;
goto out;
+ }
- if (ftruncate(metadata_fd, 0))
+ if (ftruncate(metadata_fd, 0)) {
+ ret = -EIO;
goto out;
+ }
lseek(metadata_fd, 0, SEEK_SET);
@@ -658,13 +662,16 @@ write_xattrs (int metadata_fd, char *path)
}
free(xattr_value);
-out:
- free(xattr_list);
- if (list_ptr != xattr_list + list_len)
- return ret;
+ if (list_ptr != xattr_list + list_len) {
+ ret = -EINVAL;
+ goto out;
+ }
- return 0;
+ ret = 0;
+out:
+ free(xattr_list);
+ return ret;
}
/* Read a list of file names from the standard input
--
2.27.GIT

View File

@ -0,0 +1,428 @@
From 531cabc88e9ecdc3231fad6e4856869baa9a91ef Mon Sep 17 00:00:00 2001
From: Roberto Sassu <roberto.sassu@huawei.com>
Date: Wed, 22 May 2019 09:04:39 +0200
Subject: [PATCH] cpio: add option to add file metadata in copy-out mode
This patch adds the -e <type> option to include file metadata in the
image. At the moment, only the xattr type is supported.
If the xattr type is selected, the patch includes an additional file for
each file passed to stdin, with special name 'METADATA!!!'. The
additional file might contain multiple metadata records. The format of
each record is:
<metadata len (ASCII, 8 chars)><version><type><metadata>
The format of metadata for the xattr type is:
<xattr name>\0<xattr value>
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
doc/cpio.texi | 3 ++
src/copyout.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
src/dstring.c | 26 +++++++++--
src/dstring.h | 1 +
src/extern.h | 4 +-
src/global.c | 2 +
src/initramfs.h | 21 +++++++++
src/main.c | 22 +++++++++
8 files changed, 211 insertions(+), 8 deletions(-)
create mode 100644 src/initramfs.h
diff --git a/doc/cpio.texi b/doc/cpio.texi
index 31a15fa..03d9585 100644
--- a/doc/cpio.texi
+++ b/doc/cpio.texi
@@ -276,6 +276,9 @@ Set the I/O block size to the given @var{number} of bytes.
@item -D @var{dir}
@itemx --directory=@var{dir}
Change to directory @var{dir}
+@item -e @var{type}
+@itemx --file-metadata=@var{type}
+Include in the image file metadata with the specified type.
@item --force-local
Treat the archive file as local, even if its name contains colons.
@item -F [[@var{user}@@]@var{host}:]@var{archive-file}
diff --git a/src/copyout.c b/src/copyout.c
index 4b7336b..fdafb37 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/xattr.h>
#include "filetypes.h"
#include "cpiohdr.h"
#include "dstring.h"
@@ -589,6 +590,94 @@ assign_string (char **pvar, char *value)
*pvar = p;
}
+static int
+write_xattrs (int metadata_fd, char *path)
+{
+ struct metadata_hdr hdr = { .c_version = 1, .c_type = TYPE_XATTR };
+ char str[sizeof(hdr.c_size) + 1];
+ char *xattr_list = NULL;
+ char *list_ptr = NULL;
+ char *xattr_value = NULL;
+ ssize_t list_len, name_len, value_len, len;
+ int ret = -EINVAL;
+
+ if (metadata_fd < 0)
+ return 0;
+
+ list_len = llistxattr(path, NULL, 0);
+ if (list_len <= 0)
+ return -ENOENT;
+
+ list_ptr = xattr_list = malloc(list_len);
+ if (!list_ptr) {
+ error (0, 0, _("out of memory"));
+ return ret;
+ }
+
+ len = llistxattr(path, xattr_list, list_len);
+ if (len != list_len)
+ goto out;
+
+ if (ftruncate(metadata_fd, 0))
+ goto out;
+
+ lseek(metadata_fd, 0, SEEK_SET);
+
+ while (list_ptr < xattr_list + list_len) {
+ name_len = strlen(list_ptr);
+
+ value_len = lgetxattr(path, list_ptr, NULL, 0);
+ if (value_len < 0) {
+ error (0, 0, _("cannot get xattrs"));
+ break;
+ }
+
+ if (value_len) {
+ xattr_value = malloc(value_len);
+ if (!xattr_value) {
+ error (0, 0, _("out of memory"));
+ break;
+ }
+ } else {
+ xattr_value = NULL;
+ }
+
+ len = lgetxattr(path, list_ptr, xattr_value, value_len);
+ if (len != value_len)
+ break;
+
+ snprintf(str, sizeof(str), "%.8lx",
+ sizeof(hdr) + name_len + 1 + value_len);
+
+ memcpy(hdr.c_size, str, sizeof(hdr.c_size));
+
+ if (write(metadata_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
+ break;
+
+ if (write(metadata_fd, list_ptr, name_len + 1) != name_len + 1)
+ break;
+
+ if (write(metadata_fd, xattr_value, value_len) != value_len)
+ break;
+
+ if (fsync(metadata_fd))
+ break;
+
+ list_ptr += name_len + 1;
+ free(xattr_value);
+ xattr_value = NULL;
+ }
+
+ free(xattr_value);
+out:
+ free(xattr_list);
+
+ if (list_ptr != xattr_list + list_len)
+ return ret;
+
+ return 0;
+}
+
/* Read a list of file names from the standard input
and write a cpio collection on the standard output.
The format of the header depends on the compatibility (-c) flag. */
@@ -603,6 +692,8 @@ process_copy_out ()
int in_file_des; /* Source file descriptor. */
int out_file_des; /* Output file descriptor. */
char *orig_file_name = NULL;
+ char template[] = "/tmp/cpio-metadata-XXXXXX";
+ int ret, metadata_fd, metadata = 0, old_metadata, hard_link;
/* Initialize the copy out. */
ds_init (&input_name, 128);
@@ -635,9 +726,37 @@ process_copy_out ()
prepare_append (out_file_des);
}
+ /* Create a temporary file to store file metadata */
+ if (metadata_type != TYPE_NONE) {
+ metadata_fd = mkstemp(template);
+ if (metadata_fd < 0) {
+ error (0, 0, _("cannot create temporary file"));
+ return;
+ }
+ }
+
/* Copy files with names read from stdin. */
- while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
+ while ((metadata_type != TYPE_NONE && metadata) ||
+ ds_fgetstr (stdin, &input_name, name_end) != NULL)
{
+ old_metadata = metadata;
+ hard_link = 0;
+
+ if (metadata) {
+ metadata = 0;
+
+ if (metadata_type != TYPE_XATTR) {
+ error (0, 0, _("metadata type not supported"));
+ continue;
+ }
+
+ ret = write_xattrs(metadata_fd, orig_file_name);
+ if (ret < 0)
+ continue;
+
+ ds_sgetstr (template, &input_name, name_end);
+ }
+
/* Check for blank line. */
if (input_name.ds_string[0] == 0)
{
@@ -667,8 +786,15 @@ process_copy_out ()
}
}
}
-
- assign_string (&orig_file_name, input_name.ds_string);
+
+ if (old_metadata) {
+ assign_string (&orig_file_name, template);
+ ds_sgetstr (METADATA_FILENAME, &input_name, name_end);
+ file_hdr.c_mode |= 0x10000;
+ } else {
+ assign_string (&orig_file_name, input_name.ds_string);
+ }
+
cpio_safer_name_suffix (input_name.ds_string, false,
!no_abs_paths_flag, true);
cpio_set_c_name (&file_hdr, input_name.ds_string);
@@ -700,6 +826,7 @@ process_copy_out ()
else
{
add_link_defer (&file_hdr);
+ hard_link = 1;
break;
}
}
@@ -836,6 +963,8 @@ process_copy_out ()
fprintf (stderr, "%s\n", orig_file_name);
if (dot_flag)
fputc ('.', stderr);
+ if (metadata_type != TYPE_NONE && !old_metadata && !hard_link)
+ metadata = 1;
}
}
@@ -875,6 +1004,11 @@ process_copy_out ()
(unsigned long) blocks), (unsigned long) blocks);
}
cpio_file_stat_free (&file_hdr);
+
+ if (metadata_type != TYPE_NONE) {
+ close(metadata_fd);
+ unlink(template);
+ }
}
diff --git a/src/dstring.c b/src/dstring.c
index e9c063f..1021d21 100644
--- a/src/dstring.c
+++ b/src/dstring.c
@@ -58,8 +58,8 @@ ds_resize (dynamic_string *string, int size)
Return NULL if end of file is detected. Otherwise,
Return a pointer to the null-terminated string in S. */
-char *
-ds_fgetstr (FILE *f, dynamic_string *s, char eos)
+static char *
+ds_fgetstr_common (FILE *f, char *input_string, dynamic_string *s, char eos)
{
int insize; /* Amount needed for line. */
int strsize; /* Amount allocated for S. */
@@ -70,7 +70,10 @@ ds_fgetstr (FILE *f, dynamic_string *s, char eos)
strsize = s->ds_length;
/* Read the input string. */
- next_ch = getc (f);
+ if (input_string)
+ next_ch = *input_string++;
+ else
+ next_ch = getc (f);
while (next_ch != eos && next_ch != EOF)
{
if (insize >= strsize - 1)
@@ -79,7 +82,10 @@ ds_fgetstr (FILE *f, dynamic_string *s, char eos)
strsize = s->ds_length;
}
s->ds_string[insize++] = next_ch;
- next_ch = getc (f);
+ if (input_string)
+ next_ch = *input_string++;
+ else
+ next_ch = getc (f);
}
s->ds_string[insize++] = '\0';
@@ -90,6 +96,12 @@ ds_fgetstr (FILE *f, dynamic_string *s, char eos)
}
char *
+ds_fgetstr (FILE *f, dynamic_string *s, char eos)
+{
+ return ds_fgetstr_common (f, NULL, s, eos);
+}
+
+char *
ds_fgets (FILE *f, dynamic_string *s)
{
return ds_fgetstr (f, s, '\n');
@@ -100,3 +112,9 @@ ds_fgetname (FILE *f, dynamic_string *s)
{
return ds_fgetstr (f, s, '\0');
}
+
+char *
+ds_sgetstr (char *input_string, dynamic_string *s, char eos)
+{
+ return ds_fgetstr_common (NULL, input_string, s, eos);
+}
diff --git a/src/dstring.h b/src/dstring.h
index b5135fe..f5f95ec 100644
--- a/src/dstring.h
+++ b/src/dstring.h
@@ -49,3 +49,4 @@ void ds_resize (dynamic_string *string, int size);
char *ds_fgetname (FILE *f, dynamic_string *s);
char *ds_fgets (FILE *f, dynamic_string *s);
char *ds_fgetstr (FILE *f, dynamic_string *s, char eos);
+char *ds_sgetstr (char *input_string, dynamic_string *s, char eos);
diff --git a/src/extern.h b/src/extern.h
index 11ac6bf..f295fcf 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -19,6 +19,7 @@
#include "paxlib.h"
#include "quotearg.h"
+#include "initramfs.h"
#include "quote.h"
enum archive_format
@@ -99,7 +100,8 @@ extern char output_is_seekable;
extern int (*xstat) ();
extern void (*copy_function) ();
extern char *change_directory_option;
-
+extern enum metadata_types metadata_type;
+
/* copyin.c */
void warn_junk_bytes (long bytes_skipped);
diff --git a/src/global.c b/src/global.c
index fb3abe9..0c40be0 100644
--- a/src/global.c
+++ b/src/global.c
@@ -199,3 +199,5 @@ char *change_directory_option;
int renumber_inodes_option;
int ignore_devno_option;
+/* include file metadata into the image */
+enum metadata_types metadata_type = TYPE_NONE;
diff --git a/src/initramfs.h b/src/initramfs.h
new file mode 100644
index 0000000..88abae7
--- /dev/null
+++ b/src/initramfs.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * include/linux/initramfs.h
+ *
+ * Include file for file metadata in the initial ram disk.
+ */
+#ifndef _LINUX_INITRAMFS_H
+#define _LINUX_INITRAMFS_H
+
+#define METADATA_FILENAME "METADATA!!!"
+
+enum metadata_types { TYPE_NONE, TYPE_XATTR, TYPE__LAST };
+
+struct metadata_hdr {
+ char c_size[8]; /* total size including c_size field */
+ char c_version; /* header version */
+ char c_type; /* metadata type */
+ char c_metadata[]; /* metadata */
+} __attribute__((packed));
+
+#endif /*_LINUX_INITRAMFS_H*/
diff --git a/src/main.c b/src/main.c
index 6f90055..e343286 100644
--- a/src/main.c
+++ b/src/main.c
@@ -199,6 +199,8 @@ static struct argp_option options[] = {
{"device-independent", DEVICE_INDEPENDENT_OPTION, NULL, 0,
N_("Create device-independent (reproducible) archives") },
{"reproducible", 0, NULL, OPTION_ALIAS },
+ {"file-metadata", 'e', N_("TYPE"), 0,
+ N_("Include file metadata"), GRID+1 },
#undef GRID
/* ********** */
@@ -292,6 +294,22 @@ warn_control (char *arg)
return 1;
}
+static enum metadata_types
+parse_metadata_type(char *arg)
+{
+ static char *metadata_type_str[TYPE__LAST] = {
+ [TYPE_NONE] = "none",
+ [TYPE_XATTR] = "xattr",
+ };
+ int i;
+
+ for (i = 0; i < TYPE__LAST; i++)
+ if (!strcmp (metadata_type_str[i], arg))
+ return i;
+
+ return TYPE_NONE;
+}
+
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
@@ -354,6 +372,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
copy_matching_files = false;
break;
+ case 'e': /* Metadata type. */
+ metadata_type = parse_metadata_type(arg);
+ break;
+
case 'E': /* Pattern file name. */
pattern_file_name = arg;
break;
--
1.8.3.1

Binary file not shown.

View File

@ -3,10 +3,10 @@ Date: Mon, 14 Sep 2015 09:37:15 +0200
Subject: [PATCH 3/7] Support major/minor device numbers over 127 (bz#450109)
diff --git a/src/copyin.c b/src/copyin.c
index cde911e..12bd27c 100644
index b29f348..1142d6a 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -1196,15 +1196,15 @@ read_in_binary (struct cpio_file_stat *file_hdr,
@@ -1123,15 +1123,15 @@ read_in_binary (struct cpio_file_stat *file_hdr,
swab_array ((char *) short_hdr, 13);
}
@ -25,4 +25,4 @@ index cde911e..12bd27c 100644
+ file_hdr->c_rdev_min = minor ((unsigned short)short_hdr->c_rdev);
file_hdr->c_mtime = (unsigned long) short_hdr->c_mtimes[0] << 16
| short_hdr->c_mtimes[1];
file_hdr->c_filesize = (unsigned long) short_hdr->c_filesizes[0] << 16

39
cpio-2.13-exitCode.patch Normal file
View File

@ -0,0 +1,39 @@
Subject: [PATCH 2/7] set exit code to 1 when cpio fails to store file > 4GB
(#183224)
diff --git a/src/copyout.c b/src/copyout.c
index 8b0beb6..4b7336b 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -290,7 +290,7 @@ field_width_error (const char *filename, const char *fieldname,
{
char valbuf[UINTMAX_STRSIZE_BOUND + 1];
char maxbuf[UINTMAX_STRSIZE_BOUND + 1];
- error (0, 0, _("%s: value %s %s out of allowed range 0..%s"),
+ error (1, 0, _("%s: value %s %s out of allowed range 0..%s"),
filename, fieldname,
STRINGIFY_BIGINT (value, valbuf),
STRINGIFY_BIGINT (MAX_VAL_WITH_DIGITS (width - nul, LG_8),
diff --git a/tests/CVE-2019-14866.at b/tests/CVE-2019-14866.at
index e877b39..50ad60b 100644
--- a/tests/CVE-2019-14866.at
+++ b/tests/CVE-2019-14866.at
@@ -30,6 +30,5 @@ fi
[0],
[],
[cpio: file: value size 17179869184 out of allowed range 0..8589934591
-2 blocks
])
AT_CLEANUP
diff --git a/tests/testsuite b/tests/testsuite
index b45c731..fd8454d 100755
--- a/tests/testsuite
+++ b/tests/testsuite
@@ -2885,7 +2885,6 @@ fi
at_status=$? at_failed=false
$at_check_filter
echo >>"$at_stderr"; $as_echo "cpio: file: value size 17179869184 out of allowed range 0..8589934591
-2 blocks
" | \
$at_diff - "$at_stderr" || at_failed=:
at_fn_diff_devnull "$at_stdout" || at_failed=:

BIN
cpio-2.13.tar.bz2 Normal file

Binary file not shown.

View File

@ -1,18 +0,0 @@
From: Peter Vrabec <pvrabec@redhat.com>
Date: Mon, 14 Sep 2015 09:31:08 +0200
Subject: [PATCH 2/7] set exit code to 1 when cpio fails to store file > 4GB
(#183224)
diff --git a/src/copyout.c b/src/copyout.c
index 1f0987a..dcae449 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -287,7 +287,7 @@ to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase)
static void
field_width_error (const char *filename, const char *fieldname)
{
- error (0, 0, _("%s: field width not sufficient for storing %s"),
+ error (1, 0, _("%s: field width not sufficient for storing %s"),
filename, fieldname);
}

View File

@ -1,6 +1,6 @@
Name: cpio
Version: 2.12
Release: 14
Version: 2.13
Release: 1
Summary: A GNU archiving program
License: GPLv3+
@ -8,15 +8,14 @@ URL: https://www.gnu.org/software/cpio
Source0: https://ftp.gnu.org/gnu/cpio/%{name}-%{version}.tar.bz2
Patch0: cpio-2.9-rh.patch
Patch1: cpio-2.9-exitCode.patch
Patch2: cpio-2.9-dev_number.patch
Patch1: cpio-2.13-exitCode.patch
Patch2: cpio-2.13-dev_number.patch
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
Patch6000: Fix-out-of-bounds-read.patch
Patch6001: Fix-signed-integer-overflow-big-block-sizes.patch
Patch6002: Fix-CVE-2019-14866.patch
Patch7: add-option-to-add-metadata-in-copy-out-mode.patch
Patch8: Fix-use-after-free-and-return-appropriate-error.patch
Provides: bundled(gnulib)
Provides: /bin/cpio
@ -37,7 +36,6 @@ tape, or a pipe.
%make_build
%install
rm -rf %RPM_BUILD_ROOT
%make_install
rm -rf %{buildroot}/usr/share/man/man8*
rm -rf %{buildroot}/usr/libexec/
@ -59,6 +57,15 @@ make check
%{_datadir}/man/man1/%{name}.1.gz
%changelog
* Sun Aug 23 2020 chengquan <chengquan3@huawei.com> - 2.13-1
- Update software to v2.13
* Wed Aug 12 2020 Liquor <lirui130@huawei.com> - 2.12-15
- Type:bugfix
- ID:NA
- SUG:NA
- DESC:use /etc/rmt as default rmt command
* Sat Dec 21 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.12-14
- Fix CVE-2019-14866