diff options
3 files changed, 367 insertions, 0 deletions
diff --git a/meta/recipes-extended/libarchive/files/0001-archive_write_disk_posix.c-make-_fsobj-functions-mor.patch b/meta/recipes-extended/libarchive/files/0001-archive_write_disk_posix.c-make-_fsobj-functions-mor.patch new file mode 100644 index 0000000000..e911a7c1f2 --- /dev/null +++ b/meta/recipes-extended/libarchive/files/0001-archive_write_disk_posix.c-make-_fsobj-functions-mor.patch | |||
| @@ -0,0 +1,245 @@ | |||
| 1 | From 90881d24d3f6d5fb207e97df3b91bbea8598e84e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Martin Matuska <martin@matuska.org> | ||
| 3 | Date: Tue, 29 Nov 2016 16:47:37 +0100 | ||
| 4 | Subject: [PATCH 1/2] archive_write_disk_posix.c: make *_fsobj functions more | ||
| 5 | readable | ||
| 6 | |||
| 7 | Upstream-Status: Backported | ||
| 8 | |||
| 9 | Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com> | ||
| 10 | --- | ||
| 11 | libarchive/archive_write_disk_posix.c | 121 +++++++++++++++++----------------- | ||
| 12 | 1 file changed, 61 insertions(+), 60 deletions(-) | ||
| 13 | |||
| 14 | diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c | ||
| 15 | index 17c23b0..d786bc2 100644 | ||
| 16 | --- a/libarchive/archive_write_disk_posix.c | ||
| 17 | +++ b/libarchive/archive_write_disk_posix.c | ||
| 18 | @@ -336,6 +336,8 @@ struct archive_write_disk { | ||
| 19 | |||
| 20 | #define HFS_BLOCKS(s) ((s) >> 12) | ||
| 21 | |||
| 22 | +static void fsobj_error(int *, struct archive_string *, int, const char *, | ||
| 23 | + const char *); | ||
| 24 | static int check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags); | ||
| 25 | static int check_symlinks(struct archive_write_disk *); | ||
| 26 | static int create_filesystem_object(struct archive_write_disk *); | ||
| 27 | @@ -2005,8 +2007,9 @@ restore_entry(struct archive_write_disk *a) | ||
| 28 | |||
| 29 | if (en) { | ||
| 30 | /* Everything failed; give up here. */ | ||
| 31 | - archive_set_error(&a->archive, en, "Can't create '%s'", | ||
| 32 | - a->name); | ||
| 33 | + if ((&a->archive)->error == NULL) | ||
| 34 | + archive_set_error(&a->archive, en, "Can't create '%s'", | ||
| 35 | + a->name); | ||
| 36 | return (ARCHIVE_FAILED); | ||
| 37 | } | ||
| 38 | |||
| 39 | @@ -2388,6 +2391,17 @@ current_fixup(struct archive_write_disk *a, const char *pathname) | ||
| 40 | return (a->current_fixup); | ||
| 41 | } | ||
| 42 | |||
| 43 | +/* Error helper for new *_fsobj functions */ | ||
| 44 | +static void | ||
| 45 | +fsobj_error(int *a_eno, struct archive_string *a_estr, | ||
| 46 | + int err, const char *errstr, const char *path) | ||
| 47 | +{ | ||
| 48 | + if (a_eno) | ||
| 49 | + *a_eno = err; | ||
| 50 | + if (a_estr) | ||
| 51 | + archive_string_sprintf(a_estr, errstr, path); | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | /* | ||
| 55 | * TODO: Someday, integrate this with the deep dir support; they both | ||
| 56 | * scan the path and both can be optimized by comparing against other | ||
| 57 | @@ -2400,7 +2414,7 @@ current_fixup(struct archive_write_disk *a, const char *pathname) | ||
| 58 | * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. | ||
| 59 | */ | ||
| 60 | static int | ||
| 61 | -check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags) | ||
| 62 | +check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, int flags) | ||
| 63 | { | ||
| 64 | #if !defined(HAVE_LSTAT) | ||
| 65 | /* Platform doesn't have lstat, so we can't look for symlinks. */ | ||
| 66 | @@ -2474,19 +2488,20 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error | ||
| 67 | if (errno == ENOENT) { | ||
| 68 | break; | ||
| 69 | } else { | ||
| 70 | - /* Treat any other error as fatal - best to be paranoid here | ||
| 71 | - * Note: This effectively disables deep directory | ||
| 72 | - * support when security checks are enabled. | ||
| 73 | - * Otherwise, very long pathnames that trigger | ||
| 74 | - * an error here could evade the sandbox. | ||
| 75 | - * TODO: We could do better, but it would probably | ||
| 76 | - * require merging the symlink checks with the | ||
| 77 | - * deep-directory editing. */ | ||
| 78 | - if (error_number) *error_number = errno; | ||
| 79 | - if (error_string) | ||
| 80 | - archive_string_sprintf(error_string, | ||
| 81 | - "Could not stat %s", | ||
| 82 | - path); | ||
| 83 | + /* | ||
| 84 | + * Treat any other error as fatal - best to be | ||
| 85 | + * paranoid here. | ||
| 86 | + * Note: This effectively disables deep | ||
| 87 | + * directory support when security checks are | ||
| 88 | + * enabled. Otherwise, very long pathnames that | ||
| 89 | + * trigger an error here could evade the | ||
| 90 | + * sandbox. | ||
| 91 | + * TODO: We could do better, but it would | ||
| 92 | + * probably require merging the symlink checks | ||
| 93 | + * with the deep-directory editing. | ||
| 94 | + */ | ||
| 95 | + fsobj_error(a_eno, a_estr, errno, | ||
| 96 | + "Could not stat %s", path); | ||
| 97 | res = ARCHIVE_FAILED; | ||
| 98 | break; | ||
| 99 | } | ||
| 100 | @@ -2494,11 +2509,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error | ||
| 101 | if (!last) { | ||
| 102 | if (chdir(head) != 0) { | ||
| 103 | tail[0] = c; | ||
| 104 | - if (error_number) *error_number = errno; | ||
| 105 | - if (error_string) | ||
| 106 | - archive_string_sprintf(error_string, | ||
| 107 | - "Could not chdir %s", | ||
| 108 | - path); | ||
| 109 | + fsobj_error(a_eno, a_estr, errno, | ||
| 110 | + "Could not chdir %s", path); | ||
| 111 | res = (ARCHIVE_FATAL); | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | @@ -2514,11 +2526,9 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error | ||
| 115 | */ | ||
| 116 | if (unlink(head)) { | ||
| 117 | tail[0] = c; | ||
| 118 | - if (error_number) *error_number = errno; | ||
| 119 | - if (error_string) | ||
| 120 | - archive_string_sprintf(error_string, | ||
| 121 | - "Could not remove symlink %s", | ||
| 122 | - path); | ||
| 123 | + fsobj_error(a_eno, a_estr, errno, | ||
| 124 | + "Could not remove symlink %s", | ||
| 125 | + path); | ||
| 126 | res = ARCHIVE_FAILED; | ||
| 127 | break; | ||
| 128 | } | ||
| 129 | @@ -2529,13 +2539,14 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error | ||
| 130 | * symlink with another symlink. | ||
| 131 | */ | ||
| 132 | tail[0] = c; | ||
| 133 | - /* FIXME: not sure how important this is to restore | ||
| 134 | + /* | ||
| 135 | + * FIXME: not sure how important this is to | ||
| 136 | + * restore | ||
| 137 | + */ | ||
| 138 | + /* | ||
| 139 | if (!S_ISLNK(path)) { | ||
| 140 | - if (error_number) *error_number = 0; | ||
| 141 | - if (error_string) | ||
| 142 | - archive_string_sprintf(error_string, | ||
| 143 | - "Removing symlink %s", | ||
| 144 | - path); | ||
| 145 | + fsobj_error(a_eno, a_estr, 0, | ||
| 146 | + "Removing symlink %s", path); | ||
| 147 | } | ||
| 148 | */ | ||
| 149 | /* Symlink gone. No more problem! */ | ||
| 150 | @@ -2545,22 +2556,17 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error | ||
| 151 | /* User asked us to remove problems. */ | ||
| 152 | if (unlink(head) != 0) { | ||
| 153 | tail[0] = c; | ||
| 154 | - if (error_number) *error_number = 0; | ||
| 155 | - if (error_string) | ||
| 156 | - archive_string_sprintf(error_string, | ||
| 157 | - "Cannot remove intervening symlink %s", | ||
| 158 | - path); | ||
| 159 | + fsobj_error(a_eno, a_estr, 0, | ||
| 160 | + "Cannot remove intervening " | ||
| 161 | + "symlink %s", path); | ||
| 162 | res = ARCHIVE_FAILED; | ||
| 163 | break; | ||
| 164 | } | ||
| 165 | tail[0] = c; | ||
| 166 | } else { | ||
| 167 | tail[0] = c; | ||
| 168 | - if (error_number) *error_number = 0; | ||
| 169 | - if (error_string) | ||
| 170 | - archive_string_sprintf(error_string, | ||
| 171 | - "Cannot extract through symlink %s", | ||
| 172 | - path); | ||
| 173 | + fsobj_error(a_eno, a_estr, 0, | ||
| 174 | + "Cannot extract through symlink %s", path); | ||
| 175 | res = ARCHIVE_FAILED; | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | @@ -2577,10 +2583,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error | ||
| 179 | if (restore_pwd >= 0) { | ||
| 180 | r = fchdir(restore_pwd); | ||
| 181 | if (r != 0) { | ||
| 182 | - if(error_number) *error_number = errno; | ||
| 183 | - if(error_string) | ||
| 184 | - archive_string_sprintf(error_string, | ||
| 185 | - "chdir() failure"); | ||
| 186 | + fsobj_error(a_eno, a_estr, errno, | ||
| 187 | + "chdir() failure", ""); | ||
| 188 | } | ||
| 189 | close(restore_pwd); | ||
| 190 | restore_pwd = -1; | ||
| 191 | @@ -2688,17 +2692,16 @@ cleanup_pathname_win(struct archive_write_disk *a) | ||
| 192 | * is set) if the path is absolute. | ||
| 193 | */ | ||
| 194 | static int | ||
| 195 | -cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags) | ||
| 196 | +cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr, | ||
| 197 | + int flags) | ||
| 198 | { | ||
| 199 | char *dest, *src; | ||
| 200 | char separator = '\0'; | ||
| 201 | |||
| 202 | dest = src = path; | ||
| 203 | if (*src == '\0') { | ||
| 204 | - if (error_number) *error_number = ARCHIVE_ERRNO_MISC; | ||
| 205 | - if (error_string) | ||
| 206 | - archive_string_sprintf(error_string, | ||
| 207 | - "Invalid empty pathname"); | ||
| 208 | + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, | ||
| 209 | + "Invalid empty ", "pathname"); | ||
| 210 | return (ARCHIVE_FAILED); | ||
| 211 | } | ||
| 212 | |||
| 213 | @@ -2708,10 +2711,8 @@ cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *err | ||
| 214 | /* Skip leading '/'. */ | ||
| 215 | if (*src == '/') { | ||
| 216 | if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { | ||
| 217 | - if (error_number) *error_number = ARCHIVE_ERRNO_MISC; | ||
| 218 | - if (error_string) | ||
| 219 | - archive_string_sprintf(error_string, | ||
| 220 | - "Path is absolute"); | ||
| 221 | + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, | ||
| 222 | + "Path is ", "absolute"); | ||
| 223 | return (ARCHIVE_FAILED); | ||
| 224 | } | ||
| 225 | |||
| 226 | @@ -2738,11 +2739,11 @@ cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *err | ||
| 227 | } else if (src[1] == '.') { | ||
| 228 | if (src[2] == '/' || src[2] == '\0') { | ||
| 229 | /* Conditionally warn about '..' */ | ||
| 230 | - if (flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { | ||
| 231 | - if (error_number) *error_number = ARCHIVE_ERRNO_MISC; | ||
| 232 | - if (error_string) | ||
| 233 | - archive_string_sprintf(error_string, | ||
| 234 | - "Path contains '..'"); | ||
| 235 | + if (flags | ||
| 236 | + & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { | ||
| 237 | + fsobj_error(a_eno, a_estr, | ||
| 238 | + ARCHIVE_ERRNO_MISC, | ||
| 239 | + "Path contains ", "'..'"); | ||
| 240 | return (ARCHIVE_FAILED); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | -- | ||
| 244 | 2.7.4 | ||
| 245 | |||
diff --git a/meta/recipes-extended/libarchive/files/0002-Fix-extracting-hardlinks-over-symlinks.patch b/meta/recipes-extended/libarchive/files/0002-Fix-extracting-hardlinks-over-symlinks.patch new file mode 100644 index 0000000000..37418632f3 --- /dev/null +++ b/meta/recipes-extended/libarchive/files/0002-Fix-extracting-hardlinks-over-symlinks.patch | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | From ece28103885a079a129a23c5001252a1648517af Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Martin Matuska <martin@matuska.org> | ||
| 3 | Date: Tue, 29 Nov 2016 16:55:41 +0100 | ||
| 4 | Subject: [PATCH 2/2] Fix extracting hardlinks over symlinks | ||
| 5 | |||
| 6 | Closes #821 | ||
| 7 | |||
| 8 | Upstream-Status: Backported | ||
| 9 | |||
| 10 | Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com> | ||
| 11 | --- | ||
| 12 | libarchive/archive_write_disk_posix.c | 43 +++++++++++++++++++++++++++++++++++ | ||
| 13 | tar/test/test_symlink_dir.c | 18 ++++++++++++++- | ||
| 14 | 2 files changed, 60 insertions(+), 1 deletion(-) | ||
| 15 | |||
| 16 | diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c | ||
| 17 | index d786bc2..80b03cd 100644 | ||
| 18 | --- a/libarchive/archive_write_disk_posix.c | ||
| 19 | +++ b/libarchive/archive_write_disk_posix.c | ||
| 20 | @@ -2563,6 +2563,49 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, int | ||
| 21 | break; | ||
| 22 | } | ||
| 23 | tail[0] = c; | ||
| 24 | + } else if ((flags & | ||
| 25 | + ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { | ||
| 26 | + /* | ||
| 27 | + * We are not the last element and we want to | ||
| 28 | + * follow symlinks if they are a directory. | ||
| 29 | + * | ||
| 30 | + * This is needed to extract hardlinks over | ||
| 31 | + * symlinks. | ||
| 32 | + */ | ||
| 33 | + r = stat(head, &st); | ||
| 34 | + if (r != 0) { | ||
| 35 | + tail[0] = c; | ||
| 36 | + if (errno == ENOENT) { | ||
| 37 | + break; | ||
| 38 | + } else { | ||
| 39 | + fsobj_error(a_eno, a_estr, | ||
| 40 | + errno, | ||
| 41 | + "Could not stat %s", path); | ||
| 42 | + res = (ARCHIVE_FAILED); | ||
| 43 | + break; | ||
| 44 | + } | ||
| 45 | + } else if (S_ISDIR(st.st_mode)) { | ||
| 46 | + if (chdir(head) != 0) { | ||
| 47 | + tail[0] = c; | ||
| 48 | + fsobj_error(a_eno, a_estr, | ||
| 49 | + errno, | ||
| 50 | + "Could not chdir %s", path); | ||
| 51 | + res = (ARCHIVE_FATAL); | ||
| 52 | + break; | ||
| 53 | + } | ||
| 54 | + /* | ||
| 55 | + * Our view is now from inside | ||
| 56 | + * this dir: | ||
| 57 | + */ | ||
| 58 | + head = tail + 1; | ||
| 59 | + } else { | ||
| 60 | + tail[0] = c; | ||
| 61 | + fsobj_error(a_eno, a_estr, 0, | ||
| 62 | + "Cannot extract through " | ||
| 63 | + "symlink %s", path); | ||
| 64 | + res = ARCHIVE_FAILED; | ||
| 65 | + break; | ||
| 66 | + } | ||
| 67 | } else { | ||
| 68 | tail[0] = c; | ||
| 69 | fsobj_error(a_eno, a_estr, 0, | ||
| 70 | diff --git a/tar/test/test_symlink_dir.c b/tar/test/test_symlink_dir.c | ||
| 71 | index 25bd8b1..852e00b 100644 | ||
| 72 | --- a/tar/test/test_symlink_dir.c | ||
| 73 | +++ b/tar/test/test_symlink_dir.c | ||
| 74 | @@ -47,11 +47,18 @@ DEFINE_TEST(test_symlink_dir) | ||
| 75 | assertMakeDir("source/dir3", 0755); | ||
| 76 | assertMakeDir("source/dir3/d3", 0755); | ||
| 77 | assertMakeFile("source/dir3/f3", 0755, "abcde"); | ||
| 78 | + assertMakeDir("source/dir4", 0755); | ||
| 79 | + assertMakeFile("source/dir4/file3", 0755, "abcdef"); | ||
| 80 | + assertMakeHardlink("source/dir4/file4", "source/dir4/file3"); | ||
| 81 | |||
| 82 | assertEqualInt(0, | ||
| 83 | systemf("%s -cf test.tar -C source dir dir2 dir3 file file2", | ||
| 84 | testprog)); | ||
| 85 | |||
| 86 | + /* Second archive with hardlinks */ | ||
| 87 | + assertEqualInt(0, | ||
| 88 | + systemf("%s -cf test2.tar -C source dir4", testprog)); | ||
| 89 | + | ||
| 90 | /* | ||
| 91 | * Extract with -x and without -P. | ||
| 92 | */ | ||
| 93 | @@ -118,9 +125,15 @@ DEFINE_TEST(test_symlink_dir) | ||
| 94 | assertMakeSymlink("dest2/file2", "real_file2"); | ||
| 95 | assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog)); | ||
| 96 | |||
| 97 | - /* dest2/dir symlink should be followed */ | ||
| 98 | + /* "dir4" is a symlink to existing "real_dir" */ | ||
| 99 | + if (canSymlink()) | ||
| 100 | + assertMakeSymlink("dest2/dir4", "real_dir"); | ||
| 101 | + assertEqualInt(0, systemf("%s -xPf test2.tar -C dest2", testprog)); | ||
| 102 | + | ||
| 103 | + /* dest2/dir and dest2/dir4 symlinks should be followed */ | ||
| 104 | if (canSymlink()) { | ||
| 105 | assertIsSymlink("dest2/dir", "real_dir"); | ||
| 106 | + assertIsSymlink("dest2/dir4", "real_dir"); | ||
| 107 | assertIsDir("dest2/real_dir", -1); | ||
| 108 | } | ||
| 109 | |||
| 110 | @@ -141,4 +154,7 @@ DEFINE_TEST(test_symlink_dir) | ||
| 111 | /* dest2/file2 symlink should be removed */ | ||
| 112 | failure("Symlink to non-existing file should be removed"); | ||
| 113 | assertIsReg("dest2/file2", -1); | ||
| 114 | + | ||
| 115 | + /* dest2/dir4/file3 and dest2/dir4/file4 should be hard links */ | ||
| 116 | + assertIsHardlink("dest2/dir4/file3", "dest2/dir4/file4"); | ||
| 117 | } | ||
| 118 | -- | ||
| 119 | 2.7.4 | ||
| 120 | |||
diff --git a/meta/recipes-extended/libarchive/libarchive_3.2.2.bb b/meta/recipes-extended/libarchive/libarchive_3.2.2.bb index a7c1204bd2..a7ec621fb9 100644 --- a/meta/recipes-extended/libarchive/libarchive_3.2.2.bb +++ b/meta/recipes-extended/libarchive/libarchive_3.2.2.bb | |||
| @@ -36,6 +36,8 @@ PACKAGECONFIG[lz4] = "--with-lz4,--without-lz4,lz4," | |||
| 36 | 36 | ||
| 37 | SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz \ | 37 | SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz \ |
| 38 | file://non-recursive-extract-and-list.patch \ | 38 | file://non-recursive-extract-and-list.patch \ |
| 39 | file://0001-archive_write_disk_posix.c-make-_fsobj-functions-mor.patch \ | ||
| 40 | file://0002-Fix-extracting-hardlinks-over-symlinks.patch \ | ||
| 39 | " | 41 | " |
| 40 | 42 | ||
| 41 | SRC_URI[md5sum] = "1ec00b7dcaf969dd2a5712f85f23c764" | 43 | SRC_URI[md5sum] = "1ec00b7dcaf969dd2a5712f85f23c764" |
