History

Merge tag 'denywrite-for-5.15' of git://github.com/davidhildenbrand/linux

Pull MAP_DENYWRITE removal from David Hildenbrand: "Remove all in-tree usage of MAP_DENYWRITE from the kernel and remove VM_DENYWRITE. There are some (minor) user-visible changes: - We no longer deny write access to shared libaries loaded via legacy uselib(); this behavior matches modern user space e.g. dlopen(). - We no longer deny write access to the elf interpreter after exec completed, treating it just like shared libraries (which it often is). - We always deny write access to the file linked via /proc/pid/exe: sys_prctl(PR_SET_MM_MAP/EXE_FILE) will fail if write access to the file cannot be denied, and write access to the file will remain denied until the link is effectivel gone (exec, termination, sys_prctl(PR_SET_MM_MAP/EXE_FILE)) -- just as if exec'ing the file. Cross-compiled for a bunch of architectures (alpha, microblaze, i386, s390x, ...) and verified via ltp that especially the relevant tests (i.e., creat07 and execve04) continue working as expected" * tag 'denywrite-for-5.15' of git://github.com/davidhildenbrand/linux: fs: update documentation of get_write_access() and friends mm: ignore MAP_DENYWRITE in ksys_mmap_pgoff() mm: remove VM_DENYWRITE binfmt: remove in-tree usage of MAP_DENYWRITE kernel/fork: always deny write access to current MM exe_file kernel/fork: factor out replacing the current MM exe_file binfmt: don't use MAP_DENYWRITE when loading shared libraries via uselib()

Linus Torvalds committed 5 years ago

Commit 49624ef2 parents f746406 592ca0916 files · +119 −103Browse files

Showing the changes to kernel (3 of 16 files). Show all

Unified · Split

3 files
  1. kernel/events/core.c +0 −2
  2. kernel/fork.c +84 −11
  3. kernel/sys.c +1 −32
