1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
From 8f4b080c9cbe60d504d7df6250e52a43dc83d184 Mon Sep 17 00:00:00 2001
From: Gerrit Pape <pape@smarden.org>
Date: Tue, 23 Jun 2009 09:42:46 +0000
Subject: [PATCH] daemon: Strictly parse the "extra arg" part of the command
Since 1.4.4.5 (49ba83fb67 "Add virtualization support to git-daemon")
git daemon enters an infinite loop and never terminates if a client
hides any extra arguments in the initial request line which is not
exactly "\0host=blah\0".
Since that change, a client must never insert additional extra
arguments, or attempt to use any argument other than "host=", as
any daemon will get stuck parsing the request line and will never
complete the request.
Since the client can't tell if the daemon is patched or not, it
is not possible to know if additional extra args might actually be
able to be safely requested.
If we ever need to extend the git daemon protocol to support a new
feature, we may have to do something like this to the exchange:
# If both support git:// v2
#
C: 000cgit://v2
S: 0010ok host user
C: 0018host git.kernel.org
C: 0027git-upload-pack /pub/linux-2.6.git
S: ...git-upload-pack header...
# If client supports git:// v2, server does not:
#
C: 000cgit://v2
S: <EOF>
C: 003bgit-upload-pack /pub/linux-2.6.git\0host=git.kernel.org\0
S: ...git-upload-pack header...
This requires the client to create two TCP connections to talk to
an older git daemon, however all daemons since the introduction of
daemon.c will safely reject the unknown "git://v2" command request,
so the client can quite easily determine the server supports an
older protocol.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
(cherry picked from commit 73bb33a94ec67a53e7d805b12ad9264fa25f4f8d)
Conflicts:
daemon.c
---
connect.c | 5 ++++-
daemon.c | 10 ++++++----
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/connect.c b/connect.c
index c55a20a..0ae3314 100644
--- a/connect.c
+++ b/connect.c
@@ -686,7 +686,10 @@ pid_t git_connect(int fd[2], char *url, const char *prog)
git_tcp_connect(fd, host);
/*
* Separate original protocol components prog and path
- * from extended components with a NUL byte.
+ * from extended host header with a NUL byte.
+ *
+ * Note: Do not add any other headers here! Doing so
+ * will cause older git-daemon servers to crash.
*/
packet_write(fd[1],
"%s %s%chost=%s%c",
diff --git a/daemon.c b/daemon.c
index e66bb80..1a14f48 100644
--- a/daemon.c
+++ b/daemon.c
@@ -410,16 +410,16 @@ static void make_service_overridable(const char *name, int ena) {
}
/*
- * Separate the "extra args" information as supplied by the client connection.
+ * Read the host as supplied by the client connection.
* Any resulting data is squirrelled away in the given interpolation table.
*/
-static void parse_extra_args(struct interp *table, char *extra_args, int buflen)
+static void parse_host_arg(struct interp *table, char *extra_args, int buflen)
{
char *val;
int vallen;
char *end = extra_args + buflen;
- while (extra_args < end && *extra_args) {
+ if (extra_args < end && *extra_args) {
saw_extended_args = 1;
if (strncasecmp("host=", extra_args, 5) == 0) {
val = extra_args + 5;
@@ -439,6 +439,8 @@ static void parse_extra_args(struct interp *table, char *extra_args, int buflen)
/* On to the next one */
extra_args = val + vallen;
}
+ if (extra_args < end && *extra_args)
+ die("Invalid request");
}
}
@@ -558,7 +560,7 @@ static int execute(struct sockaddr *addr)
interp_set_entry(interp_table, INTERP_SLOT_PERCENT, "%");
if (len != pktlen) {
- parse_extra_args(interp_table, line + len + 1, pktlen - len - 1);
+ parse_host_arg(interp_table, line + len + 1, pktlen - len - 1);
fill_in_extra_table_entries(interp_table);
}
--
1.6.3.1
|