From: Jiri Olsa <jolsa@kernel.org>
To: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>
Cc: lkml <linux-kernel@vger.kernel.org>,
netdev@vger.kernel.org, linux-kbuild@vger.kernel.org,
Quentin Monnet <quentin.monnet@netronome.com>,
Eugene Syromiatnikov <esyr@redhat.com>,
Jiri Benc <jbenc@redhat.com>,
Stanislav Kozina <skozina@redhat.com>,
Jerome Marchand <jmarchan@redhat.com>,
Arnaldo Carvalho de Melo <acme@redhat.com>,
Masahiro Yamada <yamada.masahiro@socionext.com>,
Michal Marek <michal.lkml@markovi.net>,
Jiri Kosina <jkosina@suse.cz>
Subject: [PATCH 6/9] bpf: Add CONFIG_BPF_BUILDID_CHECK option
Date: Thu, 5 Apr 2018 17:16:42 +0200 [thread overview]
Message-ID: <20180405151645.19130-7-jolsa@kernel.org> (raw)
In-Reply-To: <20180405151645.19130-1-jolsa@kernel.org>
Adding CONFIG_BPF_BUILDID_CHECK option that forces kernel
to check on provided build id when loading eBPF program.
If the build id does not match the one in kernel the program
fails to load.
Adding new field into struct bpf_attr. The kern_buildid
points to the user memory that contains the buildid.
Kernel expose the notes section via sysfs, but there's
currently no other use for kernel's buildid, so I needed
to add new __init buildid_init function to parse it out.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
include/uapi/linux/bpf.h | 2 ++
init/Kconfig | 9 ++++++
kernel/bpf/syscall.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c5ec89732a8d..17d8d330e6c7 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -308,6 +308,8 @@ union bpf_attr {
* (context accesses, allowed helpers, etc).
*/
__u32 expected_attach_type;
+ /* Checked when prog_type=kprobe and CONFIG_BPF_BUILDID_CHECK. */
+ __aligned_u64 kern_buildid;
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/init/Kconfig b/init/Kconfig
index 572df24dda9b..6d32220de7e0 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1406,6 +1406,15 @@ config BPF_JIT_ALWAYS_ON
Enables BPF JIT and removes BPF interpreter to avoid
speculative execution of BPF instructions by the interpreter
+config BPF_BUILDID_CHECK
+ bool "Check buildid for kprobe and tracepoint programs"
+ depends on BPF_SYSCALL
+ select BUILDID_H
+ default n
+ help
+ Enables BPF program load code to check on kernel Build ID
+ for kprobe programs.
+
config USERFAULTFD
bool "Enable userfaultfd() system call"
select ANON_INODES
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0244973ee544..d0b3bc0bd9e6 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1239,7 +1239,85 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
}
/* last field in 'union bpf_attr' used by this command */
-#define BPF_PROG_LOAD_LAST_FIELD expected_attach_type
+#define BPF_PROG_LOAD_LAST_FIELD kern_buildid
+
+#ifdef CONFIG_BPF_BUILDID_CHECK
+
+static struct {
+ const char *ptr;
+ int size;
+} buildid;
+
+#define BUILDID_MAX 40
+
+static int __check_buildid(union bpf_attr *attr)
+{
+ char id[buildid.size];
+
+ /* copy buildid from user space */
+ if (strncpy_from_user(id, u64_to_user_ptr(attr->kern_buildid),
+ buildid.size) < 0)
+ return -EFAULT;
+
+ return memcmp(id, buildid.ptr, buildid.size);
+}
+
+static int check_buildid(union bpf_attr *attr)
+{
+ return buildid.ptr ? __check_buildid(attr) : 0;
+}
+
+#define NT_ALIGN(n) (((n) + 3) & ~3)
+#define NT_GNU_BUILD_ID 3
+
+extern const void __start_notes __weak;
+extern const void __stop_notes __weak;
+
+static int __init buildid_init(void)
+{
+ const void *ptr = &__start_notes;
+
+ while (ptr < &__stop_notes) {
+ const Elf64_Nhdr *nhdr = ptr;
+ size_t namesz = NT_ALIGN(nhdr->n_namesz),
+ descsz = NT_ALIGN(nhdr->n_descsz);
+ const char *name;
+
+ ptr += sizeof(*nhdr);
+ name = ptr;
+ ptr += namesz;
+
+ if (nhdr->n_type != NT_GNU_BUILD_ID ||
+ nhdr->n_namesz != sizeof("GNU") ||
+ memcmp(name, "GNU", sizeof("GNU"))) {
+ ptr += descsz;
+ continue;
+ }
+
+ buildid.ptr = ptr;
+ buildid.size = descsz;
+ break;
+ }
+
+ /* Sanity checks on the parsed buildid. */
+ if (!buildid.ptr) {
+ pr_warn("bpf: GNU buildid not found, switching off the check\n");
+ } else if (buildid.size > 64) {
+ pr_warn("bpf: GNU buildid too long, switching off the check\n");
+ buildid.ptr = NULL;
+ }
+
+ return 0;
+}
+
+subsys_initcall(buildid_init);
+
+#else
+static int check_buildid(union bpf_attr *attr __maybe_unused)
+{
+ return 0;
+}
+#endif /* CONFIG_BPF_BUILDID_CHECK */
static int bpf_prog_load(union bpf_attr *attr)
{
@@ -1271,6 +1349,10 @@ static int bpf_prog_load(union bpf_attr *attr)
attr->kern_version != LINUX_VERSION_CODE)
return -EINVAL;
+ if (type == BPF_PROG_TYPE_KPROBE &&
+ check_buildid(attr))
+ return -EINVAL;
+
if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
type != BPF_PROG_TYPE_CGROUP_SKB &&
!capable(CAP_SYS_ADMIN))
--
2.13.6
next prev parent reply other threads:[~2018-04-05 15:16 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-05 15:16 [RFC 0/9] bpf: Add buildid check support Jiri Olsa
2018-04-05 15:16 ` [PATCH 1/9] perf tools: Make read_build_id function public Jiri Olsa
2018-04-05 15:16 ` [PATCH 2/9] perf tools: Add fetch_kernel_buildid function Jiri Olsa
2018-04-05 15:16 ` [PATCH 3/9] kbuild: Do not pass arguments to link-vmlinux.sh Jiri Olsa
2018-04-05 15:50 ` Masahiro Yamada
2018-04-05 18:59 ` Jiri Olsa
2018-04-06 0:59 ` Masahiro Yamada
2018-04-06 16:54 ` Jiri Olsa
2018-04-05 15:16 ` [PATCH 4/9] kbuild: Add filechk2 function Jiri Olsa
2018-04-05 15:16 ` [PATCH 5/9] bpf: Add CONFIG_BUILDID_H option Jiri Olsa
2018-04-05 15:16 ` Jiri Olsa [this message]
2018-04-05 15:16 ` [PATCH 7/9] libbpf: Synchronize uapi bpf.h header Jiri Olsa
2018-04-05 15:16 ` [PATCH 8/9] libbpf: Add support to attach buildid to program load Jiri Olsa
2018-04-05 15:16 ` [PATCH 9/9] perf tools: The buildid usage in example eBPF program Jiri Olsa
2018-04-06 1:37 ` [RFC 0/9] bpf: Add buildid check support Alexei Starovoitov
2018-04-06 15:07 ` Jiri Olsa
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=20180405151645.19130-7-jolsa@kernel.org \
--to=jolsa@kernel.org \
--cc=acme@redhat.com \
--cc=ast@kernel.org \
--cc=daniel@iogearbox.net \
--cc=esyr@redhat.com \
--cc=jbenc@redhat.com \
--cc=jkosina@suse.cz \
--cc=jmarchan@redhat.com \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michal.lkml@markovi.net \
--cc=netdev@vger.kernel.org \
--cc=quentin.monnet@netronome.com \
--cc=skozina@redhat.com \
--cc=yamada.masahiro@socionext.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).