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

lkdtm: Make lkdtm_do_action() return to avoid tail call optimization

The comments for lkdtm_do_action() explicitly call out that it
shouldn't be inlined because we want it to show up in stack
crawls. However, at least with some compilers / options it's still
vanishing due to tail call optimization. Let's add a return value to
the function to make it harder for the compiler to do tail call
optimization here.

Now that we have a return value, we can actually use it in the
callers, which is a minor improvement in the code.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/r/20240122164935.1.I345e485f36babad76370c59659a706723750d950@changeid
Signed-off-by: Kees Cook <keescook@chromium.org>

authored by

Douglas Anderson and committed by
Kees Cook
84022cff 41bccc98

+14 -8
+14 -8
drivers/misc/lkdtm/core.c
··· 153 153 /* 154 154 * This is forced noinline just so it distinctly shows up in the stackdump 155 155 * which makes validation of expected lkdtm crashes easier. 156 + * 157 + * NOTE: having a valid return value helps prevent the compiler from doing 158 + * tail call optimizations and taking this out of the stack trace. 156 159 */ 157 - static noinline void lkdtm_do_action(const struct crashtype *crashtype) 160 + static noinline int lkdtm_do_action(const struct crashtype *crashtype) 158 161 { 159 162 if (WARN_ON(!crashtype || !crashtype->func)) 160 - return; 163 + return -EINVAL; 161 164 crashtype->func(); 165 + 166 + return 0; 162 167 } 163 168 164 169 static int lkdtm_register_cpoint(struct crashpoint *crashpoint, ··· 172 167 int ret; 173 168 174 169 /* If this doesn't have a symbol, just call immediately. */ 175 - if (!crashpoint->kprobe.symbol_name) { 176 - lkdtm_do_action(crashtype); 177 - return 0; 178 - } 170 + if (!crashpoint->kprobe.symbol_name) 171 + return lkdtm_do_action(crashtype); 179 172 180 173 if (lkdtm_kprobe != NULL) 181 174 unregister_kprobe(lkdtm_kprobe); ··· 219 216 spin_unlock_irqrestore(&crash_count_lock, flags); 220 217 221 218 if (do_it) 222 - lkdtm_do_action(lkdtm_crashtype); 219 + return lkdtm_do_action(lkdtm_crashtype); 223 220 224 221 return 0; 225 222 } ··· 306 303 { 307 304 const struct crashtype *crashtype; 308 305 char *buf; 306 + int err; 309 307 310 308 if (count >= PAGE_SIZE) 311 309 return -EINVAL; ··· 330 326 return -EINVAL; 331 327 332 328 pr_info("Performing direct entry %s\n", crashtype->name); 333 - lkdtm_do_action(crashtype); 329 + err = lkdtm_do_action(crashtype); 334 330 *off += count; 335 331 332 + if (err) 333 + return err; 336 334 return count; 337 335 } 338 336