diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index f08159818443..52b590dc308e 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -846,10 +846,9 @@ svr4_sys_break(td, uap)
 
 	if (new > old) {
 		vm_size_t diff;
-		if (swap_pager_full) {
-			return (ENOMEM);
-		}
 		diff = new - old;
+		if (vm->vm_map.size + diff > p->p_rlimit[RLIMIT_VMEM].rlim_cur)
+			return(ENOMEM);
 		rv = vm_map_find(&vm->vm_map, NULL, 0, &old, diff, FALSE,
 			VM_PROT_ALL, VM_PROT_ALL, 0);
 		if (rv != KERN_SUCCESS) {
diff --git a/sys/compat/svr4/svr4_resource.c b/sys/compat/svr4/svr4_resource.c
index 289e6fa333f2..2d7a0eaffaa3 100644
--- a/sys/compat/svr4/svr4_resource.c
+++ b/sys/compat/svr4/svr4_resource.c
@@ -108,7 +108,7 @@ svr4_to_native_rl(rl)
 	case SVR4_RLIMIT_NOFILE:
 		return RLIMIT_NOFILE;
 	case SVR4_RLIMIT_VMEM:
-		return RLIMIT_RSS;
+		return RLIMIT_VMEM;
 	default:
 		return -1;
 	}
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 352f4c010fc3..c7e64e68cf53 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -590,6 +590,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
 	vm_prot_t prot;
 	u_long text_size = 0, data_size = 0;
 	u_long text_addr = 0, data_addr = 0;
+	u_long seg_size, seg_addr;
 	u_long addr, entry = 0, proghdr = 0;
 	vm_offset_t maxuser, usrstack, pagesize;
 	int error, i;
@@ -689,22 +690,44 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
 			    pagesize)) != 0)
   				goto fail;
 
+			seg_addr = trunc_page(phdr[i].p_vaddr);
+			seg_size = round_page(phdr[i].p_memsz +
+					phdr[i].p_vaddr - seg_addr);
+
 			/*
-			 * Is this .text or .data ??
-			 *
-			 * We only handle one each of those yet XXX
+			 * Is this .text or .data?  Use VM_PROT_WRITE
+			 * to distinguish between the two for the purposes
+			 * of limit checking and vmspace fields.
 			 */
+			if (prot & VM_PROT_WRITE) {
+				data_size += seg_size;
+				if (data_addr == 0)
+					data_addr = seg_addr;
+			} else {
+				text_size += seg_size;
+				if (text_addr == 0)
+					text_addr = seg_addr;
+			}
+
+			/*
+			 * Check limits.  It should be safe to check the
+			 * limits after loading the segment since we do
+			 * not actually fault in all the segment's pages.
+			 */
+			if (data_size >
+			    imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur ||
+			    text_size > maxtsiz ||
+			    data_size + text_size >
+			    imgp->proc->p_rlimit[RLIMIT_VMEM].rlim_cur) {
+				error = ENOMEM;
+				goto fail;
+			}
+
+			/* Does the entry point belongs to this segment? */
 			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 */