Skip to content

Commit b5287c5

Browse files
committed
Merge tag 'vfs-6.13.exec.deny_write_access.revert' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull deny_write_access revert from Christian Brauner: "It turns out that the mold linker relies on the deny_write_access() mechanism for executables. The mold linker tries to open a file for writing and if ETXTBSY is returned mold falls back to creating a new file" * tag 'vfs-6.13.exec.deny_write_access.revert' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: Revert "fs: don't block i_writecount during exec"
2 parents aaf20f8 + 3b83203 commit b5287c5

File tree

5 files changed

+49
-14
lines changed

5 files changed

+49
-14
lines changed

fs/binfmt_elf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
12571257
}
12581258
reloc_func_desc = interp_load_addr;
12591259

1260+
allow_write_access(interpreter);
12601261
fput(interpreter);
12611262

12621263
kfree(interp_elf_ex);
@@ -1353,6 +1354,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
13531354
kfree(interp_elf_ex);
13541355
kfree(interp_elf_phdata);
13551356
out_free_file:
1357+
allow_write_access(interpreter);
13561358
if (interpreter)
13571359
fput(interpreter);
13581360
out_free_ph:

fs/binfmt_elf_fdpic.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
394394
goto error;
395395
}
396396

397+
allow_write_access(interpreter);
397398
fput(interpreter);
398399
interpreter = NULL;
399400
}
@@ -465,8 +466,10 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
465466
retval = 0;
466467

467468
error:
468-
if (interpreter)
469+
if (interpreter) {
470+
allow_write_access(interpreter);
469471
fput(interpreter);
472+
}
470473
kfree(interpreter_name);
471474
kfree(exec_params.phdrs);
472475
kfree(exec_params.loadmap);

fs/binfmt_misc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,13 @@ static int load_misc_binary(struct linux_binprm *bprm)
247247
if (retval < 0)
248248
goto ret;
249249

250-
if (fmt->flags & MISC_FMT_OPEN_FILE)
250+
if (fmt->flags & MISC_FMT_OPEN_FILE) {
251251
interp_file = file_clone_open(fmt->interp_file);
252-
else
252+
if (!IS_ERR(interp_file))
253+
deny_write_access(interp_file);
254+
} else {
253255
interp_file = open_exec(fmt->interpreter);
256+
}
254257
retval = PTR_ERR(interp_file);
255258
if (IS_ERR(interp_file))
256259
goto ret;

fs/exec.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,8 @@ EXPORT_SYMBOL(transfer_args_to_stack);
883883
*/
884884
static struct file *do_open_execat(int fd, struct filename *name, int flags)
885885
{
886-
struct file *file;
886+
int err;
887+
struct file *file __free(fput) = NULL;
887888
struct open_flags open_exec_flags = {
888889
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
889890
.acc_mode = MAY_EXEC,
@@ -908,12 +909,14 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
908909
* an invariant that all non-regular files error out before we get here.
909910
*/
910911
if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
911-
path_noexec(&file->f_path)) {
912-
fput(file);
912+
path_noexec(&file->f_path))
913913
return ERR_PTR(-EACCES);
914-
}
915914

916-
return file;
915+
err = deny_write_access(file);
916+
if (err)
917+
return ERR_PTR(err);
918+
919+
return no_free_ptr(file);
917920
}
918921

919922
/**
@@ -923,7 +926,8 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
923926
*
924927
* Returns ERR_PTR on failure or allocated struct file on success.
925928
*
926-
* As this is a wrapper for the internal do_open_execat(). Also see
929+
* As this is a wrapper for the internal do_open_execat(), callers
930+
* must call allow_write_access() before fput() on release. Also see
927931
* do_close_execat().
928932
*/
929933
struct file *open_exec(const char *name)
@@ -1465,8 +1469,10 @@ static int prepare_bprm_creds(struct linux_binprm *bprm)
14651469
/* Matches do_open_execat() */
14661470
static void do_close_execat(struct file *file)
14671471
{
1468-
if (file)
1469-
fput(file);
1472+
if (!file)
1473+
return;
1474+
allow_write_access(file);
1475+
fput(file);
14701476
}
14711477

14721478
static void free_bprm(struct linux_binprm *bprm)
@@ -1791,6 +1797,7 @@ static int exec_binprm(struct linux_binprm *bprm)
17911797
bprm->file = bprm->interpreter;
17921798
bprm->interpreter = NULL;
17931799

1800+
allow_write_access(exec);
17941801
if (unlikely(bprm->have_execfd)) {
17951802
if (bprm->executable) {
17961803
fput(exec);

kernel/fork.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,12 @@ static void dup_mm_exe_file(struct mm_struct *mm, struct mm_struct *oldmm)
621621

622622
exe_file = get_mm_exe_file(oldmm);
623623
RCU_INIT_POINTER(mm->exe_file, exe_file);
624+
/*
625+
* We depend on the oldmm having properly denied write access to the
626+
* exe_file already.
627+
*/
628+
if (exe_file && deny_write_access(exe_file))
629+
pr_warn_once("deny_write_access() failed in %s\n", __func__);
624630
}
625631

626632
#ifdef CONFIG_MMU
@@ -1413,11 +1419,20 @@ int set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
14131419
*/
14141420
old_exe_file = rcu_dereference_raw(mm->exe_file);
14151421

1416-
if (new_exe_file)
1422+
if (new_exe_file) {
1423+
/*
1424+
* We expect the caller (i.e., sys_execve) to already denied
1425+
* write access, so this is unlikely to fail.
1426+
*/
1427+
if (unlikely(deny_write_access(new_exe_file)))
1428+
return -EACCES;
14171429
get_file(new_exe_file);
1430+
}
14181431
rcu_assign_pointer(mm->exe_file, new_exe_file);
1419-
if (old_exe_file)
1432+
if (old_exe_file) {
1433+
allow_write_access(old_exe_file);
14201434
fput(old_exe_file);
1435+
}
14211436
return 0;
14221437
}
14231438

@@ -1456,6 +1471,9 @@ int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
14561471
return ret;
14571472
}
14581473

1474+
ret = deny_write_access(new_exe_file);
1475+
if (ret)
1476+
return -EACCES;
14591477
get_file(new_exe_file);
14601478

14611479
/* set the new file */
@@ -1464,8 +1482,10 @@ int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
14641482
rcu_assign_pointer(mm->exe_file, new_exe_file);
14651483
mmap_write_unlock(mm);
14661484

1467-
if (old_exe_file)
1485+
if (old_exe_file) {
1486+
allow_write_access(old_exe_file);
14681487
fput(old_exe_file);
1488+
}
14691489
return 0;
14701490
}
14711491

0 commit comments

Comments
 (0)