All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC bpf-next 0/2] bpf: sign bpf programs
@ 2021-10-12 19:00 Matteo Croce
  2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
  2021-10-12 19:00 ` [RFC bpf-next 2/2] bpftool: add signature in skeleton Matteo Croce
  0 siblings, 2 replies; 10+ messages in thread
From: Matteo Croce @ 2021-10-12 19:00 UTC (permalink / raw)
  To: bpf
  Cc: linux-kernel, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Arnaldo Carvalho de Melo, Luca Boccassi,
	David S. Miller

From: Matteo Croce <mcroce@microsoft.com>

Add a field in bpf_attr which contains a signature for the eBPF instructions.
The signature is validated bpf_prog_load() in a similar way as kernel modules
are checked in load_module().

This only works with CO-RE programs.
The signature is generated by bpftool and embedded into the light skeleton
along with the instructions.
The bpftool crypto code is based on sign-file, supports the same interface,
and is compiled only if libcrypto is available, to avoid potential breaks.

Possible improvements:
- Add a knob which makes the signature check mandatory,
  similarly to CONFIG_MODULE_SIG_FORCE
- Add a dedicate key_being_used_for type instead of using
  VERIFYING_MODULE_SIGNATURE, e.g. VERIFYING_BPF_SIGNATURE

This depends on the kernel side co-re relocation[1].

[1] https://lore.kernel.org/bpf/20210917215721.43491-1-alexei.starovoitov@gmail.com/

Matteo Croce (2):
  bpf: add signature to eBPF instructions
  bpftool: add signature in skeleton

 include/uapi/linux/bpf.h       |   2 +
 kernel/bpf/syscall.c           |  33 ++++-
 tools/bpf/bpftool/Makefile     |  14 ++-
 tools/bpf/bpftool/gen.c        |  33 +++++
 tools/bpf/bpftool/main.c       |  28 +++++
 tools/bpf/bpftool/main.h       |   7 ++
 tools/bpf/bpftool/sign.c       | 217 +++++++++++++++++++++++++++++++++
 tools/include/uapi/linux/bpf.h |   2 +
 tools/lib/bpf/skel_internal.h  |   4 +
 9 files changed, 336 insertions(+), 4 deletions(-)
 create mode 100644 tools/bpf/bpftool/sign.c

-- 
2.33.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
  2021-10-12 19:00 [RFC bpf-next 0/2] bpf: sign bpf programs Matteo Croce
@ 2021-10-12 19:00 ` Matteo Croce
  2021-10-13  2:37   ` kernel test robot
                     ` (4 more replies)
  2021-10-12 19:00 ` [RFC bpf-next 2/2] bpftool: add signature in skeleton Matteo Croce
  1 sibling, 5 replies; 10+ messages in thread
From: Matteo Croce @ 2021-10-12 19:00 UTC (permalink / raw)
  To: bpf
  Cc: linux-kernel, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Arnaldo Carvalho de Melo, Luca Boccassi,
	David S. Miller

From: Matteo Croce <mcroce@microsoft.com>

When loading a BPF program, pass a signature which is used to validate
the instructions.
The signature type is the same used to validate the kernel modules.

Signed-off-by: Matteo Croce <mcroce@microsoft.com>
---
 include/uapi/linux/bpf.h |  2 ++
 kernel/bpf/syscall.c     | 33 ++++++++++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c2b8857b8a1c..b9d259f26e92 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1336,6 +1336,8 @@ union bpf_attr {
 		};
 		__u32		:32;		/* pad */
 		__aligned_u64	fd_array;	/* array of FDs */
+		__aligned_u64	signature;	/* instruction's signature */
+		__u32		sig_len;	/* signature size */
 	};
 
 	struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 3c349b244a28..5589f655033d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -31,6 +31,8 @@
 #include <linux/bpf-netns.h>
 #include <linux/rcupdate_trace.h>
 #include <linux/memcontrol.h>
+#include <linux/verification.h>
+#include <linux/module_signature.h>
 
 #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
 			  (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
@@ -2156,7 +2158,7 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
 }
 
 /* last field in 'union bpf_attr' used by this command */
-#define	BPF_PROG_LOAD_LAST_FIELD fd_array
+#define	BPF_PROG_LOAD_LAST_FIELD sig_len
 
 static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
 {
@@ -2274,6 +2276,35 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
 			     bpf_prog_insn_size(prog)) != 0)
 		goto free_prog_sec;
 
+	if (attr->sig_len) {
+		char *signature;
+
+		signature = kmalloc(attr->sig_len, GFP_USER);
+		if (!signature) {
+			err = -ENOMEM;
+			goto free_prog_sec;
+		}
+
+		if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
+			err = -EFAULT;
+			kfree(signature);
+			goto free_prog_sec;
+		}
+
+		err = verify_pkcs7_signature(prog->insns,
+					     prog->len * sizeof(struct bpf_insn),
+					     signature, attr->sig_len,
+					     VERIFY_USE_SECONDARY_KEYRING,
+					     VERIFYING_MODULE_SIGNATURE,
+					     NULL, NULL);
+		kfree(signature);
+
+		if (err) {
+			printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
+			goto free_prog_sec;
+		}
+	}
+
 	prog->orig_prog = NULL;
 	prog->jited = 0;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC bpf-next 2/2] bpftool: add signature in skeleton
  2021-10-12 19:00 [RFC bpf-next 0/2] bpf: sign bpf programs Matteo Croce
  2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
@ 2021-10-12 19:00 ` Matteo Croce
  1 sibling, 0 replies; 10+ messages in thread
From: Matteo Croce @ 2021-10-12 19:00 UTC (permalink / raw)
  To: bpf
  Cc: linux-kernel, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Arnaldo Carvalho de Melo, Luca Boccassi,
	David S. Miller

From: Matteo Croce <mcroce@microsoft.com>

When generating the skeleton, allow to add a signature.
The signature will be passed to the kernel in the newly added field.
As in sign-file, allow specifing "pkcs11:..." as key file, to use the
openssl engine.
Still as in sign-file, read the environment variable KBUILD_SIGN_PIN.

Signed-off-by: Matteo Croce <mcroce@microsoft.com>
---
 tools/bpf/bpftool/Makefile     |  14 ++-
 tools/bpf/bpftool/gen.c        |  33 +++++
 tools/bpf/bpftool/main.c       |  28 +++++
 tools/bpf/bpftool/main.h       |   7 ++
 tools/bpf/bpftool/sign.c       | 217 +++++++++++++++++++++++++++++++++
 tools/include/uapi/linux/bpf.h |   2 +
 tools/lib/bpf/skel_internal.h  |   4 +
 7 files changed, 302 insertions(+), 3 deletions(-)
 create mode 100644 tools/bpf/bpftool/sign.c

diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 1fcf5b01a193..b67d6e0b9067 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -78,9 +78,9 @@ RM ?= rm -f
 
 FEATURE_USER = .bpftool
 FEATURE_TESTS = libbfd disassembler-four-args reallocarray zlib libcap \
-	clang-bpf-co-re
+	clang-bpf-co-re libcrypto
 FEATURE_DISPLAY = libbfd disassembler-four-args zlib libcap \
-	clang-bpf-co-re
+	clang-bpf-co-re libcrypto
 
 check_feat := 1
 NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall
@@ -113,6 +113,11 @@ CFLAGS += -DUSE_LIBCAP
 LIBS += -lcap
 endif
 
+ifeq ($(feature-libcrypto), 1)
+CFLAGS_SSL := -DUSE_SIGN
+LIBS += -lssl -lcrypto
+endif
+
 include $(wildcard $(OUTPUT)*.d)
 
 all: $(OUTPUT)bpftool
@@ -120,6 +125,9 @@ all: $(OUTPUT)bpftool
 BFD_SRCS = jit_disasm.c
 
 SRCS = $(filter-out $(BFD_SRCS),$(wildcard *.c))
+ifneq ($(feature-libcrypto), 1)
+SRCS := $(filter-out sign.c,$(SRCS))
+endif
 
 ifeq ($(feature-libbfd),1)
   LIBS += -lbfd -ldl -lopcodes
@@ -202,7 +210,7 @@ $(BOOTSTRAP_OUTPUT)%.o: %.c | $(BOOTSTRAP_OUTPUT)
 	$(QUIET_CC)$(HOSTCC) $(CFLAGS) -c -MMD -o $@ $<
 
 $(OUTPUT)%.o: %.c
-	$(QUIET_CC)$(CC) $(CFLAGS) -c -MMD -o $@ $<
+	$(QUIET_CC)$(CC) $(CFLAGS) $(CFLAGS_SSL) -c -MMD -o $@ $<
 
 feature-detect-clean:
 	$(call QUIET_CLEAN, feature-detect)
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index cc835859465b..2551fe90dc89 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -434,6 +434,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
 	DECLARE_LIBBPF_OPTS(gen_loader_opts, opts);
 	struct bpf_map *map;
 	int err = 0;
+#ifdef USE_SIGN
+	char *signature = NULL;
+	int sig_len = 0;
+#endif
 
 	err = bpf_object__gen_loader(obj, &opts);
 	if (err)
@@ -453,6 +457,19 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
 	 * are populated with the loader program.
 	 */
 
+#ifdef USE_SIGN
+	if (sign_bpf) {
+		sig_len = sign(sign_hash, sign_key, sign_cert,
+			       opts.insns, opts.insns_sz,
+			       (unsigned char **)&signature);
+		if (sig_len <= 0) {
+			p_err("failed to sign instructions");
+			err = -EINVAL;
+			goto out;
+		}
+	}
+#endif
+
 	/* finish generating 'struct skel' */
 	codegen("\
 		\n\
@@ -537,6 +554,18 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
 		",
 		opts.insns_sz);
 	print_hex(opts.insns, opts.insns_sz);
+#ifdef USE_SIGN
+	if (sign_bpf) {
+		codegen("\
+			\n\
+			\";						    \n\
+				opts.sig_sz = %d;			    \n\
+				opts.signature = (void *)\"\\		    \n\
+			",
+			sig_len);
+		print_hex(signature, sig_len);
+	}
+#endif
 	codegen("\
 		\n\
 		\";							    \n\
@@ -1037,6 +1066,10 @@ static int do_help(int argc, char **argv)
 		"       %1$s %2$s help\n"
 		"\n"
 		"       " HELP_SPEC_OPTIONS " |\n"
+#ifdef USE_SIGN
+		"                    {-s|--sign} | {-H|--hash} |\n"
+		"                    {-c|--cert} | {-k|--key} |\n"
+#endif
 		"                    {-L|--use-loader} }\n"
 		"",
 		bin_name, "gen");
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 02eaaf065f65..4e70b89c5b22 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -30,6 +30,10 @@ bool block_mount;
 bool verifier_logs;
 bool relaxed_maps;
 bool use_loader;
+bool sign_bpf;
+const char *sign_hash;
+const char *sign_cert;
+const char *sign_key;
 struct btf *base_btf;
 struct pinned_obj_table prog_table;
 struct pinned_obj_table map_table;
@@ -398,6 +402,12 @@ int main(int argc, char **argv)
 		{ "debug",	no_argument,	NULL,	'd' },
 		{ "use-loader",	no_argument,	NULL,	'L' },
 		{ "base-btf",	required_argument, NULL, 'B' },
+#ifdef USE_SIGN
+		{ "sign",	no_argument,	NULL,	's' },
+		{ "hash",	required_argument, NULL, 'H' },
+		{ "cert",	required_argument, NULL, 'c' },
+		{ "key",	required_argument, NULL, 'k' },
+#endif
 		{ 0 }
 	};
 	int opt, ret;
@@ -414,7 +424,11 @@ int main(int argc, char **argv)
 	hash_init(link_table.table);
 
 	opterr = 0;
+#ifdef USE_SIGN
+	while ((opt = getopt_long(argc, argv, "VhpjfLmndB:sH:c:k:",
+#else
 	while ((opt = getopt_long(argc, argv, "VhpjfLmndB:",
+#endif
 				  options, NULL)) >= 0) {
 		switch (opt) {
 		case 'V':
@@ -460,6 +474,20 @@ int main(int argc, char **argv)
 		case 'L':
 			use_loader = true;
 			break;
+#ifdef USE_SIGN
+		case 's':
+			sign_bpf = true;
+			break;
+		case 'H':
+			sign_hash = optarg;
+			break;
+		case 'c':
+			sign_cert = optarg;
+			break;
+		case 'k':
+			sign_key = optarg;
+			break;
+#endif
 		default:
 			p_err("unrecognized option '%s'", argv[optind - 1]);
 			if (json_output)
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 90caa42aac4c..78742720447f 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -90,6 +90,10 @@ extern bool block_mount;
 extern bool verifier_logs;
 extern bool relaxed_maps;
 extern bool use_loader;
+extern bool sign_bpf;
+extern const char *sign_hash;
+extern const char *sign_cert;
+extern const char *sign_key;
 extern struct btf *base_btf;
 extern struct pinned_obj_table prog_table;
 extern struct pinned_obj_table map_table;
@@ -259,4 +263,7 @@ int do_filter_dump(struct tcmsg *ifinfo, struct nlattr **tb, const char *kind,
 
 int print_all_levels(__maybe_unused enum libbpf_print_level level,
 		     const char *format, va_list args);
+
+int sign(const char *hash_algo, const char *key_path, const char *x509_path,
+	 const char *indata, int indatalen, unsigned char **outdata);
 #endif
diff --git a/tools/bpf/bpftool/sign.c b/tools/bpf/bpftool/sign.c
new file mode 100644
index 000000000000..50b257a7177c
--- /dev/null
+++ b/tools/bpf/bpftool/sign.c
@@ -0,0 +1,217 @@
+/* Sign a module file using the given key and certificate.
+ *
+ * Inspired by Linux scripts/sign-file.c
+ * Copyright (C) 2021 Matteo Croce <mcroce@microsoft.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the licence, or (at your option) any later version.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <openssl/opensslv.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/engine.h>
+#include <openssl/cms.h>
+
+#include "main.h"
+
+static const char *key_pass;
+
+static int pem_pw_cb(char *buf, int len, int w, void *v)
+{
+	int pwlen;
+
+	if (!key_pass)
+		return -1;
+
+	pwlen = strlen(key_pass);
+	if (pwlen >= len)
+		return -1;
+
+	strcpy(buf, key_pass);
+
+	/* If it's wrong, don't keep trying it. */
+	key_pass = NULL;
+
+	return pwlen;
+}
+
+static void display_openssl_errors(void)
+{
+	const char *file;
+	char buf[120];
+	int e, line;
+
+	if (!ERR_peek_error())
+		return;
+
+	while ((e = ERR_get_error_line(&file, &line))) {
+		ERR_error_string(e, buf);
+		fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
+	}
+}
+
+static EVP_PKEY *read_private_key(const char *key_path)
+{
+	EVP_PKEY *private_key;
+
+	if (!strncmp(key_path, "pkcs11:", 7)) {
+		ENGINE *e;
+
+		ENGINE_load_builtin_engines();
+		display_openssl_errors();
+		e = ENGINE_by_id("pkcs11");
+		if (!e)
+			return NULL;
+
+		if (!ENGINE_init(e)) {
+			display_openssl_errors();
+			return NULL;
+		}
+		display_openssl_errors();
+
+		if (key_pass)
+			if (!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0))
+				return NULL;
+		private_key = ENGINE_load_private_key(e, key_path, NULL, NULL);
+	} else {
+		BIO *b;
+
+		b = BIO_new_file(key_path, "rb");
+		if (!b)
+			return NULL;
+		private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL);
+		BIO_free(b);
+	}
+
+	return private_key;
+}
+
+static X509 *read_x509(const char *x509_path)
+{
+	unsigned char buf[2];
+	X509 *x509 = NULL;
+	BIO *b;
+	int n;
+
+	b = BIO_new_file(x509_path, "rb");
+	if (!b) {
+		display_openssl_errors();
+		return NULL;
+	}
+
+	/* Look at the first two bytes of the file to determine the encoding */
+	n = BIO_read(b, buf, 2);
+	if (n != 2) {
+		if (BIO_should_retry(b))
+			fprintf(stderr, "%s: Read wanted retry\n", x509_path);
+		if (n >= 0)
+			fprintf(stderr, "%s: Short read\n", x509_path);
+		display_openssl_errors();
+		goto out_free;
+	}
+
+	if (BIO_reset(b)) {
+		display_openssl_errors();
+		goto out_free;
+	}
+
+	if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84)
+		/* Assume raw DER encoded X.509 */
+		x509 = d2i_X509_bio(b, NULL);
+	else
+		/* Assume PEM encoded X.509 */
+		x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
+
+	if (!x509)
+		display_openssl_errors();
+
+out_free:
+	BIO_free(b);
+
+	return x509;
+}
+
+int sign(const char *hash_algo, const char *key_path, const char *x509_path,
+	 const char *indata, int indatalen, unsigned char **outdata)
+{
+	CMS_ContentInfo *cms = NULL;
+	const EVP_MD *digest_algo;
+	EVP_PKEY *private_key;
+	X509 *x509;
+	BIO *bm;
+
+	OpenSSL_add_all_algorithms();
+	ERR_load_crypto_strings();
+	ERR_clear_error();
+
+	key_pass = getenv("KBUILD_SIGN_PIN");
+
+	/* Open the module file */
+	bm = BIO_new_mem_buf(indata, indatalen);
+	if (!bm) {
+		display_openssl_errors();
+		return -1;
+	}
+
+	/* Read the private key and the X.509 cert the PKCS#7 message
+	 * will point to.
+	 */
+	private_key = read_private_key(key_path);
+	if (!private_key)
+		goto out_free;
+
+	x509 = read_x509(x509_path);
+	if (!x509)
+		goto out_free;
+
+	/* Digest the module data. */
+	OpenSSL_add_all_digests();
+	display_openssl_errors();
+
+	digest_algo = EVP_get_digestbyname(hash_algo);
+	if (!digest_algo) {
+		display_openssl_errors();
+		goto out_free;
+	}
+
+	/* Load the signature message from the digest buffer. */
+	cms = CMS_sign(NULL, NULL, NULL, NULL, CMS_NOCERTS | CMS_PARTIAL |
+		       CMS_BINARY | CMS_DETACHED | CMS_STREAM);
+	if (!cms) {
+		display_openssl_errors();
+		goto out_free;
+	}
+
+	if (!CMS_add1_signer(cms, x509, private_key, digest_algo,
+			     CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP |
+			     CMS_NOATTR)) {
+	   display_openssl_errors();
+		goto out_free;
+	}
+
+	if (CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0)
+		display_openssl_errors();
+
+out_free:
+	BIO_free(bm);
+
+	if (!cms)
+		return -1;
+
+	return i2d_CMS_ContentInfo(cms, outdata);
+}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index c2b8857b8a1c..b9d259f26e92 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1336,6 +1336,8 @@ union bpf_attr {
 		};
 		__u32		:32;		/* pad */
 		__aligned_u64	fd_array;	/* array of FDs */
+		__aligned_u64	signature;	/* instruction's signature */
+		__u32		sig_len;	/* signature size */
 	};
 
 	struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h
index 9cf66702fa8d..1ef2df16f90c 100644
--- a/tools/lib/bpf/skel_internal.h
+++ b/tools/lib/bpf/skel_internal.h
@@ -42,8 +42,10 @@ struct bpf_load_and_run_opts {
 	struct bpf_loader_ctx *ctx;
 	const void *data;
 	const void *insns;
+	const void *signature;
 	__u32 data_sz;
 	__u32 insns_sz;
+	__u32 sig_sz;
 	const char *errstr;
 };
 
@@ -84,6 +86,8 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
 	attr.prog_type = BPF_PROG_TYPE_SYSCALL;
 	attr.insns = (long) opts->insns;
 	attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
+	attr.signature = (long) opts->signature;
+	attr.sig_len = opts->sig_sz;
 	attr.license = (long) "Dual BSD/GPL";
 	memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog"));
 	attr.fd_array = (long) &map_fd;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
  2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
@ 2021-10-13  2:37   ` kernel test robot
  2021-10-13  3:13   ` kernel test robot
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2021-10-13  2:37 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 10337 bytes --]

Hi Matteo,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: sparc64-randconfig-s032-20211012 (attached as .config)
compiler: sparc64-linux-gcc (GCC) 11.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/45c21d28e868dac39e5267e2e2b6f4e35f86b661
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
        git checkout 45c21d28e868dac39e5267e2e2b6f4e35f86b661
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=sparc64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> kernel/bpf/syscall.c:2288:48: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const [noderef] __user *from @@     got char * @@
   kernel/bpf/syscall.c:2288:48: sparse:     expected void const [noderef] __user *from
   kernel/bpf/syscall.c:2288:48: sparse:     got char *
   kernel/bpf/syscall.c: note: in included file (through include/linux/bpf.h):
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:81:43: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:81:43: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar

vim +2288 kernel/bpf/syscall.c

  2162	
  2163	static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
  2164	{
  2165		enum bpf_prog_type type = attr->prog_type;
  2166		struct bpf_prog *prog, *dst_prog = NULL;
  2167		struct btf *attach_btf = NULL;
  2168		int err;
  2169		char license[128];
  2170		bool is_gpl;
  2171	
  2172		if (CHECK_ATTR(BPF_PROG_LOAD))
  2173			return -EINVAL;
  2174	
  2175		if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
  2176					 BPF_F_ANY_ALIGNMENT |
  2177					 BPF_F_TEST_STATE_FREQ |
  2178					 BPF_F_SLEEPABLE |
  2179					 BPF_F_TEST_RND_HI32))
  2180			return -EINVAL;
  2181	
  2182		if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
  2183		    (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
  2184		    !bpf_capable())
  2185			return -EPERM;
  2186	
  2187		/* copy eBPF program license from user space */
  2188		if (strncpy_from_bpfptr(license,
  2189					make_bpfptr(attr->license, uattr.is_kernel),
  2190					sizeof(license) - 1) < 0)
  2191			return -EFAULT;
  2192		license[sizeof(license) - 1] = 0;
  2193	
  2194		/* eBPF programs must be GPL compatible to use GPL-ed functions */
  2195		is_gpl = license_is_gpl_compatible(license);
  2196	
  2197		if (attr->insn_cnt == 0 ||
  2198		    attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
  2199			return -E2BIG;
  2200		if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
  2201		    type != BPF_PROG_TYPE_CGROUP_SKB &&
  2202		    !bpf_capable())
  2203			return -EPERM;
  2204	
  2205		if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
  2206			return -EPERM;
  2207		if (is_perfmon_prog_type(type) && !perfmon_capable())
  2208			return -EPERM;
  2209	
  2210		/* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog
  2211		 * or btf, we need to check which one it is
  2212		 */
  2213		if (attr->attach_prog_fd) {
  2214			dst_prog = bpf_prog_get(attr->attach_prog_fd);
  2215			if (IS_ERR(dst_prog)) {
  2216				dst_prog = NULL;
  2217				attach_btf = btf_get_by_fd(attr->attach_btf_obj_fd);
  2218				if (IS_ERR(attach_btf))
  2219					return -EINVAL;
  2220				if (!btf_is_kernel(attach_btf)) {
  2221					/* attaching through specifying bpf_prog's BTF
  2222					 * objects directly might be supported eventually
  2223					 */
  2224					btf_put(attach_btf);
  2225					return -ENOTSUPP;
  2226				}
  2227			}
  2228		} else if (attr->attach_btf_id) {
  2229			/* fall back to vmlinux BTF, if BTF type ID is specified */
  2230			attach_btf = bpf_get_btf_vmlinux();
  2231			if (IS_ERR(attach_btf))
  2232				return PTR_ERR(attach_btf);
  2233			if (!attach_btf)
  2234				return -EINVAL;
  2235			btf_get(attach_btf);
  2236		}
  2237	
  2238		bpf_prog_load_fixup_attach_type(attr);
  2239		if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
  2240					       attach_btf, attr->attach_btf_id,
  2241					       dst_prog)) {
  2242			if (dst_prog)
  2243				bpf_prog_put(dst_prog);
  2244			if (attach_btf)
  2245				btf_put(attach_btf);
  2246			return -EINVAL;
  2247		}
  2248	
  2249		/* plain bpf_prog allocation */
  2250		prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
  2251		if (!prog) {
  2252			if (dst_prog)
  2253				bpf_prog_put(dst_prog);
  2254			if (attach_btf)
  2255				btf_put(attach_btf);
  2256			return -ENOMEM;
  2257		}
  2258	
  2259		prog->expected_attach_type = attr->expected_attach_type;
  2260		prog->aux->attach_btf = attach_btf;
  2261		prog->aux->attach_btf_id = attr->attach_btf_id;
  2262		prog->aux->dst_prog = dst_prog;
  2263		prog->aux->offload_requested = !!attr->prog_ifindex;
  2264		prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
  2265	
  2266		err = security_bpf_prog_alloc(prog->aux);
  2267		if (err)
  2268			goto free_prog;
  2269	
  2270		prog->aux->user = get_current_user();
  2271		prog->len = attr->insn_cnt;
  2272	
  2273		err = -EFAULT;
  2274		if (copy_from_bpfptr(prog->insns,
  2275				     make_bpfptr(attr->insns, uattr.is_kernel),
  2276				     bpf_prog_insn_size(prog)) != 0)
  2277			goto free_prog_sec;
  2278	
  2279		if (attr->sig_len) {
  2280			char *signature;
  2281	
  2282			signature = kmalloc(attr->sig_len, GFP_USER);
  2283			if (!signature) {
  2284				err = -ENOMEM;
  2285				goto free_prog_sec;
  2286			}
  2287	
> 2288			if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
  2289				err = -EFAULT;
  2290				kfree(signature);
  2291				goto free_prog_sec;
  2292			}
  2293	
  2294			err = verify_pkcs7_signature(prog->insns,
  2295						     prog->len * sizeof(struct bpf_insn),
  2296						     signature, attr->sig_len,
  2297						     VERIFY_USE_SECONDARY_KEYRING,
  2298						     VERIFYING_MODULE_SIGNATURE,
  2299						     NULL, NULL);
  2300			kfree(signature);
  2301	
  2302			if (err) {
  2303				printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
  2304				goto free_prog_sec;
  2305			}
  2306		}
  2307	
  2308		prog->orig_prog = NULL;
  2309		prog->jited = 0;
  2310	
  2311		atomic64_set(&prog->aux->refcnt, 1);
  2312		prog->gpl_compatible = is_gpl ? 1 : 0;
  2313	
  2314		if (bpf_prog_is_dev_bound(prog->aux)) {
  2315			err = bpf_prog_offload_init(prog, attr);
  2316			if (err)
  2317				goto free_prog_sec;
  2318		}
  2319	
  2320		/* find program type: socket_filter vs tracing_filter */
  2321		err = find_prog_type(type, prog);
  2322		if (err < 0)
  2323			goto free_prog_sec;
  2324	
  2325		prog->aux->load_time = ktime_get_boottime_ns();
  2326		err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
  2327				       sizeof(attr->prog_name));
  2328		if (err < 0)
  2329			goto free_prog_sec;
  2330	
  2331		/* run eBPF verifier */
  2332		err = bpf_check(&prog, attr, uattr);
  2333		if (err < 0)
  2334			goto free_used_maps;
  2335	
  2336		prog = bpf_prog_select_runtime(prog, &err);
  2337		if (err < 0)
  2338			goto free_used_maps;
  2339	
  2340		err = bpf_prog_alloc_id(prog);
  2341		if (err)
  2342			goto free_used_maps;
  2343	
  2344		/* Upon success of bpf_prog_alloc_id(), the BPF prog is
  2345		 * effectively publicly exposed. However, retrieving via
  2346		 * bpf_prog_get_fd_by_id() will take another reference,
  2347		 * therefore it cannot be gone underneath us.
  2348		 *
  2349		 * Only for the time /after/ successful bpf_prog_new_fd()
  2350		 * and before returning to userspace, we might just hold
  2351		 * one reference and any parallel close on that fd could
  2352		 * rip everything out. Hence, below notifications must
  2353		 * happen before bpf_prog_new_fd().
  2354		 *
  2355		 * Also, any failure handling from this point onwards must
  2356		 * be using bpf_prog_put() given the program is exposed.
  2357		 */
  2358		bpf_prog_kallsyms_add(prog);
  2359		perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
  2360		bpf_audit_prog(prog, BPF_AUDIT_LOAD);
  2361	
  2362		err = bpf_prog_new_fd(prog);
  2363		if (err < 0)
  2364			bpf_prog_put(prog);
  2365		return err;
  2366	
  2367	free_used_maps:
  2368		/* In case we have subprogs, we need to wait for a grace
  2369		 * period before we can tear down JIT memory since symbols
  2370		 * are already exposed under kallsyms.
  2371		 */
  2372		__bpf_prog_put_noref(prog, prog->aux->func_cnt);
  2373		return err;
  2374	free_prog_sec:
  2375		free_uid(prog->aux->user);
  2376		security_bpf_prog_free(prog->aux);
  2377	free_prog:
  2378		if (prog->aux->attach_btf)
  2379			btf_put(prog->aux->attach_btf);
  2380		bpf_prog_free(prog);
  2381		return err;
  2382	}
  2383	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 34805 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
  2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
  2021-10-13  2:37   ` kernel test robot
@ 2021-10-13  3:13   ` kernel test robot
  2021-10-13  3:36   ` kernel test robot
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2021-10-13  3:13 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 9799 bytes --]

Hi Matteo,

[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: nios2-randconfig-r034-20211013 (attached as .config)
compiler: nios2-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/45c21d28e868dac39e5267e2e2b6f4e35f86b661
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
        git checkout 45c21d28e868dac39e5267e2e2b6f4e35f86b661
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=nios2 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   kernel/bpf/syscall.c: In function 'bpf_prog_load':
>> kernel/bpf/syscall.c:2288:47: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    2288 |                 if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
         |                                               ^
>> kernel/bpf/syscall.c:2294:23: error: implicit declaration of function 'verify_pkcs7_signature' [-Werror=implicit-function-declaration]
    2294 |                 err = verify_pkcs7_signature(prog->insns,
         |                       ^~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/verify_pkcs7_signature +2294 kernel/bpf/syscall.c

  2162	
  2163	static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
  2164	{
  2165		enum bpf_prog_type type = attr->prog_type;
  2166		struct bpf_prog *prog, *dst_prog = NULL;
  2167		struct btf *attach_btf = NULL;
  2168		int err;
  2169		char license[128];
  2170		bool is_gpl;
  2171	
  2172		if (CHECK_ATTR(BPF_PROG_LOAD))
  2173			return -EINVAL;
  2174	
  2175		if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
  2176					 BPF_F_ANY_ALIGNMENT |
  2177					 BPF_F_TEST_STATE_FREQ |
  2178					 BPF_F_SLEEPABLE |
  2179					 BPF_F_TEST_RND_HI32))
  2180			return -EINVAL;
  2181	
  2182		if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
  2183		    (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
  2184		    !bpf_capable())
  2185			return -EPERM;
  2186	
  2187		/* copy eBPF program license from user space */
  2188		if (strncpy_from_bpfptr(license,
  2189					make_bpfptr(attr->license, uattr.is_kernel),
  2190					sizeof(license) - 1) < 0)
  2191			return -EFAULT;
  2192		license[sizeof(license) - 1] = 0;
  2193	
  2194		/* eBPF programs must be GPL compatible to use GPL-ed functions */
  2195		is_gpl = license_is_gpl_compatible(license);
  2196	
  2197		if (attr->insn_cnt == 0 ||
  2198		    attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
  2199			return -E2BIG;
  2200		if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
  2201		    type != BPF_PROG_TYPE_CGROUP_SKB &&
  2202		    !bpf_capable())
  2203			return -EPERM;
  2204	
  2205		if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
  2206			return -EPERM;
  2207		if (is_perfmon_prog_type(type) && !perfmon_capable())
  2208			return -EPERM;
  2209	
  2210		/* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog
  2211		 * or btf, we need to check which one it is
  2212		 */
  2213		if (attr->attach_prog_fd) {
  2214			dst_prog = bpf_prog_get(attr->attach_prog_fd);
  2215			if (IS_ERR(dst_prog)) {
  2216				dst_prog = NULL;
  2217				attach_btf = btf_get_by_fd(attr->attach_btf_obj_fd);
  2218				if (IS_ERR(attach_btf))
  2219					return -EINVAL;
  2220				if (!btf_is_kernel(attach_btf)) {
  2221					/* attaching through specifying bpf_prog's BTF
  2222					 * objects directly might be supported eventually
  2223					 */
  2224					btf_put(attach_btf);
  2225					return -ENOTSUPP;
  2226				}
  2227			}
  2228		} else if (attr->attach_btf_id) {
  2229			/* fall back to vmlinux BTF, if BTF type ID is specified */
  2230			attach_btf = bpf_get_btf_vmlinux();
  2231			if (IS_ERR(attach_btf))
  2232				return PTR_ERR(attach_btf);
  2233			if (!attach_btf)
  2234				return -EINVAL;
  2235			btf_get(attach_btf);
  2236		}
  2237	
  2238		bpf_prog_load_fixup_attach_type(attr);
  2239		if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
  2240					       attach_btf, attr->attach_btf_id,
  2241					       dst_prog)) {
  2242			if (dst_prog)
  2243				bpf_prog_put(dst_prog);
  2244			if (attach_btf)
  2245				btf_put(attach_btf);
  2246			return -EINVAL;
  2247		}
  2248	
  2249		/* plain bpf_prog allocation */
  2250		prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
  2251		if (!prog) {
  2252			if (dst_prog)
  2253				bpf_prog_put(dst_prog);
  2254			if (attach_btf)
  2255				btf_put(attach_btf);
  2256			return -ENOMEM;
  2257		}
  2258	
  2259		prog->expected_attach_type = attr->expected_attach_type;
  2260		prog->aux->attach_btf = attach_btf;
  2261		prog->aux->attach_btf_id = attr->attach_btf_id;
  2262		prog->aux->dst_prog = dst_prog;
  2263		prog->aux->offload_requested = !!attr->prog_ifindex;
  2264		prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
  2265	
  2266		err = security_bpf_prog_alloc(prog->aux);
  2267		if (err)
  2268			goto free_prog;
  2269	
  2270		prog->aux->user = get_current_user();
  2271		prog->len = attr->insn_cnt;
  2272	
  2273		err = -EFAULT;
  2274		if (copy_from_bpfptr(prog->insns,
  2275				     make_bpfptr(attr->insns, uattr.is_kernel),
  2276				     bpf_prog_insn_size(prog)) != 0)
  2277			goto free_prog_sec;
  2278	
  2279		if (attr->sig_len) {
  2280			char *signature;
  2281	
  2282			signature = kmalloc(attr->sig_len, GFP_USER);
  2283			if (!signature) {
  2284				err = -ENOMEM;
  2285				goto free_prog_sec;
  2286			}
  2287	
> 2288			if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
  2289				err = -EFAULT;
  2290				kfree(signature);
  2291				goto free_prog_sec;
  2292			}
  2293	
> 2294			err = verify_pkcs7_signature(prog->insns,
  2295						     prog->len * sizeof(struct bpf_insn),
  2296						     signature, attr->sig_len,
  2297						     VERIFY_USE_SECONDARY_KEYRING,
  2298						     VERIFYING_MODULE_SIGNATURE,
  2299						     NULL, NULL);
  2300			kfree(signature);
  2301	
  2302			if (err) {
  2303				printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
  2304				goto free_prog_sec;
  2305			}
  2306		}
  2307	
  2308		prog->orig_prog = NULL;
  2309		prog->jited = 0;
  2310	
  2311		atomic64_set(&prog->aux->refcnt, 1);
  2312		prog->gpl_compatible = is_gpl ? 1 : 0;
  2313	
  2314		if (bpf_prog_is_dev_bound(prog->aux)) {
  2315			err = bpf_prog_offload_init(prog, attr);
  2316			if (err)
  2317				goto free_prog_sec;
  2318		}
  2319	
  2320		/* find program type: socket_filter vs tracing_filter */
  2321		err = find_prog_type(type, prog);
  2322		if (err < 0)
  2323			goto free_prog_sec;
  2324	
  2325		prog->aux->load_time = ktime_get_boottime_ns();
  2326		err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
  2327				       sizeof(attr->prog_name));
  2328		if (err < 0)
  2329			goto free_prog_sec;
  2330	
  2331		/* run eBPF verifier */
  2332		err = bpf_check(&prog, attr, uattr);
  2333		if (err < 0)
  2334			goto free_used_maps;
  2335	
  2336		prog = bpf_prog_select_runtime(prog, &err);
  2337		if (err < 0)
  2338			goto free_used_maps;
  2339	
  2340		err = bpf_prog_alloc_id(prog);
  2341		if (err)
  2342			goto free_used_maps;
  2343	
  2344		/* Upon success of bpf_prog_alloc_id(), the BPF prog is
  2345		 * effectively publicly exposed. However, retrieving via
  2346		 * bpf_prog_get_fd_by_id() will take another reference,
  2347		 * therefore it cannot be gone underneath us.
  2348		 *
  2349		 * Only for the time /after/ successful bpf_prog_new_fd()
  2350		 * and before returning to userspace, we might just hold
  2351		 * one reference and any parallel close on that fd could
  2352		 * rip everything out. Hence, below notifications must
  2353		 * happen before bpf_prog_new_fd().
  2354		 *
  2355		 * Also, any failure handling from this point onwards must
  2356		 * be using bpf_prog_put() given the program is exposed.
  2357		 */
  2358		bpf_prog_kallsyms_add(prog);
  2359		perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
  2360		bpf_audit_prog(prog, BPF_AUDIT_LOAD);
  2361	
  2362		err = bpf_prog_new_fd(prog);
  2363		if (err < 0)
  2364			bpf_prog_put(prog);
  2365		return err;
  2366	
  2367	free_used_maps:
  2368		/* In case we have subprogs, we need to wait for a grace
  2369		 * period before we can tear down JIT memory since symbols
  2370		 * are already exposed under kallsyms.
  2371		 */
  2372		__bpf_prog_put_noref(prog, prog->aux->func_cnt);
  2373		return err;
  2374	free_prog_sec:
  2375		free_uid(prog->aux->user);
  2376		security_bpf_prog_free(prog->aux);
  2377	free_prog:
  2378		if (prog->aux->attach_btf)
  2379			btf_put(prog->aux->attach_btf);
  2380		bpf_prog_free(prog);
  2381		return err;
  2382	}
  2383	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 31072 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
  2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
  2021-10-13  2:37   ` kernel test robot
  2021-10-13  3:13   ` kernel test robot
@ 2021-10-13  3:36   ` kernel test robot
  2021-10-13 14:35   ` kernel test robot
  2021-10-24 22:35   ` kernel test robot
  4 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2021-10-13  3:36 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 9287 bytes --]

