Subject: [PATCH bpf-next v1 3/6] libbpf: Ensure that module BTF fd is never 0

From: Kumar Kartikeya Dwivedi <[email-masked]>
Date: Wed, 6 Oct 2021 05:58:50 +0530

Since the code assumes in various places that BTF fd for modules is
never 0, if we end up getting fd as 0, obtain a new fd > 0. Even though
fd 0 being free for allocation is usually an application error, it is
still possible that we end up getting fd 0 if the application explicitly
closes its stdin. Deal with this by getting a new fd using dup and
closing fd 0.

Signed-off-by: Kumar Kartikeya Dwivedi <[email-masked]>
---
 tools/lib/bpf/libbpf.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index d286dec73b5f..3e5e460fe63e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4975,6 +4975,20 @@ static int load_module_btfs(struct bpf_object *obj)
 			pr_warn("failed to get BTF object #%d FD: %d\n", id, err);
 			return err;
 		}
+		/* Make sure module BTF fd is never 0, as kernel depends on it
+		 * being > 0 to distinguish between vmlinux and module BTFs,
+		 * e.g. for BPF_PSEUDO_BTF_ID ld_imm64 insns (ksyms).
+		 */
+		if (!fd) {
+			fd = dup(0);
+			if (fd < 0) {
+				err = -errno;
+				pr_warn("failed to dup BTF object #%d FD 0 to FD > 0: %d\n", id, err);
+				close(0);
+				return err;
+			}
+			close(0);
+		}
 
 		len = sizeof(info);
 		memset(&info, 0, sizeof(info));
-- 
2.33.0