From 47863ccacd728e627ffc777d5881c4311e767e86 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Tue, 20 Jun 2017 17:16:11 +0900 Subject: [PATCH] Bump to libarch 3.3.1 [Model] All [BinType] AP [Customer] OPEN [Issue#] N/A [Request] N/A [Occurrence Version] N/A [Problem] version upgrade [Cause & Measure] version upgrade [Checking Method] N/A [Team] Open Source Management and Setting Part [Developer] dh0128.kwak [Solution company] Samsung [Change Type] N/A Change-Id: I25fbc6d21306b2bbd617be25f850a7a2f30d9aa7 Signed-off-by: DongHun Kwak --- libarchive/archive_write_disk_posix.c | 223 +++++++++++++++++++--------------- packaging/libarchive.spec | 2 +- 2 files changed, 129 insertions(+), 96 deletions(-) diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index 9c000fb..5a01e84 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -348,7 +348,10 @@ struct archive_write_disk { #define HFS_BLOCKS(s) ((s) >> 12) -static int check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags); +static void fsobj_error(int *, struct archive_string *, int, const char *, + const char *); +static int check_symlinks_fsobj(char *, int *, struct archive_string *, + int); static int check_symlinks(struct archive_write_disk *); static int create_filesystem_object(struct archive_write_disk *); static struct fixup_entry *current_fixup(struct archive_write_disk *, @@ -356,7 +359,8 @@ static struct fixup_entry *current_fixup(struct archive_write_disk *, #if defined(HAVE_FCHDIR) && defined(PATH_MAX) static void edit_deep_directories(struct archive_write_disk *ad); #endif -static int cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags); +static int cleanup_pathname_fsobj(char *, int *, struct archive_string *, + int); static int cleanup_pathname(struct archive_write_disk *); static int create_dir(struct archive_write_disk *, char *); static int create_parent_dir(struct archive_write_disk *, char *); @@ -2064,6 +2068,7 @@ create_filesystem_object(struct archive_write_disk *a) int r; /* these for check_symlinks_fsobj */ char *linkname_copy; /* non-const copy of linkname */ + struct stat st; struct archive_string error_string; int error_number; @@ -2079,22 +2084,38 @@ create_filesystem_object(struct archive_write_disk *a) if (linkname_copy == NULL) { return (EPERM); } - /* TODO: consider using the cleaned-up path as the link target? */ - r = cleanup_pathname_fsobj(linkname_copy, &error_number, &error_string, a->flags); + /* + * TODO: consider using the cleaned-up path as the link + * target? + */ + r = cleanup_pathname_fsobj(linkname_copy, &error_number, + &error_string, a->flags); if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, error_number, "%s", error_string.s); + archive_set_error(&a->archive, error_number, "%s", + error_string.s); free(linkname_copy); - /* EPERM is more appropriate than error_number for our callers */ + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ return (EPERM); } - r = check_symlinks_fsobj(linkname_copy, &error_number, &error_string, a->flags); + r = check_symlinks_fsobj(linkname_copy, &error_number, + &error_string, a->flags); if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, error_number, "%s", error_string.s); + archive_set_error(&a->archive, error_number, "%s", + error_string.s); free(linkname_copy); - /* EPERM is more appropriate than error_number for our callers */ + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ return (EPERM); } free(linkname_copy); + archive_string_free(&error_string); r = link(linkname, a->name) ? errno : 0; /* * New cpio and pax formats allow hardlink entries @@ -2461,11 +2482,11 @@ fsobj_error(int *a_eno, struct archive_string *a_estr, * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. */ static int -check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags) +check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) { #if !defined(HAVE_LSTAT) /* Platform doesn't have lstat, so we can't look for symlinks. */ - (void)a; /* UNUSED */ (void)path; /* UNUSED */ (void)error_number; /* UNUSED */ (void)error_string; /* UNUSED */ @@ -2495,7 +2516,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error * - if it's a directory and it's not the last chunk, cd into it * As we go: * head points to the current (relative) path - * tail points to the temporary \0 terminating the segment we're currently examining + * tail points to the temporary \0 terminating the segment we're + * currently examining * c holds what used to be in *tail * last is 1 if this is the last tail */ @@ -2517,7 +2539,9 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error * Exiting the loop with break is okay; continue is not. */ while (!last) { - /* Skip the separator we just consumed, plus any adjacent ones */ + /* + * Skip the separator we just consumed, plus any adjacent ones + */ while (*tail == '/') ++tail; /* Skip the next path element. */ @@ -2536,19 +2560,20 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error if (errno == ENOENT) { break; } else { - /* Treat any other error as fatal - best to be paranoid here - * Note: This effectively disables deep directory - * support when security checks are enabled. - * Otherwise, very long pathnames that trigger - * an error here could evade the sandbox. - * TODO: We could do better, but it would probably - * require merging the symlink checks with the - * deep-directory editing. */ - if (error_number) *error_number = errno; - if (error_string) - archive_string_sprintf(error_string, - "Could not stat %s", - path); + /* + * Treat any other error as fatal - best to be + * paranoid here. + * Note: This effectively disables deep + * directory support when security checks are + * enabled. Otherwise, very long pathnames that + * trigger an error here could evade the + * sandbox. + * TODO: We could do better, but it would + * probably require merging the symlink checks + * with the deep-directory editing. + */ + fsobj_error(a_eno, a_estr, errno, + "Could not stat %s", path); res = ARCHIVE_FAILED; break; } @@ -2556,11 +2581,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error if (!last) { if (chdir(head) != 0) { tail[0] = c; - if (error_number) *error_number = errno; - if (error_string) - archive_string_sprintf(error_string, - "Could not chdir %s", - path); + fsobj_error(a_eno, a_estr, errno, + "Could not chdir %s", path); res = (ARCHIVE_FATAL); break; } @@ -2576,11 +2598,9 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error */ if (unlink(head)) { tail[0] = c; - if (error_number) *error_number = errno; - if (error_string) - archive_string_sprintf(error_string, - "Could not remove symlink %s", - path); + fsobj_error(a_eno, a_estr, errno, + "Could not remove symlink %s", + path); res = ARCHIVE_FAILED; break; } @@ -2591,13 +2611,14 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error * symlink with another symlink. */ tail[0] = c; - /* FIXME: not sure how important this is to restore + /* + * FIXME: not sure how important this is to + * restore + */ + /* if (!S_ISLNK(path)) { - if (error_number) *error_number = 0; - if (error_string) - archive_string_sprintf(error_string, - "Removing symlink %s", - path); + fsobj_error(a_eno, a_estr, 0, + "Removing symlink %s", path); } */ /* Symlink gone. No more problem! */ @@ -2607,22 +2628,60 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error /* User asked us to remove problems. */ if (unlink(head) != 0) { tail[0] = c; - if (error_number) *error_number = 0; - if (error_string) - archive_string_sprintf(error_string, - "Cannot remove intervening symlink %s", - path); + fsobj_error(a_eno, a_estr, 0, + "Cannot remove intervening " + "symlink %s", path); res = ARCHIVE_FAILED; break; } tail[0] = c; + } else if ((flags & + ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { + /* + * We are not the last element and we want to + * follow symlinks if they are a directory. + * + * This is needed to extract hardlinks over + * symlinks. + */ + r = stat(head, &st); + if (r != 0) { + tail[0] = c; + if (errno == ENOENT) { + break; + } else { + fsobj_error(a_eno, a_estr, + errno, + "Could not stat %s", path); + res = (ARCHIVE_FAILED); + break; + } + } else if (S_ISDIR(st.st_mode)) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, + errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* + * Our view is now from inside + * this dir: + */ + head = tail + 1; + } else { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through " + "symlink %s", path); + res = ARCHIVE_FAILED; + break; + } } else { tail[0] = c; - if (error_number) *error_number = 0; - if (error_string) - archive_string_sprintf(error_string, - "Cannot extract through symlink %s", - path); + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through symlink %s", path); res = ARCHIVE_FAILED; break; } @@ -2639,10 +2698,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error if (restore_pwd >= 0) { r = fchdir(restore_pwd); if (r != 0) { - if(error_number) *error_number = errno; - if(error_string) - archive_string_sprintf(error_string, - "chdir() failure"); + fsobj_error(a_eno, a_estr, errno, + "chdir() failure", ""); } close(restore_pwd); restore_pwd = -1; @@ -2654,9 +2711,6 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error /* TODO: reintroduce a safe cache here? */ return res; #endif - /* TODO: reintroduce a safe cache here? */ - return res; -#endif } /* @@ -2681,26 +2735,6 @@ check_symlinks(struct archive_write_disk *a) return rc; } -/* - * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise - * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED} - */ -static int -check_symlinks(struct archive_write_disk *a) -{ - struct archive_string error_string; - int error_number; - int rc; - archive_string_init(&error_string); - rc = check_symlinks_fsobj(a->name, &error_number, &error_string, a->flags); - if (rc != ARCHIVE_OK) { - archive_set_error(&a->archive, error_number, "%s", error_string.s); - } - archive_string_free(&error_string); - a->pst = NULL; /* to be safe */ - return rc; -} - #if defined(__CYGWIN__) /* @@ -2775,17 +2809,16 @@ cleanup_pathname_win(char *path) * is set) if the path is absolute. */ static int -cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags) +cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) { char *dest, *src; char separator = '\0'; dest = src = path; if (*src == '\0') { - if (error_number) *error_number = ARCHIVE_ERRNO_MISC; - if (error_string) - archive_string_sprintf(error_string, - "Invalid empty pathname"); + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Invalid empty ", "pathname"); return (ARCHIVE_FAILED); } @@ -2795,10 +2828,8 @@ cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *err /* Skip leading '/'. */ if (*src == '/') { if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { - if (error_number) *error_number = ARCHIVE_ERRNO_MISC; - if (error_string) - archive_string_sprintf(error_string, - "Path is absolute"); + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Path is ", "absolute"); return (ARCHIVE_FAILED); } @@ -2825,11 +2856,11 @@ cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *err } else if (src[1] == '.') { if (src[2] == '/' || src[2] == '\0') { /* Conditionally warn about '..' */ - if (flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { - if (error_number) *error_number = ARCHIVE_ERRNO_MISC; - if (error_string) - archive_string_sprintf(error_string, - "Path contains '..'"); + if (flags + & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { + fsobj_error(a_eno, a_estr, + ARCHIVE_ERRNO_MISC, + "Path contains ", "'..'"); return (ARCHIVE_FAILED); } } @@ -2882,9 +2913,11 @@ cleanup_pathname(struct archive_write_disk *a) int error_number; int rc; archive_string_init(&error_string); - rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, a->flags); + rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, + a->flags); if (rc != ARCHIVE_OK) { - archive_set_error(&a->archive, error_number, "%s", error_string.s); + archive_set_error(&a->archive, error_number, "%s", + error_string.s); } archive_string_free(&error_string); return rc; diff --git a/packaging/libarchive.spec b/packaging/libarchive.spec index 6381083..bdd010c 100644 --- a/packaging/libarchive.spec +++ b/packaging/libarchive.spec @@ -1,5 +1,5 @@ Name: libarchive -Version: 3.2.1 +Version: 3.3.1 Release: 0 License: BSD-2-Clause Summary: A library for handling streaming archive formats -- 2.7.4