Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

c/r: prctl: update prctl_set_mm_exe_file() after mm->num_exe_file_vmas removal

A fix for commit b32dfe377102 ("c/r: prctl: add ability to set new
mm_struct::exe_file").

After removing mm->num_exe_file_vmas kernel keeps mm->exe_file until
final mmput(), it never becomes NULL while task is alive.

We can check for other mapped files in mm instead of checking
mm->num_exe_file_vmas, and mark mm with flag MMF_EXE_FILE_CHANGED in
order to forbid second changing of mm->exe_file.

Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Matt Helsley <matthltc@us.ibm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Konstantin Khlebnikov and committed by
Linus Torvalds
bafb282d 6305902c

+20 -12
+1
include/linux/sched.h
··· 439 439 /* leave room for more dump flags */ 440 440 #define MMF_VM_MERGEABLE 16 /* KSM may merge identical pages */ 441 441 #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ 442 + #define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ 442 443 443 444 #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) 444 445
+19 -12
kernel/sys.c
··· 1796 1796 1797 1797 static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) 1798 1798 { 1799 + struct vm_area_struct *vma; 1799 1800 struct file *exe_file; 1800 1801 struct dentry *dentry; 1801 1802 int err; 1802 - 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 1803 1810 1804 exe_file = fget(fd); 1811 1805 if (!exe_file) ··· 1821 1827 if (err) 1822 1828 goto exit; 1823 1829 1830 + down_write(&mm->mmap_sem); 1831 + 1832 + /* 1833 + * Forbid mm->exe_file change if there are mapped other files. 1834 + */ 1835 + err = -EBUSY; 1836 + for (vma = mm->mmap; vma; vma = vma->vm_next) { 1837 + if (vma->vm_file && !path_equal(&vma->vm_file->f_path, 1838 + &exe_file->f_path)) 1839 + goto exit_unlock; 1840 + } 1841 + 1824 1842 /* 1825 1843 * The symlink can be changed only once, just to disallow arbitrary 1826 1844 * transitions malicious software might bring in. This means one 1827 1845 * could make a snapshot over all processes running and monitor 1828 1846 * /proc/pid/exe changes to notice unusual activity if needed. 1829 1847 */ 1830 - down_write(&mm->mmap_sem); 1831 - if (likely(!mm->exe_file)) 1832 - set_mm_exe_file(mm, exe_file); 1833 - else 1834 - err = -EBUSY; 1848 + err = -EPERM; 1849 + if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) 1850 + goto exit_unlock; 1851 + 1852 + set_mm_exe_file(mm, exe_file); 1853 + exit_unlock: 1835 1854 up_write(&mm->mmap_sem); 1836 1855 1837 1856 exit: