[systemd-commits] 10 commits - Makefile.am TODO man/sd_id128_to_string.xml man/systemd.unit.xml src/core src/cryptsetup src/libsystemd-id128 src/nspawn src/nss-myhostname src/shared src/systemd src/test units/.gitignore units/systemd-nspawn at .service.in

Lennart Poettering lennart at kemper.freedesktop.org
Tue Apr 30 04:36:11 PDT 2013


 Makefile.am                           |    4 +
 TODO                                  |   81 +++++++++++-----------------------
 man/sd_id128_to_string.xml            |   17 ++++---
 man/systemd.unit.xml                  |   74 +++++++------------------------
 src/core/load-dropin.c                |   40 ++++++++++------
 src/core/machine-id-setup.c           |   30 +++++++-----
 src/core/unit.c                       |   35 ++++++++------
 src/cryptsetup/cryptsetup-generator.c |   25 ++++++++--
 src/cryptsetup/cryptsetup.c           |   18 +++++--
 src/libsystemd-id128/sd-id128.c       |   61 ++++++++++++++++---------
 src/nspawn/nspawn.c                   |   23 +++++++--
 src/nss-myhostname/Makefile           |    1 
 src/shared/cgroup-util.c              |   62 ++++++++++++++++++++------
 src/shared/cgroup-util.h              |   15 ++++++
 src/shared/util.c                     |   41 +++++++++++++++++
 src/shared/util.h                     |    2 
 src/systemd/sd-bus.h                  |    2 
 src/systemd/sd-id128.h                |    2 
 src/test/test-id128.c                 |   27 ++++++++++-
 units/.gitignore                      |    1 
 units/systemd-nspawn at .service.in      |   18 +++++++
 21 files changed, 368 insertions(+), 211 deletions(-)

New commits:
commit 675aae254e37f2c4eeb86a2b944eeb660ad682b3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 30 08:35:51 2013 -0300

    update TODO

diff --git a/TODO b/TODO
index eedabd8..052ec13 100644
--- a/TODO
+++ b/TODO
@@ -26,8 +26,6 @@ Fedora 19:
 
 Features:
 
-* add nspawn at .service
-
 * investigate endianess issues of UUID vs. GUID
 
 * see if we can fix https://bugs.freedesktop.org/show_bug.cgi?id=63672

commit 05947befcec9afb83b9ce48d613ff372c63e2ed1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 21:11:37 2013 -0300

    units: add an easy-to-use unit template file systemd-nspawn at .service for running containers as system services

diff --git a/Makefile.am b/Makefile.am
index ff70223..9e0f5fb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -442,7 +442,8 @@ nodist_systemunit_DATA = \
 	units/initrd-parse-etc.service \
 	units/initrd-cleanup.service \
 	units/initrd-udevadm-cleanup-db.service \
-	units/initrd-switch-root.service
+	units/initrd-switch-root.service \
+	units/systemd-nspawn at .service
 
 dist_userunit_DATA = \
 	units/user/default.target \
@@ -489,6 +490,7 @@ EXTRA_DIST += \
 	units/initrd-cleanup.service.in \
 	units/initrd-udevadm-cleanup-db.service.in \
 	units/initrd-switch-root.service.in \
+	units/systemd-nspawn at .service.in \
 	introspect.awk
 
 CLEANFILES += \
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 0a46313..d772b47 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1231,9 +1231,13 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
-        r = parse_argv(argc, argv);
-        if (r <= 0)
+        k = parse_argv(argc, argv);
+        if (k < 0)
                 goto finish;
