Page MenuHomeFreeBSD

D19689.diff
No OneTemporary

D19689.diff

Index: head/sys/kern/imgact_elf.c
===================================================================
--- head/sys/kern/imgact_elf.c
+++ head/sys/kern/imgact_elf.c
@@ -812,6 +812,83 @@
return (res);
}
+static int
+__elfN(enforce_limits)(struct image_params *imgp, const Elf_Ehdr *hdr,
+ const Elf_Phdr *phdr, u_long et_dyn_addr)
+{
+ struct vmspace *vmspace;
+ const char *err_str;
+ u_long text_size, data_size, total_size, text_addr, data_addr;
+ u_long seg_size, seg_addr;
+ int i;
+
+ err_str = NULL;
+ text_size = data_size = total_size = text_addr = data_addr = 0;
+
+ for (i = 0; i < hdr->e_phnum; i++) {
+ if (phdr[i].p_type != PT_LOAD || phdr[i].p_memsz == 0)
+ continue;
+
+ seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr);
+ seg_size = round_page(phdr[i].p_memsz +
+ phdr[i].p_vaddr + et_dyn_addr - seg_addr);
+
+ /*
+ * Make the largest executable segment the official
+ * text segment and all others data.
+ *
+ * Note that obreak() assumes that data_addr + data_size == end
+ * of data load area, and the ELF file format expects segments
+ * to be sorted by address. If multiple data segments exist,
+ * the last one will be used.
+ */
+
+ if ((phdr[i].p_flags & PF_X) != 0 && text_size < seg_size) {
+ text_size = seg_size;
+ text_addr = seg_addr;
+ } else {
+ data_size = seg_size;
+ data_addr = seg_addr;
+ }
+ total_size += seg_size;
+ }
+
+ if (data_addr == 0 && data_size == 0) {
+ data_addr = text_addr;
+ data_size = text_size;
+ }
+
+ /*
+ * Check limits. It should be safe to check the
+ * limits after loading the segments since we do
+ * not actually fault in all the segments pages.
+ */
+ PROC_LOCK(imgp->proc);
+ if (data_size > lim_cur_proc(imgp->proc, RLIMIT_DATA))
+ err_str = "Data segment size exceeds process limit";
+ else if (text_size > maxtsiz)
+ err_str = "Text segment size exceeds system limit";
+ else if (total_size > lim_cur_proc(imgp->proc, RLIMIT_VMEM))
+ err_str = "Total segment size exceeds process limit";
+ else if (racct_set(imgp->proc, RACCT_DATA, data_size) != 0)
+ err_str = "Data segment size exceeds resource limit";
+ else if (racct_set(imgp->proc, RACCT_VMEM, total_size) != 0)
+ err_str = "Total segment size exceeds resource limit";
+ PROC_UNLOCK(imgp->proc);
+ if (err_str != NULL) {
+ uprintf("%s\n", err_str);
+ return (ENOMEM);
+ }
+
+ vmspace = imgp->proc->p_vmspace;
+ vmspace->vm_tsize = text_size >> PAGE_SHIFT;
+ vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
+ vmspace->vm_dsize = data_size >> PAGE_SHIFT;
+ vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
+
+ return (0);
+}
+
/*
* Impossible et_dyn_addr initial value indicating that the real base
* must be calculated later with some randomization applied.
@@ -827,13 +904,12 @@
Elf_Auxargs *elf_auxargs;
struct vmspace *vmspace;
vm_map_t map;
- const char *err_str, *newinterp;
+ const char *newinterp;
char *interp, *interp_buf, *path;
Elf_Brandinfo *brand_info;
struct sysentvec *sv;
vm_prot_t prot;
- u_long text_size, data_size, total_size, text_addr, data_addr;
- u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
+ u_long addr, baddr, et_dyn_addr, entry, proghdr;
u_long maxalign, mapsz, maxv, maxv1;
uint32_t fctl0;
int32_t osrel;
@@ -872,10 +948,9 @@
baddr = 0;
osrel = 0;
fctl0 = 0;
- text_size = data_size = total_size = text_addr = data_addr = 0;
entry = proghdr = 0;
interp_name_len = 0;
- err_str = newinterp = NULL;
+ newinterp = NULL;
interp = interp_buf = NULL;
td = curthread;
maxalign = PAGE_SIZE;
@@ -1064,30 +1139,6 @@
<= phdr[i].p_filesz)
proghdr = phdr[i].p_vaddr + hdr->e_phoff +
et_dyn_addr;
-
- seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr);
- seg_size = round_page(phdr[i].p_memsz +
- phdr[i].p_vaddr + et_dyn_addr - seg_addr);
-
- /*
- * Make the largest executable segment the official
- * text segment and all others data.
- *
- * Note that obreak() assumes that data_addr +
- * data_size == end of data load area, and the ELF
- * file format expects segments to be sorted by
- * address. If multiple data segments exist, the
- * last one will be used.
- */
-
- if (phdr[i].p_flags & PF_X && text_size < seg_size) {
- text_size = seg_size;
- text_addr = seg_addr;
- } else {
- data_size = seg_size;
- data_addr = seg_addr;
- }
- total_size += seg_size;
break;
case PT_PHDR: /* Program header table info */
proghdr = phdr[i].p_vaddr + et_dyn_addr;
@@ -1096,41 +1147,12 @@
break;
}
}
-
- if (data_addr == 0 && data_size == 0) {
- data_addr = text_addr;
- data_size = text_size;
- }
- entry = (u_long)hdr->e_entry + et_dyn_addr;
-
- /*
- * Check limits. It should be safe to check the
- * limits after loading the segments since we do
- * not actually fault in all the segments pages.
- */
- PROC_LOCK(imgp->proc);
- if (data_size > lim_cur_proc(imgp->proc, RLIMIT_DATA))
- err_str = "Data segment size exceeds process limit";
- else if (text_size > maxtsiz)
- err_str = "Text segment size exceeds system limit";
- else if (total_size > lim_cur_proc(imgp->proc, RLIMIT_VMEM))
- err_str = "Total segment size exceeds process limit";
- else if (racct_set(imgp->proc, RACCT_DATA, data_size) != 0)
- err_str = "Data segment size exceeds resource limit";
- else if (racct_set(imgp->proc, RACCT_VMEM, total_size) != 0)
- err_str = "Total segment size exceeds resource limit";
- if (err_str != NULL) {
- PROC_UNLOCK(imgp->proc);
- uprintf("%s\n", err_str);
- error = ENOMEM;
+ error = __elfN(enforce_limits)(imgp, hdr, phdr, et_dyn_addr);
+ if (error != 0)
goto ret;
- }
- vmspace->vm_tsize = text_size >> PAGE_SHIFT;
- vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
- vmspace->vm_dsize = data_size >> PAGE_SHIFT;
- vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
+ entry = (u_long)hdr->e_entry + et_dyn_addr;
/*
* We load the dynamic linker where a userland call
@@ -1148,7 +1170,6 @@
} else {
map->anon_loc = addr;
}
- PROC_UNLOCK(imgp->proc);
imgp->entry_addr = entry;

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 14, 6:44 AM (20 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16638645
Default Alt Text
D19689.diff (5 KB)

Event Timeline