aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c49
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
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
@@ -1647,14 +1649,13 @@ SYSCALL_DEFINE1(umask, int, mask)
1647 return mask; 1649 return mask;
1648} 1650}
1649 1651
1650static 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)
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);
1704exit: 1716exit:
1705 fdput(exe); 1717 fdput(exe);
1706 return err; 1718 return err;
1719exit_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;