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: Ilya Leoshkevich <iii@linux.ibm.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20200602174339.2501066-1-iii@linux.ibm.com
This commit is contained in:
Родитель
7cec0b9271
Коммит
effe5be177
|
@ -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,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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,
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
* 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,
|
||||||
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 {
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
* - 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)
|
||||||
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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче