[PATCH] sanitize handling of shared descriptor tables in failing execve()
[linux-2.6-block.git] / fs / exec.c
index 54a0a557b6781ecf379015bbd60dc6f3fd37c176..475543002f13847ad7e2ef42eac0d1313c7a837a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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;
 }