Hi Matteo,

[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: i386-buildonly-randconfig-r002-20211012 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/45c21d28e868dac39e5267e2e2b6f4e35f86b661
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
        git checkout 45c21d28e868dac39e5267e2e2b6f4e35f86b661
        # save the attached .config to linux build tree
        make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   kernel/bpf/syscall.c: In function 'bpf_prog_load':
>> kernel/bpf/syscall.c:2288:33: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
    2288 |   if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
         |                                 ^
   cc1: all warnings being treated as errors


vim +2288 kernel/bpf/syscall.c

  2162	
  2163	static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
  2164	{
  2165		enum bpf_prog_type type = attr->prog_type;
  2166		struct bpf_prog *prog, *dst_prog = NULL;
  2167		struct btf *attach_btf = NULL;
  2168		int err;
  2169		char license[128];
  2170		bool is_gpl;
  2171	
  2172		if (CHECK_ATTR(BPF_PROG_LOAD))
  2173			return -EINVAL;
  2174	
  2175		if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
  2176					 BPF_F_ANY_ALIGNMENT |
  2177					 BPF_F_TEST_STATE_FREQ |
  2178					 BPF_F_SLEEPABLE |
  2179					 BPF_F_TEST_RND_HI32))
  2180			return -EINVAL;
  2181	
  2182		if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
  2183		    (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
  2184		    !bpf_capable())
  2185			return -EPERM;
  2186	
  2187		/* copy eBPF program license from user space */
  2188		if (strncpy_from_bpfptr(license,
  2189					make_bpfptr(attr->license, uattr.is_kernel),
  2190					sizeof(license) - 1) < 0)
  2191			return -EFAULT;
  2192		license[sizeof(license) - 1] = 0;
  2193	
  2194		/* eBPF programs must be GPL compatible to use GPL-ed functions */
  2195		is_gpl = license_is_gpl_compatible(license);
  2196	
  2197		if (attr->insn_cnt == 0 ||
  2198		    attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
  2199			return -E2BIG;
  2200		if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
  2201		    type != BPF_PROG_TYPE_CGROUP_SKB &&
  2202		    !bpf_capable())
  2203			return -EPERM;
  2204	
  2205		if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
  2206			return -EPERM;
  2207		if (is_perfmon_prog_type(type) && !perfmon_capable())
  2208			return -EPERM;
  2209	
  2210		/* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog
  2211		 * or btf, we need to check which one it is
  2212		 */
  2213		if (attr->attach_prog_fd) {
  2214			dst_prog = bpf_prog_get(attr->attach_prog_fd);
  2215			if (IS_ERR(dst_prog)) {
  2216				dst_prog = NULL;
  2217				attach_btf = btf_get_by_fd(attr->attach_btf_obj_fd);
  2218				if (IS_ERR(attach_btf))
  2219					return -EINVAL;
  2220				if (!btf_is_kernel(attach_btf)) {
  2221					/* attaching through specifying bpf_prog's BTF
  2222					 * objects directly might be supported eventually
  2223					 */
  2224					btf_put(attach_btf);
  2225					return -ENOTSUPP;
  2226				}
  2227			}
  2228		} else if (attr->attach_btf_id) {
  2229			/* fall back to vmlinux BTF, if BTF type ID is specified */
  2230			attach_btf = bpf_get_btf_vmlinux();
  2231			if (IS_ERR(attach_btf))
  2232				return PTR_ERR(attach_btf);
  2233			if (!attach_btf)
  2234				return -EINVAL;
  2235			btf_get(attach_btf);
  2236		}
  2237	
  2238		bpf_prog_load_fixup_attach_type(attr);
  2239		if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
  2240					       attach_btf, attr->attach_btf_id,
  2241					       dst_prog)) {
  2242			if (dst_prog)
  2243				bpf_prog_put(dst_prog);
  2244			if (attach_btf)
  2245				btf_put(attach_btf);
  2246			return -EINVAL;
  2247		}
  2248	
  2249		/* plain bpf_prog allocation */
  2250		prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
  2251		if (!prog) {
  2252			if (dst_prog)
  2253				bpf_prog_put(dst_prog);
  2254			if (attach_btf)
  2255				btf_put(attach_btf);
  2256			return -ENOMEM;
  2257		}
  2258	
  2259		prog->expected_attach_type = attr->expected_attach_type;
  2260		prog->aux->attach_btf = attach_btf;
  2261		prog->aux->attach_btf_id = attr->attach_btf_id;
  2262		prog->aux->dst_prog = dst_prog;
  2263		prog->aux->offload_requested = !!attr->prog_ifindex;
  2264		prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
  2265	
  2266		err = security_bpf_prog_alloc(prog->aux);
  2267		if (err)
  2268			goto free_prog;
  2269	
  2270		prog->aux->user = get_current_user();
  2271		prog->len = attr->insn_cnt;
  2272	
  2273		err = -EFAULT;
  2274		if (copy_from_bpfptr(prog->insns,
  2275				     make_bpfptr(attr->insns, uattr.is_kernel),
  2276				     bpf_prog_insn_size(prog)) != 0)
  2277			goto free_prog_sec;
  2278	
  2279		if (attr->sig_len) {
  2280			char *signature;
  2281	
  2282			signature = kmalloc(attr->sig_len, GFP_USER);
  2283			if (!signature) {
  2284				err = -ENOMEM;
  2285				goto free_prog_sec;
  2286			}
  2287	
> 2288			if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
  2289				err = -EFAULT;
  2290				kfree(signature);
  2291				goto free_prog_sec;
  2292			}
  2293	
  2294			err = verify_pkcs7_signature(prog->insns,
  2295						     prog->len * sizeof(struct bpf_insn),
  2296						     signature, attr->sig_len,
  2297						     VERIFY_USE_SECONDARY_KEYRING,
  2298						     VERIFYING_MODULE_SIGNATURE,
  2299						     NULL, NULL);
  2300			kfree(signature);
  2301	
  2302			if (err) {
  2303				printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
  2304				goto free_prog_sec;
  2305			}
  2306		}
  2307	
  2308		prog->orig_prog = NULL;
  2309		prog->jited = 0;
  2310	
  2311		atomic64_set(&prog->aux->refcnt, 1);
  2312		prog->gpl_compatible = is_gpl ? 1 : 0;
  2313	
  2314		if (bpf_prog_is_dev_bound(prog->aux)) {
  2315			err = bpf_prog_offload_init(prog, attr);
  2316			if (err)
  2317				goto free_prog_sec;
  2318		}
  2319	
  2320		/* find program type: socket_filter vs tracing_filter */
  2321		err = find_prog_type(type, prog);
  2322		if (err < 0)
  2323			goto free_prog_sec;
  2324	
  2325		prog->aux->load_time = ktime_get_boottime_ns();
  2326		err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
  2327				       sizeof(attr->prog_name));
  2328		if (err < 0)
  2329			goto free_prog_sec;
  2330	
  2331		/* run eBPF verifier */
  2332		err = bpf_check(&prog, attr, uattr);
  2333		if (err < 0)
  2334			goto free_used_maps;
  2335	
  2336		prog = bpf_prog_select_runtime(prog, &err);
  2337		if (err < 0)
  2338			goto free_used_maps;
  2339	
  2340		err = bpf_prog_alloc_id(prog);
  2341		if (err)
  2342			goto free_used_maps;
  2343	
  2344		/* Upon success of bpf_prog_alloc_id(), the BPF prog is
  2345		 * effectively publicly exposed. However, retrieving via
  2346		 * bpf_prog_get_fd_by_id() will take another reference,
  2347		 * therefore it cannot be gone underneath us.
  2348		 *
  2349		 * Only for the time /after/ successful bpf_prog_new_fd()
  2350		 * and before returning to userspace, we might just hold
  2351		 * one reference and any parallel close on that fd could
  2352		 * rip everything out. Hence, below notifications must
  2353		 * happen before bpf_prog_new_fd().
  2354		 *
  2355		 * Also, any failure handling from this point onwards must
  2356		 * be using bpf_prog_put() given the program is exposed.
  2357		 */
  2358		bpf_prog_kallsyms_add(prog);
  2359		perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
  2360		bpf_audit_prog(prog, BPF_AUDIT_LOAD);
  2361	
  2362		err = bpf_prog_new_fd(prog);
  2363		if (err < 0)
  2364			bpf_prog_put(prog);
  2365		return err;
  2366	
  2367	free_used_maps:
  2368		/* In case we have subprogs, we need to wait for a grace
  2369		 * period before we can tear down JIT memory since symbols
  2370		 * are already exposed under kallsyms.
  2371		 */
  2372		__bpf_prog_put_noref(prog, prog->aux->func_cnt);
  2373		return err;
  2374	free_prog_sec:
  2375		free_uid(prog->aux->user);
  2376		security_bpf_prog_free(prog->aux);
  2377	free_prog:
  2378		if (prog->aux->attach_btf)
  2379			btf_put(prog->aux->attach_btf);
  2380		bpf_prog_free(prog);
  2381		return err;
  2382	}
  2383	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 38303 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
  2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
                     ` (2 preceding siblings ...)
  2021-10-13  3:36   ` kernel test robot
