diff -Naur linux-2.4.26-tj3/arch/ia64/ia32/sys_ia32.c linux-2.4.26-tj4/arch/ia64/ia32/sys_ia32.c
--- linux-2.4.26-tj3/arch/ia64/ia32/sys_ia32.c	2004-02-18 14:36:30.000000000 +0100
+++ linux-2.4.26-tj4/arch/ia64/ia32/sys_ia32.c	2005-01-07 16:49:50.000000000 +0100
@@ -1367,6 +1367,11 @@
 #define __CMSG32_FIRSTHDR(ctl,len) \
 	((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL)
 #define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG32_OK(ucmlen, ucmsg, mhdr) \
+	((ucmlen) >= sizeof(struct cmsghdr) && \
+	 (ucmlen) <= (unsigned long) \
+	 ((mhdr)->msg_controllen - \
+	  ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
 
 static inline struct cmsghdr32 *
 __cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len)
@@ -1427,10 +1432,7 @@
 			return -EFAULT;
 
 		/* Catch bogons. */
-		if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen)
-		    > kmsg->msg_controllen)
+		if (!CMSG32_OK(ucmlen, ucmsg, kmsg))
 			return -EINVAL;
 
 		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
diff -Naur linux-2.4.26-tj3/arch/mips/kernel/irixelf.c linux-2.4.26-tj4/arch/mips/kernel/irixelf.c
--- linux-2.4.26-tj3/arch/mips/kernel/irixelf.c	2003-08-25 13:44:40.000000000 +0200
+++ linux-2.4.26-tj4/arch/mips/kernel/irixelf.c	2005-01-07 16:50:10.000000000 +0100
@@ -130,7 +130,7 @@
 	end = PAGE_ALIGN(end);
 	if (end <= start)
 		return;
-	do_brk(start, end - start);
+	do_brk_locked(start, end - start);
 }
 
 
@@ -379,7 +379,7 @@
 
 	/* Map the last of the bss segment */
 	if (last_bss > len) {
-		do_brk(len, (last_bss - len));
+		do_brk_locked(len, (last_bss - len));
 	}
 	kfree(elf_phdata);
 
@@ -567,7 +567,7 @@
 	unsigned long v;
 	struct prda *pp;
 
-	v =  do_brk (PRDA_ADDRESS, PAGE_SIZE);
+	v =  do_brk_locked (PRDA_ADDRESS, PAGE_SIZE);
 
 	if (v < 0)
 		return;
@@ -859,7 +859,7 @@
 	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
 	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
 	if (bss > len)
-	  do_brk(len, bss-len);
+	  do_brk_locked(len, bss-len);
 	kfree(elf_phdata);
 	return 0;
 }
diff -Naur linux-2.4.26-tj3/arch/mips64/kernel/linux32.c linux-2.4.26-tj4/arch/mips64/kernel/linux32.c
--- linux-2.4.26-tj3/arch/mips64/kernel/linux32.c	2004-02-18 14:36:30.000000000 +0100
+++ linux-2.4.26-tj4/arch/mips64/kernel/linux32.c	2005-01-07 16:49:50.000000000 +0100
@@ -2480,6 +2480,12 @@
 				    (struct cmsghdr32 *)(ctl) : \
 				    (struct cmsghdr32 *)NULL)
 #define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG32_OK(ucmlen, ucmsg, mhdr) \
+	((ucmlen) >= sizeof(struct cmsghdr) && \
+	 (ucmlen) <= (unsigned long) \
+	 ((mhdr)->msg_controllen - \
+	  ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
+
 
 __inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
 					      struct cmsghdr32 *__cmsg, int __cmsg_len)
@@ -2620,11 +2626,7 @@
 			return -EFAULT;
 
 		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -ENOBUFS;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
+		if (!CMSG32_OK(ucmlen, ucmsg, kmsg))
 			return -EINVAL;
 
 		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
diff -Naur linux-2.4.26-tj3/arch/parisc/kernel/sys_parisc32.c linux-2.4.26-tj4/arch/parisc/kernel/sys_parisc32.c
--- linux-2.4.26-tj3/arch/parisc/kernel/sys_parisc32.c	2004-04-21 14:39:37.000000000 +0200
+++ linux-2.4.26-tj4/arch/parisc/kernel/sys_parisc32.c	2005-01-07 16:49:50.000000000 +0100
@@ -1873,6 +1873,11 @@
 				    (struct cmsghdr32 *)(ctl) : \
 				    (struct cmsghdr32 *)NULL)
 #define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG32_OK(ucmlen, ucmsg, mhdr) \