+        else if (k == 0) {
+                r = EXIT_SUCCESS;
+                goto finish;
+        }
 
         if (arg_directory) {
                 char *p;
@@ -1321,8 +1325,8 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, newcg, false);
-        if (r <= 0 && r != -ENOENT) {
+        k = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
+        if (k <= 0 && k != -ENOENT) {
                 log_error("Container already running.");
 
                 free(newcg);
@@ -1366,6 +1370,8 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        sd_notify(0, "READY=1");
+
         assert_se(sigemptyset(&mask) == 0);
         sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
         assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
@@ -1701,8 +1707,8 @@ int main(int argc, char *argv[]) {
                 if (saved_attr_valid)
                         tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
 
-                r = wait_for_terminate(pid, &status);
-                if (r < 0) {
+                k = wait_for_terminate(pid, &status);
+                if (k < 0) {
                         r = EXIT_FAILURE;
                         break;
                 }
diff --git a/units/.gitignore b/units/.gitignore
index d2f3eb4..606d947 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -57,3 +57,4 @@
 /initrd-parse-etc.service
 /initrd-switch-root.service
 /initrd-udevadm-cleanup-db.service
+/systemd-nspawn at .service
diff --git a/units/systemd-nspawn at .service.in b/units/systemd-nspawn at .service.in
new file mode 100644
index 0000000..c0d5886
--- /dev/null
+++ b/units/systemd-nspawn at .service.in
@@ -0,0 +1,18 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Container %i
+Documentation=man:systemd-nspawn(1)
+
+[Service]
+ExecStart=@bindir@/systemd-nspawn -bjD /var/lib/container/%i
+ControlGroup=%R/machine/%i.nspawn cpu:/
+Type=notify
+
+[Install]
+Also=multi-user.target

commit 0df2d38abfc787f40149072340d79b4f7b682a24
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 20:55:34 2013 -0300

    man: improve documentation for specifiers

diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 68f02fc..f924ef6 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -1204,7 +1204,7 @@
                       <row>
                         <entry><literal>%f</literal></entry>
                         <entry>Unescaped file name</entry>
-                        <entry>This is either the unescaped instance name (if applicable) with / prepended (if applicable), or the prefix name similarly prepended with /.</entry>
+                        <entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the prefix name similarly prepended with <filename>/</filename>.</entry>
                       </row>
                       <row>
                         <entry><literal>%c</literal></entry>
@@ -1213,13 +1213,13 @@
                       </row>
                       <row>
                         <entry><literal>%r</literal></entry>
-                        <entry>Root control group path of systemd</entry>
-                        <entry></entry>
+                        <entry>Root control group path where units are placed.</entry>
+                        <entry>For system instances this usually resolves to <filename>/system</filename>, except in containers, where the path might be prefixed with the container's root control group.</entry>
                       </row>
                       <row>
                         <entry><literal>%R</literal></entry>
-                        <entry>Parent directory of the root control group path of systemd</entry>
-                        <entry></entry>
+                        <entry>Parent directory of the control group path where units are placed.</entry>
+                        <entry>For system instances this usually resolves to <filename>/</filename>, except in containers, where this resolves to the container's root directory. This specifier is particularly useful in the <varname>ControlGroup=</varname> setting (see <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>).</entry>
                       </row>
                       <row>
                         <entry><literal>%t</literal></entry>
@@ -1244,14 +1244,7 @@
                       <row>
                         <entry><literal>%s</literal></entry>
                         <entry>User shell</entry>
-                        <entry>This is the shell of the configured
-                        user of the unit, or (if none is set) the user
-                        running the systemd instance.  If the user is
-                        <literal>root</literal> (UID equal to 0), the
-                        shell configured in account database is
-                        ignored and <filename>/bin/sh</filename> is
-                        always used.
-                        </entry>
+                        <entry>This is the shell of the configured user of the unit, or (if none is set) the user running the systemd instance.  If the user is <literal>root</literal> (UID equal to 0), the shell configured in account database is ignored and <filename>/bin/sh</filename> is always used.</entry>
                       </row>
                       <row>
                         <entry><literal>%m</literal></entry>

commit c12d1eec7fdd55d9e32e8e7443d41999809d66a2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 20:39:46 2013 -0300

    build-sys: add makefile stub link to nss-myhostname/

diff --git a/src/nss-myhostname/Makefile b/src/nss-myhostname/Makefile
new file mode 120000
index 0000000..d0b0e8e
--- /dev/null
+++ b/src/nss-myhostname/Makefile
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file

commit 00d1818bb7fbc01086cc956fdb1fcbc8fb90482b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 20:36:49 2013 -0300

    man: we need to be more careful with the unit search paths we document
    
    We generally document the suggested paths, not the paths possible in
    weird, non-standard setups. We do this in order to not confuse
    administrators/users unnecessarily and to push people to install things
    into the same directories on all distributions.
    
    We are PID 1 after all, the really basic building block of the OS.
    Unlike for an app there's very little benefit in being entirely
    relocatable.

diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 26c16de..68f02fc 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -245,7 +245,7 @@
         </refsect1>
 
         <refsect1>
-                <title>Unit load path</title>
+                <title>Unit Load Path</title>
 
                 <para>Unit files are loaded from a set of paths
                 determined during compilation, described in the two
@@ -254,7 +254,7 @@
                 lower in the hierarchy, thus allowing overrides.
                 </para>
 
-                <para>When systemd is running in session mode
+                <para>When systemd is running in user mode
                 (<option>--user</option>) and the variable
                 <varname>$SYSTEMD_UNIT_PATH</varname> is set, this
                 contents of this variable overrides the unit load
@@ -278,14 +278,11 @@
                     <tbody>
                       <row>
                         <entry><filename>/run/systemd/generator.early</filename></entry>
-                        <entry>Generated units</entry>
-                      </row>
-                      <row>
-                        <entry><filename>&SYSTEM_CONFIG_UNIT_PATH;</filename></entry>
-                        <entry morerows='1'>Local configuration</entry>
+                        <entry>Generated units (early)</entry>
                       </row>
                       <row>
                         <entry><filename>/etc/systemd/system</filename></entry>
+                        <entry>Local configuration</entry>
                       </row>
                       <row>
                         <entry><filename>/run/systemd/systemd</filename></entry>
@@ -293,26 +290,19 @@
                       </row>
                       <row>
                         <entry><filename>/run/systemd/generator</filename></entry>
-                        <entry>Generated units</entry>
+                        <entry>Generated units (middle)</entry>
                       </row>
                       <row>
                         <entry><filename>/usr/local/lib/systemd/system</filename></entry>
                         <entry>Units for local packages</entry>
                       </row>
                       <row>
-                        <entry><filename>&systemunitdir;</filename></entry>
-                        <entry>Systemd package configuration</entry>
-                      </row>
-                      <row>
                         <entry><filename>/usr/lib/systemd/system</filename></entry>
-                        <entry morerows='1'>Units for installed packages</entry>
-                      </row>
-                      <row>
-                        <entry><filename>/lib/systemd/system</filename></entry>
+                        <entry>Units for installed packages</entry>
                       </row>
                       <row>
                         <entry><filename>/run/systemd/generator.late</filename></entry>
-                        <entry>Generated units</entry>
+                        <entry>Generated units (late)</entry>
                       </row>
                     </tbody>
                   </tgroup>
@@ -335,14 +325,11 @@
                     <tbody>
                       <row>
                         <entry><filename>/tmp/systemd-generator.early.<replaceable>XXXXXX</replaceable></filename></entry>
-                        <entry>Generated units</entry>
-                      </row>
-                      <row>
-                        <entry><filename>&USER_CONFIG_UNIT_PATH;</filename></entry>
-                        <entry morerows='1'>Local configuration</entry>
+                        <entry>Generated units (early)</entry>
                       </row>
                       <row>
                         <entry><filename>/etc/systemd/user</filename></entry>
+                        <entry>Local configuration</entry>
                       </row>
                       <row>
                         <entry><filename>/run/systemd/user</filename></entry>
@@ -350,40 +337,24 @@
                       </row>
                       <row>
                         <entry><filename>/tmp/systemd-generator.<replaceable>XXXXXX</replaceable></filename></entry>
-                        <entry>Generated units</entry>
+                        <entry>Generated units (middle)</entry>
                       </row>
                       <row>
                         <entry><filename>/usr/local/lib/systemd/user</filename></entry>
-                        <entry morerows='1'>Units for local packages</entry>
-                      </row>
-                      <row>
-                        <entry><filename>/usr/local/share/systemd/user</filename></entry>
-                      </row>
-                      <row>
-                        <entry><filename>&userunitdir;</filename></entry>
-                        <entry>Systemd package configuration</entry>
+                        <entry>Units for local packages</entry>
                       </row>
                       <row>
                         <entry><filename>/usr/lib/systemd/user</filename></entry>
-                        <entry morerows='1'>Units for installed packages</entry>
-                      </row>
-                      <row>
-                        <entry><filename>/usr/share/systemd/user</filename></entry>
+                        <entry>Units for installed packages</entry>
                       </row>
                       <row>
                         <entry><filename>/tmp/systemd-generator.late.<replaceable>XXXXXX</replaceable></filename></entry>
-                        <entry>Generated units</entry>
+                        <entry>Generated units (late)</entry>
                       </row>
                     </tbody>
                   </tgroup>
                 </table>
 
-                <para>Note: the paths listed above are set at
-                compilation time and differ between distributions. The
-                "authoritative" list is printed by
-                <command>systemd</command> at during start and daemon
-                reconfiguration.</para>
-
                 <para>Additional units might be loaded into systemd
                 ("linked") from directories not on the unit load
                 path. See the <command>link</command> command for

commit 8af8afd6b3a34d1218826f55ada8ece8b4e36fed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 20:22:36 2013 -0300

    cgroup: make cg_pid_get_path() work properly for co-mounted controllers and normalized named hierarchies

diff --git a/TODO b/TODO
index 78d168c..eedabd8 100644
--- a/TODO
+++ b/TODO
@@ -26,8 +26,6 @@ Fedora 19:
 
 Features:
 
-* handle named vs controller hierarchies correctly in cg_pid_get_path()
-
 * add nspawn at .service
 
 * investigate endianess issues of UUID vs. GUID
@@ -59,8 +57,6 @@ Features:
 
 * cgtop: make cgtop useful in a container
 
-* make sure cg_pid_get_path() works properly for co-mounted controllers
-
 * test/:
   - add 'set -e' to scripts in test/
   - make stuff in test/ work with separate output dir
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 016080f..1366f58 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -736,24 +736,27 @@ int cg_set_task_access(
 }
 
 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
-        char fs[sizeof("/proc/") - 1 + DECIMAL_STR_MAX(pid_t) + sizeof("/cgroup")];
         _cleanup_fclose_ FILE *f = NULL;
         char line[LINE_MAX];
+        const char *fs;
         size_t cs;
 
         assert(path);
         assert(pid >= 0);
 
-        if (controller && !cg_controller_is_valid(controller, true))
-                return -EINVAL;
+        if (controller) {
+                if (!cg_controller_is_valid(controller, true))
+                        return -EINVAL;
 
-        if (!controller)
+                controller = normalize_controller(controller);
+        } else
                 controller = SYSTEMD_CGROUP_CONTROLLER;
 
         if (pid == 0)
-                pid = getpid();
+                fs = "/proc/self/cgroup";
+        else
+                fs = procfs_file_alloca(pid, "cgroup");
 
-        sprintf(fs, "/proc/%lu/cgroup", (unsigned long) pid);
         f = fopen(fs, "re");
         if (!f)
                 return errno == ENOENT ? -ESRCH : -errno;
@@ -761,7 +764,10 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
         cs = strlen(controller);
 
         FOREACH_LINE(line, f, return -errno) {
-                char *l, *p;
+                char *l, *p, *w, *e;
+                size_t k;
+                char *state;
+                bool found = false;
 
                 truncate_nl(line);
 
@@ -770,13 +776,31 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
                         continue;
 
                 l++;
-                if (!strneq(l, controller, cs))
+                e = strchr(l, ':');
+                if (!e)
                         continue;
 
-                if (l[cs] != ':')
+                *e = 0;
+
+                FOREACH_WORD_SEPARATOR(w, k, l, ",", state) {
+
+                        if (k == cs && memcmp(w, controller, cs) == 0) {
+                                found = true;
+                                break;
+                        }
+
+                        if (k == 5 + cs &&
+                            memcmp(w, "name=", 5) == 0 &&
+                            memcmp(w+5, controller, cs) == 0) {
+                                found = true;
+                                break;
+                        }
+                }
+
+                if (!found)
                         continue;
 
-                p = strdup(l + cs + 1);
+                p = strdup(e + 1);
                 if (!p)
                         return -ENOMEM;
 

commit 5f1dac6bf605871615b35891a3966fa474db5b20
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 19:57:29 2013 -0300

    cryptsetup: warn if keyfiles are world-readable

diff --git a/TODO b/TODO
index 339a34d..78d168c 100644
--- a/TODO
+++ b/TODO
@@ -158,8 +158,6 @@ Features:
 
 * use "log level" rather than "log priority" everywhere
 
-* ensure sd_journal_seek_monotonic actually works properly.
-
 * timedate: have global on/off switches for auto-time (NTP), and auto-timezone that connman can subscribe to.
 
 * Honour "-" prefix for InaccessibleDirectories= and ReadOnlyDirectories= to
@@ -366,10 +364,10 @@ Features:
   - nspawn: make it work for dwalsh and shared /usr containers -- tmpfs mounts as command line parameters, selinux exec context
 
 * cryptsetup:
-  - cryptsetup-generator: warn if the password files are world-readable
   - cryptsetup-generator: allow specification of passwords in crypttab itself
   - move cryptsetup key caching into kernel keyctl?
     https://bugs.freedesktop.org/show_bug.cgi?id=54982
+  - support rd.luks.allow-discards= kernel cmdline params in cryptsetup generator
 
 * move debug shell to tty6 and make sure this doesn't break the gettys on tty6
 
@@ -440,8 +438,6 @@ Features:
 
 * change Requires=basic.target to RequisiteOverride=basic.target
 
-* support rd.luks.allow-discards= kernel cmdline params in cryptsetup generator
-
 * when breaking cycles drop sysv services first, then services from /run, then from /etc, then from /usr
 
 * move passno parsing to fstab generator
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index a24e61a..347394d 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -497,15 +497,25 @@ int main(int argc, char *argv[]) {
                                  crypt_get_volume_key_size(cd)*8,
                                  argv[3]);
 
-                        if (key_file)
-                                k = crypt_activate_by_keyfile_offset(cd, argv[2], CRYPT_ANY_SLOT, key_file, opt_keyfile_size,
-                                            opt_keyfile_offset, flags);
+                        if (key_file) {
+                                struct stat st;
+
+                                /* Ideally we'd do this on the open
+                                 * fd, but since this is just a
+                                 * warning it's OK to do this in two
+                                 * steps */
+                                if (stat(key_file, &st) >= 0 && (st.st_mode & 0005))
+                                        log_warning("Key file %s is world-readable. That's certainly not a good idea.", key_file);
+
+                                k = crypt_activate_by_keyfile_offset(
+                                                cd, argv[2], CRYPT_ANY_SLOT, key_file, opt_keyfile_size,
+                                                opt_keyfile_offset, flags);
                                 if (k < 0) {
                                         log_error("Failed to activate with key file '%s': %s", key_file, strerror(-k));
                                         key_file = NULL;
                                         continue;
                                 }
-                        else {
+                        } else {
                                 char **p;
 
                                 STRV_FOREACH(p, passwords) {

commit 8973790ee6f62132b1b57de15c4edaef2c097004
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 19:48:03 2013 -0300

    cryptsetup: warn if /etc/crypttab is world-readable

diff --git a/TODO b/TODO
index 1a35703..339a34d 100644
--- a/TODO
+++ b/TODO
@@ -121,8 +121,6 @@ Features:
   and we might want to requeue the mounts local-fs acquired through
   that automatically.
 
-* neither pkexec nor sudo initialize environ[] from the PAM environment?
-
 * rework specifier logic so that we can distuingish OOM errors from other errors
 
 * systemd-inhibit: make taking delay locks useful: support sending SIGINT or SIGTERM on PrepareForSleep()
@@ -131,9 +129,7 @@ Features:
 
 * remove any syslog support from log.c -- we probably can't do this before split-off udev is gone for good
 
-* fedora: connect the timer units of a service to the service via Also= in [Install]
-
-* fedora: F20: go timer units all the way, leave cron.daily for cron
+* documentation: recommend to connect the timer units of a service to the service via Also= in [Install]
 
 * add a tool that lists active timer units plus their next elapstion and the time the units ran last
 
@@ -151,12 +147,6 @@ Features:
 
 * man: maybe sort directives in man pages, and take sections from --help and apply them to man too
 
-* add "# export SYSTEMD_PAGER=" to bash login
-
-* /usr/bin/service should actually show the new command line
-
-* fedora: suggest auto-restart on failure, but not on sucess and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus=
-
 * write UI tool that pops up emergency messages from the journal as notification
 
 * think about window-manager-run-as-user-service problem: exit 0 → activate shutdown.target; exit != 0 → restart service
@@ -214,6 +204,9 @@ Features:
   - pam: when leaving a session explicitly exclude the ReleaseSession() caller process from the killing spree
   - logind: GetSessionByPID() should accept 0 as PID value
   - we should probably handle SIGTERM/SIGINT to not leave dot files around, just in case
+  - add configuration/switches to use
+    freeze (http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git) and
+    standby (https://bugs.freedesktop.org/show_bug.cgi?id=57793) as suspend modes
 
 * exec: when deinitializating a tty device fix the perms and group, too, not only when initializing. Set access mode/gid to 0620/tty.
 
@@ -239,7 +232,6 @@ Features:
   - check if we can make journalctl by default use --follow mode inside of less if called without args?
   - maybe add API to send pairs of iovecs via sd_journal_send
   - journal: when writing journal auto-rotate if time jumps backwards
-  - gatewayd: should run under its own UID
   - journal: add a setgid "systemd-journal" utility to invoke from libsystemd-journal, which passes fds via STDOUT and does PK access
   - journactl: support negative filtering, i.e. FOOBAR!="waldo",
     and !FOOBAR for events without FOOBAR.
@@ -248,7 +240,6 @@ Features:
   - journal-send.c, log.c: when the log socket is clogged, and we drop, count this and write a message about this when it gets unclogged again.
   - journal: find a way to allow dropping history early, based on priority, other rules
   - journal: When used on NFS, check payload hashes
-  - journal: When used on NFS make sure wake up sd_journal_wait() every 2s, to handle missing inotify
   - Introduce journalctl -b <nr> to show journal messages of a previous boot
   - journald: check whether it is OK if the client can still modify delivered journal entries
   - journal live copy, based on libneon (client) and libmicrohttpd (server)
@@ -259,7 +250,6 @@ Features:
   - journalctl: show multiline log messages sanely, expand tabs, and show all valid utf8 messages
   - journal: store euid in journal if it differs from uid
   - journal: sanely deal with entries which are larger than the individual file size, but where the components would fit
-  - journalctl: make journalctl smarter, and actually check groups that have access to /var/log/journal before printing message about recomming group membership for journal access
   - Replace utmp, wtmp, btmp, and lastlog completely with journal
   - Port upower to use the journal for historical power information used in future calculations
 
@@ -288,9 +278,6 @@ Features:
   - systemctl: "Journal has been rotated since unit was started." message is misleading
   - support "systemctl stop foobar at .service" to stop all units matching a certain template
   - Something is wrong with symlink handling of "autovt at .service" in "systemctl list-unit-files"
-  - add configuration/switches to use
-    freeze (http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git) and
-    standby (https://bugs.freedesktop.org/show_bug.cgi?id=57793) as suspend modes
 
 * introduce ntp.service (or suchlike) as symlink that is used to arbitrate between various NTP implementations
 
@@ -363,8 +350,6 @@ Features:
 
 * currently x-systemd.timeout is lost in the initrd, since crypttab is copied into dracut, but fstab isn't
 
-* WorkingDirectory: support env var replacements like in ExecStart= so that people can use $HOME
-
 * refuse boot if /etc/machine-id is not useful (or set taint?)
 
 * nspawn:
@@ -385,7 +370,6 @@ Features:
   - cryptsetup-generator: allow specification of passwords in crypttab itself
   - move cryptsetup key caching into kernel keyctl?
     https://bugs.freedesktop.org/show_bug.cgi?id=54982
-  - when key file cannot be found, read it from kbd in cryptsetup
 
 * move debug shell to tty6 and make sure this doesn't break the gettys on tty6
 
@@ -454,14 +438,10 @@ Features:
 
 * introduce Type=pid-file
 
-* maybe allow services with ExecStop= set, but no ExecStart=?
-
 * change Requires=basic.target to RequisiteOverride=basic.target
 
 * support rd.luks.allow-discards= kernel cmdline params in cryptsetup generator
 
-* drop accountsservice's StandardOutput=syslog and Type=dbus fields
-
 * when breaking cycles drop sysv services first, then services from /run, then from /etc, then from /usr
 
 * move passno parsing to fstab generator
@@ -492,8 +472,6 @@ Features:
 
 * cleanup syslog 'priority' vs. 'level' wording
 
-* dbus upstream still refers to dbus.target and shouldn't
-
 * when a service has the same env var set twice we actually store it twice and return that in systemctl show -p... We should only show the last setting
 
 * support container_ttys=
@@ -508,8 +486,6 @@ Features:
 
 * default unix qlen is too small (10). bump sysctl? add sockopt?
 
-* dbus: in fedora, make /var/lib/dbus/machine-id a symlink to /etc/machine-id
-
 * save coredump in Windows/Mozilla minidump format
 
 * support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting)
@@ -592,8 +568,6 @@ Features:
 
 * support systemd.mask= on the kernel command line.
 
-* reuse mkdtemp namespace dirs in /tmp?
-
 * recreate systemd's D-Bus private socket file on SIGUSR2
 
 * Support --test based on current system state
@@ -624,6 +598,13 @@ Features:
      works with ^C
    - add documentation to systemd.daemon
 
+* bootchart:
+   - plot per-process IO utilization
+   - group processes based on service association (cgroups)
+   - document initcall_debug
+   - put bootcharts in the journal
+   - kernel cmdline "bootchart" option for simplicity?
+
 External:
 
 * dbus:
@@ -649,12 +630,21 @@ External:
 
 * kernel: add device_type = "fb", "fbcon" to class "graphics"
 
-* bootchart:
-   - plot per-process IO utilization
-   - group processes based on service association (cgroups)
-   - document initcall_debug
-   - put bootcharts in the journal
-   - kernel cmdline "bootchart" option for simplicity?
+* drop accountsservice's StandardOutput=syslog and Type=dbus fields
+
+* dbus upstream still refers to dbus.target and shouldn't
+
+* dbus: in fedora, make /var/lib/dbus/machine-id a symlink to /etc/machine-id
+
+* add "# export SYSTEMD_PAGER=" to bash login
+
+* /usr/bin/service should actually show the new command line
+
+* fedora: suggest auto-restart on failure, but not on sucess and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus=
+
+* fedora: F20: go timer units all the way, leave cron.daily for cron
+
+* neither pkexec nor sudo initialize environ[] from the PAM environment?
 
 Regularly:
 
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 228039d..7eae1c8 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -328,13 +328,13 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm
 }
 
 int main(int argc, char *argv[]) {
+        _cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL;
+        _cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL;
+        _cleanup_free_ char *arg_proc_cmdline_keyfile = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         unsigned n = 0;
         int r = EXIT_SUCCESS;
         char **i;
-        _cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL;
-        _cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL;
-        _cleanup_free_ char *arg_proc_cmdline_keyfile = NULL;
 
         if (argc > 1 && argc != 4) {
                 log_error("This program takes three or no arguments.");
@@ -357,8 +357,9 @@ int main(int argc, char *argv[]) {
                 return EXIT_SUCCESS;
 
         if (arg_read_crypttab) {
-                f = fopen("/etc/crypttab", "re");
+                struct stat st;
 
+                f = fopen("/etc/crypttab", "re");
                 if (!f) {
                         if (errno == ENOENT)
                                 r = EXIT_SUCCESS;
@@ -366,7 +367,20 @@ int main(int argc, char *argv[]) {
                                 r = EXIT_FAILURE;
                                 log_error("Failed to open /etc/crypttab: %m");
                         }
-                } else for (;;) {
+
+                        goto next;
+                }
+
+                if (fstat(fileno(f), &st) < 0) {
+                        log_error("Failed to stat /etc/crypttab: %m");
+                        r = EXIT_FAILURE;
+                        goto next;
+                }
+
+                if (st.st_mode & 0005)
+                        log_warning("/etc/crypttab is world-readable. This is usually not a good idea.");
+
+                for (;;) {
                         char line[LINE_MAX], *l;
                         _cleanup_free_ char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
                         int k;
@@ -420,6 +434,7 @@ int main(int argc, char *argv[]) {
                 }
         }
 
+next:
         STRV_FOREACH(i, arg_proc_cmdline_disks) {
                 /*
                   Generate units for those UUIDs, which were specified
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 55648e0..c1ec508 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -48,6 +48,8 @@ extern "C" {
  *
  * - enforce alignment of pointers passed in
  * - negotiation for attach attributes
+ *
+ * - for kernel and unix transports allow setting the unix user/access mode for the node
  */
 
 typedef struct sd_bus sd_bus;

commit 5954c07433b134694256b9989f2ad3f85a643976
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 19:15:30 2013 -0300

    cgroup: do not allow manipulating the cgroup path of units within the systemd:/system subtree

diff --git a/TODO b/TODO
index bb18028..1a35703 100644
--- a/TODO
+++ b/TODO
@@ -26,6 +26,10 @@ Fedora 19:
 
 Features:
 
+* handle named vs controller hierarchies correctly in cg_pid_get_path()
+
+* add nspawn at .service
+
 * investigate endianess issues of UUID vs. GUID
 
 * see if we can fix https://bugs.freedesktop.org/show_bug.cgi?id=63672
@@ -57,9 +61,6 @@ Features:
 
 * make sure cg_pid_get_path() works properly for co-mounted controllers
 
-* explicitly disallow changing the cgroup path of units in the
-  name=systemd hierarchy, unless it is outside of /system
-
 * test/:
   - add 'set -e' to scripts in test/
   - make stuff in test/ work with separate output dir
diff --git a/src/core/unit.c b/src/core/unit.c
index 282852f..c0f156c 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1977,10 +1977,16 @@ static int unit_add_cgroup(Unit *u, CGroupBonding *b) {
 }
 
 char *unit_default_cgroup_path(Unit *u) {
+        _cleanup_free_ char *escaped_instance = NULL;
+
         assert(u);
 
+        escaped_instance = cg_escape(u->id);
+        if (!escaped_instance)
+                return NULL;
+
         if (u->instance) {
-                _cleanup_free_ char *t = NULL, *escaped_template = NULL, *escaped_instance = NULL;
+                _cleanup_free_ char *t = NULL, *escaped_template = NULL;
 
                 t = unit_name_template(u->id);
                 if (!t)
@@ -1990,20 +1996,9 @@ char *unit_default_cgroup_path(Unit *u) {
                 if (!escaped_template)
                         return NULL;
 
-                escaped_instance = cg_escape(u->id);
-                if (!escaped_instance)
-                        return NULL;
-
                 return strjoin(u->manager->cgroup_hierarchy, "/", escaped_template, "/", escaped_instance, NULL);
-        } else {
-                _cleanup_free_ char *escaped = NULL;
-
-                escaped = cg_escape(u->id);
-                if (!escaped)
-                        return NULL;
-
-                return strjoin(u->manager->cgroup_hierarchy, "/", escaped, NULL);
-        }
+        } else
+                return strjoin(u->manager->cgroup_hierarchy, "/", escaped_instance, NULL);
 }
 
 int unit_add_cgroup_from_text(Unit *u, const char *name, bool overwrite, CGroupBonding **ret) {
@@ -2025,7 +2020,7 @@ int unit_add_cgroup_from_text(Unit *u, const char *name, bool overwrite, CGroupB
         }
 
         if (!controller) {
-                controller = strdup(SYSTEMD_CGROUP_CONTROLLER);
+                controller = strdup("systemd");
                 ours = true;
         }
 
@@ -2035,6 +2030,16 @@ int unit_add_cgroup_from_text(Unit *u, const char *name, bool overwrite, CGroupB
                 return log_oom();
         }
 
+        if (streq(controller, "systemd")) {
+                /* Within the systemd unit hierarchy we do not allow changes. */
+                if (path_startswith(path, "/system")) {
+                        log_warning_unit(u->id, "Manipulating the systemd:/system cgroup hierarchy is not permitted.");
+                        free(path);
+                        free(controller);
+                        return -EPERM;
+                }
+        }
+
         b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
         if (b) {
                 if (streq(path, b->path)) {
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 46a8128..016080f 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -916,6 +916,7 @@ int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_
 int cg_split_spec(const char *spec, char **controller, char **path) {
         const char *e;
         char *t = NULL, *u = NULL;
+        _cleanup_free_ char *v = NULL;
 
         assert(spec);
 
@@ -928,6 +929,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
                         if (!t)
                                 return -ENOMEM;
 
+                        path_kill_slashes(t);
                         *path = t;
                 }
 
@@ -943,7 +945,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
                         return -EINVAL;
 
                 if (controller) {
-                        t = strdup(spec);
+                        t = strdup(normalize_controller(spec));
                         if (!t)
                                 return -ENOMEM;
 
@@ -956,7 +958,10 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
                 return 0;
         }
 
-        t = strndup(spec, e-spec);
+        v = strndup(spec, e-spec);
+        if (!v)
+                return -ENOMEM;
+        t = strdup(normalize_controller(v));
         if (!t)
                 return -ENOMEM;
         if (!cg_controller_is_valid(t, true)) {
@@ -969,12 +974,15 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
                 free(t);
                 return -ENOMEM;
         }
-        if (!path_is_safe(u)) {
+        if (!path_is_safe(u) ||
+            !path_is_absolute(u)) {
                 free(t);
                 free(u);
                 return -EINVAL;
         }
 
+        path_kill_slashes(u);
+
         if (controller)
                 *controller = t;
         else
@@ -993,7 +1001,6 @@ int cg_join_spec(const char *controller, const char *path, char **spec) {
 
         assert(path);
 
-
         if (!controller)
                 controller = "systemd";
         else {
@@ -1010,6 +1017,8 @@ int cg_join_spec(const char *controller, const char *path, char **spec) {
         if (!s)
                 return -ENOMEM;
 
+        path_kill_slashes(s + strlen(controller) + 1);
+
         *spec = s;
         return 0;
 }
@@ -1029,6 +1038,7 @@ int cg_mangle_path(const char *path, char **result) {
                 if (!t)
                         return -ENOMEM;
 
+                path_kill_slashes(t);
                 *result = t;
                 return 0;
         }
diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
index a2ee72d..7bd02c1 100644
--- a/src/shared/cgroup-util.h
+++ b/src/shared/cgroup-util.h
@@ -28,6 +28,21 @@
 #include "set.h"
 #include "def.h"
 
+/*
+ * General rules:
+ *
+ * We accept named hierarchies in the syntax "foo" and "name=foo".
+ *
+ * We expect that named hierarchies do not conflict in name with a
+ * kernel hierarchy, modulo the "name=" prefix.
+ *
+ * We always generate "normalized" controller names, i.e. without the
+ * "name=" prefix.
+ *
+ * We require absolute cgroup paths. When returning, we will always
+ * generate paths with multiple adjacent / removed.
+ */
+
 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f);
 int cg_read_pid(FILE *f, pid_t *_pid);

commit aa96c6cb44a6eeccc506ae055aae2519a7f914e1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 29 18:39:12 2013 -0300

    id128: when taking user input for a 128bit ID, validate syntax
    
    Also, always accept both our simple hexdump syntax and UUID syntax.

diff --git a/TODO b/TODO
index 80a591f..bb18028 100644
--- a/TODO
+++ b/TODO
@@ -26,9 +26,7 @@ Fedora 19:
 
 Features:
 
-* nss-myhostname: investigate whether there's any point in also
-  resolving localhost6, localhost.localdomain, ip6-localhost or any of
-  the other names often seen in /etc/hosts
+* investigate endianess issues of UUID vs. GUID
 
 * see if we can fix https://bugs.freedesktop.org/show_bug.cgi?id=63672
   without dropping the location cache entirely.
@@ -36,8 +34,6 @@ Features:
 * dbus: when a unit failed to load (i.e. is in UNIT_ERROR state), we
   should be able to safely try another attempt when the bus call LoadUnit() is invoked.
 
-* for instanced unit drop-ins we should look in foo at bar.service.d/ as well as foo at .service.d/
-
 * if pam_systemd is invoked by su from a process that is outside of a
   any session we should probably just become a NOP, since that's
   usually not a real user session but just some system code that just
@@ -61,8 +57,6 @@ Features:
 
 * make sure cg_pid_get_path() works properly for co-mounted controllers
 
-* nspawn: ensure syntax of --uuid= argument is correct
-
 * explicitly disallow changing the cgroup path of units in the
   name=systemd hierarchy, unless it is outside of /system
 
diff --git a/man/sd_id128_to_string.xml b/man/sd_id128_to_string.xml
index ec8b263..593d075 100644
--- a/man/sd_id128_to_string.xml
+++ b/man/sd_id128_to_string.xml
@@ -59,7 +59,7 @@
 
                         <funcprototype>
                                 <funcdef>int <function>sd_id128_from_string</function></funcdef>
-                                <paramdef>const char <parameter>s</parameter>[33], sd_id128_t* <parameter>ret</parameter></paramdef>
+                                <paramdef>const char* <parameter>s</parameter>, sd_id128_t* <parameter>ret</parameter></paramdef>
                         </funcprototype>
 
                 </funcsynopsis>
@@ -77,14 +77,19 @@
 
                 <para><function>sd_id128_from_string()</function>
                 implements the reverse operation: it takes a 33
-                character array with 32 hexadecimal digits
-                (terminated by NUL) and parses them back into an
-                128 bit ID returned in
-                <parameter>ret</parameter>.</para>
+                character string with 32 hexadecimal digits
+                (either lowercase or uppercase, terminated by NUL) and parses them back into an 128
+                bit ID returned in
+                <parameter>ret</parameter>. Alternatively, this call
+                can also parse a 37 character string with a 128bit ID
+                formatted as RFC UUID.</para>
 
                 <para>For more information about the
                 <literal>sd_id128_t</literal> type see
-                <citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+                <citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Note
+                that these calls operate the same way on all
+                architectures, i.e. the results do not depend on
+                endianess.</para>
 
                 <para>When formatting a 128 bit ID into a string it is
                 often easier to use a format string for
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index 0318296..a877e66 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -31,7 +31,12 @@
 #include "load-fragment.h"
 #include "conf-files.h"
 
-static int iterate_dir(Unit *u, const char *path, UnitDependency dependency, char ***strv) {
+static int iterate_dir(
+                Unit *u,
+                const char *path,
+                UnitDependency dependency,
+                char ***strv) {
+
         _cleanup_closedir_ DIR *d = NULL;
         int r;
 
@@ -86,7 +91,14 @@ static int iterate_dir(Unit *u, const char *path, UnitDependency dependency, cha
         return 0;
 }
 
-static int process_dir(Unit *u, const char *unit_path, const char *name, const char *suffix, UnitDependency dependency, char ***strv) {
+static int process_dir(
+                Unit *u,
+                const char *unit_path,
+                const char *name,
+                const char *suffix,
+                UnitDependency dependency,
+                char ***strv) {
+
         int r;
         char *path;
 
@@ -97,7 +109,7 @@ static int process_dir(Unit *u, const char *unit_path, const char *name, const c
 
         path = strjoin(unit_path, "/", name, suffix, NULL);
         if (!path)
-                return -ENOMEM;
+                return log_oom();
 
         if (u->manager->unit_path_cache &&
             !set_get(u->manager->unit_path_cache, path))
@@ -115,13 +127,13 @@ static int process_dir(Unit *u, const char *unit_path, const char *name, const c
 
                 template = unit_name_template(name);
                 if (!template)
-                        return -ENOMEM;
+                        return log_oom();
 
                 path = strjoin(unit_path, "/", template, suffix, NULL);
                 free(template);
 
                 if (!path)
-                        return -ENOMEM;
+                        return log_oom();
 
                 if (u->manager->unit_path_cache &&
                     !set_get(u->manager->unit_path_cache, path))
@@ -138,10 +150,10 @@ static int process_dir(Unit *u, const char *unit_path, const char *name, const c
 }
 
 char **unit_find_dropin_paths(Unit *u) {
-        Iterator i;
-        char *t;
         _cleanup_strv_free_ char **strv = NULL;
         char **configs = NULL;
+        Iterator i;
+        char *t;
         int r;
 
         assert(u);
@@ -157,14 +169,14 @@ char **unit_find_dropin_paths(Unit *u) {
                 }
         }
 
-        if (!strv_isempty(strv)) {
-                r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv);
-                if (r < 0) {
-                        log_error("Failed to get list of configuration files: %s", strerror(-r));
-                        strv_free(configs);
-                        return NULL;
-                }
+        if (strv_isempty(strv))
+                return NULL;
 
+        r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv);
+        if (r < 0) {
+                log_error("Failed to get list of configuration files: %s", strerror(-r));
+                strv_free(configs);
+                return NULL;
         }
 
         return configs;
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index 608b0a5..18e015f 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -72,16 +72,19 @@ static int generate(char id[34]) {
         /* First, try reading the D-Bus machine id, unless it is a symlink */
         fd = open("/var/lib/dbus/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd >= 0) {
-
-                k = loop_read(fd, id, 32, false);
+                k = loop_read(fd, id, 33, false);
                 close_nointr_nofail(fd);
 
-                if (k >= 32) {
-                        id[32] = '\n';
-                        id[33] = 0;
+                if (k == 33 && id[32] == '\n') {
 
-                        log_info("Initializing machine ID from D-Bus machine ID.");
-                        return 0;
+                        id[32] = 0;
+                        if (id128_is_valid(id)) {
+                                id[32] = '\n';
+                                id[33] = 0;
+
+                                log_info("Initializing machine ID from D-Bus machine ID.");
+                                return 0;
+                        }
                 }
         }
 
@@ -113,7 +116,7 @@ static int generate(char id[34]) {
          * $container_uuid the way libvirt/LXC does it */
         r = detect_container(NULL);
         if (r > 0) {
-                char *e;
+                _cleanup_free_ char *e = NULL;
 
                 r = getenv_for_pid(1, "container_uuid", &e);
                 if (r > 0) {
@@ -121,12 +124,9 @@ static int generate(char id[34]) {
                                 r = shorten_uuid(id, e);
                                 if (r >= 0) {
                                         log_info("Initializing machine ID from container UUID.");
-                                        free(e);
                                         return 0;
                                 }
                         }
-
-                        free(e);
                 }
         }
 
@@ -183,8 +183,12 @@ int machine_id_setup(void) {
         }
 
         if (S_ISREG(st.st_mode))
-                if (loop_read(fd, id, 32, false) >= 32)
-                        return 0;
+                if (loop_read(fd, id, 33, false) == 33 && id[32] == '\n') {
+                        id[32] = 0;
+
+                        if (id128_is_valid(id))
+                                return 0;
+                }
 
         /* Hmm, so, the id currently stored is not useful, then let's
          * generate one */
diff --git a/src/libsystemd-id128/sd-id128.c b/src/libsystemd-id128/sd-id128.c
index 68c4987..64ddd09 100644
--- a/src/libsystemd-id128/sd-id128.c
+++ b/src/libsystemd-id128/sd-id128.c
@@ -44,30 +44,50 @@ _public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) {
         return s;
 }
 
-_public_ int sd_id128_from_string(const char s[33], sd_id128_t *ret) {
-        unsigned n;
+_public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
+        unsigned n, i;
         sd_id128_t t;
+        bool is_guid = false;
 
         if (!s)
                 return -EINVAL;
         if (!ret)
                 return -EINVAL;
 
-        for (n = 0; n < 16; n++) {
+        for (n = 0, i = 0; n < 16;) {
                 int a, b;
 
-                a = unhexchar(s[n*2]);
+                if (s[i] == '-') {
+                        /* Is this a GUID? Then be nice, and skip over
+                         * the dashes */
+
+                        if (i == 8)
+                                is_guid = true;
+                        else if (i == 13 || i == 18 || i == 23) {
+                                if (!is_guid)
+                                        return -EINVAL;
+                        } else
+                                return -EINVAL;
+
+                        i++;
+                        continue;
+                }
+
+                a = unhexchar(s[i++]);
                 if (a < 0)
                         return -EINVAL;
 
-                b = unhexchar(s[n*2+1]);
+                b = unhexchar(s[i++]);
                 if (b < 0)
                         return -EINVAL;
 
-                t.bytes[n] = (a << 4) | b;
+                t.bytes[n++] = (a << 4) | b;
         }
 
-        if (s[32] != 0)
+        if (i != (is_guid ? 36 : 32))
+                return -EINVAL;
+
+        if (s[i] != 0)
                 return -EINVAL;
 
         *ret = t;
@@ -90,8 +110,8 @@ static sd_id128_t make_v4_uuid(sd_id128_t id) {
 _public_ int sd_id128_get_machine(sd_id128_t *ret) {
         static __thread sd_id128_t saved_machine_id;
         static __thread bool saved_machine_id_valid = false;
-        int fd;
-        char buf[32];
+        _cleanup_close_ int fd = -1;
+        char buf[33];
         ssize_t k;
         unsigned j;
         sd_id128_t t;
@@ -108,13 +128,14 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
         if (fd < 0)
                 return -errno;
 
-        k = loop_read(fd, buf, 32, false);
-        close_nointr_nofail(fd);
-
+        k = loop_read(fd, buf, 33, false);
         if (k < 0)
                 return (int) k;
 
-        if (k < 32)
+        if (k != 33)
+                return -EIO;
+
+        if (buf[32] !='\n')
                 return -EIO;
 
         for (j = 0; j < 16; j++) {
@@ -139,7 +160,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
 _public_ int sd_id128_get_boot(sd_id128_t *ret) {
         static __thread sd_id128_t saved_boot_id;
         static __thread bool saved_boot_id_valid = false;
-        int fd;
+        _cleanup_close_ int fd = -1;
         char buf[36];
         ssize_t k;
         unsigned j;
@@ -159,12 +180,10 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
                 return -errno;
 
         k = loop_read(fd, buf, 36, false);
-        close_nointr_nofail(fd);
-
         if (k < 0)
                 return (int) k;
 
-        if (k < 36)
+        if (k != 36)
                 return -EIO;
 
         for (j = 0, p = buf; j < 16; j++) {
@@ -195,9 +214,9 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
 }
 
 _public_ int sd_id128_randomize(sd_id128_t *ret) {
-        int fd;
-        ssize_t k;
+        _cleanup_close_ int fd = -1;
         sd_id128_t t;
+        ssize_t k;
 
         if (!ret)
                 return -EINVAL;
@@ -207,12 +226,10 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) {
                 return -errno;
 
         k = loop_read(fd, &t, 16, false);
-        close_nointr_nofail(fd);
-
         if (k < 0)
                 return (int) k;
 
-        if (k < 16)
+        if (k != 16)
                 return -EIO;
 
         /* Turn this into a valid v4 UUID, to be nice. Note that we
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index a49cbc2..0a46313 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -222,6 +222,11 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_UUID:
+                        if (!id128_is_valid(optarg)) {
+                                log_error("Invalid UUID: %s", optarg);
+                                return -EINVAL;
+                        }
+
                         arg_uuid = optarg;
                         break;
 
diff --git a/src/shared/util.c b/src/shared/util.c
index 38ee493..f9ec14a 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -5854,3 +5854,44 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) {
         *allocated = a;
         return q;
 }
+
+bool id128_is_valid(const char *s) {
+        size_t i, l;
+
+        l = strlen(s);
+        if (l == 32) {
+
+                /* Simple formatted 128bit hex string */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if (!(c >= '0' && c <= '9') &&
+                            !(c >= 'a' && c <= 'z') &&
+                            !(c >= 'A' && c <= 'Z'))
+                                return false;
+                }
+
+        } else if (l == 36) {
+
+                /* Formatted UUID */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+                                if (c != '-')
+                                        return false;
+                        } else {
+                                if (!(c >= '0' && c <= '9') &&
+                                    !(c >= 'a' && c <= 'z') &&
+                                    !(c >= 'A' && c <= 'Z'))
+                                        return false;
+                        }
+                }
+
+        } else
+                return false;
+
+        return true;
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index e3fc876..5d1b0b1 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -733,3 +733,5 @@ static inline void _reset_locale_(struct _locale_struct_ *s) {
                      }                                                  \
                      !_saved_locale_.quit; }) ;                         \
              _saved_locale_.quit = true)
+
+bool id128_is_valid(const char *s);
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index 79bb8b3..3a83932 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -40,7 +40,7 @@ union sd_id128 {
 
 char *sd_id128_to_string(sd_id128_t id, char s[33]);
 
-int sd_id128_from_string(const char s[33], sd_id128_t *ret);
+int sd_id128_from_string(const char *s, sd_id128_t *ret);
 
 int sd_id128_randomize(sd_id128_t *ret);
 
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index bfd743e..2ed8e29 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -27,10 +27,13 @@
 #include "macro.h"
 
 #define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10)
+#define STR_WALDI "0102030405060708090a0b0c0d0e0f10"
+#define UUID_WALDI "01020304-0506-0708-090a-0b0c0d0e0f10"
 
 int main(int argc, char *argv[]) {
         sd_id128_t id, id2;
         char t[33];
+        _cleanup_free_ char *b = NULL;
 
         assert_se(sd_id128_randomize(&id) == 0);
         printf("random: %s\n", sd_id128_to_string(id, t));
@@ -45,8 +48,28 @@ int main(int argc, char *argv[]) {
         printf("boot: %s\n", sd_id128_to_string(id, t));
 
         printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t));
-
-        printf("waldi2: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(ID128_WALDI));
+        assert_se(streq(t, STR_WALDI));
+
+        assert_se(asprintf(&b, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 32);
+        printf("waldi2: %s\n", b);
+        assert_se(streq(t, b));
+
+        assert_se(sd_id128_from_string(UUID_WALDI, &id) >= 0);
+        assert_se(sd_id128_equal(id, ID128_WALDI));
+
+        assert_se(sd_id128_from_string("", &id) < 0);
+        assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f101", &id) < 0);
+        assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f10-", &id) < 0);
+        assert_se(sd_id128_from_string("01020304-0506-0708-090a0b0c0d0e0f10", &id) < 0);
+        assert_se(sd_id128_from_string("010203040506-0708-090a-0b0c0d0e0f10", &id) < 0);
+
+        assert_se(id128_is_valid(STR_WALDI));
+        assert_se(id128_is_valid(UUID_WALDI));
+        assert_se(!id128_is_valid(""));
+        assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f101"));
+        assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f10-"));
+        assert_se(!id128_is_valid("01020304-0506-0708-090a0b0c0d0e0f10"));
+        assert_se(!id128_is_valid("010203040506-0708-090a-0b0c0d0e0f10"));
 
         return 0;
 }



More information about the systemd-commits mailing list