diff options
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index a03d9cd23ed7..a4e372b798a5 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -325,6 +325,7 @@ out_unlock: | |||
325 | * SMP: There are not races, the GIDs are checked only by filesystem | 325 | * SMP: There are not races, the GIDs are checked only by filesystem |
326 | * operations (as far as semantic preservation is concerned). | 326 | * operations (as far as semantic preservation is concerned). |
327 | */ | 327 | */ |
328 | #ifdef CONFIG_MULTIUSER | ||
328 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | 329 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) |
329 | { | 330 | { |
330 | struct user_namespace *ns = current_user_ns(); | 331 | struct user_namespace *ns = current_user_ns(); |
@@ -815,6 +816,7 @@ change_okay: | |||
815 | commit_creds(new); | 816 | commit_creds(new); |
816 | return old_fsgid; | 817 | return old_fsgid; |
817 | } | 818 | } |
819 | #endif /* CONFIG_MULTIUSER */ | ||
818 | 820 | ||
819 | /** | 821 | /** |
820 | * sys_getpid - return the thread group id of the current process | 822 | * sys_getpid - return the thread group id of the current process |
@@ -1647,14 +1649,13 @@ SYSCALL_DEFINE1(umask, int, mask) | |||
1647 | return mask; | 1649 | return mask; |
1648 | } | 1650 | } |
1649 | 1651 | ||
1650 | static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) | 1652 | static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) |
1651 | { | 1653 | { |
1652 | struct fd exe; | 1654 | struct fd exe; |
1655 | struct file *old_exe, *exe_file; | ||
1653 | struct inode *inode; | 1656 | struct inode *inode; |
1654 | int err; | 1657 | int err; |
1655 | 1658 | ||
1656 | VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_sem), mm); | ||
1657 | |||
1658 | exe = fdget(fd); | 1659 | exe = fdget(fd); |
1659 | if (!exe.file) | 1660 | if (!exe.file) |
1660 | return -EBADF; | 1661 | return -EBADF; |
@@ -1678,15 +1679,22 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) | |||
1678 | /* | 1679 | /* |
1679 | * Forbid mm->exe_file change if old file still mapped. | 1680 | * Forbid mm->exe_file change if old file still mapped. |
1680 | */ | 1681 | */ |
1682 | exe_file = get_mm_exe_file(mm); | ||
1681 | err = -EBUSY; | 1683 | err = -EBUSY; |
1682 | if (mm->exe_file) { | 1684 | if (exe_file) { |
1683 | struct vm_area_struct *vma; | 1685 | struct vm_area_struct *vma; |
1684 | 1686 | ||
1685 | for (vma = mm->mmap; vma; vma = vma->vm_next) | 1687 | down_read(&mm->mmap_sem); |
1686 | if (vma->vm_file && | 1688 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
1687 | path_equal(&vma->vm_file->f_path, | 1689 | if (!vma->vm_file) |
1688 | &mm->exe_file->f_path)) | 1690 | continue; |
1689 | goto exit; | 1691 | if (path_equal(&vma->vm_file->f_path, |
1692 | &exe_file->f_path)) | ||
1693 | goto exit_err; | ||
1694 | } | ||
1695 | |||
1696 | up_read(&mm->mmap_sem); | ||
1697 | fput(exe_file); | ||
1690 | } | 1698 | } |
1691 | 1699 | ||
1692 | /* | 1700 | /* |
@@ -1700,10 +1708,18 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) | |||
1700 | goto exit; | 1708 | goto exit; |
1701 | 1709 | ||
1702 | err = 0; | 1710 | err = 0; |
1703 | set_mm_exe_file(mm, exe.file); /* this grabs a reference to exe.file */ | 1711 | /* set the new file, lockless */ |
1712 | get_file(exe.file); | ||
1713 | old_exe = xchg(&mm->exe_file, exe.file); | ||
1714 | if (old_exe) | ||
1715 | fput(old_exe); | ||
1704 | exit: | 1716 | exit: |
1705 | fdput(exe); | 1717 | fdput(exe); |
1706 | return err; | 1718 | return err; |
1719 | exit_err: | ||
1720 | up_read(&mm->mmap_sem); | ||
1721 | fput(exe_file); | ||
1722 | goto exit; | ||
1707 | } | 1723 | } |
1708 | 1724 | ||
1709 | #ifdef CONFIG_CHECKPOINT_RESTORE | 1725 | #ifdef CONFIG_CHECKPOINT_RESTORE |
@@ -1838,10 +1854,9 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data | |||
1838 | user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL; | 1854 | user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL; |
1839 | } | 1855 | } |
1840 | 1856 | ||
1841 | down_write(&mm->mmap_sem); | ||
1842 | if (prctl_map.exe_fd != (u32)-1) | 1857 | if (prctl_map.exe_fd != (u32)-1) |
1843 | error = prctl_set_mm_exe_file_locked(mm, prctl_map.exe_fd); | 1858 | error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd); |
1844 | downgrade_write(&mm->mmap_sem); | 1859 | down_read(&mm->mmap_sem); |
1845 | if (error) | 1860 | if (error) |
1846 | goto out; | 1861 | goto out; |
1847 | 1862 | ||
@@ -1907,12 +1922,8 @@ static int prctl_set_mm(int opt, unsigned long addr, | |||
1907 | if (!capable(CAP_SYS_RESOURCE)) | 1922 | if (!capable(CAP_SYS_RESOURCE)) |
1908 | return -EPERM; | 1923 | return -EPERM; |
1909 | 1924 | ||
1910 | if (opt == PR_SET_MM_EXE_FILE) { | 1925 | if (opt == PR_SET_MM_EXE_FILE) |
1911 | down_write(&mm->mmap_sem); | 1926 | return prctl_set_mm_exe_file(mm, (unsigned int)addr); |
1912 | error = prctl_set_mm_exe_file_locked(mm, (unsigned int)addr); | ||
1913 | up_write(&mm->mmap_sem); | ||
1914 | return error; | ||
1915 | } | ||
1916 | 1927 | ||
1917 | if (addr >= TASK_SIZE || addr < mmap_min_addr) | 1928 | if (addr >= TASK_SIZE || addr < mmap_min_addr) |
1918 | return -EINVAL; | 1929 | return -EINVAL; |