diff -u linux-2.4.28-tj1/arch/ia64/ia32/sys_ia32.c linux-2.4.28-tj2/arch/ia64/ia32/sys_ia32.c
--- linux-2.4.28-tj1/arch/ia64/ia32/sys_ia32.c	2004-11-17 15:45:14.000000000 +0100
+++ linux-2.4.28-tj2/arch/ia64/ia32/sys_ia32.c	2005-01-07 17:14:12.000000000 +0100
@@ -1377,6 +1377,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)
@@ -1437,10 +1442,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 -u linux-2.4.28-tj1/arch/parisc/kernel/sys_parisc32.c linux-2.4.28-tj2/arch/parisc/kernel/sys_parisc32.c
--- linux-2.4.28-tj1/arch/parisc/kernel/sys_parisc32.c	2004-11-17 15:45:14.000000000 +0100
+++ linux-2.4.28-tj2/arch/parisc/kernel/sys_parisc32.c	2005-01-07 17:14:12.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 -u linux-2.4.28-tj1/arch/sparc64/kernel/sys_sparc32.c linux-2.4.28-tj2/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.28-tj1/arch/sparc64/kernel/sys_sparc32.c	2004-11-17 15:45:14.000000000 +0100
+++ linux-2.4.28-tj2/arch/sparc64/kernel/sys_sparc32.c	2005-01-07 17:14:12.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 -u linux-2.4.28-tj1/fs/binfmt_aout.c linux-2.4.28-tj2/fs/binfmt_aout.c
--- linux-2.4.28-tj1/fs/binfmt_aout.c	2004-11-17 15:45:14.000000000 +0100
+++ linux-2.4.28-tj2/fs/binfmt_aout.c	2005-01-07 17:14:58.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 -u linux-2.4.28-tj1/fs/binfmt_elf.c linux-2.4.28-tj2/fs/binfmt_elf.c
--- linux-2.4.28-tj1/fs/binfmt_elf.c	2004-11-17 15:45:14.000000000 +0100
+++ linux-2.4.28-tj2/fs/binfmt_elf.c	2005-01-07 17:15:25.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)
@@ -370,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;
@@ -407,7 +407,7 @@
 		goto out;
 	}
 
-	do_brk(0, text_data);
+	do_brk_locked(0, text_data);
 	if (!interpreter->f_op || !interpreter->f_op->read)
 		goto out;
 	if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
@@ -415,7 +415,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;
 
@@ -1271,7 +1271,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 -u linux-2.4.28-tj1/include/linux/mm.h linux-2.4.28-tj2/include/linux/mm.h
--- linux-2.4.28-tj1/include/linux/mm.h	2004-11-17 19:08:54.000000000 +0100
+++ linux-2.4.28-tj2/include/linux/mm.h	2005-01-07 17:14:19.000000000 +0100
@@ -601,6 +601,7 @@
 extern int do_munmap(struct mm_struct *, unsigned long, size_t);
 
 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 -u linux-2.4.28-tj1/kernel/ksyms.c linux-2.4.28-tj2/kernel/ksyms.c
--- linux-2.4.28-tj1/kernel/ksyms.c	2004-11-17 16:48:18.000000000 +0100
+++ linux-2.4.28-tj2/kernel/ksyms.c	2005-01-07 17:14:19.000000000 +0100
@@ -90,6 +90,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 -u linux-2.4.28-tj1/mm/mmap.c linux-2.4.28-tj2/mm/mmap.c
--- linux-2.4.28-tj1/mm/mmap.c	2004-11-17 16:53:36.000000000 +0100
+++ linux-2.4.28-tj2/mm/mmap.c	2005-01-07 17:14:19.000000000 +0100
@@ -1401,6 +1401,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 -u linux-2.4.28-tj1/README.tj linux-2.4.28-tj2/README.tj
--- linux-2.4.28-tj1/README.tj	2004-11-17 18:02:12.000000000 +0100
+++ linux-2.4.28-tj2/README.tj	2005-01-07 17:16:55.000000000 +0100
@@ -25,0 +26,7 @@
+
+2.4.28-tj2
+	igmp.patch
+	scm_send.patch
+	scm_send2.patch
+	uselib.patch
+	0x80_syscall_handler.patch
only in patch2:
unchanged:
--- linux-2.4.28/arch/mips/kernel/irixelf.c	2003-08-25 13:44:40.000000000 +0200
+++ linux-2.4.28-tj2/arch/mips/kernel/irixelf.c	2005-01-07 17:14:19.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;
 }