+	((ucmlen) >= sizeof(struct cmsghdr) && \
+	 (ucmlen) <= (unsigned long) \
+	 ((mhdr)->msg_controllen - \
+	  ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
 
 __inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
 					      struct cmsghdr32 *__cmsg, int __cmsg_len)
@@ -1999,11 +2004,7 @@
 			return -EFAULT;
 
 		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
+		if (!CMSG32_OK(ucmlen, ucmsg, kmsg))
 			return -EINVAL;
 
 		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
diff -Naur linux-2.4.26-tj3/arch/ppc64/kernel/sys_ppc32.c linux-2.4.26-tj4/arch/ppc64/kernel/sys_ppc32.c
--- linux-2.4.26-tj3/arch/ppc64/kernel/sys_ppc32.c	2004-02-18 14:36:30.000000000 +0100
+++ linux-2.4.26-tj4/arch/ppc64/kernel/sys_ppc32.c	2005-01-07 16:49:50.000000000 +0100
@@ -3273,6 +3273,11 @@
 				    (struct cmsghdr32 *)(ctl) : \
 				    (struct cmsghdr32 *)NULL)
 #define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG32_OK(ucmlen, ucmsg, mhdr) \
+	((ucmlen) >= sizeof(struct cmsghdr) && \
+	 (ucmlen) <= (unsigned long) \
+	 ((mhdr)->msg_controllen - \
+	  ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
 
 struct msghdr32
 {
@@ -3448,11 +3453,7 @@
 			return -EFAULT;
 
 		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
+		if (!CMSG32_OK(ucmlen, ucmsg, kmsg))
 			return -EINVAL;
 
 		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
diff -Naur linux-2.4.26-tj3/arch/sparc64/kernel/binfmt_aout32.c linux-2.4.26-tj4/arch/sparc64/kernel/binfmt_aout32.c
--- linux-2.4.26-tj3/arch/sparc64/kernel/binfmt_aout32.c	2002-08-03 02:39:43.000000000 +0200
+++ linux-2.4.26-tj4/arch/sparc64/kernel/binfmt_aout32.c	2005-01-07 16:50:10.000000000 +0100
@@ -49,7 +49,7 @@
 	end = PAGE_ALIGN(end);
 	if (end <= start)
 		return;
-	do_brk(start, end - start);
+	do_brk_locked(start, end - start);
 }
 
 /*
@@ -246,10 +246,10 @@
 	if (N_MAGIC(ex) == NMAGIC) {
 		loff_t pos = fd_offset;
 		/* Fuck me plenty... */
-		error = do_brk(N_TXTADDR(ex), ex.a_text);
+		error = do_brk_locked(N_TXTADDR(ex), ex.a_text);
 		bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
 			  ex.a_text, &pos);
-		error = do_brk(N_DATADDR(ex), ex.a_data);
+		error = do_brk_locked(N_DATADDR(ex), ex.a_data);
 		bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
 			  ex.a_data, &pos);
 		goto beyond_if;
