mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
mm/vma: eliminate mmap_action->error_hook, introduce error_override
Rather than providing a hook, simplify things by providing the ability to override mmap action errors. This allows us to more carefully validate the value provided and thus ensure only a valid error code is specified, and simplifies the interface. This way, we eliminate all hooks but mmap_prepare and allow only mmap actions to be specified (which core mm controls). This significantly improves robustness and eliminates any unnecessary code duplication in driver mmap hooks. We also update the /dev/mem logic (the only user) to use mmap_action->error_override instead. Link: https://lore.kernel.org/55d13f7d016b827c459946d46a56105635be111c.1780397980.git.ljs@kernel.org Signed-off-by: Lorenzo Stoakes <ljs@kernel.org> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jann Horn <jannh@google.com> Cc: Liam R. Howlett <liam@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Pedro Falcato <pfalcato@suse.de> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
8876dc0780
commit
4f5b875926
+1
-7
@@ -322,11 +322,6 @@ static const struct vm_operations_struct mmap_mem_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int mmap_filter_error(int err)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static int mmap_mem_prepare(struct vm_area_desc *desc)
|
||||
{
|
||||
struct file *file = desc->file;
|
||||
@@ -362,8 +357,7 @@ static int mmap_mem_prepare(struct vm_area_desc *desc)
|
||||
|
||||
/* Remap-pfn-range will mark the range with the I/O flag. */
|
||||
mmap_action_remap_full(desc, desc->pgoff);
|
||||
/* We filter remap errors to -EAGAIN. */
|
||||
desc->action.error_hook = mmap_filter_error;
|
||||
desc->action.error_override = -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -844,13 +844,10 @@ struct mmap_action {
|
||||
enum mmap_action_type type;
|
||||
|
||||
/*
|
||||
* If specified, this hook is invoked when an error occurred when
|
||||
* attempting the selected action.
|
||||
*
|
||||
* The hook can return an error code in order to filter the error, but
|
||||
* it is not valid to clear the error here.
|
||||
* If non-zero, replace errors that arise from mmap actions with this
|
||||
* value instead. Only valid error codes may be specified.
|
||||
*/
|
||||
int (*error_hook)(int err);
|
||||
int error_override;
|
||||
|
||||
/*
|
||||
* This should be set in rare instances where the operation required
|
||||
|
||||
@@ -1414,16 +1414,22 @@ static int mmap_action_finish(struct vm_area_struct *vma,
|
||||
*/
|
||||
len = vma_pages(vma) << PAGE_SHIFT;
|
||||
do_munmap(current->mm, vma->vm_start, len, NULL);
|
||||
if (action->error_hook) {
|
||||
/* We may want to filter the error. */
|
||||
err = action->error_hook(err);
|
||||
/* The caller should not clear the error. */
|
||||
VM_WARN_ON_ONCE(!err);
|
||||
}
|
||||
return err;
|
||||
|
||||
return action->error_override ?: err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
static int check_mmap_action(struct mmap_action *action)
|
||||
{
|
||||
const unsigned long override = action->error_override;
|
||||
|
||||
if (WARN_ON_ONCE(override && !IS_ERR_VALUE(override)))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmap_action_prepare - Perform preparatory setup for an VMA descriptor
|
||||
* action which need to be performed.
|
||||
@@ -1433,7 +1439,14 @@ static int mmap_action_finish(struct vm_area_struct *vma,
|
||||
*/
|
||||
int mmap_action_prepare(struct vm_area_desc *desc)
|
||||
{
|
||||
switch (desc->action.type) {
|
||||
struct mmap_action *action = &desc->action;
|
||||
int err;
|
||||
|
||||
err = check_mmap_action(action);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (action->type) {
|
||||
case MMAP_NOTHING:
|
||||
return 0;
|
||||
case MMAP_REMAP_PFN:
|
||||
|
||||
@@ -483,13 +483,10 @@ struct mmap_action {
|
||||
enum mmap_action_type type;
|
||||
|
||||
/*
|
||||
* If specified, this hook is invoked when an error occurred when
|
||||
* attempting the selection action.
|
||||
*
|
||||
* The hook can return an error code in order to filter the error, but
|
||||
* it is not valid to clear the error here.
|
||||
* If non-zero, replace errors that arise from mmap actions with this
|
||||
* value instead. Only valid error codes may be specified.
|
||||
*/
|
||||
int (*error_hook)(int err);
|
||||
int error_override;
|
||||
|
||||
/*
|
||||
* This should be set in rare instances where the operation required
|
||||
|
||||
Reference in New Issue
Block a user