only in patch2:
unchanged:
--- linux-2.4.28/arch/mips64/kernel/linux32.c	2004-11-17 12:54:21.000000000 +0100
+++ linux-2.4.28-tj2/arch/mips64/kernel/linux32.c	2005-01-07 17:14:12.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))) +
only in patch2:
unchanged:
--- linux-2.4.28/arch/ppc64/kernel/sys_ppc32.c	2004-11-17 12:54:21.000000000 +0100
+++ linux-2.4.28-tj2/arch/ppc64/kernel/sys_ppc32.c	2005-01-07 17:14:12.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))) +
only in patch2:
unchanged:
--- linux-2.4.28/arch/sparc64/kernel/binfmt_aout32.c	2002-08-03 02:39:43.000000000 +0200
+++ linux-2.4.28-tj2/arch/sparc64/kernel/binfmt_aout32.c	2005-01-07 17:14:19.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;
only in patch2:
unchanged:
--- linux-2.4.28/arch/s390x/kernel/linux32.c	2004-11-17 12:54:21.000000000 +0100
+++ linux-2.4.28-tj2/arch/s390x/kernel/linux32.c	2005-01-07 17:14:12.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))) +
only in patch2:
unchanged:
--- linux-2.4.28/arch/x86_64/ia32/ia32entry.S	2004-08-08 01:26:04.000000000 +0200
+++ linux-2.4.28-tj2/arch/x86_64/ia32/ia32entry.S	2005-01-07 17:13:44.000000000 +0100
@@ -52,6 +52,7 @@
 ENTRY(ia32_syscall)
 	swapgs	
 	sti
+	movl %eax,%eax	
 	pushq %rax
 	cld
 	SAVE_ARGS
only in patch2:
unchanged:
--- linux-2.4.28/arch/x86_64/ia32/socket32.c	2004-11-17 12:54:21.000000000 +0100
+++ linux-2.4.28-tj2/arch/x86_64/ia32/socket32.c	2005-01-07 17:14:12.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;
 
only in patch2:
unchanged:
--- linux-2.4.28/include/asm-x86_64/socket32.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.28-tj2/include/asm-x86_64/socket32.h	2005-01-07 17:14:12.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)
only in patch2:
unchanged:
--- linux-2.4.28/include/linux/socket.h	2004-11-17 12:54:22.000000000 +0100
+++ linux-2.4.28-tj2/include/linux/socket.h	2005-01-07 17:14:03.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
only in patch2:
unchanged:
--- linux-2.4.28/net/core/scm.c	2001-12-21 18:42:05.000000000 +0100
+++ linux-2.4.28-tj2/net/core/scm.c	2005-01-07 17:14:03.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)
only in patch2:
unchanged:
--- linux-2.4.28/net/ipv4/igmp.c	2004-08-08 01:26:06.000000000 +0200
+++ linux-2.4.28-tj2/net/ipv4/igmp.c	2005-01-07 17:13:55.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 */
only in patch2:
unchanged:
--- linux-2.4.28/net/ipv4/ip_sockglue.c	2004-08-08 01:26:06.000000000 +0200
+++ linux-2.4.28-tj2/net/ipv4/ip_sockglue.c	2005-01-07 17:14:03.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) {
only in patch2:
unchanged:
--- linux-2.4.28/net/ipv6/datagram.c	2004-11-17 12:54:22.000000000 +0100
+++ linux-2.4.28-tj2/net/ipv6/datagram.c	2005-01-07 17:14:03.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;
 		}
only in patch2:
unchanged:
--- linux-2.4.28/net/ipv6/mcast.c	2004-11-17 12:54:22.000000000 +0100
+++ linux-2.4.28-tj2/net/ipv6/mcast.c	2005-01-07 17:13:55.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 */
only in patch2:
unchanged:
--- linux-2.4.28/net/sctp/socket.c	2004-11-17 12:54:22.000000000 +0100
+++ linux-2.4.28-tj2/net/sctp/socket.c	2005-01-07 17:14:03.000000000 +0100
@@ -4090,12 +4090,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.28/Makefile linux-2.4.28-tj1/Makefile
--- linux-2.4.28/Makefile	2004-11-17 12:54:22.000000000 +0100
+++ linux-2.4.28-tj2/Makefile	2004-11-17 18:03:06.000000000 +0100
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 28
-EXTRAVERSION = -tj1
+EXTRAVERSION = -tj2
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
