From: Ilya Leoshkevich <iii@linux.ibm.com>
To: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org, Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Ilya Leoshkevich <iii@linux.ibm.com>
Subject: [PATCH bpf-next 8/9] libbpf: Add MSan annotations
Date: Wed, 8 Feb 2023 21:56:41 +0100 [thread overview]
Message-ID: <20230208205642.270567-9-iii@linux.ibm.com> (raw)
In-Reply-To: <20230208205642.270567-1-iii@linux.ibm.com>
MSan runs into a few false positives in libbpf. They all come from the
fact that MSan does not know anything about the bpf syscall,
particularly, what it writes to.
Add libbpf_mark_defined() function to mark memory modified by the bpf
syscall. Use the abstract name (it could be e.g.
libbpf_msan_unpoison()), because it can be used for valgrind in the
future as well.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
tools/lib/bpf/bpf.c | 70 +++++++++++++++++++++++++++++++--
tools/lib/bpf/btf.c | 1 +
tools/lib/bpf/libbpf.c | 1 +
tools/lib/bpf/libbpf_internal.h | 14 +++++++
4 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 9aff98f42a3d..12fdc4ce1780 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -92,6 +92,10 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
fd = sys_bpf_fd(BPF_PROG_LOAD, attr, size);
} while (fd < 0 && errno == EAGAIN && --attempts > 0);
+ if (attr->log_buf)
+ libbpf_mark_defined((void *)(unsigned long)attr->log_buf,
+ attr->log_size);
+
return fd;
}
@@ -395,6 +399,33 @@ int bpf_map_update_elem(int fd, const void *key, const void *value,
return libbpf_err_errno(ret);
}
+static void mark_map_value_defined(int fd, void *value)
+{
+#ifdef HAVE_LIBBPF_MARK_DEFINED
+ struct bpf_map_info info;
+ size_t size = 0;
+ __u32 info_len;
+ int num_cpus;
+ int err;
+
+ info_len = sizeof(info);
+ err = bpf_obj_get_info_by_fd(fd, &info, &info_len);
+ if (!err) {
+ size = info.value_size;
+ if (info.type == BPF_MAP_TYPE_PERCPU_ARRAY ||
+ info.type == BPF_MAP_TYPE_PERCPU_HASH ||
+ info.type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
+ info.type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
+ num_cpus = libbpf_num_possible_cpus();
+ if (num_cpus > 0)
+ size *= num_cpus;
+ }
+ }
+ if (size)
+ libbpf_mark_defined(value, size);
+#endif
+}
+
int bpf_map_lookup_elem(int fd, const void *key, void *value)
{
const size_t attr_sz = offsetofend(union bpf_attr, flags);
@@ -407,6 +438,8 @@ int bpf_map_lookup_elem(int fd, const void *key, void *value)
attr.value = ptr_to_u64(value);
ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
+ if (!ret)
+ mark_map_value_defined(fd, value);
return libbpf_err_errno(ret);
}
@@ -423,6 +456,8 @@ int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
attr.flags = flags;
ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
+ if (!ret)
+ mark_map_value_defined(fd, value);
return libbpf_err_errno(ret);
}
@@ -438,6 +473,8 @@ int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
attr.value = ptr_to_u64(value);
ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
+ if (!ret)
+ mark_map_value_defined(fd, value);
return libbpf_err_errno(ret);
}
@@ -454,6 +491,8 @@ int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, _
attr.flags = flags;
ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
+ if (!ret)
+ mark_map_value_defined(fd, value);
return libbpf_err_errno(ret);
}
@@ -823,10 +862,12 @@ int bpf_prog_query_opts(int target_fd,
{
const size_t attr_sz = offsetofend(union bpf_attr, query);
union bpf_attr attr;
+ __u32 *prog_ids;
int ret;
if (!OPTS_VALID(opts, bpf_prog_query_opts))
return libbpf_err(-EINVAL);
+ prog_ids = OPTS_GET(opts, prog_ids, NULL);
memset(&attr, 0, attr_sz);
@@ -834,11 +875,15 @@ int bpf_prog_query_opts(int target_fd,
attr.query.attach_type = type;
attr.query.query_flags = OPTS_GET(opts, query_flags, 0);
attr.query.prog_cnt = OPTS_GET(opts, prog_cnt, 0);
- attr.query.prog_ids = ptr_to_u64(OPTS_GET(opts, prog_ids, NULL));
+ attr.query.prog_ids = ptr_to_u64(prog_ids);
attr.query.prog_attach_flags = ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL));
ret = sys_bpf(BPF_PROG_QUERY, &attr, attr_sz);
+ if (!ret && prog_ids)
+ libbpf_mark_defined(prog_ids,
+ attr.query.prog_cnt * sizeof(*prog_ids));
+
OPTS_SET(opts, attach_flags, attr.query.attach_flags);
OPTS_SET(opts, prog_cnt, attr.query.prog_cnt);
@@ -868,10 +913,14 @@ int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
{
const size_t attr_sz = offsetofend(union bpf_attr, test);
union bpf_attr attr;
+ void *data_out;
+ void *ctx_out;
int ret;
if (!OPTS_VALID(opts, bpf_test_run_opts))
return libbpf_err(-EINVAL);
+ data_out = OPTS_GET(opts, data_out, NULL);
+ ctx_out = OPTS_GET(opts, ctx_out, NULL);
memset(&attr, 0, attr_sz);
attr.test.prog_fd = prog_fd;
@@ -885,12 +934,19 @@ int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0);
attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0);
attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL));
- attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL));
+ attr.test.ctx_out = ptr_to_u64(ctx_out);
attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
- attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
+ attr.test.data_out = ptr_to_u64(data_out);
ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, attr_sz);
+ if (!ret) {
+ if (data_out)
+ libbpf_mark_defined(data_out, attr.test.data_size_out);
+ if (ctx_out)
+ libbpf_mark_defined(ctx_out, attr.test.ctx_size_out);
+ }
+
OPTS_SET(opts, data_size_out, attr.test.data_size_out);
OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
OPTS_SET(opts, duration, attr.test.duration);
@@ -1039,8 +1095,10 @@ int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
attr.info.info = ptr_to_u64(info);
err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
- if (!err)
+ if (!err) {
*info_len = attr.info.info_len;
+ libbpf_mark_defined(info, attr.info.info_len);
+ }
return libbpf_err_errno(err);
}
@@ -1103,6 +1161,8 @@ int bpf_btf_load(const void *btf_data, size_t btf_size, const struct bpf_btf_loa
attr.btf_log_level = 1;
fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz);
}
+ if (log_buf)
+ libbpf_mark_defined(log_buf, attr.btf_log_size);
return libbpf_err_errno(fd);
}
@@ -1122,6 +1182,8 @@ int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
attr.task_fd_query.buf_len = *buf_len;
err = sys_bpf(BPF_TASK_FD_QUERY, &attr, attr_sz);
+ if (!err && buf)
+ libbpf_mark_defined(buf, attr.task_fd_query.buf_len + 1);
*buf_len = attr.task_fd_query.buf_len;
*prog_id = attr.task_fd_query.prog_id;
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 64841117fbb2..24a957604a97 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -1388,6 +1388,7 @@ struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf)
goto exit_free;
}
+ libbpf_mark_defined(ptr, btf_info.btf_size);
btf = btf_new(ptr, btf_info.btf_size, base_btf);
exit_free:
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 4191a78b2815..3e32ae5f0cce 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5443,6 +5443,7 @@ static int load_module_btfs(struct bpf_object *obj)
pr_warn("failed to get BTF object #%d info: %d\n", id, err);
goto err_out;
}
+ libbpf_mark_defined(name, info.name_len + 1);
/* ignore non-module BTFs */
if (!info.kernel_btf || strcmp(name, "vmlinux") == 0) {
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index fbaf68335394..4e4622f66fdf 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -577,4 +577,18 @@ static inline bool is_pow_of_2(size_t x)
#define PROG_LOAD_ATTEMPTS 5
int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts);
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#define LIBBPF_MSAN
+#endif
+#endif
+
+#ifdef LIBBPF_MSAN
+#define HAVE_LIBBPF_MARK_DEFINED
+#include <sanitizer/msan_interface.h>
+#define libbpf_mark_defined __msan_unpoison
+#else
+static inline void libbpf_mark_defined(void *s, size_t n) {}
+#endif
+
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
--
2.39.1
next prev parent reply other threads:[~2023-02-08 20:57 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-08 20:56 [PATCH bpf-next 0/9] selftests/bpf: Add Memory Sanitizer support Ilya Leoshkevich
2023-02-08 20:56 ` [PATCH bpf-next 1/9] selftests/bpf: Quote host tools Ilya Leoshkevich
2023-02-08 20:56 ` [PATCH bpf-next 2/9] tools: runqslower: Add EXTRA_CFLAGS and EXTRA_LDFLAGS support Ilya Leoshkevich
2023-02-09 1:00 ` Andrii Nakryiko
2023-02-08 20:56 ` [PATCH bpf-next 3/9] selftests/bpf: Split SAN_CFLAGS and SAN_LDFLAGS Ilya Leoshkevich
2023-02-08 20:56 ` [PATCH bpf-next 4/9] selftests/bpf: Forward SAN_CFLAGS and SAN_LDFLAGS to runqslower and libbpf Ilya Leoshkevich
2023-02-09 1:03 ` Andrii Nakryiko
2023-02-09 9:55 ` Ilya Leoshkevich
2023-02-09 17:17 ` Andrii Nakryiko
2023-02-08 20:56 ` [PATCH bpf-next 5/9] selftests/bpf: Attach to fopen()/fclose() in uprobe_autoattach Ilya Leoshkevich
2023-02-09 1:05 ` Andrii Nakryiko
2023-02-08 20:56 ` [PATCH bpf-next 6/9] selftests/bpf: Attach to fopen()/fclose() in attach_probe Ilya Leoshkevich
2023-02-09 1:06 ` Andrii Nakryiko
2023-02-08 20:56 ` [PATCH bpf-next 7/9] libbpf: Fix alen calculation in libbpf_nla_dump_errormsg() Ilya Leoshkevich
2023-02-09 1:14 ` Andrii Nakryiko
2023-02-08 20:56 ` Ilya Leoshkevich [this message]
2023-02-09 1:29 ` [PATCH bpf-next 8/9] libbpf: Add MSan annotations Andrii Nakryiko
2023-02-09 10:01 ` Ilya Leoshkevich
2023-02-09 19:37 ` Andrii Nakryiko
2023-02-08 20:56 ` [PATCH bpf-next 9/9] selftests/bpf: " Ilya Leoshkevich
2023-02-09 1:34 ` Andrii Nakryiko
2023-02-09 10:30 ` Ilya Leoshkevich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230208205642.270567-9-iii@linux.ibm.com \
--to=iii@linux.ibm.com \
--cc=agordeev@linux.ibm.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.