Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bfcli/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ set { return SET; }
counter { return COUNTER; }

/* Hooks */
BF_HOOK_[A-Z_]+ { BEGIN(STATE_HOOK_OPTS); yylval.sval = strdup(yytext); return HOOK; }
BF_HOOK_[A-Z0-9_]+ { BEGIN(STATE_HOOK_OPTS); yylval.sval = strdup(yytext); return HOOK; }
<STATE_HOOK_OPTS>{
(\{|,) /* Ignore */
\} { BEGIN(INITIAL); }
Expand Down
1 change: 1 addition & 0 deletions src/bpfilter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_executable(bpfilter
${CMAKE_CURRENT_SOURCE_DIR}/main.c
${CMAKE_CURRENT_SOURCE_DIR}/cgen/cgen.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/cgen.c
${CMAKE_CURRENT_SOURCE_DIR}/cgen/cgroup_skb.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/cgroup_skb.c
${CMAKE_CURRENT_SOURCE_DIR}/cgen/cgroup_sock_addr.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/cgroup_sock_addr.c
${CMAKE_CURRENT_SOURCE_DIR}/cgen/dump.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/dump.c
${CMAKE_CURRENT_SOURCE_DIR}/cgen/elfstub.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/elfstub.c
${CMAKE_CURRENT_SOURCE_DIR}/cgen/fixup.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/fixup.c
Expand Down
108 changes: 108 additions & 0 deletions src/bpfilter/cgen/cgroup_sock_addr.c
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;
}

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,
"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,
};
10 changes: 10 additions & 0 deletions src/bpfilter/cgen/cgroup_sock_addr.h
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;
4 changes: 3 additions & 1 deletion src/bpfilter/cgen/prog/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ int bf_link_new(struct bf_link **link, const char *name, enum bf_hook hook,
fd = r;
break;
case BF_FLAVOR_CGROUP_SKB:
case BF_FLAVOR_CGROUP_SOCK_ADDR:
cgroup_fd = open(_hookopts->cgpath, O_DIRECTORY | O_RDONLY);
if (cgroup_fd < 0) {
return bf_err_r(errno, "failed to open cgroup '%s'",
Expand All @@ -81,7 +82,7 @@ int bf_link_new(struct bf_link **link, const char *name, enum bf_hook hook,

r = bf_bpf_link_create(prog_fd, cgroup_fd, hook, 0, 0, 0);
if (r < 0)
return bf_err_r(r, "failed to create cgroup_skb BPF link");
return bf_err_r(r, "failed to create cgroup BPF link");

fd = r;
break;
Expand Down Expand Up @@ -291,6 +292,7 @@ int bf_link_update(struct bf_link *link, int prog_fd)
case BF_FLAVOR_XDP:
case BF_FLAVOR_TC:
case BF_FLAVOR_CGROUP_SKB:
case BF_FLAVOR_CGROUP_SOCK_ADDR:
r = bf_bpf_link_update(link->fd, prog_fd);
break;
case BF_FLAVOR_NF:
Expand Down
2 changes: 2 additions & 0 deletions src/bpfilter/cgen/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <bpfilter/verdict.h>

#include "cgen/cgroup_skb.h"
#include "cgen/cgroup_sock_addr.h"
#include "cgen/dump.h"
#include "cgen/fixup.h"
#include "cgen/handle.h"
Expand Down Expand Up @@ -82,6 +83,7 @@ static const struct bf_flavor_ops *bf_flavor_ops_get(enum bf_flavor flavor)
[BF_FLAVOR_NF] = &bf_flavor_ops_nf,
[BF_FLAVOR_XDP] = &bf_flavor_ops_xdp,
[BF_FLAVOR_CGROUP_SKB] = &bf_flavor_ops_cgroup_skb,
[BF_FLAVOR_CGROUP_SOCK_ADDR] = &bf_flavor_ops_cgroup_sock_addr,
};

static_assert_enum_mapping(flavor_ops, _BF_FLAVOR_MAX);
Expand Down
5 changes: 3 additions & 2 deletions src/bpfilter/cgen/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ struct bf_runtime
* - `BF_FLAVOR_XDP`: `struct xdp_md *`
* - `BF_FLAVOR_TC`: `struct struct __sk_buff *`
* - `BF_FLAVOR_CGROUP_SKB`: `struct __sk_buff *`
* - `BF_FLAVOR_NF`: `struct bpf_nf_ctx *` */
* - `BF_FLAVOR_NF`: `struct bpf_nf_ctx *`
* - `BF_FLAVOR_CGROUP_SOCK_ADDR`: `struct bpf_sock_addr *` */
void *arg;

/** BPF dynamic pointer to access the packet data. Dynamic pointers are
Expand All @@ -85,7 +86,7 @@ struct bf_runtime
/** Ring buffer map containing the logged packets. */
void *log_map;

/** Total size of the packet. */
/** Total size of the packet, or 0 for non-packet flavors. */
__u64 pkt_size;

/** IPv6 extension header mask */
Expand Down
21 changes: 10 additions & 11 deletions src/libbpfilter/chain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

if (bf_rule_mark_is_set(rule) &&
(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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're missing CGROUP_SOCK_ADDR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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) {
Expand All @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions src/libbpfilter/flavor.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const char *bf_flavor_to_str(enum bf_flavor flavor)
[BF_FLAVOR_NF] = "BF_FLAVOR_NF",
[BF_FLAVOR_XDP] = "BF_FLAVOR_XDP",
[BF_FLAVOR_CGROUP_SKB] = "BF_FLAVOR_CGROUP_SKB",
[BF_FLAVOR_CGROUP_SOCK_ADDR] = "BF_FLAVOR_CGROUP_SOCK_ADDR",
};
static_assert_enum_mapping(flavor_str, _BF_FLAVOR_MAX);

Expand Down
11 changes: 10 additions & 1 deletion src/libbpfilter/hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ static const char *_bf_hook_strs[] = {
[BF_HOOK_NF_LOCAL_OUT] = "BF_HOOK_NF_LOCAL_OUT",
[BF_HOOK_NF_POST_ROUTING] = "BF_HOOK_NF_POST_ROUTING",
[BF_HOOK_TC_EGRESS] = "BF_HOOK_TC_EGRESS",
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT4] = "BF_HOOK_CGROUP_SOCK_ADDR_CONNECT4",
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT6] = "BF_HOOK_CGROUP_SOCK_ADDR_CONNECT6",
};
static_assert_enum_mapping(_bf_hook_strs, _BF_HOOK_MAX);

Expand Down Expand Up @@ -73,6 +75,8 @@ enum bf_flavor bf_hook_to_flavor(enum bf_hook hook)
[BF_HOOK_NF_LOCAL_OUT] = BF_FLAVOR_NF,
[BF_HOOK_NF_POST_ROUTING] = BF_FLAVOR_NF,
[BF_HOOK_TC_EGRESS] = BF_FLAVOR_TC,
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT4] = BF_FLAVOR_CGROUP_SOCK_ADDR,
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT6] = BF_FLAVOR_CGROUP_SOCK_ADDR,
};

