diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 259202637531..0d23e76a0c61 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -711,15 +711,22 @@ EXPORT_SYMBOL_GPL(mmput); | |||
| 711 | * | 711 | * |
| 712 | * This changes mm's executable file (shown as symlink /proc/[pid]/exe). | 712 | * This changes mm's executable file (shown as symlink /proc/[pid]/exe). |
| 713 | * | 713 | * |
| 714 | * Main users are mmput(), sys_execve() and sys_prctl(PR_SET_MM_MAP/EXE_FILE). | 714 | * Main users are mmput() and sys_execve(). Callers prevent concurrent |
| 715 | * Callers prevent concurrent invocations: in mmput() nobody alive left, | 715 | * invocations: in mmput() nobody alive left, in execve task is single |
| 716 | * in execve task is single-threaded, prctl holds mmap_sem exclusively. | 716 | * threaded. sys_prctl(PR_SET_MM_MAP/EXE_FILE) also needs to set the |
| 717 | * mm->exe_file, but does so without using set_mm_exe_file() in order | ||
| 718 | * to do avoid the need for any locks. | ||
| 717 | */ | 719 | */ |
| 718 | void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) | 720 | void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) |
| 719 | { | 721 | { |
| 720 | struct file *old_exe_file = rcu_dereference_protected(mm->exe_file, | 722 | struct file *old_exe_file; |
| 721 | !atomic_read(&mm->mm_users) || current->in_execve || | 723 | |
| 722 | lockdep_is_held(&mm->mmap_sem)); | 724 | /* |
| 725 | * It is safe to dereference the exe_file without RCU as | ||
| 726 | * this function is only called if nobody else can access | ||
| 727 | * this mm -- see comment above for justification. | ||
| 728 | */ | ||
| 729 | old_exe_file = rcu_dereference_raw(mm->exe_file); | ||
| 723 | 730 | ||
| 724 | if (new_exe_file) | 731 | if (new_exe_file) |
| 725 | get_file(new_exe_file); | 732 | get_file(new_exe_file); |
