Package: src:kmod Version: 22-1.1 Severity: normal Tags: patch Please apply the following patch that adds support for detached module signatures. This is needed to support module signing without sacrificing reproducibility or duplicating files. It has *not* been submitted upstream, but I can do that if you prefer. I have also not tested the gzip and xz cases.
Ben.
---
libkmod/libkmod-file.c | 108 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 101 insertions(+), 7 deletions(-)
--- 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 *fil
{
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 *fil
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 *f
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 *fi
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 s
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 s
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 s
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 *f
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);
signature.asc
Description: Digital signature