@@ -257,7 +257,7 @@
 
 	if (N_MAGIC(ex) == OMAGIC) {
 		loff_t pos = fd_offset;
-		do_brk(N_TXTADDR(ex) & PAGE_MASK,
+		do_brk_locked(N_TXTADDR(ex) & PAGE_MASK,
 			ex.a_text+ex.a_data + PAGE_SIZE - 1);
 		bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
 			  ex.a_text+ex.a_data, &pos);
@@ -272,7 +272,7 @@
 
 		if (!bprm->file->f_op->mmap) {
 			loff_t pos = fd_offset;
-			do_brk(0, ex.a_text+ex.a_data);
+			do_brk_locked(0, ex.a_text+ex.a_data);
 			bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
 				  ex.a_text+ex.a_data, &pos);
 			goto beyond_if;
@@ -388,7 +388,7 @@
 	len = PAGE_ALIGN(ex.a_text + ex.a_data);
 	bss = ex.a_text + ex.a_data + ex.a_bss;
 	if (bss > len) {
-		error = do_brk(start_addr + len, bss - len);
+		error = do_brk_locked(start_addr + len, bss - len);
 		retval = error;
 		if (error != start_addr + len)
 			goto out;
diff -Naur linux-2.4.26-tj3/arch/sparc64/kernel/sys_sparc32.c linux-2.4.26-tj4/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.26-tj3/arch/sparc64/kernel/sys_sparc32.c	2004-04-21 14:39:37.000000000 +0200
+++ linux-2.4.26-tj4/arch/sparc64/kernel/sys_sparc32.c	2005-01-07 16:49:50.000000000 +0100
@@ -2356,6 +2356,11 @@
 				    (struct cmsghdr32 *)(ctl) : \
 				    (struct cmsghdr32 *)NULL)
 #define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG32_OK(ucmlen, ucmsg, mhdr) \
+	((ucmlen) >= sizeof(struct cmsghdr) && \
+	 (ucmlen) <= (unsigned long) \
+	 ((mhdr)->msg_controllen - \
+	  ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
 
 __inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
 					      struct cmsghdr32 *__cmsg, int __cmsg_len)
@@ -2482,11 +2487,7 @@
 			return -EFAULT;
 
 		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
+		if (!CMSG32_OK(ucmlen, ucmsg, kmsg))
 			return -EINVAL;
 
 		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
diff -Naur linux-2.4.26-tj3/arch/s390x/kernel/linux32.c linux-2.4.26-tj4/arch/s390x/kernel/linux32.c
--- linux-2.4.26-tj3/arch/s390x/kernel/linux32.c	2004-02-18 14:36:30.000000000 +0100
+++ linux-2.4.26-tj4/arch/s390x/kernel/linux32.c	2005-01-07 16:49:50.000000000 +0100
@@ -2306,6 +2306,11 @@
 				    (struct cmsghdr32 *)(ctl) : \
 				    (struct cmsghdr32 *)NULL)
 #define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG32_OK(ucmlen, ucmsg, mhdr) \
+	((ucmlen) >= sizeof(struct cmsghdr) && \
+	 (ucmlen) <= (unsigned long) \
+	 ((mhdr)->msg_controllen - \
+	  ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
 
 __inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
 					      struct cmsghdr32 *__cmsg, int __cmsg_len)
@@ -2432,11 +2437,7 @@
 			return -EFAULT;
 
 		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
+		if (!CMSG32_OK(ucmlen, ucmsg, kmsg))
 			return -EINVAL;
 
 		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
diff -Naur linux-2.4.26-tj3/arch/x86_64/ia32/ia32entry.S linux-2.4.26-tj4/arch/x86_64/ia32/ia32entry.S
--- linux-2.4.26-tj3/arch/x86_64/ia32/ia32entry.S	2004-02-18 14:36:31.000000000 +0100
+++ linux-2.4.26-tj4/arch/x86_64/ia32/ia32entry.S	2005-01-07 16:42:57.000000000 +0100
@@ -52,6 +52,7 @@
 ENTRY(ia32_syscall)
 	swapgs	
 	sti
+	movl %eax,%eax	
 	pushq %rax
 	cld
 	SAVE_ARGS
diff -Naur linux-2.4.26-tj3/arch/x86_64/ia32/socket32.c linux-2.4.26-tj4/arch/x86_64/ia32/socket32.c
--- linux-2.4.26-tj3/arch/x86_64/ia32/socket32.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-2.4.26-tj4/arch/x86_64/ia32/socket32.c	2005-01-07 16:49:50.000000000 +0100
@@ -136,12 +136,9 @@
 			return -EFAULT;
 
 		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
+		if (!CMSG32_OK(ucmlen, ucmsg, kmsg))
 			return -EINVAL;
+
 		if (kmsg->msg_controllen > 65536) 
 			return -EINVAL;
 
diff -Naur linux-2.4.26-tj3/fs/binfmt_aout.c linux-2.4.26-tj4/fs/binfmt_aout.c
--- linux-2.4.26-tj3/fs/binfmt_aout.c	2004-04-21 14:39:37.000000000 +0200
+++ linux-2.4.26-tj4/fs/binfmt_aout.c	2005-01-07 16:51:03.000000000 +0100
@@ -45,7 +45,7 @@
 	end = PAGE_ALIGN(end);
 	if (end <= start)
 		return;
-	do_brk(start, end - start);
+	do_brk_locked(start, end - start);
 }
 
 /*
@@ -336,10 +336,10 @@
 		loff_t pos = fd_offset;
 		/* Fuck me plenty... */
 		/* <AOL></AOL> */
-		error = do_brk(N_TXTADDR(ex), ex.a_text);
+		error = do_brk_locked(N_TXTADDR(ex), ex.a_text);
 		bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
 			  ex.a_text, &pos);
