tar: add support for PAX-encoded path=LONGFILENAME

function                                             old     new   delta
get_header_tar                                      1478    1759    +281

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2012-02-23 13:45:18 +01:00
parent af36ba206f
commit 6111f967f5
4 changed files with 46 additions and 44 deletions

View File

@ -13,13 +13,13 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
int res; int res;
#if ENABLE_FEATURE_TAR_SELINUX #if ENABLE_FEATURE_TAR_SELINUX
char *sctx = archive_handle->tar__next_file_sctx; char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
if (!sctx) if (!sctx)
sctx = archive_handle->tar__global_sctx; sctx = archive_handle->tar__sctx[PAX_GLOBAL];
if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
setfscreatecon(sctx); setfscreatecon(sctx);
free(archive_handle->tar__next_file_sctx); free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
archive_handle->tar__next_file_sctx = NULL; archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
} }
#endif #endif

View File

@ -64,13 +64,13 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
file_header_t *file_header = archive_handle->file_header; file_header_t *file_header = archive_handle->file_header;
#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */ #if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
char *sctx = archive_handle->tar__next_file_sctx; char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
if (!sctx) if (!sctx)
sctx = archive_handle->tar__global_sctx; sctx = archive_handle->tar__sctx[PAX_GLOBAL];
if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
setfscreatecon(sctx); setfscreatecon(sctx);
free(archive_handle->tar__next_file_sctx); free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
archive_handle->tar__next_file_sctx = NULL; archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
} }
#endif #endif

View File

@ -90,23 +90,20 @@ static unsigned long long getOctal(char *str, int len)
} }
#define GET_OCTAL(a) getOctal((a), sizeof(a)) #define GET_OCTAL(a) getOctal((a), sizeof(a))
#if ENABLE_FEATURE_TAR_SELINUX /* "global" is 0 or 1 */
/* Scan a PAX header for SELinux contexts, via "RHT.security.selinux" keyword. static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global)
* This is what Red Hat's patched version of tar uses.
*/
# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, unsigned sz)
{ {
char *buf, *p; char *buf, *p;
char *result; unsigned blk_sz;
blk_sz = (sz + 511) & (~511);
p = buf = xmalloc(blk_sz + 1);
xread(archive_handle->src_fd, buf, blk_sz);
archive_handle->offset += blk_sz;
p = buf = xmalloc(sz + 1);
/* prevent bb_strtou from running off the buffer */ /* prevent bb_strtou from running off the buffer */
buf[sz] = '\0'; buf[sz] = '\0';
xread(archive_handle->src_fd, buf, sz);
archive_handle->offset += sz;
result = NULL;
while (sz != 0) { while (sz != 0) {
char *end, *value; char *end, *value;
unsigned len; unsigned len;
@ -133,19 +130,33 @@ static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, uns
* (we do not bother to check that it *was* a newline) * (we do not bother to check that it *was* a newline)
*/ */
p[-1] = '\0'; p[-1] = '\0';
/* Is it selinux security context? */
value = end + 1; value = end + 1;
#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) {
value += sizeof("path=") - 1;
free(archive_handle->tar__longname);
archive_handle->tar__longname = xstrdup(value);
continue;
}
#endif
#if ENABLE_FEATURE_TAR_SELINUX
/* Scan for SELinux contexts, via "RHT.security.selinux" keyword.
* This is what Red Hat's patched version of tar uses.
*/
# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) { if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {
value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
result = xstrdup(value); free(archive_handle->tar__sctx[global]);
break; archive_handle->tar__sctx[global] = xstrdup(value);
continue;
} }
#endif
} }
free(buf); free(buf);
return result;
} }
#endif
char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
{ {
@ -418,12 +429,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
case 'S': /* Sparse file */ case 'S': /* Sparse file */
case 'V': /* Volume header */ case 'V': /* Volume header */
#endif #endif
#if !ENABLE_FEATURE_TAR_SELINUX
case 'g': /* pax global header */ case 'g': /* pax global header */
case 'x': /* pax extended header */ case 'x': { /* pax extended header */
#else if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
goto skip_ext_hdr;
process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
goto again_after_align;
}
skip_ext_hdr: skip_ext_hdr:
#endif
{ {
off_t sz; off_t sz;
bb_error_msg("warning: skipping header '%c'", tar.typeflag); bb_error_msg("warning: skipping header '%c'", tar.typeflag);
@ -435,18 +448,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
/* return get_header_tar(archive_handle); */ /* return get_header_tar(archive_handle); */
goto again_after_align; goto again_after_align;
} }
#if ENABLE_FEATURE_TAR_SELINUX
case 'g': /* pax global header */
case 'x': { /* pax extended header */
char **pp;
if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
goto skip_ext_hdr;
pp = (tar.typeflag == 'g') ? &archive_handle->tar__global_sctx : &archive_handle->tar__next_file_sctx;
free(*pp);
*pp = get_selinux_sctx_from_pax_hdr(archive_handle, file_header->size);
goto again;
}
#endif
default: default:
bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag); bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
} }

View File

@ -77,19 +77,20 @@ typedef struct archive_handle_t {
off_t offset; off_t offset;
/* Archiver specific. Can make it a union if it ever gets big */ /* Archiver specific. Can make it a union if it ever gets big */
#define PAX_NEXT_FILE 0
#define PAX_GLOBAL 1
#if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB #if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB
smallint tar__end; smallint tar__end;
# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS # if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
char* tar__longname; char* tar__longname;
char* tar__linkname; char* tar__linkname;
# endif # endif
#if ENABLE_FEATURE_TAR_TO_COMMAND # if ENABLE_FEATURE_TAR_TO_COMMAND
char* tar__to_command; char* tar__to_command;
const char* tar__to_command_shell; const char* tar__to_command_shell;
#endif # endif
# if ENABLE_FEATURE_TAR_SELINUX # if ENABLE_FEATURE_TAR_SELINUX
char* tar__global_sctx; char* tar__sctx[2];
char* tar__next_file_sctx;
# endif # endif
#endif #endif
#if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM #if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM