mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 02:09:42 +00:00
lkdtm: Fix execute_[user]_location()
execute_location() and execute_user_location() intent to copy do_nothing() text and execute it at a new location. However, at the time being it doesn't copy do_nothing() function but do_nothing() function descriptor which still points to the original text. So at the end it still executes do_nothing() at its original location allthough using a copied function descriptor. So, fix that by really copying do_nothing() text and build a new function descriptor by copying do_nothing() function descriptor and updating the target address with the new location. Also fix the displayed addresses by dereferencing do_nothing() function descriptor. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/4055839683d8d643cd99be121f4767c7c611b970.1644928018.git.christophe.leroy@csgroup.eu
This commit is contained in:
parent
b64913394f
commit
72a8643304
1 changed files with 28 additions and 9 deletions
|
@ -44,19 +44,34 @@ static noinline void do_overwritten(void)
|
|||
return;
|
||||
}
|
||||
|
||||
static void *setup_function_descriptor(func_desc_t *fdesc, void *dst)
|
||||
{
|
||||
if (!have_function_descriptors())
|
||||
return dst;
|
||||
|
||||
memcpy(fdesc, do_nothing, sizeof(*fdesc));
|
||||
fdesc->addr = (unsigned long)dst;
|
||||
barrier();
|
||||
|
||||
return fdesc;
|
||||
}
|
||||
|
||||
static noinline void execute_location(void *dst, bool write)
|
||||
{
|
||||
void (*func)(void) = dst;
|
||||
void (*func)(void);
|
||||
func_desc_t fdesc;
|
||||
void *do_nothing_text = dereference_function_descriptor(do_nothing);
|
||||
|
||||
pr_info("attempting ok execution at %px\n", do_nothing);
|
||||
pr_info("attempting ok execution at %px\n", do_nothing_text);
|
||||
do_nothing();
|
||||
|
||||
if (write == CODE_WRITE) {
|
||||
memcpy(dst, do_nothing, EXEC_SIZE);
|
||||
memcpy(dst, do_nothing_text, EXEC_SIZE);
|
||||
flush_icache_range((unsigned long)dst,
|
||||
(unsigned long)dst + EXEC_SIZE);
|
||||
}
|
||||
pr_info("attempting bad execution at %px\n", func);
|
||||
pr_info("attempting bad execution at %px\n", dst);
|
||||
func = setup_function_descriptor(&fdesc, dst);
|
||||
func();
|
||||
pr_err("FAIL: func returned\n");
|
||||
}
|
||||
|
@ -66,16 +81,19 @@ static void execute_user_location(void *dst)
|
|||
int copied;
|
||||
|
||||
/* Intentionally crossing kernel/user memory boundary. */
|
||||
void (*func)(void) = dst;
|
||||
void (*func)(void);
|
||||
func_desc_t fdesc;
|
||||
void *do_nothing_text = dereference_function_descriptor(do_nothing);
|
||||
|
||||
pr_info("attempting ok execution at %px\n", do_nothing);
|
||||
pr_info("attempting ok execution at %px\n", do_nothing_text);
|
||||
do_nothing();
|
||||
|
||||
copied = access_process_vm(current, (unsigned long)dst, do_nothing,
|
||||
copied = access_process_vm(current, (unsigned long)dst, do_nothing_text,
|
||||
EXEC_SIZE, FOLL_WRITE);
|
||||
if (copied < EXEC_SIZE)
|
||||
return;
|
||||
pr_info("attempting bad execution at %px\n", func);
|
||||
pr_info("attempting bad execution at %px\n", dst);
|
||||
func = setup_function_descriptor(&fdesc, dst);
|
||||
func();
|
||||
pr_err("FAIL: func returned\n");
|
||||
}
|
||||
|
@ -153,7 +171,8 @@ void lkdtm_EXEC_VMALLOC(void)
|
|||
|
||||
void lkdtm_EXEC_RODATA(void)
|
||||
{
|
||||
execute_location(lkdtm_rodata_do_nothing, CODE_AS_IS);
|
||||
execute_location(dereference_function_descriptor(lkdtm_rodata_do_nothing),
|
||||
CODE_AS_IS);
|
||||
}
|
||||
|
||||
void lkdtm_EXEC_USERSPACE(void)
|
||||
|
|
Loading…
Reference in a new issue