diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 68 |
1 files changed, 35 insertions, 33 deletions
@@ -126,8 +126,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
126 | struct nameidata nd; | 126 | struct nameidata nd; |
127 | int error; | 127 | int error; |
128 | 128 | ||
129 | nd.intent.open.flags = FMODE_READ; | 129 | error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ); |
130 | error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); | ||
131 | if (error) | 130 | if (error) |
132 | goto out; | 131 | goto out; |
133 | 132 | ||
@@ -139,7 +138,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
139 | if (error) | 138 | if (error) |
140 | goto exit; | 139 | goto exit; |
141 | 140 | ||
142 | file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); | 141 | file = nameidata_to_filp(&nd, O_RDONLY); |
143 | error = PTR_ERR(file); | 142 | error = PTR_ERR(file); |
144 | if (IS_ERR(file)) | 143 | if (IS_ERR(file)) |
145 | goto out; | 144 | goto out; |
@@ -167,6 +166,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
167 | out: | 166 | out: |
168 | return error; | 167 | return error; |
169 | exit: | 168 | exit: |
169 | release_open_intent(&nd); | ||
170 | path_release(&nd); | 170 | path_release(&nd); |
171 | goto out; | 171 | goto out; |
172 | } | 172 | } |
@@ -309,40 +309,36 @@ void install_arg_page(struct vm_area_struct *vma, | |||
309 | pud_t * pud; | 309 | pud_t * pud; |
310 | pmd_t * pmd; | 310 | pmd_t * pmd; |
311 | pte_t * pte; | 311 | pte_t * pte; |
312 | spinlock_t *ptl; | ||
312 | 313 | ||
313 | if (unlikely(anon_vma_prepare(vma))) | 314 | if (unlikely(anon_vma_prepare(vma))) |
314 | goto out_sig; | 315 | goto out; |
315 | 316 | ||
316 | flush_dcache_page(page); | 317 | flush_dcache_page(page); |
317 | pgd = pgd_offset(mm, address); | 318 | pgd = pgd_offset(mm, address); |
318 | |||
319 | spin_lock(&mm->page_table_lock); | ||
320 | pud = pud_alloc(mm, pgd, address); | 319 | pud = pud_alloc(mm, pgd, address); |
321 | if (!pud) | 320 | if (!pud) |
322 | goto out; | 321 | goto out; |
323 | pmd = pmd_alloc(mm, pud, address); | 322 | pmd = pmd_alloc(mm, pud, address); |
324 | if (!pmd) | 323 | if (!pmd) |
325 | goto out; | 324 | goto out; |
326 | pte = pte_alloc_map(mm, pmd, address); | 325 | pte = pte_alloc_map_lock(mm, pmd, address, &ptl); |
327 | if (!pte) | 326 | if (!pte) |
328 | goto out; | 327 | goto out; |
329 | if (!pte_none(*pte)) { | 328 | if (!pte_none(*pte)) { |
330 | pte_unmap(pte); | 329 | pte_unmap_unlock(pte, ptl); |
331 | goto out; | 330 | goto out; |
332 | } | 331 | } |
333 | inc_mm_counter(mm, rss); | 332 | inc_mm_counter(mm, anon_rss); |
334 | lru_cache_add_active(page); | 333 | lru_cache_add_active(page); |
335 | set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte( | 334 | set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte( |
336 | page, vma->vm_page_prot)))); | 335 | page, vma->vm_page_prot)))); |
337 | page_add_anon_rmap(page, vma, address); | 336 | page_add_anon_rmap(page, vma, address); |
338 | pte_unmap(pte); | 337 | pte_unmap_unlock(pte, ptl); |
339 | spin_unlock(&mm->page_table_lock); | ||
340 | 338 | ||
341 | /* no need for flush_tlb */ | 339 | /* no need for flush_tlb */ |
342 | return; | 340 | return; |
343 | out: | 341 | out: |
344 | spin_unlock(&mm->page_table_lock); | ||
345 | out_sig: | ||
346 | __free_page(page); | 342 | __free_page(page); |
347 | force_sig(SIGKILL, current); | 343 | force_sig(SIGKILL, current); |
348 | } | 344 | } |
@@ -490,8 +486,7 @@ struct file *open_exec(const char *name) | |||
490 | int err; | 486 | int err; |
491 | struct file *file; | 487 | struct file *file; |
492 | 488 | ||
493 | nd.intent.open.flags = FMODE_READ; | 489 | err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ); |
494 | err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); | ||
495 | file = ERR_PTR(err); | 490 | file = ERR_PTR(err); |
496 | 491 | ||
497 | if (!err) { | 492 | if (!err) { |
@@ -504,7 +499,7 @@ struct file *open_exec(const char *name) | |||
504 | err = -EACCES; | 499 | err = -EACCES; |
505 | file = ERR_PTR(err); | 500 | file = ERR_PTR(err); |
506 | if (!err) { | 501 | if (!err) { |
507 | file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); | 502 | file = nameidata_to_filp(&nd, O_RDONLY); |
508 | if (!IS_ERR(file)) { | 503 | if (!IS_ERR(file)) { |
509 | err = deny_write_access(file); | 504 | err = deny_write_access(file); |
510 | if (err) { | 505 | if (err) { |
@@ -516,6 +511,7 @@ out: | |||
516 | return file; | 511 | return file; |
517 | } | 512 | } |
518 | } | 513 | } |
514 | release_open_intent(&nd); | ||
519 | path_release(&nd); | 515 | path_release(&nd); |
520 | } | 516 | } |
521 | goto out; | 517 | goto out; |
@@ -634,10 +630,9 @@ static inline int de_thread(struct task_struct *tsk) | |||
634 | /* | 630 | /* |
635 | * Account for the thread group leader hanging around: | 631 | * Account for the thread group leader hanging around: |
636 | */ | 632 | */ |
637 | count = 2; | 633 | count = 1; |
638 | if (thread_group_leader(current)) | 634 | if (!thread_group_leader(current)) { |
639 | count = 1; | 635 | count = 2; |
640 | else { | ||
641 | /* | 636 | /* |
642 | * The SIGALRM timer survives the exec, but needs to point | 637 | * The SIGALRM timer survives the exec, but needs to point |
643 | * at us as the new group leader now. We have a race with | 638 | * at us as the new group leader now. We have a race with |
@@ -646,8 +641,10 @@ static inline int de_thread(struct task_struct *tsk) | |||
646 | * before we can safely let the old group leader die. | 641 | * before we can safely let the old group leader die. |
647 | */ | 642 | */ |
648 | sig->real_timer.data = (unsigned long)current; | 643 | sig->real_timer.data = (unsigned long)current; |
644 | spin_unlock_irq(lock); | ||
649 | if (del_timer_sync(&sig->real_timer)) | 645 | if (del_timer_sync(&sig->real_timer)) |
650 | add_timer(&sig->real_timer); | 646 | add_timer(&sig->real_timer); |
647 | spin_lock_irq(lock); | ||
651 | } | 648 | } |
652 | while (atomic_read(&sig->count) > count) { | 649 | while (atomic_read(&sig->count) > count) { |
653 | sig->group_exit_task = current; | 650 | sig->group_exit_task = current; |
@@ -659,7 +656,6 @@ static inline int de_thread(struct task_struct *tsk) | |||
659 | } | 656 | } |
660 | sig->group_exit_task = NULL; | 657 | sig->group_exit_task = NULL; |
661 | sig->notify_count = 0; | 658 | sig->notify_count = 0; |
662 | sig->real_timer.data = (unsigned long)current; | ||
663 | spin_unlock_irq(lock); | 659 | spin_unlock_irq(lock); |
664 | 660 | ||
665 | /* | 661 | /* |
@@ -1207,7 +1203,6 @@ int do_execve(char * filename, | |||
1207 | /* execve success */ | 1203 | /* execve success */ |
1208 | security_bprm_free(bprm); | 1204 | security_bprm_free(bprm); |
1209 | acct_update_integrals(current); | 1205 | acct_update_integrals(current); |
1210 | update_mem_hiwater(current); | ||
1211 | kfree(bprm); | 1206 | kfree(bprm); |
1212 | return retval; | 1207 | return retval; |
1213 | } | 1208 | } |
@@ -1422,19 +1417,16 @@ static void zap_threads (struct mm_struct *mm) | |||
1422 | static void coredump_wait(struct mm_struct *mm) | 1417 | static void coredump_wait(struct mm_struct *mm) |
1423 | { | 1418 | { |
1424 | DECLARE_COMPLETION(startup_done); | 1419 | DECLARE_COMPLETION(startup_done); |
1420 | int core_waiters; | ||
1425 | 1421 | ||
1426 | mm->core_waiters++; /* let other threads block */ | ||
1427 | mm->core_startup_done = &startup_done; | 1422 | mm->core_startup_done = &startup_done; |
1428 | 1423 | ||
1429 | /* give other threads a chance to run: */ | ||
1430 | yield(); | ||
1431 | |||
1432 | zap_threads(mm); | 1424 | zap_threads(mm); |
1433 | if (--mm->core_waiters) { | 1425 | core_waiters = mm->core_waiters; |
1434 | up_write(&mm->mmap_sem); | 1426 | up_write(&mm->mmap_sem); |
1427 | |||
1428 | if (core_waiters) | ||
1435 | wait_for_completion(&startup_done); | 1429 | wait_for_completion(&startup_done); |
1436 | } else | ||
1437 | up_write(&mm->mmap_sem); | ||
1438 | BUG_ON(mm->core_waiters); | 1430 | BUG_ON(mm->core_waiters); |
1439 | } | 1431 | } |
1440 | 1432 | ||
@@ -1468,11 +1460,21 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1468 | current->fsuid = 0; /* Dump root private */ | 1460 | current->fsuid = 0; /* Dump root private */ |
1469 | } | 1461 | } |
1470 | mm->dumpable = 0; | 1462 | mm->dumpable = 0; |
1471 | init_completion(&mm->core_done); | 1463 | |
1464 | retval = -EAGAIN; | ||
1472 | spin_lock_irq(¤t->sighand->siglock); | 1465 | spin_lock_irq(¤t->sighand->siglock); |
1473 | current->signal->flags = SIGNAL_GROUP_EXIT; | 1466 | if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { |
1474 | current->signal->group_exit_code = exit_code; | 1467 | current->signal->flags = SIGNAL_GROUP_EXIT; |
1468 | current->signal->group_exit_code = exit_code; | ||
1469 | retval = 0; | ||
1470 | } | ||
1475 | spin_unlock_irq(¤t->sighand->siglock); | 1471 | spin_unlock_irq(¤t->sighand->siglock); |
1472 | if (retval) { | ||
1473 | up_write(&mm->mmap_sem); | ||
1474 | goto fail; | ||
1475 | } | ||
1476 | |||
1477 | init_completion(&mm->core_done); | ||
1476 | coredump_wait(mm); | 1478 | coredump_wait(mm); |
1477 | 1479 | ||
1478 | /* | 1480 | /* |