From 713c02b59e21840f623a3e31c43d967026c75181 Mon Sep 17 00:00:00 2001 From: Yuan Chen Date: Mon, 24 Aug 2026 17:26:56 +0800 Subject: [PATCH] bpftool: Fix spurious batch file read error do_batch() checks errno after the read loop to detect read failures, but fgets() does not clear errno on success, so a stale errno left by a previously executed command (e.g. map dump's EBADF from a double close) makes bpftool report a batch file read failure and exit with an error even though every command succeeded. Clear errno before each fgets() call, so the post-loop check only sees the outcome of the last read: zero on success or EOF, E2BIG for an overlong line, and a genuine errno when fgets() fails. Since errno is now reset before every read in batch mode, drop the USE_LIBCAP errno reset in main() that existed only to keep errno clean for the batch mode. Fixes: 71bb428fe2c1 ("tools: bpf: add bpftool") Signed-off-by: Yuan Chen Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20260824092657.1789956-2-chenyuan_fl@163.com --- tools/bpf/bpftool/main.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index c91e1a6e1a1e..7a0c214f08a0 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c @@ -365,7 +365,11 @@ static int do_batch(int argc, char **argv) if (json_output) jsonw_start_array(json_wtr); - while (fgets(buf, sizeof(buf), fp)) { + for (;;) { + errno = 0; + if (!fgets(buf, sizeof(buf), fp)) + break; + cp = strchr(buf, '#'); if (cp) *cp = '\0'; @@ -467,16 +471,6 @@ int main(int argc, char **argv) setlinebuf(stdout); -#ifdef USE_LIBCAP - /* Libcap < 2.63 hooks before main() to compute the number of - * capabilities of the running kernel, and doing so it calls prctl() - * which may fail and set errno to non-zero. - * Let's reset errno to make sure this does not interfere with the - * batch mode. - */ - errno = 0; -#endif - last_do_help = do_help; pretty_output = false; json_output = false;