aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c52
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
328SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) 329SYSCALL_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 */
1112static int override_release(char __user *release, size_t len) 1115static 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
1649static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) 1652static 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);
1703exit: 1716exit:
1704 fdput(exe); 1717 fdput(exe);
1705 return err; 1718 return err;
1719exit_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;