]> git.proxmox.com Git - systemd.git/commitdiff
New upstream version 246.2
authorMichael Biebl <biebl@debian.org>
Mon, 17 Aug 2020 19:43:29 +0000 (21:43 +0200)
committerMichael Biebl <biebl@debian.org>
Mon, 17 Aug 2020 19:43:29 +0000 (21:43 +0200)
12 files changed:
man/org.freedesktop.systemd1.xml
man/systemd.service.xml
src/basic/user-util.c
src/basic/user-util.h
src/boot/bless-boot.c
src/core/namespace.c
src/shared/seccomp-util.c
src/shared/user-record-nss.c
src/shared/user-record.c
src/test/test-fs-util.c
src/test/test-user-util.c
tools/make-man-index.py

index 6b16ae16da917b1c15eff47d35bc70534de6089f..8a7990ff7d63c9d3c5b1e0962c1cfaa40456cd24 100644 (file)
@@ -8778,7 +8778,7 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
   <refsect1>
     <title>Scope Unit Objects</title>
 
-    <para>All slice unit objects implement the <interfacename>org.freedesktop.systemd1.Scope</interfacename>
+    <para>All scope unit objects implement the <interfacename>org.freedesktop.systemd1.Scope</interfacename>
     interface (described here) in addition to the generic
     <interfacename>org.freedesktop.systemd1.Unit</interfacename> interface (see above).</para>
 
index cc13bff7550f6ca7fb456eaaadb29049c00aa6f4..fbb2987d0bec705a8c45255d1c04903b3ffb7d67 100644 (file)
             this notification message has been sent. If this option is used, <varname>NotifyAccess=</varname> (see
             below) should be set to open access to the notification socket provided by systemd. If
             <varname>NotifyAccess=</varname> is missing or set to <option>none</option>, it will be forcibly set to
-            <option>main</option></para></listitem>.
+            <option>main</option>.</para></listitem>
 
             <listitem><para>Behavior of <option>idle</option> is very similar to <option>simple</option>; however,
             actual execution of the service program is delayed until all active jobs are dispatched. This may be used
index 8115065b5eca119a8515a776cb27428ee9d76b18..0e96a75797a95fdb9412ee7acada798e1ff8d7c0 100644 (file)
@@ -863,6 +863,37 @@ bool valid_gecos(const char *d) {
         return true;
 }
 
