Date: Tue, 25 Apr 2000 21:17:43 +0400 (MSD) From: jason@express.ru To: FreeBSD-gnats-submit@freebsd.org Subject: kern/18209: rlimits are never checked in exec() if executable format is ELF Message-ID: <200004251717.VAA00672@jsn.kmost.express.ru>
next in thread | raw e-mail | index | archive | help
>Number: 18209
>Category: kern
>Synopsis: rlimits are never checked in exec() if executable format is ELF
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Apr 25 10:20:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator: Dmitry Kim
>Release: FreeBSD 4.0-RELEASE i386
>Organization:
TSB "Russian Express"
>Environment:
Any version of FreeBSD from 3.0 to CURRENT
>Description:
when handling exec*() system calls, FreeBSD checks if the new executable image
memory requirements fit into active RLIMIT_* bounds. if they do not fit,
exec*() fails returning ENOMEM. The problem is, this check is never done for
ELF binaries, thus, ELF-format program can grab all available memory, no matter
how low *rlimits are.
>How-To-Repeat:
/*
* This program demonstrates a leak in freebsd exec(), which [erroneously]
* allows ELF program to get as much memory as it wishes, ignoring *rlimit
* settings, while [correctly] denying any non-ELF program to exceed *rlimit
* settings on exec().
* How to use:
* gcc -elf -o m_elf m.c # compat 3 probably required for fbsd4
* gcc -aout -o m_aout m.c
* /usr/bin/limits -d 1 ./m_aout
* /usr/bin/limits -d 1 ./m_elf
* you'll see the difference.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
char a[ 10000000 ] ;
int main( int ac, char **av ) {
memset( a, 1, sizeof(a) ) ;
puts( "sleeping" ) ;
sleep( 100 ) ;
return 0 ;
}
>Fix:
Index: kern/imgact_elf.c
===================================================================
RCS file: /home/cvsroot/jsn/sys/kern/imgact_elf.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- kern/imgact_elf.c 2000/04/17 10:30:39 1.1.1.1
+++ kern/imgact_elf.c 2000/04/25 16:52:11 1.4
@@ -451,7 +451,39 @@
return ENOEXEC;
}
phdr = (const Elf_Phdr*)(imgp->image_header + hdr->e_phoff);
+
+ /* we better check rlimits *before* new vmspace is exec()-ed */
+ for (i = 0; i < hdr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_LOAD) { /* Loadable segment */
+ /*
+ * Is this .text or .data ??
+ *
+ * We only handle one each of those yet XXX
+ */
+ if (hdr->e_entry >= phdr[i].p_vaddr &&
+ hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
+ text_addr = trunc_page(phdr[i].p_vaddr);
+ text_size = round_page(phdr[i].p_memsz +
+ phdr[i].p_vaddr -
+ text_addr);
+ entry = (u_long)hdr->e_entry;
+ } else {
+ data_addr = trunc_page(phdr[i].p_vaddr);
+ data_size = round_page(phdr[i].p_memsz +
+ phdr[i].p_vaddr -
+ data_addr);
+ }
+ }
+ }
+
+ if (text_size > MAXTSIZ ||
+ text_size + data_size >
+ imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) {
+ error = ENOMEM ;
+ goto fail ;
+ }
+
/*
* From this point on, we may have resources that need to be freed.
*/
@@ -481,25 +513,6 @@
phdr[i].p_memsz,
phdr[i].p_filesz, prot)) != 0)
goto fail;
-
- /*
- * Is this .text or .data ??
- *
- * We only handle one each of those yet XXX
- */
- if (hdr->e_entry >= phdr[i].p_vaddr &&
- hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
- text_addr = trunc_page(phdr[i].p_vaddr);
- text_size = round_page(phdr[i].p_memsz +
- phdr[i].p_vaddr -
- text_addr);
- entry = (u_long)hdr->e_entry;
- } else {
- data_addr = trunc_page(phdr[i].p_vaddr);
- data_size = round_page(phdr[i].p_memsz +
- phdr[i].p_vaddr -
- data_addr);
- }
break;
case PT_INTERP: /* Path to interpreter */
if (phdr[i].p_filesz > MAXPATHLEN ||
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200004251717.VAA00672>
