|
@@ -5064,14 +5064,21 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of
|
|
return new_prog;
|
|
return new_prog;
|
|
}
|
|
}
|
|
|
|
|
|
-/* The verifier does more data flow analysis than llvm and will not explore
|
|
|
|
- * branches that are dead at run time. Malicious programs can have dead code
|
|
|
|
- * too. Therefore replace all dead at-run-time code with nops.
|
|
|
|
|
|
+/* The verifier does more data flow analysis than llvm and will not
|
|
|
|
+ * explore branches that are dead at run time. Malicious programs can
|
|
|
|
+ * have dead code too. Therefore replace all dead at-run-time code
|
|
|
|
+ * with 'ja -1'.
|
|
|
|
+ *
|
|
|
|
+ * Just nops are not optimal, e.g. if they would sit at the end of the
|
|
|
|
+ * program and through another bug we would manage to jump there, then
|
|
|
|
+ * we'd execute beyond program memory otherwise. Returning exception
|
|
|
|
+ * code also wouldn't work since we can have subprogs where the dead
|
|
|
|
+ * code could be located.
|
|
*/
|
|
*/
|
|
static void sanitize_dead_code(struct bpf_verifier_env *env)
|
|
static void sanitize_dead_code(struct bpf_verifier_env *env)
|
|
{
|
|
{
|
|
struct bpf_insn_aux_data *aux_data = env->insn_aux_data;
|
|
struct bpf_insn_aux_data *aux_data = env->insn_aux_data;
|
|
- struct bpf_insn nop = BPF_MOV64_REG(BPF_REG_0, BPF_REG_0);
|
|
|
|
|
|
+ struct bpf_insn trap = BPF_JMP_IMM(BPF_JA, 0, 0, -1);
|
|
struct bpf_insn *insn = env->prog->insnsi;
|
|
struct bpf_insn *insn = env->prog->insnsi;
|
|
const int insn_cnt = env->prog->len;
|
|
const int insn_cnt = env->prog->len;
|
|
int i;
|
|
int i;
|
|
@@ -5079,7 +5086,7 @@ static void sanitize_dead_code(struct bpf_verifier_env *env)
|
|
for (i = 0; i < insn_cnt; i++) {
|
|
for (i = 0; i < insn_cnt; i++) {
|
|
if (aux_data[i].seen)
|
|
if (aux_data[i].seen)
|
|
continue;
|
|
continue;
|
|
- memcpy(insn + i, &nop, sizeof(nop));
|
|
|
|
|
|
+ memcpy(insn + i, &trap, sizeof(trap));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|