-		error = do_brk(N_DATADDR(ex), ex.a_data);
+		error = do_brk_locked(N_DATADDR(ex), ex.a_data);
 		bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
 			  ex.a_data, &pos);
 		goto beyond_if;
@@ -360,7 +360,7 @@
 		map_size = ex.a_text+ex.a_data;
 #endif
 
-		error = do_brk(text_addr & PAGE_MASK, map_size);
+		error = do_brk_locked(text_addr & PAGE_MASK, map_size);
 		if (error != (text_addr & PAGE_MASK)) {
 			send_sig(SIGKILL, current, 0);
 			return error;
@@ -394,7 +394,7 @@
 
 		if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
 			loff_t pos = fd_offset;
-			do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			do_brk_locked(N_TXTADDR(ex), ex.a_text+ex.a_data);
 			bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
 					ex.a_text+ex.a_data, &pos);
 			flush_icache_range((unsigned long) N_TXTADDR(ex),
@@ -491,7 +491,7 @@
 			error_time = jiffies;
 		}
 
-		do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		do_brk_locked(start_addr, ex.a_text + ex.a_data + ex.a_bss);
 		
 		file->f_op->read(file, (char *)start_addr,
 			ex.a_text + ex.a_data, &pos);
@@ -515,7 +515,7 @@
 	len = PAGE_ALIGN(ex.a_text + ex.a_data);
 	bss = ex.a_text + ex.a_data + ex.a_bss;
 	if (bss > len) {
-		error = do_brk(start_addr + len, bss - len);
+		error = do_brk_locked(start_addr + len, bss - len);
 		retval = error;
 		if (error != start_addr + len)
 			goto out;
diff -Naur linux-2.4.26-tj3/fs/binfmt_elf.c linux-2.4.26-tj4/fs/binfmt_elf.c
--- linux-2.4.26-tj3/fs/binfmt_elf.c	2004-04-21 14:39:37.000000000 +0200
+++ linux-2.4.26-tj4/fs/binfmt_elf.c	2005-01-07 16:52:47.000000000 +0100
@@ -88,7 +88,7 @@
 	end = ELF_PAGEALIGN(end);
 	if (end <= start)
 		return;
-	do_brk(start, end - start);
+	do_brk_locked(start, end - start);
 
 #ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC
 	if (current->flags & PF_PAX_RANDEXEC)
@@ -308,9 +308,12 @@
 		goto out;
 
 	retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size);
-	error = retval;
-	if (retval < 0)
+	error = -EIO;
+	if (retval != size) {
+		if (retval < 0)
+			error = retval;	
 		goto out_close;
+	}
 
 	eppnt = elf_phdata;
 	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
@@ -367,7 +370,7 @@
 
 	/* Map the last of the bss segment */
 	if (last_bss > elf_bss)
-		do_brk(elf_bss, last_bss - elf_bss);
+		do_brk_locked(elf_bss, last_bss - elf_bss);
 
 	*interp_load_addr = load_addr;
 	error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;
@@ -405,7 +408,7 @@
 		goto out;
 	}
 
-	do_brk(0, text_data);
+	do_brk_locked(0, text_data);
 	retval = -ENOEXEC;
 	if (!interpreter->f_op || !interpreter->f_op->read)
 		goto out;
@@ -415,7 +418,7 @@
 	flush_icache_range((unsigned long)addr,
 	                   (unsigned long)addr + text_data);
 
-	do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
+	do_brk_locked(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
 		interp_ex->a_bss);
 	elf_entry = interp_ex->a_entry;
 
@@ -686,9 +689,12 @@
 		goto out;
 
 	retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *) elf_phdata, size);
