Skip to content

Commit

Permalink
lkdtm: Do not use flush_icache_range() on user addresses
Browse files Browse the repository at this point in the history
The flush_icache_range() API is meant to be used on kernel addresses
only as it may not have the infrastructure (exception entries) to handle
user memory faults.

The lkdtm execute_user_location() function tests the kernel execution of
user space addresses by mmap'ing an anonymous page, copying some code
together with cache maintenance and attempting to run it. However, the
cache maintenance step may fail because of the incorrect API usage
described above. The patch changes lkdtm to use access_process_vm() for
copying the code into user space which would take care of the necessary
cache maintenance.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
[kees: export access_process_vm() for module use]
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
ctmarinas authored and gregkh committed Nov 10, 2016
1 parent 052662c commit fcd3585
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 2 deletions.
7 changes: 5 additions & 2 deletions drivers/misc/lkdtm_perms.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,18 @@ static noinline void execute_location(void *dst, bool write)

static void execute_user_location(void *dst)
{
int copied;

/* Intentionally crossing kernel/user memory boundary. */
void (*func)(void) = dst;

pr_info("attempting ok execution at %p\n", do_nothing);
do_nothing();

if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE))
copied = access_process_vm(current, (unsigned long)dst, do_nothing,
EXEC_SIZE, FOLL_WRITE);
if (copied < EXEC_SIZE)
return;
flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE);
pr_info("attempting bad execution at %p\n", func);
func();
}
Expand Down
1 change: 1 addition & 0 deletions mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -3966,6 +3966,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr,

return ret;
}
EXPORT_SYMBOL_GPL(access_process_vm);

/*
* Print the name of a VMA.
Expand Down
1 change: 1 addition & 0 deletions mm/nommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1878,6 +1878,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
mmput(mm);
return len;
}
EXPORT_SYMBOL_GPL(access_process_vm);

/**
* nommu_shrink_inode_mappings - Shrink the shared mappings on an inode
Expand Down

0 comments on commit fcd3585

Please sign in to comment.