[lxc-devel] [lxc/master] cgroups: fix bpf device program generation
brauner on Github
lxc-bot at linuxcontainers.org
Sun Jul 5 09:18:03 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 380 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200705/57492fd2/attachment.bin>
-------------- next part --------------
From ee9d3ef05b1fd13afd47d54166d12d2042f1704f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 5 Jul 2020 10:49:58 +0200
Subject: [PATCH] cgroups: fix bpf device program generation
Closes: #3473.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/cgroups/cgfsng.c | 18 ++++-----
src/lxc/cgroups/cgroup2_devices.c | 66 +++++++++++++++++--------------
2 files changed, 44 insertions(+), 40 deletions(-)
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 45dde6726f..da78f552c2 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2934,17 +2934,13 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
struct lxc_cgroup *cg = iterator->elem;
int ret;
- if (strncmp("devices", cg->subsystem, 7) == 0) {
- ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem,
- cg->value);
- } else {
- ret = lxc_write_openat(h->container_limit_path,
- cg->subsystem, cg->value,
- strlen(cg->value));
- if (ret < 0)
- return log_error_errno(false, errno, "Failed to set \"%s\" to \"%s\"",
- cg->subsystem, cg->value);
- }
+ if (strncmp("devices", cg->subsystem, 7) == 0)
+ ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem, cg->value);
+ else
+ ret = lxc_write_openat(h->container_limit_path, cg->subsystem, cg->value, strlen(cg->value));
+ if (ret < 0)
+ return log_error_errno(false, errno, "Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value);
+
TRACE("Set \"%s\" to \"%s\"", cg->subsystem, cg->value);
}
diff --git a/src/lxc/cgroups/cgroup2_devices.c b/src/lxc/cgroups/cgroup2_devices.c
index 7f682d3e32..fd60d5a49b 100644
--- a/src/lxc/cgroups/cgroup2_devices.c
+++ b/src/lxc/cgroups/cgroup2_devices.c
@@ -27,6 +27,18 @@
lxc_log_define(cgroup2_devices, cgroup);
+#ifndef BPF_LOG_LEVEL1
+#define BPF_LOG_LEVEL1 1
+#endif
+
+#ifndef BPF_LOG_LEVEL2
+#define BPF_LOG_LEVEL2 2
+#endif
+
+#ifndef BPF_LOG_LEVEL
+#define BPF_LOG_LEVEL (BPF_LOG_LEVEL1 | BPF_LOG_LEVEL2)
+#endif
+
static int bpf_program_add_instructions(struct bpf_program *prog,
const struct bpf_insn *instructions,
size_t count)
@@ -118,10 +130,8 @@ void bpf_program_free(struct bpf_program *prog)
.off = 0, \
.imm = 0})
-static int bpf_access_mask(const char *acc, int *mask)
+static int bpf_access_mask(const char *acc, __u32 *mask)
{
- *mask = 0;
-
if (!acc)
return 0;
@@ -136,8 +146,6 @@ static int bpf_access_mask(const char *acc, int *mask)
case 'm':
*mask |= BPF_DEVCG_ACC_MKNOD;
break;
- case '\0':
- continue;
default:
return -EINVAL;
}
@@ -160,10 +168,9 @@ static int bpf_device_type(char type)
return -1;
}
-static inline bool bpf_device_all_access(int access_mask)
+static inline bool bpf_device_all_access(__u32 access_mask)
{
- return (access_mask == (BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE |
- BPF_DEVCG_ACC_MKNOD));
+ return access_mask == (BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE | BPF_DEVCG_ACC_MKNOD);
}
struct bpf_program *bpf_program_new(uint32_t prog_type)
@@ -211,7 +218,8 @@ int bpf_program_init(struct bpf_program *prog)
int bpf_program_append_device(struct bpf_program *prog, struct device_item *device)
{
int jump_nr = 1;
- int access_mask, device_type, ret;
+ __u32 access_mask = 0;
+ int device_type, ret;
struct bpf_insn bpf_access_decision[2];
if (!prog || !device)
@@ -223,6 +231,13 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
return 0;
}
+ ret = bpf_access_mask(device->access, &access_mask);
+ if (ret < 0)
+ return log_error_errno(ret, -ret, "Invalid access mask specified %s", device->access);
+
+ if (!bpf_device_all_access(access_mask))
+ jump_nr++;
+
device_type = bpf_device_type(device->type);
if (device_type < 0)
return log_error_errno(-1, EINVAL, "Invalid bpf cgroup device type %c", device->type);
@@ -230,22 +245,17 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
if (device_type > 0)
jump_nr++;
- ret = bpf_access_mask(device->access, &access_mask);
- if (ret < 0)
- return log_error_errno(ret, -ret, "Invalid access mask specified %s", device->access);
-
- if (!bpf_device_all_access(access_mask))
- jump_nr += 3;
-
if (device->major != -1)
jump_nr++;
if (device->minor != -1)
jump_nr++;
- if (device_type > 0) {
+ if (!bpf_device_all_access(access_mask)) {
struct bpf_insn ins[] = {
- BPF_JMP_IMM(BPF_JNE, BPF_REG_2, device_type, jump_nr--),
+ BPF_MOV32_REG(BPF_REG_1, BPF_REG_3),
+ BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access_mask),
+ BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, jump_nr--),
};
ret = bpf_program_add_instructions(prog, ins, ARRAY_SIZE(ins));
@@ -253,14 +263,11 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
}
- if (!bpf_device_all_access(access_mask)) {
+ if (device_type > 0) {
struct bpf_insn ins[] = {
- BPF_MOV32_REG(BPF_REG_1, BPF_REG_3),
- BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access_mask),
- BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, jump_nr),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_2, device_type, jump_nr--),
};
- jump_nr -= 3;
ret = bpf_program_add_instructions(prog, ins, ARRAY_SIZE(ins));
if (ret)
return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
@@ -289,7 +296,7 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
bpf_access_decision[0] = BPF_MOV64_IMM(BPF_REG_0, device->allow);
bpf_access_decision[1] = BPF_EXIT_INSN();
ret = bpf_program_add_instructions(prog, bpf_access_decision,
- ARRAY_SIZE(bpf_access_decision));
+ ARRAY_SIZE(bpf_access_decision));
if (ret)
return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
@@ -314,7 +321,7 @@ int bpf_program_finalize(struct bpf_program *prog)
}
static int bpf_program_load_kernel(struct bpf_program *prog, char *log_buf,
- size_t log_size)
+ __u32 log_size, __u32 log_level)
{
union bpf_attr attr;
@@ -329,14 +336,15 @@ static int bpf_program_load_kernel(struct bpf_program *prog, char *log_buf,
.insn_cnt = prog->n_instructions,
.license = PTR_TO_UINT64("GPL"),
.log_buf = PTR_TO_UINT64(log_buf),
- .log_level = !!log_buf,
+ .log_level = log_level,
.log_size = log_size,
};
prog->kernel_fd = bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
if (prog->kernel_fd < 0)
- return log_error_errno(-1, errno, "Failed to load bpf program");
+ return log_error_errno(-1, errno, "Failed to load bpf program: %s", log_buf);
+ TRACE("Loaded bpf program: %s", log_buf);
return 0;
}
@@ -365,7 +373,7 @@ int bpf_program_cgroup_attach(struct bpf_program *prog, int type,
return true;
}
- ret = bpf_program_load_kernel(prog, NULL, 0);
+ ret = bpf_program_load_kernel(prog, NULL, 0, 0);
if (ret < 0)
return log_error_errno(-1, ret, "Failed to load bpf program");
@@ -527,7 +535,7 @@ bool bpf_devices_cgroup_supported(void)
if (ret < 0)
return log_trace(false, "Failed to add new instructions to bpf device cgroup program");
- ret = bpf_program_load_kernel(prog, NULL, 0);
+ ret = bpf_program_load_kernel(prog, NULL, 0, 0);
if (ret < 0)
return log_trace(false, "Failed to load new bpf device cgroup program");
More information about the lxc-devel
mailing list