@ 2021-10-13 14:35   ` kernel test robot
  2021-10-24 22:35   ` kernel test robot
  4 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2021-10-13 14:35 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 11053 bytes --]

Hi Matteo,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: mips-randconfig-s031-20211013 (attached as .config)
compiler: mipsel-linux-gcc (GCC) 11.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/45c21d28e868dac39e5267e2e2b6f4e35f86b661
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
        git checkout 45c21d28e868dac39e5267e2e2b6f4e35f86b661
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=mips SHELL=/bin/bash kernel/bpf/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   command-line: note: in included file:
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_ACQUIRE redefined
   builtin:0:0: sparse: this was the original definition
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_SEQ_CST redefined
   builtin:0:0: sparse: this was the original definition
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_ACQ_REL redefined
   builtin:0:0: sparse: this was the original definition
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_RELEASE redefined
   builtin:0:0: sparse: this was the original definition
   kernel/bpf/syscall.c:2288:48: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const [noderef] __user *from @@     got char * @@
   kernel/bpf/syscall.c:2288:48: sparse:     expected void const [noderef] __user *from
   kernel/bpf/syscall.c:2288:48: sparse:     got char *
   kernel/bpf/syscall.c: note: in included file (through include/linux/bpf.h):
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:81:43: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:81:43: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
>> kernel/bpf/syscall.c:2288:55: sparse: sparse: non size-preserving integer to pointer cast
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar

vim +2288 kernel/bpf/syscall.c

  2162	
  2163	static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
  2164	{
  2165		enum bpf_prog_type type = attr->prog_type;
  2166		struct bpf_prog *prog, *dst_prog = NULL;
  2167		struct btf *attach_btf = NULL;
  2168		int err;
  2169		char license[128];
  2170		bool is_gpl;
  2171	
  2172		if (CHECK_ATTR(BPF_PROG_LOAD))
  2173			return -EINVAL;
  2174	
  2175		if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
  2176					 BPF_F_ANY_ALIGNMENT |
  2177					 BPF_F_TEST_STATE_FREQ |
  2178					 BPF_F_SLEEPABLE |
  2179					 BPF_F_TEST_RND_HI32))
  2180			return -EINVAL;
  2181	
  2182		if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
  2183		    (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
  2184		    !bpf_capable())
  2185			return -EPERM;
  2186	
  2187		/* copy eBPF program license from user space */
  2188		if (strncpy_from_bpfptr(license,
  2189					make_bpfptr(attr->license, uattr.is_kernel),
  2190					sizeof(license) - 1) < 0)
  2191			return -EFAULT;
  2192		license[sizeof(license) - 1] = 0;
  2193	
  2194		/* eBPF programs must be GPL compatible to use GPL-ed functions */
  2195		is_gpl = license_is_gpl_compatible(license);
  2196	
  2197		if (attr->insn_cnt == 0 ||
  2198		    attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
  2199			return -E2BIG;
  2200		if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
  2201		    type != BPF_PROG_TYPE_CGROUP_SKB &&
  2202		    !bpf_capable())
  2203			return -EPERM;
  2204	
  2205		if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
  2206			return -EPERM;
  2207		if (is_perfmon_prog_type(type) && !perfmon_capable())
  2208			return -EPERM;
  2209	
  2210		/* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog
  2211		 * or btf, we need to check which one it is
  2212		 */
  2213		if (attr->attach_prog_fd) {
  2214			dst_prog = bpf_prog_get(attr->attach_prog_fd);
  2215			if (IS_ERR(dst_prog)) {
  2216				dst_prog = NULL;
  2217				attach_btf = btf_get_by_fd(attr->attach_btf_obj_fd);
  2218				if (IS_ERR(attach_btf))
  2219					return -EINVAL;
  2220				if (!btf_is_kernel(attach_btf)) {
  2221					/* attaching through specifying bpf_prog's BTF
  2222					 * objects directly might be supported eventually
  2223					 */
  2224					btf_put(attach_btf);
  2225					return -ENOTSUPP;
  2226				}
  2227			}
  2228		} else if (attr->attach_btf_id) {
  2229			/* fall back to vmlinux BTF, if BTF type ID is specified */
  2230			attach_btf = bpf_get_btf_vmlinux();
  2231			if (IS_ERR(attach_btf))
  2232				return PTR_ERR(attach_btf);
  2233			if (!attach_btf)
  2234				return -EINVAL;
  2235			btf_get(attach_btf);
  2236		}
  2237	
  2238		bpf_prog_load_fixup_attach_type(attr);
  2239		if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
  2240					       attach_btf, attr->attach_btf_id,
  2241					       dst_prog)) {
  2242			if (dst_prog)
  2243				bpf_prog_put(dst_prog);
  2244			if (attach_btf)
  2245				btf_put(attach_btf);
  2246			return -EINVAL;
  2247		}
  2248	
  2249		/* plain bpf_prog allocation */
  2250		prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
  2251		if (!prog) {
  2252			if (dst_prog)
  2253				bpf_prog_put(dst_prog);
  2254			if (attach_btf)
  2255				btf_put(attach_btf);
  2256			return -ENOMEM;
  2257		}
  2258	
  2259		prog->expected_attach_type = attr->expected_attach_type;
  2260		prog->aux->attach_btf = attach_btf;
  2261		prog->aux->attach_btf_id = attr->attach_btf_id;
  2262		prog->aux->dst_prog = dst_prog;
  2263		prog->aux->offload_requested = !!attr->prog_ifindex;
  2264		prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
  2265	
  2266		err = security_bpf_prog_alloc(prog->aux);
  2267		if (err)
  2268			goto free_prog;
  2269	
  2270		prog->aux->user = get_current_user();
  2271		prog->len = attr->insn_cnt;
  2272	
  2273		err = -EFAULT;
  2274		if (copy_from_bpfptr(prog->insns,
  2275				     make_bpfptr(attr->insns, uattr.is_kernel),
  2276				     bpf_prog_insn_size(prog)) != 0)
  2277			goto free_prog_sec;
  2278	
  2279		if (attr->sig_len) {
  2280			char *signature;
  2281	
  2282			signature = kmalloc(attr->sig_len, GFP_USER);
  2283			if (!signature) {
  2284				err = -ENOMEM;
  2285				goto free_prog_sec;
  2286			}
  2287	
> 2288			if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
  2289				err = -EFAULT;
  2290				kfree(signature);
  2291				goto free_prog_sec;
  2292			}
  2293	
  2294			err = verify_pkcs7_signature(prog->insns,
  2295						     prog->len * sizeof(struct bpf_insn),
  2296						     signature, attr->sig_len,
  2297						     VERIFY_USE_SECONDARY_KEYRING,
  2298						     VERIFYING_MODULE_SIGNATURE,
  2299						     NULL, NULL);
  2300			kfree(signature);
  2301	
  2302			if (err) {
  2303				printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
  2304				goto free_prog_sec;
  2305			}
  2306		}
  2307	
  2308		prog->orig_prog = NULL;
  2309		prog->jited = 0;
  2310	
  2311		atomic64_set(&prog->aux->refcnt, 1);
  2312		prog->gpl_compatible = is_gpl ? 1 : 0;
  2313	
  2314		if (bpf_prog_is_dev_bound(prog->aux)) {
  2315			err = bpf_prog_offload_init(prog, attr);
  2316			if (err)
  2317				goto free_prog_sec;
  2318		}
  2319	
  2320		/* find program type: socket_filter vs tracing_filter */
  2321		err = find_prog_type(type, prog);
  2322		if (err < 0)
  2323			goto free_prog_sec;
  2324	
  2325		prog->aux->load_time = ktime_get_boottime_ns();
  2326		err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
  2327				       sizeof(attr->prog_name));
  2328		if (err < 0)
  2329			goto free_prog_sec;
  2330	
  2331		/* run eBPF verifier */
  2332		err = bpf_check(&prog, attr, uattr);
  2333		if (err < 0)
  2334			goto free_used_maps;
  2335	
  2336		prog = bpf_prog_select_runtime(prog, &err);
  2337		if (err < 0)
  2338			goto free_used_maps;
  2339	
  2340		err = bpf_prog_alloc_id(prog);
  2341		if (err)
  2342			goto free_used_maps;
  2343	
  2344		/* Upon success of bpf_prog_alloc_id(), the BPF prog is
  2345		 * effectively publicly exposed. However, retrieving via
  2346		 * bpf_prog_get_fd_by_id() will take another reference,
  2347		 * therefore it cannot be gone underneath us.
  2348		 *
  2349		 * Only for the time /after/ successful bpf_prog_new_fd()
  2350		 * and before returning to userspace, we might just hold
  2351		 * one reference and any parallel close on that fd could
  2352		 * rip everything out. Hence, below notifications must
  2353		 * happen before bpf_prog_new_fd().
  2354		 *
  2355		 * Also, any failure handling from this point onwards must
  2356		 * be using bpf_prog_put() given the program is exposed.
  2357		 */
  2358		bpf_prog_kallsyms_add(prog);
  2359		perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
  2360		bpf_audit_prog(prog, BPF_AUDIT_LOAD);
  2361	
  2362		err = bpf_prog_new_fd(prog);
  2363		if (err < 0)
  2364			bpf_prog_put(prog);
  2365		return err;
  2366	
  2367	free_used_maps:
  2368		/* In case we have subprogs, we need to wait for a grace
  2369		 * period before we can tear down JIT memory since symbols
  2370		 * are already exposed under kallsyms.
  2371		 */
  2372		__bpf_prog_put_noref(prog, prog->aux->func_cnt);
  2373		return err;
  2374	free_prog_sec:
  2375		free_uid(prog->aux->user);
  2376		security_bpf_prog_free(prog->aux);
  2377	free_prog:
  2378		if (prog->aux->attach_btf)
  2379			btf_put(prog->aux->attach_btf);
  2380		bpf_prog_free(prog);
  2381		return err;
  2382	}
  2383	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 37722 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
  2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
                     ` (3 preceding siblings ...)
  2021-10-13 14:35   ` kernel test robot
