$NetBSD: patch-ar,v 1.7 2007/06/28 01:24:39 lkundrak Exp $

Fix for CVE-2007-3304 denial of service.

--- src/main/http_main.c.orig	2009-03-22 18:14:58.000000000 +0300
+++ src/main/http_main.c
@@ -705,6 +705,18 @@ static void remove_sync_sigs(sigset_t *s
 static void accept_mutex_init_pthread(pool *p)
 {
     pthread_mutexattr_t mattr;
+
+#ifdef MAP_ANON
+#ifndef NOFD
+#define NOFD	-1
+#endif
+    accept_mutex = (pthread_mutex_t *) mmap((caddr_t) 0, sizeof(*accept_mutex),
+				 PROT_READ | PROT_WRITE, MAP_ANON|MAP_SHARED, NOFD, 0);
+    if (accept_mutex == (void *) (caddr_t) - 1) {
+	perror("mmap");
+	exit(APEXIT_INIT);
+    }
+#else
     int fd;
 
     fd = open("/dev/zero", O_RDWR);
@@ -719,6 +731,7 @@ static void accept_mutex_init_pthread(po
 	exit(APEXIT_INIT);
     }
     close(fd);
+#endif
     if ((errno = pthread_mutexattr_init(&mattr))) {
 	perror("pthread_mutexattr_init");
 	exit(APEXIT_INIT);
@@ -2217,30 +2230,13 @@ static void reopen_scoreboard(pool *p)
 /* 
  * POSIX 1003.4 style
  *
- * Note 1: 
- * As of version 4.23A, shared memory in QNX must reside under /dev/shmem,
- * where no subdirectories allowed.
- *
- * POSIX shm_open() and shm_unlink() will take care about this issue,
- * but to avoid confusion, I suggest to redefine scoreboard file name
- * in httpd.conf to cut "logs/" from it. With default setup actual name
- * will be "/dev/shmem/logs.apache_status". 
- * 
- * If something went wrong and Apache did not unlinked this object upon
- * exit, you can remove it manually, using "rm -f" command.
- * 
- * Note 2:
- * <sys/mman.h> in QNX defines MAP_ANON, but current implementation 
- * does NOT support BSD style anonymous mapping. So, the order of 
- * conditional compilation is important: 
- * this #ifdef section must be ABOVE the next one (BSD style).
- *
- * I tested this stuff and it works fine for me, but if it provides 
- * trouble for you, just comment out USE_MMAP_SCOREBOARD in QNX section
- * of ap_config.h
+ * This code is only used by QNX4 probably, and from version 4.25
+ * QNX4 can actually use USE_MMAP_SCOREBOARD. So this is only still 
+ * useful if you're stuck with one of earlier versions. Otherwise
+ * just define USE_MMAP_SCOREBOARD in QNX section of Configure.
  *
- * June 5, 1997, 
- * Igor N. Kovalenko -- infoh@mail.wplus.net
+ * Oct 18, 2001, 
+ * Igor Kovalenko -- ikovalenko@sourceforge.net
  */
 
 static void cleanup_shared_mem(void *d)
@@ -2793,6 +2789,17 @@ static int find_child_by_pid(int pid)
     return -1;
 }
 
+static int safe_child_kill(pid_t pid, int sig)
+{
+    if (getpgid(pid) == getpgrp()) {
+        return kill(pid, sig);
+    }
+    else {
+        errno = EINVAL;
+        return -1;
+    }
+}
+
 static void reclaim_child_processes(int terminate)
 {
 #ifndef MULTITHREAD
@@ -5207,7 +5214,7 @@ static void perform_idle_server_maintena
 		else if (ps->last_rtime + ss->timeout_len < now) {
 		    /* no progress, and the timeout length has been exceeded */
 		    ss->timeout_len = 0;
-		    kill(ps->pid, SIG_TIMEOUT_KILL);
+		    safe_child_kill(ps->pid, SIG_TIMEOUT_KILL);
 		}
 	    }
 #endif
@@ -5220,7 +5227,7 @@ static void perform_idle_server_maintena
 	 * while we were counting. Use the define SIG_IDLE_KILL to reflect
 	 * which signal should be used on the specific OS.
 	 */
-	kill(ap_scoreboard_image->parent[to_kill].pid, SIG_IDLE_KILL);
+	safe_child_kill(ap_scoreboard_image->parent[to_kill].pid, SIG_IDLE_KILL);
 	idle_spawn_rate = 1;
 #ifdef TPF
         ap_update_child_status(to_kill, SERVER_DEAD, (request_rec *)NULL);
