diff options
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 238 |
1 files changed, 176 insertions, 62 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 3a6175fe10c0..02b16910f4c9 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -386,6 +386,127 @@ static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr) | |||
386 | ELF_PAGESTART(cmds[first_idx].p_vaddr); | 386 | ELF_PAGESTART(cmds[first_idx].p_vaddr); |
387 | } | 387 | } |
388 | 388 | ||
389 | /** | ||
390 | * load_elf_phdrs() - load ELF program headers | ||
391 | * @elf_ex: ELF header of the binary whose program headers should be loaded | ||
392 | * @elf_file: the opened ELF binary file | ||
393 | * | ||
394 | * Loads ELF program headers from the binary file elf_file, which has the ELF | ||
395 | * header pointed to by elf_ex, into a newly allocated array. The caller is | ||
396 | * responsible for freeing the allocated data. Returns an ERR_PTR upon failure. | ||
397 | */ | ||
398 | static struct elf_phdr *load_elf_phdrs(struct elfhdr *elf_ex, | ||
399 | struct file *elf_file) | ||
400 | { | ||
401 | struct elf_phdr *elf_phdata = NULL; | ||
402 | int retval, size, err = -1; | ||
403 | |||
404 | /* | ||
405 | * If the size of this structure has changed, then punt, since | ||
406 | * we will be doing the wrong thing. | ||
407 | */ | ||
408 | if (elf_ex->e_phentsize != sizeof(struct elf_phdr)) | ||
409 | goto out; | ||
410 | |||
411 | /* Sanity check the number of program headers... */ | ||
412 | if (elf_ex->e_phnum < 1 || | ||
413 | elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) | ||
414 | goto out; | ||
415 | |||
416 | /* ...and their total size. */ | ||
417 | size = sizeof(struct elf_phdr) * elf_ex->e_phnum; | ||
418 | if (size > ELF_MIN_ALIGN) | ||
419 | goto out; | ||
420 | |||
421 | elf_phdata = kmalloc(size, GFP_KERNEL); | ||
422 | if (!elf_phdata) | ||
423 | goto out; | ||
424 | |||
425 | /* Read in the program headers */ | ||
426 | retval = kernel_read(elf_file, elf_ex->e_phoff, | ||
427 | (char *)elf_phdata, size); | ||
428 | if (retval != size) { | ||
429 | err = (retval < 0) ? retval : -EIO; | ||
430 | goto out; | ||
431 | } | ||
432 | |||
433 | /* Success! */ | ||
434 | err = 0; | ||
435 | out: | ||
436 | if (err) { | ||
437 | kfree(elf_phdata); | ||
438 | elf_phdata = NULL; | ||
439 | } | ||
440 | return elf_phdata; | ||
441 | } | ||
442 | |||
443 | #ifndef CONFIG_ARCH_BINFMT_ELF_STATE | ||
444 | |||
445 | /** | ||
446 | * struct arch_elf_state - arch-specific ELF loading state | ||
447 | * | ||
448 | * This structure is used to preserve architecture specific data during | ||
449 | * the loading of an ELF file, throughout the checking of architecture | ||
450 | * specific ELF headers & through to the point where the ELF load is | ||
451 | * known to be proceeding (ie. SET_PERSONALITY). | ||
452 | * | ||
453 | * This implementation is a dummy for architectures which require no | ||
454 | * specific state. | ||
455 | */ | ||
456 | struct arch_elf_state { | ||
457 | }; | ||
458 | |||
459 | #define INIT_ARCH_ELF_STATE {} | ||
460 | |||
461 | /** | ||
462 | * arch_elf_pt_proc() - check a PT_LOPROC..PT_HIPROC ELF program header | ||
463 | * @ehdr: The main ELF header | ||
464 | * @phdr: The program header to check | ||
465 | * @elf: The open ELF file | ||
466 | * @is_interp: True if the phdr is from the interpreter of the ELF being | ||
467 | * loaded, else false. | ||
468 | * @state: Architecture-specific state preserved throughout the process | ||
469 | * of loading the ELF. | ||
470 | * | ||
471 | * Inspects the program header phdr to validate its correctness and/or | ||
472 | * suitability for the system. Called once per ELF program header in the | ||
473 | * range PT_LOPROC to PT_HIPROC, for both the ELF being loaded and its | ||
474 | * interpreter. | ||
475 | * | ||
476 | * Return: Zero to proceed with the ELF load, non-zero to fail the ELF load | ||
477 | * with that return code. | ||
478 | */ | ||
479 | static inline int arch_elf_pt_proc(struct elfhdr *ehdr, | ||
480 | struct elf_phdr *phdr, | ||
481 | struct file *elf, bool is_interp, | ||
482 | struct arch_elf_state *state) | ||
483 | { | ||
484 | /* Dummy implementation, always proceed */ | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * arch_check_elf() - check a PT_LOPROC..PT_HIPROC ELF program header | ||
490 | * @ehdr: The main ELF header | ||
491 | * @has_interp: True if the ELF has an interpreter, else false. | ||
492 | * @state: Architecture-specific state preserved throughout the process | ||
493 | * of loading the ELF. | ||
494 | * | ||
495 | * Provides a final opportunity for architecture code to reject the loading | ||
496 | * of the ELF & cause an exec syscall to return an error. This is called after | ||
497 | * all program headers to be checked by arch_elf_pt_proc have been. | ||
498 | * | ||
499 | * Return: Zero to proceed with the ELF load, non-zero to fail the ELF load | ||
500 | * with that return code. | ||
501 | */ | ||
502 | static inline int arch_check_elf(struct elfhdr *ehdr, bool has_interp, | ||
503 | struct arch_elf_state *state) | ||
504 | { | ||
505 | /* Dummy implementation, always proceed */ | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | #endif /* !CONFIG_ARCH_BINFMT_ELF_STATE */ | ||
389 | 510 | ||
390 | /* This is much more generalized than the library routine read function, | 511 | /* This is much more generalized than the library routine read function, |
391 | so we keep this separate. Technically the library read function | 512 | so we keep this separate. Technically the library read function |
@@ -394,16 +515,15 @@ static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr) | |||
394 | 515 | ||
395 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | 516 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, |
396 | struct file *interpreter, unsigned long *interp_map_addr, | 517 | struct file *interpreter, unsigned long *interp_map_addr, |
397 | unsigned long no_base) | 518 | unsigned long no_base, struct elf_phdr *interp_elf_phdata) |
398 | { | 519 | { |
399 | struct elf_phdr *elf_phdata; | ||
400 | struct elf_phdr *eppnt; | 520 | struct elf_phdr *eppnt; |
401 | unsigned long load_addr = 0; | 521 | unsigned long load_addr = 0; |
402 | int load_addr_set = 0; | 522 | int load_addr_set = 0; |
403 | unsigned long last_bss = 0, elf_bss = 0; | 523 | unsigned long last_bss = 0, elf_bss = 0; |
404 | unsigned long error = ~0UL; | 524 | unsigned long error = ~0UL; |
405 | unsigned long total_size; | 525 | unsigned long total_size; |
406 | int retval, i, size; | 526 | int i; |
407 | 527 | ||
408 | /* First of all, some simple consistency checks */ | 528 | /* First of all, some simple consistency checks */ |
409 | if (interp_elf_ex->e_type != ET_EXEC && | 529 | if (interp_elf_ex->e_type != ET_EXEC && |
@@ -414,40 +534,14 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
414 | if (!interpreter->f_op->mmap) | 534 | if (!interpreter->f_op->mmap) |
415 | goto out; | 535 | goto out; |
416 | 536 | ||
417 | /* | 537 | total_size = total_mapping_size(interp_elf_phdata, |
418 | * If the size of this structure has changed, then punt, since | 538 | interp_elf_ex->e_phnum); |
419 | * we will be doing the wrong thing. | ||
420 | */ | ||
421 | if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) | ||
422 | goto out; | ||
423 | if (interp_elf_ex->e_phnum < 1 || | ||
424 | interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) | ||
425 | goto out; | ||
426 | |||
427 | /* Now read in all of the header information */ | ||
428 | size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; | ||
429 | if (size > ELF_MIN_ALIGN) | ||
430 | goto out; | ||
431 | elf_phdata = kmalloc(size, GFP_KERNEL); | ||
432 | if (!elf_phdata) | ||
433 | goto out; | ||
434 | |||
435 | retval = kernel_read(interpreter, interp_elf_ex->e_phoff, | ||
436 | (char *)elf_phdata, size); | ||
437 | error = -EIO; | ||
438 | if (retval != size) { | ||
439 | if (retval < 0) | ||
440 | error = retval; | ||
441 | goto out_close; | ||
442 | } | ||
443 | |||
444 | total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum); | ||
445 | if (!total_size) { | 539 | if (!total_size) { |
446 | error = -EINVAL; | 540 | error = -EINVAL; |
447 | goto out_close; | 541 | goto out; |
448 | } | 542 | } |
449 | 543 | ||
450 | eppnt = elf_phdata; | 544 | eppnt = interp_elf_phdata; |
451 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { | 545 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { |
452 | if (eppnt->p_type == PT_LOAD) { | 546 | if (eppnt->p_type == PT_LOAD) { |
453 | int elf_type = MAP_PRIVATE | MAP_DENYWRITE; | 547 | int elf_type = MAP_PRIVATE | MAP_DENYWRITE; |
@@ -474,7 +568,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
474 | *interp_map_addr = map_addr; | 568 | *interp_map_addr = map_addr; |
475 | error = map_addr; | 569 | error = map_addr; |
476 | if (BAD_ADDR(map_addr)) | 570 | if (BAD_ADDR(map_addr)) |
477 | goto out_close; | 571 | goto out; |
478 | 572 | ||
479 | if (!load_addr_set && | 573 | if (!load_addr_set && |
480 | interp_elf_ex->e_type == ET_DYN) { | 574 | interp_elf_ex->e_type == ET_DYN) { |
@@ -493,7 +587,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
493 | eppnt->p_memsz > TASK_SIZE || | 587 | eppnt->p_memsz > TASK_SIZE || |
494 | TASK_SIZE - eppnt->p_memsz < k) { | 588 | TASK_SIZE - eppnt->p_memsz < k) { |
495 | error = -ENOMEM; | 589 | error = -ENOMEM; |
496 | goto out_close; | 590 | goto out; |
497 | } | 591 | } |
498 | 592 | ||
499 | /* | 593 | /* |
@@ -523,7 +617,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
523 | */ | 617 | */ |
524 | if (padzero(elf_bss)) { | 618 | if (padzero(elf_bss)) { |
525 | error = -EFAULT; | 619 | error = -EFAULT; |
526 | goto out_close; | 620 | goto out; |
527 | } | 621 | } |
528 | 622 | ||
529 | /* What we have mapped so far */ | 623 | /* What we have mapped so far */ |
@@ -532,13 +626,10 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
532 | /* Map the last of the bss segment */ | 626 | /* Map the last of the bss segment */ |
533 | error = vm_brk(elf_bss, last_bss - elf_bss); | 627 | error = vm_brk(elf_bss, last_bss - elf_bss); |
534 | if (BAD_ADDR(error)) | 628 | if (BAD_ADDR(error)) |
535 | goto out_close; | 629 | goto out; |
536 | } | 630 | } |
537 | 631 | ||
538 | error = load_addr; | 632 | error = load_addr; |
539 | |||
540 | out_close: | ||
541 | kfree(elf_phdata); | ||
542 | out: | 633 | out: |
543 | return error; | 634 | return error; |
544 | } | 635 | } |
@@ -575,10 +666,9 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
575 | int load_addr_set = 0; | 666 | int load_addr_set = 0; |
576 | char * elf_interpreter = NULL; | 667 | char * elf_interpreter = NULL; |
577 | unsigned long error; | 668 | unsigned long error; |
578 | struct elf_phdr *elf_ppnt, *elf_phdata; | 669 | struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; |
579 | unsigned long elf_bss, elf_brk; | 670 | unsigned long elf_bss, elf_brk; |
580 | int retval, i; | 671 | int retval, i; |
581 | unsigned int size; | ||
582 | unsigned long elf_entry; | 672 | unsigned long elf_entry; |
583 | unsigned long interp_load_addr = 0; | 673 | unsigned long interp_load_addr = 0; |
584 | unsigned long start_code, end_code, start_data, end_data; | 674 | unsigned long start_code, end_code, start_data, end_data; |
@@ -589,6 +679,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
589 | struct elfhdr elf_ex; | 679 | struct elfhdr elf_ex; |
590 | struct elfhdr interp_elf_ex; | 680 | struct elfhdr interp_elf_ex; |
591 | } *loc; | 681 | } *loc; |
682 | struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE; | ||
592 | 683 | ||
593 | loc = kmalloc(sizeof(*loc), GFP_KERNEL); | 684 | loc = kmalloc(sizeof(*loc), GFP_KERNEL); |
594 | if (!loc) { | 685 | if (!loc) { |
@@ -611,26 +702,10 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
611 | if (!bprm->file->f_op->mmap) | 702 | if (!bprm->file->f_op->mmap) |
612 | goto out; | 703 | goto out; |
613 | 704 | ||
614 | /* Now read in all of the header information */ | 705 | elf_phdata = load_elf_phdrs(&loc->elf_ex, bprm->file); |
615 | if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) | ||
616 | goto out; | ||
617 | if (loc->elf_ex.e_phnum < 1 || | ||
618 | loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr)) | ||
619 | goto out; | ||
620 | size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); | ||
621 | retval = -ENOMEM; | ||
622 | elf_phdata = kmalloc(size, GFP_KERNEL); | ||
623 | if (!elf_phdata) | 706 | if (!elf_phdata) |
624 | goto out; | 707 | goto out; |
625 | 708 | ||
626 | retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, | ||
627 | (char *)elf_phdata, size); | ||
628 | if (retval != size) { | ||
629 | if (retval >= 0) | ||
630 | retval = -EIO; | ||
631 | goto out_free_ph; | ||
632 | } | ||
633 | |||
634 | elf_ppnt = elf_phdata; | 709 | elf_ppnt = elf_phdata; |
635 | elf_bss = 0; | 710 | elf_bss = 0; |
636 | elf_brk = 0; | 711 | elf_brk = 0; |
@@ -699,12 +774,21 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
699 | 774 | ||
700 | elf_ppnt = elf_phdata; | 775 | elf_ppnt = elf_phdata; |
701 | for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) | 776 | for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) |
702 | if (elf_ppnt->p_type == PT_GNU_STACK) { | 777 | switch (elf_ppnt->p_type) { |
778 | case PT_GNU_STACK: | ||
703 | if (elf_ppnt->p_flags & PF_X) | 779 | if (elf_ppnt->p_flags & PF_X) |
704 | executable_stack = EXSTACK_ENABLE_X; | 780 | executable_stack = EXSTACK_ENABLE_X; |
705 | else | 781 | else |
706 | executable_stack = EXSTACK_DISABLE_X; | 782 | executable_stack = EXSTACK_DISABLE_X; |
707 | break; | 783 | break; |
784 | |||
785 | case PT_LOPROC ... PT_HIPROC: | ||
786 | retval = arch_elf_pt_proc(&loc->elf_ex, elf_ppnt, | ||
787 | bprm->file, false, | ||
788 | &arch_state); | ||
789 | if (retval) | ||
790 | goto out_free_dentry; | ||
791 | break; | ||
708 | } | 792 | } |
709 | 793 | ||
710 | /* Some simple consistency checks for the interpreter */ | 794 | /* Some simple consistency checks for the interpreter */ |
@@ -716,8 +800,36 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
716 | /* Verify the interpreter has a valid arch */ | 800 | /* Verify the interpreter has a valid arch */ |
717 | if (!elf_check_arch(&loc->interp_elf_ex)) | 801 | if (!elf_check_arch(&loc->interp_elf_ex)) |
718 | goto out_free_dentry; | 802 | goto out_free_dentry; |
803 | |||
804 | /* Load the interpreter program headers */ | ||
805 | interp_elf_phdata = load_elf_phdrs(&loc->interp_elf_ex, | ||
806 | interpreter); | ||
807 | if (!interp_elf_phdata) | ||
808 | goto out_free_dentry; | ||
809 | |||
810 | /* Pass PT_LOPROC..PT_HIPROC headers to arch code */ | ||
811 | elf_ppnt = interp_elf_phdata; | ||
812 | for (i = 0; i < loc->interp_elf_ex.e_phnum; i++, elf_ppnt++) | ||
813 | switch (elf_ppnt->p_type) { | ||
814 | case PT_LOPROC ... PT_HIPROC: | ||
815 | retval = arch_elf_pt_proc(&loc->interp_elf_ex, | ||
816 | elf_ppnt, interpreter, | ||
817 | true, &arch_state); | ||
818 | if (retval) | ||
819 | goto out_free_dentry; | ||
820 | break; | ||
821 | } | ||
719 | } | 822 | } |
720 | 823 | ||
824 | /* | ||
825 | * Allow arch code to reject the ELF at this point, whilst it's | ||
826 | * still possible to return an error to the code that invoked | ||
827 | * the exec syscall. | ||
828 | */ | ||
829 | retval = arch_check_elf(&loc->elf_ex, !!interpreter, &arch_state); | ||
830 | if (retval) | ||
831 | goto out_free_dentry; | ||
832 | |||
721 | /* Flush all traces of the currently running executable */ | 833 | /* Flush all traces of the currently running executable */ |
722 | retval = flush_old_exec(bprm); | 834 | retval = flush_old_exec(bprm); |
723 | if (retval) | 835 | if (retval) |
@@ -725,7 +837,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
725 | 837 | ||
726 | /* Do this immediately, since STACK_TOP as used in setup_arg_pages | 838 | /* Do this immediately, since STACK_TOP as used in setup_arg_pages |
727 | may depend on the personality. */ | 839 | may depend on the personality. */ |
728 | SET_PERSONALITY(loc->elf_ex); | 840 | SET_PERSONALITY2(loc->elf_ex, &arch_state); |
729 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) | 841 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) |
730 | current->personality |= READ_IMPLIES_EXEC; | 842 | current->personality |= READ_IMPLIES_EXEC; |
731 | 843 | ||
@@ -890,7 +1002,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
890 | elf_entry = load_elf_interp(&loc->interp_elf_ex, | 1002 | elf_entry = load_elf_interp(&loc->interp_elf_ex, |
891 | interpreter, | 1003 | interpreter, |
892 | &interp_map_addr, | 1004 | &interp_map_addr, |
893 | load_bias); | 1005 | load_bias, interp_elf_phdata); |
894 | if (!IS_ERR((void *)elf_entry)) { | 1006 | if (!IS_ERR((void *)elf_entry)) { |
895 | /* | 1007 | /* |
896 | * load_elf_interp() returns relocation | 1008 | * load_elf_interp() returns relocation |
@@ -917,6 +1029,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
917 | } | 1029 | } |
918 | } | 1030 | } |
919 | 1031 | ||
1032 | kfree(interp_elf_phdata); | ||
920 | kfree(elf_phdata); | 1033 | kfree(elf_phdata); |
921 | 1034 | ||
922 | set_binfmt(&elf_format); | 1035 | set_binfmt(&elf_format); |
@@ -981,6 +1094,7 @@ out_ret: | |||
981 | 1094 | ||
982 | /* error cleanup */ | 1095 | /* error cleanup */ |
983 | out_free_dentry: | 1096 | out_free_dentry: |
1097 | kfree(interp_elf_phdata); | ||
984 | allow_write_access(interpreter); | 1098 | allow_write_access(interpreter); |
985 | if (interpreter) | 1099 | if (interpreter) |
986 | fput(interpreter); | 1100 | fput(interpreter); |