daemon: detect and reject too-long paths

When we are checking the path via path_ok(), we use some fixed PATH_MAX buffers. We write into them via snprintf(), so there's no possibility of overflow, but it does mean we may silently truncate the path, leading to potentially confusing errors when the partial path does not exist. We're better off to reject the path explicitly. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Oct 22, 2016 at 00:59 UTC 6bdb0083be3b42aab5dfa6bf18b447623704f7f5
1 file changed +21 -4
daemon.c
+21 -4
@@ -161,6 +161,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
161 {
162 static char rpath[PATH_MAX];
163 static char interp_path[PATH_MAX];
164 + size_t rlen;
165 const char *path;
166 const char *dir;
167
@@ -188,8 +189,12 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
189 namlen = slash - dir;
190 restlen -= namlen;
191 loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
191 - snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
192 - namlen, dir, user_path, restlen, slash);
192 + rlen = snprintf(rpath, sizeof(rpath), "%.*s/%s%.*s",
193 + namlen, dir, user_path, restlen, slash);
194 + if (rlen >= sizeof(rpath)) {
195 + logerror("user-path too large: %s", rpath);
196 + return NULL;
197 + }
198 dir = rpath;
199 }
200 }
@@ -208,7 +213,15 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
213
214 strbuf_expand(&expanded_path, interpolated_path,
215 expand_path, &context);
211 - strlcpy(interp_path, expanded_path.buf, PATH_MAX);
216 +
217 + rlen = strlcpy(interp_path, expanded_path.buf,
218 + sizeof(interp_path));
219 + if (rlen >= sizeof(interp_path)) {
220 + logerror("interpolated path too large: %s",
221 + interp_path);
222 + return NULL;
223 + }
224 +
225 strbuf_release(&expanded_path);
226 loginfo("Interpolated dir '%s'", interp_path);
227
@@ -220,7 +233,11 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
233 logerror("'%s': Non-absolute path denied (base-path active)", dir);
234 return NULL;
235 }
223 - snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
236 + rlen = snprintf(rpath, sizeof(rpath), "%s%s", base_path, dir);
237 + if (rlen >= sizeof(rpath)) {
238 + logerror("base-path too large: %s", rpath);
239 + return NULL;
240 + }
241 dir = rpath;
242 }
243