Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/archival/libarchive/get_header_tar.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/archival/libarchive/get_header_tar.c
r3232 r3621 17 17 typedef uint32_t aliased_uint32_t FIX_ALIASING; 18 18 typedef off_t aliased_off_t FIX_ALIASING; 19 20 21 const char* FAST_FUNC strip_unsafe_prefix(const char *str)22 {23 const char *cp = str;24 while (1) {25 char *cp2;26 if (*cp == '/') {27 cp++;28 continue;29 }30 if (strncmp(cp, "/../"+1, 3) == 0) {31 cp += 3;32 continue;33 }34 cp2 = strstr(cp, "/../");35 if (!cp2)36 break;37 cp = cp2 + 4;38 }39 if (cp != str) {40 static smallint warned = 0;41 if (!warned) {42 warned = 1;43 bb_error_msg("removing leading '%.*s' from member names",44 (int)(cp - str), str);45 }46 }47 return cp;48 }49 19 50 20 /* NB: _DESTROYS_ str[len] character! */ … … 91 61 #define GET_OCTAL(a) getOctal((a), sizeof(a)) 92 62 63 #define TAR_EXTD (ENABLE_FEATURE_TAR_GNU_EXTENSIONS || ENABLE_FEATURE_TAR_SELINUX) 64 #if !TAR_EXTD 65 #define process_pax_hdr(archive_handle, sz, global) \ 66 process_pax_hdr(archive_handle, sz) 67 #endif 93 68 /* "global" is 0 or 1 */ 94 69 static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global) 95 70 { 71 #if !TAR_EXTD 72 unsigned blk_sz = (sz + 511) & (~511); 73 seek_by_read(archive_handle->src_fd, blk_sz); 74 #else 75 unsigned blk_sz = (sz + 511) & (~511); 96 76 char *buf, *p; 97 unsigned blk_sz; 98 99 blk_sz = (sz + 511) & (~511); 77 100 78 p = buf = xmalloc(blk_sz + 1); 101 79 xread(archive_handle->src_fd, buf, blk_sz); … … 116 94 p += len; 117 95 sz -= len; 118 if ((int)sz < 0 96 if ( 97 /** (int)sz < 0 - not good enough for huge malicious VALUE of 2^32-1 */ 98 (int)(sz|len) < 0 /* this works */ 119 99 || len == 0 120 100 || errno != EINVAL … … 133 113 value = end + 1; 134 114 135 # if ENABLE_FEATURE_TAR_GNU_EXTENSIONS136 if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) {115 # if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 116 if (!global && is_prefixed_with(value, "path=")) { 137 117 value += sizeof("path=") - 1; 138 118 free(archive_handle->tar__longname); … … 140 120 continue; 141 121 } 142 # endif143 144 # if ENABLE_FEATURE_TAR_SELINUX122 # endif 123 124 # if ENABLE_FEATURE_TAR_SELINUX 145 125 /* Scan for SELinux contexts, via "RHT.security.selinux" keyword. 146 126 * This is what Red Hat's patched version of tar uses. 147 127 */ 148 # define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"149 if ( strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {128 # define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux" 129 if (is_prefixed_with(value, SELINUX_CONTEXT_KEYWORD"=")) { 150 130 value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; 151 131 free(archive_handle->tar__sctx[global]); … … 153 133 continue; 154 134 } 155 # endif135 # endif 156 136 } 157 137 158 138 free(buf); 139 #endif 159 140 } 160 141 … … 199 180 * saw zero block directly before this. */ 200 181 if (i == 0) { 201 xfunc_error_retval = 0;202 short_read: 203 bb_error_msg_and_die("short read");182 bb_error_msg("short read"); 183 /* this merely signals end of archive, not exit(1): */ 184 return EXIT_FAILURE; 204 185 } 205 186 if (i != 512) { 206 187 IF_FEATURE_TAR_AUTODETECT(goto autodetect;) 207 goto short_read;188 bb_error_msg_and_die("short read"); 208 189 } 209 190 … … 222 203 while (full_read(archive_handle->src_fd, &tar, 512) == 512) 223 204 continue; 224 return EXIT_FAILURE; 205 return EXIT_FAILURE; /* "end of archive" */ 225 206 } 226 207 archive_handle->tar__end = 1; 227 return EXIT_SUCCESS; 208 return EXIT_SUCCESS; /* "decoded one header" */ 228 209 } 229 210 archive_handle->tar__end = 0; … … 231 212 /* Check header has valid magic, "ustar" is for the proper tar, 232 213 * five NULs are for the old tar format */ 233 if ( strncmp(tar.magic, "ustar", 5) != 0214 if (!is_prefixed_with(tar.magic, "ustar") 234 215 && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY 235 216 || memcmp(tar.magic, "\0\0\0\0", 5) != 0) … … 242 223 if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0) 243 224 goto err; 244 if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_ detected:*/ 0) != 0)225 if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_compressed:*/ 0) != 0) 245 226 err: 246 227 bb_error_msg_and_die("invalid tar magic"); … … 379 360 file_header->mode |= S_IFIFO; 380 361 goto size0; 362 case 'g': /* pax global header */ 363 case 'x': { /* pax extended header */ 364 if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ 365 goto skip_ext_hdr; 366 process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g')); 367 goto again_after_align; 381 368 #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 369 /* See http://www.gnu.org/software/tar/manual/html_node/Extensions.html */ 382 370 case 'L': 383 371 /* free: paranoia: tar with several consecutive longnames */ … … 399 387 /* return get_header_tar(archive_handle); */ 400 388 goto again; 401 case 'D': /* GNU dump dir */ 402 case 'M': /* Continuation of multi volume archive */ 403 case 'N': /* Old GNU for names > 100 characters */ 404 case 'S': /* Sparse file */ 405 case 'V': /* Volume header */ 406 #endif 407 case 'g': /* pax global header */ 408 case 'x': { /* pax extended header */ 409 if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ 410 goto skip_ext_hdr; 411 process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g')); 412 goto again_after_align; 389 /* 390 * case 'S': // Sparse file 391 * Was seen in the wild. Not supported (yet?). 392 * See https://www.gnu.org/software/tar/manual/html_section/tar_92.html 393 * for the format. (An "Old GNU Format" was seen, not PAX formats). 394 */ 395 // case 'D': /* GNU dump dir */ 396 // case 'M': /* Continuation of multi volume archive */ 397 // case 'N': /* Old GNU for names > 100 characters */ 398 // case 'V': /* Volume header */ 399 #endif 413 400 } 414 401 skip_ext_hdr: … … 441 428 /* Everything up to and including last ".." component is stripped */ 442 429 overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name)); 430 //TODO: do the same for file_header->link_target? 443 431 444 432 /* Strip trailing '/' in directories */ … … 472 460 free(file_header->tar__gname); 473 461 #endif 474 return EXIT_SUCCESS; 462 return EXIT_SUCCESS; /* "decoded one header" */ 475 463 }
Note:
See TracChangeset
for help on using the changeset viewer.