8000 Merge tag 'denywrite-for-5.15' of git://github.com/davidhildenbrand/l… · josefbacik/linux@49624ef · GitHub
[go: up one dir, main page]

Skip to content

Commit 49624ef

Browse files
committed
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()
2 parents f746406 + 592ca09 commit 49624ef

File tree

16 files changed

+119
-103
lines changed

16 files changed

+119
-103
lines changed

arch/x86/ia32/ia32_aout.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,15 @@ static int load_aout_binary(struct linux_binprm *bprm)
202202

203203
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
204204
PROT_READ | PROT_EXEC,
205-
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
206-
MAP_32BIT,
205+
MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
207206
fd_offset);
208207

209208
if (error != N_TXTADDR(ex))
210209
return error;
211210

212211
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
213212
PROT_READ | PROT_WRITE | PROT_EXEC,
214-
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
215-
MAP_32BIT,
213+
MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
216214
fd_offset + ex.a_text);
217215
if (error != N_DATADDR(ex))
218216
return error;
@@ -293,7 +291,7 @@ static int load_aout_library(struct file *file)
293291
/* Now use mmap to map the library into memory. */
294292
error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
295293
PROT_READ | PROT_WRITE | PROT_EXEC,
296-
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
294+
MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
297295
N_TXTOFF(ex));
298296
retval = error;
299297
if (error != start_addr)

fs/binfmt_aout.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,15 @@ static int load_aout_binary(struct linux_binprm * bprm)
221221
}
222222

223223
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
224-
PROT_READ | PROT_EXEC,
225-
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
224+
PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
226225
fd_offset);
227226

228227
if (error != N_TXTADDR(ex))
229228
return error;
230229

231230
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
232231
PROT_READ | PROT_WRITE | PROT_EXEC,
233-
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
232+
MAP_FIXED | MAP_PRIVATE,
234233
fd_offset + ex.a_text);
235234
if (error != N_DATADDR(ex))
236235
return error;
309308
/* Now use mmap to map the library into memory. */
310309
error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
311310
PROT_READ | PROT_WRITE | PROT_EXEC,
312-
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
311+
MAP_FIXED | MAP_PRIVATE;
313312
N_TXTOFF(ex));
314313
retval = error;
315314
if (error != start_addr)

fs/binfmt_elf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
622622
eppnt = interp_elf_phdata;
623623
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
624624
if (eppnt->p_type == PT_LOAD) {
625-
int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
625+
int elf_type = MAP_PRIVATE;
626626
int elf_prot = make_prot(eppnt->p_flags, arch_state,
627627
true, true);
628628
unsigned long vaddr = 0;
@@ -1070,7 +1070,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
10701070
elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,
10711071
!!interpreter, false);
10721072

1073-
elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
1073+
elf_flags = MAP_PRIVATE;
10741074

10751075
vaddr = elf_ppnt->p_vaddr;
10761076
/*
@@ -1384,7 +1384,7 @@ static int load_elf_library(struct file *file)
13841384
(eppnt->p_filesz +
13851385
ELF_PAGEOFFSET(eppnt->p_vaddr)),
13861386
PROT_READ | PROT_WRITE | PROT_EXEC,
1387-
MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_DENYWRITE,
1387+
MAP_FIXED_NOREPLACE | MAP_PRIVATE,
13881388
(eppnt->p_offset -
13891389
ELF_PAGEOFFSET(eppnt->p_vaddr)));
13901390
if (error != ELF_PAGESTART(eppnt->p_vaddr))

fs/binfmt_elf_fdpic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
10411041
if (phdr->p_flags & PF_W) prot |= PROT_WRITE;
10421042
if (phdr->p_flags & PF_X) prot |= PROT_EXEC;
10431043

1044-
flags = MAP_PRIVATE | MAP_DENYWRITE;
1044+
flags = MAP_PRIVATE;
10451045
maddr = 0;
10461046

10471047
switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {

fs/exec.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,9 @@ int begin_new_exec(struct linux_binprm * bprm)
12721272
* not visibile until then. This also enables the update
12731273
* to be lockless.
12741274
*/
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;
12761278

