diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-22 05:11:59 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-25 09:23:53 -0400 |
commit | fd8328be874f4190a811c58cd4778ec2c74d2c05 (patch) | |
tree | b44ae8e99ce96a1a4739b04d4d1a23c40ab8b163 /fs/binfmt_elf.c | |
parent | 6b335d9c80d7f3c2a3f6545f664ae9007a0f3821 (diff) |
[PATCH] sanitize handling of shared descriptor tables in failing execve()
* unshare_files() can fail; doing it after irreversible actions is wrong
and de_thread() is certainly irreversible.
* since we do it unconditionally anyway, we might as well do it in do_execve()
and save ourselves the PITA in binfmt handlers, etc.
* while we are at it, binfmt_som actually leaked files_struct on failure.
As a side benefit, unshare_files(), put_files_struct() and reset_files_struct()
become unexported.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 23 |
1 files changed, 1 insertions, 22 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 5e1a4fb5cacb..9924581df6f6 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -543,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
543 | unsigned long interp_load_addr = 0; | 543 | unsigned long interp_load_addr = 0; |
544 | unsigned long start_code, end_code, start_data, end_data; | 544 | unsigned long start_code, end_code, start_data, end_data; |
545 | unsigned long reloc_func_desc = 0; | 545 | unsigned long reloc_func_desc = 0; |
546 | struct files_struct *files; | ||
547 | int executable_stack = EXSTACK_DEFAULT; | 546 | int executable_stack = EXSTACK_DEFAULT; |
548 | unsigned long def_flags = 0; | 547 | unsigned long def_flags = 0; |
549 | struct { | 548 | struct { |
@@ -593,20 +592,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
593 | goto out_free_ph; | 592 | goto out_free_ph; |
594 | } | 593 | } |
595 | 594 | ||
596 | files = current->files; /* Refcounted so ok */ | ||
597 | retval = unshare_files(); | ||
598 | if (retval < 0) | ||
599 | goto out_free_ph; | ||
600 | if (files == current->files) { | ||
601 | put_files_struct(files); | ||
602 | files = NULL; | ||
603 | } | ||
604 | |||
605 | /* exec will make our files private anyway, but for the a.out | ||
606 | loader stuff we need to do it earlier */ | ||
607 | retval = get_unused_fd(); | 595 | retval = get_unused_fd(); |
608 | if (retval < 0) | 596 | if (retval < 0) |
609 | goto out_free_fh; | 597 | goto out_free_ph; |
610 | get_file(bprm->file); | 598 | get_file(bprm->file); |
611 | fd_install(elf_exec_fileno = retval, bprm->file); | 599 | fd_install(elf_exec_fileno = retval, bprm->file); |
612 | 600 | ||
@@ -728,12 +716,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
728 | if (retval) | 716 | if (retval) |
729 | goto out_free_dentry; | 717 | goto out_free_dentry; |
730 | 718 | ||
731 | /* Discard our unneeded old files struct */ | ||
732 | if (files) { | ||
733 | put_files_struct(files); | ||
734 | files = NULL; | ||
735 | } | ||
736 | |||
737 | /* OK, This is the point of no return */ | 719 | /* OK, This is the point of no return */ |
738 | current->flags &= ~PF_FORKNOEXEC; | 720 | current->flags &= ~PF_FORKNOEXEC; |
739 | current->mm->def_flags = def_flags; | 721 | current->mm->def_flags = def_flags; |
@@ -1016,9 +998,6 @@ out_free_interp: | |||
1016 | kfree(elf_interpreter); | 998 | kfree(elf_interpreter); |
1017 | out_free_file: | 999 | out_free_file: |
1018 | sys_close(elf_exec_fileno); | 1000 | sys_close(elf_exec_fileno); |
1019 | out_free_fh: | ||
1020 | if (files) | ||
1021 | reset_files_struct(current, files); | ||
1022 | out_free_ph: | 1001 | out_free_ph: |
1023 | kfree(elf_phdata); | 1002 | kfree(elf_phdata); |
1024 | goto out; | 1003 | goto out; |