]> git.karo-electronics.de Git - linux-beck.git/commitdiff
lkdtm: Do not use flush_icache_range() on user addresses
authorCatalin Marinas <catalin.marinas@arm.com>
Tue, 1 Nov 2016 21:43:25 +0000 (14:43 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Nov 2016 14:34:56 +0000 (15:34 +0100)
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>
drivers/misc/lkdtm_perms.c
mm/memory.c
mm/nommu.c

index 45f1c0f966123c7b3870e4f42d724270f4f75e5f..c7635a79341fb3e52d527135db2a1c958cc7e087 100644 (file)
@@ -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();
 }
index e18c57bdc75c4c96e3ef79546afe11fab5a3c07a..485f12d8ad5c84abdf93fae26e4c92d175b4a13e 100644 (file)
@@ -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.
index 8b8faaf2a9e95cfc607ff1a5a37c83eadfda59fe..9720e0bab0298fcec3855d7300934eb9e6223b4c 100644 (file)
@@ -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