Update to efivar 35

fixes for older compilers
efi_get_variable_exists()
Lots of stuff to make CI work.
use usleep() to avoid hitting the kernel rate limiter on efivarfs
better EFI_GUID macro
add efi_guid_fwupdate (0abba7dc-e516-4167-bbf5-4d9d1c739416)

Signed-off-by: Peter Jones <pjones@redhat.com>
This commit is contained in:
Peter Jones 2018-04-09 14:56:58 -04:00
parent 1cf335fff3
commit a5e29614d5
3 changed files with 11 additions and 120 deletions

View File

@ -1,117 +0,0 @@
From 5ea8c3400693b30c2b65a887899dc2a8e36a9688 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 23 Feb 2018 15:49:02 -0500
Subject: [PATCH] efivarfs / vars: usleep() before reading from efivarfs if
euid != 0
There's a kernel rate limiter on efi variable reads now for
non-root users, and we'd rather just not hit it than have to dig out
from having hit it. So this adds a 10ms sleep before each read call.
If you do have 50 variables, efibootmgr will do 100 reads, which would
trigger the rate limit. In that case, this patch adds 1 second (plus
lossage due to calling, etc.), so it should stay just below the
triggering threshold. That will definitely be /smoother/ than hitting
it, and almost certainly faster as well, because the extra calls will
re-enforce the limit.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
src/efivarfs.c | 12 ++++++++++++
src/vars.c | 11 +++++++++++
src/util.h | 7 +++++++
3 files changed, 30 insertions(+)
diff --git a/src/efivarfs.c b/src/efivarfs.c
index d1458a24d1e..38e4074e977 100644
--- a/src/efivarfs.c
+++ b/src/efivarfs.c
@@ -220,6 +220,16 @@ efivarfs_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
int fd = -1;
char *path = NULL;
int rc;
+ int ratelimit;
+
+ /*
+ * The kernel rate limiter hits us if we go faster than 100 efi
+ * variable reads per second as non-root. So if we're not root, just
+ * delay this long after each read. The user is not going to notice.
+ *
+ * 1s / 100 = 10000us.
+ */
+ ratelimit = geteuid() == 0 ? 0 : 10000;
rc = make_efivarfs_path(&path, guid, name);
if (rc < 0) {
@@ -233,12 +243,14 @@ efivarfs_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
goto err;
}
+ usleep(ratelimit);
rc = read(fd, &ret_attributes, sizeof (ret_attributes));
if (rc < 0) {
efi_error("read failed");
goto err;
}
+ usleep(ratelimit);
rc = read_file(fd, &ret_data, &size);
if (rc < 0) {
efi_error("read_file failed");
diff --git a/src/vars.c b/src/vars.c
index a7b5e2387f9..8522725a51f 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -305,6 +305,16 @@ vars_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
char *path = NULL;
int rc;
int fd = -1;
+ int ratelimit;
+
+ /*
+ * The kernel rate limiter hits us if we go faster than 100 efi
+ * variable reads per second as non-root. So if we're not root, just
+ * delay this long after each read. The user is not going to notice.
+ *
+ * 1s / 100 = 10000us.
+ */
+ ratelimit = geteuid() == 0 ? 0 : 10000;
rc = asprintf(&path, "%s%s-" GUID_FORMAT "/raw_var",
get_vars_path(),
@@ -322,6 +332,7 @@ vars_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
goto err;
}
+ usleep(ratelimit);
rc = read_file(fd, &buf, &bufsize);
if (rc < 0) {
efi_error("read_file(%s) failed", path);
diff --git a/src/util.h b/src/util.h
index deef7e71bc4..69042d3cf9a 100644
--- a/src/util.h
+++ b/src/util.h
@@ -25,6 +25,7 @@
#include <endian.h>
#include <errno.h>
#include <limits.h>
+#include <sched.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -137,6 +138,12 @@ read_file(int fd, uint8_t **buf, size_t *bufsize)
* before doing so. */
s = read(fd, p, size - filesize);
if (s < 0 && errno == EAGAIN) {
+ /*
+ * if we got EAGAIN, there's a good chance we've hit
+ * the kernel rate limiter. Doing more reads is just
+ * going to make it worse, so instead, give it a rest.
+ */
+ sched_yield();
continue;
} else if (s < 0) {
int saved_errno = errno;
--
2.15.0

View File

@ -1,5 +1,5 @@
Name: efivar
Version: 34
Version: 35
Release: 1%{?dist}
Summary: Tools to manage UEFI variables
License: LGPLv2.1
@ -11,7 +11,6 @@ BuildRequires: popt-devel git glibc-static libabigail
# please don't fix this to reflect github's incomprehensible url that goes
# to a different tarball.
Source0: https://github.com/rhboot/efivar/archive/efivar-%{version}.tar.bz2
Patch0001: 0001-efivarfs-vars-usleep-before-reading-from-efivarfs-if.patch
%description
efivar provides a simple command line interface to the UEFI variable facility.
@ -73,6 +72,15 @@ make libdir=%{_libdir} bindir=%{_bindir} CFLAGS="$RPM_OPT_FLAGS -flto" LDFLAGS="
%{_libdir}/*.so.*
%changelog
* Mon Apr 09 2018 Peter Jones <pjones@redhat.com> - 35-1
- Update to efivar 35
- fixes for older compilers
- efi_get_variable_exists()
- Lots of stuff to make CI work.
- use usleep() to avoid hitting the kernel rate limiter on efivarfs
- better EFI_GUID macro
- add efi_guid_fwupdate (0abba7dc-e516-4167-bbf5-4d9d1c739416)
* Tue Feb 27 2018 Peter Jones <pjones@redhat.com> - 34-1
- Update to efivar 34, and include a patch to avoid upstream rate limiting.

View File

@ -1 +1 @@
SHA512 (efivar-34.tar.bz2) = 6baa02e1ad919f84d129a032a4631126d6f43dfc247f63c247624cc2af697fb627fd76fe0ffed069b42b835d862582877644fb19843361ef9ced62aa7cd518c4
SHA512 (efivar-35.tar.bz2) = c7ba60b2112053f088ad0b74aaa834860601b7fe17118c35b012050176f5205d948fba9c4b6de35991249f702e3bc24832539e2eb3c235c4188e1eabc78965ee