-
Notifications
You must be signed in to change notification settings - Fork 52
[2/3] Add CGROUP_SOCK_ADDR initial chain support
#459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| /* | ||
| * Copyright (c) Meta Platforms, Inc. and affiliates. | ||
| */ | ||
|
|
||
| #include "cgen/cgroup_sock_addr.h" | ||
|
|
||
| #include <linux/bpf.h> | ||
| #include <linux/bpf_common.h> | ||
| #include <linux/if_ether.h> | ||
|
|
||
| #include <assert.h> | ||
| #include <errno.h> | ||
| #include <stddef.h> | ||
| #include <sys/socket.h> | ||
|
|
||
| #include <bpfilter/flavor.h> | ||
| #include <bpfilter/logger.h> | ||
| #include <bpfilter/matcher.h> | ||
| #include <bpfilter/verdict.h> | ||
|
|
||
| #include "cgen/program.h" | ||
| #include "cgen/swich.h" | ||
| #include "filter.h" | ||
|
|
||
| // Forward definition to avoid header conflicts. | ||
| uint16_t htons(uint16_t hostshort); | ||
|
|
||
| static int _bf_cgroup_sock_addr_gen_inline_prologue(struct bf_program *program) | ||
| { | ||
| int r; | ||
|
|
||
| assert(program); | ||
|
|
||
| // The counters stub reads `pkt_size` unconditionally; zero it out. | ||
| EMIT(program, BPF_ST_MEM(BPF_DW, BPF_REG_10, BF_PROG_CTX_OFF(pkt_size), 0)); | ||
|
|
||
| /* Convert `bpf_sock_addr.family` to L3 protocol ID in R7, using the same | ||
| * `bf_swich` pattern as cgroup_skb. */ | ||
| EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | ||
| offsetof(struct bpf_sock_addr, family))); | ||
|
|
||
| { | ||
| _clean_bf_swich_ struct bf_swich swich = | ||
| bf_swich_get(program, BPF_REG_2); | ||
|
|
||
| EMIT_SWICH_OPTION(&swich, AF_INET, | ||
| BPF_MOV64_IMM(BPF_REG_7, htons(ETH_P_IP))); | ||
| EMIT_SWICH_OPTION(&swich, AF_INET6, | ||
| BPF_MOV64_IMM(BPF_REG_7, htons(ETH_P_IPV6))); | ||
| EMIT_SWICH_DEFAULT(&swich, BPF_MOV64_IMM(BPF_REG_7, 0)); | ||
|
|
||
| r = bf_swich_generate(&swich); | ||
| if (r) | ||
| return r; | ||
| } | ||
|
|
||
| EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1, | ||
| offsetof(struct bpf_sock_addr, protocol))); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int _bf_cgroup_sock_addr_gen_inline_epilogue(struct bf_program *program) | ||
| { | ||
| (void)program; | ||
|
|
||
| return 0; | ||
yaakov-stein marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| static int | ||
| _bf_cgroup_sock_addr_gen_inline_matcher(struct bf_program *program, | ||
| const struct bf_matcher *matcher) | ||
| { | ||
| assert(program); | ||
| assert(matcher); | ||
|
|
||
| (void)program; | ||
|
|
||
| return bf_err_r(-ENOTSUP, | ||
yaakov-stein marked this conversation as resolved.
Show resolved
Hide resolved
yaakov-stein marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "matcher '%s' not yet supported for cgroup_sock_addr", | ||
| bf_matcher_type_to_str(bf_matcher_get_type(matcher))); | ||
| } | ||
|
|
||
| /** | ||
| * @brief Convert a standard verdict into a return value. | ||
| * | ||
| * @param verdict Verdict to convert. Must be valid. | ||
| * @return Cgroup return code corresponding to the verdict, as an integer. | ||
| */ | ||
| static int _bf_cgroup_sock_addr_get_verdict(enum bf_verdict verdict) | ||
| { | ||
| switch (verdict) { | ||
| case BF_VERDICT_ACCEPT: | ||
| return 1; | ||
| case BF_VERDICT_DROP: | ||
| return 0; | ||
| default: | ||
| return -ENOTSUP; | ||
| } | ||
| } | ||
|
|
||
| const struct bf_flavor_ops bf_flavor_ops_cgroup_sock_addr = { | ||
| .gen_inline_prologue = _bf_cgroup_sock_addr_gen_inline_prologue, | ||
| .gen_inline_epilogue = _bf_cgroup_sock_addr_gen_inline_epilogue, | ||
| .get_verdict = _bf_cgroup_sock_addr_get_verdict, | ||
| .gen_inline_matcher = _bf_cgroup_sock_addr_gen_inline_matcher, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| /* | ||
| * Copyright (c) Meta Platforms, Inc. and affiliates. | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <bpfilter/flavor.h> | ||
|
|
||
| extern const struct bf_flavor_ops bf_flavor_ops_cgroup_sock_addr; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,14 +73,17 @@ int _bf_chain_check_rule(struct bf_chain *chain, struct bf_rule *rule) | |
| if (rule->log && !rule->disabled) | ||
| chain->flags |= BF_FLAG(BF_CHAIN_LOG); | ||
|
|
||
| if (rule->log && | ||
| bf_hook_to_flavor(chain->hook) == BF_FLAVOR_CGROUP_SOCK_ADDR) { | ||
| return bf_err_r(-ENOTSUP, "logging is not supported by %s", | ||
| bf_hook_to_str(chain->hook)); | ||
| } | ||
|
|
||
yaakov-stein marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (bf_rule_mark_is_set(rule) && | ||
yaakov-stein marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| (chain->hook == BF_HOOK_XDP || chain->hook == BF_HOOK_NF_PRE_ROUTING || | ||
| chain->hook == BF_HOOK_NF_POST_ROUTING || | ||
| chain->hook == BF_HOOK_NF_FORWARD || | ||
| chain->hook == BF_HOOK_NF_LOCAL_IN || | ||
| chain->hook == BF_HOOK_NF_LOCAL_OUT)) { | ||
| return bf_err_r(-EINVAL, | ||
| "XDP and Netfilter chains can't set packet mark"); | ||
| bf_hook_to_flavor(chain->hook) != BF_FLAVOR_TC && | ||
| bf_hook_to_flavor(chain->hook) != BF_FLAVOR_CGROUP_SKB) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're missing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This reverses the logic (now that fewer flavors allow for setting the mark than those that don't). So we're checking if it's not an allowed flavor |
||
| return bf_err_r(-EINVAL, "%s chains can't set packet mark", | ||
| bf_hook_to_str(chain->hook)); | ||
| } | ||
|
|
||
| bf_list_foreach (&rule->matchers, matcher_node) { | ||
|
|
@@ -92,10 +95,6 @@ int _bf_chain_check_rule(struct bf_chain *chain, struct bf_rule *rule) | |
| !rule->disabled) | ||
| chain->flags |= BF_FLAG(BF_CHAIN_STORE_NEXTHDR); | ||
|
|
||
| // Set matchers are compatible with all hooks. | ||
| if (bf_matcher_get_type(matcher) == BF_MATCHER_SET) | ||
| continue; | ||
|
|
||
| // Ensure the matcher is compatible with the chain's hook. | ||
| meta = bf_matcher_get_meta(bf_matcher_get_type(matcher)); | ||
| if (!meta) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.