@ 2021-10-24 22:35   ` kernel test robot
  4 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2021-10-24 22:35 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 11053 bytes --]

Hi Matteo,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: mips-randconfig-s031-20211013 (attached as .config)
compiler: mipsel-linux-gcc (GCC) 11.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/45c21d28e868dac39e5267e2e2b6f4e35f86b661
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matteo-Croce/bpf-sign-bpf-programs/20211013-030207
        git checkout 45c21d28e868dac39e5267e2e2b6f4e35f86b661
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=mips SHELL=/bin/bash kernel/bpf/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   command-line: note: in included file:
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_ACQUIRE redefined
   builtin:0:0: sparse: this was the original definition
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_SEQ_CST redefined
   builtin:0:0: sparse: this was the original definition
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_ACQ_REL redefined
   builtin:0:0: sparse: this was the original definition
   builtin:1:9: sparse: sparse: preprocessor token __ATOMIC_RELEASE redefined
   builtin:0:0: sparse: this was the original definition
   kernel/bpf/syscall.c:2288:48: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const [noderef] __user *from @@     got char * @@
   kernel/bpf/syscall.c:2288:48: sparse:     expected void const [noderef] __user *from
   kernel/bpf/syscall.c:2288:48: sparse:     got char *
   kernel/bpf/syscall.c: note: in included file (through include/linux/bpf.h):
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:81:43: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:81:43: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar
>> kernel/bpf/syscall.c:2288:55: sparse: sparse: non size-preserving integer to pointer cast
   include/linux/bpfptr.h:52:47: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:52:47: sparse: sparse: cast from non-scalar

vim +2288 kernel/bpf/syscall.c

  2162	
  2163	static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
  2164	{
  2165		enum bpf_prog_type type = attr->prog_type;
  2166		struct bpf_prog *prog, *dst_prog = NULL;
  2167		struct btf *attach_btf = NULL;
  2168		int err;
  2169		char license[128];
  2170		bool is_gpl;
  2171	
  2172		if (CHECK_ATTR(BPF_PROG_LOAD))
  2173			return -EINVAL;
  2174	
  2175		if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
  2176					 BPF_F_ANY_ALIGNMENT |
  2177					 BPF_F_TEST_STATE_FREQ |
  2178					 BPF_F_SLEEPABLE |
  2179					 BPF_F_TEST_RND_HI32))
  2180			return -EINVAL;
  2181	
  2182		if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
  2183		    (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
  2184		    !bpf_capable())
  2185			return -EPERM;
  2186	
  2187		/* copy eBPF program license from user space */
  2188		if (strncpy_from_bpfptr(license,
  2189					make_bpfptr(attr->license, uattr.is_kernel),
  2190					sizeof(license) - 1) < 0)
  2191			return -EFAULT;
  2192		license[sizeof(license) - 1] = 0;
  2193	
  2194		/* eBPF programs must be GPL compatible to use GPL-ed functions */
  2195		is_gpl = license_is_gpl_compatible(license);
  2196	
  2197		if (attr->insn_cnt == 0 ||
  2198		    attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
  2199			return -E2BIG;
  2200		if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
  2201		    type != BPF_PROG_TYPE_CGROUP_SKB &&
  2202		    !bpf_capable())
  2203			return -EPERM;
  2204	
  2205		if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
  2206			return -EPERM;
  2207		if (is_perfmon_prog_type(type) && !perfmon_capable())
  2208			return -EPERM;
  2209	
  2210		/* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog
  2211		 * or btf, we need to check which one it is
  2212		 */
  2213		if (attr->attach_prog_fd) {
  2214			dst_prog = bpf_prog_get(attr->attach_prog_fd);
  2215			if (IS_ERR(dst_prog)) {
  2216				dst_prog = NULL;
  2217				attach_btf = btf_get_by_fd(attr->attach_btf_obj_fd);
  2218				if (IS_ERR(attach_btf))
  2219					return -EINVAL;
  2220				if (!btf_is_kernel(attach_btf)) {
  2221					/* attaching through specifying bpf_prog's BTF
  2222					 * objects directly might be supported eventually
  2223					 */
  2224					btf_put(attach_btf);
  2225					return -ENOTSUPP;
  2226				}
  2227			}
  2228		} else if (attr->attach_btf_id) {
  2229			/* fall back to vmlinux BTF, if BTF type ID is specified */
  2230			attach_btf = bpf_get_btf_vmlinux();
  2231			if (IS_ERR(attach_btf))
  2232				return PTR_ERR(attach_btf);
  2233			if (!attach_btf)
  2234				return -EINVAL;
  2235			btf_get(attach_btf);
  2236		}
  2237	
  2238		bpf_prog_load_fixup_attach_type(attr);
  2239		if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
  2240					       attach_btf, attr->attach_btf_id,
  2241					       dst_prog)) {
  2242			if (dst_prog)
  2243				bpf_prog_put(dst_prog);
  2244			if (attach_btf)
  2245				btf_put(attach_btf);
  2246			return -EINVAL;
  2247		}
  2248	
  2249		/* plain bpf_prog allocation */
  2250		prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
  2251		if (!prog) {
  2252			if (dst_prog)
  2253				bpf_prog_put(dst_prog);
  2254			if (attach_btf)
  2255				btf_put(attach_btf);
  2256			return -ENOMEM;
  2257		}
  2258	
  2259		prog->expected_attach_type = attr->expected_attach_type;
  2260		prog->aux->attach_btf = attach_btf;
  2261		prog->aux->attach_btf_id = attr->attach_btf_id;
  2262		prog->aux->dst_prog = dst_prog;
  2263		prog->aux->offload_requested = !!attr->prog_ifindex;
  2264		prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
  2265	
  2266		err = security_bpf_prog_alloc(prog->aux);
  2267		if (err)
  2268			goto free_prog;
  2269	
  2270		prog->aux->user = get_current_user();
  2271		prog->len = attr->insn_cnt;
  2272	
  2273		err = -EFAULT;
  2274		if (copy_from_bpfptr(prog->insns,
  2275				     make_bpfptr(attr->insns, uattr.is_kernel),
  2276				     bpf_prog_insn_size(prog)) != 0)
  2277			goto free_prog_sec;
  2278	
  2279		if (attr->sig_len) {
  2280			char *signature;
  2281	
  2282			signature = kmalloc(attr->sig_len, GFP_USER);
  2283			if (!signature) {
  2284				err = -ENOMEM;
  2285				goto free_prog_sec;
  2286			}
  2287	
> 2288			if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
  2289				err = -EFAULT;
  2290				kfree(signature);
  2291				goto free_prog_sec;
  2292			}
  2293	
  2294			err = verify_pkcs7_signature(prog->insns,
  2295						     prog->len * sizeof(struct bpf_insn),
  2296						     signature, attr->sig_len,
  2297						     VERIFY_USE_SECONDARY_KEYRING,
  2298						     VERIFYING_MODULE_SIGNATURE,
  2299						     NULL, NULL);
  2300			kfree(signature);
  2301	
  2302			if (err) {
  2303				printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
  2304				goto free_prog_sec;
  2305			}
  2306		}
  2307	
  2308		prog->orig_prog = NULL;
  2309		prog->jited = 0;
  2310	
  2311		atomic64_set(&prog->aux->refcnt, 1);
  2312		prog->gpl_compatible = is_gpl ? 1 : 0;
  2313	
  2314		if (bpf_prog_is_dev_bound(prog->aux)) {
  2315			err = bpf_prog_offload_init(prog, attr);
  2316			if (err)
  2317				goto free_prog_sec;
  2318		}
  2319	
  2320		/* find program type: socket_filter vs tracing_filter */
  2321		err = find_prog_type(type, prog);
  2322		if (err < 0)
  2323			goto free_prog_sec;
  2324	
  2325		prog->aux->load_time = ktime_get_boottime_ns();
  2326		err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
  2327				       sizeof(attr->prog_name));
  2328		if (err < 0)
  2329			goto free_prog_sec;
  2330	
  2331		/* run eBPF verifier */
  2332		err = bpf_check(&prog, attr, uattr);
  2333		if (err < 0)
  2334			goto free_used_maps;
  2335	
  2336		prog = bpf_prog_select_runtime(prog, &err);
  2337		if (err < 0)
  2338			goto free_used_maps;
  2339	
  2340		err = bpf_prog_alloc_id(prog);
  2341		if (err)
  2342			goto free_used_maps;
  2343	
  2344		/* Upon success of bpf_prog_alloc_id(), the BPF prog is
  2345		 * effectively publicly exposed. However, retrieving via
  2346		 * bpf_prog_get_fd_by_id() will take another reference,
  2347		 * therefore it cannot be gone underneath us.
  2348		 *
  2349		 * Only for the time /after/ successful bpf_prog_new_fd()
  2350		 * and before returning to userspace, we might just hold
  2351		 * one reference and any parallel close on that fd could
  2352		 * rip everything out. Hence, below notifications must
  2353		 * happen before bpf_prog_new_fd().
  2354		 *
  2355		 * Also, any failure handling from this point onwards must
  2356		 * be using bpf_prog_put() given the program is exposed.
  2357		 */
  2358		bpf_prog_kallsyms_add(prog);
  2359		perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
  2360		bpf_audit_prog(prog, BPF_AUDIT_LOAD);
  2361	
  2362		err = bpf_prog_new_fd(prog);
  2363		if (err < 0)
  2364			bpf_prog_put(prog);
  2365		return err;
  2366	
  2367	free_used_maps:
  2368		/* In case we have subprogs, we need to wait for a grace
  2369		 * period before we can tear down JIT memory since symbols
  2370		 * are already exposed under kallsyms.
  2371		 */
  2372		__bpf_prog_put_noref(prog, prog->aux->func_cnt);
  2373		return err;
  2374	free_prog_sec:
  2375		free_uid(prog->aux->user);
  2376		security_bpf_prog_free(prog->aux);
  2377	free_prog:
  2378		if (prog->aux->attach_btf)
  2379			btf_put(prog->aux->attach_btf);
  2380		bpf_prog_free(prog);
  2381		return err;
  2382	}
  2383	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 37722 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
  2021-10-12 18:58 [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
@ 2021-10-12 19:02 ` Matteo Croce
  0 siblings, 0 replies; 10+ messages in thread
