From nobody Fri Oct 2 08:24:48 2026 Received: from out-171.mta1.migadu.com (out-171.mta1.migadu.com [95.215.58.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C990836923B for ; Mon, 3 Aug 2026 16:51:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775902; cv=none; b=QSrXDyw90O9Z2/UKx8mUBp8o2l1zheePz8beccFg7oFBRvxWD8qJ+SlM8hSXzK3llL7g3ttfvDVFSJIcd3dzWQnK/hGDijl99lW3s0s4EwG9AoB/Ut068haoa7nR4Ne7xcmgyHXQVlM4buLgZot4BzEkti2h6vtEXT4y9bVyHRs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775902; c=relaxed/simple; bh=ZRg+ZYHrpKdKwv0IAMlmZLgdkJd2nb5sieMoGxIA6bk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gtpVhxpPnYTbCe8aWshJ0A0Py+ky+i6wfa1e20nkayWhFTU6iXyNf6vOSPAEbjABooPFpIqiHkZXxKNo6cPSpigUpd/xTbueR5b2ZsU1/1uEI3NqC9zg2PIhsI5qVCtClRWzPLtgZs2gdW0gl1zMKJl5EppVYN0vc+1YD9/wLnw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=k0lshOJ7; arc=none smtp.client-ip=95.215.58.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="k0lshOJ7" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1785775897; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eBlLxE+fYfxpXqzS45PMr1YuPhCVWYb35QGSfAmvVkQ=; b=k0lshOJ7YzTvRvGhyBNDXWpWILzV9URYkhPTsWNRoLV+KXr/iAi83jqTG05ME8LhgkqO+B Qm/jR/XQw4KuN/mum9i+UpYNhU8DL+SvfwV+NzpEW+jvecgpi5HvsYQYbMLgU6boVJiTxp Tt+SbIj1eh31ahxd2t4rrXqoHa6Uf60= From: Vineet Gupta To: bpf@gcc.gnu.org, ast@kernel.org, Eduard Zingerman , Andrii Nakryiko , Ihor Solodrai Cc: linux-kernel@vger.kernel.org, Vineet Gupta Subject: [bpf-next 1/4] selftests/bpf: map_kptr: force BPF_STX for the scalar store to kptr Date: Mon, 3 Aug 2026 09:51:19 -0700 Message-ID: <20260803165122.1884825-2-vineet.gupta@linux.dev> In-Reply-To: <20260803165122.1884825-1-vineet.gupta@linux.dev> References: <20260803165122.1884825-1-vineet.gupta@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" reject_scalar_store_to_kptr stores a scalar constant to a kptr field: *(volatile u64 *)&v->unref_ptr =3D 0xBADC0DE; Compilers generate one of two encodings for that: 1. Materialize the constant into a register and emit BPF_STX: r1 =3D 0xbadc0de *(u64 *)(r0 + 0x8) =3D r1 2. Or fold it into a single BPF_ST (store immediate): *(u64 *)(r0 + 0x8) =3D 0xbadc0de check_map_kptr_access() rejects both, but through very different checks. BPF_STX goes through map_kptr_match_type(), whose first test is base_type(reg->type) !=3D PTR_TO_BTF_ID - the scalar rejection this test is named for - and which prints "invalid kptr access, R...". BPF_ST only gets the trivial "BPF_ST imm must be 0 when storing to kptr" immediate check and never reaches map_kptr_match_type() at all. So on a compiler that folds the constant - bpf-gcc, and clang from -mcpu=3Dv4, which enabled BPF_ST around v4 support due to historical verifier limitations - the test fails against its expected message. Widening the __msg to accept either message would make it pass again, but on those toolchains it would then only re-test the imm !=3D 0 path, which verifier/map_kptr.c ("map_kptr: BPF_ST imm !=3D 0") already covers, and the scalar-vs-PTR_TO_BTF_ID check would lose its only test in the tree. Route the value through barrier_var() instead, so the store stays a BPF_STX everywhere and the test keeps asserting what it was written to assert. clang -mcpu=3Dv1..v4 and bpf-gcc 16.1 all emit the register form afterwards. bpf-gcc, before: #229/20 map_kptr/reject_scalar_store_to_kptr:FAIL bpf-gcc, after : #229/20 map_kptr/reject_scalar_store_to_kptr:OK Signed-off-by: Vineet Gupta --- tools/testing/selftests/bpf/progs/map_kptr_fail.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/progs/map_kptr_fail.c b/tools/test= ing/selftests/bpf/progs/map_kptr_fail.c index f11848dfa78f..cb84e23b83c0 100644 --- a/tools/testing/selftests/bpf/progs/map_kptr_fail.c +++ b/tools/testing/selftests/bpf/progs/map_kptr_fail.c @@ -390,13 +390,22 @@ __failure __msg("invalid kptr access, R") int reject_scalar_store_to_kptr(struct __sk_buff *ctx) { struct map_value *v; + u64 val =3D 0xBADC0DE; int key =3D 0; =20 v =3D bpf_map_lookup_elem(&array_map, &key); if (!v) return 0; =20 - *(volatile u64 *)&v->unref_ptr =3D 0xBADC0DE; + /* + * Keep the value in a register so this stays a BPF_STX and keeps + * exercising map_kptr_match_type(). Compilers that fold the constant + * into a BPF_ST (store immediate) instead - bpf-gcc, and clang from + * -mcpu=3Dv4 - would be rejected by the far weaker "BPF_ST imm must be + * 0" check, which verifier/map_kptr.c already covers. + */ + barrier_var(val); + *(volatile u64 *)&v->unref_ptr =3D val; return 0; } =20 --=20 2.55.0 From nobody Fri Oct 2 08:24:48 2026 Received: from out-183.mta1.migadu.com (out-183.mta1.migadu.com [95.215.58.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D57838734E for ; Mon, 3 Aug 2026 16:51:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.183 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775903; cv=none; b=IOVMZXXpMwRpyJjvJ78f6EJHjoPPUW8GuUdTVECIaNpvbCx08MC77l+sTRVkmeoi9ZQVKGSbcqlxiaqs6aPzDgBEEQWW6a9rSD9c7a0Xw8P9nxDYOJVnfVHG1L5ARFLYNYSIw44cOYdhO+955WSkyE/YXnhDOxNDJ9h86HnsjW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775903; c=relaxed/simple; bh=PntVbVoJ3cP5UK/Pf1vcwbAos9ji3QPpXIrkcKvezDc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ji+KqAS+EBcHJdwyT7ASGI5bdg0i7q5ziHD9R1C2uNKGu+Sv0v6PUa1fdor+wQwbraGcp1NqL+1dRdEw4hT3d+7+yMlnwLSHkaK66Q5mGwBcYIhU1NiUj9r+Xdr+ptV4+VPEFSZ/p1zaIS1yN03+PPaWGVgTiv5YjmTJLLxOmYs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=vDYSI1Uu; arc=none smtp.client-ip=95.215.58.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="vDYSI1Uu" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1785775899; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=G6aMs96tVFxUGKFV9Stb3Pdz8RGhtrcoFiiFq+FcCd4=; b=vDYSI1Uuagwh4bWK1FFtsaPanH9odXVYh6e0DzN/P1PoIXzE/41aZ3QXp5fK07cCAC2MSx JfybptdkGin+wAQeue/e9nt2nOWFK60Zkp6+qFkxhbU5f8uHUw/dBYKQc847gHMTphsZTL TuhoDtWU9dDv5cbDRIkikwR/28f6EvY= From: Vineet Gupta To: bpf@gcc.gnu.org, ast@kernel.org, Eduard Zingerman , Andrii Nakryiko , Ihor Solodrai Cc: linux-kernel@vger.kernel.org, Vineet Gupta Subject: [bpf-next 2/4] selftests/bpf: add --no-error-summary to skip end-of-run error log dump Date: Mon, 3 Aug 2026 09:51:20 -0700 Message-ID: <20260803165122.1884825-3-vineet.gupta@linux.dev> In-Reply-To: <20260803165122.1884825-1-vineet.gupta@linux.dev> References: <20260803165122.1884825-1-vineet.gupta@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" By default test_progs re-prints the aggregated error logs of all failed tests at the end of the run (when not in verbose mode), starting with "All error logs:". With bpf-gcc the current failures and a couple runaway 1M fails cause a huge print overhead/delay at the end. Add a subtractive --no-error-summary flag, gated on a new env.error_summary field which defaults to true, so the default behavior is unchanged. Passing --no-error-summary suppresses the final "All error logs:" dump. Only the human readable output is elided. dump_test_log() also emits the per-test and per-subtest entries of the --json-summary "results" array, so it keeps being called (via a new @quiet argument) and the JSON report is bit for bit what it was before. Signed-off-by: Vineet Gupta --- tools/testing/selftests/bpf/test_progs.c | 41 ++++++++++++++++-------- tools/testing/selftests/bpf/test_progs.h | 1 + 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selft= ests/bpf/test_progs.c index aa06bab30966..8ee46745e2e8 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -424,10 +424,12 @@ static void jsonw_write_log_message(json_writer_t *w,= char *log_buf, size_t log_ } } =20 +/* @quiet elides the human readable output, the JSON report is unaffected = */ static void dump_test_log(const struct prog_test_def *test, const struct test_state *test_state, bool skip_ok_subtests, bool par_exec_result, + bool quiet, json_writer_t *w) { bool test_failed =3D test_state->error_cnt > 0; @@ -449,7 +451,7 @@ static void dump_test_log(const struct prog_test_def *t= est, if (verbose() && !par_exec_result) return; =20 - if (test_state->log_cnt && print_test) + if (test_state->log_cnt && print_test && !quiet) print_test_log(test_state->log_buf, test_state->log_cnt); =20 if (w && print_test) { @@ -471,15 +473,16 @@ static void dump_test_log(const struct prog_test_def = *test, if ((skip_ok_subtests && !subtest_failed) || subtest_filtered) continue; =20 - if (subtest_state->log_cnt && print_subtest) { + if (subtest_state->log_cnt && print_subtest && !quiet) { print_test_log(subtest_state->log_buf, subtest_state->log_cnt); } =20 - print_subtest_name(test->test_num, i + 1, - test->test_name, subtest_state->name, - test_result(subtest_state->error_cnt, - subtest_state->skipped)); + if (!quiet) + print_subtest_name(test->test_num, i + 1, + test->test_name, subtest_state->name, + test_result(subtest_state->error_cnt, + subtest_state->skipped)); =20 if (w && print_subtest) { jsonw_start_object(w); @@ -496,7 +499,8 @@ static void dump_test_log(const struct prog_test_def *t= est, jsonw_end_object(w); } =20 - print_test_result(test, test_state); + if (!quiet) + print_test_result(test, test_state); } =20 /* A bunch of tests set custom affinity per-thread and/or per-process. Res= et @@ -899,6 +903,7 @@ enum ARG_KEYS { ARG_JSON_SUMMARY =3D 'J', ARG_TRAFFIC_MONITOR =3D 'm', ARG_WATCHDOG_TIMEOUT =3D 'w', + ARG_NO_ERROR_SUMMARY =3D -2, }; =20 static const struct argp_option opts[] =3D { @@ -931,6 +936,8 @@ static const struct argp_option opts[] =3D { #endif { "watchdog-timeout", ARG_WATCHDOG_TIMEOUT, "SECONDS", 0, "Kill the process if tests are not making progress for specified number= of seconds." }, + { "no-error-summary", ARG_NO_ERROR_SUMMARY, NULL, 0, + "Do not re-print the aggregated error logs of failed tests at the end o= f the run." }, {}, }; =20 @@ -1132,6 +1139,9 @@ static error_t parse_arg(int key, char *arg, struct a= rgp_state *state) case ARG_DEBUG: env->debug =3D true; break; + case ARG_NO_ERROR_SUMMARY: + env->error_summary =3D false; + break; case ARG_JSON_SUMMARY: env->json =3D fopen(arg, "w"); if (env->json =3D=3D NULL) { @@ -1304,7 +1314,7 @@ static void dump_crash_log(void) =20 if (env.test) { env.test_state->error_cnt++; - dump_test_log(env.test, env.test_state, true, false, NULL); + dump_test_log(env.test, env.test_state, true, false, false, NULL); } } =20 @@ -1462,7 +1472,7 @@ static void run_one_test(int test_num) =20 free(stop_libbpf_log_capture()); =20 - dump_test_log(test, state, false, false, NULL); + dump_test_log(test, state, false, false, false, NULL); } =20 struct dispatch_data { @@ -1623,7 +1633,7 @@ static void *dispatch_thread(void *ctx) } while (false); =20 pthread_mutex_lock(&stdout_output_lock); - dump_test_log(test, state, false, true, NULL); + dump_test_log(test, state, false, true, false, NULL); pthread_mutex_unlock(&stdout_output_lock); } /* while (true) */ error: @@ -1686,9 +1696,12 @@ static void calculate_summary_and_print_errors(struc= t test_env *env) * We only print error logs summary when there are failed tests and * verbose mode is not enabled. Otherwise, results may be inconsistent. * + * --no-error-summary only elides the human readable dump: the walk + * still happens so the JSON report keeps its per-test results. */ - if (!verbose() && fail_cnt) { - printf("\nAll error logs:\n"); + if (!verbose() && fail_cnt && (env->error_summary || w)) { + if (env->error_summary) + printf("\nAll error logs:\n"); =20 /* print error logs again */ for (i =3D 0; i < prog_test_cnt; i++) { @@ -1698,7 +1711,8 @@ static void calculate_summary_and_print_errors(struct= test_env *env) if (!state->tested || !state->error_cnt) continue; =20 - dump_test_log(test, state, true, true, w); + dump_test_log(test, state, true, true, + !env->error_summary, w); } } =20 @@ -2028,6 +2042,7 @@ int main(int argc, char **argv) =20 env.secs_till_notify =3D 10; env.secs_till_kill =3D 120; + env.error_summary =3D true; err =3D argp_parse(&argp, argc, argv, 0, NULL, &env); if (err) return err; diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selft= ests/bpf/test_progs.h index 2cf950afcd85..e66d5c457901 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -105,6 +105,7 @@ struct test_env { struct test_selector tmon_selector; bool verifier_stats; bool debug; + bool error_summary; enum verbosity verbosity; =20 bool jit_enabled; --=20 2.55.0 From nobody Fri Oct 2 08:24:48 2026 Received: from out-188.mta1.migadu.com (out-188.mta1.migadu.com [95.215.58.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 006FC38E8A2 for ; Mon, 3 Aug 2026 16:51:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775904; cv=none; b=usArh93/J5NFHv2LS0J0vg8AtxB4MANQel+4OIFVgqs/crXaZ6DBJ6usDbMf99oIgJPVhExMl8XbTlCfSS9+fRUkqn99/BiayxC98xmISNUxtddkC4rVXB8gMS6HQThV+aWhL2Ew4rq0FlV968Nbi7KALEppswfbB/MeRnUKhzw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775904; c=relaxed/simple; bh=YueUsyAPM50kr+tvjkqG3/IXAA21hvRsOkbvnXAcEk0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iLjlMG/yyAwiUPZuYRVE964eQUWCHSoJcPKbXQKqGn2kiBL2kapSIc8Y6jids7vEPLTDc3V45A2pJdJJKh1YzA88mGdHCXfKwHNWrIF51N3pj6mvtbmC4mW8AnPPUWZvOqGWrK9pFy/QbZatF4/HnBSjvPPHwKlPELrpYwYdQgc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=OZNVnlQz; arc=none smtp.client-ip=95.215.58.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="OZNVnlQz" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1785775900; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xJo3x4oawUqd8sXksvOFjNdRI29zIVI6gG2AIfHhMaU=; b=OZNVnlQzc3mcrIBH+cevf9uGFUEejFgP9wuhX02gpQTZ5gAnEUXTfeYb0d1EgtCB9FKhIk meKPaDsKJ9gAzJ7Yi0SQ8/dOWNvMy3zO0GGUZ1FERvhxPeDSnTuExa0m9pOT6tbhEO3lOu jO8uVjjIuPzL9d8Hx/KqvPHugtyFqBw= From: Vineet Gupta To: bpf@gcc.gnu.org, ast@kernel.org, Eduard Zingerman , Andrii Nakryiko , Ihor Solodrai Cc: linux-kernel@vger.kernel.org, Vineet Gupta Subject: [bpf-next 3/4] selftests/bpf: report failed subtest count in test_progs summary Date: Mon, 3 Aug 2026 09:51:21 -0700 Message-ID: <20260803165122.1884825-4-vineet.gupta@linux.dev> In-Reply-To: <20260803165122.1884825-1-vineet.gupta@linux.dev> References: <20260803165122.1884825-1-vineet.gupta@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" The final summary line is asymmetric: the PASSED field reports both the number of top-level tests and the number of subtests within them, while the FAILED field reports only top-level tests: Summary: 640/5750 PASSED, 7760 SKIPPED, 100 FAILED There is no way to tell whether those 100 failing tests amount to 100 broken subtests or 1000. So count subtests with a non-zero error_cnt into a new sub_fail_cnt and print it alongside fail_cnt: Summary: 640/5750 PASSED, 7760 SKIPPED, 100/342 FAILED ^^^^^ This is correct for -j runs, as subtest_states[] is populated both in sequential and parallel modes. A test that fails without declaring any subtests contributes 0 to sub_fail_cnt. That mirrors the existing behaviour of sub_succ_cnt for tests that pass without subtests, keeping the two numerators comparable. Also emit the new count as a "failed_subtest" field in the JSON output, for parity with the existing "success_subtest". Note that this changes the trailing field of the summary line from a bare integer to "A/B", so anything scraping "N FAILED" out of it needs updating. While here, fix the fail_cnt comment in struct test_env, which claims it counts "total failed tests + sub-tests". Signed-off-by: Vineet Gupta --- tools/testing/selftests/bpf/test_progs.c | 21 +++++++++++++-------- tools/testing/selftests/bpf/test_progs.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selft= ests/bpf/test_progs.c index 8ee46745e2e8..5e2f6ec2e212 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -1656,8 +1656,8 @@ static void *dispatch_thread(void *ctx) =20 static void calculate_summary_and_print_errors(struct test_env *env) { - int i; - int succ_cnt =3D 0, fail_cnt =3D 0, sub_succ_cnt =3D 0, skip_cnt =3D 0; + int i, j; + int succ_cnt =3D 0, fail_cnt =3D 0, sub_succ_cnt =3D 0, sub_fail_cnt =3D = 0, skip_cnt =3D 0; json_writer_t *w =3D NULL; =20 for (i =3D 0; i < prog_test_cnt; i++) { @@ -1670,10 +1670,14 @@ static void calculate_summary_and_print_errors(stru= ct test_env *env) sub_succ_cnt +=3D state->sub_succ_cnt; skip_cnt +=3D state->skip_cnt; =20 - if (state->error_cnt) + if (state->error_cnt) { fail_cnt++; - else if (!test->not_built) + for (j =3D 0; j < state->subtest_num; j++) + if (state->subtest_states[j].error_cnt) + sub_fail_cnt++; + } else if (!test->not_built) { succ_cnt++; + } } =20 if (env->json) { @@ -1688,6 +1692,7 @@ static void calculate_summary_and_print_errors(struct= test_env *env) jsonw_uint_field(w, "success_subtest", sub_succ_cnt); jsonw_uint_field(w, "skipped", skip_cnt); jsonw_uint_field(w, "failed", fail_cnt); + jsonw_uint_field(w, "failed_subtest", sub_fail_cnt); jsonw_name(w, "results"); jsonw_start_array(w); } @@ -1726,12 +1731,12 @@ static void calculate_summary_and_print_errors(stru= ct test_env *env) fclose(env->json); =20 if (env->not_built_cnt) - printf("Summary: %d/%d PASSED, %d SKIPPED (%d not built), %d FAILED\n", + printf("Summary: %d/%d PASSED, %d SKIPPED (%d not built), %d/%d FAILED\n= ", succ_cnt, sub_succ_cnt, skip_cnt, env->not_built_cnt, - fail_cnt); + fail_cnt, sub_fail_cnt); else - printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n", - succ_cnt, sub_succ_cnt, skip_cnt, fail_cnt); + printf("Summary: %d/%d PASSED, %d SKIPPED, %d/%d FAILED\n", + succ_cnt, sub_succ_cnt, skip_cnt, fail_cnt, sub_fail_cnt); =20 env->succ_cnt =3D succ_cnt; env->sub_succ_cnt =3D sub_succ_cnt; diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selft= ests/bpf/test_progs.h index e66d5c457901..ea493c477fbd 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -124,7 +124,7 @@ struct test_env { =20 int succ_cnt; /* successful tests */ int sub_succ_cnt; /* successful sub-tests */ - int fail_cnt; /* total failed tests + sub-tests */ + int fail_cnt; /* failed tests */ int skip_cnt; /* skipped tests */ int not_built_cnt; /* tests not built */ =20 --=20 2.55.0 From nobody Fri Oct 2 08:24:48 2026 Received: from out-171.mta1.migadu.com (out-171.mta1.migadu.com [95.215.58.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B60E33937F for ; Mon, 3 Aug 2026 16:51:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775906; cv=none; b=d1vkuPFR8ot7whwBuc24wpU1AiMIV9D4GCezzxtI9N8qzIsChWUD9r9rDNPdcwKXPQUmnOFEgB+GWruj/PZeMloi0qt67L0604uHODmrA5h8AifYpJ+spVnhaS9IZG9oUjWI8vrquqNBKKFMKAtBdJpaJGUsbVsuBfjMre9A/vE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785775906; c=relaxed/simple; bh=AomQnBJrOabZeFIgszGdHUBOPU2NS3CZgOB9fea5+CE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nDlUsIkZ8omLCXbqbARuzvwUMqtkXQJrZZFrRH17MUW1o0DAZB8yhZmVzpcLIb6Tz4Hyfjn83vhGcbMLQxjDuZw9cSEsSV7WVB0Tny51jMGPIsfUM7sshqzgB2DusHfKNDsVnf9Uuh/dU7KBTEdLxF08+PKu5sAXrQUxWm66vgs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=rXH2D6Vv; arc=none smtp.client-ip=95.215.58.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="rXH2D6Vv" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1785775902; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mkwIs7oH/Bj4wRZsMV4sV1xxa0iYAnaHv7HnajZqz60=; b=rXH2D6Vv5N2KvAEvYZIAqbBiNggXFP6ZQhfRHyMk/I00BzvGsCaGFnITjUgAHpaPdTjIMz IqPrgz+/aEbEga5y5n5QrxgLIJxMuN2yYdV8U6G+eHts9BkOnNSYIHESe1WD/776yEcYVR okPJkApenEkUNGbhFQhXojiYr2EcWBM= From: Vineet Gupta To: bpf@gcc.gnu.org, ast@kernel.org, Eduard Zingerman , Andrii Nakryiko , Ihor Solodrai Cc: linux-kernel@vger.kernel.org, Vineet Gupta Subject: [bpf-next 4/4] selftests/bpf: vmtest.sh: preserve command quoting when running in the VM Date: Mon, 3 Aug 2026 09:51:22 -0700 Message-ID: <20260803165122.1884825-5-vineet.gupta@linux.dev> In-Reply-To: <20260803165122.1884825-1-vineet.gupta@linux.dev> References: <20260803165122.1884825-1-vineet.gupta@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" vmtest.sh captures the trailing command with command=3D"$@", which flattens the arguments into a single space-separated string, and then pastes it into the generated guest init script: cd /root/bpf echo ${command} stdbuf -oL -eL ${command} That here-doc is unquoted, so the host expands ${command} and the flattened text lands in the script verbatim. The guest bash then parses those lines as shell source, re-splitting the text on whitespace and glob-expanding it against /root/bpf. As a result any command with a glob or an argument containing spaces is corrupted before it reaches the test binary. For example: vmtest.sh -- ./test_progs -a 'verifier_*' has 'verifier_*' expanded in the guest into the matching object/skeleton files (verifier_align.bpf.o verifier_align.skel.h ...), so test_progs is handed a list of filenames instead of the intended name filter and runs no matching tests. Quote each argument with printf '%q ' so the command is reproduced verbatim inside the VM: the escaped text goes through exactly one round of quote removal when the guest parses the init script, yielding the original argv with globs and special characters intact. The common case (e.g. -t ) is unaffected. Only do this when there is a command to quote. printf '%q ' with no arguments still applies the format once and emits '', which the -s (debug shell) path would take for a real command and try to run. Note this makes the trailing command strictly an argv rather than a shell snippet: passing it pre-quoted as one word, e.g. vmtest.sh -- "./test_progs -t foo" no longer works, and neither does embedding guest-side shell syntax such as ';' or a redirection. Neither form is documented - usage() and README.rst both show the command unquoted - and 'sh -c ...' still works. Fixes: c9709f52386d ("bpf: Helper script for running BPF presubmit tests") Signed-off-by: Vineet Gupta --- tools/testing/selftests/bpf/vmtest.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/vmtest.sh b/tools/testing/selftest= s/bpf/vmtest.sh index 9ca802285393..6a3d026d76bd 100755 --- a/tools/testing/selftests/bpf/vmtest.sh +++ b/tools/testing/selftests/bpf/vmtest.sh @@ -428,8 +428,17 @@ main() =20 if [[ $# -eq 0 && "${debug_shell}" =3D=3D "no" ]]; then echo "No command specified, will run ${DEFAULT_COMMAND} in the vm" - else - command=3D"$@" + elif [[ $# -gt 0 ]]; then + # Quote each argument so the command survives into the guest: the + # host expands ${command} into the generated init script, which + # the guest bash then parses as shell source. Without the %q + # escapes an argument with a space or a glob (e.g. -a 'verifier_*') + # is re-split and expanded against /root/bpf there. + # + # Skip this when there is no command: printf '%q ' would still + # apply the format once and emit '', which is not the empty + # command that -s (debug shell) expects. + command=3D$(printf '%q ' "$@") fi =20 local kconfig_file=3D"${OUTPUT_DIR}/latest.config" --=20 2.55.0