static_assert_enum_mapping(flavors, _BF_HOOK_MAX);
Expand All @@ -93,6 +97,8 @@ enum bf_bpf_attach_type bf_hook_to_bpf_attach_type(enum bf_hook hook)
[BF_HOOK_NF_LOCAL_OUT] = BF_BPF_NETFILTER,
[BF_HOOK_NF_POST_ROUTING] = BF_BPF_NETFILTER,
[BF_HOOK_TC_EGRESS] = BF_BPF_TCX_ENGRESS,
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT4] = BF_BPF_CGROUP_INET4_CONNECT,
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT6] = BF_BPF_CGROUP_INET6_CONNECT,
};

static_assert_enum_mapping(attach_types, _BF_HOOK_MAX);
Expand All @@ -113,6 +119,8 @@ enum bf_bpf_prog_type bf_hook_to_bpf_prog_type(enum bf_hook hook)
[BF_HOOK_NF_LOCAL_OUT] = BF_BPF_PROG_TYPE_NETFILTER,
[BF_HOOK_NF_POST_ROUTING] = BF_BPF_PROG_TYPE_NETFILTER,
[BF_HOOK_TC_EGRESS] = BF_BPF_PROG_TYPE_SCHED_CLS,
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT4] = BF_BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
[BF_HOOK_CGROUP_SOCK_ADDR_CONNECT6] = BF_BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
};

