LCOV - code coverage report
Current view: top level - core - efi-random.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 50 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 2 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 54 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <fcntl.h>
       4                 :            : #include <linux/random.h>
       5                 :            : #include <sys/ioctl.h>
       6                 :            : #include <unistd.h>
       7                 :            : 
       8                 :            : #include "alloc-util.h"
       9                 :            : #include "chattr-util.h"
      10                 :            : #include "efi-random.h"
      11                 :            : #include "efivars.h"
      12                 :            : #include "fd-util.h"
      13                 :            : #include "fs-util.h"
      14                 :            : #include "strv.h"
      15                 :            : 
      16                 :            : /* If a random seed was passed by the boot loader in the LoaderRandomSeed EFI variable, let's credit it to
      17                 :            :  * the kernel's random pool, but only once per boot. If this is run very early during initialization we can
      18                 :            :  * instantly boot up with a filled random pool.
      19                 :            :  *
      20                 :            :  * This makes no judgement on the entropy passed, it's the job of the boot loader to only pass us a seed that
      21                 :            :  * is suitably validated. */
      22                 :            : 
      23                 :          0 : static void lock_down_efi_variables(void) {
      24                 :            :         const char *p;
      25                 :            :         int r;
      26                 :            : 
      27                 :            :         /* Paranoia: let's restrict access modes of these a bit, so that unprivileged users can't use them to
      28                 :            :          * identify the system or gain too much insight into what we might have credited to the entropy
      29                 :            :          * pool. */
      30         [ #  # ]:          0 :         FOREACH_STRING(p,
      31                 :            :                        "/sys/firmware/efi/efivars/LoaderRandomSeed-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f",
      32                 :            :                        "/sys/firmware/efi/efivars/LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f") {
      33                 :            : 
      34                 :          0 :                 r = chattr_path(p, 0, FS_IMMUTABLE_FL, NULL);
      35         [ #  # ]:          0 :                 if (r == -ENOENT)
      36                 :          0 :                         continue;
      37         [ #  # ]:          0 :                 if (r < 0)
      38         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to drop FS_IMMUTABLE_FL from %s, ignoring: %m", p);
      39                 :            : 
      40         [ #  # ]:          0 :                 if (chmod(p, 0600) < 0)
      41         [ #  # ]:          0 :                         log_warning_errno(errno, "Failed to reduce access mode of %s, ignoring: %m", p);
      42                 :            :         }
      43                 :          0 : }
      44                 :            : 
      45                 :          0 : int efi_take_random_seed(void) {
      46                 :          0 :         _cleanup_free_ struct rand_pool_info *info = NULL;
      47                 :          0 :         _cleanup_free_ void *value = NULL;
      48                 :          0 :         _cleanup_close_ int random_fd = -1;
      49                 :            :         size_t size;
      50                 :            :         int r;
      51                 :            : 
      52                 :            :         /* Paranoia comes first. */
      53                 :          0 :         lock_down_efi_variables();
      54                 :            : 
      55         [ #  # ]:          0 :         if (access("/run/systemd/efi-random-seed-taken", F_OK) < 0) {
      56         [ #  # ]:          0 :                 if (errno != ENOENT) {
      57         [ #  # ]:          0 :                         log_warning_errno(errno, "Failed to determine whether we already used the random seed token, not using it.");
      58                 :          0 :                         return 0;
      59                 :            :                 }
      60                 :            : 
      61                 :            :                 /* ENOENT means we haven't used it yet. */
      62                 :            :         } else {
      63         [ #  # ]:          0 :                 log_debug("EFI random seed already used, not using again.");
      64                 :          0 :                 return 0;
      65                 :            :         }
      66                 :            : 
      67                 :          0 :         r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderRandomSeed", NULL, &value, &size);
      68         [ #  # ]:          0 :         if (r == -EOPNOTSUPP) {
      69         [ #  # ]:          0 :                 log_debug_errno(r, "System lacks EFI support, not initializing random seed from EFI variable.");
      70                 :          0 :                 return 0;
      71                 :            :         }
      72         [ #  # ]:          0 :         if (r == -ENOENT) {
      73         [ #  # ]:          0 :                 log_debug_errno(r, "Boot loader did not pass LoaderRandomSeed EFI variable, not crediting any entropy.");
      74                 :          0 :                 return 0;
      75                 :            :         }
      76         [ #  # ]:          0 :         if (r < 0)
      77         [ #  # ]:          0 :                 return log_warning_errno(r, "Failed to read LoaderRandomSeed EFI variable, ignoring: %m");
      78                 :            : 
      79         [ #  # ]:          0 :         if (size == 0)
      80         [ #  # ]:          0 :                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Random seed passed from boot loader has zero size? Ignoring.");
      81                 :            : 
      82                 :            :         /* The kernel API only accepts "int" as entropy count (which is in bits), let's avoid any chance for
      83                 :            :          * confusion here. */
      84         [ #  # ]:          0 :         if (size > INT_MAX / 8)
      85                 :          0 :                 size = INT_MAX / 8;
      86                 :            : 
      87                 :          0 :         random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
      88         [ #  # ]:          0 :         if (random_fd < 0)
      89         [ #  # ]:          0 :                 return log_warning_errno(errno, "Failed to open /dev/urandom for writing, ignoring: %m");
      90                 :            : 
      91                 :            :         /* Before we use the seed, let's mark it as used, so that we never credit it twice. Also, it's a nice
      92                 :            :          * way to let users known that we successfully acquired entropy from the boot laoder. */
      93                 :          0 :         r = touch("/run/systemd/efi-random-seed-taken");
      94         [ #  # ]:          0 :         if (r < 0)
      95         [ #  # ]:          0 :                 return log_warning_errno(r, "Unable to mark EFI random seed as used, not using it: %m");
      96                 :            : 
      97                 :          0 :         info = malloc(offsetof(struct rand_pool_info, buf) + size);
      98         [ #  # ]:          0 :         if (!info)
      99                 :          0 :                 return log_oom();
     100                 :            : 
     101                 :          0 :         info->entropy_count = size * 8;
     102                 :          0 :         info->buf_size = size;
     103                 :          0 :         memcpy(info->buf, value, size);
     104                 :            : 
     105         [ #  # ]:          0 :         if (ioctl(random_fd, RNDADDENTROPY, info) < 0)
     106         [ #  # ]:          0 :                 return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m");
     107                 :            : 
     108         [ #  # ]:          0 :         log_info("Successfully credited entropy passed from boot loader.");
     109                 :          0 :         return 1;
     110                 :            : }

Generated by: LCOV version 1.14