Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.5.75 /fs/exec.c

Filename:/fs/exec.c
Lines Added:34
Lines Deleted:23
Also changed in: (Previous) 2.5.74-bk7  2.5.74-bk6  2.5.74-bk5  2.5.74-bk4  2.5.74-bk3  2.5.74-bk2 
(Following) 2.5.75-bk1  2.5.75-bk2  2.5.75-bk3 

Location
[  2.5.75
  [  fs
     o  exec.c

Patch

diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c   Thu Jul 10 13:16:27 2003
+++ b/fs/exec.c   Thu Jul 10 13:16:27 2003
@@ -117,7 +117,8 @@
    struct nameidata nd;
    int error;
 
-   error = user_path_walk(library, &nd);
+   nd.intent.open.flags = O_RDONLY;
+   error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
    if (error)
       goto out;
 
@@ -125,7 +126,7 @@
    if (!S_ISREG(nd.dentry->d_inode->i_mode))
       goto exit;
 
-   error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC);
+   error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd);
    if (error)
       goto exit;
 
@@ -392,7 +393,7 @@
    if (!mpnt)
       return -ENOMEM;
 
-   if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+   if (security_vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
       kmem_cache_free(vm_area_cachep, mpnt);
       return -ENOMEM;
    }
@@ -441,9 +442,9 @@
 {
    int i;
 
-   for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
+   for (i = 0; i < MAX_ARG_PAGES; i++) {
       if (bprm->page[i])
-      __free_page(bprm->page[i]);
+         __free_page(bprm->page[i]);
       bprm->page[i] = NULL;
    }
 }
@@ -461,7 +462,7 @@
       file = ERR_PTR(-EACCES);
       if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
           S_ISREG(inode->i_mode)) {
-         int err = permission(inode, MAY_EXEC);
+         int err = permission(inode, MAY_EXEC, &nd);
          if (!err && !(inode->i_mode & 0111))
             err = -EACCES;
          file = ERR_PTR(err);
@@ -758,12 +759,6 @@
    char * name;
    int i, ch, retval;
 
-   /* 
-    * Release all of the old mmap stuff
-    */
-   retval = exec_mmap(bprm->mm);
-   if (retval)
-      goto out;
    /*
     * Make sure we have a private signal table and that
     * we are unassociated from the previous thread group.
@@ -772,6 +767,15 @@
    if (retval)
       goto out;
 
+   /*
+    * Release all of the old mmap stuff
+    */
+   retval = exec_mmap(bprm->mm);
+   if (retval)
+      goto out;
+
+   bprm->mm = NULL;      /* We're using it now */
+
    /* This is the point of no return */
 
    current->sas_ss_sp = current->sas_ss_size = 0;
@@ -791,7 +795,7 @@
    flush_thread();
 
    if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
-       permission(bprm->file->f_dentry->d_inode,MAY_READ))
+       permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL))
       current->mm->dumpable = 0;
 
    /* An exec changes our domain. We are no longer part of the thread
@@ -999,7 +1003,7 @@
          }
          read_lock(&binfmt_lock);
          put_binfmt(fmt);
-         if (retval != -ENOEXEC)
+         if (retval != -ENOEXEC || bprm->mm == NULL)
             break;
          if (!bprm->file) {
             read_unlock(&binfmt_lock);
@@ -1007,7 +1011,7 @@
          }
       }
       read_unlock(&binfmt_lock);
-      if (retval != -ENOEXEC) {
+      if (retval != -ENOEXEC || bprm->mm == NULL) {
          break;
 #ifdef CONFIG_KMOD
       }else{
@@ -1035,7 +1039,6 @@
    struct linux_binprm bprm;
    struct file *file;
    int retval;
-   int i;
 
    sched_balance_exec();
 
@@ -1103,17 +1106,14 @@
 
 out:
    /* Something went wrong, return the inode and free the argument pages*/
-   for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-      struct page * page = bprm.page[i];
-      if (page)
-         __free_page(page);
-   }
+   free_arg_pages(&bprm);
 
    if (bprm.security)
       security_bprm_free(&bprm);
 
 out_mm:
-   mmdrop(bprm.mm);
+   if (bprm.mm)
+      mmdrop(bprm.mm);
 
 out_file:
    if (bprm.file) {
@@ -1256,10 +1256,21 @@
 static void zap_threads (struct mm_struct *mm)
 {
    struct task_struct *g, *p;
+   struct task_struct *tsk = current;
+   struct completion *vfork_done = tsk->vfork_done;
+
+   /*
+    * Make sure nobody is waiting for us to release the VM,
+    * otherwise we can deadlock when we wait on each other
+    */
+   if (vfork_done) {
+      tsk->vfork_done = NULL;
+      complete(vfork_done);
+   }
 
    read_lock(&tasklist_lock);
    do_each_thread(g,p)
-      if (mm == p->mm && p != current) {
+      if (mm == p->mm && p != tsk) {
          force_sig_specific(SIGKILL, p);
          mm->core_waiters++;
       }


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.