diff options
| -rw-r--r-- | meta/recipes-extended/cpio/cpio-2.12/CVE-2019-14866.patch | 316 | ||||
| -rw-r--r-- | meta/recipes-extended/cpio/cpio_2.12.bb | 1 |
2 files changed, 317 insertions, 0 deletions
diff --git a/meta/recipes-extended/cpio/cpio-2.12/CVE-2019-14866.patch b/meta/recipes-extended/cpio/cpio-2.12/CVE-2019-14866.patch new file mode 100644 index 0000000000..5d587fc832 --- /dev/null +++ b/meta/recipes-extended/cpio/cpio-2.12/CVE-2019-14866.patch | |||
| @@ -0,0 +1,316 @@ | |||
| 1 | CVE: CVE-2019-14866 | ||
| 2 | Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/cpio.git/commit/?id=7554e3e42cd72f6f8304410c47fe6f8918e9bfd7] | ||
| 3 | Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> | ||
| 4 | |||
| 5 | From a052401293e45a13cded5959b258204dae6d0af5 Mon Sep 17 00:00:00 2001 | ||
| 6 | From: Sergey Poznyakoff <gray@gnu.org> | ||
| 7 | Date: Sun, 3 Nov 2019 23:59:39 +0200 | ||
| 8 | Subject: [PATCH] Fix CVE-2019-14866 | ||
| 9 | |||
| 10 | * src/copyout.c (to_ascii): Additional argument nul controls whether | ||
| 11 | to add the terminating nul character. | ||
| 12 | (field_width_error): Improve diagnostics: print the actual and the | ||
| 13 | maximum allowed field value. | ||
| 14 | * src/extern.h (to_ascii, field_width_error): New prototypes. | ||
| 15 | * src/tar.c (to_oct): Remove. | ||
| 16 | (to_oct_or_error): New function. | ||
| 17 | (TO_OCT): New macro. | ||
| 18 | (write_out_tar_header): Use TO_OCT and to_ascii. Return 0 on | ||
| 19 | success, 1 on error. | ||
| 20 | --- | ||
| 21 | src/copyout.c | 49 ++++++++++++++++++++++-------------- | ||
| 22 | src/extern.h | 15 +++++++++-- | ||
| 23 | src/tar.c | 69 ++++++++++++++++++++++++--------------------------- | ||
| 24 | 3 files changed, 75 insertions(+), 58 deletions(-) | ||
| 25 | |||
| 26 | diff --git a/src/copyout.c b/src/copyout.c | ||
| 27 | index 1f0987a..1ae5477 100644 | ||
| 28 | --- a/src/copyout.c | ||
| 29 | +++ b/src/copyout.c | ||
| 30 | @@ -269,26 +269,32 @@ writeout_final_defers (int out_des) | ||
| 31 | so it should be moved to paxutils too. | ||
| 32 | Allowed values for logbase are: 1 (binary), 2, 3 (octal), 4 (hex) */ | ||
| 33 | int | ||
| 34 | -to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase) | ||
| 35 | +to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase, bool nul) | ||
| 36 | { | ||
| 37 | static char codetab[] = "0123456789ABCDEF"; | ||
| 38 | - int i = digits; | ||
| 39 | - | ||
| 40 | - do | ||
| 41 | + | ||
| 42 | + if (nul) | ||
| 43 | + where[--digits] = 0; | ||
| 44 | + while (digits > 0) | ||
| 45 | { | ||
| 46 | - where[--i] = codetab[(v & ((1 << logbase) - 1))]; | ||
| 47 | + where[--digits] = codetab[(v & ((1 << logbase) - 1))]; | ||
| 48 | v >>= logbase; | ||
| 49 | } | ||
| 50 | - while (i); | ||
| 51 | |||
| 52 | return v != 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | -static void | ||
| 56 | -field_width_error (const char *filename, const char *fieldname) | ||
| 57 | +void | ||
| 58 | +field_width_error (const char *filename, const char *fieldname, | ||
| 59 | + uintmax_t value, size_t width, bool nul) | ||
| 60 | { | ||
| 61 | - error (0, 0, _("%s: field width not sufficient for storing %s"), | ||
| 62 | - filename, fieldname); | ||
| 63 | + char valbuf[UINTMAX_STRSIZE_BOUND + 1]; | ||
| 64 | + char maxbuf[UINTMAX_STRSIZE_BOUND + 1]; | ||
| 65 | + error (0, 0, _("%s: value %s %s out of allowed range 0..%s"), | ||
| 66 | + filename, fieldname, | ||
| 67 | + STRINGIFY_BIGINT (value, valbuf), | ||
| 68 | + STRINGIFY_BIGINT (MAX_VAL_WITH_DIGITS (width - nul, LG_8), | ||
| 69 | + maxbuf)); | ||
| 70 | } | ||
| 71 | |||
| 72 | static void | ||
| 73 | @@ -303,7 +309,7 @@ to_ascii_or_warn (char *where, uintmax_t n, size_t digits, | ||
| 74 | unsigned logbase, | ||
| 75 | const char *filename, const char *fieldname) | ||
| 76 | { | ||
| 77 | - if (to_ascii (where, n, digits, logbase)) | ||
| 78 | + if (to_ascii (where, n, digits, logbase, false)) | ||
| 79 | field_width_warning (filename, fieldname); | ||
| 80 | } | ||
| 81 | |||
| 82 | @@ -312,9 +318,9 @@ to_ascii_or_error (char *where, uintmax_t n, size_t digits, | ||
| 83 | unsigned logbase, | ||
| 84 | const char *filename, const char *fieldname) | ||
| 85 | { | ||
| 86 | - if (to_ascii (where, n, digits, logbase)) | ||
| 87 | + if (to_ascii (where, n, digits, logbase, false)) | ||
| 88 | { | ||
| 89 | - field_width_error (filename, fieldname); | ||
| 90 | + field_width_error (filename, fieldname, n, digits, false); | ||
| 91 | return 1; | ||
| 92 | } | ||
| 93 | return 0; | ||
| 94 | @@ -371,7 +377,7 @@ write_out_new_ascii_header (const char *magic_string, | ||
| 95 | _("name size"))) | ||
| 96 | return 1; | ||
| 97 | p += 8; | ||
| 98 | - to_ascii (p, file_hdr->c_chksum & 0xffffffff, 8, LG_16); | ||
| 99 | + to_ascii (p, file_hdr->c_chksum & 0xffffffff, 8, LG_16, false); | ||
| 100 | |||
| 101 | tape_buffered_write (ascii_header, out_des, sizeof ascii_header); | ||
| 102 | |||
| 103 | @@ -388,7 +394,7 @@ write_out_old_ascii_header (dev_t dev, dev_t rdev, | ||
| 104 | char ascii_header[76]; | ||
| 105 | char *p = ascii_header; | ||
| 106 | |||
| 107 | - to_ascii (p, file_hdr->c_magic, 6, LG_8); | ||
| 108 | + to_ascii (p, file_hdr->c_magic, 6, LG_8, false); | ||
| 109 | p += 6; | ||
| 110 | to_ascii_or_warn (p, dev, 6, LG_8, file_hdr->c_name, _("device number")); | ||
| 111 | p += 6; | ||
| 112 | @@ -492,7 +498,10 @@ write_out_binary_header (dev_t rdev, | ||
| 113 | short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF; | ||
| 114 | if (short_hdr.c_namesize != file_hdr->c_namesize) | ||
| 115 | { | ||
| 116 | - field_width_error (file_hdr->c_name, _("name size")); | ||
| 117 | + char maxbuf[UINTMAX_STRSIZE_BOUND + 1]; | ||
| 118 | + error (0, 0, _("%s: value %s %s out of allowed range 0..%u"), | ||
| 119 | + file_hdr->c_name, _("name size"), | ||
| 120 | + STRINGIFY_BIGINT (file_hdr->c_namesize, maxbuf), 0xFFFFu); | ||
| 121 | return 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | @@ -502,7 +511,10 @@ write_out_binary_header (dev_t rdev, | ||
| 125 | if (((off_t)short_hdr.c_filesizes[0] << 16) + short_hdr.c_filesizes[1] | ||
| 126 | != file_hdr->c_filesize) | ||
| 127 | { | ||
| 128 | - field_width_error (file_hdr->c_name, _("file size")); | ||
| 129 | + char maxbuf[UINTMAX_STRSIZE_BOUND + 1]; | ||
| 130 | + error (0, 0, _("%s: value %s %s out of allowed range 0..%lu"), | ||
| 131 | + file_hdr->c_name, _("file size"), | ||
| 132 | + STRINGIFY_BIGINT (file_hdr->c_namesize, maxbuf), 0xFFFFFFFFlu); | ||
| 133 | return 1; | ||
| 134 | } | ||
| 135 | |||
| 136 | @@ -552,8 +564,7 @@ write_out_header (struct cpio_file_stat *file_hdr, int out_des) | ||
| 137 | error (0, 0, _("%s: file name too long"), file_hdr->c_name); | ||
| 138 | return 1; | ||
| 139 | } | ||
| 140 | - write_out_tar_header (file_hdr, out_des); /* FIXME: No error checking */ | ||
| 141 | - return 0; | ||
| 142 | + return write_out_tar_header (file_hdr, out_des); | ||
| 143 | |||
| 144 | case arf_binary: | ||
| 145 | return write_out_binary_header (makedev (file_hdr->c_rdev_maj, | ||
| 146 | diff --git a/src/extern.h b/src/extern.h | ||
| 147 | index e27d662..f9ef56a 100644 | ||
| 148 | --- a/src/extern.h | ||
| 149 | +++ b/src/extern.h | ||
| 150 | @@ -117,6 +117,10 @@ void print_name_with_quoting (char *p); | ||
| 151 | /* copyout.c */ | ||
| 152 | int write_out_header (struct cpio_file_stat *file_hdr, int out_des); | ||
| 153 | void process_copy_out (void); | ||
| 154 | +int to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase, | ||
| 155 | + bool nul); | ||
| 156 | +void field_width_error (const char *filename, const char *fieldname, | ||
| 157 | + uintmax_t value, size_t width, bool nul); | ||
| 158 | |||
| 159 | /* copypass.c */ | ||
| 160 | void process_copy_pass (void); | ||
| 161 | @@ -145,7 +149,7 @@ int make_path (char *argpath, uid_t owner, gid_t group, | ||
| 162 | const char *verbose_fmt_string); | ||
| 163 | |||
| 164 | /* tar.c */ | ||
| 165 | -void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des); | ||
| 166 | +int write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des); | ||
| 167 | int null_block (long *block, int size); | ||
| 168 | void read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des); | ||
| 169 | int otoa (char *s, unsigned long *n); | ||
| 170 | @@ -204,9 +208,16 @@ void cpio_safer_name_suffix (char *name, bool link_target, | ||
| 171 | int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir); | ||
| 172 | void change_dir (void); | ||
| 173 | |||
| 174 | -/* FIXME: These two defines should be defined in paxutils */ | ||
| 175 | +/* FIXME: The following three should be defined in paxutils */ | ||
| 176 | #define LG_8 3 | ||
| 177 | #define LG_16 4 | ||
| 178 | +/* The maximum uintmax_t value that can be represented with DIGITS digits, | ||
| 179 | + assuming that each digit is BITS_PER_DIGIT wide. */ | ||
| 180 | +#define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \ | ||
| 181 | + ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \ | ||
| 182 | + ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \ | ||
| 183 | + : (uintmax_t) -1) | ||
| 184 | + | ||
| 185 | |||
| 186 | uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase); | ||
| 187 | |||
| 188 | diff --git a/src/tar.c b/src/tar.c | ||
| 189 | index a2ce171..ef58027 100644 | ||
| 190 | --- a/src/tar.c | ||
| 191 | +++ b/src/tar.c | ||
| 192 | @@ -79,36 +79,17 @@ stash_tar_filename (char *prefix, char *filename) | ||
| 193 | return hold_tar_filename; | ||
| 194 | } | ||
| 195 | |||
| 196 | -/* Convert a number into a string of octal digits. | ||
| 197 | - Convert long VALUE into a DIGITS-digit field at WHERE, | ||
| 198 | - including a trailing space and room for a NUL. DIGITS==3 means | ||
| 199 | - 1 digit, a space, and room for a NUL. | ||
| 200 | - | ||
| 201 | - We assume the trailing NUL is already there and don't fill it in. | ||
| 202 | - This fact is used by start_header and finish_header, so don't change it! | ||
| 203 | - | ||
| 204 | - This is be equivalent to: | ||
| 205 | - sprintf (where, "%*lo ", digits - 2, value); | ||
| 206 | - except that sprintf fills in the trailing NUL and we don't. */ | ||
| 207 | - | ||
| 208 | -static void | ||
| 209 | -to_oct (register long value, register int digits, register char *where) | ||
| 210 | +static int | ||
| 211 | +to_oct_or_error (uintmax_t value, size_t digits, char *where, char const *field, | ||
| 212 | + char const *file) | ||
| 213 | { | ||
| 214 | - --digits; /* Leave the trailing NUL slot alone. */ | ||
| 215 | - | ||
| 216 | - /* Produce the digits -- at least one. */ | ||
| 217 | - do | ||
| 218 | + if (to_ascii (where, value, digits, LG_8, true)) | ||
| 219 | { | ||
| 220 | - where[--digits] = '0' + (char) (value & 7); /* One octal digit. */ | ||
| 221 | - value >>= 3; | ||
| 222 | + field_width_error (file, field, value, digits, true); | ||
| 223 | + return 1; | ||
| 224 | } | ||
| 225 | - while (digits > 0 && value != 0); | ||
| 226 | - | ||
| 227 | - /* Add leading zeroes, if necessary. */ | ||
| 228 | - while (digits > 0) | ||
| 229 | - where[--digits] = '0'; | ||
| 230 | + return 0; | ||
| 231 | } | ||
| 232 | - | ||
| 233 | |||
| 234 | |||
| 235 | /* Compute and return a checksum for TAR_HDR, | ||
| 236 | @@ -134,10 +115,22 @@ tar_checksum (struct tar_header *tar_hdr) | ||
| 237 | return sum; | ||
| 238 | } | ||
| 239 | |||
| 240 | +#define TO_OCT(file_hdr, c_fld, digits, tar_hdr, tar_field) \ | ||
| 241 | + do \ | ||
| 242 | + { \ | ||
| 243 | + if (to_oct_or_error (file_hdr -> c_fld, \ | ||
| 244 | + digits, \ | ||
| 245 | + tar_hdr -> tar_field, \ | ||
| 246 | + #tar_field, \ | ||
| 247 | + file_hdr->c_name)) \ | ||
| 248 | + return 1; \ | ||
| 249 | + } \ | ||
| 250 | + while (0) | ||
| 251 | + | ||
| 252 | /* Write out header FILE_HDR, including the file name, to file | ||
| 253 | descriptor OUT_DES. */ | ||
| 254 | |||
| 255 | -void | ||
| 256 | +int | ||
| 257 | write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) | ||
| 258 | { | ||
| 259 | int name_len; | ||
| 260 | @@ -166,11 +159,11 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) | ||
| 261 | |||
| 262 | /* Ustar standard (POSIX.1-1988) requires the mode to contain only 3 octal | ||
| 263 | digits */ | ||
| 264 | - to_oct (file_hdr->c_mode & MODE_ALL, 8, tar_hdr->mode); | ||
| 265 | - to_oct (file_hdr->c_uid, 8, tar_hdr->uid); | ||
| 266 | - to_oct (file_hdr->c_gid, 8, tar_hdr->gid); | ||
| 267 | - to_oct (file_hdr->c_filesize, 12, tar_hdr->size); | ||
| 268 | - to_oct (file_hdr->c_mtime, 12, tar_hdr->mtime); | ||
| 269 | + TO_OCT (file_hdr, c_mode & MODE_ALL, 8, tar_hdr, mode); | ||
| 270 | + TO_OCT (file_hdr, c_uid, 8, tar_hdr, uid); | ||
| 271 | + TO_OCT (file_hdr, c_gid, 8, tar_hdr, gid); | ||
| 272 | + TO_OCT (file_hdr, c_filesize, 12, tar_hdr, size); | ||
| 273 | + TO_OCT (file_hdr, c_mtime, 12, tar_hdr, mtime); | ||
| 274 | |||
| 275 | switch (file_hdr->c_mode & CP_IFMT) | ||
| 276 | { | ||
| 277 | @@ -182,7 +175,7 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) | ||
| 278 | strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname, | ||
| 279 | TARLINKNAMESIZE); | ||
| 280 | tar_hdr->typeflag = LNKTYPE; | ||
| 281 | - to_oct (0, 12, tar_hdr->size); | ||
| 282 | + to_ascii (tar_hdr->size, 0, 12, LG_8, true); | ||
| 283 | } | ||
| 284 | else | ||
| 285 | tar_hdr->typeflag = REGTYPE; | ||
| 286 | @@ -208,7 +201,7 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) | ||
| 287 | than TARLINKNAMESIZE. */ | ||
| 288 | strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname, | ||
| 289 | TARLINKNAMESIZE); | ||
| 290 | - to_oct (0, 12, tar_hdr->size); | ||
| 291 | + to_ascii (tar_hdr->size, 0, 12, LG_8, true); | ||
| 292 | break; | ||
| 293 | #endif /* CP_IFLNK */ | ||
| 294 | } | ||
| 295 | @@ -227,13 +220,15 @@ write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) | ||
| 296 | if (name) | ||
| 297 | strcpy (tar_hdr->gname, name); | ||
| 298 | |||
| 299 | - to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor); | ||
| 300 | - to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor); | ||
| 301 | + TO_OCT (file_hdr, c_rdev_maj, 8, tar_hdr, devmajor); | ||
| 302 | + TO_OCT (file_hdr, c_rdev_min, 8, tar_hdr, devminor); | ||
| 303 | } | ||
| 304 | |||
| 305 | - to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum); | ||
| 306 | + to_ascii (tar_hdr->chksum, tar_checksum (tar_hdr), 8, LG_8, true); | ||
| 307 | |||
| 308 | tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE); | ||
| 309 | + | ||
| 310 | + return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* Return nonzero iff all the bytes in BLOCK are NUL. | ||
| 314 | -- | ||
| 315 | 2.24.1 | ||
| 316 | |||
diff --git a/meta/recipes-extended/cpio/cpio_2.12.bb b/meta/recipes-extended/cpio/cpio_2.12.bb index 3713bf0b1f..5abe494ebc 100644 --- a/meta/recipes-extended/cpio/cpio_2.12.bb +++ b/meta/recipes-extended/cpio/cpio_2.12.bb | |||
| @@ -11,6 +11,7 @@ SRC_URI = "${GNU_MIRROR}/cpio/cpio-${PV}.tar.gz \ | |||
| 11 | file://0001-Fix-CVE-2015-1197.patch \ | 11 | file://0001-Fix-CVE-2015-1197.patch \ |
| 12 | file://0001-CVE-2016-2037-1-byte-out-of-bounds-write.patch \ | 12 | file://0001-CVE-2016-2037-1-byte-out-of-bounds-write.patch \ |
| 13 | file://0001-Fix-segfault-with-append.patch \ | 13 | file://0001-Fix-segfault-with-append.patch \ |
| 14 | file://CVE-2019-14866.patch \ | ||
| 14 | " | 15 | " |
| 15 | 16 | ||
| 16 | SRC_URI[md5sum] = "fc207561a86b63862eea4b8300313e86" | 17 | SRC_URI[md5sum] = "fc207561a86b63862eea4b8300313e86" |
