aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c64
1 files changed, 37 insertions, 27 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 9ff89cb9657a..2d39a84cd857 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1786,27 +1786,12 @@ SYSCALL_DEFINE1(umask, int, mask)
1786} 1786}
1787 1787
1788#ifdef CONFIG_CHECKPOINT_RESTORE 1788#ifdef CONFIG_CHECKPOINT_RESTORE
1789static bool vma_flags_mismatch(struct vm_area_struct *vma,
1790 unsigned long required,
1791 unsigned long banned)
1792{
1793 return (vma->vm_flags & required) != required ||
1794 (vma->vm_flags & banned);
1795}
1796
1797static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) 1789static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1798{ 1790{
1799 struct file *exe_file; 1791 struct file *exe_file;
1800 struct dentry *dentry; 1792 struct dentry *dentry;
1801 int err; 1793 int err;
1802 1794
1803 /*
1804 * Setting new mm::exe_file is only allowed when no VM_EXECUTABLE vma's
1805 * remain. So perform a quick test first.
1806 */
1807 if (mm->num_exe_file_vmas)
1808 return -EBUSY;
1809
1810 exe_file = fget(fd); 1795 exe_file = fget(fd);
1811 if (!exe_file) 1796 if (!exe_file)
1812 return -EBADF; 1797 return -EBADF;
@@ -1827,17 +1812,35 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1827 if (err) 1812 if (err)
1828 goto exit; 1813 goto exit;
1829 1814
1815 down_write(&mm->mmap_sem);
1816
1817 /*
1818 * Forbid mm->exe_file change if old file still mapped.
1819 */
1820 err = -EBUSY;
1821 if (mm->exe_file) {
1822 struct vm_area_struct *vma;
1823
1824 for (vma = mm->mmap; vma; vma = vma->vm_next)
1825 if (vma->vm_file &&
1826 path_equal(&vma->vm_file->f_path,
1827 &mm->exe_file->f_path))
1828 goto exit_unlock;
1829 }
1830
1830 /* 1831 /*
1831 * The symlink can be changed only once, just to disallow arbitrary 1832 * The symlink can be changed only once, just to disallow arbitrary
1832 * transitions malicious software might bring in. This means one 1833 * transitions malicious software might bring in. This means one
1833 * could make a snapshot over all processes running and monitor 1834 * could make a snapshot over all processes running and monitor
1834 * /proc/pid/exe changes to notice unusual activity if needed. 1835 * /proc/pid/exe changes to notice unusual activity if needed.
1835 */ 1836 */
1836 down_write(&mm->mmap_sem); 1837 err = -EPERM;
1837 if (likely(!mm->exe_file)) 1838 if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags))
1838 set_mm_exe_file(mm, exe_file); 1839 goto exit_unlock;
1839 else 1840
1840 err = -EBUSY; 1841 err = 0;
1842 set_mm_exe_file(mm, exe_file);
1843exit_unlock:
1841 up_write(&mm->mmap_sem); 1844 up_write(&mm->mmap_sem);
1842 1845
1843exit: 1846exit:
@@ -1862,7 +1865,7 @@ static int prctl_set_mm(int opt, unsigned long addr,
1862 if (opt == PR_SET_MM_EXE_FILE) 1865 if (opt == PR_SET_MM_EXE_FILE)
1863 return prctl_set_mm_exe_file(mm, (unsigned int)addr); 1866 return prctl_set_mm_exe_file(mm, (unsigned int)addr);
1864 1867
1865 if (addr >= TASK_SIZE) 1868 if (addr >= TASK_SIZE || addr < mmap_min_addr)
1866 return -EINVAL; 1869 return -EINVAL;
1867 1870
1868 error = -EINVAL; 1871 error = -EINVAL;
@@ -1924,12 +1927,6 @@ static int prctl_set_mm(int opt, unsigned long addr,
1924 error = -EFAULT; 1927 error = -EFAULT;
1925 goto out; 1928 goto out;
1926 } 1929 }
1927#ifdef CONFIG_STACK_GROWSUP
1928 if (vma_flags_mismatch(vma, VM_READ | VM_WRITE | VM_GROWSUP, 0))
1929#else
1930 if (vma_flags_mismatch(vma, VM_READ | VM_WRITE | VM_GROWSDOWN, 0))
1931#endif
1932 goto out;
1933 if (opt == PR_SET_MM_START_STACK) 1930 if (opt == PR_SET_MM_START_STACK)
1934 mm->start_stack = addr; 1931 mm->start_stack = addr;
1935 else if (opt == PR_SET_MM_ARG_START) 1932 else if (opt == PR_SET_MM_ARG_START)
@@ -1981,12 +1978,22 @@ out:
1981 up_read(&mm->mmap_sem); 1978 up_read(&mm->mmap_sem);
1982 return error; 1979 return error;
1983} 1980}
1981
1982static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
1983{
1984 return put_user(me->clear_child_tid, tid_addr);
1985}
1986
1984#else /* CONFIG_CHECKPOINT_RESTORE */ 1987#else /* CONFIG_CHECKPOINT_RESTORE */
1985static int prctl_set_mm(int opt, unsigned long addr, 1988static int prctl_set_mm(int opt, unsigned long addr,
1986 unsigned long arg4, unsigned long arg5) 1989 unsigned long arg4, unsigned long arg5)
1987{ 1990{
1988 return -EINVAL; 1991 return -EINVAL;
1989} 1992}
1993static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
1994{
1995 return -EINVAL;
1996}
1990#endif 1997#endif
1991 1998
1992SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, 1999SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
@@ -2141,6 +2148,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
2141 case PR_SET_MM: 2148 case PR_SET_MM:
2142 error = prctl_set_mm(arg2, arg3, arg4, arg5); 2149 error = prctl_set_mm(arg2, arg3, arg4, arg5);
2143 break; 2150 break;
2151 case PR_GET_TID_ADDRESS:
2152 error = prctl_get_tid_address(me, (int __user **)arg2);
2153 break;
2144 case PR_SET_CHILD_SUBREAPER: 2154 case PR_SET_CHILD_SUBREAPER:
2145 me->signal->is_child_subreaper = !!arg2; 2155 me->signal->is_child_subreaper = !!arg2;
2146 error = 0; 2156 error = 0;