]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #14398 from poettering/mount-prep
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 4 Feb 2020 14:36:17 +0000 (15:36 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 4 Feb 2020 15:28:51 +0000 (16:28 +0100)
1  2 
TODO
src/core/unit.c
src/shared/generator.c
units/meson.build

diff --combined TODO
index a9902ddff2d5ad98b8858a7fdd3066811606df46,ed5e048d9a09e39e58c174171af0e3426c7bbcfd..4a6c8d3512d4e6e8600552fd804b7bb3e9687b77
--- 1/TODO
--- 2/TODO
+++ b/TODO
@@@ -19,106 -19,20 +19,109 @@@ Janitorial Clean-ups
  
  Features:
  
 -* when dissecting images, warn about unrecognized partition flags
 +* cryptsetup/homed: also support FIDO2 HMAC password logic for unlocking
 +  devices. (see: https://github.com/mjec/fido2-hmac-secret)
 +
 +* systemd-gpt-auto should probably set x-systemd.growfs on the mounts it
 +  creates
 +
 +* homed/userdb: distuingish passwords and recovery keys in the records, since
 +  we probably want to use different PBKDF algorithms/settings for them:
 +  passwords have low entropy but recovery keys should have good entropy key
 +  hence we can make them quicker to work.
 +
 +* bootctl:
 +  - teach it to prepare an ESP wholesale, i.e. with mkfs.vfat invocation
 +  - teach it to copy in unified kernel images and maybe type #1 boot loader spec entries from host
 +  - make it operate on loopback files, dissecting enough to find ESP to operate on
 +
 +* by default, in systemd --user service bump the OOMAdjust to 100, as privs
 +  allow so that systemd survives
  
  * honour specifiers in unit files that resolve to some very basic
    /etc/os-release data, such as ID, VERSION_ID, BUILD_ID, VARIANT_ID.
  
 +* cryptsetup: allow encoding key directly in /etc/crypttab, maybe with a
 +  "base64:" prefix. Useful in particular for pkcs11 mode.
 +
+ * cryptsetup: reimplement the mkswap/mke2fs in cryptsetup-generator to use
+   systemd-makefs.service instead.
  * socket units: allow creating a udev monitor socket with ListenDevices= or so,
    with matches, then actviate app thorugh that passing socket oveer
  
 +* unify on openssl:
 +  - port sd_id128_get_machine_app_specific() over from khash
 +  - port resolved over from libgcrypt (DNSSEC code)
 +  - port journald + fsprg over from libgcrypt
 +  - port importd over from libgcrypt
 +  - when that's done: kill khash.c
 +  - when that's done: kill gnutls support in resolved
 +
  * kill zenata, all hail weblate?
  
 -* move discoverable partitions spec into markdown and our tree
 +* when we resize disks (homed?) always round up to 4K sectors, not 512K
 +
 +* add growvol and makevol options for /etc/crypttab, similar to
 +  x-systemd.growfs and x-systemd-makefs.
 +
 +* hook up the TPM to /etc/crypttab, with a new option that is similar to the
 +  new PKCS#11 option in crypttab, and allows unlocking a LUKS volume via a key
 +  unsealed from the TPM. Optionally, if TPM is not available fall back to
 +  TPM-less mode, and set up linear DM mapping instead (inspired by kpartx), so
 +  that the device paths stay the same, regardless if crypto is used or not.
 +
 +* systemd-repart: by default generate minimized partition tables (i.e. tables
 +  that only covere the space actually used, excluding any free space at the
 +  end), in order to maximize dd'ability. Requires libfdisk work, see
 +  https://github.com/karelzak/util-linux/issues/907
 +
 +* systemd-repart: optionally, allow specifiying a path to initialize new
 +  partitions from, i.e. an fs image file or a source device node. This would
 +  then turn systemd-repart into a simple installer: with a few .repart files
 +  you could replicate the host system on another device. a full installer would
 +  then be: "systemd-repart /dev/sda && bootctl install /dev/sda &&
 +  systemd-firstboot --image= …"
 +
 +* systemd-repart: MBR partition table support. Care needs to be taken regarding
 +  Type=, so that partition definitions can sanely apply to both the GPT and the
 +  MBR case. Idea: accept syntax "Type=gpt:home mbr:0x83" for setting the types
 +  for the two partition types explicitly. And provide an internal mapping so
 +  that "Type=linux-generic" maps to the right types for both partition tables
 +  automatically.
 +
 +* systemd-repart: allow sizing partitions as factor of available RAM, so that
 +  we can reasonably size swap partitions for hibernation.
 +
 +* systemd-repart: allow running mkfs before making partitions pop up +
 +  encryption via LUKS to allow booting into an empty root with only /usr mounted in
 +
 +* systemd-repart: allow managing the gpt read-only partition flag + auto-mount flag
 +
 +* systemd-repart: allow disabling growing of specific partitions, or making
 +  them (think ESP: we don't ever want to grow it, since we cannot resize vfat)
 +
 +* systemd-repart: add specifier expansion, add especifier that refers to root
 +  device node of current system, /usr device node, and matching verity, so that
 +  an installer can be made a "copy" installer of the booted OS
 +
 +* systemd-repart: make it a static checker during early boot for existence and
 +  absence of other partitions for trusted boot environments
 +
 +* systemd-repart: when no configuration is found, exit early do not check
 +  partition table, so that it is safe to run in the initrd on any system
 +
 +* systemd-repart: allow config of partition uuid
 +
 +* userdb: allow username prefix searches in varlink API
 +
 +* userdb: allow existence checks
 +
 +* pid: activation by journal search expression
 +
 +* when switching root from initrd to host, set the machine_id env var so that
 +  if the host has no machine ID set yet we continue to use the random one the
 +  initrd had set.
  
  * sd-event: add native support for P_ALL waitid() watching, then move PID 1 to
    it fo reaping assigned but unknown children. This needs to some special care
    right) become genuine first class citizens, and we gain automatic, sane JSON
    output for them.
  
 -* dissector: invoke fsck on the file systems we encounter, after all ext4 is
 -  still pretty popular (and we mount the ESP too with it after all, which is
 -  fat)
 -
  * systemd-firstboot: teach it dissector magic, so that you can point it to some
    disk image and it will just set everything in it all behind the scenes.
  
    user@.service, which returns the XDG_RUNTIME_DIR value, and make this
    behaviour selectable via pam module option.
  
 +* homed:
 +  - when user tries to log into record signed by unrecognized key, automatically add key to our chain after polkit auth
 +  - hook up machined/nspawn users with a varlink user query interface
 +  - rollback when resize fails mid-operation
 +  - GNOME's side for forget key on suspend (requires rework so that lock screen runs outside of uid)
 +  - resize on login?
 +  - fstrim on logout?
 +  - shrink fs on logout?
 +  - update LUKS password on login if we find there's a password that unlocks the JSON record but not the LUKS device.
 +  - create on activate?
 +  - properties: icon url?, preferred session type?, administrator bool (which translates to 'wheel' membership)?, address?, telephone?, vcard?, samba stuff?, parental controls?
 +  - communicate clearly when usb stick is safe to remove. probably involves
 +    beefing up logind to make pam session close hook synchronous and wait until
 +    systemd --user is shut down.
 +  - logind: maybe keep a "busy fd" as long as there's a non-released session around or the user@.service
 +  - maybe make automatic, read-only, time-based reflink-copies of LUKS disk images (think: time machine)
 +  - distuingish destroy / remove (i.e. currently we can unregister a user, unregister+remove their home directory, but not just remove their home directory)
 +  - in systemd's PAMName= logic: query passwords with ssh-askpassword, so that we can make "loginctl set-linger" mode work
 +  - fingerprint authentication, pattern authentication, …
 +  - make sure "classic" user records can also be managed by homed
 +  - description field for groups
 +  - make size of $XDG_RUNTIME_DIR configurable in user record
 +  - reuse pwquality magic in firstboot
 +  - query password from kernel keyring first
 +  - update even if record is "absent"
 +  - add a "access mode" + "fstype" field to the "status" section of json identity records reflecting the actually used access mode and fstype, even on non-luks backends
 +  - move acct mgmt stuff from pam_systemd_home to pam_systemd?
 +  - when "homectl --pkcs11-token-uri=" is used, synthesize ssh-authorized-keys records for all keys we have private keys on the stick for
 +  - make slice for users configurable (requires logind rework)
 +  - logind: populate auto-login list bus property from PKCS#11 token
 +  - when determining state of a LUKS home directory, check DM suspended sysfs file
 +
  * introduce a new per-process uuid, similar to the boot id, the machine id, the
    invocation id, that is derived from process creds, specifically a hashed
    combination of AT_RANDOM + getpid() + the starttime from
  
  * introduce per-unit (i.e. per-slice, per-service) journal log size limits.
  
 -* optionally, if a per-partition GPT flag is set for the root/home/… partitions
 -  format the partition on next boot and unset the flag, in order to implement
 -  factory reset. also, add a second flag that simply indicates whether such a
 -  scheme is supported. then, add a tool (or maybe beef up systemd-dissect) to
 -  show state of these flags, and optionally trigger such a factory reset on
 -  next boot by setting the flag.
 -
  * sd-boot: automatically load EFI modules from some drop-in dir, so that people
    can add in file system drivers and such
  
    yogas can be recognized as "convertible" too, even if they predate the DMI
    "convertible" form factor
  
 -* Maybe add a small tool invoked early at boot, that adds in or resizes
 -  partitions automatically, to be used when the media used is actually larger
 -  than the image written onto it is.
 -
  * Maybe add PrivatePIDs= as new unit setting, and do minimal PID namespacing
    after all. Be strict however, only support the equivalent of nspawn's
    --as-pid2 switch, and sanely proxy sd_notify() messages dropping stuff such
    "systemd-gdb" for attaching to the start-up of any system service in its
    natural habitat.
  
 -* maybe add gpt-partition-based user management: each user gets his own
 -  LUKS-encrypted GPT partition with a new GPT type. A small nss module
 -  enumerates users via udev partition enumeration. UIDs are assigned in a fixed
 -  way: the partition index is added as offset to some fixed base uid. User name
 -  is stored in GPT partition name. A PAM module authenticates the user via the
 -  LUKS partition password. Benefits: strong per-user security, compatibility
 -  with stateless/read-only/verity-enabled root. (other idea: do this based on
 -  loopback files in /home, without GPT involvement)
 -
  * gpt-auto logic: related to the above, maybe support a "secondary" root
    partition, that is mounted to / and is writable, and where the actual root's
    /usr is mounted into.
    - journald: when we drop syslog messages because the syslog socket is
      full, make sure to write how many messages are lost as first thing
      to syslog when it works again.
 -  - change systemd-journal-flush into a service that stays around during
 -    boot, and causes the journal to be moved back to /run on shutdown,
 -    so that we do not keep /var busy. This needs to happen synchronously,
 -    hence doing this via signals is not going to work.
 -  - optionally support running journald from the command line for testing purposes in external projects
    - journald: allow per-priority and per-service retention times when rotating/vacuuming
    - journald: make use of uid-range.h to managed uid ranges to split
      journals in.
diff --combined src/core/unit.c
index 6b97c35ffa1ebd639ab9dd05d644bc26b8baeb53,9e95857d9abd32851ce090dfdb2839e6d1583dc5..3f616e7acf1c9a288cce0b30efe4484ff6d8bb7b
@@@ -1059,33 -1059,13 +1059,33 @@@ int unit_add_exec_dependencies(Unit *u
              !IN_SET(c->std_error,
                      EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE,
                      EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE,
 -                    EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE))
 +                    EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE) &&
 +            !c->log_namespace)
                  return 0;
  
 -        /* If syslog or kernel logging is requested, make sure our own
 -         * logging daemon is run first. */
 +        /* If syslog or kernel logging is requested (or log namespacing is), make sure our own logging daemon
 +         * is run first. */
 +
 +        if (c->log_namespace) {
 +                _cleanup_free_ char *socket_unit = NULL, *varlink_socket_unit = NULL;
 +
 +                r = unit_name_build_from_type("systemd-journald", c->log_namespace, UNIT_SOCKET, &socket_unit);
 +                if (r < 0)
 +                        return r;
 +
 +                r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, socket_unit, true, UNIT_DEPENDENCY_FILE);
 +                if (r < 0)
 +                        return r;
  
 -        r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, true, UNIT_DEPENDENCY_FILE);
 +                r = unit_name_build_from_type("systemd-journald-varlink", c->log_namespace, UNIT_SOCKET, &varlink_socket_unit);
 +                if (r < 0)
 +                        return r;
 +
 +                r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, varlink_socket_unit, true, UNIT_DEPENDENCY_FILE);
 +                if (r < 0)
 +                        return r;
 +        } else
 +                r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, true, UNIT_DEPENDENCY_FILE);
          if (r < 0)
                  return r;
  
