diff options
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 667b2e62fad2..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 |
@@ -1108,6 +1110,7 @@ DECLARE_RWSEM(uts_sem); | |||
1108 | /* | 1110 | /* |
1109 | * Work around broken programs that cannot handle "Linux 3.0". | 1111 | * Work around broken programs that cannot handle "Linux 3.0". |
1110 | * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 | 1112 | * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 |
1113 | * And we map 4.x to 2.6.60+x, so 4.0 would be 2.6.60. | ||
1111 | */ | 1114 | */ |
1112 | static int override_release(char __user *release, size_t len) | 1115 | static int override_release(char __user *release, size_t len) |
1113 | { | 1116 | { |
@@ -1127,7 +1130,7 @@ static int override_release(char __user *release, size_t len) | |||
1127 | break; | 1130 | break; |
1128 | rest++; | 1131 | rest++; |
1129 | } | 1132 | } |
1130 | v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; | 1133 | v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 60; |
1131 | copy = clamp_t(size_t, len, 1, sizeof(buf)); | 1134 | copy = clamp_t(size_t, len, 1, sizeof(buf)); |
1132 | copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); | 1135 | copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); |
1133 | ret = copy_to_user(release, buf, copy + 1); | 1136 | ret = copy_to_user(release, buf, copy + 1); |
@@ -1646,14 +1649,13 @@ SYSCALL_DEFINE1(umask, int, mask) | |||
1646 | return mask; | 1649 | return mask; |
1647 | } | 1650 | } |
1648 | 1651 | ||
1649 | 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) |
1650 | { | 1653 | { |
1651 | struct fd exe; | 1654 | struct fd exe; |
1655 | struct file *old_exe, *exe_file; | ||
1652 | struct inode *inode; | 1656 | struct inode *inode; |
1653 | int err; | 1657 | int err; |
1654 | 1658 | ||
1655 | VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_sem), mm); | ||
1656 | |||
1657 | exe = fdget(fd); | 1659 | exe = fdget(fd); |
1658 | if (!exe.file) | 1660 | if (!exe.file) |
1659 | return -EBADF; | 1661 | return -EBADF; |
@@ -1677,15 +1679,22 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) | |||
1677 | /* | 1679 | /* |
1678 | * Forbid mm->exe_file change if old file still mapped. | 1680 | * Forbid mm->exe_file change if old file still mapped. |
1679 | */ | 1681 | */ |
1682 | exe_file = get_mm_exe_file(mm); | ||
1680 | err = -EBUSY; | 1683 | err = -EBUSY; |
1681 | if (mm->exe_file) { | 1684 | if (exe_file) { |
1682 | struct vm_area_struct *vma; | 1685 | struct vm_area_struct *vma; |
1683 | 1686 | ||
1684 | for (vma = mm->mmap; vma; vma = vma->vm_next) | 1687 | down_read(&mm->mmap_sem); |
1685 | if (vma->vm_file && | 1688 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
1686 | path_equal(&vma->vm_file->f_path, | 1689 | if (!vma->vm_file) |
1687 | &mm->exe_file->f_path)) | 1690 | continue; |
1688 | 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); | ||
1689 | } | 1698 | } |
1690 | 1699 | ||
1691 | /* | 1700 | /* |
@@ -1699,10 +1708,18 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) | |||
1699 | goto exit; | 1708 | goto exit; |
1700 | 1709 | ||
1701 | err = 0; | 1710 | err = 0; |
1702 | 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); | ||
1703 | exit: | 1716 | exit: |
1704 | fdput(exe); | 1717 | fdput(exe); |
1705 | return err; | 1718 | return err; |
1719 | exit_err: | ||
1720 | up_read(&mm->mmap_sem); | ||
1721 | fput(exe_file); | ||
1722 | goto exit; | ||
1706 | } | 1723 | } |
1707 | 1724 | ||
1708 | #ifdef CONFIG_CHECKPOINT_RESTORE | 1725 | #ifdef CONFIG_CHECKPOINT_RESTORE |
@@ -1837,10 +1854,9 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data | |||
1837 | user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL; | 1854 | user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL; |
1838 | } | 1855 | } |
1839 | 1856 | ||
1840 | down_write(&mm->mmap_sem); | ||
1841 | if (prctl_map.exe_fd != (u32)-1) | 1857 | if (prctl_map.exe_fd != (u32)-1) |
1842 | error = prctl_set_mm_exe_file_locked(mm, prctl_map.exe_fd); | 1858 | error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd); |
1843 | downgrade_write(&mm->mmap_sem); | 1859 | down_read(&mm->mmap_sem); |
1844 | if (error) | 1860 | if (error) |
1845 | goto out; | 1861 | goto out; |
1846 | 1862 | ||
@@ -1906,12 +1922,8 @@ static int prctl_set_mm(int opt, unsigned long addr, | |||
1906 | if (!capable(CAP_SYS_RESOURCE)) | 1922 | if (!capable(CAP_SYS_RESOURCE)) |
1907 | return -EPERM; | 1923 | return -EPERM; |
1908 | 1924 | ||
1909 | if (opt == PR_SET_MM_EXE_FILE) { | 1925 | if (opt == PR_SET_MM_EXE_FILE) |
1910 | down_write(&mm->mmap_sem); | 1926 | return prctl_set_mm_exe_file(mm, (unsigned int)addr); |
1911 | error = prctl_set_mm_exe_file_locked(mm, (unsigned int)addr); | ||
1912 | up_write(&mm->mmap_sem); | ||
1913 | return error; | ||
1914 | } | ||
1915 | 1927 | ||
1916 | if (addr >= TASK_SIZE || addr < mmap_min_addr) | 1928 | if (addr >= TASK_SIZE || addr < mmap_min_addr) |
1917 | return -EINVAL; | 1929 | return -EINVAL; |