12771279
/* If the binary is not readable then enforce mm->dumpable=0 */
12781280
would_dump(bprm, bprm->file);

fs/proc/task_mmu.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,6 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
619619
[ilog2(VM_MAYSHARE)] = "ms",
620620
[ilog2(VM_GROWSDOWN)] = "gd",
621621
[ilog2(VM_PFNMAP)] = "pf",
622-
[ilog2(VM_DENYWRITE)] = "dw",
623622
[ilog2(VM_LOCKED)] = "lo",
624623
[ilog2(VM_IO)] = "io",
625624
[ilog2(VM_SEQ_READ)] = "sr",

include/linux/fs.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3023,15 +3023,20 @@ static inline void file_end_write(struct file *file)
30233023
}
30243024

30253025
/*
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+
*
30263031
* get_write_access() gets write permission for a file.
30273032
* put_write_access() releases this write permission.
3028-
* This is used for regular files.
3029-
* We cannot support write (and maybe mmap read-write shared) accesses and
3030-
* MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode
3031-
* can have the following values:
3032-
* 0: no writers, no VM_DENYWRITE mappings
3033-
* < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
3034-
* > 0: (i_writecount) users are writing to the file.
3033+
* deny_write_access() denies write access to a file.
3034+
* allow_write_access() re-enables write access to a file.
3035+
*
3036+
* The i_writecount field of an inode can have the following values:
3037+
* 0: no write access, no denied write access
3038+
* < 0: (-i_writecount) users that denied write access to the file.
3039+
* > 0: (i_writecount) users that have write access to the file.
30353040
*
30363041
* Normally we operate on that counter with atomic_{inc,dec} and it's safe
30373042
* except for the cases where we don't hold i_writecount yet. Then we need to

include/linux/mm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ extern unsigned int kobjsize(const void *objp);
281281
#define VM_GROWSDOWN 0x00000100 /* general info on the segment */
282282
#define VM_UFFD_MISSING 0x00000200 /* missing pages tracking */
283283
#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
284-
#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */
285284
#define VM_UFFD_WP 0x00001000 /* wrprotect pages tracking */
286285

287286
#define VM_LOCKED 0x00002000
@@ -2573,7 +2572,8 @@ static inline int check_data_rlimit(unsigned long rlim,
25732572
extern int mm_take_all_locks(struct mm_struct *mm);
25742573
extern void mm_drop_all_locks(struct mm_struct *mm);
25752574

2576-
extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
2575+
extern int set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
2576+
extern int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
25772577
extern struct file *get_mm_exe_file(struct mm_struct *mm);
25782578
extern struct file *get_task_exe_file(struct task_struct *task);
25792579

include/linux/mman.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
* The historical set of flags that all mmap implementations implicitly
3333
* support when a ->mmap_validate() op is not provided in file_operations.
3434
*
35-
* MAP_EXECUTABLE is completely ignored throughout the kernel.
35+
* MAP_EXECUTABLE and MAP_DENYWRITE are completely ignored throughout the
36+
* kernel.
3637
*/
3738
#define LEGACY_MAP_MASK (MAP_SHARED \
3839
| MAP_PRIVATE \
@@ -153,7 +154,6 @@ static inline unsigned long
153154
calc_vm_flag_bits(unsigned long flags)
154155
{
155156
return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
156-
_calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
157157
_calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) |
158158
_calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) |
159159
arch_calc_vm_flag_bits(flags);

include/trace/events/mmflags.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ IF_HAVE_PG_SKIP_KASAN_POISON(PG_skip_kasan_poison, "skip_kasan_poison")
165165
{VM_UFFD_MISSING, "uffd_missing" }, \
166166
IF_HAVE_UFFD_MINOR(VM_UFFD_MINOR, "uffd_minor" ) \
167167
{VM_PFNMAP, "pfnmap" }, \
168-
{VM_DENYWRITE, "denywrite" }, \
169168
{VM_UFFD_WP, "uffd_wp" }, \
170169
{VM_LOCKED, "locked" }, \
171170
{VM_IO, "io" }, \

0 commit comments

Comments
 (0)
0