All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Hutchings <ben@decadent.org.uk>
To: linux-modules@vger.kernel.org
Cc: 820010@bugs.debian.org
Subject: [PATCH v2] libkmod: Add support for detached module signatures
Date: Tue, 5 Apr 2016 01:32:38 +0100	[thread overview]
Message-ID: <20160405003237.GK21187@decadent.org.uk> (raw)
In-Reply-To: <20160405001611.GJ21187@decadent.org.uk>

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

Debian will not sign modules during the kernel package build, as this
conflicts with the goal of reproducible builds.  Instead, we will
generate detached signatures offline and include them in a second
package.

We could attach the signatures when building this second package or at
installation time, but that leads to duplication of all modules,
either in the archive or on users' systems.

To avoid this, add support to libkmod for concatenating modules with
detached signatures (files with the '.sig' extension) at load time.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
v2: Fix syntax error in the xz case

Missed this because I didn't realise the Debian package disables gzip
and xz support.

Ben.

 libkmod/libkmod-file.c | 110 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 103 insertions(+), 7 deletions(-)

diff --git a/libkmod/libkmod-file.c b/libkmod/libkmod-file.c
index 5eeba6a912a2..cb1da3c9e2ae 100644
--- a/libkmod/libkmod-file.c
+++ b/libkmod/libkmod-file.c
@@ -52,6 +52,7 @@ struct kmod_file {
 	gzFile gzf;
 #endif
 	int fd;
+	int sig_fd;
 	bool direct;
 	off_t size;
 	void *memory;
@@ -60,6 +61,37 @@ struct kmod_file {
 	struct kmod_elf *elf;
 };
 
+static int append_detached_sig(struct kmod_file *file, size_t buf_size)
+{
+	struct stat st;
+	ssize_t read_size;
+
+	if (file->sig_fd < 0)
+		return 0;
+
+	if (fstat(file->sig_fd, &st) < 0)
+		return -errno;
+
+	/* Grow the buffer if necessary */
+	if ((size_t)st.st_size > buf_size - file->size) {
+		void *tmp = realloc(file->memory, file->size + st.st_size);
+		if (tmp == NULL)
+			return -errno;
+		file->memory = tmp;
+	}
+
+	read_size = read(file->sig_fd, (char *)file->memory + file->size,
+			 st.st_size);
+	if (read_size < 0)
+		return -errno;
+	if (read_size != st.st_size)
+		return -EINVAL;
+
+	file->size += read_size;
+
+	return 0;
+}
+
 #ifdef ENABLE_XZ
 static void xz_uncompress_belch(struct kmod_file *file, lzma_ret ret)
 {
@@ -144,6 +176,7 @@ static int load_xz(struct kmod_file *file)
 {
 	lzma_stream strm = LZMA_STREAM_INIT;
 	lzma_ret lzret;
+	size_t buf_size;
 	int ret;
 
 	lzret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
@@ -155,7 +188,14 @@ static int load_xz(struct kmod_file *file)
 		return -EINVAL;
 	}
 	ret = xz_uncompress(&strm, file);
+	buf_size = file->size + strm.avail_out;
 	lzma_end(&strm);
+
+	if (!ret) {
+		ret = append_detached_sig(file, buf_size);
+		if (ret)
+			free(file->memory);
+	}
 	return ret;
 }
 
@@ -214,6 +254,11 @@ static int load_zlib(struct kmod_file *file)
 
 	file->memory = p;
 	file->size = did;
+
+	err = append_detached_sig(file, total);
+	if (err)
+		goto error;
+
 	p = NULL;
 	return 0;
 
@@ -254,18 +299,50 @@ static int load_reg(struct kmod_file *file)
 	if (fstat(file->fd, &st) < 0)
 		return -errno;
 
-	file->size = st.st_size;
-	file->memory = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE,
-			    file->fd, 0);
-	if (file->memory == MAP_FAILED)
-		return -errno;
-	file->direct = true;
+	if (file->sig_fd < 0) {
+		file->size = st.st_size;
+		file->memory = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE,
+				    file->fd, 0);
+		if (file->memory == MAP_FAILED)
+			return -errno;
+		file->direct = true;
+	} else {
+		size_t plain_size = st.st_size, sig_size;
+		_cleanup_free_ unsigned char *p = NULL;
+		ssize_t ret;
+
+		if (fstat(file->sig_fd, &st) < 0)
+			return -errno;
+		sig_size = st.st_size;
+
+		p = malloc(plain_size + sig_size);
+		if (!p)
+			return -errno;
+
+		ret = read(file->fd, p, plain_size);
+		if (ret < 0)
+			return -errno;
+		if ((size_t)ret != plain_size)
+			return -EINVAL;
+		file->memory = p;
+		file->size = plain_size;
+
+		ret = append_detached_sig(file, plain_size + sig_size);
+		if (ret)
+			return ret;
+
+		p = NULL;
+	}
+
 	return 0;
 }
 
 static void unload_reg(struct kmod_file *file)
 {
-	munmap(file->memory, file->size);
+	if (file->direct)
+		munmap(file->memory, file->size);
+	else
+		free(file->memory);
 }
 
 static const struct file_ops reg_ops = {
@@ -285,6 +362,7 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
 						const char *filename)
 {
 	struct kmod_file *file = calloc(1, sizeof(struct kmod_file));
+	char *sig_filename = NULL;
 	const struct comp_type *itr;
 	size_t magic_size_max = 0;
 	int err;
@@ -292,12 +370,25 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
 	if (file == NULL)
 		return NULL;
 
+	file->sig_fd = -1;
+
 	file->fd = open(filename, O_RDONLY|O_CLOEXEC);
 	if (file->fd < 0) {
 		err = -errno;
 		goto error;
 	}
 
+	/* Try to open a detached signature.  If it's missing, that's OK. */
+	if (asprintf(&sig_filename, "%s.sig", filename) < 0) {
+		err = -errno;
+		goto error;
+	}
+	file->sig_fd = open(sig_filename, O_RDONLY|O_CLOEXEC);
+	if (file->sig_fd < 0 && errno != ENOENT) {
+		err = -errno;
+		goto error;
+	}
+
 	for (itr = comp_types; itr->ops.load != NULL; itr++) {
 		if (magic_size_max < itr->magic_size)
 			magic_size_max = itr->magic_size;
@@ -336,7 +427,10 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
 	err = file->ops->load(file);
 	file->ctx = ctx;
 error:
+	free(sig_filename);
 	if (err < 0) {
+		if (file->sig_fd >= 0)
+			close(file->sig_fd);
 		if (file->fd >= 0)
 			close(file->fd);
 		free(file);
@@ -373,6 +467,8 @@ void kmod_file_unref(struct kmod_file *file)
 		kmod_elf_unref(file->elf);
 
 	file->ops->unload(file);
+	if (file->sig_fd >= 0)
+		close(file->sig_fd);
 	if (file->fd >= 0)
 		close(file->fd);
 	free(file);

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

  reply	other threads:[~2016-04-05  0:32 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-05  0:16 [PATCH] " Ben Hutchings
2016-04-05  0:32 ` Ben Hutchings [this message]
2016-04-13  4:05   ` [PATCH v2] " Lucas De Marchi
2016-04-13 10:00     ` Ben Hutchings
2016-05-17 12:51       ` Ben Hutchings
2016-05-21 18:31       ` Lucas De Marchi
2016-05-21 18:40         ` Bug#820010: " Marco d'Itri
2016-05-21 19:01         ` Ben Hutchings
2016-05-29 12:48           ` Ben Hutchings
2016-06-04 14:13             ` Lucas De Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160405003237.GK21187@decadent.org.uk \
    --to=ben@decadent.org.uk \
    --cc=820010@bugs.debian.org \
    --cc=linux-modules@vger.kernel.org \
    --subject='Re: [PATCH v2] libkmod: Add support for detached module signatures' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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.