Commit effe5be1 authored by Ilya Leoshkevich's avatar Ilya Leoshkevich Committed by Daniel Borkmann

s390/bpf: Maintain 8-byte stack alignment

Certain kernel functions (e.g. get_vtimer/set_vtimer) cause kernel
panic when the stack is not 8-byte aligned. Currently JITed BPF programs
may trigger this by allocating stack frames with non-rounded sizes and
then being interrupted. Fix by using rounded fp->aux->stack_depth.
Signed-off-by: default avatarIlya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20200602174339.2501066-1-iii@linux.ibm.com
parent 7cec0b92
...@@ -594,7 +594,7 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth) ...@@ -594,7 +594,7 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
* stack space for the large switch statement. * stack space for the large switch statement.
*/ */
static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
int i, bool extra_pass) int i, bool extra_pass, u32 stack_depth)
{ {
struct bpf_insn *insn = &fp->insnsi[i]; struct bpf_insn *insn = &fp->insnsi[i];
u32 dst_reg = insn->dst_reg; u32 dst_reg = insn->dst_reg;
...@@ -1207,7 +1207,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1207,7 +1207,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
*/ */
if (jit->seen & SEEN_STACK) if (jit->seen & SEEN_STACK)
off = STK_OFF_TCCNT + STK_OFF + fp->aux->stack_depth; off = STK_OFF_TCCNT + STK_OFF + stack_depth;
else else
off = STK_OFF_TCCNT; off = STK_OFF_TCCNT;
/* lhi %w0,1 */ /* lhi %w0,1 */
...@@ -1249,7 +1249,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1249,7 +1249,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
/* /*
* Restore registers before calling function * Restore registers before calling function
*/ */
save_restore_regs(jit, REGS_RESTORE, fp->aux->stack_depth); save_restore_regs(jit, REGS_RESTORE, stack_depth);
/* /*
* goto *(prog->bpf_func + tail_call_start); * goto *(prog->bpf_func + tail_call_start);
...@@ -1519,7 +1519,7 @@ static int bpf_set_addr(struct bpf_jit *jit, int i) ...@@ -1519,7 +1519,7 @@ static int bpf_set_addr(struct bpf_jit *jit, int i)
* Compile eBPF program into s390x code * Compile eBPF program into s390x code
*/ */
static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp, static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp,
bool extra_pass) bool extra_pass, u32 stack_depth)
{ {
int i, insn_count, lit32_size, lit64_size; int i, insn_count, lit32_size, lit64_size;
...@@ -1527,18 +1527,18 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1527,18 +1527,18 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp,
jit->lit64 = jit->lit64_start; jit->lit64 = jit->lit64_start;
jit->prg = 0; jit->prg = 0;
bpf_jit_prologue(jit, fp->aux->stack_depth); bpf_jit_prologue(jit, stack_depth);
if (bpf_set_addr(jit, 0) < 0) if (bpf_set_addr(jit, 0) < 0)
return -1; return -1;
for (i = 0; i < fp->len; i += insn_count) { for (i = 0; i < fp->len; i += insn_count) {
insn_count = bpf_jit_insn(jit, fp, i, extra_pass); insn_count = bpf_jit_insn(jit, fp, i, extra_pass, stack_depth);
if (insn_count < 0) if (insn_count < 0)
return -1; return -1;
/* Next instruction address */ /* Next instruction address */
if (bpf_set_addr(jit, i + insn_count) < 0) if (bpf_set_addr(jit, i + insn_count) < 0)
return -1; return -1;
} }
bpf_jit_epilogue(jit, fp->aux->stack_depth); bpf_jit_epilogue(jit, stack_depth);
lit32_size = jit->lit32 - jit->lit32_start; lit32_size = jit->lit32 - jit->lit32_start;
lit64_size = jit->lit64 - jit->lit64_start; lit64_size = jit->lit64 - jit->lit64_start;
...@@ -1569,6 +1569,7 @@ struct s390_jit_data { ...@@ -1569,6 +1569,7 @@ struct s390_jit_data {
*/ */
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
{ {
u32 stack_depth = round_up(fp->aux->stack_depth, 8);
struct bpf_prog *tmp, *orig_fp = fp; struct bpf_prog *tmp, *orig_fp = fp;
struct bpf_binary_header *header; struct bpf_binary_header *header;
struct s390_jit_data *jit_data; struct s390_jit_data *jit_data;
...@@ -1621,7 +1622,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) ...@@ -1621,7 +1622,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
* - 3: Calculate program size and addrs arrray * - 3: Calculate program size and addrs arrray
*/ */
for (pass = 1; pass <= 3; pass++) { for (pass = 1; pass <= 3; pass++) {
if (bpf_jit_prog(&jit, fp, extra_pass)) { if (bpf_jit_prog(&jit, fp, extra_pass, stack_depth)) {
fp = orig_fp; fp = orig_fp;
goto free_addrs; goto free_addrs;
} }
...@@ -1635,7 +1636,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) ...@@ -1635,7 +1636,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
goto free_addrs; goto free_addrs;
} }
skip_init_ctx: skip_init_ctx:
if (bpf_jit_prog(&jit, fp, extra_pass)) { if (bpf_jit_prog(&jit, fp, extra_pass, stack_depth)) {
bpf_jit_binary_free(header); bpf_jit_binary_free(header);
fp = orig_fp; fp = orig_fp;
goto free_addrs; goto free_addrs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment