[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>
This commit is contained in:
Al Viro
2008-04-22 05:11:59 -04:00
parent 6b335d9c80
commit fd8328be87
6 changed files with 20 additions and 70 deletions

View File

@ -953,7 +953,6 @@ int flush_old_exec(struct linux_binprm * bprm)
{
char * name;
int i, ch, retval;
struct files_struct *files;
char tcomm[sizeof(current->comm)];
/*
@ -964,27 +963,16 @@ int flush_old_exec(struct linux_binprm * bprm)
if (retval)
goto out;
/*
* Make sure we have private file handles. Ask the
* fork helper to do the work for us and the exit
* helper to do the cleanup of the old one.
*/
files = current->files; /* refcounted so safe to hold */
retval = unshare_files();
if (retval)
goto out;
/*
* Release all of the old mmap stuff
*/
retval = exec_mmap(bprm->mm);
if (retval)
goto mmap_failed;
goto out;
bprm->mm = NULL; /* We're using it now */
/* This is the point of no return */
put_files_struct(files);
current->sas_ss_sp = current->sas_ss_size = 0;
if (current->euid == current->uid && current->egid == current->gid)
@ -1034,8 +1022,6 @@ int flush_old_exec(struct linux_binprm * bprm)
return 0;
mmap_failed:
reset_files_struct(current, files);
out:
return retval;
}
@ -1283,12 +1269,23 @@ int do_execve(char * filename,
struct linux_binprm *bprm;
struct file *file;
unsigned long env_p;
struct files_struct *files;
int retval;
files = current->files;
retval = unshare_files();
if (retval)
goto out_ret;
if (files == current->files) {
put_files_struct(files);
files = NULL;
}
retval = -ENOMEM;
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
if (!bprm)
goto out_ret;
goto out_files;
file = open_exec(filename);
retval = PTR_ERR(file);
@ -1343,6 +1340,8 @@ int do_execve(char * filename,
security_bprm_free(bprm);
acct_update_integrals(current);
kfree(bprm);
if (files)
put_files_struct(files);
return retval;
}
@ -1363,6 +1362,9 @@ out_file:
out_kfree:
kfree(bprm);
out_files:
if (files)
reset_files_struct(current, files);
out_ret:
return retval;
}