Skip to content

Conversation

@weli-l
Copy link
Contributor

@weli-l weli-l commented Oct 26, 2024

What type of PR is this?

What this PR does / why we need it:
support xdp auth in tail call
Which issue(s) this PR fixes:
Fixes #

Special notes for your reviewer:

Does this PR introduce a user-facing change?:


@codecov
Copy link

codecov bot commented Oct 26, 2024

Codecov Report

Attention: Patch coverage is 15.78947% with 48 lines in your changes missing coverage. Please review.

Project coverage is 48.91%. Comparing base (f14f7d2) to head (e22e641).
Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
pkg/status/status_server.go 0.00% 34 Missing ⚠️
pkg/bpf/workload/xdp.go 50.00% 6 Missing and 3 partials ⚠️
pkg/bpf/bpf.go 0.00% 4 Missing ⚠️
pkg/controller/controller.go 0.00% 1 Missing ⚠️
Files with missing lines Coverage Δ
pkg/controller/controller.go 0.00% <0.00%> (ø)
pkg/bpf/bpf.go 37.30% <0.00%> (-0.15%) ⬇️
pkg/bpf/workload/xdp.go 48.27% <50.00%> (-0.30%) ⬇️
pkg/status/status_server.go 35.48% <0.00%> (-3.46%) ⬇️

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6cdc638...e22e641. Read the comment docs.

@lec-bit
Copy link
Contributor

lec-bit commented Oct 26, 2024

/retest

uint32(constants.TailCallPolicyCheck),
uint32(xa.PolicyCheck.FD()),
ebpf.UpdateAny); err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

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

In the case where only error is returned, is it possible to know if it is a policyCheck error or a ruleCheck error?

Copy link
Member

Choose a reason for hiding this comment

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

please add some more error info

@weli-l
Copy link
Contributor Author

weli-l commented Oct 27, 2024

/retest

__uint(key_size, sizeof(struct bpf_sock_tuple));
__uint(value_size, sizeof(struct match_ctx));
__uint(max_entries, 256);
} tailcall_info_map SEC(".maps");
Copy link
Member

Choose a reason for hiding this comment

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

suggest add kmesh prefix

Add __uint(map_flags, BPF_F_NO_PREALLOC);

Is 256 enough? I think we should greatly increase to support higher throughput if BPF_F_NO_PREALLOC set


// Safely access policyId and check if the policy exists
if (bpf_probe_read_kernel(&policyId, sizeof(policyId), (void *)(policies->policyIds + res->policy_index)) != 0) {
BPF_LOG(ERR, AUTH, "Failed to read policyId, thrown it to user auth");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
BPF_LOG(ERR, AUTH, "Failed to read policyId, thrown it to user auth");
BPF_LOG(ERR, AUTH, "Failed to read policyId, throw it to user auth");

if (bpf_probe_read_kernel(&policyId, sizeof(policyId), (void *)(policies->policyIds + res->policy_index)) != 0) {
BPF_LOG(ERR, AUTH, "Failed to read policyId, thrown it to user auth");
if (bpf_map_delete_elem(&tailcall_info_map, &tuple_key) != 0) {
BPF_LOG(DEBUG, AUTH, "Failed to delete context from map");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
BPF_LOG(DEBUG, AUTH, "Failed to delete context from map");
BPF_LOG(DEBUG, AUTH, "Failed to delete tailcall context from map");

return AUTH_DENY;
res = bpf_map_lookup_elem(&tailcall_info_map, &tuple_key);
if (!res) {
BPF_LOG(ERR, AUTH, "Failed to retrieve res from map");
Copy link
Member

Choose a reason for hiding this comment

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

please be more clear

BPF_LOG(ERR, AUTH, "Failed to retrieve match_ctx from map");
return XDP_PASS;
}
for (i = 0; i < MAX_MEMBER_NUM_PER_POLICY; i++) {
Copy link
Member

Choose a reason for hiding this comment

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

MAX_MEMBER_NUM_PER_POLICY does not only limit the policy numbers but also the rules number per policy, right?

int xdp_shutdown(struct xdp_md *ctx)
{
int ret = 0;
struct match_ctx res;
Copy link
Member

Choose a reason for hiding this comment

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

please rename

return AUTH_ALLOW;
} else {
return AUTH_DENY;
res->policy_index++;
Copy link
Member

Choose a reason for hiding this comment

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

should we move the policy index check here?

    if (res->policy_index < 0 || res->policy_index >= MAX_MEMBER_NUM_PER_POLICY) {
        BPF_LOG(ERR, AUTH, "Policy index out of bounds");
        return XDP_PASS;
    }

break;
}
rule = (Istio__Security__Rule *)kmesh_get_ptr_val((void *)*((__u64 *)rulesPtr + i));
if (!res) {
Copy link
Member

Choose a reason for hiding this comment

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

redundant check with line 342?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

redundant check with line 342?

In xdp type eBPF program, the null pointer check may fail. An additional check is needed here, otherwise the verifier will report an error.

static int construct_tuple_key(struct xdp_md *ctx, struct bpf_sock_tuple *tuple_info, struct xdp_info *info)
{
int ret = parser_xdp_info(ctx, info);
if (ret != PARSER_SUCC) {
Copy link
Member

Choose a reason for hiding this comment

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

redundant check

@weli-l
Copy link
Contributor Author

weli-l commented Nov 2, 2024

/retest

@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch from 2ff203f to 637d38e Compare November 4, 2024 01:55
if (bpf_map_delete_elem(&kmesh_tc_info_map, &tuple_key) != 0) {
BPF_LOG(DEBUG, AUTH, "Failed to delete tailcall context from map");
}
bpf_tail_call(ctx, &xdp_tailcall_map, TAIL_CALL_AUTH_IN_USER_SPACE);
Copy link
Contributor

Choose a reason for hiding this comment

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

This code has multiple calls in the function, can it converge to one place?:
bpf_map_delete_elem(&kmesh_tc_info_map, &tuple_key)
bpf_tail_call(ctx, &xdp_tailcall_map, TAIL_CALL_AUTH_IN_USER_SPACE);

}

static inline int match_check(Istio__Security__Match *match, struct xdp_info *info, struct bpf_sock_tuple *tuple_info)
static int match_check(Istio__Security__Match *match, struct xdp_info *info, struct bpf_sock_tuple *tuple_info)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why remove the inline here?

__uint(value_size, sizeof(struct match_context));
__uint(map_flags, BPF_F_NO_PREALLOC);
__uint(max_entries, MAP_SIZE_OF_AUTH_TAILCALL);
} kmesh_tc_info_map SEC(".maps");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
} kmesh_tc_info_map SEC(".maps");
} kmesh_tc_args SEC(".maps");

uint32(constants.TailCallPolicyCheck),
uint32(xa.PolicyCheck.FD()),
ebpf.UpdateAny); err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

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

please add some more error info


static inline int match_workload_policy(struct xdp_info *info, struct bpf_sock_tuple *tuple_info)
SEC("xdp_auth")
int xdp_shutdown(struct xdp_md *ctx)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int xdp_shutdown(struct xdp_md *ctx)
int xdp_authz(struct xdp_md *ctx)

}

static inline int match_workload_policy(struct xdp_info *info, struct bpf_sock_tuple *tuple_info)
SEC("xdp_auth")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
SEC("xdp_auth")
SEC("xdp_authz")

}
match_ctx.policies = policies;
match_ctx.policy_index = 0;
ret = bpf_map_update_elem(&kmesh_tc_info_map, &tuple_key, &match_ctx, BPF_ANY);
Copy link
Member

Choose a reason for hiding this comment

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

here we write a ctx to this map, and in the another place this ctx could be read , is it safe to access policies concurrently?


static inline int
do_auth(Istio__Security__Authorization *policy, struct xdp_info *info, struct bpf_sock_tuple *tuple_info)
SEC("xdp_auth")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
SEC("xdp_auth")
SEC("xdp_authz")

@weli-l
Copy link
Contributor Author

weli-l commented Nov 8, 2024

A switch needs to be added to determine whether to enable link-level authentication or packet-based authentication.

@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch 2 times, most recently from 2acab18 to 68a44df Compare November 9, 2024 02:52
@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch 4 times, most recently from 2d5c667 to 9380fa6 Compare November 13, 2024 01:43
@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch from 9380fa6 to f558a42 Compare November 13, 2024 01:51
@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch from 669dd29 to 949a4af Compare November 13, 2024 08:11
@hzxuzhonghu
Copy link
Member

It is painful for me to review such a big pr with round and round update/review. We should incrementallly update. Never force push

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__uint(max_entries, 4);
Copy link
Member

Choose a reason for hiding this comment

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

return PARSER_SUCC;
}

static int matchDstPorts(Istio__Security__Match *match, struct xdp_info *info, struct bpf_sock_tuple *tuple_info)
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be called match_dst_port

__u32 i;

if (match->n_destination_ports == 0 && match->n_not_destination_ports == 0) {
BPF_LOG(DEBUG, AUTH, "No ports configured, matching by default");
Copy link
Member

Choose a reason for hiding this comment

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

log should be started with small cased word

__u32 i;

if (rule->n_clauses == 0) {
BPF_LOG(ERR, AUTH, "rule has no clauses\n");
Copy link
Member

Choose a reason for hiding this comment

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

this is not an error, it is a valid case to have {}

struct xdp_info info = {0};
int ret;

if (construct_tuple_key(ctx, &tuple_key, &info) != PARSER_SUCC) {
Copy link
Member

Choose a reason for hiding this comment

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

instead of parsing this everywhere, can we move the parsed res into kmesh_tc_args

int ret;
int i;

if (construct_tuple_key(ctx, &tuple_key, &info) != PARSER_SUCC) {
Copy link
Member

Choose a reason for hiding this comment

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

ditto if we add to the kmesh_tc_args, we will not need to parse again

return XDP_DROP;
}

static bool is_authz_enabled()
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
static bool is_authz_enabled()
static bool is_authz_offload_enabled()

if (bpf_map_update_elem(&map_of_auth, &tuple_key, &auth_result, BPF_ANY) != 0) {
BPF_LOG(ERR, AUTH, "Failed to update auth result in map_of_auth");
}
return match_ctx->action == ISTIO__SECURITY__ACTION__DENY ? XDP_DROP : XDP_PASS;
Copy link
Member

Choose a reason for hiding this comment

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

this logic is not correct. Say we have two authorizationPolicy set, wih the returned result, i think we may miss the second policy check

Signed-off-by: weli-l <1289113577@qq.com>
Signed-off-by: weli-l <1289113577@qq.com>
Signed-off-by: weli-l <1289113577@qq.com>
Signed-off-by: weli-l <1289113577@qq.com>
Signed-off-by: weli-l <1289113577@qq.com>
@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch from 949a4af to cc2168d Compare November 18, 2024 03:19
Signed-off-by: weli-l <1289113577@qq.com>
@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch 2 times, most recently from 7851592 to 88af784 Compare November 18, 2024 08:34
Signed-off-by: weli-l <1289113577@qq.com>
@weli-l weli-l force-pushed the dev/auth_multi_tailcall branch from 88af784 to 7161af5 Compare November 18, 2024 09:04
Signed-off-by: weli-l <1289113577@qq.com>
Copy link
Member

@hzxuzhonghu hzxuzhonghu left a comment

Choose a reason for hiding this comment

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

/lgtm

@kmesh-bot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: hzxuzhonghu

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kmesh-bot kmesh-bot merged commit 7b5abca into kmesh-net:main Nov 18, 2024
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants