linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3 v2] Certificate insertion support for x86 bzImages
@ 2016-06-22 22:37 Mehmet Kayaalp
  2016-06-22 22:37 ` [PATCH 1/3 v2] KEYS: Support for inserting a certificate into x86 bzImage Mehmet Kayaalp
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Mehmet Kayaalp @ 2016-06-22 22:37 UTC (permalink / raw)
  To: David Howells, linux-kernel, linux-security-module,
	linux-ima-devel, keyrings
  Cc: Mimi Zohar, George Wilson, Stefan Berger, Mehmet Kayaalp

These patches add support for modifying the reserved space for extra 
certificates in a compressed bzImage in x86. This allows separating the 
system keyring certificate from the kernel build process. After the kernel 
image is distributed, the insert-sys-cert script can be used to insert the 
certificate for x86.

Changes:
* Rebased 2/3 on top of be1fb0e8eb082 ("kbuild: delete unnecessary "@:"")

Mehmet Kayaalp (3):
  KEYS: Support for inserting a certificate into x86 bzImage
  KEYS: Insert incompressible bytes to vmlinux to reserve space in
    bzImage
  KEYS: Print insert-sys-cert information to stdout instead of stderr

 arch/x86/boot/compressed/Makefile |   8 ++
 scripts/insert-sys-cert.c         | 212 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 212 insertions(+), 8 deletions(-)

-- 
2.7.4

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

* [PATCH 1/3 v2] KEYS: Support for inserting a certificate into x86 bzImage
  2016-06-22 22:37 [PATCH 0/3 v2] Certificate insertion support for x86 bzImages Mehmet Kayaalp
@ 2016-06-22 22:37 ` Mehmet Kayaalp
  2016-06-22 22:37 ` [PATCH 2/3 v2] KEYS: Insert incompressible bytes to vmlinux to reserve space in bzImage Mehmet Kayaalp
  2016-06-22 22:37 ` [PATCH 3/3 v2] KEYS: Print insert-sys-cert information to stdout instead of stderr Mehmet Kayaalp
  2 siblings, 0 replies; 5+ messages in thread
From: Mehmet Kayaalp @ 2016-06-22 22:37 UTC (permalink / raw)
  To: David Howells, linux-kernel, linux-security-module,
	linux-ima-devel, keyrings
  Cc: Mimi Zohar, George Wilson, Stefan Berger, Mehmet Kayaalp

The config option SYSTEM_EXTRA_CERTIFICATE (introduced in c4c361059585)
reserves space in vmlinux file, which is compressed to create the
self-extracting bzImage. This patch adds the capability of extracting the
vmlinux, inserting the certificate, and repackaging the result into a
bzImage.

It only works if the resulting compressed vmlinux is smaller than the
original. Otherwise re-linking would be required. To make the reserved
space allocate actual space in bzImage, a null key is inserted into vmlinux
before creating the bzImage:

	make vmlinux
	scripts/insert-sys-cert -b vmlinux -c /dev/null
	make bzImage

After null key insertion, the script populates the rest of the reserved
space with random bytes, which have poor compression. After receiving a
bzImage that is created this way, the actual certificate can be inserted
into the bzImage:

	scripts/insert-sys-cert -s <System.map> -z <bzImage> -c <certfile>

Signed-off-by: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 scripts/insert-sys-cert.c | 210 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 203 insertions(+), 7 deletions(-)

diff --git a/scripts/insert-sys-cert.c b/scripts/insert-sys-cert.c
index 8902836..6c6120d 100644
--- a/scripts/insert-sys-cert.c
+++ b/scripts/insert-sys-cert.c
@@ -7,7 +7,8 @@
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
  *
- * Usage: insert-sys-cert [-s <System.map> -b <vmlinux> -c <certfile>
+ * Usage: insert-sys-cert [-s <System.map>] -b <vmlinux> -c <certfile>
+ *                        [-s <System.map>] -z <bzImage> -c <certfile>
  */
 
 #define _GNU_SOURCE
@@ -257,6 +258,169 @@ static char *read_file(char *file_name, int *size)
 	return buf;
 }
 
