From: Zbigniew Jędrzejewski-Szmek Date: Sun, 10 Nov 2019 12:19:51 +0000 (+0100) Subject: bpf: optimize device type access away most of the time X-Git-Tag: v244-rc1~62^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=00486578281bccbe36a6a447b3597d6bf8967933;p=thirdparty%2Fsystemd.git bpf: optimize device type access away most of the time Most of the time, we specify the allowed access mode as "rwm", so the check always trivially passes. In that case, skip the check. The repeating part changes from: 5: (55) if r2 != 0x2 goto pc+6 6: (bc) w1 = w3 7: (54) w1 &= 7 8: (5d) if r1 != r3 goto pc+3 9: (55) if r4 != 0x1 goto pc+2 10: (55) if r5 != 0x3 goto pc+1 11: (05) goto pc+8 to 6: (55) if r2 != 0x2 goto pc+3 7: (55) if r4 != 0x1 goto pc+2 8: (55) if r5 != 0x3 goto pc+1 9: (05) goto pc+40 --- diff --git a/src/core/bpf-devices.c b/src/core/bpf-devices.c index 932c73033a7..827c3ab9492 100644 --- a/src/core/bpf-devices.c +++ b/src/core/bpf-devices.c @@ -54,16 +54,20 @@ static int bpf_prog_whitelist_device(BPFProgram *prog, char type, int major, int const int bpf_type = type == 'c' ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK; const struct bpf_insn insn[] = { - BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 6), /* compare device type */ - BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), /* calculate access type */ + BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access), - BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 3), /* compare access type */ - BPF_JMP_IMM(BPF_JNE, BPF_REG_4, major, 2), /* compare major */ - BPF_JMP_IMM(BPF_JNE, BPF_REG_5, minor, 1), /* compare minor */ - BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ + BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 4), /* compare access type */ + + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 3), /* compare device type */ + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, major, 2), /* compare major */ + BPF_JMP_IMM(BPF_JNE, BPF_REG_5, minor, 1), /* compare minor */ + BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ }; - r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); + if (FLAGS_SET(access, BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE | BPF_DEVCG_ACC_MKNOD)) + r = bpf_program_add_instructions(prog, insn + 3, ELEMENTSOF(insn) - 3); + else + r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); if (r < 0) log_error_errno(r, "Extending device control BPF program failed: %m"); @@ -86,15 +90,19 @@ static int bpf_prog_whitelist_major(BPFProgram *prog, char type, int major, cons const int bpf_type = type == 'c' ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK; const struct bpf_insn insn[] = { - BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 5), /* compare device type */ - BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), /* calculate access type */ + BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access), - BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 2), /* compare access type */ - BPF_JMP_IMM(BPF_JNE, BPF_REG_4, major, 1), /* compare major */ - BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ + BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 3), /* compare access type */ + + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 2), /* compare device type */ + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, major, 1), /* compare major */ + BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ }; - r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); + if (FLAGS_SET(access, BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE | BPF_DEVCG_ACC_MKNOD)) + r = bpf_program_add_instructions(prog, insn + 3, ELEMENTSOF(insn) - 3); + else + r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); if (r < 0) log_error_errno(r, "Extending device control BPF program failed: %m"); @@ -117,14 +125,18 @@ static int bpf_prog_whitelist_class(BPFProgram *prog, char type, const char *acc const int bpf_type = type == 'c' ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK; const struct bpf_insn insn[] = { - BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 4), /* compare device type */ - BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), /* calculate access type */ + BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access), - BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 1), /* compare access type */ - BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ + BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 2), /* compare access type */ + + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 1), /* compare device type */ + BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ }; - r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); + if (FLAGS_SET(access, BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE | BPF_DEVCG_ACC_MKNOD)) + r = bpf_program_add_instructions(prog, insn + 3, ELEMENTSOF(insn) - 3); + else + r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); if (r < 0) log_error_errno(r, "Extending device control BPF program failed: %m");