@@@ -3866,8 -3846,8 +3866,8 @@@ int unit_deserialize_skip(FILE *f) 
  }
  
  int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
-         Unit *device;
          _cleanup_free_ char *e = NULL;
+         Unit *device;
          int r;
  
          assert(u);
          if (!is_device_path(what))
                  return 0;
  
-         /* When device units aren't supported (such as in a
-          * container), don't create dependencies on them. */
+         /* When device units aren't supported (such as in a container), don't create dependencies on them. */
          if (!unit_type_supported(UNIT_DEVICE))
                  return 0;
  
                                           device, true, mask);
  }
  
+ int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask) {
+         _cleanup_free_ char *escaped = NULL, *target = NULL;
+         int r;
+         assert(u);
+         if (isempty(what))
+                 return 0;
+         if (!path_startswith(what, "/dev/"))
+                 return 0;
+         /* If we don't support devices, then also don't bother with blockdev@.target */
+         if (!unit_type_supported(UNIT_DEVICE))
+                 return 0;
+         r = unit_name_path_escape(what, &escaped);
+         if (r < 0)
+                 return r;
+         r = unit_name_build("blockdev", escaped, ".target", &target);
+         if (r < 0)
+                 return r;
+         return unit_add_dependency_by_name(u, UNIT_AFTER, target, true, mask);
+ }
  int unit_coldplug(Unit *u) {
          int r = 0, q;
          char **i;
@@@ -4307,9 -4313,6 +4333,9 @@@ int unit_patch_contexts(Unit *u) 
                  if (ec->protect_kernel_logs)
                          ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYSLOG);
  
 +                if (ec->protect_clock)
 +                        ec->capability_bounding_set &= ~((UINT64_C(1) << CAP_SYS_TIME) | (UINT64_C(1) << CAP_WAKE_ALARM));
 +
                  if (ec->dynamic_user) {
                          if (!ec->user) {
                                  r = user_from_unit_name(u, &ec->user);
                          if (r < 0)
                                  return r;
                  }
 +
 +                if (ec->protect_clock) {
 +                        r = cgroup_add_device_allow(cc, "char-rtc", "r");
 +                        if (r < 0)
 +                                return r;
 +                }
          }
  
          return 0;