From: Matteo Croce @ 2021-10-12 19:02 UTC (permalink / raw)
  To: bpf
  Cc: Linux Kernel Mailing List, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Arnaldo Carvalho de Melo, Luca Boccassi,
	David S. Miller

On Tue, Oct 12, 2021 at 8:59 PM Matteo Croce <mcroce@linux.microsoft.com> wrote:
>
> From: Matteo Croce <mcroce@microsoft.com>
>
> When loading a BPF program, pass a signature which is used to validate
> the instructions.
> The signature type is the same used to validate the kernel modules.
>
> Signed-off-by: Matteo Croce <mcroce@microsoft.com>
> ---

Slipped out by mistake, duplicate of:

https://lore.kernel.org/bpf/20211012190028.54828-2-mcroce@linux.microsoft.com/T/#u

Sorry,
-- 
per aspera ad upstream

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC bpf-next 1/2] bpf: add signature to eBPF instructions
@ 2021-10-12 18:58 Matteo Croce
  2021-10-12 19:02 ` Matteo Croce
  0 siblings, 1 reply; 10+ messages in thread
From: Matteo Croce @ 2021-10-12 18:58 UTC (permalink / raw)
  To: bpf
  Cc: linux-kernel, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Arnaldo Carvalho de Melo, Luca Boccassi,
	David S. Miller

From: Matteo Croce <mcroce@microsoft.com>

When loading a BPF program, pass a signature which is used to validate
the instructions.
The signature type is the same used to validate the kernel modules.

Signed-off-by: Matteo Croce <mcroce@microsoft.com>
---
 include/uapi/linux/bpf.h |  2 ++
 kernel/bpf/syscall.c     | 33 ++++++++++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c2b8857b8a1c..b9d259f26e92 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1336,6 +1336,8 @@ union bpf_attr {
 		};
 		__u32		:32;		/* pad */
 		__aligned_u64	fd_array;	/* array of FDs */
+		__aligned_u64	signature;	/* instruction's signature */
+		__u32		sig_len;	/* signature size */
 	};
 
 	struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 3c349b244a28..5589f655033d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -31,6 +31,8 @@
 #include <linux/bpf-netns.h>
 #include <linux/rcupdate_trace.h>
 #include <linux/memcontrol.h>
+#include <linux/verification.h>
+#include <linux/module_signature.h>
 
 #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
 			  (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
@@ -2156,7 +2158,7 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
 }
 
 /* last field in 'union bpf_attr' used by this command */
-#define	BPF_PROG_LOAD_LAST_FIELD fd_array
+#define	BPF_PROG_LOAD_LAST_FIELD sig_len
 
 static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
 {
@@ -2274,6 +2276,35 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
 			     bpf_prog_insn_size(prog)) != 0)
 		goto free_prog_sec;
 
+	if (attr->sig_len) {
+		char *signature;
+
+		signature = kmalloc(attr->sig_len, GFP_USER);
+		if (!signature) {
+			err = -ENOMEM;
+			goto free_prog_sec;
+		}
+
+		if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
+			err = -EFAULT;
+			kfree(signature);
+			goto free_prog_sec;
+		}
+
+		err = verify_pkcs7_signature(prog->insns,
+					     prog->len * sizeof(struct bpf_insn),
+					     signature, attr->sig_len,
+					     VERIFY_USE_SECONDARY_KEYRING,
+					     VERIFYING_MODULE_SIGNATURE,
+					     NULL, NULL);
+		kfree(signature);
+
+		if (err) {
+			printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
+			goto free_prog_sec;
+		}
+	}
+
 	prog->orig_prog = NULL;
 	prog->jited = 0;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-10-24 22:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-12 19:00 [RFC bpf-next 0/2] bpf: sign bpf programs Matteo Croce
2021-10-12 19:00 ` [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
2021-10-13  2:37   ` kernel test robot
2021-10-13  3:13   ` kernel test robot
2021-10-13  3:36   ` kernel test robot
2021-10-13 14:35   ` kernel test robot
2021-10-24 22:35   ` kernel test robot
2021-10-12 19:00 ` [RFC bpf-next 2/2] bpftool: add signature in skeleton Matteo Croce
  -- strict thread matches above, loose matches on Subject: below --
2021-10-12 18:58 [RFC bpf-next 1/2] bpf: add signature to eBPF instructions Matteo Croce
2021-10-12 19:02 ` Matteo Croce

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.