[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241119153502.41361-10-vschneid@redhat.com>
Date: Tue, 19 Nov 2024 16:34:56 +0100
From: Valentin Schneider <vschneid@...hat.com>
To: linux-kernel@...r.kernel.org,
linux-doc@...r.kernel.org,
kvm@...r.kernel.org,
linux-mm@...ck.org,
bpf@...r.kernel.org,
x86@...nel.org,
rcu@...r.kernel.org,
linux-kselftest@...r.kernel.org
Cc: Josh Poimboeuf <jpoimboe@...hat.com>,
Steven Rostedt <rostedt@...dmis.org>,
Masami Hiramatsu <mhiramat@...nel.org>,
Jonathan Corbet <corbet@....net>,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>,
Borislav Petkov <bp@...en8.de>,
Dave Hansen <dave.hansen@...ux.intel.com>,
"H. Peter Anvin" <hpa@...or.com>,
Paolo Bonzini <pbonzini@...hat.com>,
Wanpeng Li <wanpengli@...cent.com>,
Vitaly Kuznetsov <vkuznets@...hat.com>,
Andy Lutomirski <luto@...nel.org>,
Peter Zijlstra <peterz@...radead.org>,
Frederic Weisbecker <frederic@...nel.org>,
"Paul E. McKenney" <paulmck@...nel.org>,
Neeraj Upadhyay <quic_neeraju@...cinc.com>,
Joel Fernandes <joel@...lfernandes.org>,
Josh Triplett <josh@...htriplett.org>,
Boqun Feng <boqun.feng@...il.com>,
Mathieu Desnoyers <mathieu.desnoyers@...icios.com>,
Lai Jiangshan <jiangshanlai@...il.com>,
Zqiang <qiang.zhang1211@...il.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Uladzislau Rezki <urezki@...il.com>,
Christoph Hellwig <hch@...radead.org>,
Lorenzo Stoakes <lstoakes@...il.com>,
Josh Poimboeuf <jpoimboe@...nel.org>,
Jason Baron <jbaron@...mai.com>,
Kees Cook <keescook@...omium.org>,
Sami Tolvanen <samitolvanen@...gle.com>,
Ard Biesheuvel <ardb@...nel.org>,
Nicholas Piggin <npiggin@...il.com>,
Juerg Haefliger <juerg.haefliger@...onical.com>,
Nicolas Saenz Julienne <nsaenz@...nel.org>,
"Kirill A. Shutemov" <kirill.shutemov@...ux.intel.com>,
Nadav Amit <namit@...are.com>,
Dan Carpenter <error27@...il.com>,
Chuang Wang <nashuiliang@...il.com>,
Yang Jihong <yangjihong1@...wei.com>,
Petr Mladek <pmladek@...e.com>,
"Jason A. Donenfeld" <Jason@...c4.com>,
Song Liu <song@...nel.org>,
Julian Pidancet <julian.pidancet@...cle.com>,
Tom Lendacky <thomas.lendacky@....com>,
Dionna Glaze <dionnaglaze@...gle.com>,
Thomas Weißschuh <linux@...ssschuh.net>,
Juri Lelli <juri.lelli@...hat.com>,
Marcelo Tosatti <mtosatti@...hat.com>,
Yair Podemsky <ypodemsk@...hat.com>,
Daniel Wagner <dwagner@...e.de>,
Petr Tesarik <ptesarik@...e.com>
Subject: [RFC PATCH v3 09/15] objtool: Warn about non __ro_after_init static key usage in .noinstr
Later commits will disallow runtime-mutable text in .noinstr sections in
order to safely defer instruction patching IPIs.
All static keys used in .noinstr sections have now been checked as being
either flagged as __ro_after_init, or as forceful static keys. Any
occurrence of this new warning would be the result of a code change that
will need looking at.
Suggested-by: Josh Poimboeuf <jpoimboe@...hat.com>
Signed-off-by: Valentin Schneider <vschneid@...hat.com>
---
offset_of(static_key.type) and JUMP_TYPE_FORCEFUL would need to be shoved
into a somewhat standalone header file that could be included by objtool
itself.
---
tools/objtool/Documentation/objtool.txt | 13 ++++++++
tools/objtool/check.c | 41 +++++++++++++++++++++++++
tools/objtool/include/objtool/check.h | 1 +
tools/objtool/include/objtool/special.h | 2 ++
tools/objtool/special.c | 3 ++
5 files changed, 60 insertions(+)
diff --git a/tools/objtool/Documentation/objtool.txt b/tools/objtool/Documentation/objtool.txt
index 7c3ee959b63c7..06fa285873387 100644
--- a/tools/objtool/Documentation/objtool.txt
+++ b/tools/objtool/Documentation/objtool.txt
@@ -447,6 +447,19 @@ the objtool maintainers.
names and does not use module_init() / module_exit() macros to create
them.
+13. file.o: warning: func()+0x2a: non __ro_after_init static key "key" in .noinstr section
+
+ This means that the noinstr function func() uses a static key that can be
+ modified at runtime. This is not allowed as noinstr functions rely on
+ containing stable instructions after init.
+
+ Check whether the static key in question can really be modified at runtime,
+ and if it is only enabled during init then mark it as __ro_after_init. If it
+ genuinely needs to be modified at runtime:
+
+ 1) Directly rely on the underlying atomic count of they key in the noinstr
+ functions.
+ 2) Mark the static key as forceful.
If the error doesn't seem to make sense, it could be a bug in objtool.
Feel free to ask the objtool maintainer for help.
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 00e25492f5065..c1fb02c326839 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2056,6 +2056,9 @@ static int add_special_section_alts(struct objtool_file *file)
alt->next = orig_insn->alts;
orig_insn->alts = alt;
+ if (special_alt->key_sym)
+ orig_insn->key_sym = special_alt->key_sym;
+
list_del(&special_alt->list);
free(special_alt);
}
@@ -3605,6 +3608,41 @@ static int validate_return(struct symbol *func, struct instruction *insn, struct
return 0;
}
+static bool static_key_is_forceful(struct symbol *key)
+{
+ if (!strcmp(key->sec->name, ".data")) {
+ unsigned long data_offset = key->sec->data->d_off;
+ unsigned long key_offset = key->sym.st_value;
+ char* data = key->sec->data->d_buf;
+
+ /*
+ * offset_of(static_key.type)
+ * v
+ * v JUMP_TYPE_FORCEFUL
+ * v v
+ */
+ return data[(key_offset + 8) - data_offset] & 0x4;
+ }
+
+ return false;
+}
+
+static int validate_static_key(struct instruction *insn, struct insn_state *state)
+{
+ if (state->noinstr && state->instr <= 0) {
+ if (static_key_is_forceful(insn->key_sym))
+ return 0;
+
+ if ((strcmp(insn->key_sym->sec->name, ".data..ro_after_init"))) {
+ WARN_INSN(insn, "non __ro_after_init static key \"%s\" in .noinstr section",
+ insn->key_sym->name);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static struct instruction *next_insn_to_validate(struct objtool_file *file,
struct instruction *insn)
{
@@ -3766,6 +3804,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
if (handle_insn_ops(insn, next_insn, &state))
return 1;
+ if (insn->key_sym)
+ validate_static_key(insn, &state);
+
switch (insn->type) {
case INSN_RETURN:
diff --git a/tools/objtool/include/objtool/check.h b/tools/objtool/include/objtool/check.h
index daa46f1f0965a..35dd21f8f41e1 100644
--- a/tools/objtool/include/objtool/check.h
+++ b/tools/objtool/include/objtool/check.h
@@ -77,6 +77,7 @@ struct instruction {
struct symbol *sym;
struct stack_op *stack_ops;
struct cfi_state *cfi;
+ struct symbol *key_sym;
};
static inline struct symbol *insn_func(struct instruction *insn)
diff --git a/tools/objtool/include/objtool/special.h b/tools/objtool/include/objtool/special.h
index 86d4af9c5aa9d..0e61f34fe3a28 100644
--- a/tools/objtool/include/objtool/special.h
+++ b/tools/objtool/include/objtool/special.h
@@ -27,6 +27,8 @@ struct special_alt {
struct section *new_sec;
unsigned long new_off;
+ struct symbol *key_sym;
+
unsigned int orig_len, new_len; /* group only */
};
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index 097a69db82a0e..fefab2b471bf8 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -127,6 +127,9 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
return -1;
}
alt->key_addend = reloc_addend(key_reloc);
+
+ reloc_to_sec_off(key_reloc, &sec, &offset);
+ alt->key_sym = find_symbol_by_offset(sec, offset & ~3);
}
return 0;
--
2.43.0
Powered by blists - more mailing lists