It seems the routines interpreting ELF headers trust them more than
necessary. To be specific:
1) do_load_elf_binary() can be confused by odd values e_phentsize
impact: the kernel may be coaxed to access the memory outside the
area it has kmalloc()'ed for the phdr table
fix: the kernel refuses to load the binary if e_phentsize !=
sizeof(elf_phdr) (check reused from do_load_elf_interpret())
I have also added this check to do_load_elf_library() to make
things consistent (even it does not use the value)
2) do_load_elf_binary() can be forced to temporarily kmalloc() arbitrary
(subject to the limits imposed by kmalloc() implementation) amount of
non-swappable memory when it reads the phdr table or the interpreter
filename
impact: potential denial of service, not serious (in most cases) but
I am a purist :)
[ Actually, this is quite serious because it is possible to make the
loader block forever when it opens the interpreter (e.g. if the
filename points at a fifo). One needs only several processes of this
sort to hoard all kernel memory. ]
fix: the kernel refuses to load the binary if the size of phdr table
is biger than ELF_EXEC_PAGESIZE (check reused from
do_load_elf_interpret())
the kernel refuses to load the binary (with ENOMEM, is this
right?) if the interpret filename is longer than PAGE_SIZE
(open() would fail anyway)
Affected versions: <=2.0.34pre10, <=2.1.99
[ 2.0.34 and 2.1.108 seem to be affected as well. ]
(Replies by e-mail, please. I am not subscribed to this list.)
--Pavel Kankovsky aka Peak [ Boycott Microsoft--http://www.vcnet.com/bms ]
Here is the patch (against 2.1.98):
--- binfmt_elf.c-2.1.98.orig Mon May 4 14:56:59 1998
+++ binfmt_elf.c-2.1.98 Wed May 6 10:38:27 1998
@@ -440,10 +440,20 @@
!bprm->dentry->d_inode->i_op->default_file_ops->mmap)
goto out;
+ /*
+ * If the size of this structure has changed, then punt, since
+ * we will be doing the wrong thing.
+ */
+ if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
+ goto out;
+
/* Now read in all of the header information */
+ size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
+ if (size > ELF_EXEC_PAGESIZE)
+ goto out;
+
retval = -ENOMEM;
- size = elf_ex.e_phentsize * elf_ex.e_phnum;
elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
if (!elf_phdata)
goto out;
@@ -478,6 +488,10 @@
* is an a.out format binary
*/
+ retval = -ENAMETOOLONG;
+ if (elf_ppnt->p_filesz > PAGE_SIZE)
+ goto out_free_file;
+
retval = -ENOMEM;
elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
GFP_KERNEL);
@@ -836,6 +850,13 @@
!elf_check_arch(elf_ex.e_machine) ||
(!inode->i_op || !inode->i_op->default_file_ops->mmap))
goto out_putf;
+
+ /*
+ * If the size of this structure has changed, then punt, since
+ * we will be doing the wrong thing.
+ */
+ if (elf_ex.e_phentsize != sizeof(struct elf_phdr))
+ goto out;
/* Now read in all of the header information */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu