From patchwork Mon Dec 4 23:39:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Nakryiko X-Patchwork-Id: 13479196 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mx0a-00082601.pphosted.com (mx0a-00082601.pphosted.com [67.231.145.42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E80210F for ; Mon, 4 Dec 2023 15:40:19 -0800 (PST) Received: from pps.filterd (m0109333.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 3B4KGl7X008058 for ; Mon, 4 Dec 2023 15:40:19 -0800 Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3urr81bfe2-10 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Mon, 04 Dec 2023 15:40:19 -0800 Received: from twshared29562.14.frc2.facebook.com (2620:10d:c0a8:1c::11) by mail.thefacebook.com (2620:10d:c0a8:83::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Mon, 4 Dec 2023 15:40:17 -0800 Received: by devbig019.vll3.facebook.com (Postfix, from userid 137359) id CE1B13C972752; Mon, 4 Dec 2023 15:40:04 -0800 (PST) From: Andrii Nakryiko To: , , , CC: , Subject: [PATCH bpf-next 13/13] selftests/bpf: add global subprog annotation tests Date: Mon, 4 Dec 2023 15:39:31 -0800 Message-ID: <20231204233931.49758-14-andrii@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231204233931.49758-1-andrii@kernel.org> References: <20231204233931.49758-1-andrii@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-GUID: sWhzJL7-AkzlcQavp9CEyqHDwCoZh8ea X-Proofpoint-ORIG-GUID: sWhzJL7-AkzlcQavp9CEyqHDwCoZh8ea X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-04_22,2023-12-04_01,2023-05-22_02 X-Patchwork-Delegate: bpf@iogearbox.net Add test cases to validate semantics of global subprog argument annotations: - non-null pointers; - context argument; - const dynptr passing; - packet pointers (data, metadata, end). Signed-off-by: Andrii Nakryiko Acked-by: Eduard Zingerman --- .../bpf/progs/verifier_global_subprogs.c | 134 +++++++++++++++++- 1 file changed, 130 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c index a0a5efd1caa1..9883d3e47130 100644 --- a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c +++ b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ -#include -#include -#include -#include +#include #include #include "bpf_misc.h" +#include "xdp_metadata.h" +#include "bpf_kfuncs.h" int arr[1]; int unkn_idx; @@ -89,4 +88,131 @@ int unguarded_unsupp_global_called(void) return global_unsupp(&x); } +long stack[128]; + +__weak int subprog_nullable_ptr_bad(int *p) +{ + return (*p) * 2; /* bad, missing null check */ +} + +SEC("?raw_tp") +__failure __log_level(2) +__msg("invalid mem access 'mem_or_null'") +int arg_tag_nullable_ptr_fail(void *ctx) +{ + int x = 42; + + return subprog_nullable_ptr_bad(&x); +} + +__noinline __weak int subprog_nonnull_ptr_good(int *p1 __arg_nonnull, int *p2 __arg_nonnull) +{ + return (*p1) * (*p2); /* good, no need for NULL checks */ +} + +int x = 47; + +SEC("?raw_tp") +__success __log_level(2) +int arg_tag_nonnull_ptr_good(void *ctx) +{ + int y = 74; + + return subprog_nonnull_ptr_good(&x, &y); +} + +/* this global subprog can be now called from many types of entry progs, each + * with different context type + */ +__weak int subprog_ctx_tag(void *ctx __arg_ctx) +{ + return bpf_get_stack(ctx, stack, sizeof(stack), 0); +} + +SEC("?raw_tp") +__success __log_level(2) +int arg_tag_ctx_raw_tp(void *ctx) +{ + return subprog_ctx_tag(ctx); +} + +SEC("?tp") +__success __log_level(2) +int arg_tag_ctx_tp(void *ctx) +{ + return subprog_ctx_tag(ctx); +} + +SEC("?kprobe") +__success __log_level(2) +int arg_tag_ctx_kprobe(void *ctx) +{ + return subprog_ctx_tag(ctx); +} + +__weak int subprog_pkt(void *ctx __arg_ctx, + void *pkt_meta __arg_pkt_meta, + void *pkt_data __arg_pkt_data, + void *pkt_end __arg_pkt_end) +{ + struct xdp_meta *meta; + + /* use pkt_data + pkt_end */ + if (pkt_data + 64 > pkt_end) + return XDP_DROP; + + if (*(u8 *)(pkt_data + 63) > 0) + return XDP_DROP; + + /* use pkt_meta + pkt_data */ + if (pkt_meta + sizeof(*meta) > pkt_data) + return XDP_DROP; + + meta = pkt_meta; + meta->rx_timestamp = 1; + + return XDP_PASS; +} + +SEC("?xdp") +__success __log_level(2) +int arg_tag_pkt_pointers(struct xdp_md *ctx) +{ + void *pkt_meta = (void *)(long)ctx->data_meta; + void *pkt_data = (void *)(long)ctx->data; + void *pkt_end = (void *)(long)ctx->data_end; + + return subprog_pkt(ctx, pkt_meta, pkt_data, pkt_end); +} + +__weak int subprog_dynptr(struct bpf_dynptr *dptr __arg_dynptr) +{ + long *d, t, buf[1] = {}; + + d = bpf_dynptr_data(dptr, 0, sizeof(long)); + if (!d) + return 0; + + t = *d + 1; + + d = bpf_dynptr_slice(dptr, 0, &buf, sizeof(long)); + if (!d) + return t; + + t = *d + 2; + + return t; +} + +SEC("?xdp") +__success __log_level(2) +int arg_tag_dynptr(struct xdp_md *ctx) +{ + struct bpf_dynptr dptr; + + bpf_dynptr_from_xdp(ctx, 0, &dptr); + + return subprog_dynptr(&dptr); +} + char _license[] SEC("license") = "GPL";