core: remove refcount for bpf program
Currently ref count of bpf-program is kept in user space. However, the kernel already implements its own ref count. Thus the ref count we keep for bpf-program is redundant. This PR removes ref count for bpf program as part of a task to simplify bpf-program and remove redundancies, which will make the switch to code-compiled BPF programs easier. Part of #19270
This commit is contained in:
committed by
Lennart Poettering
parent
d92681a65e
commit
76dc17254f
+13
-12
@@ -184,7 +184,7 @@ int bpf_devices_cgroup_init(
|
||||
offsetof(struct bpf_cgroup_dev_ctx, minor)),
|
||||
};
|
||||
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *prog = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
@@ -208,7 +208,7 @@ int bpf_devices_cgroup_init(
|
||||
}
|
||||
|
||||
int bpf_devices_apply_policy(
|
||||
BPFProgram *prog,
|
||||
BPFProgram **prog,
|
||||
CGroupDevicePolicy policy,
|
||||
bool allow_list,
|
||||
const char *cgroup_path,
|
||||
@@ -219,7 +219,8 @@ int bpf_devices_apply_policy(
|
||||
|
||||
/* This will assign *prog_installed if everything goes well. */
|
||||
|
||||
if (!prog)
|
||||
assert(prog);
|
||||
if (!*prog)
|
||||
goto finish;
|
||||
|
||||
const bool deny_everything = policy == CGROUP_DEVICE_POLICY_STRICT && !allow_list;
|
||||
@@ -237,20 +238,20 @@ int bpf_devices_apply_policy(
|
||||
};
|
||||
|
||||
if (!deny_everything) {
|
||||
r = bpf_program_add_instructions(prog, post_insn, ELEMENTSOF(post_insn));
|
||||
r = bpf_program_add_instructions(*prog, post_insn, ELEMENTSOF(post_insn));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Extending device control BPF program failed: %m");
|
||||
|
||||
/* Fixup PASS_JUMP_OFF jump offsets. */
|
||||
for (size_t off = 0; off < prog->n_instructions; off++) {
|
||||
struct bpf_insn *ins = &prog->instructions[off];
|
||||
for (size_t off = 0; off < (*prog)->n_instructions; off++) {
|
||||
struct bpf_insn *ins = &((*prog)->instructions[off]);
|
||||
|
||||
if (ins->code == (BPF_JMP | BPF_JA) && ins->off == PASS_JUMP_OFF)
|
||||
ins->off = prog->n_instructions - off - 1;
|
||||
ins->off = (*prog)->n_instructions - off - 1;
|
||||
}
|
||||
}
|
||||
|
||||
r = bpf_program_add_instructions(prog, exit_insn, ELEMENTSOF(exit_insn));
|
||||
r = bpf_program_add_instructions(*prog, exit_insn, ELEMENTSOF(exit_insn));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Extending device control BPF program failed: %m");
|
||||
|
||||
@@ -258,7 +259,7 @@ int bpf_devices_apply_policy(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine cgroup path: %m");
|
||||
|
||||
r = bpf_program_cgroup_attach(prog, BPF_CGROUP_DEVICE, controller_path, BPF_F_ALLOW_MULTI);
|
||||
r = bpf_program_cgroup_attach(*prog, BPF_CGROUP_DEVICE, controller_path, BPF_F_ALLOW_MULTI);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Attaching device control BPF program to cgroup %s failed: %m",
|
||||
empty_to_root(cgroup_path));
|
||||
@@ -266,8 +267,8 @@ int bpf_devices_apply_policy(
|
||||
finish:
|
||||
/* Unref the old BPF program (which will implicitly detach it) right before attaching the new program. */
|
||||
if (prog_installed) {
|
||||
bpf_program_unref(*prog_installed);
|
||||
*prog_installed = bpf_program_ref(prog);
|
||||
bpf_program_free(*prog_installed);
|
||||
*prog_installed = TAKE_PTR(*prog);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -278,7 +279,7 @@ int bpf_devices_supported(void) {
|
||||
BPF_EXIT_INSN()
|
||||
};
|
||||
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *program = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *program = NULL;
|
||||
static int supported = -1;
|
||||
int r;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ typedef struct BPFProgram BPFProgram;
|
||||
|
||||
int bpf_devices_cgroup_init(BPFProgram **ret, CGroupDevicePolicy policy, bool allow_list);
|
||||
int bpf_devices_apply_policy(
|
||||
BPFProgram *prog,
|
||||
BPFProgram **prog,
|
||||
CGroupDevicePolicy policy,
|
||||
bool allow_list,
|
||||
const char *cgroup_path,
|
||||
|
||||
+18
-25
@@ -192,7 +192,7 @@ static int bpf_firewall_compile_bpf(
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
};
|
||||
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *p = NULL;
|
||||
int accounting_map_fd, r;
|
||||
bool access_enabled;
|
||||
|
||||
@@ -555,8 +555,8 @@ int bpf_firewall_compile(Unit *u) {
|
||||
* but we reuse the accounting maps. That way the firewall in effect always maps to the actual
|
||||
* configuration, but we don't flush out the accounting unnecessarily */
|
||||
|
||||
u->ip_bpf_ingress = bpf_program_unref(u->ip_bpf_ingress);
|
||||
u->ip_bpf_egress = bpf_program_unref(u->ip_bpf_egress);
|
||||
u->ip_bpf_ingress = bpf_program_free(u->ip_bpf_ingress);
|
||||
u->ip_bpf_egress = bpf_program_free(u->ip_bpf_egress);
|
||||
|
||||
u->ipv4_allow_map_fd = safe_close(u->ipv4_allow_map_fd);
|
||||
u->ipv4_deny_map_fd = safe_close(u->ipv4_deny_map_fd);
|
||||
@@ -601,7 +601,7 @@ static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set
|
||||
set_clear(*set);
|
||||
|
||||
STRV_FOREACH(bpf_fs_path, filter_paths) {
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *prog = NULL;
|
||||
int r;
|
||||
|
||||
r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &prog);
|
||||
@@ -657,25 +657,18 @@ static int attach_custom_bpf_progs(Unit *u, const char *path, int attach_type, S
|
||||
assert(u);
|
||||
|
||||
set_clear(*set_installed);
|
||||
set_ensure_allocated(set_installed, &bpf_program_hash_ops);
|
||||
|
||||
SET_FOREACH(prog, *set) {
|
||||
SET_FOREACH_MOVE(prog, *set_installed, *set) {
|
||||
r = bpf_program_cgroup_attach(prog, attach_type, path, BPF_F_ALLOW_MULTI);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Attaching custom egress BPF program to cgroup %s failed: %m", path);
|
||||
|
||||
/* Remember that these BPF programs are installed now. */
|
||||
r = set_ensure_put(set_installed, &bpf_program_hash_ops, prog);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m");
|
||||
|
||||
bpf_program_ref(prog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_firewall_install(Unit *u) {
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *ip_bpf_ingress_uninstall = NULL, *ip_bpf_egress_uninstall = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *ip_bpf_ingress_uninstall = NULL, *ip_bpf_egress_uninstall = NULL;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
CGroupContext *cc;
|
||||
int r, supported;
|
||||
@@ -719,8 +712,8 @@ int bpf_firewall_install(Unit *u) {
|
||||
/* If we don't have BPF_F_ALLOW_MULTI then unref the old BPF programs (which will implicitly
|
||||
* detach them) right before attaching the new program, to minimize the time window when we
|
||||
* don't account for IP traffic. */
|
||||
u->ip_bpf_egress_installed = bpf_program_unref(u->ip_bpf_egress_installed);
|
||||
u->ip_bpf_ingress_installed = bpf_program_unref(u->ip_bpf_ingress_installed);
|
||||
u->ip_bpf_egress_installed = bpf_program_free(u->ip_bpf_egress_installed);
|
||||
u->ip_bpf_ingress_installed = bpf_program_free(u->ip_bpf_ingress_installed);
|
||||
}
|
||||
|
||||
if (u->ip_bpf_egress) {
|
||||
@@ -729,7 +722,7 @@ int bpf_firewall_install(Unit *u) {
|
||||
return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path);
|
||||
|
||||
/* Remember that this BPF program is installed now. */
|
||||
u->ip_bpf_egress_installed = bpf_program_ref(u->ip_bpf_egress);
|
||||
u->ip_bpf_egress_installed = TAKE_PTR(u->ip_bpf_egress);
|
||||
}
|
||||
|
||||
if (u->ip_bpf_ingress) {
|
||||
@@ -737,12 +730,12 @@ int bpf_firewall_install(Unit *u) {
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path);
|
||||
|
||||
u->ip_bpf_ingress_installed = bpf_program_ref(u->ip_bpf_ingress);
|
||||
u->ip_bpf_ingress_installed = TAKE_PTR(u->ip_bpf_ingress);
|
||||
}
|
||||
|
||||
/* And now, definitely get rid of the old programs, and detach them */
|
||||
ip_bpf_egress_uninstall = bpf_program_unref(ip_bpf_egress_uninstall);
|
||||
ip_bpf_ingress_uninstall = bpf_program_unref(ip_bpf_ingress_uninstall);
|
||||
ip_bpf_egress_uninstall = bpf_program_free(ip_bpf_egress_uninstall);
|
||||
ip_bpf_ingress_uninstall = bpf_program_free(ip_bpf_ingress_uninstall);
|
||||
|
||||
r = attach_custom_bpf_progs(u, path, BPF_CGROUP_INET_EGRESS, &u->ip_bpf_custom_egress, &u->ip_bpf_custom_egress_installed);
|
||||
if (r < 0)
|
||||
@@ -806,7 +799,7 @@ int bpf_firewall_supported(void) {
|
||||
BPF_EXIT_INSN()
|
||||
};
|
||||
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *program = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *program = NULL;
|
||||
static int supported = -1;
|
||||
union bpf_attr attr;
|
||||
int r;
|
||||
@@ -936,10 +929,10 @@ void bpf_firewall_close(Unit *u) {
|
||||
u->ipv4_deny_map_fd = safe_close(u->ipv4_deny_map_fd);
|
||||
u->ipv6_deny_map_fd = safe_close(u->ipv6_deny_map_fd);
|
||||
|
||||
u->ip_bpf_ingress = bpf_program_unref(u->ip_bpf_ingress);
|
||||
u->ip_bpf_ingress_installed = bpf_program_unref(u->ip_bpf_ingress_installed);
|
||||
u->ip_bpf_egress = bpf_program_unref(u->ip_bpf_egress);
|
||||
u->ip_bpf_egress_installed = bpf_program_unref(u->ip_bpf_egress_installed);
|
||||
u->ip_bpf_ingress = bpf_program_free(u->ip_bpf_ingress);
|
||||
u->ip_bpf_ingress_installed = bpf_program_free(u->ip_bpf_ingress_installed);
|
||||
u->ip_bpf_egress = bpf_program_free(u->ip_bpf_egress);
|
||||
u->ip_bpf_egress_installed = bpf_program_free(u->ip_bpf_egress_installed);
|
||||
|
||||
u->ip_bpf_custom_ingress = set_free(u->ip_bpf_custom_ingress);
|
||||
u->ip_bpf_custom_egress = set_free(u->ip_bpf_custom_egress);
|
||||
|
||||
@@ -49,7 +49,7 @@ static void bpf_foreign_key_hash_func(const BPFForeignKey *p, struct siphash *h)
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_FULL(bpf_foreign_by_key_hash_ops,
|
||||
BPFForeignKey, bpf_foreign_key_hash_func, bpf_foreign_key_compare_func, free,
|
||||
BPFProgram, bpf_program_unref);
|
||||
BPFProgram, bpf_program_free);
|
||||
|
||||
static int attach_programs(Unit *u, const char *path, Hashmap* foreign_by_key, uint32_t attach_flags) {
|
||||
const BPFForeignKey *key;
|
||||
@@ -76,7 +76,7 @@ static int bpf_foreign_prepare(
|
||||
Unit *u,
|
||||
enum bpf_attach_type attach_type,
|
||||
const char *bpffs_path) {
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *prog = NULL;
|
||||
_cleanup_free_ BPFForeignKey *key = NULL;
|
||||
uint32_t prog_id;
|
||||
int r;
|
||||
|
||||
+3
-3
@@ -1170,7 +1170,7 @@ static void cgroup_apply_restrict_network_interfaces(Unit *u) {
|
||||
}
|
||||
|
||||
static int cgroup_apply_devices(Unit *u) {
|
||||
_cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
|
||||
_cleanup_(bpf_program_freep) BPFProgram *prog = NULL;
|
||||
const char *path;
|
||||
CGroupContext *c;
|
||||
CGroupDeviceAllow *a;
|
||||
@@ -1244,7 +1244,7 @@ static int cgroup_apply_devices(Unit *u) {
|
||||
policy = CGROUP_DEVICE_POLICY_STRICT;
|
||||
}
|
||||
|
||||
r = bpf_devices_apply_policy(prog, policy, any, path, &u->bpf_device_control_installed);
|
||||
r = bpf_devices_apply_policy(&prog, policy, any, path, &u->bpf_device_control_installed);
|
||||
if (r < 0) {
|
||||
static bool warned = false;
|
||||
|
||||
@@ -2767,7 +2767,7 @@ void unit_prune_cgroup(Unit *u) {
|
||||
u->cgroup_realized_mask = 0;
|
||||
u->cgroup_enabled_mask = 0;
|
||||
|
||||
u->bpf_device_control_installed = bpf_program_unref(u->bpf_device_control_installed);
|
||||
u->bpf_device_control_installed = bpf_program_free(u->bpf_device_control_installed);
|
||||
}
|
||||
|
||||
int unit_search_main_pid(Unit *u, pid_t *ret) {
|
||||
|
||||
+1
-1
@@ -770,7 +770,7 @@ Unit* unit_free(Unit *u) {
|
||||
|
||||
hashmap_free(u->bpf_foreign_by_key);
|
||||
|
||||
bpf_program_unref(u->bpf_device_control_installed);
|
||||
bpf_program_free(u->bpf_device_control_installed);
|
||||
|
||||
#if BPF_FRAMEWORK
|
||||
bpf_link_free(u->restrict_ifaces_ingress_bpf_link);
|
||||
|
||||
Reference in New Issue
Block a user