static_assert_enum_mapping(prog_types, _BF_HOOK_MAX);
Expand Down Expand Up @@ -359,7 +367,8 @@ static struct bf_hookopts_ops
.dump = _bf_hookopts_ifindex_dump},
[BF_HOOKOPTS_CGPATH] = {.name = "cgpath",
.type = BF_HOOKOPTS_CGPATH,
.required_by = BF_FLAGS(BF_FLAVOR_CGROUP_SKB),
.required_by = BF_FLAGS(BF_FLAVOR_CGROUP_SKB,
BF_FLAVOR_CGROUP_SOCK_ADDR),
.supported_by = 0,
.parse = _bf_hookopts_cgpath_parse,
.dump = _bf_hookopts_cgpath_dump},
Expand Down
3 changes: 3 additions & 0 deletions src/libbpfilter/include/bpfilter/bpf_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum bf_bpf_prog_type
BF_BPF_PROG_TYPE_XDP = 6,
BF_BPF_PROG_TYPE_SCHED_CLS = 3,
BF_BPF_PROG_TYPE_CGROUP_SKB = 8,
BF_BPF_PROG_TYPE_CGROUP_SOCK_ADDR = 18,
BF_BPF_PROG_TYPE_NETFILTER = 32,
};

Expand All @@ -39,6 +40,8 @@ enum bf_bpf_attach_type
BF_BPF_TCX_ENGRESS = 47,
BF_BPF_CGROUP_INET_INGRESS = 0,
BF_BPF_CGROUP_INET_EGRESS = 1,
BF_BPF_CGROUP_INET4_CONNECT = 10,
BF_BPF_CGROUP_INET6_CONNECT = 11,
};

enum bf_bpf_map_type
Expand Down
9 changes: 9 additions & 0 deletions src/libbpfilter/include/bpfilter/flavor.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ enum bf_flavor
* - Return code: 0 to drop, 1 to accept
*/
BF_FLAVOR_CGROUP_SKB,

/**
* cgroup_sock_addr BPF programs, attached to a cgroup to intercept
* socket operations (connect, bind, sendmsg, recvmsg):
* - Input: `struct bpf_sock_addr`
* - No packet data; L3/L4 protocol from socket metadata
* - Return code: 0 to drop, 1 to accept
*/
BF_FLAVOR_CGROUP_SOCK_ADDR,
_BF_FLAVOR_MAX,
};

Expand Down
4 changes: 3 additions & 1 deletion src/libbpfilter/include/bpfilter/hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ enum bf_hook
BF_HOOK_NF_LOCAL_OUT,
BF_HOOK_NF_POST_ROUTING,
BF_HOOK_TC_EGRESS,
BF_HOOK_CGROUP_SOCK_ADDR_CONNECT4,
BF_HOOK_CGROUP_SOCK_ADDR_CONNECT6,
_BF_HOOK_MAX,
};

Expand Down Expand Up @@ -139,7 +141,7 @@ struct bf_hookopts
// XDP and TC
int ifindex;

// cgroup_skb
// cgroup_skb and cgroup_sock_addr
const char *cgpath;

// Netfilter
Expand Down
Loading
Loading