From 00486578281bccbe36a6a447b3597d6bf8967933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 10 Nov 2019 13:19:51 +0100 Subject: 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 --- src/core/bpf-devices.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'src/core/bpf-devices.c') diff --git a/src/core/bpf-devices.c b/src/core/bpf-devices.c index 932c73033a..827c3ab949 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"); -- cgit v1.2.1