+static void get_payload_info(char *bzimage, int *offset, int *size)
+{
+	unsigned int system_offset;
+	unsigned char setup_sectors;
+
+	setup_sectors = bzimage[0x1f1] + 1;
+	system_offset = setup_sectors * 512;
+	*offset = system_offset + *((int*)&bzimage[0x248]);
+	*size = *((int*)&bzimage[0x24c]);
+}
+
+static void update_payload_info(char* bzimage, int new_size)
+{
+	int offset, size;
+	get_payload_info(bzimage, &offset, &size);
+	*((int*)&bzimage[0x24c]) = new_size;
+	if (new_size < size)
+		memset(bzimage + offset + new_size, 0, size - new_size);
+}
+
+struct zipper {
+	unsigned char pattern[10];
+	int length;
+	char *command;
+	char *compress;
+};
+
+struct zipper zippers[] = {
+	{{0x7F,'E','L','F'}, 4, "cat", "cat"},
+	{{0x1F,0x8B}, 2, "gunzip", "gzip -n -f -9"},
+	{{0xFD,'7','z','X','Z',0}, 6, "unxz", "xz"},
+	{{'B','Z','h'},3, "bunzip2", "bzip2 -9"},
+	{{0xFF,'L','Z','M','A',0}, 6, "unlzma", "lzma -9"},
+	{{0xD3,'L','Z','O',0,'\r','\n',0x20,'\n'}, 9, "lzop -d", "lzop -9"}
+};
+
+static struct zipper* get_zipper(char *p) {
+	int i;
+	for (i = 0; i < sizeof(zippers)/sizeof(struct zipper); i++) {
+		if (memcmp(p, zippers[i].pattern, zippers[i].length) == 0)
+			return &zippers[i];
+	}
+	return NULL;
+}
+
+/*
+ * This only works for x86 bzImage
+ */
+static void extract_vmlinux(char *bzimage, int bzimage_size,
+			char **file, struct zipper **zipper)
+{
+	int r;
+	char src[15] = "vmlinux-XXXXXX";
+	char dest[15] = "vmlinux-XXXXXX";
+	char cmd[100];
+	int src_fd, dest_fd;
+	int offset, size;
+	struct zipper *z;
+
+	/* TODO: verify that bzImage is supported */
+
+	get_payload_info(bzimage, &offset, &size);
+	z = get_zipper(bzimage + offset);
+	if (z == NULL) {
+		err("Unable to determine the compression of vmlinux\n");
+		return;
+	}
+
+	src_fd = mkstemp(src);
+	if (src_fd == -1) {
+		perror("Could not create temp file");
+		return;
+	}
+
+	r = write(src_fd, bzimage + offset, size);
+	if (r != size) {
+		perror("Could not write vmlinux");
+		return;
+	}
+	dest_fd = mkstemp(dest);
+	if (dest_fd == -1) {
+		perror("Could not create temp file");
+		return;
+	}
+
+	snprintf(cmd, sizeof(cmd), "%s <%s >%s", z->command, src, dest);
+	info("Executing: %s\n", cmd);
+	r = system(cmd);
+	if (r!=0)
+		warn("Possible errors when extracting\n");
+
+	r = remove(src);
+	if (r!=0)
+		perror(src);
+
+	*file = strdup(dest);
+	*zipper = z;
+}
+
+static void repack_image(char *bzimage, int bzimage_size,
+			char* vmlinux_file, struct zipper *z)
+{
+	char tmp[15] = "vmlinux-XXXXXX";
+	char cmd[100];
+	int fd;
+	struct stat st;
+	int new_size;
+	int r;
+	int offset, size;
+
+	get_payload_info(bzimage, &offset, &size);
+
+	fd = mkstemp(tmp);
+	if (fd == -1) {
+		perror("Could not create temp file");
+		return;
+	}
+	snprintf(cmd, sizeof(cmd), "%s <%s >%s",
+			z->compress, vmlinux_file, tmp);
+
+	info("Executing: %s\n", cmd);
+	r = system(cmd);
+	if (r!=0)
+		warn("Possible errors when compressing\n");
+
+	r = remove(vmlinux_file);
+	if (r!=0)
+		perror(vmlinux_file);
+
+	if (fstat(fd, &st)) {
+		perror("Could not determine file size");
+		close(fd);
+
+	}
+	new_size = st.st_size;
+	if (new_size > size) {
+		err("Increase in compressed size is not supported.\n");
+		err("Old size was %d, new size is %d\n", size, new_size);
+		exit(EXIT_FAILURE);
+	}
+
+	r = read(fd, bzimage + offset, new_size);
+	if (r != new_size)
+		perror(tmp);
+
+	r = remove(tmp);
+	if (r!=0)
+		perror(tmp);
+
+	/* x86 specific patching of bzimage */
+	update_payload_info(bzimage, new_size);
+
+	/* TODO: update CRC */
+
+}
+
+static void fill_random(unsigned char *p, int n) {
+	srand(0);
+	int i;
+	for (i = 0; i < n; i++)
+		p[i] = rand();
+}
+
 static void print_sym(Elf_Ehdr *hdr, struct sym *s)
 {
 	info("sym:    %s\n", s->name);
@@ -267,18 +431,23 @@ static void print_sym(Elf_Ehdr *hdr, struct sym *s)
 
 static void print_usage(char *e)
 {
-	printf("Usage %s [-s <System.map>] -b <vmlinux> -c <certfile>\n", e);
+	printf("Usage: %s [-s <System.map>] -b <vmlinux> -c <certfile>\n", e);
+	printf("       %s [-s <System.map>] -z <bzImage> -c <certfile>\n", e);
 }
 
 int main(int argc, char **argv)
 {
 	char *system_map_file = NULL;
 	char *vmlinux_file = NULL;
+	char *bzimage_file = NULL;
 	char *cert_file = NULL;
 	int vmlinux_size;
+	int bzimage_size;
 	int cert_size;
 	Elf_Ehdr *hdr;
 	char *cert;
+	char *bzimage = NULL;
+	struct zipper *z = NULL;
 	FILE *system_map;
 	unsigned long *lsize;
 	int *used;
@@ -286,7 +455,7 @@ int main(int argc, char **argv)
 	Elf_Shdr *symtab = NULL;
 	struct sym cert_sym, lsize_sym, used_sym;
 
-	while ((opt = getopt(argc, argv, "b:c:s:")) != -1) {
+	while ((opt = getopt(argc, argv, "b:z:c:s:")) != -1) {
 		switch (opt) {
 		case 's':
 			system_map_file = optarg;
@@ -294,6 +463,9 @@ int main(int argc, char **argv)
 		case 'b':
 			vmlinux_file = optarg;
 			break;
+		case 'z':
+			bzimage_file = optarg;
+			break;
 		case 'c':
 			cert_file = optarg;
 			break;
@@ -302,7 +474,9 @@ int main(int argc, char **argv)
 		}
 	}
 
-	if (!vmlinux_file || !cert_file) {
+	if (!cert_file ||
+	(!vmlinux_file && !bzimage_file) ||
+	(vmlinux_file && bzimage_file)) {
 		print_usage(argv[0]);
 		exit(EXIT_FAILURE);
 	}
@@ -311,6 +485,16 @@ int main(int argc, char **argv)
 	if (!cert)
 		exit(EXIT_FAILURE);
 
+	if (bzimage_file) {
+		bzimage = map_file(bzimage_file, &bzimage_size);
+		if (!bzimage)
+			exit(EXIT_FAILURE);
+
+		extract_vmlinux(bzimage, bzimage_size, &vmlinux_file, &z);
+		if (!vmlinux_file)
+			exit(EXIT_FAILURE);
+	}
+
 	hdr = map_file(vmlinux_file, &vmlinux_size);
 	if (!hdr)
 		exit(EXIT_FAILURE);
@@ -386,7 +570,7 @@ int main(int argc, char **argv)
 	}
 
 	/* If the existing cert is the same, don't overwrite */
-	if (cert_size == *used &&
+	if (cert_size > 0 && cert_size == *used &&
 	    strncmp(cert_sym.content, cert, cert_size) == 0) {
 		warn("Certificate was already inserted.\n");
 		exit(EXIT_SUCCESS);
@@ -396,9 +580,11 @@ int main(int argc, char **argv)
 		warn("Replacing previously inserted certificate.\n");
 
 	memcpy(cert_sym.content, cert, cert_size);
+
 	if (cert_size < cert_sym.size)
-		memset(cert_sym.content + cert_size,
-			0, cert_sym.size - cert_size);
+		/* This makes the reserved space incompressable */
+		fill_random(cert_sym.content + cert_size,
+				cert_sym.size - cert_size);
 
 	*lsize = *lsize + cert_size - *used;
 	*used = cert_size;
@@ -406,5 +592,15 @@ int main(int argc, char **argv)
 						cert_sym.address);
 	info("Used %d bytes out of %d bytes reserved.\n", *used,
 						 cert_sym.size);
+
+	if (munmap(hdr, vmlinux_size) == -1) {
+		perror(vmlinux_file);
+		exit(EXIT_FAILURE);
+	}
+
+	if (bzimage) {
+		repack_image(bzimage, bzimage_size, vmlinux_file, z);
+	}
+
 	exit(EXIT_SUCCESS);
 }
-- 
2.7.4

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

* [PATCH 2/3 v2] KEYS: Insert incompressible bytes to vmlinux to reserve space in bzImage
  2016-06-22 22:37 [PATCH 0/3 v2] Certificate insertion support for x86 bzImages Mehmet Kayaalp
  2016-06-22 22:37 ` [PATCH 1/3 v2] KEYS: Support for inserting a certificate into x86 bzImage Mehmet Kayaalp
@ 2016-06-22 22:37 ` Mehmet Kayaalp
  2016-06-23  6:17   ` kbuild test robot
  2016-06-22 22:37 ` [PATCH 3/3 v2] KEYS: Print insert-sys-cert information to stdout instead of stderr Mehmet Kayaalp
  2 siblings, 1 reply; 5+ messages in thread
From: Mehmet Kayaalp @ 2016-06-22 22:37 UTC (permalink / raw)
  To: David Howells, linux-kernel, linux-security-module,
	linux-ima-devel, keyrings
  Cc: Mimi Zohar, George Wilson, Stefan Berger, Mehmet Kayaalp

Call insert-sys-cert script with null file to ensure that random bytes are
inserted to the space reserved with CONFIG_SYSTEM_EXTRA_CERTIFICATE, before
compressing the vmlinux. This results in an uncompressed reserved area
inside the bzImage as well, so that it can be replaced with an actual
certificate later (after the bzImage is distributed).

Cross compilation is not supported yet.

Signed-off-by: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 arch/x86/boot/compressed/Makefile | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index f135688..5b15e56 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -88,8 +88,16 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
 $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
 	$(call if_changed,ld)
 
+quiet_cmd_inscert = INSCERT /dev/null to $<
+      cmd_inscert = scripts/insert-sys-cert -b $< -c /dev/null > /dev/null
+
 OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S
 $(obj)/vmlinux.bin: vmlinux FORCE
+ifndef CROSS_COMPILE
+ifeq ("$(CONFIG_SYSTEM_EXTRA_CERTIFICATE)", "y")
+	$(call if_changed,inscert)
+endif
+endif
 	$(call if_changed,objcopy)
 
 targets += $(patsubst $(obj)/%,%,$(vmlinux-objs-y)) vmlinux.bin.all vmlinux.relocs
-- 
2.7.4

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

* [PATCH 3/3 v2] KEYS: Print insert-sys-cert information to stdout instead of stderr
  2016-06-22 22:37 [PATCH 0/3 v2] Certificate insertion support for x86 bzImages Mehmet Kayaalp
  2016-06-22 22:37 ` [PATCH 1/3 v2] KEYS: Support for inserting a certificate into x86 bzImage Mehmet Kayaalp
  2016-06-22 22:37 ` [PATCH 2/3 v2] KEYS: Insert incompressible bytes to vmlinux to reserve space in bzImage Mehmet Kayaalp
@ 2016-06-22 22:37 ` Mehmet Kayaalp
  2 siblings, 0 replies; 5+ messages in thread
From: Mehmet Kayaalp @ 2016-06-22 22:37 UTC (permalink / raw)
  To: David Howells, linux-kernel, linux-security-module,
	linux-ima-devel, keyrings
  Cc: Mimi Zohar, George Wilson, Stefan Berger, Mehmet Kayaalp

Detailed INFO output should go to stdout instead of stderr. This removes
the clutter from the output of build, which discards stdout.

Fixes: c4c361059585 ("KEYS: Reserve an extra certificate symbol for inserting without recompiling")

Signed-off-by: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 scripts/insert-sys-cert.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/insert-sys-cert.c b/scripts/insert-sys-cert.c
index 6c6120d..75e646d 100644
--- a/scripts/insert-sys-cert.c
+++ b/scripts/insert-sys-cert.c
@@ -31,7 +31,7 @@
 #define USED_SYM  "system_extra_cert_used"
 #define LSIZE_SYM "system_certificate_list_size"
 
-#define info(format, args...) fprintf(stderr, "INFO:    " format, ## args)
+#define info(format, args...) fprintf(stdout, "INFO:    " format, ## args)
 #define warn(format, args...) fprintf(stdout, "WARNING: " format, ## args)
 #define  err(format, args...) fprintf(stderr, "ERROR:   " format, ## args)
 
-- 
2.7.4

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

* Re: [PATCH 2/3 v2] KEYS: Insert incompressible bytes to vmlinux to reserve space in bzImage
  2016-06-22 22:37 ` [PATCH 2/3 v2] KEYS: Insert incompressible bytes to vmlinux to reserve space in bzImage Mehmet Kayaalp
@ 2016-06-23  6:17   ` kbuild test robot
  0 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2016-06-23  6:17 UTC (permalink / raw)
  To: Mehmet Kayaalp
  Cc: kbuild-all, David Howells, linux-kernel, linux-security-module,
	linux-ima-devel, keyrings, Mimi Zohar, George Wilson,
	Stefan Berger, Mehmet Kayaalp

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

Hi,

[auto build test ERROR on v4.7-rc4]
[also build test ERROR on next-20160622]
[cannot apply to dhowells-fs/fscache tip/x86/core]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Mehmet-Kayaalp/KEYS-Support-for-inserting-a-certificate-into-x86-bzImage/20160623-064412
config: i386-allyesconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

>> ERROR:   ELF class mismatch.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 54399 bytes --]

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

end of thread, other threads:[~2016-06-23  6:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-22 22:37 [PATCH 0/3 v2] Certificate insertion support for x86 bzImages Mehmet Kayaalp
2016-06-22 22:37 ` [PATCH 1/3 v2] KEYS: Support for inserting a certificate into x86 bzImage Mehmet Kayaalp
2016-06-22 22:37 ` [PATCH 2/3 v2] KEYS: Insert incompressible bytes to vmlinux to reserve space in bzImage Mehmet Kayaalp
2016-06-23  6:17   ` kbuild test robot
2016-06-22 22:37 ` [PATCH 3/3 v2] KEYS: Print insert-sys-cert information to stdout instead of stderr Mehmet Kayaalp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).