diff --combined src/shared/generator.c
index 1cf5887a60de1516bac1df3322d3abe8f1b4c5c3,48667c93a21e9bacf3d6aefa39f733aee8bffc5e..acdd0096f1419391bae148a8a041928b4a8cd822
@@@ -493,21 -493,15 +493,21 @@@ int generator_hook_up_growfs
                  "BindsTo=%%i.mount\n"
                  "Conflicts=shutdown.target\n"
                  "After=%%i.mount\n"
 -                "Before=shutdown.target %s\n"
 +                "Before=shutdown.target %s\n",
 +                program_invocation_short_name,
 +                target);
 +
 +        if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */
 +                fprintf(f,
 +                        "After=systemd-remount-fs.service\n");
 +
 +        fprintf(f,
                  "\n"
                  "[Service]\n"
                  "Type=oneshot\n"
                  "RemainAfterExit=yes\n"
                  "ExecStart="SYSTEMD_GROWFS_PATH " %s\n"
                  "TimeoutSec=0\n",
 -                program_invocation_short_name,
 -                target,
                  escaped);
  
          return generator_add_symlink(dir, where_unit, "wants", unit);
@@@ -519,6 -513,103 +519,103 @@@ int generator_enable_remount_fs_service
                                       SYSTEM_DATA_UNIT_PATH "/" SPECIAL_REMOUNT_FS_SERVICE);
  }
  
