diff --git a/.efivar.metadata b/.efivar.metadata
index 3116e27..5e01996 100644
--- a/.efivar.metadata
+++ b/.efivar.metadata
@@ -1 +1 @@
-cf8563d5783fce87f331ae9eed531648e1aeb861 SOURCES/efivar-0.11.tar.bz2
+3f1e11c83b5edaafaa76cc5e2ac72921d2244876 SOURCES/efivar-31.tar.bz2
diff --git a/.gitignore b/.gitignore
index 7eacbf4..005c3cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/efivar-0.11.tar.bz2
+SOURCES/efivar-31.tar.bz2
diff --git a/SOURCES/0001-Revert-Only-open-with-O_CREAT-if-we-re-not-using-EFI.patch b/SOURCES/0001-Revert-Only-open-with-O_CREAT-if-we-re-not-using-EFI.patch
deleted file mode 100644
index a6702f0..0000000
--- a/SOURCES/0001-Revert-Only-open-with-O_CREAT-if-we-re-not-using-EFI.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 5a43dce1ef31d3d4927a4c67400a7e33ff8afe75 Mon Sep 17 00:00:00 2001
-From: Peter Jones <pjones@redhat.com>
-Date: Fri, 22 Aug 2014 12:23:28 -0400
-Subject: [PATCH] Revert "Only open with O_CREAT if we're not using
- EFI_VARIABLE_APPEND_WRITE."
-
-This reverts commit 7153d0dbb7d1d36b1712dfa91e2e62043880fdfa.
----
- src/efivarfs.c | 5 +----
- 1 file changed, 1 insertion(+), 4 deletions(-)
-
-diff --git a/src/efivarfs.c b/src/efivarfs.c
-index b918c67..9b77d4e 100644
---- a/src/efivarfs.c
-+++ b/src/efivarfs.c
-@@ -209,10 +209,7 @@ efivarfs_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
- 			goto err;
- 	}
- 
--	int flags = O_WRONLY;
--	if (!(attributes & EFI_VARIABLE_APPEND_WRITE))
--		flags |= O_CREAT|O_EXCL;
--	fd = open(path, flags, 0600);
-+	fd = open(path, O_WRONLY|O_CREAT, 0600);
- 	if (fd < 0)
- 		goto err;
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0001-libabigail-isn-t-in-RHEL-yet-so-nerf-the-abi-check.patch b/SOURCES/0001-libabigail-isn-t-in-RHEL-yet-so-nerf-the-abi-check.patch
new file mode 100644
index 0000000..43ed277
--- /dev/null
+++ b/SOURCES/0001-libabigail-isn-t-in-RHEL-yet-so-nerf-the-abi-check.patch
@@ -0,0 +1,82 @@
+From 78bda9cefdb5e29cedd379c1b9ea9fd8274d7c5d Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 13 Mar 2017 13:05:58 -0400
+Subject: [PATCH 1/3] libabigail isn't in RHEL yet, so nerf the abi check.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ Make.rules   | 9 ---------
+ Makefile     | 6 +++---
+ src/Makefile | 5 -----
+ 3 files changed, 3 insertions(+), 17 deletions(-)
+
+diff --git a/Make.rules b/Make.rules
+index 88b9aa7..a7d6a23 100644
+--- a/Make.rules
++++ b/Make.rules
+@@ -22,15 +22,6 @@ include $(TOPDIR)/Make.version
+ 	  -Wl,--version-script=$(MAP) \
+ 	  -o $@ $^ $(LDLIBS)
+ 
+-%.abixml : %.so
+-	$(ABIDW) --headers-dir $(TOPDIR)/src/include/efivar/ --out-file $@ $^
+-
+-%.abicheck : %.so
+-	$(ABIDIFF) --suppr \
+-		$(patsubst %.so,%.abignore,$<) \
+-		$(patsubst %.so,%.abixml,$<) \
+-		$<
+-
+ %.o : %.c
+ 	$(CC) $(cflags) -fPIC $(CPPFLAGS) -c -o $@ $(filter %.c %.o %.S,$^)
+ 
+diff --git a/Makefile b/Makefile
+index 4d6d308..504a747 100644
+--- a/Makefile
++++ b/Makefile
+@@ -17,7 +17,7 @@ install :
+ 		$(MAKE) -C $$x $@ ; \
+ 	done
+ 
+-abidw abicheck efivar efivar-static static:
++efivar efivar-static static:
+ 	$(MAKE) -C src $@
+ 
+ $(SUBDIRS) :
+@@ -44,7 +44,7 @@ clean :
+ 
+ GITTAG = $(VERSION)
+ 
+-test-archive: abicheck efivar.spec
++test-archive: efivar.spec
+ 	@rm -rf /tmp/efivar-$(VERSION) /tmp/efivar-$(VERSION)-tmp
+ 	@mkdir -p /tmp/efivar-$(VERSION)-tmp
+ 	@git archive --format=tar $(shell git branch | awk '/^*/ { print $$2 }') | ( cd /tmp/efivar-$(VERSION)-tmp/ ; tar x )
+@@ -58,7 +58,7 @@ test-archive: abicheck efivar.spec
+ tag:
+ 	git tag -s $(GITTAG) refs/heads/master
+ 
+-archive: abicheck abidw tag efivar.spec
++archive: tag efivar.spec
+ 	@rm -rf /tmp/efivar-$(VERSION) /tmp/efivar-$(VERSION)-tmp
+ 	@mkdir -p /tmp/efivar-$(VERSION)-tmp
+ 	@git archive --format=tar $(GITTAG) | ( cd /tmp/efivar-$(VERSION)-tmp/ ; tar x )
+diff --git a/src/Makefile b/src/Makefile
+index 0c16597..a5d98ec 100644
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -32,11 +32,6 @@ all : $(TARGETS)
+ 
+ static : $(STATICTARGETS)
+ 
+-abidw : $(patsubst %.so,%.abixml,$(LIBTARGETS))
+-	git commit -m "Update .abixml files" -s $^
+-
+-abicheck : $(patsubst %.so,%.abicheck,$(LIBTARGETS))
+-
+ ./guid-symbols.c : include/efivar/efivar-guids.h
+ ./guids.bin : include/efivar/efivar-guids.h
+ ./names.bin : include/efivar/efivar-guids.h
+-- 
+2.9.3
+
diff --git a/SOURCES/0002-Don-t-use-_Generic-because-gcc-4.x-doesn-t-have-it.patch b/SOURCES/0002-Don-t-use-_Generic-because-gcc-4.x-doesn-t-have-it.patch
new file mode 100644
index 0000000..fd34b85
--- /dev/null
+++ b/SOURCES/0002-Don-t-use-_Generic-because-gcc-4.x-doesn-t-have-it.patch
@@ -0,0 +1,48 @@
+From 1b74597f9327ae2d763ae8863ac784a5a0d6bb93 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 13 Mar 2017 13:36:55 -0400
+Subject: [PATCH 2/3] Don't use _Generic because gcc 4.x doesn't have it...
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/util.h | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/src/util.h b/src/util.h
+index 0af7dbe..7ad6ce4 100644
+--- a/src/util.h
++++ b/src/util.h
+@@ -105,14 +105,29 @@
+ 	})
+ #endif
+ 
++#if defined(__GNUC__) && defined(__GNUC_MINOR__)
++#if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1
+ #define add(a, b, c) _Generic((c),					\
+ 			      int *: int_add(a,b,c),			\
+ 			      long *: long_add(a,b,c),			\
+ 			      unsigned long *: ulong_add(a,b,c))
+-
+ #define mult(a, b, c) _Generic((c),					\
+ 			      long *: long_mult(a,b,c),			\
+ 			      unsigned long *: ulong_mult(a,b,c))
++#endif
++#endif
++
++#ifndef add
++#define add(a, b, c) ({						\
++		(*(c)) = ((a) + (b));				\
++		})
++#endif
++#ifndef mult
++#define mult(a, b, c) ({					\
++		(*(c)) = ((a) * (b));				\
++		})
++#endif
++
+ 
+ static inline int
+ __attribute__((unused))
+-- 
+2.9.3
+
diff --git a/SOURCES/0003-popt-devel-in-RHEL-7.4-doesn-t-provide-popt.pc-so-in.patch b/SOURCES/0003-popt-devel-in-RHEL-7.4-doesn-t-provide-popt.pc-so-in.patch
new file mode 100644
index 0000000..663746f
--- /dev/null
+++ b/SOURCES/0003-popt-devel-in-RHEL-7.4-doesn-t-provide-popt.pc-so-in.patch
@@ -0,0 +1,34 @@
+From 262e2900dde1e03d499b3e06f389dcdd8f12f2fd Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 13 Mar 2017 14:03:55 -0400
+Subject: [PATCH 3/3] popt-devel in RHEL 7.4 doesn't provide popt.pc, so
+ include it the other way.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/Makefile | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/src/Makefile b/src/Makefile
+index a5d98ec..c957d84 100644
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -56,13 +56,11 @@ libefivar.so : LIBS=dl
+ libefivar.so : MAP=libefivar.map
+ 
+ efivar : efivar.c | libefivar.so
+-efivar : LIBS=efivar dl
+-efivar : PKGS=popt
++efivar : LIBS=efivar dl popt
+ 
+ efivar-static : efivar.c $(patsubst %.o,%.static.o,$(LIBEFIVAR_OBJECTS))
+ efivar-static : | $(GENERATED_SOURCES)
+-efivar-static : LIBS=dl
+-efivar-static : PKGS=popt
++efivar-static : LIBS=dl popt
+ 
+ libefiboot.a : $(patsubst %.o,%.static.o,$(LIBEFIBOOT_OBJECTS))
+ 
+-- 
+2.9.3
+
diff --git a/SOURCES/0004-efi_loadopt_args_from_file-fix-leaked-file-descripto.patch b/SOURCES/0004-efi_loadopt_args_from_file-fix-leaked-file-descripto.patch
new file mode 100644
index 0000000..af9fbf5
--- /dev/null
+++ b/SOURCES/0004-efi_loadopt_args_from_file-fix-leaked-file-descripto.patch
@@ -0,0 +1,35 @@
+From 0967cd89ae6c1e55c1d136669e2f426752f233f4 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:40:26 -0400
+Subject: [PATCH 04/22] efi_loadopt_args_from_file(): fix leaked file
+ descriptor.
+
+In the case where we're just trying to figure out the file's size, we're
+failing to close the file.  So close it.
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/loadopt.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/loadopt.c b/src/loadopt.c
+index ce88986..a3c1ba9 100644
+--- a/src/loadopt.c
++++ b/src/loadopt.c
+@@ -275,8 +275,10 @@ efi_loadopt_args_from_file(uint8_t *buf, ssize_t size, char *filename)
+ 	if (rc < 0)
+ 		goto err;
+ 
+-	if (size == 0)
++	if (size == 0) {
++		fclose(f);
+ 		return statbuf.st_size;
++	}
+ 
+ 	if (size < statbuf.st_size) {
+ 		errno = ENOSPC;
+-- 
+2.12.2
+
diff --git a/SOURCES/0005-make_mac_path-fix-leaked-file-descriptor.patch b/SOURCES/0005-make_mac_path-fix-leaked-file-descriptor.patch
new file mode 100644
index 0000000..85bf612
--- /dev/null
+++ b/SOURCES/0005-make_mac_path-fix-leaked-file-descriptor.patch
@@ -0,0 +1,41 @@
+From f3304710b72de55249ef461c544edffd5705bdc7 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:42:25 -0400
+Subject: [PATCH 05/22] make_mac_path(): fix leaked file descriptor.
+
+When make_mac_path() gets an error from efidp_make_mac_addr(), it fails
+to close the file descriptor to the network device.  So close it.  Also
+ensure that the ifrn_name field is NUL terminated.
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/linux.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/linux.c b/src/linux.c
+index 34ed479..3c77a93 100644
+--- a/src/linux.c
++++ b/src/linux.c
+@@ -1035,6 +1035,7 @@ make_mac_path(uint8_t *buf, ssize_t size, const char * const ifname)
+ 
+ 	memset(&ifr, 0, sizeof (ifr));
+ 	strncpy(ifr.ifr_name, ifname, IF_NAMESIZE);
++	ifr.ifr_name[IF_NAMESIZE-1] = '\0';
+ 	drvinfo.cmd = ETHTOOL_GDRVINFO;
+ 	ifr.ifr_data = (caddr_t)&drvinfo;
+ 
+@@ -1062,7 +1063,8 @@ make_mac_path(uint8_t *buf, ssize_t size, const char * const ifname)
+ 				 (uint8_t *)ifr.ifr_ifru.ifru_hwaddr.sa_data,
+ 				 sizeof(ifr.ifr_ifru.ifru_hwaddr.sa_data));
+ 	if (sz < 0)
+-		return -1;
++		goto err;
++
+ 	off += sz;
+ 	ret = off;
+ err:
+-- 
+2.12.2
+
diff --git a/SOURCES/0006-gpt_disk_get_partition_info-free-our-allocations-on-.patch b/SOURCES/0006-gpt_disk_get_partition_info-free-our-allocations-on-.patch
new file mode 100644
index 0000000..aff5553
--- /dev/null
+++ b/SOURCES/0006-gpt_disk_get_partition_info-free-our-allocations-on-.patch
@@ -0,0 +1,48 @@
+From 939e4a8524821ccc30b34fec97416bc1b97b5455 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:44:43 -0400
+Subject: [PATCH 06/22] gpt_disk_get_partition_info(): free our allocations on
+ the error path.
+
+When gpt_disk_get_partition_info() discovers that a partition is
+invalid, it returns error, but it forgets to free its allocations.
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/gpt.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/src/gpt.c b/src/gpt.c
+index 30cbdfd..e9c713b 100644
+--- a/src/gpt.c
++++ b/src/gpt.c
+@@ -640,7 +640,7 @@ gpt_disk_get_partition_info(int fd, uint32_t num, uint64_t * start,
+ 	gpt_entry *ptes = NULL, *p;
+ 	int rc = 0;
+ 
+-	char *report=getenv("LIBEFIBOOT_REPORT_GPT_ERRORS");
++	char *report = getenv("LIBEFIBOOT_REPORT_GPT_ERRORS");
+ 	if (report)
+ 		report_errors = 1;
+ 
+@@ -662,12 +662,10 @@ gpt_disk_get_partition_info(int fd, uint32_t num, uint64_t * start,
+ 		if (report_errors)
+ 			fprintf(stderr, "partition %d is not valid\n", num);
+ 		errno = EINVAL;
+-		return -1;
++		rc = -1;
+ 	}
+-	if (ptes)
+-		free(ptes);
+-	if (gpt)
+-		free(gpt);
++	free(ptes);
++	free(gpt);
+ 
+ 	return rc;
+ }
+-- 
+2.12.2
+
diff --git a/SOURCES/0007-efi_generate_file_device_path-fix-one-error-case-s-f.patch b/SOURCES/0007-efi_generate_file_device_path-fix-one-error-case-s-f.patch
new file mode 100644
index 0000000..868ca11
--- /dev/null
+++ b/SOURCES/0007-efi_generate_file_device_path-fix-one-error-case-s-f.patch
@@ -0,0 +1,42 @@
+From 1461dc3b17aa54377bbc461bf7d5a809322dae17 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:46:37 -0400
+Subject: [PATCH 07/22] efi_generate_file_device_path(): fix one error case's
+ free path.
+
+When efi_generate_file_device_path() gets an error from
+find_parent_devpath(), it currently just returns an error, rather than
+freeing up its intermediate resources.  So free them.
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/creator.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/creator.c b/src/creator.c
+index ca01964..6d662b7 100644
+--- a/src/creator.c
++++ b/src/creator.c
+@@ -345,7 +345,7 @@ efi_generate_file_device_path(uint8_t *buf, ssize_t size,
+ 	rc = find_parent_devpath(child_devpath, &parent_devpath);
+ 	if (rc < 0) {
+ 		efi_error("could not find parent device for file");
+-		return -1;
++		goto err;
+ 	}
+ 
+ 	rc = get_partition_number(child_devpath);
+@@ -369,7 +369,7 @@ err:
+ 	if (child_devpath)
+ 		free(child_devpath);
+ 	if (parent_devpath)
+-			free(parent_devpath);
++		free(parent_devpath);
+ 	if (relpath)
+ 		free(relpath);
+ 	errno = saved_errno;
+-- 
+2.12.2
+
diff --git a/SOURCES/0008-efi_va_generate_file_device_path_from_esp-handle-err.patch b/SOURCES/0008-efi_va_generate_file_device_path_from_esp-handle-err.patch
new file mode 100644
index 0000000..e54dff6
--- /dev/null
+++ b/SOURCES/0008-efi_va_generate_file_device_path_from_esp-handle-err.patch
@@ -0,0 +1,52 @@
+From 537d3d37d1091080362e11a6fa99b9f31cb48e53 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:48:49 -0400
+Subject: [PATCH 08/22] efi_va_generate_file_device_path_from_esp(): handle
+ errors better.
+
+When efi_va_generate_file_device_path_from_esp() gets an error from
+efidp_make_edd10() or make_blockdev_path(), it fails to close the file
+descriptor it uses to do ioctl() against the disk.  So make it use the
+common error path for those as well.
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/creator.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/creator.c b/src/creator.c
+index 6d662b7..ccd0faf 100644
+--- a/src/creator.c
++++ b/src/creator.c
+@@ -180,7 +180,7 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
+ 				       uint32_t options, va_list ap)
+ {
+ 	int rc;
+-	ssize_t ret = -1, off=0, sz;
++	ssize_t ret = -1, off = 0, sz;
+ 	struct disk_info info = { 0, };
+ 	int fd = -1;
+ 	int saved_errno;
+@@ -215,7 +215,7 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
+ 		sz = efidp_make_edd10(buf, size, info.edd10_devicenum);
+ 		if (sz < 0) {
+ 			efi_error("could not make EDD 1.0 device path");
+-			return -1;
++			goto err;
+ 		}
+ 		off = sz;
+ 	} else if (!(options & EFIBOOT_ABBREV_FILE)
+@@ -228,7 +228,7 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
+ 		sz = make_blockdev_path(buf, size, &info);
+ 		if (sz < 0) {
+ 			efi_error("could not create device path");
+-			return -1;
++			goto err;
+ 		}
+ 		off += sz;
+ 	}
+-- 
+2.12.2
+
diff --git a/SOURCES/0009-efi_variable_import-fix-memory-leak-on-failure-path.patch b/SOURCES/0009-efi_variable_import-fix-memory-leak-on-failure-path.patch
new file mode 100644
index 0000000..5751166
--- /dev/null
+++ b/SOURCES/0009-efi_variable_import-fix-memory-leak-on-failure-path.patch
@@ -0,0 +1,40 @@
+From 1ae1196e74d5bac16e63a9c453f88da9c28b5c4a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:52:48 -0400
+Subject: [PATCH 09/22] efi_variable_import(): fix memory leak on failure path.
+
+When one of our allocations fails, we leak the other one.  Woops.
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/export.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/src/export.c b/src/export.c
+index 7f2d4dd..89af720 100644
+--- a/src/export.c
++++ b/src/export.c
+@@ -96,11 +96,14 @@ efi_variable_import(uint8_t *data, size_t size, efi_variable_t **var_out)
+ 		ptr += sizeof (uint32_t);
+ 
+ 		if (name_len < 1 ||
+-				name_len != ((data + size) - ptr - data_len))
+-			return -1;
+-		if (data_len < 1 ||
+-				data_len != ((data + size) - ptr - name_len))
++		    name_len != ((data + size) - ptr - data_len) ||
++		    data_len < 1 ||
++		    data_len != ((data + size) - ptr - name_len)) {
++			int saved_errno = errno;
++			free(var.guid);
++			errno = saved_errno;
+ 			return -1;
++		}
+ 
+ 		var.name = calloc(1, name_len + 1);
+ 		if (!var.name) {
+-- 
+2.12.2
+
diff --git a/SOURCES/0010-efidp_append_path-error-check-the-right-variable.patch b/SOURCES/0010-efidp_append_path-error-check-the-right-variable.patch
new file mode 100644
index 0000000..5b8c630
--- /dev/null
+++ b/SOURCES/0010-efidp_append_path-error-check-the-right-variable.patch
@@ -0,0 +1,90 @@
+From 62e8de172dfa707990e3f2721954290499c0e14f Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:54:15 -0400
+Subject: [PATCH 10/22] efidp_append_path(): error check the right variable.
+
+We do lsz=efidp_size(dp); rsz=efidp_size(dn); and then we error check
+lsz twice.  One should be rsz.
+
+We also actually do the whole thing with lsz twice anyway, and fail to
+check that dp isn't NULL first.
+
+We're also not error checking that the buffer from our addition is
+actually large enough to hold something meaningful.  So do that too.
+
+None of that is right, so fix it.
+
+Covscan completely failed to notice this, but complained about something
+irrelevant later on in the code that's a result.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/dp.c | 26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/src/dp.c b/src/dp.c
+index e9a257e..e700af9 100644
+--- a/src/dp.c
++++ b/src/dp.c
+@@ -139,7 +139,7 @@ efidp_append_path(const_efidp dp0, const_efidp dp1, efidp *out)
+ 	}
+ 
+ 	rsz = efidp_size(dp1);
+-	if (lsz < 0) {
++	if (rsz < 0) {
+ 		efi_error("efidp_size(dp1) returned error");
+ 		return -1;
+ 	}
+@@ -166,6 +166,13 @@ efidp_append_path(const_efidp dp0, const_efidp dp1, efidp *out)
+ 		efi_error("arithmetic overflow computing allocation size");
+ 		return -1;
+ 	}
++
++	if (newsz < (ssize_t)sizeof(efidp_header)) {
++		errno = EINVAL;
++		efi_error("allocation for new device path is smaller than device path header.");
++		return -1;
++	}
++
+ 	new = malloc(newsz);
+ 	if (!new) {
+ 		efi_error("allocation failed");
+@@ -195,10 +202,11 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
+ 		return rc;
+ 	}
+ 
+-	lsz = efidp_size(dp);
+-	if (lsz < 0) {
+-		efi_error("efidp_size(dp) returned error");
+-		return -1;
++	if (!dp && dn) {
++		rc = efidp_duplicate_path(dn, out);
++		if (rc < 0)
++			efi_error("efidp_duplicate_path() failed");
++		return rc;
+ 	}
+ 
+ 	if (dp && !dn) {
+@@ -209,13 +217,17 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
+ 	}
+ 
+ 	lsz = efidp_size(dp);
+-	if (lsz < 0)
++	if (lsz < 0) {
++		efi_error("efidp_size(dp) returned error");
+ 		return -1;
++	}
+ 
+ 
+ 	rsz = efidp_node_size(dn);
+-	if (rsz < 0)
++	if (rsz < 0) {
++		efi_error("efidp_size(dn) returned error");
+ 		return -1;
++	}
+ 
+ 	if (!dp && dn) {
+ 		if (add(rsz, sizeof(end_entire), &newsz)) {
+-- 
+2.12.2
+
diff --git a/SOURCES/0011-efi_variable_import-make-sure-var.data_size-is-set.patch b/SOURCES/0011-efi_variable_import-make-sure-var.data_size-is-set.patch
new file mode 100644
index 0000000..c037b05
--- /dev/null
+++ b/SOURCES/0011-efi_variable_import-make-sure-var.data_size-is-set.patch
@@ -0,0 +1,28 @@
+From bc5f74e97ff48b89028a5f3cd0064401b37c0951 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:56:53 -0400
+Subject: [PATCH 11/22] efi_variable_import(): make sure var.data_size is set.
+
+Covscan noticed that var.data_size isn't set when we memcpy the
+structure.  It should be set.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/export.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/export.c b/src/export.c
+index 89af720..27ce501 100644
+--- a/src/export.c
++++ b/src/export.c
+@@ -118,6 +118,7 @@ efi_variable_import(uint8_t *data, size_t size, efi_variable_t **var_out)
+ 			var.name[i] = wname[i] & 0xff;
+ 		ptr += name_len * 2;
+ 
++		var.data_size = data_len;
+ 		var.data = malloc(data_len);
+ 		if (!var.data) {
+ 			int saved_errno = errno;
+-- 
+2.12.2
+
diff --git a/SOURCES/0012-makeguids-free-our-input-buffer.patch b/SOURCES/0012-makeguids-free-our-input-buffer.patch
new file mode 100644
index 0000000..c3a6b24
--- /dev/null
+++ b/SOURCES/0012-makeguids-free-our-input-buffer.patch
@@ -0,0 +1,29 @@
+From a09b1f454d01799f4976cb1396348bd850e7223a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 14:59:57 -0400
+Subject: [PATCH 12/22] makeguids: free our input buffer.
+
+Covscan noticed this, but didn't notice that this is a short lived
+program that just parses some tables during the build.  It *sooo*
+doesn't matter.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/makeguids.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/makeguids.c b/src/makeguids.c
+index da2f5f7..6a76c46 100644
+--- a/src/makeguids.c
++++ b/src/makeguids.c
+@@ -212,6 +212,7 @@ main(int argc, char *argv[])
+ 	close(in);
+ 	close(guidout);
+ 	close(nameout);
++	free(inbuf);
+ 
+ 	return 0;
+ }
+-- 
+2.12.2
+
diff --git a/SOURCES/0013-efi_variable_import-constrain-our-inputs-better.patch b/SOURCES/0013-efi_variable_import-constrain-our-inputs-better.patch
new file mode 100644
index 0000000..d8b1f64
--- /dev/null
+++ b/SOURCES/0013-efi_variable_import-constrain-our-inputs-better.patch
@@ -0,0 +1,32 @@
+From f6dc880cb1684d1836ade34e44c7710029c174e2 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:02:27 -0400
+Subject: [PATCH 13/22] efi_variable_import(): constrain our inputs better.
+
+efi_variable_import() could plausibly pass NULL to memcpy() if buf is 0
+and size is < 0, though that should never be the case.  Make the input
+checking return EINVAL if that's the case.
+
+Found by Covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/loadopt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/loadopt.c b/src/loadopt.c
+index a3c1ba9..d4c2d46 100644
+--- a/src/loadopt.c
++++ b/src/loadopt.c
+@@ -302,7 +302,7 @@ __attribute__((__visibility__ ("default")))
+ efi_loadopt_args_as_utf8(uint8_t *buf, ssize_t size, uint8_t *utf8)
+ {
+ 	ssize_t req;
+-	if (!buf && size > 0) {
++	if (!buf && size != 0) {
+ 		errno = EINVAL;
+ 		return -1;
+ 	}
+-- 
+2.12.2
+
diff --git a/SOURCES/0014-efi_loadopt_create-check-buf-for-NULLness.patch b/SOURCES/0014-efi_loadopt_create-check-buf-for-NULLness.patch
new file mode 100644
index 0000000..2a564e6
--- /dev/null
+++ b/SOURCES/0014-efi_loadopt_create-check-buf-for-NULLness.patch
@@ -0,0 +1,40 @@
+From 20e9ecb4a4b327a32dc639a7ff826af5089e3fbf Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:04:24 -0400
+Subject: [PATCH 14/22] efi_loadopt_create(): check buf for NULLness.
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/loadopt.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/loadopt.c b/src/loadopt.c
+index d4c2d46..8db8074 100644
+--- a/src/loadopt.c
++++ b/src/loadopt.c
+@@ -46,13 +46,20 @@ efi_loadopt_create(uint8_t *buf, ssize_t size, uint32_t attributes,
+ 	ssize_t sz = sizeof (attributes)
+ 		     + sizeof (uint16_t) + desc_len
+ 		     + dp_size + optional_data_size;
++
+ 	if (size == 0)
+ 		return sz;
++
+ 	if (size < sz) {
+ 		errno = ENOSPC;
+ 		return -1;
+ 	}
+ 
++	if (!buf) {
++		errno = EINVAL;
++		return -1;
++	}
++
+ 	if (!optional_data && optional_data_size != 0) {
+ 		errno = EINVAL;
+ 		return -1;
+-- 
+2.12.2
+
diff --git a/SOURCES/0015-efidp_duplicate_extra-error-if-our-allocation-is-too.patch b/SOURCES/0015-efidp_duplicate_extra-error-if-our-allocation-is-too.patch
new file mode 100644
index 0000000..c75750d
--- /dev/null
+++ b/SOURCES/0015-efidp_duplicate_extra-error-if-our-allocation-is-too.patch
@@ -0,0 +1,34 @@
+From 32f6b0d5974e39dbcce89d9ab8551e35eb8fdaab Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:14:33 -0400
+Subject: [PATCH 15/22] efidp_duplicate_extra(): error if our allocation is too
+ small.
+
+Covscan believes we might pass 0 to calloc(), though I suspect this is
+because it doesn't fully grok add().
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/dp.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/dp.c b/src/dp.c
+index e700af9..eadb397 100644
+--- a/src/dp.c
++++ b/src/dp.c
+@@ -81,6 +81,12 @@ efidp_duplicate_extra(const_efidp dp, efidp *out, size_t extra)
+ 		return -1;
+ 	}
+ 
++	if (plus < (ssize_t)sizeof(efidp_header)) {
++		errno = EINVAL;
++		efi_error("allocation for new device path is smaller than device path header.");
++		return -1;
++	}
++
+ 	new = calloc(1, plus);
+ 	if (!new) {
+ 		efi_error("allocation failed");
+-- 
+2.12.2
+
diff --git a/SOURCES/0016-show_errors-make-the-useful-part-here-not-be-dead-co.patch b/SOURCES/0016-show_errors-make-the-useful-part-here-not-be-dead-co.patch
new file mode 100644
index 0000000..0b2b17a
--- /dev/null
+++ b/SOURCES/0016-show_errors-make-the-useful-part-here-not-be-dead-co.patch
@@ -0,0 +1,29 @@
+From 878c81f02e9cabbc990028b2cf87442813eb39f5 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:18:05 -0400
+Subject: [PATCH 16/22] show_errors(): make the useful part here not be dead
+ code.
+
+Woops.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/efivar.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/efivar.c b/src/efivar.c
+index cbefe8b..38d19e1 100644
+--- a/src/efivar.c
++++ b/src/efivar.c
+@@ -61,7 +61,7 @@ static int verbose_errors = 0;
+ static void
+ show_errors(void)
+ {
+-	int rc = 0;
++	int rc = 1;
+ 
+ 	if (!verbose_errors)
+ 		return;
+-- 
+2.12.2
+
diff --git a/SOURCES/0017-efi_loadopt_args_from_file-make-sure-buf-is-only-NUL.patch b/SOURCES/0017-efi_loadopt_args_from_file-make-sure-buf-is-only-NUL.patch
new file mode 100644
index 0000000..cfecd77
--- /dev/null
+++ b/SOURCES/0017-efi_loadopt_args_from_file-make-sure-buf-is-only-NUL.patch
@@ -0,0 +1,31 @@
+From d251242a71ef01626444180c630330bcfb0ca69e Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:19:18 -0400
+Subject: [PATCH 17/22] efi_loadopt_args_from_file(): make sure buf is only
+ NULL if size is.
+
+This avoids passing NULL to fread().
+
+Found by covscan.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/loadopt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/loadopt.c b/src/loadopt.c
+index 8db8074..5301f3d 100644
+--- a/src/loadopt.c
++++ b/src/loadopt.c
+@@ -269,7 +269,7 @@ efi_loadopt_args_from_file(uint8_t *buf, ssize_t size, char *filename)
+ 	int saved_errno;
+ 	FILE *f;
+ 
+-	if (!buf && size > 0) {
++	if (!buf && size != 0) {
+ 		errno = -EINVAL;
+ 		return -1;
+ 	}
+-- 
+2.12.2
+
diff --git a/SOURCES/0018-calls-to-sysfs_readlink-check-linkbuf-for-NULLness.patch b/SOURCES/0018-calls-to-sysfs_readlink-check-linkbuf-for-NULLness.patch
new file mode 100644
index 0000000..a53c6b7
--- /dev/null
+++ b/SOURCES/0018-calls-to-sysfs_readlink-check-linkbuf-for-NULLness.patch
@@ -0,0 +1,91 @@
+From 38039634f722eb6e3ef4221e3f37c19a1bc96ae7 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:21:13 -0400
+Subject: [PATCH 18/22] calls to sysfs_readlink(): check linkbuf for NULLness.
+
+If linkbuf were NULL, sysfs_readlink() would have returned an error, but
+covscan can't figure that out, so it thinks linkbuf might be NULL.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/linux.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/src/linux.c b/src/linux.c
+index 3c77a93..85b4ee3 100644
+--- a/src/linux.c
++++ b/src/linux.c
+@@ -53,7 +53,7 @@ set_disk_and_part_name(struct disk_info *info)
+ 
+ 	rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%"PRIu32,
+ 		      info->major, info->minor);
+-	if (rc < 0)
++	if (rc < 0 || !linkbuf)
+ 		return -1;
+ 
+ 	char *ultimate;
+@@ -141,7 +141,7 @@ get_partition_number(const char *devpath)
+ 	min = minor(statbuf.st_rdev);
+ 
+ 	rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%u:%u", maj, min);
+-	if (rc < 0)
++	if (rc < 0 || !linkbuf)
+ 		return -1;
+ 
+ 	rc = read_sysfs_file(&partbuf, "/sys/dev/block/%s/partition", linkbuf);
+@@ -170,7 +170,7 @@ find_parent_devpath(const char * const child, char **parent)
+ 
+ 	/* look up full path symlink */
+ 	ret = sysfs_readlink(&linkbuf, "/sys/class/block/%s", node);
+-	if (ret < 0)
++	if (ret < 0 || !linkbuf)
+ 		return ret;
+ 
+ 	/* strip child */
+@@ -747,7 +747,7 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
+ 
+ 	rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%u",
+ 			    info->major, info->minor);
+-	if (rc < 0)
++	if (rc < 0 || !linkbuf)
+ 		return -1;
+ 
+ 	/*
+@@ -771,7 +771,7 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
+ 		return -1;
+ 	tmppath[loff] = '\0';
+ 	rc = sysfs_readlink(&driverbuf, "/sys/dev/block/%s/driver", tmppath);
+-	if (rc < 0)
++	if (rc < 0 || !driverbuf)
+ 		return -1;
+ 
+ 	char *driver = strrchr(driverbuf, '/');
+@@ -867,7 +867,7 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
+ 
+ 		rc = sysfs_readlink(&linkbuf, "/sys/class/block/%s/device",
+ 			      info->disk_name);
+-		if (rc < 0)
++		if (rc < 0 || !linkbuf)
+ 			return 0;
+ 
+ 		rc = sscanf(linkbuf, "../../../%d:%d:%d:%"PRIu64,
+@@ -1001,14 +1001,14 @@ make_net_pci_path(uint8_t *buf, ssize_t size, const char * const ifname)
+ 	int rc;
+ 
+ 	rc = sysfs_readlink(&linkbuf, "/sys/class/net/%s", ifname);
+-	if (rc < 0)
++	if (rc < 0 || !linkbuf)
+ 		return -1;
+ 
+ 	/*
+ 	 * the sysfs path basically looks like:
+ 	 * ../../devices/$PCI_STUFF/net/$IFACE
+ 	 */
+-	rc = sscanf(linkbuf+loff, "../../devices/%n", &lsz);
++	rc = sscanf(linkbuf, "../../devices/%n", &lsz);
+ 	if (rc != 0)
+ 		return -1;
+ 	loff += lsz;
+-- 
+2.12.2
+
diff --git a/SOURCES/0019-efivar-main-explain-efi_well_known_guids-to-the-comp.patch b/SOURCES/0019-efivar-main-explain-efi_well_known_guids-to-the-comp.patch
new file mode 100644
index 0000000..54386b1
--- /dev/null
+++ b/SOURCES/0019-efivar-main-explain-efi_well_known_guids-to-the-comp.patch
@@ -0,0 +1,38 @@
+From 089265335dfb746a77ec15a917c12e8c77a41240 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:34:28 -0400
+Subject: [PATCH 19/22] efivar main(): explain efi_well_known_guids to the
+ compiler better.
+
+Covscan doesn't quite understand that this _is_ an array, so make it
+look even more like one.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/efivar.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/efivar.c b/src/efivar.c
+index 38d19e1..3ed9a84 100644
+--- a/src/efivar.c
++++ b/src/efivar.c
+@@ -461,13 +461,13 @@ int main(int argc, char *argv[])
+ 		case ACTION_LIST_GUIDS: {
+ 			efi_guid_t sentinal = {0xffffffff,0xffff,0xffff,0xffff,
+ 					       {0xff,0xff,0xff,0xff,0xff,0xff}};
+-			extern struct guidname efi_well_known_guids;
+-			extern struct guidname efi_well_known_guids_end;
++			extern struct guidname efi_well_known_guids[];
++			extern struct guidname *efi_well_known_guids_end;
+ 			intptr_t start = (intptr_t)&efi_well_known_guids;
+ 			intptr_t end = (intptr_t)&efi_well_known_guids_end;
+ 			unsigned int i;
+ 
+-			struct guidname *guid = &efi_well_known_guids;
++			struct guidname *guid = &efi_well_known_guids[0];
+ 			for (i = 0; i < (end-start) / sizeof(*guid); i++) {
+ 				if (!efi_guid_cmp(&sentinal, &guid[i].guid))
+ 					break;
+-- 
+2.12.2
+
diff --git a/SOURCES/0020-dp.h-Try-to-make-covscan-believe-format-is-checking-.patch b/SOURCES/0020-dp.h-Try-to-make-covscan-believe-format-is-checking-.patch
new file mode 100644
index 0000000..3962f5f
--- /dev/null
+++ b/SOURCES/0020-dp.h-Try-to-make-covscan-believe-format-is-checking-.patch
@@ -0,0 +1,44 @@
+From 9d74090cea256021e68b204c4770a5df28398cbd Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 May 2017 15:59:09 -0400
+Subject: [PATCH 20/22] dp.h: Try to make covscan believe format() is checking
+ its bounds.
+
+covscan doesn't grok that size and off wind up being proxies for buf's
+NULL check.  Hilarity ensues.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/dp.h | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/src/dp.h b/src/dp.h
+index d6775a6..c14a9ec 100644
+--- a/src/dp.h
++++ b/src/dp.h
+@@ -28,11 +28,17 @@
+ #include "ucs2.h"
+ 
+ #define format(buf, size, off, dp_type, fmt, args...) ({		\
+-		ssize_t _x = 0;						\
+-		if ((off) >= 0) {					\
+-			_x = snprintf(((buf)+(off)),			\
+-			       ((size)?((size)-(off)):0),		\
+-			       fmt, ## args);				\
++		ssize_t _insize = 0;					\
++		void *_inbuf = NULL;					\
++		if ((buf) != NULL && (size) > 0) {			\
++			_inbuf = (buf) + (off);				\
++			_insize = (size) - (off);			\
++		}							\
++		if ((off) >= 0 &&					\
++		    ((buf == NULL && _insize == 0) ||			\
++		     (buf != NULL && _insize >= 0))) {			\
++			ssize_t _x = 0;					\
++			_x = snprintf(_inbuf, _insize, fmt, ## args);	\
+ 			if (_x < 0) {					\
+ 				efi_error(				\
+ 					"could not build %s DP string",	\
+-- 
+2.12.2
+
diff --git a/SOURCES/0021-gpt-try-to-avoid-trusting-unverified-partition-table.patch b/SOURCES/0021-gpt-try-to-avoid-trusting-unverified-partition-table.patch
new file mode 100644
index 0000000..af9704d
--- /dev/null
+++ b/SOURCES/0021-gpt-try-to-avoid-trusting-unverified-partition-table.patch
@@ -0,0 +1,360 @@
+From 29a53c93ce063c8272e44f4981201a4752fc6ba1 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 9 May 2017 14:20:13 -0400
+Subject: [PATCH 21/24] gpt: try to avoid trusting unverified partition table
+ data.
+
+Covscan complains thusly:
+ 4. efivar-31/src/gpt.c:338: tainted_data_return: Function "alloc_read_gpt_header" returns tainted data.
+ 7. efivar-31/src/gpt.c:311:2: tainted_data_argument: Function "read_lba" taints argument "gpt".
+12. efivar-31/src/gpt.c:245:2: tainted_data_argument: Calling function "read" taints parameter "*iobuf". [Note: The source code implementation of the function has been overridden by a builtin model.]
+13. efivar-31/src/gpt.c:246:2: tainted_data_transitive: "memcpy" taints argument "buffer" because argument "iobuf" is tainted. [Note: The source code implementation of the function has been overridden by a builtin model.]
+16. efivar-31/src/gpt.c:316:2: return_tainted_data: Returning tainted variable "gpt".
+17. efivar-31/src/gpt.c:338: var_assign: Assigning: "*gpt" = "alloc_read_gpt_header", which taints "*gpt".
+26. efivar-31/src/gpt.c:382: tainted_data: Passing tainted variable "(*gpt)->num_partition_entries" to a tainted sink.
+27. efivar-31/src/gpt.c:272:15: var_assign_alias: Assigning: "count" = "(__u32)(__le32)gpt->num_partition_entries * (__u32)(__le32)gpt->sizeof_partition_entry". Both are now tainted.
+30. efivar-31/src/gpt.c:278:2: tainted_data_sink_lv_call: Passing tainted variable "count" to tainted data sink "malloc".
+
+Hopefully this patch validates num_partition_entries and
+sizeof_partition_entry well enough...
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/disk.c |   3 +-
+ src/gpt.c  | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
+ src/gpt.h  |   3 +-
+ 3 files changed, 173 insertions(+), 23 deletions(-)
+
+diff --git a/src/disk.c b/src/disk.c
+index 91d636d..0a7a769 100644
+--- a/src/disk.c
++++ b/src/disk.c
+@@ -225,7 +225,8 @@ get_partition_info(int fd, uint32_t options,
+ 						  signature,
+ 						  mbr_type,
+ 						  signature_type,
+-			(options & EFIBOOT_OPTIONS_IGNORE_PMBR_ERR)?1:0);
++			(options & EFIBOOT_OPTIONS_IGNORE_PMBR_ERR)?1:0,
++			sector_size);
+ 	if (gpt_invalid) {
+ 		mbr_invalid = msdos_disk_get_partition_info(fd,
+ 			(options & EFIBOOT_OPTIONS_WRITE_SIGNATURE)?1:0,
+diff --git a/src/gpt.c b/src/gpt.c
+index e9c713b..7baa992 100644
+--- a/src/gpt.c
++++ b/src/gpt.c
+@@ -29,6 +29,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <sys/param.h>
+ #include <sys/stat.h>
+ #include <sys/utsname.h>
+ #include <unistd.h>
+@@ -266,11 +267,10 @@ read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
+  * Notes: remember to free pte when you're done!
+  */
+ static gpt_entry *
+-alloc_read_gpt_entries(int fd, gpt_header * gpt)
++alloc_read_gpt_entries(int fd, uint32_t nptes, uint32_t ptesz, uint64_t ptelba)
+ {
+ 	gpt_entry *pte;
+-	size_t count = __le32_to_cpu(gpt->num_partition_entries) *
+-		__le32_to_cpu(gpt->sizeof_partition_entry);
++	size_t count = nptes * ptesz;
+ 
+ 	if (!count)
+ 		return NULL;
+@@ -280,8 +280,7 @@ alloc_read_gpt_entries(int fd, gpt_header * gpt)
+ 		return NULL;
+ 
+ 	memset(pte, 0, count);
+-	if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte,
+-		      count)) {
++	if (!read_lba(fd, ptelba, pte, count)) {
+ 		free(pte);
+ 		return NULL;
+ 	}
+@@ -317,6 +316,65 @@ alloc_read_gpt_header(int fd, uint64_t lba)
+ }
+ 
+ /**
++ * validate_nptes(): Tries to ensure that nptes is a reasonable value
++ * @first_block is the beginning LBA to bound the table
++ * @pte_start is the starting LBA of the partition table
++ * @last_block is the end LBA of to bound the table
++ * @ptesz is the size of a partition table entry
++ * @nptes is the number of entries we have.
++ * @blksz is the block size of the device.
++ *
++ * Description: returns 0 if the partition table doesn't fit, 1 if it does
++ */
++static int
++validate_nptes(uint64_t first_block, uint64_t pte_start, uint64_t last_block,
++	       uint32_t ptesz, uint32_t nptes, uint32_t blksz)
++{
++	uint32_t min_entry_size = sizeof(gpt_entry);
++	uint32_t min_entry_size_mod = 128 - sizeof(gpt_entry) % 128;
++	uint64_t max_blocks, max_bytes;
++
++	if (min_entry_size_mod == 128)
++		min_entry_size_mod = 0;
++	min_entry_size += min_entry_size_mod;
++
++	if (ptesz < min_entry_size)
++		return 0;
++
++	if (pte_start < first_block || pte_start > last_block)
++		return 0;
++
++	max_blocks = last_block - pte_start;
++	if (UINT64_MAX / blksz < max_blocks)
++		return 0;
++
++	max_bytes = max_blocks * blksz;
++	if (UINT64_MAX / ptesz < max_bytes)
++		return 0;
++
++	if (ptesz > max_bytes / nptes)
++		return 0;
++
++	if (max_bytes / ptesz < nptes)
++		return 0;
++
++	return 1;
++}
++
++static int
++check_lba(uint64_t lba, uint64_t lastlba, char *name)
++{
++	if (lba > lastlba) {
++		if (report_errors)
++			fprintf(stderr,
++				"Invalid %s LBA %"PRIx64" max:%"PRIx64"\n",
++				name, lba, lastlba);
++		return 0;
++	}
++	return 1;
++}
++
++/**
+  * is_gpt_valid() - tests one GPT header and PTEs for validity
+  * @fd  is an open file descriptor to the whole disk
+  * @lba is the logical block address of the GPT header to test
+@@ -328,10 +386,12 @@ alloc_read_gpt_header(int fd, uint64_t lba)
+  */
+ static int
+ is_gpt_valid(int fd, uint64_t lba,
+-	     gpt_header ** gpt, gpt_entry ** ptes)
++	     gpt_header ** gpt, gpt_entry ** ptes,
++	     uint32_t logical_block_size)
+ {
+ 	int rc = 0;		/* default to not valid */
+ 	uint32_t crc, origcrc;
++	uint64_t max_device_lba = last_lba(fd);
+ 
+ 	if (!gpt || !ptes)
+ 		return 0;
+@@ -343,7 +403,7 @@ is_gpt_valid(int fd, uint64_t lba,
+ 		if (report_errors)
+ 			fprintf(stderr,
+ 				"GUID Partition Table Header signature is wrong"
+-			       ": %" PRIx64" != %" PRIx64 "\n",
++			       ": %"PRIx64" != %"PRIx64"\n",
+ 			       (uint64_t)__le64_to_cpu((*gpt)->signature),
+ 			       GPT_HEADER_SIGNATURE);
+ 		free(*gpt);
+@@ -351,6 +411,20 @@ is_gpt_valid(int fd, uint64_t lba,
+ 		return rc;
+ 	}
+ 
++	uint32_t hdrsz = __le32_to_cpu((*gpt)->header_size);
++	uint32_t hdrmin = MAX(92,
++			      sizeof(gpt_header) - sizeof((*gpt)->reserved2));
++	if (hdrsz < hdrmin || hdrsz > logical_block_size) {
++		if (report_errors)
++			fprintf(stderr,
++				"GUID Partition Table Header size is invalid (%d < %d < %d)\n",
++				hdrmin, hdrsz,
++				logical_block_size);
++		free (*gpt);
++		*gpt = NULL;
++		return rc;
++	}
++
+ 	/* Check the GUID Partition Table Header CRC */
+ 	origcrc = __le32_to_cpu((*gpt)->header_crc32);
+ 	(*gpt)->header_crc32 = 0;
+@@ -369,26 +443,97 @@ is_gpt_valid(int fd, uint64_t lba,
+ 
+ 	/* Check that the my_lba entry points to the LBA
+ 	 * that contains the GPT we read */
+-	if (__le64_to_cpu((*gpt)->my_lba) != lba) {
++	uint64_t mylba = __le64_to_cpu((*gpt)->my_lba);
++	uint64_t altlba = __le64_to_cpu((*gpt)->alternate_lba);
++	if (mylba != lba && altlba != lba) {
+ 		if (report_errors)
+ 			fprintf(stderr,
+-				"my_lba %"PRIx64 "x != lba %"PRIx64 "x.\n",
+-				(uint64_t)__le64_to_cpu((*gpt)->my_lba), lba);
++				"lba %"PRIx64" != lba %"PRIx64".\n",
++				mylba, lba);
++err:
+ 		free(*gpt);
+ 		*gpt = NULL;
+ 		return 0;
+ 	}
+ 
+-	if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) {
++	if (!check_lba(mylba, max_device_lba, "GPT"))
++		goto err;
++
++	if (!check_lba(altlba, max_device_lba, "GPT Alt"))
++		goto err;
++
++	uint64_t ptelba = __le64_to_cpu((*gpt)->partition_entry_lba);
++	uint64_t fulba = __le64_to_cpu((*gpt)->first_usable_lba);
++	uint64_t lulba = __le64_to_cpu((*gpt)->last_usable_lba);
++	uint32_t nptes = __le32_to_cpu((*gpt)->num_partition_entries);
++	uint32_t ptesz = __le32_to_cpu((*gpt)->sizeof_partition_entry);
++
++	if (!check_lba(ptelba, max_device_lba, "PTE"))
++		goto err;
++	if (!check_lba(fulba, max_device_lba, "First Usable"))
++		goto err;
++	if (!check_lba(lulba, max_device_lba, "Last Usable"))
++		goto err;
++
++	if (ptesz < sizeof(gpt_entry) || ptesz % 128 != 0) {
++		if (report_errors)
++			fprintf(stderr,
++				"Invalid GPT entry size is %d.\n",
++				ptesz);
++		goto err;
++	}
++
++	/* There's really no good answer to maximum bounds, but this large
++	 * would be completely absurd, so... */
++	if (nptes > 1024) {
++		if (report_errors)
++			fprintf(stderr,
++				"Not honoring insane number of Partition Table Entries 0x%"PRIx32".\n",
++				nptes);
++
++		goto err;
++	}
++
++	if (ptesz > 4096) {
++		if (report_errors)
++			fprintf(stderr,
++				"Not honoring insane Partition Table Entry size 0x%"PRIx32".\n",
++				ptesz);
++		goto err;
++	}
++
++	uint64_t pte_blocks;
++	uint64_t firstlba, lastlba;
++
++	if (altlba > mylba) {
++		firstlba = mylba + 1;
++		lastlba = fulba;
++		pte_blocks = fulba - ptelba;
++		rc = validate_nptes(firstlba, ptelba, fulba,
++				    ptesz, nptes, logical_block_size);
++	} else {
++		firstlba = lulba;
++		lastlba = mylba;
++		pte_blocks = mylba - ptelba;
++		rc = validate_nptes(lulba, ptelba, mylba,
++				    ptesz, nptes, logical_block_size);
++	}
++	if (!rc) {
++		if (report_errors)
++			fprintf(stderr,
++				"%"PRIu32" partition table entries with size 0x%"PRIx32" doesn't fit in 0x%"PRIx64" blocks between 0x%"PRIx64" and 0x%"PRIx64".\n",
++				nptes, ptesz, pte_blocks, firstlba, lastlba);
++		goto err;
++	}
++
++	if (!(*ptes = alloc_read_gpt_entries(fd, nptes, ptesz, ptelba))) {
+ 		free(*gpt);
+ 		*gpt = NULL;
+ 		return 0;
+ 	}
+ 
+ 	/* Check the GUID Partition Entry Array CRC */
+-	crc = efi_crc32(*ptes,
+-			__le32_to_cpu((*gpt)->num_partition_entries) *
+-			__le32_to_cpu((*gpt)->sizeof_partition_entry));
++	crc = efi_crc32(*ptes, nptes * ptesz);
+ 	if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
+ 		if (report_errors)
+ 		     fprintf(stderr,
+@@ -519,7 +664,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
+  */
+ static int
+ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes,
+-	       int ignore_pmbr_err)
++	       int ignore_pmbr_err, int logical_block_size)
+ {
+ 	int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
+ 	gpt_header *pgpt = NULL, *agpt = NULL;
+@@ -535,16 +680,18 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes,
+ 
+ 	lastlba = last_lba(fd);
+ 	good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
+-				 &pgpt, &pptes);
++				 &pgpt, &pptes, logical_block_size);
+ 	if (good_pgpt) {
+ 		good_agpt = is_gpt_valid(fd,
+ 					 __le64_to_cpu(pgpt->alternate_lba),
+-					 &agpt, &aptes);
++					 &agpt, &aptes, logical_block_size);
+ 		if (!good_agpt) {
+-			good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes);
++			good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes,
++						 logical_block_size);
+ 		}
+ 	} else {
+-		good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes);
++		good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes,
++					 logical_block_size);
+ 	}
+ 
+ 	/* The obviously unsuccessful case */
+@@ -634,7 +781,7 @@ __attribute__((__visibility__ ("hidden")))
+ gpt_disk_get_partition_info(int fd, uint32_t num, uint64_t * start,
+ 			    uint64_t * size, uint8_t *signature,
+ 			    uint8_t * mbr_type, uint8_t * signature_type,
+-			    int ignore_pmbr_error)
++			    int ignore_pmbr_error, int logical_block_size)
+ {
+ 	gpt_header *gpt = NULL;
+ 	gpt_entry *ptes = NULL, *p;
+@@ -644,7 +791,8 @@ gpt_disk_get_partition_info(int fd, uint32_t num, uint64_t * start,
+ 	if (report)
+ 		report_errors = 1;
+ 
+-	rc = find_valid_gpt(fd, &gpt, &ptes, ignore_pmbr_error);
++	rc = find_valid_gpt(fd, &gpt, &ptes, ignore_pmbr_error,
++			    logical_block_size);
+ 	if (rc < 0)
+ 		return rc;
+ 
+diff --git a/src/gpt.h b/src/gpt.h
+index 2249b59..678ee37 100644
+--- a/src/gpt.h
++++ b/src/gpt.h
+@@ -147,7 +147,8 @@ extern int gpt_disk_get_partition_info (int fd, uint32_t num, uint64_t *start,
+ 					uint64_t *size, uint8_t *signature,
+ 					uint8_t *mbr_type,
+ 					uint8_t *signature_type,
+-					int ignore_pmbr_error)
++					int ignore_pmbr_error,
++					int logical_sector_size)
+ 	__attribute__((__nonnull__ (3, 4, 5, 6, 7)))
+ 	__attribute__((__visibility__ ("hidden")));
+ 
+-- 
+2.12.2
+
diff --git a/SOURCES/0022-Simplify-efidp_append_node-even-more.patch b/SOURCES/0022-Simplify-efidp_append_node-even-more.patch
new file mode 100644
index 0000000..d9ff9db
--- /dev/null
+++ b/SOURCES/0022-Simplify-efidp_append_node-even-more.patch
@@ -0,0 +1,138 @@
+From 6e59831ea44426736c2ac615c5145c427418086a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 9 May 2017 15:15:55 -0400
+Subject: [PATCH 22/24] Simplify efidp_append_node() even more.
+
+Covscan rightly notices that now we've got enough tests on dp and dn
+that some of them are provably dead code.
+
+So take a bunch out.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/dp.c | 94 +++++++++++++++++++---------------------------------------------
+ 1 file changed, 28 insertions(+), 66 deletions(-)
+
+diff --git a/src/dp.c b/src/dp.c
+index eadb397..14f4cfe 100644
+--- a/src/dp.c
++++ b/src/dp.c
+@@ -196,78 +196,38 @@ int
+ __attribute__((__visibility__ ("default")))
+ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
+ {
+-	ssize_t lsz, rsz, newsz;
++	ssize_t lsz = 0, rsz = 0, newsz;
+ 	int rc;
+ 
+-	if (!dp && !dn) {
+-		rc = efidp_duplicate_path(
+-			(const_efidp)(const efidp_header * const)&end_entire,
+-			out);
+-		if (rc < 0)
+-			efi_error("efidp_duplicate_path() failed");
+-		return rc;
+-	}
+-
+-	if (!dp && dn) {
+-		rc = efidp_duplicate_path(dn, out);
+-		if (rc < 0)
+-			efi_error("efidp_duplicate_path() failed");
+-		return rc;
+-	}
+-
+-	if (dp && !dn) {
+-		rc = efidp_duplicate_path(dp, out);
+-		if (rc < 0)
+-			efi_error("efidp_duplicate_path() failed");
+-		return rc;
+-	}
+-
+-	lsz = efidp_size(dp);
+-	if (lsz < 0) {
+-		efi_error("efidp_size(dp) returned error");
+-		return -1;
+-	}
+-
+-
+-	rsz = efidp_node_size(dn);
+-	if (rsz < 0) {
+-		efi_error("efidp_size(dn) returned error");
+-		return -1;
+-	}
+-
+-	if (!dp && dn) {
+-		if (add(rsz, sizeof(end_entire), &newsz)) {
+-			errno = EOVERFLOW;
+-			efi_error(
+-			  "arithmetic overflow computing allocation size");
+-			return -1;
+-		}
+-		efidp new = malloc(rsz + sizeof (end_entire));
+-		if (!new) {
+-			efi_error("allocation failed");
++	if (dp) {
++		lsz = efidp_size(dp);
++		if (lsz < 0) {
++			efi_error("efidp_size(dp) returned error");
+ 			return -1;
+ 		}
+ 
+-		memcpy(new, dn, dn->length);
+-		memcpy((uint8_t *)new + dn->length, &end_entire,
+-		       sizeof (end_entire));
+-		*out = new;
+-		return 0;
+-	}
++		const_efidp le;
++		le = dp;
++		while (1) {
++			if (efidp_type(le) == EFIDP_END_TYPE &&
++			    efidp_subtype(le) == EFIDP_END_ENTIRE) {
++				ssize_t lesz = efidp_size(le);
++				lsz -= lesz;
++				break;
++			}
+ 
+-	const_efidp le;
+-	le = dp;
+-	while (1) {
+-		if (efidp_type(le) == EFIDP_END_TYPE &&
+-				efidp_subtype(le) == EFIDP_END_ENTIRE) {
+-			ssize_t lesz = efidp_size(le);
+-			lsz -= lesz;
+-			break;
++			rc = efidp_get_next_end(le, &le);
++			if (rc < 0) {
++				efi_error("efidp_get_next_end() returned error");
++				return -1;
++			}
+ 		}
++	}
+ 
+-		rc = efidp_get_next_end(le, &le);
+-		if (rc < 0) {
+-			efi_error("efidp_get_next_end() returned error");
++	if (dn) {
++		rsz = efidp_node_size(dn);
++		if (rsz < 0) {
++			efi_error("efidp_size(dn) returned error");
+ 			return -1;
+ 		}
+ 	}
+@@ -285,8 +245,10 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
+ 	}
+ 
+ 	*out = new;
+-	memcpy(new, dp, lsz);
+-	memcpy((uint8_t *)new + lsz, dn, rsz);
++	if (dp)
++		memcpy(new, dp, lsz);
++	if (dn)
++		memcpy((uint8_t *)new + lsz, dn, rsz);
+ 	memcpy((uint8_t *)new + lsz + rsz, &end_entire, sizeof (end_entire));
+ 
+ 	return 0;
+-- 
+2.12.2
+
diff --git a/SOURCES/0023-efi_loadopt_create-avoid-NULL-dereference.patch b/SOURCES/0023-efi_loadopt_create-avoid-NULL-dereference.patch
new file mode 100644
index 0000000..db94606
--- /dev/null
+++ b/SOURCES/0023-efi_loadopt_create-avoid-NULL-dereference.patch
@@ -0,0 +1,86 @@
+From e9ce922ddf2ec6c1095f42ee9857f369084761c3 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 9 May 2017 15:34:08 -0400
+Subject: [PATCH 23/24] efi_loadopt_create(): avoid NULL dereference
+
+covscan rightly points out that dp is allowed to be NULL (and so is
+buf), so we can't pass those in to memcpy() in those cases.
+
+So don't.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/loadopt.c | 46 +++++++++++++++++++++++++++-------------------
+ 1 file changed, 27 insertions(+), 19 deletions(-)
+
+diff --git a/src/loadopt.c b/src/loadopt.c
+index 5301f3d..cf0886d 100644
+--- a/src/loadopt.c
++++ b/src/loadopt.c
+@@ -56,36 +56,44 @@ efi_loadopt_create(uint8_t *buf, ssize_t size, uint32_t attributes,
+ 	}
+ 
+ 	if (!buf) {
++invalid:
+ 		errno = EINVAL;
+ 		return -1;
+ 	}
+ 
+-	if (!optional_data && optional_data_size != 0) {
+-		errno = EINVAL;
+-		return -1;
+-	}
++	if (!optional_data && optional_data_size != 0)
++		goto invalid;
+ 
+-	if (!dp && dp_size == 0) {
+-		errno = EINVAL;
+-		return -1;
+-	}
++	if ((!dp && dp_size == 0) || dp_size < 0)
++		goto invalid;
++
++	if (dp) {
++		if (!efidp_is_valid(dp, dp_size))
++			goto invalid;
+ 
+-	uint8_t *pos = buf;
++		if (efidp_size(dp) != dp_size)
++			goto invalid;
++	}
+ 
+-	*(uint32_t *)pos = attributes;
+-	pos += sizeof (attributes);
++	if (buf) {
++		uint8_t *pos = buf;
++		*(uint32_t *)pos = attributes;
++		pos += sizeof (attributes);
+ 
+-	*(uint16_t *)pos = dp_size;
+-	pos += sizeof (uint16_t);
++		*(uint16_t *)pos = dp_size;
++		pos += sizeof (uint16_t);
+ 
+-	utf8_to_ucs2((uint16_t *)pos, desc_len, 1, (uint8_t *)description);
+-	pos += desc_len;
++		utf8_to_ucs2((uint16_t *)pos, desc_len, 1,
++			     (uint8_t *)description);
++		pos += desc_len;
+ 
+-	memcpy(pos, dp, dp_size);
+-	pos += dp_size;
++		if (dp)
++			memcpy(pos, dp, dp_size);
++		pos += dp_size;
+ 
+-	if (optional_data && optional_data_size > 0)
+-		memcpy(pos, optional_data, optional_data_size);
++		if (optional_data && optional_data_size > 0)
++			memcpy(pos, optional_data, optional_data_size);
++	}
+ 
+ 	return sz;
+ }
+-- 
+2.12.2
+
diff --git a/SOURCES/0024-efi_generate_file_device_path-make-all-error-paths-u.patch b/SOURCES/0024-efi_generate_file_device_path-make-all-error-paths-u.patch
new file mode 100644
index 0000000..7c54866
--- /dev/null
+++ b/SOURCES/0024-efi_generate_file_device_path-make-all-error-paths-u.patch
@@ -0,0 +1,30 @@
+From 1995ef6d9459931170f5718221104d7eb8c35eba Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 9 May 2017 16:32:09 -0400
+Subject: [PATCH 24/26] efi_generate_file_device_path(): make all error paths
+ use "goto err;"
+
+Honestly I'm just trying to shut coverity up about checking
+child_devpath for NULL-ness twice on the other two error paths.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/creator.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/creator.c b/src/creator.c
+index ccd0faf..21fc6b0 100644
+--- a/src/creator.c
++++ b/src/creator.c
+@@ -339,7 +339,7 @@ efi_generate_file_device_path(uint8_t *buf, ssize_t size,
+ 	rc = find_file(filepath, &child_devpath, &relpath);
+ 	if (rc < 0) {
+ 		efi_error("could not canonicalize fs path");
+-		return -1;
++		goto err;
+ 	}
+ 
+ 	rc = find_parent_devpath(child_devpath, &parent_devpath);
+-- 
+2.12.2
+
diff --git a/SOURCES/0025-linux.c-fix-a-pile-of-sscanf-NULL-.-possibilities.patch b/SOURCES/0025-linux.c-fix-a-pile-of-sscanf-NULL-.-possibilities.patch
new file mode 100644
index 0000000..c8779eb
--- /dev/null
+++ b/SOURCES/0025-linux.c-fix-a-pile-of-sscanf-NULL-.-possibilities.patch
@@ -0,0 +1,74 @@
+From d8cef3fe75ef8ca3e2622230c81caba06c3476bd Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 9 May 2017 16:33:27 -0400
+Subject: [PATCH 25/26] linux.c: fix a pile of sscanf(NULL, ...) possibilities.
+
+Covscan apparently can't figure out that rc!=error == buf!=NULL.
+
+None of these should ever actually happen, because we're checking for
+the error cases from the functions that should fill them in, but hey,
+belt and suspenders.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ src/linux.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/linux.c b/src/linux.c
+index 85b4ee3..f419ad4 100644
+--- a/src/linux.c
++++ b/src/linux.c
+@@ -297,7 +297,7 @@ sysfs_sata_get_port_info(uint32_t print_id, struct disk_info *info)
+ 
+ 	rc = read_sysfs_file(&buf, "/sys/class/ata_port/ata%d/port_no",
+ 			     print_id);
+-	if (rc <= 0)
++	if (rc <= 0 || buf == NULL)
+ 		return -1;
+ 
+ 	rc = sscanf((char *)buf, "%d", &info->sata_info.ata_port);
+@@ -361,12 +361,12 @@ sysfs_parse_nvme(uint8_t *buf, ssize_t size, ssize_t *off,
+ 	rc = read_sysfs_file(&filebuf,
+ 			     "/sys/class/block/nvme%dn%d/eui",
+ 			     ctrl_id, ns_id);
+-	if (rc < 0 && errno == ENOENT) {
++	if ((rc < 0 && errno == ENOENT) || filebuf == NULL) {
+ 		rc = read_sysfs_file(&filebuf,
+ 			     "/sys/class/block/nvme%dn%d/device/eui",
+ 			     ctrl_id, ns_id);
+ 	}
+-	if (rc >= 0) {
++	if (rc >= 0 && filebuf != NULL) {
+ 		uint8_t eui[8];
+ 		if (rc < 23) {
+ 			errno = EINVAL;
+@@ -606,7 +606,7 @@ sysfs_parse_sas(uint8_t *buf, ssize_t size, ssize_t *off,
+ 	rc = read_sysfs_file(&filebuf,
+ 			     "/sys/class/block/%s/device/sas_address",
+ 			     disk_name);
+-	if (rc < 0)
++	if (rc < 0 || filebuf == NULL)
+ 		return -1;
+ 
+ 	rc = sscanf((char *)filebuf, "%"PRIx64, &sas_address);
+@@ -656,7 +656,7 @@ make_pci_path(uint8_t *buf, ssize_t size, char *pathstr, ssize_t *pathoff)
+ 	rc = read_sysfs_file(&fbuf,
+ 			     "/sys/devices/pci%04x:%02x/firmware_node/hid",
+ 			     root_domain, root_bus);
+-	if (rc < 0)
++	if (rc < 0 || fbuf == NULL)
+ 		return -1;
+ 
+ 	uint16_t tmp16 = 0;
+@@ -679,7 +679,7 @@ make_pci_path(uint8_t *buf, ssize_t size, char *pathstr, ssize_t *pathoff)
+ 	rc = read_sysfs_file(&fbuf,
+ 			     "/sys/devices/pci%4x:%02x/firmware_node/uid",
+ 			     root_domain, root_bus);
+-	if (rc <= 0 && errno != ENOENT)
++	if ((rc <= 0 && errno != ENOENT) || fbuf == NULL)
+ 		return -1;
+ 	if (rc > 0) {
+ 		rc = sscanf((char *)fbuf, "%"PRIu64"\n", &acpi_uid_int);
+-- 
+2.12.2
+
diff --git a/SPECS/efivar.spec b/SPECS/efivar.spec
index b8408b1..68243f5 100644
--- a/SPECS/efivar.spec
+++ b/SPECS/efivar.spec
@@ -1,15 +1,39 @@
 Name:           efivar
-Version:        0.11
-Release:        1%{?dist}
+Version:        31
+Release:        4%{?dist}
 Summary:        Tools to manage UEFI variables
 License:        LGPLv2.1
-URL:            https://github.com/vathpela/efivar
+URL:            https://github.com/rhinstaller/efivar
 Requires:       %{name}-libs = %{version}-%{release}
-ExclusiveArch:	i386 x86_64 aarch64
-
-BuildRequires:  popt-devel git
-Source0:        https://github.com/vathpela/%{name}/archive/efivar-%{version}.tar.bz2
-Patch0001:	0001-Revert-Only-open-with-O_CREAT-if-we-re-not-using-EFI.patch
+ExclusiveArch:	x86_64 aarch64
+
+BuildRequires:  popt popt-devel popt-static git glibc-static
+Source0:        https://github.com/rhinstaller/efivar/releases/download/efivar-%{version}/efivar-%{version}.tar.bz2
+Patch0001:	0001-libabigail-isn-t-in-RHEL-yet-so-nerf-the-abi-check.patch
+Patch0002:	0002-Don-t-use-_Generic-because-gcc-4.x-doesn-t-have-it.patch
+Patch0003:	0003-popt-devel-in-RHEL-7.4-doesn-t-provide-popt.pc-so-in.patch
+Patch0004:	0004-efi_loadopt_args_from_file-fix-leaked-file-descripto.patch
+Patch0005:	0005-make_mac_path-fix-leaked-file-descriptor.patch
+Patch0006:	0006-gpt_disk_get_partition_info-free-our-allocations-on-.patch
+Patch0007:	0007-efi_generate_file_device_path-fix-one-error-case-s-f.patch
+Patch0008:	0008-efi_va_generate_file_device_path_from_esp-handle-err.patch
+Patch0009:	0009-efi_variable_import-fix-memory-leak-on-failure-path.patch
+Patch0010:	0010-efidp_append_path-error-check-the-right-variable.patch
+Patch0011:	0011-efi_variable_import-make-sure-var.data_size-is-set.patch
+Patch0012:	0012-makeguids-free-our-input-buffer.patch
+Patch0013:	0013-efi_variable_import-constrain-our-inputs-better.patch
+Patch0014:	0014-efi_loadopt_create-check-buf-for-NULLness.patch
+Patch0015:	0015-efidp_duplicate_extra-error-if-our-allocation-is-too.patch
+Patch0016:	0016-show_errors-make-the-useful-part-here-not-be-dead-co.patch
+Patch0017:	0017-efi_loadopt_args_from_file-make-sure-buf-is-only-NUL.patch
+Patch0018:	0018-calls-to-sysfs_readlink-check-linkbuf-for-NULLness.patch
+Patch0019:	0019-efivar-main-explain-efi_well_known_guids-to-the-comp.patch
+Patch0020:	0020-dp.h-Try-to-make-covscan-believe-format-is-checking-.patch
+Patch0021:	0021-gpt-try-to-avoid-trusting-unverified-partition-table.patch
+Patch0022:	0022-Simplify-efidp_append_node-even-more.patch
+Patch0023:	0023-efi_loadopt_create-avoid-NULL-dereference.patch
+Patch0024:	0024-efi_generate_file_device_path-make-all-error-paths-u.patch
+Patch0025:	0025-linux.c-fix-a-pile-of-sscanf-NULL-.-possibilities.patch
 
 %description
 efivar provides a simple command line interface to the UEFI variable facility.
@@ -35,9 +59,11 @@ git config user.name "RHEL Ninjas"
 git add .
 git commit -a -q -m "%{version} baseline."
 git am %{patches} </dev/null
+git config --unset user.email
+git config --unset user.name
 
 %build
-make libdir=%{_libdir} bindir=%{_bindir} OPT_FLAGS="$RPM_OPT_FLAGS"
+make libdir=%{_libdir} bindir=%{_bindir} CFLAGS="$RPM_OPT_FLAGS -flto" LDFLAGS="$RPM_LD_FLAGS -flto"
 
 %install
 rm -rf $RPM_BUILD_ROOT
@@ -51,8 +77,11 @@ rm -rf $RPM_BUILD_ROOT
 %postun libs -p /sbin/ldconfig
 
 %files
-%doc COPYING README
+%{!?_licensedir:%global license %%doc}
+%license COPYING
+%doc README.md
 %{_bindir}/efivar
+%exclude %{_bindir}/efivar-static
 %{_mandir}/man1/*
 
 %files devel
@@ -65,6 +94,26 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/*.so.*
 
 %changelog
+* Tue May 09 2017 Peter Jones <pjones@redhat.com> - 31-4
+- Fix a bunch of coverity issues.
+  Related: rhbz#1380825
+  Related: rhbz#1310779
+
+* Tue May 09 2017 Peter Jones <pjones@redhat.com> - 31-3
+- Fix a bunch of coverity issues.
+  Related: rhbz#1380825
+  Related: rhbz#1310779
+
+* Tue May 09 2017 Peter Jones <pjones@redhat.com> - 31-2
+- Fix a bunch of coverity issues.
+  Related: rhbz#1380825
+  Related: rhbz#1310779
+
+* Mon Mar 13 2017 Peter Jones <pjones@redhat.com> - 31-1
+- Update to efivar 31
+  Related: rhbz#1380825
+  Related: rhbz#1310779
+
 * Wed Aug 20 2014 Peter Jones <pjones@redhat.com> - 0.11-1
 - Update to 0.11