+char *mangle_gecos(const char *d) {
+        char *mangled;
+
+        /* Makes sure the provided string becomes valid as a GEGOS field, by dropping bad chars. glibc's
+         * putwent() only changes \n and : to spaces. We do more: replace all CC too, and remove invalid
+         * UTF-8 */
+
+        mangled = strdup(d);
+        if (!mangled)
+                return NULL;
+
+        for (char *i = mangled; *i; i++) {
+                int len;
+
+                if ((uint8_t) *i < (uint8_t) ' ' || *i == ':') {
+                        *i = ' ';
+                        continue;
+                }
+
+                len = utf8_encoded_valid_unichar(i, (size_t) -1);
+                if (len < 0) {
+                        *i = ' ';
+                        continue;
+                }
+
+                i += len - 1;
+        }
+
+        return mangled;
+}
+
 bool valid_home(const char *p) {
         /* Note that this function is also called by valid_shell(), any
          * changes must account for that. */
index 1f267d21a3f3f188af142b3f7e2925b9626fd450..7c142dd1e66e6521f91a2cf73eb247a755870257 100644 (file)
@@ -105,6 +105,7 @@ typedef enum ValidUserFlags {
 
 bool valid_user_group_name(const char *u, ValidUserFlags flags);
 bool valid_gecos(const char *d);
+char *mangle_gecos(const char *d);
 bool valid_home(const char *p);
 
 static inline bool valid_shell(const char *p) {
index b96e1f927fffab84d1e4f9d28d4dab6a11875c0e..0824266a809a89688961ae77870c8e9f5d5ce1ec 100644 (file)
@@ -34,6 +34,7 @@ static int help(int argc, char *argv[], void *userdata) {
         printf("%s [OPTIONS...] COMMAND\n"
                "\n%sMark the boot process as good or bad.%s\n"
                "\nCommands:\n"
+               "     status          Show status of current boot loader entry\n"
                "     good            Mark this boot as good\n"
                "     bad             Mark this boot as bad\n"
                "     indeterminate   Undo any marking as good or bad\n"
index 36d5ff67aed6db4f4add24dbb5b05bc1816179df..d30c810882be5a29122b12db5cc601fb93eb3f56 100644 (file)
@@ -1830,11 +1830,11 @@ static int make_tmp_prefix(const char *prefix) {
 static int make_tmp_subdir(const char *parent, char **ret) {
         _cleanup_free_ char *y = NULL;
 
-        RUN_WITH_UMASK(0000) {
-                y = strjoin(parent, "/tmp");
-                if (!y)
-                        return -ENOMEM;
+        y = path_join(parent, "/tmp");
+        if (!y)
+                return -ENOMEM;
 
+        RUN_WITH_UMASK(0000) {
                 if (mkdir(y, 0777 | S_ISVTX) < 0)
                         return -errno;
         }
@@ -1890,9 +1890,9 @@ static int setup_one_tmp_dir(const char *id, const char *prefix, char **path, ch
                 if (r < 0)
                         return r;
 
-                x = strdup(RUN_SYSTEMD_EMPTY);
-                if (!x)
-                        return -ENOMEM;
+                r = free_and_strdup(&x, RUN_SYSTEMD_EMPTY);
+                if (r < 0)
+                        return r;
         }
 
         *path = TAKE_PTR(x);
index a8dd069a758dbb82edd9266bddb63e1cbadcee49..45bf309bcf8c536306eb99b9e1bb9078e9e33bf3 100644 (file)
@@ -402,6 +402,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "close\0"
                 "creat\0"
                 "faccessat\0"
+                "faccessat2\0"
                 "fallocate\0"
                 "fchdir\0"
                 "fchmod\0"
index f265a2af9333e24457cd634b77cbb77ab0840090..b27a12c55d06bd15e2ad732c009eb066cb03e179 100644 (file)
@@ -5,6 +5,7 @@
 #include "libcrypt-util.h"
 #include "strv.h"
 #include "user-record-nss.h"
+#include "user-util.h"
 
 #define SET_IF(field, condition, value, fallback)  \
         field = (condition) ? (value) : (fallback)
@@ -34,10 +35,25 @@ int nss_passwd_to_user_record(
         if (r < 0)
                 return r;
 
-        r = free_and_strdup(&hr->real_name,
-                            streq_ptr(pwd->pw_gecos, hr->user_name) ? NULL : empty_to_null(pwd->pw_gecos));
-        if (r < 0)
-                return r;
+        /* Some bad NSS modules synthesize GECOS fields with embedded ":" or "\n" characters, which are not
+         * something we can output in /etc/passwd compatible format, since these are record separators
+         * there. We normally refuse that, but we need to maintain compatibility with arbitrary NSS modules,
+         * hence let's do what glibc does: mangle the data to fit the format. */
+        if (isempty(pwd->pw_gecos) || streq_ptr(pwd->pw_gecos, hr->user_name))
+                hr->real_name = mfree(hr->real_name);
+        else if (valid_gecos(pwd->pw_gecos)) {
+                r = free_and_strdup(&hr->real_name, pwd->pw_gecos);
+                if (r < 0)
+                        return r;
+        } else {
+                _cleanup_free_ char *mangled = NULL;
+
+                mangled = mangle_gecos(pwd->pw_gecos);
+                if (!mangled)
+                        return -ENOMEM;
+
+                free_and_replace(hr->real_name, mangled);
+        }
 
         r = free_and_strdup(&hr->home_directory, empty_to_null(pwd->pw_dir));
         if (r < 0)
index 16edaa45face3bb66a17f196efa47d54ba3873c3..2c0de383e042316623a97cb6fecd9c58e7e2c45b 100644 (file)
@@ -206,7 +206,6 @@ int json_dispatch_realm(const char *name, JsonVariant *variant, JsonDispatchFlag
 static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
         char **s = userdata;
         const char *n;
-        int r;
 
         if (json_variant_is_null(variant)) {
                 *s = mfree(*s);
@@ -217,12 +216,20 @@ static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispa
                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
 
         n = json_variant_string(variant);
-        if (!valid_gecos(n))
-                return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible real name.", strna(name));
+        if (valid_gecos(n)) {
+                if (free_and_strdup(s, n) < 0)
+                        return json_log_oom(variant, flags);
+        } else {
+                _cleanup_free_ char *m = NULL;
 
-        r = free_and_strdup(s, n);
-        if (r < 0)
-                return json_log(variant, flags, r, "Failed to allocate string: %m");
+                json_log(variant, flags|JSON_DEBUG, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible string, mangling.", strna(name));
+
+                m = mangle_gecos(n);
+                if (!m)
+                        return json_log_oom(variant, flags);
+
+                free_and_replace(*s, m);
+        }
 
         return 0;
 }
index dfea70ca27390a4bcfa504f1d695ef8c2db2a175..1ea845dd9bd7109463c198cd9fc4e921cabb77fc 100644 (file)
@@ -850,11 +850,12 @@ static void test_path_is_encrypted_one(const char *p, int expect) {
         int r;
 
         r = path_is_encrypted(p);
-        if (r == -ENOENT) /* This might fail, if btrfs is used and we run in a container. In that case we
-                           * cannot resolve the device node paths that BTRFS_IOC_DEV_INFO returns, because
-                           * the device nodes are unlikely to exist in the container. But if we can't stat()
-                           * them we cannot determine the dev_t of them, and thus cannot figure out if they
-                           * are enrypted. Hence let's just ignore ENOENT here. */
+        if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* This might fail, if btrfs is used and we run in a
+                           * container. In that case we cannot resolve the device node paths that
+                           * BTRFS_IOC_DEV_INFO returns, because the device nodes are unlikely to exist in
+                           * the container. But if we can't stat() them we cannot determine the dev_t of
+                           * them, and thus cannot figure out if they are enrypted. Hence let's just ignore
+                           * ENOENT here. Also skip the test if we lack privileges. */
                 return;
         assert_se(r >= 0);
 
index c9bff941be17673ab4d327057026a201e83511ea..306d08a2824cb9640075a6ed385da9796da19610 100644 (file)
@@ -452,6 +452,25 @@ static void test_parse_uid_range(void) {
         assert_se(parse_uid_range(" 01", &a, &b) == -EINVAL && a == 4 && b == 5);
 }
 
+static void test_mangle_gecos_one(const char *input, const char *expected) {
+        _cleanup_free_ char *p = NULL;
+
+        assert_se(p = mangle_gecos(input));
+        assert_se(streq(p, expected));
+        assert_se(valid_gecos(p));
+}
+
+static void test_mangle_gecos(void) {
+        test_mangle_gecos_one("", "");
+        test_mangle_gecos_one("root", "root");
+        test_mangle_gecos_one("wuff\nwuff", "wuff wuff");
+        test_mangle_gecos_one("wuff:wuff", "wuff wuff");
+        test_mangle_gecos_one("wuff\r\n:wuff", "wuff   wuff");
+        test_mangle_gecos_one("\n--wüff-wäff-wöff::", " --wüff-wäff-wöff  ");
+        test_mangle_gecos_one("\xc3\x28", " (");
+        test_mangle_gecos_one("\xe2\x28\xa1", " ( ");
+}
+
 int main(int argc, char *argv[]) {
         test_uid_to_name_one(0, "root");
         test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
@@ -482,6 +501,7 @@ int main(int argc, char *argv[]) {
         test_valid_user_group_name_or_numeric_relaxed();
         test_valid_user_group_name_or_numeric();
         test_valid_gecos();
+        test_mangle_gecos();
         test_valid_home();
 
         test_make_salt();
index 4d206ca0b6bb741f9ce2e0d9d012d469e7a2682b..37c708d81dc0953df4bcc2183a49331838da6ae9 100755 (executable)
@@ -55,7 +55,8 @@ def make_index(pages):
         check_id(p, t)
         section = t.find('./refmeta/manvolnum').text
         refname = t.find('./refnamediv/refname').text
-        purpose = ' '.join(t.find('./refnamediv/refpurpose').text.split())
+        purpose_text = ' '.join(t.find('./refnamediv/refpurpose').itertext())
+        purpose = ' '.join(purpose_text.split())
         for f in t.findall('./refnamediv/refname'):
             infos = (f.text, section, purpose, refname)
             index[f.text[0].upper()].append(infos)