summaryrefslogtreecommitdiff
path: root/src/core/bpf-devices.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-11-10 13:19:51 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-11-11 15:14:02 +0100
commit00486578281bccbe36a6a447b3597d6bf8967933 (patch)
tree86236e8a613a4d92bdfba34a8b10698859a0bff5 /src/core/bpf-devices.c
parent8ad08622d6f818f65e56b1e588221a4d546ab9bb (diff)
downloadsystemd-00486578281bccbe36a6a447b3597d6bf8967933.tar.gz
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
Diffstat (limited to 'src/core/bpf-devices.c')
-rw-r--r--src/core/bpf-devices.c48
1 files changed, 30 insertions, 18 deletions
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");