lkml.org 
[lkml]   [2015]   [Jul]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH 01/21] stackvalidate: Process ignores earlier and add more ignore checks
Date
Process the ignore macros earlier and associate them with their
corresponding instructions. This allows ignores to be checked in
get_jump_destinations() which is needed for some funky xen code which
introduces fake instructions (XEN_EMULATE_PREFIX).

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
scripts/stackvalidate/stackvalidate.c | 77 +++++++++++++++++++++++++----------
1 file changed, 56 insertions(+), 21 deletions(-)

diff --git a/scripts/stackvalidate/stackvalidate.c b/scripts/stackvalidate/stackvalidate.c
index a817130..6173412 100644
--- a/scripts/stackvalidate/stackvalidate.c
+++ b/scripts/stackvalidate/stackvalidate.c
@@ -49,7 +49,7 @@ struct instruction {
unsigned int len, state;
unsigned char type;
unsigned long immediate;
- bool alt_group, visited;
+ bool alt_group, visited, ignore;
struct symbol *call_dest;
struct instruction *jump_dest;
struct list_head alts;
@@ -106,8 +106,7 @@ static struct argp argp = { options, parse_opt, args_doc, 0 };
/*
* Check for the STACKVALIDATE_IGNORE_INSN macro.
*/
-static bool ignore_insn(struct elf *elf, struct section *sec,
- unsigned long offset)
+static bool ignore_insn(struct elf *elf, struct instruction *insn)
{
struct section *macro_sec;
struct rela *rela;
@@ -118,8 +117,8 @@ static bool ignore_insn(struct elf *elf, struct section *sec,

list_for_each_entry(rela, &macro_sec->rela->relas, list)
if (rela->sym->type == STT_SECTION &&
- rela->sym == sec->sym &&
- rela->addend == offset)
+ rela->sym == insn->sec->sym &&
+ rela->addend == insn->offset)
return true;

return false;
@@ -138,9 +137,11 @@ static bool ignore_func(struct elf *elf, struct symbol *func)
return false;

list_for_each_entry(rela, &macro_sec->rela->relas, list)
- if (rela->sym == func)
+ if (rela->sym->sec == func->sec &&
+ rela->addend == func->offset)
return true;

+
return false;
}

@@ -266,6 +267,44 @@ static int decode_instructions(struct elf *elf)
}

/*
+ * Warnings shouldn't be reported for ignored instructions. Set insn->ignore
+ * for each ignored instruction and each instruction contained in an ignored
+ * function.
+ */
+static void get_ignores(struct elf *elf)
+{
+ struct instruction *insn;
+ struct section *sec;
+ struct symbol *func;
+
+ list_for_each_entry(insn, &insns, list)
+ insn->ignore = ignore_insn(elf, insn);
+
+ list_for_each_entry(sec, &elf->sections, list) {
+ list_for_each_entry(func, &sec->symbols, list) {
+ if (func->type != STT_FUNC)
+ continue;
+
+ if (!ignore_func(elf, func))
+ continue;
+
+ insn = find_instruction(sec, func->offset);
+ if (!insn)
+ continue;
+
+ list_for_each_entry_from(insn, &insns, list) {
+ if (insn->sec != func->sec ||
+ insn->offset >= func->offset + func->len)
+ break;
+
+ insn->ignore = true;
+ insn->visited = true;
+ }
+ }
+ }
+}
+
+/*
* Find the destination instructions for all jumps.
*/
static int get_jump_destinations(struct elf *elf)
@@ -300,7 +339,7 @@ static int get_jump_destinations(struct elf *elf)
}

insn->jump_dest = find_instruction(dest_sec, dest_off);
- if (!insn->jump_dest) {
+ if (!insn->jump_dest && !insn->ignore) {

/*
* This is a special case where an alt instruction
@@ -591,6 +630,8 @@ static int decode_sections(struct elf *elf)
if (ret)
return ret;

+ get_ignores(elf);
+
ret = get_jump_destinations(elf);
if (ret)
return ret;
@@ -734,7 +775,8 @@ static int validate_branch(struct elf *elf, struct instruction *first,
break;

case INSN_JUMP_DYNAMIC:
- if (list_empty(&insn->alts) && insn->state) {
+ if (list_empty(&insn->alts) && insn->state &&
+ !insn->ignore) {
WARN("%s: sibling call from callable instruction with changed frame pointer",
offstr(sec, insn->offset));
warnings++;
@@ -743,9 +785,11 @@ static int validate_branch(struct elf *elf, struct instruction *first,
return warnings;

case INSN_CONTEXT_SWITCH:
- WARN("%s: kernel entry/exit from callable instruction",
- offstr(sec, insn->offset));
- warnings++;
+ if (!insn->ignore) {
+ WARN("%s: kernel entry/exit from callable instruction",
+ offstr(sec, insn->offset));
+ warnings++;
+ }

return warnings;

@@ -786,15 +830,6 @@ static int validate_functions(struct elf *elf)
continue;
}

- if (ignore_func(elf, func)) {
- list_for_each_entry_from(insn, &insns, list) {
- if (insn->sec != func->sec ||
- insn->offset >= func->offset + func->len)
- break;
- insn->visited = true;
- }
- }
-
ret = validate_branch(elf, insn, 0);
warnings += ret;
}
@@ -835,7 +870,7 @@ static int validate_uncallable_instructions(struct elf *elf)

list_for_each_entry(insn, &insns, list) {
if (!insn->visited && insn->type == INSN_RETURN &&
- !ignore_insn(elf, insn->sec, insn->offset)) {
+ !insn->ignore) {
WARN("%s: return instruction outside of a callable function",
offstr(insn->sec, insn->offset));
warnings++;
--
2.1.0


\
 
 \ /
  Last update: 2015-07-17 19:21    [W:1.745 / U:0.072 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site