+ int generator_write_blockdev_dependency(
+                 FILE *f,
+                 const char *what) {
+         _cleanup_free_ char *escaped = NULL;
+         int r;
+         assert(f);
+         assert(what);
+         if (!path_startswith(what, "/dev/"))
+                 return 0;
+         r = unit_name_path_escape(what, &escaped);
+         if (r < 0)
+                 return log_error_errno(r, "Failed to escape device node path %s: %m", what);
+         fprintf(f,
+                 "After=blockdev@%s.target\n",
+                 escaped);
+         return 0;
+ }
+ int generator_write_cryptsetup_unit_section(
+                 FILE *f,
+                 const char *source) {
+         assert(f);
+         fprintf(f,
+                 "[Unit]\n"
+                 "Description=Cryptography Setup for %%I\n"
+                 "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n");
+         if (source)
+                 fprintf(f, "SourcePath=%s\n", source);
+         fprintf(f,
+                 "DefaultDependencies=no\n"
+                 "IgnoreOnIsolate=true\n"
+                 "After=cryptsetup-pre.target\n"
+                 "Before=blockdev@dev-mapper-%%i.target\n"
+                 "Wants=blockdev@dev-mapper-%%i.target\n");
+         return 0;
+ }
+ int generator_write_cryptsetup_service_section(
+                 FILE *f,
+                 const char *name,
+                 const char *what,
+                 const char *password,
+                 const char *options) {
+         _cleanup_free_ char *name_escaped = NULL, *what_escaped = NULL, *password_escaped = NULL, *options_escaped = NULL;
+         assert(f);
+         assert(name);
+         assert(what);
+         name_escaped = specifier_escape(name);
+         if (!name_escaped)
+                 return log_oom();
+         what_escaped = specifier_escape(what);
+         if (!what_escaped)
+                 return log_oom();
+         if (password) {
+                 password_escaped = specifier_escape(password);
+                 if (!password_escaped)
+                         return log_oom();
+         }
+         if (options) {
+                 options_escaped = specifier_escape(options);
+                 if (!options_escaped)
+                         return log_oom();
+         }
+         fprintf(f,
+                 "\n"
+                 "[Service]\n"
+                 "Type=oneshot\n"
+                 "RemainAfterExit=yes\n"
+                 "TimeoutSec=0\n"          /* The binary handles timeouts on its own */
+                 "KeyringMode=shared\n"    /* Make sure we can share cached keys among instances */
+                 "OOMScoreAdjust=500\n"    /* Unlocking can allocate a lot of memory if Argon2 is used */
+                 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
+                 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
+                 name_escaped, what_escaped, strempty(password_escaped), strempty(options_escaped),
+                 name_escaped);
+         return 0;
+ }
  void log_setup_generator(void) {
          log_set_prohibit_ipc(true);
          log_setup_service();
diff --combined units/meson.build
index 0dc85ac64a3c88cb28a19429b610d3af89bd130c,27742044c5ff2f7151e3e32a1197cff40260b320..f3145a1099ec05a67b6a6a9d48ad1ed5f7a255c4
@@@ -2,6 -2,7 +2,7 @@@
  
  units = [
          ['basic.target',                        ''],
+         ['blockdev@.target',                    ''],
          ['bluetooth.target',                    ''],
          ['boot-complete.target',                ''],
          ['cryptsetup-pre.target',               'HAVE_LIBCRYPTSETUP'],
          ['systemd-kexec.service',               ''],
          ['systemd-machine-id-commit.service',   '',
           'sysinit.target.wants/'],
 +        ['systemd-journald@.socket',            ''],
 +        ['systemd-journald-varlink@.socket',    ''],
          ['systemd-networkd.socket',             'ENABLE_NETWORKD'],
          ['systemd-poweroff.service',            ''],
          ['systemd-reboot.service',              ''],
@@@ -182,7 -181,6 +183,7 @@@ in_units = 
          ['systemd-journal-upload.service',       'ENABLE_REMOTE HAVE_LIBCURL'],
          ['systemd-journald.service',             '',
           'sysinit.target.wants/'],
 +        ['systemd-journald@.service',            ''],
          ['systemd-localed.service',              'ENABLE_LOCALED',
           'dbus-org.freedesktop.locale1.service'],
          ['systemd-logind.service',               'ENABLE_LOGIND',
          ['systemd-portabled.service',            'ENABLE_PORTABLED',
           'dbus-org.freedesktop.portable1.service'],
          ['systemd-userdbd.service',              'ENABLE_USERDB'],
 +        ['systemd-homed.service',                'ENABLE_HOMED',
 +         'multi-user.target.wants/ dbus-org.freedesktop.home1.service'],
          ['systemd-quotacheck.service',           'ENABLE_QUOTACHECK'],
          ['systemd-random-seed.service',          'ENABLE_RANDOMSEED',
           'sysinit.target.wants/'],
           'multi-user.target.wants/'],
          ['systemd-vconsole-setup.service',       'ENABLE_VCONSOLE'],
          ['systemd-volatile-root.service',        ''],
 +        ['systemd-repart.service',               'ENABLE_REPART',
 +         'sysinit.target.wants/ initrd-root-fs.target.wants/'],
          ['user-runtime-dir@.service',            ''],
          ['user@.service',                        ''],
  ]