THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

357 lines
7.5KB

  1. #include "cache.h"
  2. #include "pkt-line.h"
  3. #include <signal.h>
  4. #include <sys/wait.h>
  5. #include <sys/socket.h>
  6. #include <netdb.h>
  7. #include <netinet/in.h>
  8. static const char daemon_usage[] = "git-daemon [--inetd | --port=n]";
  9. static int upload(char *dir, int dirlen)
  10. {
  11. if (chdir(dir) < 0)
  12. return -1;
  13. chdir(".git");
  14. /*
  15. * Security on the cheap.
  16. *
  17. * We want a readable HEAD, usable "objects" directory, and
  18. * a "git-daemon-export-ok" flag that says that the other side
  19. * is ok with us doing this.
  20. */
  21. if (access("git-daemon-export-ok", F_OK) ||
  22. access("objects/00", X_OK) ||
  23. access("HEAD", R_OK))
  24. return -1;
  25. /*
  26. * We'll ignore SIGTERM from now on, we have a
  27. * good client.
  28. */
  29. signal(SIGTERM, SIG_IGN);
  30. /* git-upload-pack only ever reads stuff, so this is safe */
  31. execlp("git-upload-pack", "git-upload-pack", ".", NULL);
  32. return -1;
  33. }
  34. static int execute(void)
  35. {
  36. static char line[1000];
  37. int len;
  38. len = packet_read_line(0, line, sizeof(line));
  39. if (len && line[len-1] == '\n')
  40. line[--len] = 0;
  41. if (!strncmp("git-upload-pack /", line, 17))
  42. return upload(line + 16, len - 16);
  43. fprintf(stderr, "got bad connection '%s'\n", line);
  44. return -1;
  45. }
  46. /*
  47. * We count spawned/reaped separately, just to avoid any
  48. * races when updating them from signals. The SIGCHLD handler
  49. * will only update children_reaped, and the fork logic will
  50. * only update children_spawned.
  51. *
  52. * MAX_CHILDREN should be a power-of-two to make the modulus
  53. * operation cheap. It should also be at least twice
  54. * the maximum number of connections we will ever allow.
  55. */
  56. #define MAX_CHILDREN 128
  57. static int max_connections = 25;
  58. /* These are updated by the signal handler */
  59. static volatile unsigned int children_reaped = 0;
  60. pid_t dead_child[MAX_CHILDREN];
  61. /* These are updated by the main loop */
  62. static unsigned int children_spawned = 0;
  63. static unsigned int children_deleted = 0;
  64. struct child {
  65. pid_t pid;
  66. socklen_t addrlen;
  67. struct sockaddr_storage address;
  68. } live_child[MAX_CHILDREN];
  69. static void add_child(int idx, pid_t pid, struct sockaddr *addr, socklen_t addrlen)
  70. {
  71. live_child[idx].pid = pid;
  72. live_child[idx].addrlen = addrlen;
  73. memcpy(&live_child[idx].address, addr, addrlen);
  74. }
  75. /*
  76. * Walk from "deleted" to "spawned", and remove child "pid".
  77. *
  78. * We move everything up by one, since the new "deleted" will
  79. * be one higher.
  80. */
  81. static void remove_child(pid_t pid, unsigned deleted, unsigned spawned)
  82. {
  83. struct child n;
  84. deleted %= MAX_CHILDREN;
  85. spawned %= MAX_CHILDREN;
  86. if (live_child[deleted].pid == pid) {
  87. live_child[deleted].pid = -1;
  88. return;
  89. }
  90. n = live_child[deleted];
  91. for (;;) {
  92. struct child m;
  93. deleted = (deleted + 1) % MAX_CHILDREN;
  94. if (deleted == spawned)
  95. die("could not find dead child %d\n", pid);
  96. m = live_child[deleted];
  97. live_child[deleted] = n;
  98. if (m.pid == pid)
  99. return;
  100. n = m;
  101. }
  102. }
  103. /*
  104. * This gets called if the number of connections grows
  105. * past "max_connections".
  106. *
  107. * We _should_ start off by searching for connections
  108. * from the same IP, and if there is some address wth
  109. * multiple connections, we should kill that first.
  110. *
  111. * As it is, we just "randomly" kill 25% of the connections,
  112. * and our pseudo-random generator sucks too. I have no
  113. * shame.
  114. *
  115. * Really, this is just a place-holder for a _real_ algorithm.
  116. */
  117. static void kill_some_children(int signo, unsigned start, unsigned stop)
  118. {
  119. start %= MAX_CHILDREN;
  120. stop %= MAX_CHILDREN;
  121. while (start != stop) {
  122. if (!(start & 3))
  123. kill(live_child[start].pid, signo);
  124. start = (start + 1) % MAX_CHILDREN;
  125. }
  126. }
  127. static void check_max_connections(void)
  128. {
  129. for (;;) {
  130. int active;
  131. unsigned spawned, reaped, deleted;
  132. spawned = children_spawned;
  133. reaped = children_reaped;
  134. deleted = children_deleted;
  135. while (deleted < reaped) {
  136. pid_t pid = dead_child[deleted % MAX_CHILDREN];
  137. remove_child(pid, deleted, spawned);
  138. deleted++;
  139. }
  140. children_deleted = deleted;
  141. active = spawned - deleted;
  142. if (active <= max_connections)
  143. break;
  144. /* Kill some unstarted connections with SIGTERM */
  145. kill_some_children(SIGTERM, deleted, spawned);
  146. if (active <= max_connections << 1)
  147. break;
  148. /* If the SIGTERM thing isn't helping use SIGKILL */
  149. kill_some_children(SIGKILL, deleted, spawned);
  150. sleep(1);
  151. }
  152. }
  153. static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
  154. {
  155. pid_t pid = fork();
  156. if (pid) {
  157. unsigned idx;
  158. close(incoming);
  159. if (pid < 0)
  160. return;
  161. idx = children_spawned % MAX_CHILDREN;
  162. children_spawned++;
  163. add_child(idx, pid, addr, addrlen);
  164. check_max_connections();
  165. return;
  166. }
  167. dup2(incoming, 0);
  168. dup2(incoming, 1);
  169. close(incoming);
  170. exit(execute());
  171. }
  172. static void child_handler(int signo)
  173. {
  174. for (;;) {
  175. pid_t pid = waitpid(-1, NULL, WNOHANG);
  176. if (pid > 0) {
  177. unsigned reaped = children_reaped;
  178. dead_child[reaped % MAX_CHILDREN] = pid;
  179. children_reaped = reaped + 1;
  180. continue;
  181. }
  182. break;
  183. }
  184. }
  185. static int serve(int port)
  186. {
  187. struct addrinfo hints, *ai0, *ai;
  188. int gai;
  189. int socknum = 0, *socklist = NULL;
  190. int maxfd = -1;
  191. fd_set fds_init, fds;
  192. char pbuf[NI_MAXSERV];
  193. signal(SIGCHLD, child_handler);
  194. sprintf(pbuf, "%d", port);
  195. memset(&hints, 0, sizeof(hints));
  196. hints.ai_family = AF_UNSPEC;
  197. hints.ai_socktype = SOCK_STREAM;
  198. hints.ai_protocol = IPPROTO_TCP;
  199. hints.ai_flags = AI_PASSIVE;
  200. gai = getaddrinfo(NULL, pbuf, &hints, &ai0);
  201. if (gai)
  202. die("getaddrinfo() failed: %s\n", gai_strerror(gai));
  203. FD_ZERO(&fds_init);
  204. for (ai = ai0; ai; ai = ai->ai_next) {
  205. int sockfd;
  206. int *newlist;
  207. sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  208. if (sockfd < 0)
  209. continue;
  210. if (sockfd >= FD_SETSIZE) {
  211. error("too large socket descriptor.");
  212. close(sockfd);
  213. continue;
  214. }
  215. #ifdef IPV6_V6ONLY
  216. if (ai->ai_family == AF_INET6) {
  217. int on = 1;
  218. setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
  219. &on, sizeof(on));
  220. /* Note: error is not fatal */
  221. }
  222. #endif
  223. if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
  224. close(sockfd);
  225. continue; /* not fatal */
  226. }
  227. if (listen(sockfd, 5) < 0) {
  228. close(sockfd);
  229. continue; /* not fatal */
  230. }
  231. newlist = realloc(socklist, sizeof(int) * (socknum + 1));
  232. if (!newlist)
  233. die("memory allocation failed: %s", strerror(errno));
  234. socklist = newlist;
  235. socklist[socknum++] = sockfd;
  236. FD_SET(sockfd, &fds_init);
  237. if (maxfd < sockfd)
  238. maxfd = sockfd;
  239. }
  240. freeaddrinfo(ai0);
  241. if (socknum == 0)
  242. die("unable to allocate any listen sockets on port %u", port);
  243. for (;;) {
  244. int i;
  245. fds = fds_init;
  246. if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 0) {
  247. error("select failed, resuming: %s", strerror(errno));
  248. sleep(1);
  249. continue;
  250. }
  251. for (i = 0; i < socknum; i++) {
  252. int sockfd = socklist[i];
  253. if (FD_ISSET(sockfd, &fds)) {
  254. struct sockaddr_storage ss;
  255. socklen_t sslen = sizeof(ss);
  256. int incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);
  257. if (incoming < 0) {
  258. switch (errno) {
  259. case EAGAIN:
  260. case EINTR:
  261. case ECONNABORTED:
  262. continue;
  263. default:
  264. die("accept returned %s", strerror(errno));
  265. }
  266. }
  267. handle(incoming, (struct sockaddr *)&ss, sslen);
  268. }
  269. }
  270. }
  271. }
  272. int main(int argc, char **argv)
  273. {
  274. int port = DEFAULT_GIT_PORT;
  275. int inetd_mode = 0;
  276. int i;
  277. for (i = 1; i < argc; i++) {
  278. char *arg = argv[i];
  279. if (!strncmp(arg, "--port=", 7)) {
  280. char *end;
  281. unsigned long n;
  282. n = strtoul(arg+7, &end, 0);
  283. if (arg[7] && !*end) {
  284. port = n;
  285. continue;
  286. }
  287. }
  288. if (!strcmp(arg, "--inetd")) {
  289. inetd_mode = 1;
  290. continue;
  291. }
  292. usage(daemon_usage);
  293. }
  294. if (inetd_mode)
  295. return execute();
  296. return serve(port);
  297. }