Commit bdd8f624 authored by Kees Cook's avatar Kees Cook

exec: Add do_close_execat() helper

Consolidate the calls to allow_write_access()/fput() into a single
place, since we repeat this code pattern. Add comments around the
callers for the details on it.

Link: https://lore.kernel.org/r/202209161637.9EDAF6B18@keescookSigned-off-by: default avatarKees Cook <keescook@chromium.org>
parent 8788a17c
...@@ -904,6 +904,10 @@ EXPORT_SYMBOL(transfer_args_to_stack); ...@@ -904,6 +904,10 @@ EXPORT_SYMBOL(transfer_args_to_stack);
#endif /* CONFIG_MMU */ #endif /* CONFIG_MMU */
/*
* On success, caller must call do_close_execat() on the returned
* struct file to close it.
*/
static struct file *do_open_execat(int fd, struct filename *name, int flags) static struct file *do_open_execat(int fd, struct filename *name, int flags)
{ {
struct file *file; struct file *file;
...@@ -948,6 +952,17 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags) ...@@ -948,6 +952,17 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
return ERR_PTR(err); return ERR_PTR(err);
} }
/**
* open_exec - Open a path name for execution
*
* @name: path name to open with the intent of executing it.
*
* Returns ERR_PTR on failure or allocated struct file on success.
*
* As this is a wrapper for the internal do_open_execat(), callers
* must call allow_write_access() before fput() on release. Also see
* do_close_execat().
*/
struct file *open_exec(const char *name) struct file *open_exec(const char *name)
{ {
struct filename *filename = getname_kernel(name); struct filename *filename = getname_kernel(name);
...@@ -1484,6 +1499,15 @@ static int prepare_bprm_creds(struct linux_binprm *bprm) ...@@ -1484,6 +1499,15 @@ static int prepare_bprm_creds(struct linux_binprm *bprm)
return -ENOMEM; return -ENOMEM;
} }
/* Matches do_open_execat() */
static void do_close_execat(struct file *file)
{
if (!file)
return;
allow_write_access(file);
fput(file);
}
static void free_bprm(struct linux_binprm *bprm) static void free_bprm(struct linux_binprm *bprm)
{ {
if (bprm->mm) { if (bprm->mm) {
...@@ -1495,10 +1519,7 @@ static void free_bprm(struct linux_binprm *bprm) ...@@ -1495,10 +1519,7 @@ static void free_bprm(struct linux_binprm *bprm)
mutex_unlock(&current->signal->cred_guard_mutex); mutex_unlock(&current->signal->cred_guard_mutex);
abort_creds(bprm->cred); abort_creds(bprm->cred);
} }
if (bprm->file) { do_close_execat(bprm->file);
allow_write_access(bprm->file);
fput(bprm->file);
}
if (bprm->executable) if (bprm->executable)
fput(bprm->executable); fput(bprm->executable);
/* If a binfmt changed the interp, free it. */ /* If a binfmt changed the interp, free it. */
...@@ -1520,8 +1541,7 @@ static struct linux_binprm *alloc_bprm(int fd, struct filename *filename, int fl ...@@ -1520,8 +1541,7 @@ static struct linux_binprm *alloc_bprm(int fd, struct filename *filename, int fl
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
if (!bprm) { if (!bprm) {
allow_write_access(file); do_close_execat(file);
fput(file);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment