All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH x7] misc fixes from 2.4.33-ow1
@ 2006-08-20  2:04 Solar Designer
  2006-08-20  9:15 ` [PATCH] binfmt_elf.c : the BAD_ADDR macro again Willy Tarreau
  0 siblings, 1 reply; 23+ messages in thread
From: Solar Designer @ 2006-08-20  2:04 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3157 bytes --]

Willy and all,

Attached are 7 small changes from 2.4.33-ow1, as separate patches.  I do
not feel that these warrant separate messages.

linux-2.4.33-ow1-BAD_ADDR.diff

This one is a one-liner, in binfmt_elf.c:

-#define BAD_ADDR(x)	((unsigned long)(x) > TASK_SIZE)
+#define BAD_ADDR(x)	((unsigned long)(x) >= TASK_SIZE)

I feel that it is more logical to have BAD_ADDR() defined in this way:
indeed, the first kernel-space address is unusable for userspace.  I
don't think this change affects anything, and we had it in -ow for a
couple of years.

linux-2.4.33-ow1-create_elf_tables.diff
linux-2.4.33-ow1-elf_core_dump.diff

These two are pieces from my more elaborate version of the coredump
vulnerability fix:

	http://www.isec.pl/vulnerabilities/isec-0023-coredump.txt

The first one does for env_end the same thing that the minimal fix did
for arg_end, and the second one makes things more correct for 64-bit
archs.  Neither fixes any known security problem, although I would not
be surprised if there's a yet unexplored attack vector that uses env_end.
This has been in -ow for over a year.

linux-2.4.33-ow1-load_elf_library.diff

This rejects ELF libraries with elf_ex.e_phnum == 0 earlier in the code.
Without this change, such libraries would be rejected anyway - after a
kmalloc() and a kernel_read(), both of zero bytes.  This has been in -ow
for almost two years.

linux-2.4.33-ow1-mremap-arch-sanity.diff

This makes 32-bit emulation mmap/mremap calls on 64-bit archs refuse to
accept/return addresses beyond the 32-bit user address space.  This is
about correctness, not security.  Andrea Arcangeli did not like these,
commenting on them like: "supeflous, reject, must BUG if something", to
which I replied:

I don't see how these architecture-specific checks are superfluous.
The non-arch-specific code has only checked against TASK_SIZE, not
against the lower limit present with 32-bit syscall emulation on
64-bit archs.  Yes, with other checks in the arch-specific code, my
added checks are pretty much limited to just the special case of
addr == end, but such addr's are invalid under 32-bit syscall
emulation and should not be accepted/returned by syscalls.

BUG() would be wrong, it would introduce a DoS.

(That discussion occurred in December, 2003; I kept the changes in -ow
since then.)

linux-2.4.33-ow1-proc_file_read.diff

This is hardening of proc_file_read() similar to what was recently done
in 2.6 in response to the vulnerability discovery.  While 2.4 kernels
were not vulnerable due to differences in the lseek implementation, I
prefer to harden the reads as well.  This change is new with 2.4.33-ow1.

linux-2.4.33-ow1-proc-nosuid-noexec-nodev.diff

This attempts to make procfs MS_NOSUID | MS_NOEXEC | MS_NODEV by
default, in response to another recently discovered 2.6-specific
vulnerability (so for 2.4 this is just proactive hardening).  Most of
the changes in this patch were in -ow patches for years (in order to
enable the uid= and gid= mount options to work).  Only the specific
"s->s_flags |= ..." line is a recent addition, and this one has not yet
been tested to actually make a difference.

Thanks,

Alexander

[-- Attachment #2: linux-2.4.33-ow1-BAD_ADDR.diff --]
[-- Type: text/plain, Size: 375 bytes --]

diff -urpPX nopatch linux-2.4.33/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.33/fs/binfmt_elf.c	Sat Aug 12 08:48:39 2006
+++ linux/fs/binfmt_elf.c	Sat Aug 12 08:51:47 2006
@@ -73,5 +76,5 @@
 };
 
-#define BAD_ADDR(x)	((unsigned long)(x) > TASK_SIZE)
+#define BAD_ADDR(x)	((unsigned long)(x) >= TASK_SIZE)
 
 static int set_brk(unsigned long start, unsigned long end)

[-- Attachment #3: linux-2.4.33-ow1-create_elf_tables.diff --]
[-- Type: text/plain, Size: 509 bytes --]

diff -urpPX nopatch linux-2.4.33/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.33/fs/binfmt_elf.c	Sat Aug 12 08:48:39 2006
+++ linux/fs/binfmt_elf.c	Sat Aug 12 08:51:47 2006
@@ -232,6 +244,7 @@ create_elf_tables(char *p, int argc, int
 	}
 	__put_user(NULL, argv);
 	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+	current->mm->env_end = (unsigned long) p;
 	while (envc-->0) {
 		__put_user((elf_caddr_t)(unsigned long)p,envp++);
 		len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);

[-- Attachment #4: linux-2.4.33-ow1-elf_core_dump.diff --]
[-- Type: text/plain, Size: 691 bytes --]

diff -urpPX nopatch linux-2.4.33/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.33/fs/binfmt_elf.c	Sat Aug 12 08:48:39 2006
+++ linux/fs/binfmt_elf.c	Sat Aug 12 08:51:47 2006
@@ -1166,9 +1206,12 @@ static int elf_core_dump(long signr, str
 	{
 		unsigned int i, len;
 
-		len = current->mm->arg_end - current->mm->arg_start;
-		if (len >= ELF_PRARGSZ)
-			len = ELF_PRARGSZ-1;
+		if (current->mm->arg_end > current->mm->arg_start) {
+			len = current->mm->arg_end - current->mm->arg_start;
+			if (len >= ELF_PRARGSZ)
+				len = ELF_PRARGSZ-1;
+		} else
+			len = 0;
 		copy_from_user(&psinfo.pr_psargs,
 			      (const char *)current->mm->arg_start, len);
 		for(i = 0; i < len; i++)

[-- Attachment #5: linux-2.4.33-ow1-load_elf_library.diff --]
[-- Type: text/plain, Size: 649 bytes --]

diff -urpPX nopatch linux-2.4.33/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.33/fs/binfmt_elf.c	Sat Aug 12 08:48:39 2006
+++ linux/fs/binfmt_elf.c	Sat Aug 12 08:51:47 2006
@@ -945,8 +983,9 @@ static int load_elf_library(struct file 
 		goto out;
 
 	/* First of all, some simple consistency checks */
-	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
-	   !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
+	if (elf_ex.e_type != ET_EXEC ||
+	    elf_ex.e_phnum < 1 || elf_ex.e_phnum > 2 ||
+	    !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
 		goto out;
 
 	/* Now read in all of the header information */

[-- Attachment #6: linux-2.4.33-ow1-mremap-arch-sanity.diff --]
[-- Type: text/plain, Size: 1945 bytes --]

diff -urpPX nopatch linux-2.4.33/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- linux-2.4.33/arch/alpha/kernel/osf_sys.c	Fri Jun 13 18:51:29 2003
+++ linux/arch/alpha/kernel/osf_sys.c	Sat Aug 12 08:51:47 2006
@@ -1346,6 +1346,8 @@ arch_get_unmapped_area(struct file *filp
 
 	if (len > limit)
 		return -ENOMEM;
+	if (addr >= limit)
+		return -ENOMEM;
 
 	/* First, see if the given suggestion fits.
 
diff -urpPX nopatch linux-2.4.33/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- linux-2.4.33/arch/sparc/kernel/sys_sparc.c	Mon Aug 25 15:44:40 2003
+++ linux/arch/sparc/kernel/sys_sparc.c	Sat Aug 12 08:51:47 2006
@@ -52,6 +52,8 @@ unsigned long arch_get_unmapped_area(str
 	/* See asm-sparc/uaccess.h */
 	if (len > TASK_SIZE - PAGE_SIZE)
 		return -ENOMEM;
+	if (addr >= TASK_SIZE - PAGE_SIZE)
+		return -ENOMEM;
 	if (ARCH_SUN4C_SUN4 && len > 0x20000000)
 		return -ENOMEM;
 	if (!addr)
diff -urpPX nopatch linux-2.4.33/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- linux-2.4.33/arch/sparc64/kernel/sys_sparc.c	Mon Aug 25 15:44:40 2003
+++ linux/arch/sparc64/kernel/sys_sparc.c	Sat Aug 12 08:51:47 2006
@@ -63,6 +63,8 @@ unsigned long arch_get_unmapped_area(str
 		task_size = 0xf0000000UL;
 	if (len > task_size || len > -PAGE_OFFSET)
 		return -ENOMEM;
+	if (addr >= task_size)
+		return -ENOMEM;
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
 
diff -urpPX nopatch linux-2.4.33/arch/x86_64/kernel/sys_x86_64.c linux/arch/x86_64/kernel/sys_x86_64.c
--- linux-2.4.33/arch/x86_64/kernel/sys_x86_64.c	Fri Nov 28 21:26:19 2003
+++ linux/arch/x86_64/kernel/sys_x86_64.c	Sat Aug 12 08:51:47 2006
@@ -94,6 +94,8 @@ unsigned long arch_get_unmapped_area(str
 	if (len > end)
 		return -ENOMEM;
 	addr = PAGE_ALIGN(addr);
+	if (addr >= end)
+		return -ENOMEM;
 
 	for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
 		/* At this point:  (!vma || addr < vma->vm_end). */

[-- Attachment #7: linux-2.4.33-ow1-proc_file_read.diff --]
[-- Type: text/plain, Size: 739 bytes --]

diff -urpPX nopatch linux-2.4.33/fs/proc/generic.c linux/fs/proc/generic.c
--- linux-2.4.33/fs/proc/generic.c	Wed Jan 19 17:10:11 2005
+++ linux/fs/proc/generic.c	Sun Aug 13 20:59:16 2006
@@ -62,11 +62,17 @@ proc_file_read(struct file * file, char 
 	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
 
+	if (pos < 0 || pos >= MAX_NON_LFS)
+		eof = 1;
+	else if (nbytes > MAX_NON_LFS - pos)
+		nbytes = MAX_NON_LFS - pos;
+
 	while ((nbytes > 0) && !eof)
 	{
-		count = MIN(PROC_BLOCK_SIZE, nbytes);
-		if ((unsigned)pos > INT_MAX)
+		/* This is redundant, but better safe than sorry */
+		if (pos < 0 || pos >= MAX_NON_LFS)
 			break;
+		count = MIN(PROC_BLOCK_SIZE, nbytes);
 
 		start = NULL;
 		if (dp->get_info) {

[-- Attachment #8: linux-2.4.33-ow1-proc-nosuid-noexec-nodev.diff --]
[-- Type: text/plain, Size: 2706 bytes --]

diff -urpPX nopatch linux-2.4.33/fs/proc/generic.c linux/fs/proc/generic.c
--- linux-2.4.33/fs/proc/generic.c	Wed Jan 19 17:10:11 2005
+++ linux/fs/proc/generic.c	Sun Aug 13 20:59:16 2006
@@ -396,7 +402,9 @@ static int proc_register(struct proc_dir
 static void proc_kill_inodes(struct proc_dir_entry *de)
 {
 	struct list_head *p;
-	struct super_block *sb = proc_mnt->mnt_sb;
+	struct super_block *sb = proc_super;
+
+	if (!sb) return;
 
 	/*
 	 * Actually it's a partial revoke().
diff -urpPX nopatch linux-2.4.33/fs/proc/inode.c linux/fs/proc/inode.c
--- linux-2.4.33/fs/proc/inode.c	Fri Nov 28 21:26:21 2003
+++ linux/fs/proc/inode.c	Wed Aug 16 04:54:57 2006
@@ -73,8 +74,6 @@ static void proc_delete_inode(struct ino
 	}
 }
 
-struct vfsmount *proc_mnt;
-
 static void proc_read_inode(struct inode * inode)
 {
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -176,12 +179,15 @@ out_fail:
 	goto out;
 }			
 
+struct super_block *proc_super = NULL;
+
 struct super_block *proc_read_super(struct super_block *s,void *data, 
 				    int silent)
 {
 	struct inode * root_inode;
 	struct task_struct *p;
 
+	s->s_flags |= MS_NOSUID | MS_NOEXEC | MS_NODEV;
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
 	s->s_magic = PROC_SUPER_MAGIC;
@@ -201,6 +207,10 @@ struct super_block *proc_read_super(stru
 	if (!s->s_root)
 		goto out_no_root;
 	parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
+	if (!proc_super) {
+		s->s_count++;
+		proc_super = s;
+	}
 	return s;
 
 out_no_root:
diff -urpPX nopatch linux-2.4.33/fs/proc/root.c linux/fs/proc/root.c
--- linux-2.4.33/fs/proc/root.c	Wed Nov 17 14:54:21 2004
+++ linux/fs/proc/root.c	Sat Aug 12 08:51:47 2006
@@ -30,12 +31,6 @@ void __init proc_root_init(void)
 	int err = register_filesystem(&proc_fs_type);
 	if (err)
 		return;
-	proc_mnt = kern_mount(&proc_fs_type);
-	err = PTR_ERR(proc_mnt);
-	if (IS_ERR(proc_mnt)) {
-		unregister_filesystem(&proc_fs_type);
-		return;
-	}
 	proc_misc_init();
 	proc_net = proc_mkdir("net", 0);
 	proc_net_stat = proc_mkdir("net/stat", NULL);
diff -urpPX nopatch linux-2.4.33/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- linux-2.4.33/include/linux/proc_fs.h	Sat Aug 12 08:48:39 2006
+++ linux/include/linux/proc_fs.h	Sat Aug 12 08:51:47 2006
@@ -96,7 +96,7 @@ extern struct proc_dir_entry *create_pro
 						struct proc_dir_entry *parent);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
-extern struct vfsmount *proc_mnt;
+extern struct super_block *proc_super;
 extern struct super_block *proc_read_super(struct super_block *,void *,int);
 extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *);
 

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2006-09-01 14:23 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-20  2:04 [PATCH x7] misc fixes from 2.4.33-ow1 Solar Designer
2006-08-20  9:15 ` [PATCH] binfmt_elf.c : the BAD_ADDR macro again Willy Tarreau
2006-08-20 15:51   ` Solar Designer
2006-08-20 16:23     ` Willy Tarreau
2006-08-21 20:35       ` Ernie Petrides
2006-08-21 21:11         ` Willy Tarreau
2006-08-21 23:36           ` Ernie Petrides
2006-08-22  3:07             ` printk()s of user-supplied strings (Re: [PATCH] binfmt_elf.c : the BAD_ADDR macro again) Solar Designer
2006-08-22 20:23               ` Ernie Petrides
2006-08-22 20:34                 ` printk()s of user-supplied strings Willy Tarreau
2006-08-24 16:44                 ` printk()s of user-supplied strings (Re: [PATCH] binfmt_elf.c : the BAD_ADDR macro again) Solar Designer
2006-08-24 16:46                   ` Willy Tarreau
2006-08-26  2:29                     ` Solar Designer
2006-08-26  8:22                       ` Willy Tarreau
2006-08-26 23:13                         ` Solar Designer
2006-08-27 20:04                           ` printk()s of user-supplied strings Willy Tarreau
2006-08-28  1:52                             ` Solar Designer
1970-01-01  0:16                               ` Pavel Machek
2006-08-28  8:02                               ` Willy Tarreau
2006-08-28 11:17                                 ` Krzysztof Halasa
2006-08-30  6:15                                   ` Willy Tarreau
2006-08-28 17:35                               ` Valdis.Kletnieks
2006-08-22  4:36             ` [PATCH] binfmt_elf.c : the BAD_ADDR macro again Willy Tarreau

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.