-	if (retval < 0)
+	if (retval != size) {
+		if (retval >= 0)
+			retval = -EIO;
 		goto out_free_ph;
-		
+	}
+
 	files = current->files;		/* Refcounted so ok */
 	retval = unshare_files();
 	if (retval < 0)
@@ -734,8 +740,14 @@
 			retval = kernel_read(bprm->file, elf_ppnt->p_offset,
 					   elf_interpreter,
 					   elf_ppnt->p_filesz);
-			if (retval < 0)
+			if (retval != elf_ppnt->p_filesz) {
+				if (retval >= 0)
+					retval = -EIO;
 				goto out_free_interp;
+			}
+			/* make sure path is NULL terminated */
+			elf_interpreter[elf_ppnt->p_filesz - 1] = '\0';
+
 			/* If the program interpreter is one of these two,
 			 * then assume an iBCS2 image. Otherwise assume
 			 * a native linux image.
@@ -754,8 +766,11 @@
 			if (IS_ERR(interpreter))
 				goto out_free_interp;
 			retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
-			if (retval < 0)
+			if (retval != BINPRM_BUF_SIZE) {
+				if (retval >= 0)
+					retval = -EIO;
 				goto out_free_dentry;
+			}
 
 			/* Get the exec headers */
 			interp_ex = *((struct exec *) bprm->buf);
@@ -1004,8 +1019,10 @@
 #endif
 		{
 			error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
-			if (BAD_ADDR(error))
-				continue;
+			if (BAD_ADDR(error)) {
+				send_sig(SIGKILL, current, 0);
+				goto out_free_dentry;
+			}
 		}
 
 		if (!load_addr_set) {
@@ -1246,7 +1263,7 @@
 	len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1);
 	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
 	if (bss > len)
-		do_brk(len, bss - len);
+		do_brk_locked(len, bss - len);
 	error = 0;
 
 out_free_ph:
diff -Naur linux-2.4.26-tj3/include/asm-x86_64/socket32.h linux-2.4.26-tj4/include/asm-x86_64/socket32.h
--- linux-2.4.26-tj3/include/asm-x86_64/socket32.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.26-tj4/include/asm-x86_64/socket32.h	2005-01-07 16:49:50.000000000 +0100
@@ -45,6 +45,11 @@
 				    (struct cmsghdr32 *)(ctl) : \
 				    (struct cmsghdr32 *)NULL)
 #define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG32_OK(ucmlen, ucmsg, mhdr) \
+	((ucmlen) >= sizeof(struct cmsghdr) && \
+	 (ucmlen) <= (unsigned long) \
+	 ((mhdr)->msg_controllen - \
+	  ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
 
 __inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
 					      struct cmsghdr32 *__cmsg, int __cmsg_len)
diff -Naur linux-2.4.26-tj3/include/linux/mm.h linux-2.4.26-tj4/include/linux/mm.h
--- linux-2.4.26-tj3/include/linux/mm.h	2004-08-04 20:40:25.000000000 +0200
+++ linux-2.4.26-tj4/include/linux/mm.h	2005-01-07 16:50:10.000000000 +0100
@@ -632,6 +632,7 @@
 }
 
 extern unsigned long do_brk(unsigned long, unsigned long);
+extern unsigned long do_brk_locked(unsigned long, unsigned long);
 
 static inline void __vma_unlink(struct mm_struct * mm, struct vm_area_struct * vma, struct vm_area_struct * prev)
 {
diff -Naur linux-2.4.26-tj3/include/linux/socket.h linux-2.4.26-tj4/include/linux/socket.h
--- linux-2.4.26-tj3/include/linux/socket.h	2004-08-04 20:40:25.000000000 +0200
+++ linux-2.4.26-tj4/include/linux/socket.h	2005-01-07 16:49:41.000000000 +0100
@@ -87,6 +87,10 @@
 				  (struct cmsghdr *)(ctl) : \
 				  (struct cmsghdr *)NULL)
 #define CMSG_FIRSTHDR(msg)	__CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && \
