summaryrefslogtreecommitdiffstats
path: root/tools/objtool/check.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2019-02-25 06:50:09 -0500
committerIngo Molnar <mingo@kernel.org>2019-04-03 05:02:24 -0400
commitea24213d8088f9da73e1b6aadf7abd2435b70397 (patch)
treefba1e181531f8f20ff04ed6a57e10b8bd2805343 /tools/objtool/check.c
parent54262aa2830151f89699fa8a6c5aa05f0992e672 (diff)
objtool: Add UACCESS validation
It is important that UACCESS regions are as small as possible; furthermore the UACCESS state is not scheduled, so doing anything that might directly call into the scheduler will cause random code to be ran with UACCESS enabled. Teach objtool too track UACCESS state and warn about any CALL made while UACCESS is enabled. This very much includes the __fentry__() and __preempt_schedule() calls. Note that exceptions _do_ save/restore the UACCESS state, and therefore they can drive preemption. This also means that all exception handlers must have an otherwise redundant UACCESS disable instruction; therefore ignore this warning for !STT_FUNC code (exception handlers are not normal functions). Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/objtool/check.c')
-rw-r--r--tools/objtool/check.c197
1 files changed, 183 insertions, 14 deletions
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 8118361295dd..965e954e07f4 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -443,6 +443,82 @@ static void add_ignores(struct objtool_file *file)
443} 443}
444 444
445/* 445/*
446 * This is a whitelist of functions that is allowed to be called with AC set.
447 * The list is meant to be minimal and only contains compiler instrumentation
448 * ABI and a few functions used to implement *_{to,from}_user() functions.
449 *
450 * These functions must not directly change AC, but may PUSHF/POPF.
451 */
452static const char *uaccess_safe_builtin[] = {
453 /* KASAN */
454 "kasan_report",
455 "check_memory_region",
456 /* KASAN out-of-line */
457 "__asan_loadN_noabort",
458 "__asan_load1_noabort",
459 "__asan_load2_noabort",
460 "__asan_load4_noabort",
461 "__asan_load8_noabort",
462 "__asan_load16_noabort",
463 "__asan_storeN_noabort",
464 "__asan_store1_noabort",
465 "__asan_store2_noabort",
466 "__asan_store4_noabort",
467 "__asan_store8_noabort",
468 "__asan_store16_noabort",
469 /* KASAN in-line */
470 "__asan_report_load_n_noabort",
471 "__asan_report_load1_noabort",
472 "__asan_report_load2_noabort",
473 "__asan_report_load4_noabort",
474 "__asan_report_load8_noabort",
475 "__asan_report_load16_noabort",
476 "__asan_report_store_n_noabort",
477 "__asan_report_store1_noabort",
478 "__asan_report_store2_noabort",
479 "__asan_report_store4_noabort",
480 "__asan_report_store8_noabort",
481 "__asan_report_store16_noabort",
482 /* KCOV */
483 "write_comp_data",
484 "__sanitizer_cov_trace_pc",
485 "__sanitizer_cov_trace_const_cmp1",
486 "__sanitizer_cov_trace_const_cmp2",
487 "__sanitizer_cov_trace_const_cmp4",
488 "__sanitizer_cov_trace_const_cmp8",
489 "__sanitizer_cov_trace_cmp1",
490 "__sanitizer_cov_trace_cmp2",
491 "__sanitizer_cov_trace_cmp4",
492 "__sanitizer_cov_trace_cmp8",
493 /* UBSAN */
494 "ubsan_type_mismatch_common",
495 "__ubsan_handle_type_mismatch",
496 "__ubsan_handle_type_mismatch_v1",
497 /* misc */
498 "csum_partial_copy_generic",
499 "__memcpy_mcsafe",
500 "ftrace_likely_update", /* CONFIG_TRACE_BRANCH_PROFILING */
501 NULL
502};
503
504static void add_uaccess_safe(struct objtool_file *file)
505{
506 struct symbol *func;
507 const char **name;
508
509 if (!uaccess)
510 return;
511
512 for (name = uaccess_safe_builtin; *name; name++) {
513 func = find_symbol_by_name(file->elf, *name);
514 if (!func)
515 continue;
516
517 func->alias->uaccess_safe = true;
518 }
519}
520
521/*
446 * FIXME: For now, just ignore any alternatives which add retpolines. This is 522 * FIXME: For now, just ignore any alternatives which add retpolines. This is
447 * a temporary hack, as it doesn't allow ORC to unwind from inside a retpoline. 523 * a temporary hack, as it doesn't allow ORC to unwind from inside a retpoline.
448 * But it at least allows objtool to understand the control flow *around* the 524 * But it at least allows objtool to understand the control flow *around* the
@@ -818,6 +894,7 @@ static int add_special_section_alts(struct objtool_file *file)
818 894
819 alt->insn = new_insn; 895 alt->insn = new_insn;
820 alt->skip_orig = special_alt->skip_orig; 896 alt->skip_orig = special_alt->skip_orig;
897 orig_insn->ignore_alts |= special_alt->skip_alt;
821 list_add_tail(&alt->list, &orig_insn->alts); 898 list_add_tail(&alt->list, &orig_insn->alts);
822 899
823 list_del(&special_alt->list); 900 list_del(&special_alt->list);
@@ -1239,6 +1316,7 @@ static int decode_sections(struct objtool_file *file)
1239 return ret; 1316 return ret;
1240 1317
1241 add_ignores(file); 1318 add_ignores(file);
1319 add_uaccess_safe(file);
1242 1320
1243 ret = add_ignore_alternatives(file); 1321 ret = add_ignore_alternatives(file);
1244 if (ret) 1322 if (ret)
@@ -1320,11 +1398,11 @@ static int update_insn_state_regs(struct instruction *insn, struct insn_state *s
1320 return 0; 1398 return 0;
1321 1399
1322 /* push */ 1400 /* push */
1323 if (op->dest.type == OP_DEST_PUSH) 1401 if (op->dest.type == OP_DEST_PUSH || op->dest.type == OP_DEST_PUSHF)
1324 cfa->offset += 8; 1402 cfa->offset += 8;
1325 1403
1326 /* pop */ 1404 /* pop */
1327 if (op->src.type == OP_SRC_POP) 1405 if (op->src.type == OP_SRC_POP || op->src.type == OP_SRC_POPF)
1328 cfa->offset -= 8; 1406 cfa->offset -= 8;
1329 1407
1330 /* add immediate to sp */ 1408 /* add immediate to sp */
@@ -1581,6 +1659,7 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1581 break; 1659 break;
1582 1660
1583 case OP_SRC_POP: 1661 case OP_SRC_POP:
1662 case OP_SRC_POPF:
1584 if (!state->drap && op->dest.type == OP_DEST_REG && 1663 if (!state->drap && op->dest.type == OP_DEST_REG &&
1585 op->dest.reg == cfa->base) { 1664 op->dest.reg == cfa->base) {
1586 1665
@@ -1645,6 +1724,7 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1645 break; 1724 break;
1646 1725
1647 case OP_DEST_PUSH: 1726 case OP_DEST_PUSH:
1727 case OP_DEST_PUSHF:
1648 state->stack_size += 8; 1728 state->stack_size += 8;
1649 if (cfa->base == CFI_SP) 1729 if (cfa->base == CFI_SP)
1650 cfa->offset += 8; 1730 cfa->offset += 8;
@@ -1735,7 +1815,7 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1735 break; 1815 break;
1736 1816
1737 case OP_DEST_MEM: 1817 case OP_DEST_MEM:
1738 if (op->src.type != OP_SRC_POP) { 1818 if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
1739 WARN_FUNC("unknown stack-related memory operation", 1819 WARN_FUNC("unknown stack-related memory operation",
1740 insn->sec, insn->offset); 1820 insn->sec, insn->offset);
1741 return -1; 1821 return -1;
@@ -1799,6 +1879,33 @@ static bool insn_state_match(struct instruction *insn, struct insn_state *state)
1799 return false; 1879 return false;
1800} 1880}
1801 1881
1882static inline bool func_uaccess_safe(struct symbol *func)
1883{
1884 if (func)
1885 return func->alias->uaccess_safe;
1886
1887 return false;
1888}
1889
1890static inline const char *insn_dest_name(struct instruction *insn)
1891{
1892 if (insn->call_dest)
1893 return insn->call_dest->name;
1894
1895 return "{dynamic}";
1896}
1897
1898static int validate_call(struct instruction *insn, struct insn_state *state)
1899{
1900 if (state->uaccess && !func_uaccess_safe(insn->call_dest)) {
1901 WARN_FUNC("call to %s() with UACCESS enabled",
1902 insn->sec, insn->offset, insn_dest_name(insn));
1903 return 1;
1904 }
1905
1906 return 0;
1907}
1908
1802static int validate_sibling_call(struct instruction *insn, struct insn_state *state) 1909static int validate_sibling_call(struct instruction *insn, struct insn_state *state)
1803{ 1910{
1804 if (has_modified_stack_frame(state)) { 1911 if (has_modified_stack_frame(state)) {
@@ -1807,7 +1914,7 @@ static int validate_sibling_call(struct instruction *insn, struct insn_state *st
1807 return 1; 1914 return 1;
1808 } 1915 }
1809 1916
1810 return 0; 1917 return validate_call(insn, state);
1811} 1918}
1812 1919
1813/* 1920/*
@@ -1855,7 +1962,9 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1855 if (!insn->hint && !insn_state_match(insn, &state)) 1962 if (!insn->hint && !insn_state_match(insn, &state))
1856 return 1; 1963 return 1;
1857 1964
1858 return 0; 1965 /* If we were here with AC=0, but now have AC=1, go again */
1966 if (insn->state.uaccess || !state.uaccess)
1967 return 0;
1859 } 1968 }
1860 1969
1861 if (insn->hint) { 1970 if (insn->hint) {
@@ -1925,6 +2034,16 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1925 switch (insn->type) { 2034 switch (insn->type) {
1926 2035
1927 case INSN_RETURN: 2036 case INSN_RETURN:
2037 if (state.uaccess && !func_uaccess_safe(func)) {
2038 WARN_FUNC("return with UACCESS enabled", sec, insn->offset);
2039 return 1;
2040 }
2041
2042 if (!state.uaccess && func_uaccess_safe(func)) {
2043 WARN_FUNC("return with UACCESS disabled from a UACCESS-safe function", sec, insn->offset);
2044 return 1;
2045 }
2046
1928 if (func && has_modified_stack_frame(&state)) { 2047 if (func && has_modified_stack_frame(&state)) {
1929 WARN_FUNC("return with modified stack frame", 2048 WARN_FUNC("return with modified stack frame",
1930 sec, insn->offset); 2049 sec, insn->offset);
@@ -1940,17 +2059,22 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1940 return 0; 2059 return 0;
1941 2060
1942 case INSN_CALL: 2061 case INSN_CALL:
1943 if (is_fentry_call(insn)) 2062 case INSN_CALL_DYNAMIC:
1944 break; 2063 ret = validate_call(insn, &state);
2064 if (ret)
2065 return ret;
1945 2066
1946 ret = dead_end_function(file, insn->call_dest); 2067 if (insn->type == INSN_CALL) {
1947 if (ret == 1) 2068 if (is_fentry_call(insn))
1948 return 0; 2069 break;
1949 if (ret == -1) 2070
1950 return 1; 2071 ret = dead_end_function(file, insn->call_dest);
2072 if (ret == 1)
2073 return 0;
2074 if (ret == -1)
2075 return 1;
2076 }
1951 2077
1952 /* fallthrough */
1953 case INSN_CALL_DYNAMIC:
1954 if (!no_fp && func && !has_valid_stack_frame(&state)) { 2078 if (!no_fp && func && !has_valid_stack_frame(&state)) {
1955 WARN_FUNC("call without frame pointer save/setup", 2079 WARN_FUNC("call without frame pointer save/setup",
1956 sec, insn->offset); 2080 sec, insn->offset);
@@ -2003,6 +2127,49 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
2003 if (update_insn_state(insn, &state)) 2127 if (update_insn_state(insn, &state))
2004 return 1; 2128 return 1;
2005 2129
2130 if (insn->stack_op.dest.type == OP_DEST_PUSHF) {
2131 if (!state.uaccess_stack) {
2132 state.uaccess_stack = 1;
2133 } else if (state.uaccess_stack >> 31) {
2134 WARN_FUNC("PUSHF stack exhausted", sec, insn->offset);
2135 return 1;
2136 }
2137 state.uaccess_stack <<= 1;
2138 state.uaccess_stack |= state.uaccess;
2139 }
2140
2141 if (insn->stack_op.src.type == OP_SRC_POPF) {
2142 if (state.uaccess_stack) {
2143 state.uaccess = state.uaccess_stack & 1;
2144 state.uaccess_stack >>= 1;
2145 if (state.uaccess_stack == 1)
2146 state.uaccess_stack = 0;
2147 }
2148 }
2149
2150 break;
2151
2152 case INSN_STAC:
2153 if (state.uaccess) {
2154 WARN_FUNC("recursive UACCESS enable", sec, insn->offset);
2155 return 1;
2156 }
2157
2158 state.uaccess = true;
2159 break;
2160
2161 case INSN_CLAC:
2162 if (!state.uaccess && insn->func) {
2163 WARN_FUNC("redundant UACCESS disable", sec, insn->offset);
2164 return 1;
2165 }
2166
2167 if (func_uaccess_safe(func) && !state.uaccess_stack) {
2168 WARN_FUNC("UACCESS-safe disables UACCESS", sec, insn->offset);
2169 return 1;
2170 }
2171
2172 state.uaccess = false;
2006 break; 2173 break;
2007 2174
2008 default: 2175 default:
@@ -2168,6 +2335,8 @@ static int validate_functions(struct objtool_file *file)
2168 if (!insn || insn->ignore) 2335 if (!insn || insn->ignore)
2169 continue; 2336 continue;
2170 2337
2338 state.uaccess = func->alias->uaccess_safe;
2339
2171 ret = validate_branch(file, insn, state); 2340 ret = validate_branch(file, insn, state);
2172 if (ret && backtrace) 2341 if (ret && backtrace)
2173 BT_FUNC("<=== (func)", insn); 2342 BT_FUNC("<=== (func)", insn);