diff options
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 348 |
1 files changed, 185 insertions, 163 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 537893a16014..d0434406eaeb 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -38,15 +38,13 @@ | |||
38 | #include <linux/security.h> | 38 | #include <linux/security.h> |
39 | #include <linux/syscalls.h> | 39 | #include <linux/syscalls.h> |
40 | #include <linux/random.h> | 40 | #include <linux/random.h> |
41 | 41 | #include <linux/elf.h> | |
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/param.h> | 43 | #include <asm/param.h> |
44 | #include <asm/page.h> | 44 | #include <asm/page.h> |
45 | 45 | ||
46 | #include <linux/elf.h> | 46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); |
47 | 47 | static int load_elf_library(struct file *); | |
48 | static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs); | ||
49 | static int load_elf_library(struct file*); | ||
50 | static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); | 48 | static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); |
51 | extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); | 49 | extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); |
52 | 50 | ||
@@ -59,15 +57,15 @@ extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); | |||
59 | * don't even try. | 57 | * don't even try. |
60 | */ | 58 | */ |
61 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 59 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) |
62 | static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file); | 60 | static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file); |
63 | #else | 61 | #else |
64 | #define elf_core_dump NULL | 62 | #define elf_core_dump NULL |
65 | #endif | 63 | #endif |
66 | 64 | ||
67 | #if ELF_EXEC_PAGESIZE > PAGE_SIZE | 65 | #if ELF_EXEC_PAGESIZE > PAGE_SIZE |
68 | # define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE | 66 | #define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE |
69 | #else | 67 | #else |
70 | # define ELF_MIN_ALIGN PAGE_SIZE | 68 | #define ELF_MIN_ALIGN PAGE_SIZE |
71 | #endif | 69 | #endif |
72 | 70 | ||
73 | #ifndef ELF_CORE_EFLAGS | 71 | #ifndef ELF_CORE_EFLAGS |
@@ -86,7 +84,7 @@ static struct linux_binfmt elf_format = { | |||
86 | .min_coredump = ELF_EXEC_PAGESIZE | 84 | .min_coredump = ELF_EXEC_PAGESIZE |
87 | }; | 85 | }; |
88 | 86 | ||
89 | #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) | 87 | #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) |
90 | 88 | ||
91 | static int set_brk(unsigned long start, unsigned long end) | 89 | static int set_brk(unsigned long start, unsigned long end) |
92 | { | 90 | { |
@@ -104,13 +102,11 @@ static int set_brk(unsigned long start, unsigned long end) | |||
104 | return 0; | 102 | return 0; |
105 | } | 103 | } |
106 | 104 | ||
107 | |||
108 | /* We need to explicitly zero any fractional pages | 105 | /* We need to explicitly zero any fractional pages |
109 | after the data section (i.e. bss). This would | 106 | after the data section (i.e. bss). This would |
110 | contain the junk from the file that should not | 107 | contain the junk from the file that should not |
111 | be in memory */ | 108 | be in memory |
112 | 109 | */ | |
113 | |||
114 | static int padzero(unsigned long elf_bss) | 110 | static int padzero(unsigned long elf_bss) |
115 | { | 111 | { |
116 | unsigned long nbyte; | 112 | unsigned long nbyte; |
@@ -129,7 +125,9 @@ static int padzero(unsigned long elf_bss) | |||
129 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items)) | 125 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items)) |
130 | #define STACK_ROUND(sp, items) \ | 126 | #define STACK_ROUND(sp, items) \ |
131 | ((15 + (unsigned long) ((sp) + (items))) &~ 15UL) | 127 | ((15 + (unsigned long) ((sp) + (items))) &~ 15UL) |
132 | #define STACK_ALLOC(sp, len) ({ elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; old_sp; }) | 128 | #define STACK_ALLOC(sp, len) ({ \ |
129 | elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; \ | ||
130 | old_sp; }) | ||
133 | #else | 131 | #else |
134 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items)) | 132 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items)) |
135 | #define STACK_ROUND(sp, items) \ | 133 | #define STACK_ROUND(sp, items) \ |
@@ -138,7 +136,7 @@ static int padzero(unsigned long elf_bss) | |||
138 | #endif | 136 | #endif |
139 | 137 | ||
140 | static int | 138 | static int |
141 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | 139 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, |
142 | int interp_aout, unsigned long load_addr, | 140 | int interp_aout, unsigned long load_addr, |
143 | unsigned long interp_load_addr) | 141 | unsigned long interp_load_addr) |
144 | { | 142 | { |
@@ -161,7 +159,6 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
161 | * for userspace to get any other way, in others (i386) it is | 159 | * for userspace to get any other way, in others (i386) it is |
162 | * merely difficult. | 160 | * merely difficult. |
163 | */ | 161 | */ |
164 | |||
165 | u_platform = NULL; | 162 | u_platform = NULL; |
166 | if (k_platform) { | 163 | if (k_platform) { |
167 | size_t len = strlen(k_platform) + 1; | 164 | size_t len = strlen(k_platform) + 1; |
@@ -171,7 +168,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
171 | * evictions by the processes running on the same package. One | 168 | * evictions by the processes running on the same package. One |
172 | * thing we can do is to shuffle the initial stack for them. | 169 | * thing we can do is to shuffle the initial stack for them. |
173 | */ | 170 | */ |
174 | 171 | ||
175 | p = arch_align_stack(p); | 172 | p = arch_align_stack(p); |
176 | 173 | ||
177 | u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); | 174 | u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); |
@@ -180,9 +177,12 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
180 | } | 177 | } |
181 | 178 | ||
182 | /* Create the ELF interpreter info */ | 179 | /* Create the ELF interpreter info */ |
183 | elf_info = (elf_addr_t *) current->mm->saved_auxv; | 180 | elf_info = (elf_addr_t *)current->mm->saved_auxv; |
184 | #define NEW_AUX_ENT(id, val) \ | 181 | #define NEW_AUX_ENT(id, val) \ |
185 | do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0) | 182 | do { \ |
183 | elf_info[ei_index++] = id; \ | ||
184 | elf_info[ei_index++] = val; \ | ||
185 | } while (0) | ||
186 | 186 | ||
187 | #ifdef ARCH_DLINFO | 187 | #ifdef ARCH_DLINFO |
188 | /* | 188 | /* |
@@ -195,21 +195,22 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
195 | NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); | 195 | NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); |
196 | NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); | 196 | NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); |
197 | NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); | 197 | NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); |
198 | NEW_AUX_ENT(AT_PHENT, sizeof (struct elf_phdr)); | 198 | NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr)); |
199 | NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); | 199 | NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); |
200 | NEW_AUX_ENT(AT_BASE, interp_load_addr); | 200 | NEW_AUX_ENT(AT_BASE, interp_load_addr); |
201 | NEW_AUX_ENT(AT_FLAGS, 0); | 201 | NEW_AUX_ENT(AT_FLAGS, 0); |
202 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); | 202 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); |
203 | NEW_AUX_ENT(AT_UID, (elf_addr_t) tsk->uid); | 203 | NEW_AUX_ENT(AT_UID, tsk->uid); |
204 | NEW_AUX_ENT(AT_EUID, (elf_addr_t) tsk->euid); | 204 | NEW_AUX_ENT(AT_EUID, tsk->euid); |
205 | NEW_AUX_ENT(AT_GID, (elf_addr_t) tsk->gid); | 205 | NEW_AUX_ENT(AT_GID, tsk->gid); |
206 | NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid); | 206 | NEW_AUX_ENT(AT_EGID, tsk->egid); |
207 | NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm)); | 207 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); |
208 | if (k_platform) { | 208 | if (k_platform) { |
209 | NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform); | 209 | NEW_AUX_ENT(AT_PLATFORM, |
210 | (elf_addr_t)(unsigned long)u_platform); | ||
210 | } | 211 | } |
211 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { | 212 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { |
212 | NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data); | 213 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); |
213 | } | 214 | } |
214 | #undef NEW_AUX_ENT | 215 | #undef NEW_AUX_ENT |
215 | /* AT_NULL is zero; clear the rest too */ | 216 | /* AT_NULL is zero; clear the rest too */ |
@@ -232,7 +233,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
232 | /* Point sp at the lowest address on the stack */ | 233 | /* Point sp at the lowest address on the stack */ |
233 | #ifdef CONFIG_STACK_GROWSUP | 234 | #ifdef CONFIG_STACK_GROWSUP |
234 | sp = (elf_addr_t __user *)bprm->p - items - ei_index; | 235 | sp = (elf_addr_t __user *)bprm->p - items - ei_index; |
235 | bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */ | 236 | bprm->exec = (unsigned long)sp; /* XXX: PARISC HACK */ |
236 | #else | 237 | #else |
237 | sp = (elf_addr_t __user *)bprm->p; | 238 | sp = (elf_addr_t __user *)bprm->p; |
238 | #endif | 239 | #endif |
@@ -285,7 +286,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
285 | #ifndef elf_map | 286 | #ifndef elf_map |
286 | 287 | ||
287 | static unsigned long elf_map(struct file *filep, unsigned long addr, | 288 | static unsigned long elf_map(struct file *filep, unsigned long addr, |
288 | struct elf_phdr *eppnt, int prot, int type) | 289 | struct elf_phdr *eppnt, int prot, int type) |
289 | { | 290 | { |
290 | unsigned long map_addr; | 291 | unsigned long map_addr; |
291 | unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); | 292 | unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); |
@@ -310,9 +311,8 @@ static unsigned long elf_map(struct file *filep, unsigned long addr, | |||
310 | is only provided so that we can read a.out libraries that have | 311 | is only provided so that we can read a.out libraries that have |
311 | an ELF header */ | 312 | an ELF header */ |
312 | 313 | ||
313 | static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | 314 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, |
314 | struct file * interpreter, | 315 | struct file *interpreter, unsigned long *interp_load_addr) |
315 | unsigned long *interp_load_addr) | ||
316 | { | 316 | { |
317 | struct elf_phdr *elf_phdata; | 317 | struct elf_phdr *elf_phdata; |
318 | struct elf_phdr *eppnt; | 318 | struct elf_phdr *eppnt; |
@@ -342,15 +342,15 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
342 | goto out; | 342 | goto out; |
343 | 343 | ||
344 | /* Now read in all of the header information */ | 344 | /* Now read in all of the header information */ |
345 | |||
346 | size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; | 345 | size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; |
347 | if (size > ELF_MIN_ALIGN) | 346 | if (size > ELF_MIN_ALIGN) |
348 | goto out; | 347 | goto out; |
349 | elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); | 348 | elf_phdata = kmalloc(size, GFP_KERNEL); |
350 | if (!elf_phdata) | 349 | if (!elf_phdata) |
351 | goto out; | 350 | goto out; |
352 | 351 | ||
353 | retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size); | 352 | retval = kernel_read(interpreter, interp_elf_ex->e_phoff, |
353 | (char *)elf_phdata,size); | ||
354 | error = -EIO; | 354 | error = -EIO; |
355 | if (retval != size) { | 355 | if (retval != size) { |
356 | if (retval < 0) | 356 | if (retval < 0) |
@@ -359,58 +359,65 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
359 | } | 359 | } |
360 | 360 | ||
361 | eppnt = elf_phdata; | 361 | eppnt = elf_phdata; |
362 | for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { | 362 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { |
363 | if (eppnt->p_type == PT_LOAD) { | 363 | if (eppnt->p_type == PT_LOAD) { |
364 | int elf_type = MAP_PRIVATE | MAP_DENYWRITE; | 364 | int elf_type = MAP_PRIVATE | MAP_DENYWRITE; |
365 | int elf_prot = 0; | 365 | int elf_prot = 0; |
366 | unsigned long vaddr = 0; | 366 | unsigned long vaddr = 0; |
367 | unsigned long k, map_addr; | 367 | unsigned long k, map_addr; |
368 | 368 | ||
369 | if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; | 369 | if (eppnt->p_flags & PF_R) |
370 | if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; | 370 | elf_prot = PROT_READ; |
371 | if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; | 371 | if (eppnt->p_flags & PF_W) |
372 | vaddr = eppnt->p_vaddr; | 372 | elf_prot |= PROT_WRITE; |
373 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) | 373 | if (eppnt->p_flags & PF_X) |
374 | elf_type |= MAP_FIXED; | 374 | elf_prot |= PROT_EXEC; |
375 | 375 | vaddr = eppnt->p_vaddr; | |
376 | map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type); | 376 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) |
377 | error = map_addr; | 377 | elf_type |= MAP_FIXED; |
378 | if (BAD_ADDR(map_addr)) | 378 | |
379 | goto out_close; | 379 | map_addr = elf_map(interpreter, load_addr + vaddr, |
380 | 380 | eppnt, elf_prot, elf_type); | |
381 | if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { | 381 | error = map_addr; |
382 | load_addr = map_addr - ELF_PAGESTART(vaddr); | 382 | if (BAD_ADDR(map_addr)) |
383 | load_addr_set = 1; | 383 | goto out_close; |
384 | } | 384 | |
385 | 385 | if (!load_addr_set && | |
386 | /* | 386 | interp_elf_ex->e_type == ET_DYN) { |
387 | * Check to see if the section's size will overflow the | 387 | load_addr = map_addr - ELF_PAGESTART(vaddr); |
388 | * allowed task size. Note that p_filesz must always be | 388 | load_addr_set = 1; |
389 | * <= p_memsize so it is only necessary to check p_memsz. | 389 | } |
390 | */ | 390 | |
391 | k = load_addr + eppnt->p_vaddr; | 391 | /* |
392 | if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz || | 392 | * Check to see if the section's size will overflow the |
393 | eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) { | 393 | * allowed task size. Note that p_filesz must always be |
394 | error = -ENOMEM; | 394 | * <= p_memsize so it's only necessary to check p_memsz. |
395 | goto out_close; | 395 | */ |
396 | } | 396 | k = load_addr + eppnt->p_vaddr; |
397 | 397 | if (k > TASK_SIZE || | |
398 | /* | 398 | eppnt->p_filesz > eppnt->p_memsz || |
399 | * Find the end of the file mapping for this phdr, and keep | 399 | eppnt->p_memsz > TASK_SIZE || |
400 | * track of the largest address we see for this. | 400 | TASK_SIZE - eppnt->p_memsz < k) { |
401 | */ | 401 | error = -ENOMEM; |
402 | k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; | 402 | goto out_close; |
403 | if (k > elf_bss) | 403 | } |
404 | elf_bss = k; | 404 | |
405 | 405 | /* | |
406 | /* | 406 | * Find the end of the file mapping for this phdr, and |
407 | * Do the same thing for the memory mapping - between | 407 | * keep track of the largest address we see for this. |
408 | * elf_bss and last_bss is the bss section. | 408 | */ |
409 | */ | 409 | k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; |
410 | k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; | 410 | if (k > elf_bss) |
411 | if (k > last_bss) | 411 | elf_bss = k; |
412 | last_bss = k; | 412 | |
413 | } | 413 | /* |
414 | * Do the same thing for the memory mapping - between | ||
415 | * elf_bss and last_bss is the bss section. | ||
416 | */ | ||
417 | k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; | ||
418 | if (k > last_bss) | ||
419 | last_bss = k; | ||
420 | } | ||
414 | } | 421 | } |
415 | 422 | ||
416 | /* | 423 | /* |
@@ -424,7 +431,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
424 | goto out_close; | 431 | goto out_close; |
425 | } | 432 | } |
426 | 433 | ||
427 | elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); /* What we have mapped so far */ | 434 | /* What we have mapped so far */ |
435 | elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); | ||
428 | 436 | ||
429 | /* Map the last of the bss segment */ | 437 | /* Map the last of the bss segment */ |
430 | if (last_bss > elf_bss) { | 438 | if (last_bss > elf_bss) { |
@@ -436,7 +444,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
436 | } | 444 | } |
437 | 445 | ||
438 | *interp_load_addr = load_addr; | 446 | *interp_load_addr = load_addr; |
439 | error = ((unsigned long) interp_elf_ex->e_entry) + load_addr; | 447 | error = ((unsigned long)interp_elf_ex->e_entry) + load_addr; |
440 | 448 | ||
441 | out_close: | 449 | out_close: |
442 | kfree(elf_phdata); | 450 | kfree(elf_phdata); |
@@ -444,8 +452,8 @@ out: | |||
444 | return error; | 452 | return error; |
445 | } | 453 | } |
446 | 454 | ||
447 | static unsigned long load_aout_interp(struct exec * interp_ex, | 455 | static unsigned long load_aout_interp(struct exec *interp_ex, |
448 | struct file * interpreter) | 456 | struct file *interpreter) |
449 | { | 457 | { |
450 | unsigned long text_data, elf_entry = ~0UL; | 458 | unsigned long text_data, elf_entry = ~0UL; |
451 | char __user * addr; | 459 | char __user * addr; |
@@ -464,7 +472,7 @@ static unsigned long load_aout_interp(struct exec * interp_ex, | |||
464 | case ZMAGIC: | 472 | case ZMAGIC: |
465 | case QMAGIC: | 473 | case QMAGIC: |
466 | offset = N_TXTOFF(*interp_ex); | 474 | offset = N_TXTOFF(*interp_ex); |
467 | addr = (char __user *) N_TXTADDR(*interp_ex); | 475 | addr = (char __user *)N_TXTADDR(*interp_ex); |
468 | break; | 476 | break; |
469 | default: | 477 | default: |
470 | goto out; | 478 | goto out; |
@@ -480,7 +488,6 @@ static unsigned long load_aout_interp(struct exec * interp_ex, | |||
480 | flush_icache_range((unsigned long)addr, | 488 | flush_icache_range((unsigned long)addr, |
481 | (unsigned long)addr + text_data); | 489 | (unsigned long)addr + text_data); |
482 | 490 | ||
483 | |||
484 | down_write(¤t->mm->mmap_sem); | 491 | down_write(¤t->mm->mmap_sem); |
485 | do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), | 492 | do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), |
486 | interp_ex->a_bss); | 493 | interp_ex->a_bss); |
@@ -519,7 +526,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top) | |||
519 | #endif | 526 | #endif |
520 | } | 527 | } |
521 | 528 | ||
522 | static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | 529 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) |
523 | { | 530 | { |
524 | struct file *interpreter = NULL; /* to shut gcc up */ | 531 | struct file *interpreter = NULL; /* to shut gcc up */ |
525 | unsigned long load_addr = 0, load_bias = 0; | 532 | unsigned long load_addr = 0, load_bias = 0; |
@@ -528,7 +535,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
528 | unsigned int interpreter_type = INTERPRETER_NONE; | 535 | unsigned int interpreter_type = INTERPRETER_NONE; |
529 | unsigned char ibcs2_interpreter = 0; | 536 | unsigned char ibcs2_interpreter = 0; |
530 | unsigned long error; | 537 | unsigned long error; |
531 | struct elf_phdr * elf_ppnt, *elf_phdata; | 538 | struct elf_phdr *elf_ppnt, *elf_phdata; |
532 | unsigned long elf_bss, elf_brk; | 539 | unsigned long elf_bss, elf_brk; |
533 | int elf_exec_fileno; | 540 | int elf_exec_fileno; |
534 | int retval, i; | 541 | int retval, i; |
@@ -553,7 +560,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
553 | } | 560 | } |
554 | 561 | ||
555 | /* Get the exec-header */ | 562 | /* Get the exec-header */ |
556 | loc->elf_ex = *((struct elfhdr *) bprm->buf); | 563 | loc->elf_ex = *((struct elfhdr *)bprm->buf); |
557 | 564 | ||
558 | retval = -ENOEXEC; | 565 | retval = -ENOEXEC; |
559 | /* First of all, some simple consistency checks */ | 566 | /* First of all, some simple consistency checks */ |
@@ -568,7 +575,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
568 | goto out; | 575 | goto out; |
569 | 576 | ||
570 | /* Now read in all of the header information */ | 577 | /* Now read in all of the header information */ |
571 | |||
572 | if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) | 578 | if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) |
573 | goto out; | 579 | goto out; |
574 | if (loc->elf_ex.e_phnum < 1 || | 580 | if (loc->elf_ex.e_phnum < 1 || |
@@ -576,18 +582,19 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
576 | goto out; | 582 | goto out; |
577 | size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); | 583 | size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); |
578 | retval = -ENOMEM; | 584 | retval = -ENOMEM; |
579 | elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); | 585 | elf_phdata = kmalloc(size, GFP_KERNEL); |
580 | if (!elf_phdata) | 586 | if (!elf_phdata) |
581 | goto out; | 587 | goto out; |
582 | 588 | ||
583 | retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size); | 589 | retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, |
590 | (char *)elf_phdata, size); | ||
584 | if (retval != size) { | 591 | if (retval != size) { |
585 | if (retval >= 0) | 592 | if (retval >= 0) |
586 | retval = -EIO; | 593 | retval = -EIO; |
587 | goto out_free_ph; | 594 | goto out_free_ph; |
588 | } | 595 | } |
589 | 596 | ||
590 | files = current->files; /* Refcounted so ok */ | 597 | files = current->files; /* Refcounted so ok */ |
591 | retval = unshare_files(); | 598 | retval = unshare_files(); |
592 | if (retval < 0) | 599 | if (retval < 0) |
593 | goto out_free_ph; | 600 | goto out_free_ph; |
@@ -598,7 +605,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
598 | 605 | ||
599 | /* exec will make our files private anyway, but for the a.out | 606 | /* exec will make our files private anyway, but for the a.out |
600 | loader stuff we need to do it earlier */ | 607 | loader stuff we need to do it earlier */ |
601 | |||
602 | retval = get_unused_fd(); | 608 | retval = get_unused_fd(); |
603 | if (retval < 0) | 609 | if (retval < 0) |
604 | goto out_free_fh; | 610 | goto out_free_fh; |
@@ -620,7 +626,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
620 | * shared libraries - for now assume that this | 626 | * shared libraries - for now assume that this |
621 | * is an a.out format binary | 627 | * is an a.out format binary |
622 | */ | 628 | */ |
623 | |||
624 | retval = -ENOEXEC; | 629 | retval = -ENOEXEC; |
625 | if (elf_ppnt->p_filesz > PATH_MAX || | 630 | if (elf_ppnt->p_filesz > PATH_MAX || |
626 | elf_ppnt->p_filesz < 2) | 631 | elf_ppnt->p_filesz < 2) |
@@ -628,13 +633,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
628 | 633 | ||
629 | retval = -ENOMEM; | 634 | retval = -ENOMEM; |
630 | elf_interpreter = kmalloc(elf_ppnt->p_filesz, | 635 | elf_interpreter = kmalloc(elf_ppnt->p_filesz, |
631 | GFP_KERNEL); | 636 | GFP_KERNEL); |
632 | if (!elf_interpreter) | 637 | if (!elf_interpreter) |
633 | goto out_free_file; | 638 | goto out_free_file; |
634 | 639 | ||
635 | retval = kernel_read(bprm->file, elf_ppnt->p_offset, | 640 | retval = kernel_read(bprm->file, elf_ppnt->p_offset, |
636 | elf_interpreter, | 641 | elf_interpreter, |
637 | elf_ppnt->p_filesz); | 642 | elf_ppnt->p_filesz); |
638 | if (retval != elf_ppnt->p_filesz) { | 643 | if (retval != elf_ppnt->p_filesz) { |
639 | if (retval >= 0) | 644 | if (retval >= 0) |
640 | retval = -EIO; | 645 | retval = -EIO; |
@@ -678,7 +683,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
678 | retval = PTR_ERR(interpreter); | 683 | retval = PTR_ERR(interpreter); |
679 | if (IS_ERR(interpreter)) | 684 | if (IS_ERR(interpreter)) |
680 | goto out_free_interp; | 685 | goto out_free_interp; |
681 | retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); | 686 | retval = kernel_read(interpreter, 0, bprm->buf, |
687 | BINPRM_BUF_SIZE); | ||
682 | if (retval != BINPRM_BUF_SIZE) { | 688 | if (retval != BINPRM_BUF_SIZE) { |
683 | if (retval >= 0) | 689 | if (retval >= 0) |
684 | retval = -EIO; | 690 | retval = -EIO; |
@@ -686,8 +692,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
686 | } | 692 | } |
687 | 693 | ||
688 | /* Get the exec headers */ | 694 | /* Get the exec headers */ |
689 | loc->interp_ex = *((struct exec *) bprm->buf); | 695 | loc->interp_ex = *((struct exec *)bprm->buf); |
690 | loc->interp_elf_ex = *((struct elfhdr *) bprm->buf); | 696 | loc->interp_elf_ex = *((struct elfhdr *)bprm->buf); |
691 | break; | 697 | break; |
692 | } | 698 | } |
693 | elf_ppnt++; | 699 | elf_ppnt++; |
@@ -739,7 +745,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
739 | 745 | ||
740 | /* OK, we are done with that, now set up the arg stuff, | 746 | /* OK, we are done with that, now set up the arg stuff, |
741 | and then start this sucker up */ | 747 | and then start this sucker up */ |
742 | |||
743 | if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { | 748 | if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { |
744 | char *passed_p = passed_fileno; | 749 | char *passed_p = passed_fileno; |
745 | sprintf(passed_fileno, "%d", elf_exec_fileno); | 750 | sprintf(passed_fileno, "%d", elf_exec_fileno); |
@@ -759,7 +764,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
759 | 764 | ||
760 | /* Discard our unneeded old files struct */ | 765 | /* Discard our unneeded old files struct */ |
761 | if (files) { | 766 | if (files) { |
762 | steal_locks(files); | ||
763 | put_files_struct(files); | 767 | put_files_struct(files); |
764 | files = NULL; | 768 | files = NULL; |
765 | } | 769 | } |
@@ -778,7 +782,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
778 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) | 782 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) |
779 | current->personality |= READ_IMPLIES_EXEC; | 783 | current->personality |= READ_IMPLIES_EXEC; |
780 | 784 | ||
781 | if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | 785 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
782 | current->flags |= PF_RANDOMIZE; | 786 | current->flags |= PF_RANDOMIZE; |
783 | arch_pick_mmap_layout(current->mm); | 787 | arch_pick_mmap_layout(current->mm); |
784 | 788 | ||
@@ -799,8 +803,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
799 | the correct location in memory. At this point, we assume that | 803 | the correct location in memory. At this point, we assume that |
800 | the image should be loaded at fixed address, not at a variable | 804 | the image should be loaded at fixed address, not at a variable |
801 | address. */ | 805 | address. */ |
802 | 806 | for(i = 0, elf_ppnt = elf_phdata; | |
803 | for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { | 807 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { |
804 | int elf_prot = 0, elf_flags; | 808 | int elf_prot = 0, elf_flags; |
805 | unsigned long k, vaddr; | 809 | unsigned long k, vaddr; |
806 | 810 | ||
@@ -828,30 +832,35 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
828 | load_bias, nbyte)) { | 832 | load_bias, nbyte)) { |
829 | /* | 833 | /* |
830 | * This bss-zeroing can fail if the ELF | 834 | * This bss-zeroing can fail if the ELF |
831 | * file specifies odd protections. So | 835 | * file specifies odd protections. So |
832 | * we don't check the return value | 836 | * we don't check the return value |
833 | */ | 837 | */ |
834 | } | 838 | } |
835 | } | 839 | } |
836 | } | 840 | } |
837 | 841 | ||
838 | if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; | 842 | if (elf_ppnt->p_flags & PF_R) |
839 | if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; | 843 | elf_prot |= PROT_READ; |
840 | if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; | 844 | if (elf_ppnt->p_flags & PF_W) |
845 | elf_prot |= PROT_WRITE; | ||
846 | if (elf_ppnt->p_flags & PF_X) | ||
847 | elf_prot |= PROT_EXEC; | ||
841 | 848 | ||
842 | elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; | 849 | elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; |
843 | 850 | ||
844 | vaddr = elf_ppnt->p_vaddr; | 851 | vaddr = elf_ppnt->p_vaddr; |
845 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { | 852 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { |
846 | elf_flags |= MAP_FIXED; | 853 | elf_flags |= MAP_FIXED; |
847 | } else if (loc->elf_ex.e_type == ET_DYN) { | 854 | } else if (loc->elf_ex.e_type == ET_DYN) { |
848 | /* Try and get dynamic programs out of the way of the default mmap | 855 | /* Try and get dynamic programs out of the way of the |
849 | base, as well as whatever program they might try to exec. This | 856 | * default mmap base, as well as whatever program they |
850 | is because the brk will follow the loader, and is not movable. */ | 857 | * might try to exec. This is because the brk will |
858 | * follow the loader, and is not movable. */ | ||
851 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); | 859 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); |
852 | } | 860 | } |
853 | 861 | ||
854 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); | 862 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, |
863 | elf_prot, elf_flags); | ||
855 | if (BAD_ADDR(error)) { | 864 | if (BAD_ADDR(error)) { |
856 | send_sig(SIGKILL, current, 0); | 865 | send_sig(SIGKILL, current, 0); |
857 | goto out_free_dentry; | 866 | goto out_free_dentry; |
@@ -868,8 +877,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
868 | } | 877 | } |
869 | } | 878 | } |
870 | k = elf_ppnt->p_vaddr; | 879 | k = elf_ppnt->p_vaddr; |
871 | if (k < start_code) start_code = k; | 880 | if (k < start_code) |
872 | if (start_data < k) start_data = k; | 881 | start_code = k; |
882 | if (start_data < k) | ||
883 | start_data = k; | ||
873 | 884 | ||
874 | /* | 885 | /* |
875 | * Check to see if the section's size will overflow the | 886 | * Check to see if the section's size will overflow the |
@@ -879,7 +890,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
879 | if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || | 890 | if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || |
880 | elf_ppnt->p_memsz > TASK_SIZE || | 891 | elf_ppnt->p_memsz > TASK_SIZE || |
881 | TASK_SIZE - elf_ppnt->p_memsz < k) { | 892 | TASK_SIZE - elf_ppnt->p_memsz < k) { |
882 | /* set_brk can never work. Avoid overflows. */ | 893 | /* set_brk can never work. Avoid overflows. */ |
883 | send_sig(SIGKILL, current, 0); | 894 | send_sig(SIGKILL, current, 0); |
884 | goto out_free_dentry; | 895 | goto out_free_dentry; |
885 | } | 896 | } |
@@ -967,8 +978,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
967 | 978 | ||
968 | compute_creds(bprm); | 979 | compute_creds(bprm); |
969 | current->flags &= ~PF_FORKNOEXEC; | 980 | current->flags &= ~PF_FORKNOEXEC; |
970 | create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT), | 981 | create_elf_tables(bprm, &loc->elf_ex, |
971 | load_addr, interp_load_addr); | 982 | (interpreter_type == INTERPRETER_AOUT), |
983 | load_addr, interp_load_addr); | ||
972 | /* N.B. passed_fileno might not be initialized? */ | 984 | /* N.B. passed_fileno might not be initialized? */ |
973 | if (interpreter_type == INTERPRETER_AOUT) | 985 | if (interpreter_type == INTERPRETER_AOUT) |
974 | current->mm->arg_start += strlen(passed_fileno) + 1; | 986 | current->mm->arg_start += strlen(passed_fileno) + 1; |
@@ -982,7 +994,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
982 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, | 994 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, |
983 | and some applications "depend" upon this behavior. | 995 | and some applications "depend" upon this behavior. |
984 | Since we do not have the power to recompile these, we | 996 | Since we do not have the power to recompile these, we |
985 | emulate the SVr4 behavior. Sigh. */ | 997 | emulate the SVr4 behavior. Sigh. */ |
986 | down_write(¤t->mm->mmap_sem); | 998 | down_write(¤t->mm->mmap_sem); |
987 | error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, | 999 | error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, |
988 | MAP_FIXED | MAP_PRIVATE, 0); | 1000 | MAP_FIXED | MAP_PRIVATE, 0); |
@@ -1037,7 +1049,6 @@ out_free_ph: | |||
1037 | 1049 | ||
1038 | /* This is really simpleminded and specialized - we are loading an | 1050 | /* This is really simpleminded and specialized - we are loading an |
1039 | a.out library that is given an ELF header. */ | 1051 | a.out library that is given an ELF header. */ |
1040 | |||
1041 | static int load_elf_library(struct file *file) | 1052 | static int load_elf_library(struct file *file) |
1042 | { | 1053 | { |
1043 | struct elf_phdr *elf_phdata; | 1054 | struct elf_phdr *elf_phdata; |
@@ -1047,7 +1058,7 @@ static int load_elf_library(struct file *file) | |||
1047 | struct elfhdr elf_ex; | 1058 | struct elfhdr elf_ex; |
1048 | 1059 | ||
1049 | error = -ENOEXEC; | 1060 | error = -ENOEXEC; |
1050 | retval = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex)); | 1061 | retval = kernel_read(file, 0, (char *)&elf_ex, sizeof(elf_ex)); |
1051 | if (retval != sizeof(elf_ex)) | 1062 | if (retval != sizeof(elf_ex)) |
1052 | goto out; | 1063 | goto out; |
1053 | 1064 | ||
@@ -1056,7 +1067,7 @@ static int load_elf_library(struct file *file) | |||
1056 | 1067 | ||
1057 | /* First of all, some simple consistency checks */ | 1068 | /* First of all, some simple consistency checks */ |
1058 | if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || | 1069 | if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || |
1059 | !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap) | 1070 | !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap) |
1060 | goto out; | 1071 | goto out; |
1061 | 1072 | ||
1062 | /* Now read in all of the header information */ | 1073 | /* Now read in all of the header information */ |
@@ -1104,7 +1115,8 @@ static int load_elf_library(struct file *file) | |||
1104 | goto out_free_ph; | 1115 | goto out_free_ph; |
1105 | } | 1116 | } |
1106 | 1117 | ||
1107 | len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1); | 1118 | len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + |
1119 | ELF_MIN_ALIGN - 1); | ||
1108 | bss = eppnt->p_memsz + eppnt->p_vaddr; | 1120 | bss = eppnt->p_memsz + eppnt->p_vaddr; |
1109 | if (bss > len) { | 1121 | if (bss > len) { |
1110 | down_write(¤t->mm->mmap_sem); | 1122 | down_write(¤t->mm->mmap_sem); |
@@ -1163,7 +1175,7 @@ static int maydump(struct vm_area_struct *vma) | |||
1163 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) | 1175 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) |
1164 | return 0; | 1176 | return 0; |
1165 | 1177 | ||
1166 | /* Dump shared memory only if mapped from an anonymous file. */ | 1178 | /* Dump shared memory only if mapped from an anonymous file. */ |
1167 | if (vma->vm_flags & VM_SHARED) | 1179 | if (vma->vm_flags & VM_SHARED) |
1168 | return vma->vm_file->f_dentry->d_inode->i_nlink == 0; | 1180 | return vma->vm_file->f_dentry->d_inode->i_nlink == 0; |
1169 | 1181 | ||
@@ -1174,7 +1186,7 @@ static int maydump(struct vm_area_struct *vma) | |||
1174 | return 1; | 1186 | return 1; |
1175 | } | 1187 | } |
1176 | 1188 | ||
1177 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | 1189 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) |
1178 | 1190 | ||
1179 | /* An ELF note in memory */ | 1191 | /* An ELF note in memory */ |
1180 | struct memelfnote | 1192 | struct memelfnote |
@@ -1277,11 +1289,11 @@ static void fill_note(struct memelfnote *note, const char *name, int type, | |||
1277 | } | 1289 | } |
1278 | 1290 | ||
1279 | /* | 1291 | /* |
1280 | * fill up all the fields in prstatus from the given task struct, except registers | 1292 | * fill up all the fields in prstatus from the given task struct, except |
1281 | * which need to be filled up separately. | 1293 | * registers which need to be filled up separately. |
1282 | */ | 1294 | */ |
1283 | static void fill_prstatus(struct elf_prstatus *prstatus, | 1295 | static void fill_prstatus(struct elf_prstatus *prstatus, |
1284 | struct task_struct *p, long signr) | 1296 | struct task_struct *p, long signr) |
1285 | { | 1297 | { |
1286 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; | 1298 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; |
1287 | prstatus->pr_sigpend = p->pending.signal.sig[0]; | 1299 | prstatus->pr_sigpend = p->pending.signal.sig[0]; |
@@ -1366,8 +1378,8 @@ struct elf_thread_status | |||
1366 | 1378 | ||
1367 | /* | 1379 | /* |
1368 | * In order to add the specific thread information for the elf file format, | 1380 | * In order to add the specific thread information for the elf file format, |
1369 | * we need to keep a linked list of every threads pr_status and then | 1381 | * we need to keep a linked list of every threads pr_status and then create |
1370 | * create a single section for them in the final core file. | 1382 | * a single section for them in the final core file. |
1371 | */ | 1383 | */ |
1372 | static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | 1384 | static int elf_dump_thread_status(long signr, struct elf_thread_status *t) |
1373 | { | 1385 | { |
@@ -1378,19 +1390,23 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
1378 | fill_prstatus(&t->prstatus, p, signr); | 1390 | fill_prstatus(&t->prstatus, p, signr); |
1379 | elf_core_copy_task_regs(p, &t->prstatus.pr_reg); | 1391 | elf_core_copy_task_regs(p, &t->prstatus.pr_reg); |
1380 | 1392 | ||
1381 | fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), &(t->prstatus)); | 1393 | fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), |
1394 | &(t->prstatus)); | ||
1382 | t->num_notes++; | 1395 | t->num_notes++; |
1383 | sz += notesize(&t->notes[0]); | 1396 | sz += notesize(&t->notes[0]); |
1384 | 1397 | ||
1385 | if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu))) { | 1398 | if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, |
1386 | fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), &(t->fpu)); | 1399 | &t->fpu))) { |
1400 | fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), | ||
1401 | &(t->fpu)); | ||
1387 | t->num_notes++; | 1402 | t->num_notes++; |
1388 | sz += notesize(&t->notes[1]); | 1403 | sz += notesize(&t->notes[1]); |
1389 | } | 1404 | } |
1390 | 1405 | ||
1391 | #ifdef ELF_CORE_COPY_XFPREGS | 1406 | #ifdef ELF_CORE_COPY_XFPREGS |
1392 | if (elf_core_copy_task_xfpregs(p, &t->xfpu)) { | 1407 | if (elf_core_copy_task_xfpregs(p, &t->xfpu)) { |
1393 | fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu), &t->xfpu); | 1408 | fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu), |
1409 | &t->xfpu); | ||
1394 | t->num_notes++; | 1410 | t->num_notes++; |
1395 | sz += notesize(&t->notes[2]); | 1411 | sz += notesize(&t->notes[2]); |
1396 | } | 1412 | } |
@@ -1405,7 +1421,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
1405 | * and then they are actually written out. If we run out of core limit | 1421 | * and then they are actually written out. If we run out of core limit |
1406 | * we just truncate. | 1422 | * we just truncate. |
1407 | */ | 1423 | */ |
1408 | static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | 1424 | static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) |
1409 | { | 1425 | { |
1410 | #define NUM_NOTES 6 | 1426 | #define NUM_NOTES 6 |
1411 | int has_dumped = 0; | 1427 | int has_dumped = 0; |
@@ -1434,12 +1450,12 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1434 | /* | 1450 | /* |
1435 | * We no longer stop all VM operations. | 1451 | * We no longer stop all VM operations. |
1436 | * | 1452 | * |
1437 | * This is because those proceses that could possibly change map_count or | 1453 | * This is because those proceses that could possibly change map_count |
1438 | * the mmap / vma pages are now blocked in do_exit on current finishing | 1454 | * or the mmap / vma pages are now blocked in do_exit on current |
1439 | * this core dump. | 1455 | * finishing this core dump. |
1440 | * | 1456 | * |
1441 | * Only ptrace can touch these memory addresses, but it doesn't change | 1457 | * Only ptrace can touch these memory addresses, but it doesn't change |
1442 | * the map_count or the pages allocated. So no possibility of crashing | 1458 | * the map_count or the pages allocated. So no possibility of crashing |
1443 | * exists while dumping the mm->vm_next areas to the core file. | 1459 | * exists while dumping the mm->vm_next areas to the core file. |
1444 | */ | 1460 | */ |
1445 | 1461 | ||
@@ -1501,7 +1517,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1501 | #endif | 1517 | #endif |
1502 | 1518 | ||
1503 | /* Set up header */ | 1519 | /* Set up header */ |
1504 | fill_elf_header(elf, segs+1); /* including notes section */ | 1520 | fill_elf_header(elf, segs + 1); /* including notes section */ |
1505 | 1521 | ||
1506 | has_dumped = 1; | 1522 | has_dumped = 1; |
1507 | current->flags |= PF_DUMPCORE; | 1523 | current->flags |= PF_DUMPCORE; |
@@ -1511,24 +1527,24 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1511 | * with info from their /proc. | 1527 | * with info from their /proc. |
1512 | */ | 1528 | */ |
1513 | 1529 | ||
1514 | fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); | 1530 | fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); |
1515 | |||
1516 | fill_psinfo(psinfo, current->group_leader, current->mm); | 1531 | fill_psinfo(psinfo, current->group_leader, current->mm); |
1517 | fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); | 1532 | fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); |
1518 | 1533 | ||
1519 | numnote = 2; | 1534 | numnote = 2; |
1520 | 1535 | ||
1521 | auxv = (elf_addr_t *) current->mm->saved_auxv; | 1536 | auxv = (elf_addr_t *)current->mm->saved_auxv; |
1522 | 1537 | ||
1523 | i = 0; | 1538 | i = 0; |
1524 | do | 1539 | do |
1525 | i += 2; | 1540 | i += 2; |
1526 | while (auxv[i - 2] != AT_NULL); | 1541 | while (auxv[i - 2] != AT_NULL); |
1527 | fill_note(¬es[numnote++], "CORE", NT_AUXV, | 1542 | fill_note(¬es[numnote++], "CORE", NT_AUXV, |
1528 | i * sizeof (elf_addr_t), auxv); | 1543 | i * sizeof(elf_addr_t), auxv); |
1529 | 1544 | ||
1530 | /* Try to dump the FPU. */ | 1545 | /* Try to dump the FPU. */ |
1531 | if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu))) | 1546 | if ((prstatus->pr_fpvalid = |
1547 | elf_core_copy_task_fpregs(current, regs, fpu))) | ||
1532 | fill_note(notes + numnote++, | 1548 | fill_note(notes + numnote++, |
1533 | "CORE", NT_PRFPREG, sizeof(*fpu), fpu); | 1549 | "CORE", NT_PRFPREG, sizeof(*fpu), fpu); |
1534 | #ifdef ELF_CORE_COPY_XFPREGS | 1550 | #ifdef ELF_CORE_COPY_XFPREGS |
@@ -1577,8 +1593,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1577 | phdr.p_memsz = sz; | 1593 | phdr.p_memsz = sz; |
1578 | offset += phdr.p_filesz; | 1594 | offset += phdr.p_filesz; |
1579 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; | 1595 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
1580 | if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W; | 1596 | if (vma->vm_flags & VM_WRITE) |
1581 | if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X; | 1597 | phdr.p_flags |= PF_W; |
1598 | if (vma->vm_flags & VM_EXEC) | ||
1599 | phdr.p_flags |= PF_X; | ||
1582 | phdr.p_align = ELF_EXEC_PAGESIZE; | 1600 | phdr.p_align = ELF_EXEC_PAGESIZE; |
1583 | 1601 | ||
1584 | DUMP_WRITE(&phdr, sizeof(phdr)); | 1602 | DUMP_WRITE(&phdr, sizeof(phdr)); |
@@ -1595,7 +1613,9 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1595 | 1613 | ||
1596 | /* write out the thread status notes section */ | 1614 | /* write out the thread status notes section */ |
1597 | list_for_each(t, &thread_list) { | 1615 | list_for_each(t, &thread_list) { |
1598 | struct elf_thread_status *tmp = list_entry(t, struct elf_thread_status, list); | 1616 | struct elf_thread_status *tmp = |
1617 | list_entry(t, struct elf_thread_status, list); | ||
1618 | |||
1599 | for (i = 0; i < tmp->num_notes; i++) | 1619 | for (i = 0; i < tmp->num_notes; i++) |
1600 | if (!writenote(&tmp->notes[i], file)) | 1620 | if (!writenote(&tmp->notes[i], file)) |
1601 | goto end_coredump; | 1621 | goto end_coredump; |
@@ -1612,18 +1632,19 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1612 | for (addr = vma->vm_start; | 1632 | for (addr = vma->vm_start; |
1613 | addr < vma->vm_end; | 1633 | addr < vma->vm_end; |
1614 | addr += PAGE_SIZE) { | 1634 | addr += PAGE_SIZE) { |
1615 | struct page* page; | 1635 | struct page *page; |
1616 | struct vm_area_struct *vma; | 1636 | struct vm_area_struct *vma; |
1617 | 1637 | ||
1618 | if (get_user_pages(current, current->mm, addr, 1, 0, 1, | 1638 | if (get_user_pages(current, current->mm, addr, 1, 0, 1, |
1619 | &page, &vma) <= 0) { | 1639 | &page, &vma) <= 0) { |
1620 | DUMP_SEEK (file->f_pos + PAGE_SIZE); | 1640 | DUMP_SEEK(file->f_pos + PAGE_SIZE); |
1621 | } else { | 1641 | } else { |
1622 | if (page == ZERO_PAGE(addr)) { | 1642 | if (page == ZERO_PAGE(addr)) { |
1623 | DUMP_SEEK (file->f_pos + PAGE_SIZE); | 1643 | DUMP_SEEK(file->f_pos + PAGE_SIZE); |
1624 | } else { | 1644 | } else { |
1625 | void *kaddr; | 1645 | void *kaddr; |
1626 | flush_cache_page(vma, addr, page_to_pfn(page)); | 1646 | flush_cache_page(vma, addr, |
1647 | page_to_pfn(page)); | ||
1627 | kaddr = kmap(page); | 1648 | kaddr = kmap(page); |
1628 | if ((size += PAGE_SIZE) > limit || | 1649 | if ((size += PAGE_SIZE) > limit || |
1629 | !dump_write(file, kaddr, | 1650 | !dump_write(file, kaddr, |
@@ -1645,7 +1666,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1645 | 1666 | ||
1646 | if ((off_t)file->f_pos != offset) { | 1667 | if ((off_t)file->f_pos != offset) { |
1647 | /* Sanity check */ | 1668 | /* Sanity check */ |
1648 | printk(KERN_WARNING "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", | 1669 | printk(KERN_WARNING |
1670 | "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", | ||
1649 | (off_t)file->f_pos, offset); | 1671 | (off_t)file->f_pos, offset); |
1650 | } | 1672 | } |
1651 | 1673 | ||