+			     (cmsg)->cmsg_len <= (unsigned long) \
+			     ((mhdr)->msg_controllen - \
+			      ((char *)(cmsg) - (char *)(mhdr)->msg_control)))
 
 /*
  *	This mess will go away with glibc
diff -Naur linux-2.4.26-tj3/kernel/ksyms.c linux-2.4.26-tj4/kernel/ksyms.c
--- linux-2.4.26-tj3/kernel/ksyms.c	2004-04-21 15:14:30.000000000 +0200
+++ linux-2.4.26-tj4/kernel/ksyms.c	2005-01-07 16:50:10.000000000 +0100
@@ -89,6 +89,7 @@
 EXPORT_SYMBOL(do_mmap_pgoff);
 EXPORT_SYMBOL(do_munmap);
 EXPORT_SYMBOL(do_brk);
+EXPORT_SYMBOL(do_brk_locked);
 EXPORT_SYMBOL(exit_mm);
 EXPORT_SYMBOL(exit_files);
 EXPORT_SYMBOL(exit_fs);
diff -Naur linux-2.4.26-tj3/mm/mmap.c linux-2.4.26-tj4/mm/mmap.c
--- linux-2.4.26-tj3/mm/mmap.c	2004-04-21 15:20:22.000000000 +0200
+++ linux-2.4.26-tj4/mm/mmap.c	2005-01-07 16:50:10.000000000 +0100
@@ -1377,6 +1377,21 @@
 	return addr;
 }
 
+/* locking version of do_brk. */
+unsigned long do_brk_locked(unsigned long addr, unsigned long len)
+{
+	unsigned long ret;
+
+	down_write(&current->mm->mmap_sem);
+	ret = do_brk(addr, len);
+	up_write(&current->mm->mmap_sem);
+
+	return ret;
+}
+
+
+
+
 /* Build the RB tree corresponding to the VMA list. */
 void build_mmap_rb(struct mm_struct * mm)
 {
diff -Naur linux-2.4.26-tj3/net/core/scm.c linux-2.4.26-tj4/net/core/scm.c
--- linux-2.4.26-tj3/net/core/scm.c	2001-12-21 18:42:05.000000000 +0100
+++ linux-2.4.26-tj4/net/core/scm.c	2005-01-07 16:49:41.000000000 +0100
@@ -124,9 +124,7 @@
 		   for too short ancillary data object at all! Oops.
 		   OK, let's add it...
 		 */
-		if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
-		    (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
-				    + cmsg->cmsg_len) > msg->msg_controllen)
+		if (!CMSG_OK(msg, cmsg))
 			goto error;
 
 		if (cmsg->cmsg_level != SOL_SOCKET)
diff -Naur linux-2.4.26-tj3/net/ipv4/igmp.c linux-2.4.26-tj4/net/ipv4/igmp.c
--- linux-2.4.26-tj3/net/ipv4/igmp.c	2004-04-14 15:05:41.000000000 +0200
+++ linux-2.4.26-tj4/net/ipv4/igmp.c	2005-01-07 16:49:26.000000000 +0100
@@ -1757,12 +1757,12 @@
 			goto done;
 		rv = !0;
 		for (i=0; i<psl->sl_count; i++) {
-			rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+			rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
 				sizeof(__u32));
-			if (rv >= 0)
+			if (rv == 0)
 				break;
 		}
-		if (!rv)	/* source not found */
+		if (rv)		/* source not found */
 			goto done;
 
 		/* update the interface filter */
@@ -1804,9 +1804,9 @@
 	}
 	rv = 1;	/* > 0 for insert logic below if sl_count is 0 */
 	for (i=0; i<psl->sl_count; i++) {
-		rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+		rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
 			sizeof(__u32));
-		if (rv >= 0)
+		if (rv == 0)
 			break;
 	}
 	if (rv == 0)		/* address already there is an error */
diff -Naur linux-2.4.26-tj3/net/ipv4/ip_sockglue.c linux-2.4.26-tj4/net/ipv4/ip_sockglue.c
--- linux-2.4.26-tj3/net/ipv4/ip_sockglue.c	2004-04-14 15:05:41.000000000 +0200
+++ linux-2.4.26-tj4/net/ipv4/ip_sockglue.c	2005-01-07 16:49:41.000000000 +0100
@@ -143,11 +143,8 @@
 	struct cmsghdr *cmsg;
 
 	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
