Bump to libarch 3.3.1 01/134901/1 tizen
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 20 Jun 2017 08:16:11 +0000 (17:16 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 20 Jun 2017 08:20:23 +0000 (17:20 +0900)
[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 <dh0128.kwak@samsung.com>
libarchive/archive_write_disk_posix.c
packaging/libarchive.spec

index 9c000fb..5a01e84 100644 (file)
@@ -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;
index 6381083..bdd010c 100644 (file)
@@ -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