From: Junio C Hamano Date: Thu, 27 Oct 2016 21:58:50 +0000 (-0700) Subject: Merge branch 'jk/daemon-path-ok-check-truncation' X-Git-Tag: v2.11.0-rc0~18 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/ee87d47b364cdaf78badefb3f7044b8074ed1550?ds=inline;hp=-c Merge branch 'jk/daemon-path-ok-check-truncation' "git daemon" used fixed-length buffers to turn URL to the repository the client asked for into the server side directory path, using snprintf() to avoid overflowing these buffers, but allowed possibly truncated paths to the directory. This has been tightened to reject such a request that causes overlong path to be required to serve. * jk/daemon-path-ok-check-truncation: daemon: detect and reject too-long paths --- ee87d47b364cdaf78badefb3f7044b8074ed1550 diff --combined daemon.c index 425aad0507,72f6ad3c0d..ff0fa583b0 --- a/daemon.c +++ b/daemon.c @@@ -1,5 -1,6 +1,5 @@@ #include "cache.h" #include "pkt-line.h" -#include "exec_cmd.h" #include "run-command.h" #include "strbuf.h" #include "string-list.h" @@@ -31,7 -32,7 +31,7 @@@ static const char daemon_usage[] " [...]"; /* List of acceptable pathname prefixes */ -static char **ok_paths; +static const char **ok_paths; static int strict_paths; /* If this is set, git-daemon-export-ok is not required */ @@@ -160,6 -161,7 +160,7 @@@ static const char *path_ok(const char * { static char rpath[PATH_MAX]; static char interp_path[PATH_MAX]; + size_t rlen; const char *path; const char *dir; @@@ -187,8 -189,12 +188,12 @@@ namlen = slash - dir; restlen -= namlen; loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash); - snprintf(rpath, PATH_MAX, "%.*s/%s%.*s", - namlen, dir, user_path, restlen, slash); + rlen = snprintf(rpath, sizeof(rpath), "%.*s/%s%.*s", + namlen, dir, user_path, restlen, slash); + if (rlen >= sizeof(rpath)) { + logerror("user-path too large: %s", rpath); + return NULL; + } dir = rpath; } } @@@ -207,7 -213,15 +212,15 @@@ strbuf_expand(&expanded_path, interpolated_path, expand_path, &context); - strlcpy(interp_path, expanded_path.buf, PATH_MAX); + + rlen = strlcpy(interp_path, expanded_path.buf, + sizeof(interp_path)); + if (rlen >= sizeof(interp_path)) { + logerror("interpolated path too large: %s", + interp_path); + return NULL; + } + strbuf_release(&expanded_path); loginfo("Interpolated dir '%s'", interp_path); @@@ -219,7 -233,11 +232,11 @@@ logerror("'%s': Non-absolute path denied (base-path active)", dir); return NULL; } - snprintf(rpath, PATH_MAX, "%s%s", base_path, dir); + rlen = snprintf(rpath, sizeof(rpath), "%s%s", base_path, dir); + if (rlen >= sizeof(rpath)) { + logerror("base-path too large: %s", rpath); + return NULL; + } dir = rpath; } @@@ -239,7 -257,7 +256,7 @@@ } if ( ok_paths && *ok_paths ) { - char **pp; + const char **pp; int pathlen = strlen(path); /* The validation is done on the paths after enter_repo @@@ -668,17 -686,6 +685,17 @@@ static void hostinfo_clear(struct hosti strbuf_release(&hi->tcp_port); } +static void set_keep_alive(int sockfd) +{ + int ka = 1; + + if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0) { + if (errno != ENOTSOCK) + logerror("unable to set SO_KEEPALIVE on socket: %s", + strerror(errno)); + } +} + static int execute(void) { char *line = packet_buffer; @@@ -691,7 -698,6 +708,7 @@@ if (addr) loginfo("Connection from %s:%s", addr, port); + set_keep_alive(0); alarm(init_timeout ? init_timeout : timeout); pktlen = packet_read(0, NULL, NULL, packet_buffer, sizeof(packet_buffer), 0); alarm(0); @@@ -962,8 -968,6 +979,8 @@@ static int setup_named_sock(char *liste continue; } + set_keep_alive(sockfd); + if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { logerror("Could not bind to %s: %s", ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen), @@@ -1023,8 -1027,6 +1040,8 @@@ static int setup_named_sock(char *liste return 0; } + set_keep_alive(sockfd); + if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) { logerror("Could not bind to %s: %s", ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)), @@@ -1193,7 -1195,7 +1210,7 @@@ static int serve(struct string_list *li return service_loop(&socklist); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { int listen_port = 0; struct string_list listen_addr = STRING_LIST_INIT_NODUP; @@@ -1203,8 -1205,12 +1220,8 @@@ struct credentials *cred = NULL; int i; - git_setup_gettext(); - - git_extract_argv0_path(argv[0]); - for (i = 1; i < argc; i++) { - char *arg = argv[i]; + const char *arg = argv[i]; const char *v; if (skip_prefix(arg, "--listen=", &v)) { @@@ -1378,7 -1384,8 +1395,7 @@@ if (detach) { if (daemonize()) die("--detach not supported on this platform"); - } else - sanitize_stdfds(); + } if (pid_file) write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid());