LCOV - code coverage report
Current view: top level - gpt-auto-generator - gpt-auto-generator.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 398 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 17 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 528 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <blkid.h>
       4                 :            : #include <stdlib.h>
       5                 :            : #include <sys/statfs.h>
       6                 :            : #include <unistd.h>
       7                 :            : 
       8                 :            : #include "sd-device.h"
       9                 :            : #include "sd-id128.h"
      10                 :            : 
      11                 :            : #include "alloc-util.h"
      12                 :            : #include "blkid-util.h"
      13                 :            : #include "blockdev-util.h"
      14                 :            : #include "btrfs-util.h"
      15                 :            : #include "device-util.h"
      16                 :            : #include "dirent-util.h"
      17                 :            : #include "dissect-image.h"
      18                 :            : #include "efivars.h"
      19                 :            : #include "fd-util.h"
      20                 :            : #include "fileio.h"
      21                 :            : #include "fs-util.h"
      22                 :            : #include "fstab-util.h"
      23                 :            : #include "generator.h"
      24                 :            : #include "gpt.h"
      25                 :            : #include "missing.h"
      26                 :            : #include "mkdir.h"
      27                 :            : #include "mountpoint-util.h"
      28                 :            : #include "parse-util.h"
      29                 :            : #include "path-util.h"
      30                 :            : #include "proc-cmdline.h"
      31                 :            : #include "special.h"
      32                 :            : #include "specifier.h"
      33                 :            : #include "stat-util.h"
      34                 :            : #include "string-util.h"
      35                 :            : #include "strv.h"
      36                 :            : #include "unit-name.h"
      37                 :            : #include "util.h"
      38                 :            : #include "virt.h"
      39                 :            : 
      40                 :            : static const char *arg_dest = NULL;
      41                 :            : static bool arg_enabled = true;
      42                 :            : static bool arg_root_enabled = true;
      43                 :            : static int arg_root_rw = -1;
      44                 :            : 
      45                 :          0 : static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
      46                 :          0 :         _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
      47                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
      48                 :            :         const char *p;
      49                 :            :         int r;
      50                 :            : 
      51         [ #  # ]:          0 :         assert(id);
      52         [ #  # ]:          0 :         assert(what);
      53                 :            : 
      54                 :          0 :         r = unit_name_from_path(what, ".device", &d);
      55         [ #  # ]:          0 :         if (r < 0)
      56         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to generate unit name: %m");
      57                 :            : 
      58                 :          0 :         e = unit_name_escape(id);
      59         [ #  # ]:          0 :         if (!e)
      60                 :          0 :                 return log_oom();
      61                 :            : 
      62                 :          0 :         r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
      63         [ #  # ]:          0 :         if (r < 0)
      64         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to generate unit name: %m");
      65                 :            : 
      66                 :          0 :         id_escaped = specifier_escape(id);
      67         [ #  # ]:          0 :         if (!id_escaped)
      68                 :          0 :                 return log_oom();
      69                 :            : 
      70                 :          0 :         what_escaped = specifier_escape(what);
      71         [ #  # ]:          0 :         if (!what_escaped)
      72                 :          0 :                 return log_oom();
      73                 :            : 
      74   [ #  #  #  #  :          0 :         p = prefix_roota(arg_dest, n);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
      75                 :          0 :         f = fopen(p, "wxe");
      76         [ #  # ]:          0 :         if (!f)
      77         [ #  # ]:          0 :                 return log_error_errno(errno, "Failed to create unit file %s: %m", p);
      78                 :            : 
      79         [ #  # ]:          0 :         fprintf(f,
      80                 :            :                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
      81                 :            :                 "[Unit]\n"
      82                 :            :                 "Description=Cryptography Setup for %%I\n"
      83                 :            :                 "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
      84                 :            :                 "DefaultDependencies=no\n"
      85                 :            :                 "Conflicts=umount.target\n"
      86                 :            :                 "BindsTo=dev-mapper-%%i.device %s\n"
      87                 :            :                 "Before=umount.target cryptsetup.target\n"
      88                 :            :                 "After=%s\n"
      89                 :            :                 "IgnoreOnIsolate=true\n"
      90                 :            :                 "[Service]\n"
      91                 :            :                 "Type=oneshot\n"
      92                 :            :                 "RemainAfterExit=yes\n"
      93                 :            :                 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
      94                 :            :                 "KeyringMode=shared\n" /* make sure we can share cached keys among instances */
      95                 :            :                 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
      96                 :            :                 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
      97                 :            :                 d, d,
      98                 :            :                 id_escaped, what_escaped, rw ? "" : "read-only",
      99                 :            :                 id_escaped);
     100                 :            : 
     101                 :          0 :         r = fflush_and_check(f);
     102         [ #  # ]:          0 :         if (r < 0)
     103         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to write file %s: %m", p);
     104                 :            : 
     105                 :          0 :         r = generator_add_symlink(arg_dest, d, "wants", n);
     106         [ #  # ]:          0 :         if (r < 0)
     107                 :          0 :                 return r;
     108                 :            : 
     109         [ #  # ]:          0 :         if (require) {
     110                 :            :                 const char *dmname;
     111                 :            : 
     112                 :          0 :                 r = generator_add_symlink(arg_dest, "cryptsetup.target", "requires", n);
     113         [ #  # ]:          0 :                 if (r < 0)
     114                 :          0 :                         return r;
     115                 :            : 
     116   [ #  #  #  #  :          0 :                 dmname = strjoina("dev-mapper-", e, ".device");
          #  #  #  #  #  
                #  #  # ]
     117                 :          0 :                 r = generator_add_symlink(arg_dest, dmname, "requires", n);
     118         [ #  # ]:          0 :                 if (r < 0)
     119                 :          0 :                         return r;
     120                 :            :         }
     121                 :            : 
     122   [ #  #  #  #  :          0 :         p = strjoina(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf");
          #  #  #  #  #  
                #  #  # ]
     123                 :          0 :         mkdir_parents_label(p, 0755);
     124                 :          0 :         r = write_string_file(p,
     125                 :            :                         "# Automatically generated by systemd-gpt-auto-generator\n\n"
     126                 :            :                         "[Unit]\n"
     127                 :            :                         "JobTimeoutSec=0\n",
     128                 :            :                         WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
     129         [ #  # ]:          0 :         if (r < 0)
     130         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to write device drop-in: %m");
     131                 :            : 
     132         [ #  # ]:          0 :         if (device) {
     133                 :            :                 char *ret;
     134                 :            : 
     135                 :          0 :                 ret = path_join("/dev/mapper", id);
     136         [ #  # ]:          0 :                 if (!ret)
     137                 :          0 :                         return log_oom();
     138                 :            : 
     139                 :          0 :                 *device = ret;
     140                 :            :         }
     141                 :            : 
     142                 :          0 :         return 0;
     143                 :            : }
     144                 :            : 
     145                 :          0 : static int add_mount(
     146                 :            :                 const char *id,
     147                 :            :                 const char *what,
     148                 :            :                 const char *where,
     149                 :            :                 const char *fstype,
     150                 :            :                 bool rw,
     151                 :            :                 const char *options,
     152                 :            :                 const char *description,
     153                 :            :                 const char *post) {
     154                 :            : 
     155                 :          0 :         _cleanup_free_ char *unit = NULL, *crypto_what = NULL, *p = NULL;
     156                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
     157                 :            :         int r;
     158                 :            : 
     159                 :            :         /* Note that we don't apply specifier escaping on the input strings here, since we know they are not configured
     160                 :            :          * externally, but all originate from our own sources here, and hence we know they contain no % characters that
     161                 :            :          * could potentially be understood as specifiers. */
     162                 :            : 
     163         [ #  # ]:          0 :         assert(id);
     164         [ #  # ]:          0 :         assert(what);
     165         [ #  # ]:          0 :         assert(where);
     166         [ #  # ]:          0 :         assert(description);
     167                 :            : 
     168         [ #  # ]:          0 :         log_debug("Adding %s: %s %s", where, what, strna(fstype));
     169                 :            : 
     170         [ #  # ]:          0 :         if (streq_ptr(fstype, "crypto_LUKS")) {
     171                 :            : 
     172                 :          0 :                 r = add_cryptsetup(id, what, rw, true, &crypto_what);
     173         [ #  # ]:          0 :                 if (r < 0)
     174                 :          0 :                         return r;
     175                 :            : 
     176                 :          0 :                 what = crypto_what;
     177                 :          0 :                 fstype = NULL;
     178                 :            :         }
     179                 :            : 
     180                 :          0 :         r = unit_name_from_path(where, ".mount", &unit);
     181         [ #  # ]:          0 :         if (r < 0)
     182         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to generate unit name: %m");
     183                 :            : 
     184                 :          0 :         p = path_join(empty_to_root(arg_dest), unit);
     185         [ #  # ]:          0 :         if (!p)
     186                 :          0 :                 return log_oom();
     187                 :            : 
     188                 :          0 :         f = fopen(p, "wxe");
     189         [ #  # ]:          0 :         if (!f)
     190         [ #  # ]:          0 :                 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
     191                 :            : 
     192                 :          0 :         fprintf(f,
     193                 :            :                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
     194                 :            :                 "[Unit]\n"
     195                 :            :                 "Description=%s\n"
     196                 :            :                 "Documentation=man:systemd-gpt-auto-generator(8)\n",
     197                 :            :                 description);
     198                 :            : 
     199         [ #  # ]:          0 :         if (post)
     200                 :          0 :                 fprintf(f, "Before=%s\n", post);
     201                 :            : 
     202                 :          0 :         r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
     203         [ #  # ]:          0 :         if (r < 0)
     204                 :          0 :                 return r;
     205                 :            : 
     206                 :          0 :         fprintf(f,
     207                 :            :                 "\n"
     208                 :            :                 "[Mount]\n"
     209                 :            :                 "What=%s\n"
     210                 :            :                 "Where=%s\n",
     211                 :            :                 what, where);
     212                 :            : 
     213         [ #  # ]:          0 :         if (fstype)
     214                 :          0 :                 fprintf(f, "Type=%s\n", fstype);
     215                 :            : 
     216         [ #  # ]:          0 :         if (options)
     217         [ #  # ]:          0 :                 fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro");
     218                 :            :         else
     219         [ #  # ]:          0 :                 fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
     220                 :            : 
     221                 :          0 :         r = fflush_and_check(f);
     222         [ #  # ]:          0 :         if (r < 0)
     223         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to write unit file %s: %m", p);
     224                 :            : 
     225         [ #  # ]:          0 :         if (post)
     226                 :          0 :                 return generator_add_symlink(arg_dest, post, "requires", unit);
     227                 :          0 :         return 0;
     228                 :            : }
     229                 :            : 
     230                 :          0 : static int path_is_busy(const char *where) {
     231                 :            :         int r;
     232                 :            : 
     233                 :            :         /* already a mountpoint; generators run during reload */
     234                 :          0 :         r = path_is_mount_point(where, NULL, AT_SYMLINK_FOLLOW);
     235         [ #  # ]:          0 :         if (r > 0)
     236                 :          0 :                 return false;
     237                 :            : 
     238                 :            :         /* the directory might not exist on a stateless system */
     239         [ #  # ]:          0 :         if (r == -ENOENT)
     240                 :          0 :                 return false;
     241                 :            : 
     242         [ #  # ]:          0 :         if (r < 0)
     243         [ #  # ]:          0 :                 return log_warning_errno(r, "Cannot check if \"%s\" is a mount point: %m", where);
     244                 :            : 
     245                 :            :         /* not a mountpoint but it contains files */
     246                 :          0 :         r = dir_is_empty(where);
     247         [ #  # ]:          0 :         if (r < 0)
     248         [ #  # ]:          0 :                 return log_warning_errno(r, "Cannot check if \"%s\" is empty: %m", where);
     249         [ #  # ]:          0 :         if (r > 0)
     250                 :          0 :                 return false;
     251                 :            : 
     252         [ #  # ]:          0 :         log_debug("\"%s\" already populated, ignoring.", where);
     253                 :          0 :         return true;
     254                 :            : }
     255                 :            : 
     256                 :          0 : static int add_partition_mount(
     257                 :            :                 DissectedPartition *p,
     258                 :            :                 const char *id,
     259                 :            :                 const char *where,
     260                 :            :                 const char *description) {
     261                 :            : 
     262                 :            :         int r;
     263         [ #  # ]:          0 :         assert(p);
     264                 :            : 
     265                 :          0 :         r = path_is_busy(where);
     266         [ #  # ]:          0 :         if (r != 0)
     267                 :          0 :                 return r < 0 ? r : 0;
     268                 :            : 
     269                 :          0 :         return add_mount(
     270                 :            :                         id,
     271                 :          0 :                         p->node,
     272                 :            :                         where,
     273                 :          0 :                         p->fstype,
     274                 :          0 :                         p->rw,
     275                 :            :                         NULL,
     276                 :            :                         description,
     277                 :            :                         SPECIAL_LOCAL_FS_TARGET);
     278                 :            : }
     279                 :            : 
     280                 :          0 : static int add_swap(const char *path) {
     281                 :          0 :         _cleanup_free_ char *name = NULL, *unit = NULL;
     282                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
     283                 :            :         int r;
     284                 :            : 
     285         [ #  # ]:          0 :         assert(path);
     286                 :            : 
     287                 :            :         /* Disable the swap auto logic if at least one swap is defined in /etc/fstab, see #6192. */
     288                 :          0 :         r = fstab_has_fstype("swap");
     289         [ #  # ]:          0 :         if (r < 0)
     290         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to parse fstab: %m");
     291         [ #  # ]:          0 :         if (r > 0) {
     292         [ #  # ]:          0 :                 log_debug("swap specified in fstab, ignoring.");
     293                 :          0 :                 return 0;
     294                 :            :         }
     295                 :            : 
     296         [ #  # ]:          0 :         log_debug("Adding swap: %s", path);
     297                 :            : 
     298                 :          0 :         r = unit_name_from_path(path, ".swap", &name);
     299         [ #  # ]:          0 :         if (r < 0)
     300         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to generate unit name: %m");
     301                 :            : 
     302                 :          0 :         unit = path_join(empty_to_root(arg_dest), name);
     303         [ #  # ]:          0 :         if (!unit)
     304                 :          0 :                 return log_oom();
     305                 :            : 
     306                 :          0 :         f = fopen(unit, "wxe");
     307         [ #  # ]:          0 :         if (!f)
     308         [ #  # ]:          0 :                 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
     309                 :            : 
     310                 :          0 :         fprintf(f,
     311                 :            :                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
     312                 :            :                 "[Unit]\n"
     313                 :            :                 "Description=Swap Partition\n"
     314                 :            :                 "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
     315                 :            :                 "[Swap]\n"
     316                 :            :                 "What=%s\n",
     317                 :            :                 path);
     318                 :            : 
     319                 :          0 :         r = fflush_and_check(f);
     320         [ #  # ]:          0 :         if (r < 0)
     321         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
     322                 :            : 
     323                 :          0 :         return generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET, "wants", name);
     324                 :            : }
     325                 :            : 
     326                 :          0 : static int add_automount(
     327                 :            :                 const char *id,
     328                 :            :                 const char *what,
     329                 :            :                 const char *where,
     330                 :            :                 const char *fstype,
     331                 :            :                 bool rw,
     332                 :            :                 const char *options,
     333                 :            :                 const char *description,
     334                 :            :                 usec_t timeout) {
     335                 :            : 
     336                 :          0 :         _cleanup_free_ char *unit = NULL;
     337                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
     338                 :          0 :         const char *opt = "noauto", *p;
     339                 :            :         int r;
     340                 :            : 
     341         [ #  # ]:          0 :         assert(id);
     342         [ #  # ]:          0 :         assert(where);
     343         [ #  # ]:          0 :         assert(description);
     344                 :            : 
     345         [ #  # ]:          0 :         if (options)
     346   [ #  #  #  #  :          0 :                 opt = strjoina(options, ",", opt);
          #  #  #  #  #  
                #  #  # ]
     347                 :            : 
     348                 :          0 :         r = add_mount(id,
     349                 :            :                       what,
     350                 :            :                       where,
     351                 :            :                       fstype,
     352                 :            :                       rw,
     353                 :            :                       opt,
     354                 :            :                       description,
     355                 :            :                       NULL);
     356         [ #  # ]:          0 :         if (r < 0)
     357                 :          0 :                 return r;
     358                 :            : 
     359                 :          0 :         r = unit_name_from_path(where, ".automount", &unit);
     360         [ #  # ]:          0 :         if (r < 0)
     361         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to generate unit name: %m");
     362                 :            : 
     363   [ #  #  #  #  :          0 :         p = prefix_roota(arg_dest, unit);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     364                 :          0 :         f = fopen(p, "wxe");
     365         [ #  # ]:          0 :         if (!f)
     366         [ #  # ]:          0 :                 return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
     367                 :            : 
     368                 :          0 :         fprintf(f,
     369                 :            :                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
     370                 :            :                 "[Unit]\n"
     371                 :            :                 "Description=%s\n"
     372                 :            :                 "Documentation=man:systemd-gpt-auto-generator(8)\n"
     373                 :            :                 "[Automount]\n"
     374                 :            :                 "Where=%s\n"
     375                 :            :                 "TimeoutIdleSec="USEC_FMT"\n",
     376                 :            :                 description,
     377                 :            :                 where,
     378                 :            :                 timeout / USEC_PER_SEC);
     379                 :            : 
     380                 :          0 :         r = fflush_and_check(f);
     381         [ #  # ]:          0 :         if (r < 0)
     382         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to write unit file %s: %m", p);
     383                 :            : 
     384                 :          0 :         return generator_add_symlink(arg_dest, SPECIAL_LOCAL_FS_TARGET, "wants", unit);
     385                 :            : }
     386                 :            : 
     387                 :          0 : static int add_xbootldr(DissectedPartition *p) {
     388                 :            :         int r;
     389                 :            : 
     390         [ #  # ]:          0 :         assert(p);
     391                 :            : 
     392         [ #  # ]:          0 :         if (in_initrd()) {
     393         [ #  # ]:          0 :                 log_debug("In initrd, ignoring the XBOOTLDR partition.");
     394                 :          0 :                 return 0;
     395                 :            :         }
     396                 :            : 
     397                 :          0 :         r = fstab_is_mount_point("/boot");
     398         [ #  # ]:          0 :         if (r < 0)
     399         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to parse fstab: %m");
     400         [ #  # ]:          0 :         if (r > 0) {
     401         [ #  # ]:          0 :                 log_debug("/boot specified in fstab, ignoring XBOOTLDR partition.");
     402                 :          0 :                 return 0;
     403                 :            :         }
     404                 :            : 
     405                 :          0 :         r = path_is_busy("/boot");
     406         [ #  # ]:          0 :         if (r < 0)
     407                 :          0 :                 return r;
     408         [ #  # ]:          0 :         if (r > 0)
     409                 :          0 :                 return 0;
     410                 :            : 
     411                 :          0 :         return add_automount("boot",
     412                 :          0 :                              p->node,
     413                 :            :                              "/boot",
     414                 :          0 :                              p->fstype,
     415                 :            :                              true,
     416                 :            :                              "umask=0077",
     417                 :            :                              "Boot Loader Partition",
     418                 :            :                              120 * USEC_PER_SEC);
     419                 :            : }
     420                 :            : 
     421                 :            : #if ENABLE_EFI
     422                 :          0 : static int add_esp(DissectedPartition *p, bool has_xbootldr) {
     423                 :          0 :         const char *esp_path = NULL, *id = NULL;
     424                 :            :         int r;
     425                 :            : 
     426         [ #  # ]:          0 :         assert(p);
     427                 :            : 
     428         [ #  # ]:          0 :         if (in_initrd()) {
     429         [ #  # ]:          0 :                 log_debug("In initrd, ignoring the ESP.");
     430                 :          0 :                 return 0;
     431                 :            :         }
     432                 :            : 
     433                 :            :         /* If /efi exists we'll use that. Otherwise we'll use /boot, as that's usually the better choice, but
     434                 :            :          * only if there's no explicit XBOOTLDR partition around. */
     435         [ #  # ]:          0 :         if (access("/efi", F_OK) < 0) {
     436         [ #  # ]:          0 :                 if (errno != ENOENT)
     437         [ #  # ]:          0 :                         return log_error_errno(errno, "Failed to determine whether /efi exists: %m");
     438                 :            : 
     439                 :            :                 /* Use /boot as fallback, but only if there's no XBOOTLDR partition */
     440         [ #  # ]:          0 :                 if (!has_xbootldr) {
     441                 :          0 :                         esp_path = "/boot";
     442                 :          0 :                         id = "boot";
     443                 :            :                 }
     444                 :            :         }
     445         [ #  # ]:          0 :         if (!esp_path)
     446                 :          0 :                 esp_path = "/efi";
     447         [ #  # ]:          0 :         if (!id)
     448                 :          0 :                 id = "efi";
     449                 :            : 
     450                 :            :         /* We create an .automount which is not overridden by the .mount from the fstab generator. */
     451                 :          0 :         r = fstab_is_mount_point(esp_path);
     452         [ #  # ]:          0 :         if (r < 0)
     453         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to parse fstab: %m");
     454         [ #  # ]:          0 :         if (r > 0) {
     455         [ #  # ]:          0 :                 log_debug("%s specified in fstab, ignoring.", esp_path);
     456                 :          0 :                 return 0;
     457                 :            :         }
     458                 :            : 
     459                 :          0 :         r = path_is_busy(esp_path);
     460         [ #  # ]:          0 :         if (r < 0)
     461                 :          0 :                 return r;
     462         [ #  # ]:          0 :         if (r > 0)
     463                 :          0 :                 return 0;
     464                 :            : 
     465         [ #  # ]:          0 :         if (is_efi_boot()) {
     466                 :            :                 sd_id128_t loader_uuid;
     467                 :            : 
     468                 :            :                 /* If this is an EFI boot, be extra careful, and only mount the ESP if it was the ESP used for booting. */
     469                 :            : 
     470                 :          0 :                 r = efi_loader_get_device_part_uuid(&loader_uuid);
     471         [ #  # ]:          0 :                 if (r == -ENOENT) {
     472         [ #  # ]:          0 :                         log_debug("EFI loader partition unknown.");
     473                 :          0 :                         return 0;
     474                 :            :                 }
     475         [ #  # ]:          0 :                 if (r < 0)
     476         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to read ESP partition UUID: %m");
     477                 :            : 
     478         [ #  # ]:          0 :                 if (!sd_id128_equal(p->uuid, loader_uuid)) {
     479         [ #  # ]:          0 :                         log_debug("Partition for %s does not appear to be the partition we are booted from.", p->node);
     480                 :          0 :                         return 0;
     481                 :            :                 }
     482                 :            :         } else
     483         [ #  # ]:          0 :                 log_debug("Not an EFI boot, skipping ESP check.");
     484                 :            : 
     485                 :          0 :         return add_automount(id,
     486                 :          0 :                              p->node,
     487                 :            :                              esp_path,
     488                 :          0 :                              p->fstype,
     489                 :            :                              true,
     490                 :            :                              "umask=0077",
     491                 :            :                              "EFI System Partition Automount",
     492                 :            :                              120 * USEC_PER_SEC);
     493                 :            : }
     494                 :            : #else
     495                 :            : static int add_esp(DissectedPartition *p, bool has_xbootldr) {
     496                 :            :         return 0;
     497                 :            : }
     498                 :            : #endif
     499                 :            : 
     500                 :          0 : static int add_root_rw(DissectedPartition *p) {
     501                 :            :         const char *path;
     502                 :            :         int r;
     503                 :            : 
     504         [ #  # ]:          0 :         assert(p);
     505                 :            : 
     506         [ #  # ]:          0 :         if (in_initrd()) {
     507         [ #  # ]:          0 :                 log_debug("In initrd, not generating drop-in for systemd-remount-fs.service.");
     508                 :          0 :                 return 0;
     509                 :            :         }
     510                 :            : 
     511         [ #  # ]:          0 :         if (arg_root_rw >= 0) {
     512         [ #  # ]:          0 :                 log_debug("Parameter ro/rw specified on kernel command line, not generating drop-in for systemd-remount-fs.service.");
     513                 :          0 :                 return 0;
     514                 :            :         }
     515                 :            : 
     516         [ #  # ]:          0 :         if (!p->rw) {
     517         [ #  # ]:          0 :                 log_debug("Root partition marked read-only in GPT partition table, not generating drop-in for systemd-remount-fs.service.");
     518                 :          0 :                 return 0;
     519                 :            :         }
     520                 :            : 
     521                 :          0 :         (void) generator_enable_remount_fs_service(arg_dest);
     522                 :            : 
     523   [ #  #  #  #  :          0 :         path = strjoina(arg_dest, "/systemd-remount-fs.service.d/50-remount-rw.conf");
          #  #  #  #  #  
                #  #  # ]
     524                 :            : 
     525                 :          0 :         r = write_string_file(path,
     526                 :            :                               "# Automatically generated by systemd-gpt-generator\n\n"
     527                 :            :                               "[Service]\n"
     528                 :            :                               "Environment=SYSTEMD_REMOUNT_ROOT_RW=1\n",
     529                 :            :                               WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_NOFOLLOW|WRITE_STRING_FILE_MKDIR_0755);
     530         [ #  # ]:          0 :         if (r < 0)
     531         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to write drop-in file %s: %m", path);
     532                 :            : 
     533                 :          0 :         return 0;
     534                 :            : }
     535                 :            : 
     536                 :          0 : static int open_parent_devno(dev_t devnum, int *ret) {
     537                 :          0 :         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
     538                 :            :         const char *name, *devtype, *node;
     539                 :            :         sd_device *parent;
     540                 :            :         dev_t pn;
     541                 :            :         int fd, r;
     542                 :            : 
     543         [ #  # ]:          0 :         assert(ret);
     544                 :            : 
     545                 :          0 :         r = sd_device_new_from_devnum(&d, 'b', devnum);
     546         [ #  # ]:          0 :         if (r < 0)
     547         [ #  # ]:          0 :                 return log_debug_errno(r, "Failed to open device: %m");
     548                 :            : 
     549         [ #  # ]:          0 :         if (sd_device_get_devname(d, &name) < 0) {
     550                 :          0 :                 r = sd_device_get_syspath(d, &name);
     551         [ #  # ]:          0 :                 if (r < 0) {
     552   [ #  #  #  #  :          0 :                         log_device_debug_errno(d, r, "Device %u:%u does not have a name, ignoring: %m", major(devnum), minor(devnum));
                   #  # ]
     553                 :          0 :                         return 0;
     554                 :            :                 }
     555                 :            :         }
     556                 :            : 
     557                 :          0 :         r = sd_device_get_parent(d, &parent);
     558         [ #  # ]:          0 :         if (r < 0) {
     559   [ #  #  #  #  :          0 :                 log_device_debug_errno(d, r, "Not a partitioned device, ignoring: %m");
                   #  # ]
     560                 :          0 :                 return 0;
     561                 :            :         }
     562                 :            : 
     563                 :            :         /* Does it have a devtype? */
     564                 :          0 :         r = sd_device_get_devtype(parent, &devtype);
     565         [ #  # ]:          0 :         if (r < 0) {
     566   [ #  #  #  #  :          0 :                 log_device_debug_errno(parent, r, "Parent doesn't have a device type, ignoring: %m");
                   #  # ]
     567                 :          0 :                 return 0;
     568                 :            :         }
     569                 :            : 
     570                 :            :         /* Is this a disk or a partition? We only care for disks... */
     571         [ #  # ]:          0 :         if (!streq(devtype, "disk")) {
     572   [ #  #  #  #  :          0 :                 log_device_debug(parent, "Parent isn't a raw disk, ignoring.");
                   #  # ]
     573                 :          0 :                 return 0;
     574                 :            :         }
     575                 :            : 
     576                 :            :         /* Does it have a device node? */
     577                 :          0 :         r = sd_device_get_devname(parent, &node);
     578         [ #  # ]:          0 :         if (r < 0) {
     579   [ #  #  #  #  :          0 :                 log_device_debug_errno(parent, r, "Parent device does not have device node, ignoring: %m");
                   #  # ]
     580                 :          0 :                 return 0;
     581                 :            :         }
     582                 :            : 
     583   [ #  #  #  #  :          0 :         log_device_debug(d, "Root device %s.", node);
                   #  # ]
     584                 :            : 
     585                 :          0 :         r = sd_device_get_devnum(parent, &pn);
     586         [ #  # ]:          0 :         if (r < 0) {
     587   [ #  #  #  #  :          0 :                 log_device_debug_errno(parent, r, "Parent device is not a proper block device, ignoring: %m");
                   #  # ]
     588                 :          0 :                 return 0;
     589                 :            :         }
     590                 :            : 
     591                 :          0 :         fd = open(node, O_RDONLY|O_CLOEXEC|O_NOCTTY);
     592         [ #  # ]:          0 :         if (fd < 0)
     593         [ #  # ]:          0 :                 return log_error_errno(errno, "Failed to open %s: %m", node);
     594                 :            : 
     595                 :          0 :         *ret = fd;
     596                 :          0 :         return 1;
     597                 :            : }
     598                 :            : 
     599                 :          0 : static int enumerate_partitions(dev_t devnum) {
     600                 :          0 :         _cleanup_close_ int fd = -1;
     601                 :          0 :         _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
     602                 :            :         int r, k;
     603                 :            : 
     604                 :          0 :         r = open_parent_devno(devnum, &fd);
     605         [ #  # ]:          0 :         if (r <= 0)
     606                 :          0 :                 return r;
     607                 :            : 
     608                 :          0 :         r = dissect_image(fd, NULL, 0, DISSECT_IMAGE_GPT_ONLY|DISSECT_IMAGE_NO_UDEV, &m);
     609         [ #  # ]:          0 :         if (r == -ENOPKG) {
     610         [ #  # ]:          0 :                 log_debug_errno(r, "No suitable partition table found, ignoring.");
     611                 :          0 :                 return 0;
     612                 :            :         }
     613         [ #  # ]:          0 :         if (r < 0)
     614         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to dissect: %m");
     615                 :            : 
     616         [ #  # ]:          0 :         if (m->partitions[PARTITION_SWAP].found) {
     617                 :          0 :                 k = add_swap(m->partitions[PARTITION_SWAP].node);
     618         [ #  # ]:          0 :                 if (k < 0)
     619                 :          0 :                         r = k;
     620                 :            :         }
     621                 :            : 
     622         [ #  # ]:          0 :         if (m->partitions[PARTITION_XBOOTLDR].found) {
     623                 :          0 :                 k = add_xbootldr(m->partitions + PARTITION_XBOOTLDR);
     624         [ #  # ]:          0 :                 if (k < 0)
     625                 :          0 :                         r = k;
     626                 :            :         }
     627                 :            : 
     628         [ #  # ]:          0 :         if (m->partitions[PARTITION_ESP].found) {
     629                 :          0 :                 k = add_esp(m->partitions + PARTITION_ESP, m->partitions[PARTITION_XBOOTLDR].found);
     630         [ #  # ]:          0 :                 if (k < 0)
     631                 :          0 :                         r = k;
     632                 :            :         }
     633                 :            : 
     634         [ #  # ]:          0 :         if (m->partitions[PARTITION_HOME].found) {
     635                 :          0 :                 k = add_partition_mount(m->partitions + PARTITION_HOME, "home", "/home", "Home Partition");
     636         [ #  # ]:          0 :                 if (k < 0)
     637                 :          0 :                         r = k;
     638                 :            :         }
     639                 :            : 
     640         [ #  # ]:          0 :         if (m->partitions[PARTITION_SRV].found) {
     641                 :          0 :                 k = add_partition_mount(m->partitions + PARTITION_SRV, "srv", "/srv", "Server Data Partition");
     642         [ #  # ]:          0 :                 if (k < 0)
     643                 :          0 :                         r = k;
     644                 :            :         }
     645                 :            : 
     646         [ #  # ]:          0 :         if (m->partitions[PARTITION_ROOT].found) {
     647                 :          0 :                 k = add_root_rw(m->partitions + PARTITION_ROOT);
     648         [ #  # ]:          0 :                 if (k < 0)
     649                 :          0 :                         r = k;
     650                 :            :         }
     651                 :            : 
     652                 :          0 :         return r;
     653                 :            : }
     654                 :            : 
     655                 :          0 : static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
     656                 :            :         int r;
     657                 :            : 
     658         [ #  # ]:          0 :         assert(key);
     659                 :            : 
     660   [ #  #  #  # ]:          0 :         if (proc_cmdline_key_streq(key, "systemd.gpt_auto") ||
     661                 :          0 :             proc_cmdline_key_streq(key, "rd.systemd.gpt_auto")) {
     662                 :            : 
     663         [ #  # ]:          0 :                 r = value ? parse_boolean(value) : 1;
     664         [ #  # ]:          0 :                 if (r < 0)
     665         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to parse gpt-auto switch \"%s\", ignoring: %m", value);
     666                 :            :                 else
     667                 :          0 :                         arg_enabled = r;
     668                 :            : 
     669         [ #  # ]:          0 :         } else if (proc_cmdline_key_streq(key, "root")) {
     670                 :            : 
     671         [ #  # ]:          0 :                 if (proc_cmdline_value_missing(key, value))
     672                 :          0 :                         return 0;
     673                 :            : 
     674                 :            :                 /* Disable root disk logic if there's a root= value
     675                 :            :                  * specified (unless it happens to be "gpt-auto") */
     676                 :            : 
     677                 :          0 :                 arg_root_enabled = streq(value, "gpt-auto");
     678                 :            : 
     679         [ #  # ]:          0 :         } else if (proc_cmdline_key_streq(key, "roothash")) {
     680                 :            : 
     681         [ #  # ]:          0 :                 if (proc_cmdline_value_missing(key, value))
     682                 :          0 :                         return 0;
     683                 :            : 
     684                 :            :                 /* Disable root disk logic if there's roothash= defined (i.e. verity enabled) */
     685                 :            : 
     686                 :          0 :                 arg_root_enabled = false;
     687                 :            : 
     688   [ #  #  #  # ]:          0 :         } else if (proc_cmdline_key_streq(key, "rw") && !value)
     689                 :          0 :                 arg_root_rw = true;
     690   [ #  #  #  # ]:          0 :         else if (proc_cmdline_key_streq(key, "ro") && !value)
     691                 :          0 :                 arg_root_rw = false;
     692                 :            : 
     693                 :          0 :         return 0;
     694                 :            : }
     695                 :            : 
     696                 :            : #if ENABLE_EFI
     697                 :          0 : static int add_root_cryptsetup(void) {
     698                 :            : 
     699                 :            :         /* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which
     700                 :            :          * sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */
     701                 :            : 
     702                 :          0 :         return add_cryptsetup("root", "/dev/gpt-auto-root-luks", true, false, NULL);
     703                 :            : }
     704                 :            : #endif
     705                 :            : 
     706                 :          0 : static int add_root_mount(void) {
     707                 :            : 
     708                 :            : #if ENABLE_EFI
     709                 :            :         int r;
     710                 :            : 
     711         [ #  # ]:          0 :         if (!is_efi_boot()) {
     712         [ #  # ]:          0 :                 log_debug("Not a EFI boot, not creating root mount.");
     713                 :          0 :                 return 0;
     714                 :            :         }
     715                 :            : 
     716                 :          0 :         r = efi_loader_get_device_part_uuid(NULL);
     717         [ #  # ]:          0 :         if (r == -ENOENT) {
     718         [ #  # ]:          0 :                 log_debug("EFI loader partition unknown, exiting.");
     719                 :          0 :                 return 0;
     720         [ #  # ]:          0 :         } else if (r < 0)
     721         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to read ESP partition UUID: %m");
     722                 :            : 
     723                 :            :         /* OK, we have an ESP partition, this is fantastic, so let's
     724                 :            :          * wait for a root device to show up. A udev rule will create
     725                 :            :          * the link for us under the right name. */
     726                 :            : 
     727         [ #  # ]:          0 :         if (in_initrd()) {
     728                 :          0 :                 r = generator_write_initrd_root_device_deps(arg_dest, "/dev/gpt-auto-root");
     729         [ #  # ]:          0 :                 if (r < 0)
     730                 :          0 :                         return 0;
     731                 :            : 
     732                 :          0 :                 r = add_root_cryptsetup();
     733         [ #  # ]:          0 :                 if (r < 0)
     734                 :          0 :                         return r;
     735                 :            :         }
     736                 :            : 
     737                 :            :         /* Note that we do not need to enable systemd-remount-fs.service here. If
     738                 :            :          * /etc/fstab exists, systemd-fstab-generator will pull it in for us. */
     739                 :            : 
     740   [ #  #  #  # ]:          0 :         return add_mount(
     741                 :            :                         "root",
     742                 :            :                         "/dev/gpt-auto-root",
     743                 :          0 :                         in_initrd() ? "/sysroot" : "/",
     744                 :            :                         NULL,
     745                 :            :                         arg_root_rw > 0,
     746                 :            :                         NULL,
     747                 :            :                         "Root Partition",
     748                 :          0 :                         in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
     749                 :            : #else
     750                 :            :         return 0;
     751                 :            : #endif
     752                 :            : }
     753                 :            : 
     754                 :          0 : static int add_mounts(void) {
     755                 :            :         dev_t devno;
     756                 :            :         int r;
     757                 :            : 
     758                 :          0 :         r = get_block_device_harder("/", &devno);
     759         [ #  # ]:          0 :         if (r < 0)
     760         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to determine block device of root file system: %m");
     761         [ #  # ]:          0 :         if (r == 0) {
     762                 :          0 :                 r = get_block_device_harder("/usr", &devno);
     763         [ #  # ]:          0 :                 if (r < 0)
     764         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
     765         [ #  # ]:          0 :                 if (r == 0) {
     766         [ #  # ]:          0 :                         _cleanup_free_ char *p = NULL;
     767                 :            :                         mode_t m;
     768                 :            : 
     769                 :            :                         /* If the root mount has been replaced by some form of volatile file system (overlayfs), the
     770                 :            :                          * original root block device node is symlinked in /run/systemd/volatile-root. Let's read that
     771                 :            :                          * here. */
     772                 :          0 :                         r = readlink_malloc("/run/systemd/volatile-root", &p);
     773         [ #  # ]:          0 :                         if (r == -ENOENT) {
     774         [ #  # ]:          0 :                                 log_debug("Neither root nor /usr file system are on a (single) block device.");
     775                 :          0 :                                 return 0;
     776                 :            :                         }
     777         [ #  # ]:          0 :                         if (r < 0)
     778         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
     779                 :            : 
     780                 :          0 :                         r = device_path_parse_major_minor(p, &m, &devno);
     781         [ #  # ]:          0 :                         if (r < 0)
     782         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to parse major/minor device node: %m");
     783         [ #  # ]:          0 :                         if (!S_ISBLK(m))
     784         [ #  # ]:          0 :                                 return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Volatile root device is of wrong type.");
     785                 :            :                 }
     786                 :            :         }
     787                 :            : 
     788                 :          0 :         return enumerate_partitions(devno);
     789                 :            : }
     790                 :            : 
     791                 :          0 : static int run(const char *dest, const char *dest_early, const char *dest_late) {
     792                 :            :         int r, k;
     793                 :            : 
     794         [ #  # ]:          0 :         assert_se(arg_dest = dest_late);
     795                 :            : 
     796         [ #  # ]:          0 :         if (detect_container() > 0) {
     797         [ #  # ]:          0 :                 log_debug("In a container, exiting.");
     798                 :          0 :                 return 0;
     799                 :            :         }
     800                 :            : 
     801                 :          0 :         r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
     802         [ #  # ]:          0 :         if (r < 0)
     803         [ #  # ]:          0 :                 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
     804                 :            : 
     805         [ #  # ]:          0 :         if (!arg_enabled) {
     806         [ #  # ]:          0 :                 log_debug("Disabled, exiting.");
     807                 :          0 :                 return 0;
     808                 :            :         }
     809                 :            : 
     810         [ #  # ]:          0 :         if (arg_root_enabled)
     811                 :          0 :                 r = add_root_mount();
     812                 :            : 
     813         [ #  # ]:          0 :         if (!in_initrd()) {
     814                 :          0 :                 k = add_mounts();
     815         [ #  # ]:          0 :                 if (r >= 0)
     816                 :          0 :                         r = k;
     817                 :            :         }
     818                 :            : 
     819                 :          0 :         return r;
     820                 :            : }
     821                 :            : 
     822   [ #  #  #  #  :          0 : DEFINE_MAIN_GENERATOR_FUNCTION(run);
          #  #  #  #  #  
                #  #  # ]

Generated by: LCOV version 1.14