-		if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
-		    (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
-				    + cmsg->cmsg_len) > msg->msg_controllen) {
+		if (!CMSG_OK(msg, cmsg))
 			return -EINVAL;
-		}
 		if (cmsg->cmsg_level != SOL_IP)
 			continue;
 		switch (cmsg->cmsg_type) {
diff -Naur linux-2.4.26-tj3/net/ipv6/datagram.c linux-2.4.26-tj4/net/ipv6/datagram.c
--- linux-2.4.26-tj3/net/ipv6/datagram.c	2003-06-13 16:51:39.000000000 +0200
+++ linux-2.4.26-tj4/net/ipv6/datagram.c	2005-01-07 16:49:41.000000000 +0100
@@ -260,9 +260,7 @@
 
 	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
 
-		if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
-		    (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
-				    + cmsg->cmsg_len) > msg->msg_controllen) {
+		if (!CMSG_OK(msg, cmsg)) {
 			err = -EINVAL;
 			goto exit_f;
 		}
diff -Naur linux-2.4.26-tj3/net/ipv6/mcast.c linux-2.4.26-tj4/net/ipv6/mcast.c
--- linux-2.4.26-tj3/net/ipv6/mcast.c	2004-04-14 15:05:41.000000000 +0200
+++ linux-2.4.26-tj4/net/ipv6/mcast.c	2005-01-07 16:49:26.000000000 +0100
@@ -386,12 +386,12 @@
 			goto done;
 		rv = !0;
 		for (i=0; i<psl->sl_count; i++) {
-			rv = memcmp(&psl->sl_addr, group,
+			rv = memcmp(&psl->sl_addr[i], source,
 				sizeof(struct in6_addr));
-			if (rv >= 0)
+			if (rv == 0)
 				break;
 		}
-		if (!rv)	/* source not found */
+		if (rv)		/* source not found */
 			goto done;
 
 		/* update the interface filter */
@@ -432,8 +432,8 @@
 	}
 	rv = 1;	/* > 0 for insert logic below if sl_count is 0 */
 	for (i=0; i<psl->sl_count; i++) {
-		rv = memcmp(&psl->sl_addr, group, sizeof(struct in6_addr));
-		if (rv >= 0)
+		rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr));
+		if (rv == 0)
 			break;
 	}
 	if (rv == 0)		/* address already there is an error */
diff -Naur linux-2.4.26-tj3/net/sctp/socket.c linux-2.4.26-tj4/net/sctp/socket.c
--- linux-2.4.26-tj3/net/sctp/socket.c	2004-04-14 15:05:41.000000000 +0200
+++ linux-2.4.26-tj4/net/sctp/socket.c	2005-01-07 16:49:41.000000000 +0100
@@ -3937,12 +3937,8 @@
 	for (cmsg = CMSG_FIRSTHDR(msg);
 	     cmsg != NULL;
 	     cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) {
-		/* Check for minimum length.  The SCM code has this check.  */
-		if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
-		    (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
-				    + cmsg->cmsg_len) > msg->msg_controllen) {
+		if (!CMSG_OK(msg, cmsg))
 			return -EINVAL;
-		}
 
 		/* Should we parse this header or ignore?  */
 		if (cmsg->cmsg_level != IPPROTO_SCTP)
diff -Naur linux-2.4.26-tj3/README.tj linux-2.4.26-tj4/README.tj
--- linux-2.4.26-tj3/README.tj	2004-08-04 20:35:50.000000000 +0200
+++ linux-2.4.26-tj4/README.tj	2005-01-07 16:58:08.000000000 +0100
@@ -30,3 +30,11 @@
 fixed floating point leak on ia64
 some usb sparse fixes
 fixed file offset pointer handling race
+
+ -tj4:
+binfmt.patch
+igmp.patch
+scm_send.patch
+scm_send2.patch
+uselib.patch
+0x80_syscall_handler.patch
diff -Naur linux-2.4.26-tj3/Makefile linux-2.4.26-tj4/Makefile
--- linux-2.4.26-tj3/Makefile	2004-11-17 12:54:22.000000000 +0100
+++ linux-2.4.28-tj4/Makefile	2004-11-17 18:03:06.000000000 +0100
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 26
-EXTRAVERSION = -tj3
+EXTRAVERSION = -tj4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