kernel/events/core.c+0−2
@@ -8320,8 +8320,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) · 8319 unmodified lines
8320 else8320 else
8321 flags = MAP_PRIVATE;8321 flags = MAP_PRIVATE;
8322 8322
8323 if (vma->vm_flags & VM_DENYWRITE)
8324 flags |= MAP_DENYWRITE;
8325 if (vma->vm_flags & VM_LOCKED)8323 if (vma->vm_flags & VM_LOCKED)
8326 flags |= MAP_LOCKED;8324 flags |= MAP_LOCKED;
8327 if (is_vm_hugetlb_page(vma))8325 if (is_vm_hugetlb_page(vma))
kernel/fork.c+84−11
@@ -471,6 +471,20 @@ void free_task(struct task_struct *tsk) · 470 unmodified lines
471}471}
472EXPORT_SYMBOL(free_task);472EXPORT_SYMBOL(free_task);
473 473
474static void dup_mm_exe_file(struct mm_struct *mm, struct mm_struct *oldmm)
475{
476 struct file *exe_file;
477
478 exe_file = get_mm_exe_file(oldmm);
479 RCU_INIT_POINTER(mm->exe_file, exe_file);
480 /*
481 * We depend on the oldmm having properly denied write access to the
482 * exe_file already.
483 */
484 if (exe_file && deny_write_access(exe_file))
485 pr_warn_once("deny_write_access() failed in %s\n", __func__);
486}
487
474#ifdef CONFIG_MMU488#ifdef CONFIG_MMU
475static __latent_entropy int dup_mmap(struct mm_struct *mm,489static __latent_entropy int dup_mmap(struct mm_struct *mm,
476 struct mm_struct *oldmm)490 struct mm_struct *oldmm)
@@ -494,7 +508,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, · 17 unmodified lines
494 mmap_write_lock_nested(mm, SINGLE_DEPTH_NESTING);508 mmap_write_lock_nested(mm, SINGLE_DEPTH_NESTING);
495 509
496 /* No ordering required: file already has been exposed. */510 /* No ordering required: file already has been exposed. */
497 RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm));511 dup_mm_exe_file(mm, oldmm);
498 512
499 mm->total_vm = oldmm->total_vm;513 mm->total_vm = oldmm->total_vm;
500 mm->data_vm = oldmm->data_vm;514 mm->data_vm = oldmm->data_vm;
@@ -557,12 +571,9 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, · 56 unmodified lines
557 tmp->vm_flags &= ~(VM_LOCKED | VM_LOCKONFAULT);571 tmp->vm_flags &= ~(VM_LOCKED | VM_LOCKONFAULT);
558 file = tmp->vm_file;572 file = tmp->vm_file;
559 if (file) {573 if (file) {
560 struct inode *inode = file_inode(file);
561 struct address_space *mapping = file->f_mapping;574 struct address_space *mapping = file->f_mapping;
562 575
563 get_file(file);576 get_file(file);
564 if (tmp->vm_flags & VM_DENYWRITE)
565 put_write_access(inode);
566 i_mmap_lock_write(mapping);577 i_mmap_lock_write(mapping);
567 if (tmp->vm_flags & VM_SHARED)578 if (tmp->vm_flags & VM_SHARED)
568 mapping_allow_writable(mapping);579 mapping_allow_writable(mapping);
@@ -640,7 +651,7 @@ static inline void mm_free_pgd(struct mm_struct *mm) · 71 unmodified lines
640static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)651static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
641{652{
642 mmap_write_lock(oldmm);653 mmap_write_lock(oldmm);
643 RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm));654 dup_mm_exe_file(mm, oldmm);
644 mmap_write_unlock(oldmm);655 mmap_write_unlock(oldmm);
645 return 0;656 return 0;
646}657}
@@ -1150,11 +1161,11 @@ void mmput_async(struct mm_struct *mm) · 503 unmodified lines
1150 *1161 *
1151 * Main users are mmput() and sys_execve(). Callers prevent concurrent1162 * Main users are mmput() and sys_execve(). Callers prevent concurrent
1152 * invocations: in mmput() nobody alive left, in execve task is single1163 * invocations: in mmput() nobody alive left, in execve task is single
1153 * threaded. sys_prctl(PR_SET_MM_MAP/EXE_FILE) also needs to set the1164 * threaded.
1154 * mm->exe_file, but does so without using set_mm_exe_file() in order1165 *
1155 * to avoid the need for any locks.1166 * Can only fail if new_exe_file != NULL.
1156 */1167 */
1157void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)1168int set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
1158{1169{
1159 struct file *old_exe_file;1170 struct file *old_exe_file;
1160 1171
@@ -1165,11 +1176,73 @@ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) · 4 unmodified lines
1165 */1176 */
1166 old_exe_file = rcu_dereference_raw(mm->exe_file);1177 old_exe_file = rcu_dereference_raw(mm->exe_file);
1167 1178
1168 if (new_exe_file)1179 if (new_exe_file) {
1180 /*
1181 * We expect the caller (i.e., sys_execve) to already denied
1182 * write access, so this is unlikely to fail.
1183 */
1184 if (unlikely(deny_write_access(new_exe_file)))
1185 return -EACCES;
1169 get_file(new_exe_file);1186 get_file(new_exe_file);
1187 }
1170 rcu_assign_pointer(mm->exe_file, new_exe_file);1188 rcu_assign_pointer(mm->exe_file, new_exe_file);
1171 if (old_exe_file)1189 if (old_exe_file) {
1190 allow_write_access(old_exe_file);
1172 fput(old_exe_file);1191 fput(old_exe_file);
1192 }
1193 return 0;
1194}
1195
1196/**
1197 * replace_mm_exe_file - replace a reference to the mm's executable file
1198 *
1199 * This changes mm's executable file (shown as symlink /proc/[pid]/exe),
1200 * dealing with concurrent invocation and without grabbing the mmap lock in
1201 * write mode.
1202 *
1203 * Main user is sys_prctl(PR_SET_MM_MAP/EXE_FILE).
1204 */
1205int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
1206{
1207 struct vm_area_struct *vma;
1208 struct file *old_exe_file;
1209 int ret = 0;
1210
1211 /* Forbid mm->exe_file change if old file still mapped. */
1212 old_exe_file = get_mm_exe_file(mm);
1213 if (old_exe_file) {
1214 mmap_read_lock(mm);
1215 for (vma = mm->mmap; vma && !ret; vma = vma->vm_next) {
1216 if (!vma->vm_file)
1217 continue;
1218 if (path_equal(&vma->vm_file->f_path,
1219 &old_exe_file->f_path))
1220 ret = -EBUSY;
1221 }
1222 mmap_read_unlock(mm);
1223 fput(old_exe_file);
1224 if (ret)
1225 return ret;
1226 }
1227
1228 /* set the new file, lockless */
1229 ret = deny_write_access(new_exe_file);
1230 if (ret)
1231 return -EACCES;
1232 get_file(new_exe_file);
1233
1234 old_exe_file = xchg(&mm->exe_file, new_exe_file);
1235 if (old_exe_file) {
1236 /*
1237 * Don't race with dup_mmap() getting the file and disallowing
1238 * write access while someone might open the file writable.
1239 */
1240 mmap_read_lock(mm);
1241 allow_write_access(old_exe_file);
1242 fput(old_exe_file);
1243 mmap_read_unlock(mm);
1244 }
1245 return 0;
1173}1246}
1174 1247
1175/**1248/**
kernel/sys.c+1−32
@@ -1847,7 +1847,6 @@ SYSCALL_DEFINE1(umask, int, mask) · 1846 unmodified lines
1847static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)1847static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1848{1848{
1849 struct fd exe;1849 struct fd exe;
1850 struct file *old_exe, *exe_file;
1851 struct inode *inode;1850 struct inode *inode;
1852 int err;1851 int err;
1853 1852
@@ -1870,40 +1869,10 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) · 16 unmodified lines
1870 if (err)1869 if (err)
1871 goto exit;1870 goto exit;
1872 1871
1873 /*1872 err = replace_mm_exe_file(mm, exe.file);
1874 * Forbid mm->exe_file change if old file still mapped.
1875 */
1876 exe_file = get_mm_exe_file(mm);
1877 err = -EBUSY;
1878 if (exe_file) {
1879 struct vm_area_struct *vma;
1880
1881 mmap_read_lock(mm);
1882 for (vma = mm->mmap; vma; vma = vma->vm_next) {
1883 if (!vma->vm_file)
1884 continue;
1885 if (path_equal(&vma->vm_file->f_path,
1886 &exe_file->f_path))
1887 goto exit_err;
1888 }
1889
1890 mmap_read_unlock(mm);
1891 fput(exe_file);
1892 }
1893
1894 err = 0;
1895 /* set the new file, lockless */
1896 get_file(exe.file);
1897 old_exe = xchg(&mm->exe_file, exe.file);
1898 if (old_exe)
1899 fput(old_exe);
1900exit:1873exit:
1901 fdput(exe);1874 fdput(exe);
1902 return err;1875 return err;
1903exit_err:
1904 mmap_read_unlock(mm);
1905 fput(exe_file);
1906 goto exit;
1907}1876}
1908 1877
1909/*1878/*