diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-12-06 12:13:34 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-12-15 21:06:42 +0100 |
commit | 35b9eb0a72b6254568a294f0ebd011da20958a64 (patch) | |
tree | 3016915686e94c719d64003cbba61970614174f2 /src/basic/efivars.c | |
parent | shared/efi-loader: add some debugging statements (diff) | |
download | systemd-35b9eb0a72b6254568a294f0ebd011da20958a64.tar.xz systemd-35b9eb0a72b6254568a294f0ebd011da20958a64.zip |
basic/efivars: do not return EIO if an efivar read is shorten than fstat size
On my machine stat returns size 22, but only 20 bytes are read:
openat(AT_FDCWD, "/sys/firmware/efi/efivars/LoaderTimeInitUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", O_RDONLY|O_NOCTTY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=22, ...}) = 0
read(3, "\6\0\0\0", 4) = 4
read(3, "7\0001\0001\0003\0005\0002\0007\0\0\0", 18) = 16
Failed to read LoaderTimeInitUSec: Input/output error
Let's just accept that the kernel is returning inconsistent results.
It seems to happen two only two variables on my machine:
/sys/firmware/efi/efivars/LoaderTimeInitUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
/sys/firmware/efi/efivars/LoaderTimeMenuUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
so it might be related to the way we write them.
Diffstat (limited to 'src/basic/efivars.c')
-rw-r--r-- | src/basic/efivars.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/src/basic/efivars.c b/src/basic/efivars.c index 7b14c062df..bfde67a883 100644 --- a/src/basic/efivars.c +++ b/src/basic/efivars.c @@ -90,13 +90,14 @@ int efi_get_variable( n = read(fd, buf, (size_t) st.st_size - 4); if (n < 0) return -errno; - if (n != st.st_size - 4) - return -EIO; + assert(n <= st.st_size - 4); /* Always NUL terminate (2 bytes, to protect UTF-16) */ - ((char*) buf)[st.st_size - 4] = 0; - ((char*) buf)[st.st_size - 4 + 1] = 0; - } + ((char*) buf)[n - 4] = 0; + ((char*) buf)[n - 4 + 1] = 0; + } else + /* Assume that the reported size is accurate */ + n = st.st_size - 4; /* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable * with a smaller value. */ @@ -108,7 +109,7 @@ int efi_get_variable( *ret_value = TAKE_PTR(buf); if (ret_size) - *ret_size = (size_t) st.st_size - 4; + *ret_size = n; return 0; } |