]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/efivars: do not return EIO if an efivar read is shorten than fstat size
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 6 Dec 2019 11:13:34 +0000 (12:13 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 15 Dec 2019 20:06:42 +0000 (21:06 +0100)
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.

src/basic/efivars.c

index 7b14c062df1df251cf89c04c318663b06cce906a..bfde67a883b9fb7e56791ae0dcbcd28b2a3b806e 100644 (file)
@@ -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;
 }