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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ messages in thread

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

Thread overview: 8+ 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

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.