Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers/misc: sram-exec: have the callers of set_memory_*() check the return value

Right now several architectures allow their set_memory_*() family of
functions to fail, but callers may not be checking the return values.
If set_memory_*() returns with an error, call-site assumptions may be
infact wrong to assume that it would either succeed or not succeed at
all. Ideally, the failure of set_memory_*() should be passed up the call
stack, and callers should examine the failure and deal with it.

Need to fix the callers and add the __must_check attribute. They also
may not provide any level of atomicity, in the sense that the memory
protections may be left incomplete on failure. This issue likely has a
few steps on effects architectures:
1) Have all callers of set_memory_*() helpers check the return value.
2) Add __must_check to all set_memory_*() helpers so that new uses do
not ignore the return value.
3) Add atomicity to the calls so that the memory protections aren't
left in a partial state.

This series is part of step 1. Make sram driver check the return value
of set_memory_*().

Signed-off-by: Tianlin Li <tli@digitalocean.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20191217194528.16461-1-tli@digitalocean.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Tianlin Li and committed by
Greg Kroah-Hartman
c576eddf 2523816d

+17 -4
+17 -4
drivers/misc/sram-exec.c
··· 85 85 unsigned long base; 86 86 int pages; 87 87 void *dst_cpy; 88 + int ret; 88 89 89 90 mutex_lock(&exec_pool_list_mutex); 90 91 list_for_each_entry(p, &exec_pool_list, list) { ··· 105 104 106 105 mutex_lock(&part->lock); 107 106 108 - set_memory_nx((unsigned long)base, pages); 109 - set_memory_rw((unsigned long)base, pages); 107 + ret = set_memory_nx((unsigned long)base, pages); 108 + if (ret) 109 + goto error_out; 110 + ret = set_memory_rw((unsigned long)base, pages); 111 + if (ret) 112 + goto error_out; 110 113 111 114 dst_cpy = fncpy(dst, src, size); 112 115 113 - set_memory_ro((unsigned long)base, pages); 114 - set_memory_x((unsigned long)base, pages); 116 + ret = set_memory_ro((unsigned long)base, pages); 117 + if (ret) 118 + goto error_out; 119 + ret = set_memory_x((unsigned long)base, pages); 120 + if (ret) 121 + goto error_out; 115 122 116 123 mutex_unlock(&part->lock); 117 124 118 125 return dst_cpy; 126 + 127 + error_out: 128 + mutex_unlock(&part->lock); 129 + return NULL; 119 130 } 120 131 EXPORT_SYMBOL_GPL(sram_exec_copy);