@@ -1786,27 +1786,13 @@ SYSCALL_DEFINE1(umask, int, mask)
1786
1786
}
1787
1787
1788
1788
#ifdef CONFIG_CHECKPOINT_RESTORE
1789
- static 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
-
1797
1789
static int prctl_set_mm_exe_file (struct mm_struct * mm , unsigned int fd )
1798
1790
{
1791
+ struct vm_area_struct * vma ;
1799
1792
struct file * exe_file ;
1800
1793
struct dentry * dentry ;
1801
1794
int err ;
1802
1795
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
1796
exe_file = fget (fd );
1811
1797
if (!exe_file )
1812
1798
return - EBADF ;
@@ -1827,17 +1813,30 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1827
1813
if (err )
1828
1814
goto exit ;
1829
1815
1816
+ down_write (& mm -> mmap_sem );
1817
+
1818
+ /*
1819
+ * Forbid mm->exe_file change if there are mapped other files.
1820
+ */
1821
+ err = - EBUSY ;
1822
+ for (vma = mm -> mmap ; vma ; vma = vma -> vm_next ) {
1823
+ if (vma -> vm_file && !path_equal (& vma -> vm_file -> f_path ,
1824
+ & exe_file -> f_path ))
1825
+ goto exit_unlock ;
1826
+ }
1827
+
1830
1828
/*
1831
1829
* The symlink can be changed only once, just to disallow arbitrary
1832
1830
* transitions malicious software might bring in. This means one
1833
1831
* could make a snapshot over all processes running and monitor
1834
1832
* /proc/pid/exe changes to notice unusual activity if needed.
1835
1833
*/
1836
- down_write (& mm -> mmap_sem );
1837
- if (likely (!mm -> exe_file ))
1838
- set_mm_exe_file (mm , exe_file );
1839
- else
1840
- err = - EBUSY ;
1834
+ err = - EPERM ;
1835
+ if (test_and_set_bit (MMF_EXE_FILE_CHANGED , & mm -> flags ))
1836
+ goto exit_unlock ;
1837
+
1838
+ set_mm_exe_file (mm , exe_file );
1839
+ exit_unlock :
1841
1840
up_write (& mm -> mmap_sem );
1842
1841
1843
1842
exit :
@@ -1862,7 +1861,7 @@ static int prctl_set_mm(int opt, unsigned long addr,
1862
1861
if (opt == PR_SET_MM_EXE_FILE )
1863
1862
return prctl_set_mm_exe_file (mm , (unsigned int )addr );
1864
1863
1865
- if (addr >= TASK_SIZE )
1864
+ if (addr >= TASK_SIZE || addr < mmap_min_addr )
1866
1865
return - EINVAL ;
1867
1866
1868
1867
error = - EINVAL ;
@@ -1924,12 +1923,6 @@ static int prctl_set_mm(int opt, unsigned long addr,
1924
1923
error = - EFAULT ;
1925
1924
goto out ;
1926
1925
}
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
1926
if (opt == PR_SET_MM_START_STACK )
1934
1927
mm -> start_stack = addr ;
1935
1928
else if (opt == PR_SET_MM_ARG_START )
@@ -1981,12 +1974,22 @@ static int prctl_set_mm(int opt, unsigned long addr,
1981
1974
up_read (& mm -> mmap_sem );
1982
1975
return error ;
1983
1976
}
1977
+
1978
+ static int prctl_get_tid_address (struct task_struct * me , int __user * * tid_addr )
1979
+ {
1980
+ return put_user (me -> clear_child_tid , tid_addr );
1981
+ }
1982
+
1984
1983
#else /* CONFIG_CHECKPOINT_RESTORE */
1985
1984
static int prctl_set_mm (int opt , unsigned long addr ,
1986
1985
unsigned long arg4 , unsigned long arg5 )
1987
1986
{
1988
1987
return - EINVAL ;
1989
1988
}
1989
+ static int prctl_get_tid_address (struct task_struct * me , int __user * * tid_addr )
1990
+ {
1991
+ return - EINVAL ;
1992
+ }
1990
1993
#endif
1991
1994
1992
1995
SYSCALL_DEFINE5 (prctl , int , option , unsigned long , arg2 , unsigned long , arg3 ,
@@ -2124,6 +2127,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
2124
2127
else
2125
2128
return - EINVAL ;
2126
2129
break ;
2130
+ case PR_GET_TID_ADDRESS :
2131
+ error = prctl_get_tid_address (me , (int __user * * )arg2 );
2132
+ break ;
2127
2133
default :
2128
2134
return - EINVAL ;
2129
2135
}
0 commit comments