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
7 Upstream-Status: Backported
9 Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
11 libarchive/archive_write_disk_posix.c | 121 +++++++++++++++++-----------------
12 1 file changed, 61 insertions(+), 60 deletions(-)
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 {
20 #define HFS_BLOCKS(s) ((s) >> 12)
22 +static void fsobj_error(int *, struct archive_string *, int, 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)
30 /* Everything failed; give up here. */
31 - archive_set_error(&a->archive, en, "Can't create '%s'",
33 + if ((&a->archive)->error == NULL)
34 + archive_set_error(&a->archive, en, "Can't create '%s'",
36 return (ARCHIVE_FAILED);
39 @@ -2388,6 +2391,17 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
40 return (a->current_fixup);
43 +/* Error helper for new *_fsobj functions */
45 +fsobj_error(int *a_eno, struct archive_string *a_estr,
46 + int err, const char *errstr, const char *path)
51 + archive_string_sprintf(a_estr, errstr, path);
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.
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)
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) {
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;
80 - archive_string_sprintf(error_string,
81 - "Could not stat %s",
84 + * Treat any other error as fatal - best to be
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
91 + * TODO: We could do better, but it would
92 + * probably require merging the symlink checks
93 + * with the deep-directory editing.
95 + fsobj_error(a_eno, a_estr, errno,
96 + "Could not stat %s", path);
100 @@ -2494,11 +2509,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
102 if (chdir(head) != 0) {
104 - if (error_number) *error_number = errno;
106 - archive_string_sprintf(error_string,
107 - "Could not chdir %s",
109 + fsobj_error(a_eno, a_estr, errno,
110 + "Could not chdir %s", path);
111 res = (ARCHIVE_FATAL);
114 @@ -2514,11 +2526,9 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
118 - if (error_number) *error_number = errno;
120 - archive_string_sprintf(error_string,
121 - "Could not remove symlink %s",
123 + fsobj_error(a_eno, a_estr, errno,
124 + "Could not remove symlink %s",
126 res = ARCHIVE_FAILED;
129 @@ -2529,13 +2539,14 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
130 * symlink with another symlink.
133 - /* FIXME: not sure how important this is to restore
135 + * FIXME: not sure how important this is to
139 if (!S_ISLNK(path)) {
140 - if (error_number) *error_number = 0;
142 - archive_string_sprintf(error_string,
143 - "Removing symlink %s",
145 + fsobj_error(a_eno, a_estr, 0,
146 + "Removing symlink %s", path);
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) {
154 - if (error_number) *error_number = 0;
156 - archive_string_sprintf(error_string,
157 - "Cannot remove intervening symlink %s",
159 + fsobj_error(a_eno, a_estr, 0,
160 + "Cannot remove intervening "
161 + "symlink %s", path);
162 res = ARCHIVE_FAILED;
168 - if (error_number) *error_number = 0;
170 - archive_string_sprintf(error_string,
171 - "Cannot extract through symlink %s",
173 + fsobj_error(a_eno, a_estr, 0,
174 + "Cannot extract through symlink %s", path);
175 res = ARCHIVE_FAILED;
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);
182 - if(error_number) *error_number = errno;
184 - archive_string_sprintf(error_string,
185 - "chdir() failure");
186 + fsobj_error(a_eno, a_estr, errno,
187 + "chdir() failure", "");
191 @@ -2688,17 +2692,16 @@ cleanup_pathname_win(struct archive_write_disk *a)
192 * is set) if the path is absolute.
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,
200 char separator = '\0';
204 - if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
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);
213 @@ -2708,10 +2711,8 @@ cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *err
214 /* Skip leading '/'. */
216 if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
217 - if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
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);
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;
233 - archive_string_sprintf(error_string,
234 - "Path contains '..'");
236 + & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
237 + fsobj_error(a_eno, a_estr,
238 + ARCHIVE_ERRNO_MISC,
239 + "Path contains ", "'..'");
240 return (ARCHIVE_FAILED);