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

Unified · Split

16 files
  1. arch/x86/ia32/ia32_aout.c +3 −5
  2. fs/binfmt_aout.c +3 −4
  3. fs/binfmt_elf.c +3 −3
  4. fs/binfmt_elf_fdpic.c +1 −1
  5. fs/exec.c +3 −1
  6. fs/proc/task_mmu.c +0 −1
  7. include/linux/fs.h +12 −7
  8. include/linux/mm.h +2 −2
  9. include/linux/mman.h +2 −2
  10. include/trace/events/mmflags.h +0 −1
  11. kernel/events/core.c +0 −2
  12. kernel/fork.c +84 −11
  13. kernel/sys.c +1 −32
  14. lib/test_printf.c +2 −3
  15. mm/mmap.c +3 −26
  16. mm/nommu.c +0 −2
arch/x86/ia32/ia32_aout.c+3−5
@@ -202,8 +202,7 @@ static int load_aout_binary(struct linux_binprm *bprm) · 201 unmodified lines
202 202
203 error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,203 error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
204 PROT_READ | PROT_EXEC,204 PROT_READ | PROT_EXEC,
205 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |205 MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
206 MAP_32BIT,
207 fd_offset);206 fd_offset);
208 207
209 if (error != N_TXTADDR(ex))208 if (error != N_TXTADDR(ex))
@@ -211,8 +210,7 @@ static int load_aout_binary(struct linux_binprm *bprm) · 1 unmodified line
211 210
212 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,211 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
213 PROT_READ | PROT_WRITE | PROT_EXEC,212 PROT_READ | PROT_WRITE | PROT_EXEC,
214 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |213 MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
215 MAP_32BIT,
216 fd_offset + ex.a_text);214 fd_offset + ex.a_text);
217 if (error != N_DATADDR(ex))215 if (error != N_DATADDR(ex))
218 return error;216 return error;
@@ -293,7 +291,7 @@ static int load_aout_library(struct file *file) · 74 unmodified lines
293 /* Now use mmap to map the library into memory. */291 /* Now use mmap to map the library into memory. */
294 error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,292 error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
295 PROT_READ | PROT_WRITE | PROT_EXEC,293 PROT_READ | PROT_WRITE | PROT_EXEC,
296 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,294 MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
297 N_TXTOFF(ex));295 N_TXTOFF(ex));
298 retval = error;296 retval = error;
299 if (error != start_addr)297 if (error != start_addr)
fs/binfmt_aout.c+3−4
@@ -221,8 +221,7 @@ static int load_aout_binary(struct linux_binprm * bprm) · 220 unmodified lines
221 }221 }
222 222
223 error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,223 error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
224 PROT_READ | PROT_EXEC,224 PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
225 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
226 fd_offset);225 fd_offset);
227 226
228 if (error != N_TXTADDR(ex))227 if (error != N_TXTADDR(ex))
@@ -230,7 +229,7 @@ static int load_aout_binary(struct linux_binprm * bprm) · 1 unmodified line
230 229
231 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,230 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
232 PROT_READ | PROT_WRITE | PROT_EXEC,231 PROT_READ | PROT_WRITE | PROT_EXEC,
233 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,232 MAP_FIXED | MAP_PRIVATE,
234 fd_offset + ex.a_text);233 fd_offset + ex.a_text);
235 if (error != N_DATADDR(ex))234 if (error != N_DATADDR(ex))
236 return error;235 return error;
@@ -309,7 +308,7 @@ static int load_aout_library(struct file *file) · 72 unmodified lines
309 /* Now use mmap to map the library into memory. */308 /* Now use mmap to map the library into memory. */
310 error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,309 error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
311 PROT_READ | PROT_WRITE | PROT_EXEC,310 PROT_READ | PROT_WRITE | PROT_EXEC,
312 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,311 MAP_FIXED | MAP_PRIVATE;
313 N_TXTOFF(ex));312 N_TXTOFF(ex));
314 retval = error;313 retval = error;
315 if (error != start_addr)314 if (error != start_addr)
fs/binfmt_elf.c+3−3
@@ -622,7 +622,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, · 621 unmodified lines
622 eppnt = interp_elf_phdata;622 eppnt = interp_elf_phdata;
623 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {623 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
624 if (eppnt->p_type == PT_LOAD) {624 if (eppnt->p_type == PT_LOAD) {
625 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;625 int elf_type = MAP_PRIVATE;
626 int elf_prot = make_prot(eppnt->p_flags, arch_state,626 int elf_prot = make_prot(eppnt->p_flags, arch_state,
627 true, true);627 true, true);
628 unsigned long vaddr = 0;628 unsigned long vaddr = 0;
@@ -1070,7 +1070,7 @@ out_free_interp: · 441 unmodified lines
1070 elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,1070 elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,
1071 !!interpreter, false);1071 !!interpreter, false);
1072 1072
1073 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;1073 elf_flags = MAP_PRIVATE;
1074 1074
1075 vaddr = elf_ppnt->p_vaddr;1075 vaddr = elf_ppnt->p_vaddr;
1076 /*1076 /*
@@ -1384,7 +1384,7 @@ static int load_elf_library(struct file *file) · 307 unmodified lines
1384 (eppnt->p_filesz +1384 (eppnt->p_filesz +
1385 ELF_PAGEOFFSET(eppnt->p_vaddr)),1385 ELF_PAGEOFFSET(eppnt->p_vaddr)),
1386 PROT_READ | PROT_WRITE | PROT_EXEC,1386 PROT_READ | PROT_WRITE | PROT_EXEC,
1387 MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_DENYWRITE,1387 MAP_FIXED_NOREPLACE | MAP_PRIVATE,
1388 (eppnt->p_offset -1388 (eppnt->p_offset -
1389 ELF_PAGEOFFSET(eppnt->p_vaddr)));1389 ELF_PAGEOFFSET(eppnt->p_vaddr)));
1390 if (error != ELF_PAGESTART(eppnt->p_vaddr))1390 if (error != ELF_PAGESTART(eppnt->p_vaddr))
fs/binfmt_elf_fdpic.c+1−1
@@ -1041,7 +1041,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, · 1040 unmodified lines
1041 if (phdr->p_flags & PF_W) prot |= PROT_WRITE;1041 if (phdr->p_flags & PF_W) prot |= PROT_WRITE;
1042 if (phdr->p_flags & PF_X) prot |= PROT_EXEC;1042 if (phdr->p_flags & PF_X) prot |= PROT_EXEC;
1043 1043
1044 flags = MAP_PRIVATE | MAP_DENYWRITE;1044 flags = MAP_PRIVATE;
1045 maddr = 0;1045 maddr = 0;
1046 1046
1047 switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {1047 switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {
fs/exec.c+3−1
@@ -1272,7 +1272,9 @@ int begin_new_exec(struct linux_binprm * bprm) · 1271 unmodified lines
1272 * not visibile until then. This also enables the update1272 * not visibile until then. This also enables the update
1273 * to be lockless.1273 * to be lockless.
1274 */1274 */
1275 set_mm_exe_file(bprm->mm, bprm->file);1275 retval = set_mm_exe_file(bprm->mm, bprm->file);
1276 if (retval)
1277 goto out;
1276 1278
1277 /* If the binary is not readable then enforce mm->dumpable=0 */1279 /* If the binary is not readable then enforce mm->dumpable=0 */
1278 would_dump(bprm, bprm->file);1280 would_dump(bprm, bprm->file);
fs/proc/task_mmu.c+0−1
@@ -619,7 +619,6 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) · 618 unmodified lines
619 [ilog2(VM_MAYSHARE)] = "ms",619 [ilog2(VM_MAYSHARE)] = "ms",
620 [ilog2(VM_GROWSDOWN)] = "gd",620 [ilog2(VM_GROWSDOWN)] = "gd",
621 [ilog2(VM_PFNMAP)] = "pf",621 [ilog2(VM_PFNMAP)] = "pf",
622 [ilog2(VM_DENYWRITE)] = "dw",
623 [ilog2(VM_LOCKED)] = "lo",622 [ilog2(VM_LOCKED)] = "lo",
624 [ilog2(VM_IO)] = "io",623 [ilog2(VM_IO)] = "io",
625 [ilog2(VM_SEQ_READ)] = "sr",624 [ilog2(VM_SEQ_READ)] = "sr",
include/linux/fs.h+12−7
@@ -3023,15 +3023,20 @@ static inline void file_end_write(struct file *file) · 3022 unmodified lines
3023}3023}
3024 3024
3025/*3025/*
3026 * This is used for regular files where some users -- especially the
3027 * currently executed binary in a process, previously handled via
3028 * VM_DENYWRITE -- cannot handle concurrent write (and maybe mmap
3029 * read-write shared) accesses.
3030 *
3026 * get_write_access() gets write permission for a file.3031 * get_write_access() gets write permission for a file.
3027 * put_write_access() releases this write permission.3032 * put_write_access() releases this write permission.
3028 * This is used for regular files.3033 * deny_write_access() denies write access to a file.
3029 * We cannot support write (and maybe mmap read-write shared) accesses and3034 * allow_write_access() re-enables write access to a file.
3030 * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode3035 *
3031 * can have the following values:3036 * The i_writecount field of an inode can have the following values:
3032 * 0: no writers, no VM_DENYWRITE mappings3037 * 0: no write access, no denied write access
3033 * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist3038 * < 0: (-i_writecount) users that denied write access to the file.
3034 * > 0: (i_writecount) users are writing to the file.3039 * > 0: (i_writecount) users that have write access to the file.
3035 *3040 *
3036 * Normally we operate on that counter with atomic_{inc,dec} and it's safe3041 * Normally we operate on that counter with atomic_{inc,dec} and it's safe
3037 * except for the cases where we don't hold i_writecount yet. Then we need to3042 * except for the cases where we don't hold i_writecount yet. Then we need to
include/linux/mm.h+2−2
@@ -281,7 +281,6 @@ extern unsigned int kobjsize(const void *objp); · 280 unmodified lines
281#define VM_GROWSDOWN 0x00000100 /* general info on the segment */281#define VM_GROWSDOWN 0x00000100 /* general info on the segment */
282#define VM_UFFD_MISSING 0x00000200 /* missing pages tracking */282#define VM_UFFD_MISSING 0x00000200 /* missing pages tracking */
283#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */283#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
284#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */
285#define VM_UFFD_WP 0x00001000 /* wrprotect pages tracking */284#define VM_UFFD_WP 0x00001000 /* wrprotect pages tracking */
286 285
287#define VM_LOCKED 0x00002000286#define VM_LOCKED 0x00002000
@@ -2573,7 +2572,8 @@ static inline int check_data_rlimit(unsigned long rlim, · 2285 unmodified lines
2573extern int mm_take_all_locks(struct mm_struct *mm);2572extern int mm_take_all_locks(struct mm_struct *mm);
2574extern void mm_drop_all_locks(struct mm_struct *mm);2573extern void mm_drop_all_locks(struct mm_struct *mm);
2575 2574
2576extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);2575extern int set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
2576extern int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
2577extern struct file *get_mm_exe_file(struct mm_struct *mm);2577extern struct file *get_mm_exe_file(struct mm_struct *mm);
2578extern struct file *get_task_exe_file(struct task_struct *task);2578extern struct file *get_task_exe_file(struct task_struct *task);
2579 2579
include/linux/mman.h+2−2
@@ -32,7 +32,8 @@ · 31 unmodified lines
32 * The historical set of flags that all mmap implementations implicitly32 * The historical set of flags that all mmap implementations implicitly
33 * support when a ->mmap_validate() op is not provided in file_operations.33 * support when a ->mmap_validate() op is not provided in file_operations.
34 *34 *
35 * MAP_EXECUTABLE is completely ignored throughout the kernel.35 * MAP_EXECUTABLE and MAP_DENYWRITE are completely ignored throughout the
36 * kernel.
36 */37 */
37#define LEGACY_MAP_MASK (MAP_SHARED \38#define LEGACY_MAP_MASK (MAP_SHARED \
38 | MAP_PRIVATE \39 | MAP_PRIVATE \
@@ -153,7 +154,6 @@ static inline unsigned long · 114 unmodified lines
153calc_vm_flag_bits(unsigned long flags)154calc_vm_flag_bits(unsigned long flags)
154{155{
155 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |156 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
156 _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
157 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) |157 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) |
158 _calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) |158 _calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) |
159 arch_calc_vm_flag_bits(flags);159 arch_calc_vm_flag_bits(flags);
include/trace/events/mmflags.h+0−1
@@ -165,7 +165,6 @@ IF_HAVE_PG_SKIP_KASAN_POISON(PG_skip_kasan_poison, "skip_kasan_poison") · 164 unmodified lines
165 {VM_UFFD_MISSING, "uffd_missing" }, \165 {VM_UFFD_MISSING, "uffd_missing" }, \
166IF_HAVE_UFFD_MINOR(VM_UFFD_MINOR, "uffd_minor" ) \166IF_HAVE_UFFD_MINOR(VM_UFFD_MINOR, "uffd_minor" ) \
167 {VM_PFNMAP, "pfnmap" }, \167 {VM_PFNMAP, "pfnmap" }, \
168 {VM_DENYWRITE, "denywrite" }, \
169 {VM_UFFD_WP, "uffd_wp" }, \168 {VM_UFFD_WP, "uffd_wp" }, \
170 {VM_LOCKED, "locked" }, \169 {VM_LOCKED, "locked" }, \
171 {VM_IO, "io" }, \170 {VM_IO, "io" }, \
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/*
lib/test_printf.c+2−3
@@ -675,9 +675,8 @@ flags(void) · 674 unmodified lines
675 "uptodate|dirty|lru|active|swapbacked",675 "uptodate|dirty|lru|active|swapbacked",
676 cmp_buffer);676 cmp_buffer);
677 677
678 flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC678 flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
679 | VM_DENYWRITE;679 test("read|exec|mayread|maywrite|mayexec", "%pGv", &flags);
680 test("read|exec|mayread|maywrite|mayexec|denywrite", "%pGv", &flags);
681 680
682 gfp = GFP_TRANSHUGE;681 gfp = GFP_TRANSHUGE;
683 test("GFP_TRANSHUGE", "%pGg", &gfp);682 test("GFP_TRANSHUGE", "%pGg", &gfp);
mm/mmap.c+3−26
@@ -148,8 +148,6 @@ void vma_set_page_prot(struct vm_area_struct *vma) · 147 unmodified lines
148static void __remove_shared_vm_struct(struct vm_area_struct *vma,148static void __remove_shared_vm_struct(struct vm_area_struct *vma,
149 struct file *file, struct address_space *mapping)149 struct file *file, struct address_space *mapping)
150{150{
151 if (vma->vm_flags & VM_DENYWRITE)
152 allow_write_access(file);
153 if (vma->vm_flags & VM_SHARED)151 if (vma->vm_flags & VM_SHARED)
154 mapping_unmap_writable(mapping);152 mapping_unmap_writable(mapping);
155 153
@@ -667,8 +665,6 @@ static void __vma_link_file(struct vm_area_struct *vma) · 511 unmodified lines
667 if (file) {665 if (file) {
668 struct address_space *mapping = file->f_mapping;666 struct address_space *mapping = file->f_mapping;
669 667
670 if (vma->vm_flags & VM_DENYWRITE)
671 put_write_access(file_inode(file));
672 if (vma->vm_flags & VM_SHARED)668 if (vma->vm_flags & VM_SHARED)
673 mapping_allow_writable(mapping);669 mapping_allow_writable(mapping);
674 670
@@ -1625,8 +1621,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, · 950 unmodified lines
1625 return PTR_ERR(file);1621 return PTR_ERR(file);
1626 }1622 }
1627 1623
1628 flags &= ~MAP_DENYWRITE;
1629
1630 retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);1624 retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
1631out_fput:1625out_fput:
1632 if (file)1626 if (file)
@@ -1783,22 +1777,12 @@ unsigned long mmap_region(struct file *file, unsigned long addr, · 150 unmodified lines
1783 vma->vm_pgoff = pgoff;1777 vma->vm_pgoff = pgoff;
1784 1778
1785 if (file) {1779 if (file) {
1786 if (vm_flags & VM_DENYWRITE) {
1787 error = deny_write_access(file);
1788 if (error)
1789 goto free_vma;
1790 }
1791 if (vm_flags & VM_SHARED) {1780 if (vm_flags & VM_SHARED) {
1792 error = mapping_map_writable(file->f_mapping);1781 error = mapping_map_writable(file->f_mapping);
1793 if (error)1782 if (error)
1794 goto allow_write_and_free_vma;1783 goto free_vma;
1795 }1784 }
1796 1785
1797 /* ->mmap() can change vma->vm_file, but must guarantee that
1798 * vma_link() below can deny write-access if VM_DENYWRITE is set
1799 * and map writably if VM_SHARED is set. This usually means the
1800 * new file must not have been exposed to user-space, yet.
1801 */
1802 vma->vm_file = get_file(file);1786 vma->vm_file = get_file(file);
1803 error = call_mmap(file, vma);1787 error = call_mmap(file, vma);
1804 if (error)1788 if (error)
@@ -1855,13 +1839,9 @@ unsigned long mmap_region(struct file *file, unsigned long addr, · 50 unmodified lines
1855 1839
1856 vma_link(mm, vma, prev, rb_link, rb_parent);1840 vma_link(mm, vma, prev, rb_link, rb_parent);
1857 /* Once vma denies write, undo our temporary denial count */1841 /* Once vma denies write, undo our temporary denial count */
1858 if (file) {
1859unmap_writable:1842unmap_writable:
1860 if (vm_flags & VM_SHARED)1843 if (file && vm_flags & VM_SHARED)
1861 mapping_unmap_writable(file->f_mapping);1844 mapping_unmap_writable(file->f_mapping);
1862 if (vm_flags & VM_DENYWRITE)
1863 allow_write_access(file);
1864 }
1865 file = vma->vm_file;1845 file = vma->vm_file;
1866out:1846out:
1867 perf_event_mmap(vma);1847 perf_event_mmap(vma);
@@ -1901,9 +1881,6 @@ unmap_and_free_vma: · 33 unmodified lines
1901 charged = 0;1881 charged = 0;
1902 if (vm_flags & VM_SHARED)1882 if (vm_flags & VM_SHARED)
1903 mapping_unmap_writable(file->f_mapping);1883 mapping_unmap_writable(file->f_mapping);
1904allow_write_and_free_vma:
1905 if (vm_flags & VM_DENYWRITE)
1906 allow_write_access(file);
1907free_vma:1884free_vma:
1908 vm_area_free(vma);1885 vm_area_free(vma);
1909unacct_error:1886unacct_error:
mm/nommu.c+0−2
@@ -1293,8 +1293,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, · 1292 unmodified lines
1293 goto out;1293 goto out;
1294 }1294 }
1295 1295
1296 flags &= ~MAP_DENYWRITE;
1297
1298 retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);1296 retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
1299 1297
1300 if (file)1298 if (file)