[systemd/f16] cherry-picks from v44

Michal Schmidt michich at fedoraproject.org
Mon Mar 19 23:37:04 UTC 2012


commit 14c3102fc6ee3500b6f56ce8db7c35a96abcd60f
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Tue Mar 20 00:34:19 2012 +0100

    cherry-picks from v44

 0162-man-reword-tmpfiles-selinux-bits.patch        |   55 ++
 0163-conf-enforce-UTF8-validty-everywhere.patch    |  766 ++++++++++++++++++++
 ...dd-brute-force-fallback-for-close_all_fds.patch |   91 +++
 ...-warn-if-an-assignment-is-place-outside-o.patch |   31 +
 0166-mount-fix-assertion.patch                     |   33 +
 ...-sure-that-the-name-for-per-connection-se.patch |   51 ++
 ...t-where-we-read-kernel-cmdline-options-fr.patch |   33 +
 ...t-etc-timezone-into-nspawn-environment-to.patch |   39 +
 systemd.spec                                       |   19 +-
 9 files changed, 1117 insertions(+), 1 deletions(-)
---
diff --git a/0162-man-reword-tmpfiles-selinux-bits.patch b/0162-man-reword-tmpfiles-selinux-bits.patch
new file mode 100644
index 0000000..b8ba43b
--- /dev/null
+++ b/0162-man-reword-tmpfiles-selinux-bits.patch
@@ -0,0 +1,55 @@
+From e02e2cd119d731cdd830c9b4f5312ed35d2ad6ba Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Mon, 12 Mar 2012 21:51:39 +0100
+Subject: [PATCH] man: reword tmpfiles selinux bits (cherry picked from commit
+ 669e49fe2c841e53f7f2196bbe5d614013429ecd)
+
+---
+ man/tmpfiles.d.xml |   29 +++++++++++++++++------------
+ 1 files changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
+index 4a8e831..74fcc75 100644
+--- a/man/tmpfiles.d.xml
++++ b/man/tmpfiles.d.xml
+@@ -158,23 +158,28 @@ d    /run/user 0755 root root 10d</programlisting>
+ 
+                                 <varlistentry>
+                                         <term><varname>z</varname></term>
+-                                        <listitem><para>Set ownership, access
+-                                        mode and relabel security context of
+-                                        a file or directory if it exists.
+-                                        Lines of this type accept shell-style
+-                                        globs in place of normal path names.
++                                        <listitem><para>Restore
++                                        SELinux security context label
++                                        and set ownership and access
++                                        mode of a file or directory if
++                                        it exists.  Lines of this type
++                                        accept shell-style globs in
++                                        place of normal path names.
+                                         </para></listitem>
+                                 </varlistentry>
+ 
+                                 <varlistentry>
+                                         <term><varname>Z</varname></term>
+-                                        <listitem><para>Recursively set
+-                                        ownership, access mode and relabel
+-                                        security context of a path and
+-                                        all its subdirectories (if it is a
+-                                        directory). Lines of this type accept
+-                                        shell-style globs in place of normal
+-                                        path names.</para></listitem>
++                                        <listitem><para>Recursively
++                                        restore SELinux security
++                                        context label and set
++                                        ownership and access mode of a
++                                        path and all its
++                                        subdirectories (if it is a
++                                        directory). Lines of this type
++                                        accept shell-style globs in
++                                        place of normal path
++                                        names.</para></listitem>
+                                 </varlistentry>
+                         </variablelist>
+                 </refsect2>
diff --git a/0163-conf-enforce-UTF8-validty-everywhere.patch b/0163-conf-enforce-UTF8-validty-everywhere.patch
new file mode 100644
index 0000000..bc83e41
--- /dev/null
+++ b/0163-conf-enforce-UTF8-validty-everywhere.patch
@@ -0,0 +1,766 @@
+From d2ebd2444f5ecf11e091e8108232ef6b3322f32f Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Mon, 12 Mar 2012 22:22:16 +0100
+Subject: [PATCH] conf: enforce UTF8 validty everywhere
+
+we need to make sure that configuration data we expose via the bus ends
+up in using getting an assert(). Even though configuration data is only
+parsed from trusted sources we should be more careful with what we read.
+(cherry picked from commit 7f110ff9b8828b477e87de7b28c708cf69a3d008)
+
+Conflicts:
+
+	Makefile.am
+	TODO
+---
+ Makefile.am         |    6 +-
+ src/conf-parser.c   |   66 ++++++++++++----
+ src/load-fragment.c |  102 ++++++++++++++-----------
+ src/service.c       |   13 +++-
+ src/utf8.c          |  214 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/utf8.h          |   33 ++++++++
+ src/util.c          |   17 +++--
+ 7 files changed, 382 insertions(+), 69 deletions(-)
+ create mode 100644 src/utf8.c
+ create mode 100644 src/utf8.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 295944d..2f5dcdb 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -632,7 +632,8 @@ libsystemd_basic_la_SOURCES = \
+ 	src/socket-util.c \
+ 	src/log.c \
+ 	src/ratelimit.c \
+-	src/exit-status.c
++	src/exit-status.c \
++	src/utf8.c
+ 
+ libsystemd_basic_la_CFLAGS = \
+ 	$(AM_CFLAGS) \
+@@ -757,7 +758,8 @@ EXTRA_DIST += \
+         src/logind-user.h \
+         src/logind-acl.h \
+         src/dbus-loop.h \
+-        src/spawn-agent.h
++        src/spawn-agent.h \
++        src/utf8.h
+ 
+ MANPAGES = \
+ 	man/systemd.1 \
+diff --git a/src/conf-parser.c b/src/conf-parser.c
+index af34378..9edf637 100644
+--- a/src/conf-parser.c
++++ b/src/conf-parser.c
+@@ -30,6 +30,7 @@
+ #include "macro.h"
+ #include "strv.h"
+ #include "log.h"
++#include "utf8.h"
+ 
+ int config_item_table_lookup(
+                 void *table,
+@@ -554,14 +555,23 @@ int config_parse_string(
+         assert(rvalue);
+         assert(data);
+ 
+-        if (*rvalue) {
+-                if (!(n = strdup(rvalue)))
+-                        return -ENOMEM;
+-        } else
+-                n = NULL;
++        n = cunescape(rvalue);
++        if (!n)
++                return -ENOMEM;
++
++        if (!utf8_is_valid(n)) {
++                log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
++                free(n);
++                return 0;
++        }
+ 
+         free(*s);
+-        *s = n;
++        if (*n)
++                *s = n;
++        else {
++                free(n);
++                *s = NULL;
++        }
+ 
+         return 0;
+ }
+@@ -584,12 +594,18 @@ int config_parse_path(
+         assert(rvalue);
+         assert(data);
+ 
++        if (!utf8_is_valid(rvalue)) {
++                log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
++                return 0;
++        }
++
+         if (!path_is_absolute(rvalue)) {
+                 log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
+                 return 0;
+         }
+ 
+-        if (!(n = strdup(rvalue)))
++        n = strdup(rvalue);
++        if (!n)
+                 return -ENOMEM;
+ 
+         path_kill_slashes(n);
+@@ -616,6 +632,7 @@ int config_parse_strv(
+         unsigned k;
+         size_t l;
+         char *state;
++        int r;
+ 
+         assert(filename);
+         assert(lvalue);
+@@ -626,7 +643,8 @@ int config_parse_strv(
+         FOREACH_WORD_QUOTED(w, l, rvalue, state)
+                 k++;
+ 
+-        if (!(n = new(char*, k+1)))
++        n = new(char*, k+1);
++        if (!n)
+                 return -ENOMEM;
+ 
+         if (*sv)
+@@ -635,9 +653,21 @@ int config_parse_strv(
+         else
+                 k = 0;
+ 
+-        FOREACH_WORD_QUOTED(w, l, rvalue, state)
+-                if (!(n[k++] = cunescape_length(w, l)))
++        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
++                n[k] = cunescape_length(w, l);
++                if (!n[k]) {
++                        r = -ENOMEM;
+                         goto fail;
++                }
++
++                if (!utf8_is_valid(n[k])) {
++                        log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
++                        free(n[k]);
++                        continue;
++                }
++
++                k++;
++        }
+ 
+         n[k] = NULL;
+         free(*sv);
+@@ -650,7 +680,7 @@ fail:
+                 free(n[k-1]);
+         free(n);
+ 
+-        return -ENOMEM;
++        return r;
+ }
+ 
+ int config_parse_path_strv(
+@@ -680,7 +710,8 @@ int config_parse_path_strv(
+         FOREACH_WORD_QUOTED(w, l, rvalue, state)
+                 k++;
+ 
+-        if (!(n = new(char*, k+1)))
++        n = new(char*, k+1);
++        if (!n)
+                 return -ENOMEM;
+ 
+         k = 0;
+@@ -689,11 +720,18 @@ int config_parse_path_strv(
+                         n[k] = (*sv)[k];
+ 
+         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+-                if (!(n[k] = cunescape_length(w, l))) {
++                n[k] = strndup(w, l);
++                if (!n[k]) {
+                         r = -ENOMEM;
+                         goto fail;
+                 }
+ 
++                if (!utf8_is_valid(n[k])) {
++                        log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
++                        free(n[k]);
++                        continue;
++                }
++
+                 if (!path_is_absolute(n[k])) {
+                         log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
+                         free(n[k]);
+@@ -701,7 +739,6 @@ int config_parse_path_strv(
+                 }
+ 
+                 path_kill_slashes(n[k]);
+-
+                 k++;
+         }
+ 
+@@ -712,7 +749,6 @@ int config_parse_path_strv(
+         return 0;
+ 
+ fail:
+-        free(n[k]);
+         for (; k > 0; k--)
+                 free(n[k-1]);
+         free(n);
+diff --git a/src/load-fragment.c b/src/load-fragment.c
+index ba28398..1d4a8c1 100644
+--- a/src/load-fragment.c
++++ b/src/load-fragment.c
+@@ -43,6 +43,7 @@
+ #include "missing.h"
+ #include "unit-name.h"
+ #include "bus-errors.h"
++#include "utf8.h"
+ 
+ #ifndef HAVE_SYSV_COMPAT
+ int config_parse_warn_compat(
+@@ -90,7 +91,6 @@ int config_parse_unit_deps(
+ 
+                 k = unit_name_printf(u, t);
+                 free(t);
+-
+                 if (!k)
+                         return -ENOMEM;
+ 
+@@ -128,22 +128,18 @@ int config_parse_unit_names(
+                 char *t, *k;
+                 int r;
+ 
+-                if (!(t = strndup(w, l)))
++                t = strndup(w, l);
++                if (!t)
+                         return -ENOMEM;
+ 
+                 k = unit_name_printf(u, t);
+                 free(t);
+-
+                 if (!k)
+                         return -ENOMEM;
+ 
+                 r = unit_merge_by_name(u, k);
+-
+-                if (r < 0) {
++                if (r < 0)
+                         log_error("Failed to add name %s, ignoring: %s", k, strerror(-r));
+-                        free(k);
+-                        return 0;
+-                }
+ 
+                 free(k);
+         }
+@@ -162,27 +158,22 @@ int config_parse_unit_string_printf(
+                 void *userdata) {
+ 
+         Unit *u = userdata;
+-        char **s = data;
+         char *k;
++        int r;
+ 
+         assert(filename);
+         assert(lvalue);
+         assert(rvalue);
+-        assert(s);
+         assert(u);
+ 
+-        if (!(k = unit_full_printf(u, rvalue)))
++        k = unit_full_printf(u, rvalue);
++        if (!k)
+                 return -ENOMEM;
+ 
+-        free(*s);
+-        if (*k)
+-                *s = k;
+-        else {
+-                free(k);
+-                *s = NULL;
+-        }
++        r = config_parse_string(filename, line, section, lvalue, ltype, k, data, userdata);
++        free (k);
+ 
+-        return 0;
++        return r;
+ }
+ 
+ int config_parse_unit_strv_printf(
+@@ -225,30 +216,22 @@ int config_parse_unit_path_printf(
+                 void *userdata) {
+ 
+         Unit *u = userdata;
+-        char **s = data;
+         char *k;
++        int r;
+ 
+         assert(filename);
+         assert(lvalue);
+         assert(rvalue);
+-        assert(s);
+         assert(u);
+ 
+-        if (!(k = unit_full_printf(u, rvalue)))
++        k = unit_full_printf(u, rvalue);
++        if (!k)
+                 return -ENOMEM;
+ 
+-        if (!path_is_absolute(k)) {
+-                log_error("[%s:%u] Not an absolute path: %s", filename, line, k);
+-                free(k);
+-                return -EINVAL;
+-        }
+-
+-        path_kill_slashes(k);
+-
+-        free(*s);
+-        *s = k;
++        r = config_parse_path(filename, line, section, lvalue, ltype, k, data, userdata);
++        free(k);
+ 
+-        return 0;
++        return r;
+ }
+ 
+ int config_parse_socket_listen(
+@@ -271,7 +254,8 @@ int config_parse_socket_listen(
+ 
+         s = (Socket*) data;
+ 
+-        if (!(p = new0(SocketPort, 1)))
++        p = new0(SocketPort, 1);
++        if (!p)
+                 return -ENOMEM;
+ 
+         if (streq(lvalue, "ListenFIFO")) {
+@@ -478,6 +462,7 @@ int config_parse_exec(
+         ExecCommand **e = data, *nce;
+         char *path, **n;
+         unsigned k;
++        int r;
+ 
+         assert(filename);
+         assert(lvalue);
+@@ -528,7 +513,8 @@ int config_parse_exec(
+                         k++;
+                 }
+ 
+-                if (!(n = new(char*, k + !honour_argv0)))
++                n = new(char*, k + !honour_argv0);
++                if (!n)
+                         return -ENOMEM;
+ 
+                 k = 0;
+@@ -538,11 +524,33 @@ int config_parse_exec(
+ 
+                         if (honour_argv0 && w == rvalue) {
+                                 assert(!path);
+-                                if (!(path = cunescape_length(w, l)))
++
++                                path = strndup(w, l);
++                                if (!path) {
++                                        r = -ENOMEM;
+                                         goto fail;
++                                }
++
++                                if (!utf8_is_valid(path)) {
++                                        log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
++                                        r = 0;
++                                        goto fail;
++                                }
++
+                         } else {
+-                                if (!(n[k++] = cunescape_length(w, l)))
++                                char *c;
++
++                                c = n[k++] = cunescape_length(w, l);
++                                if (!c) {
++                                        r = -ENOMEM;
+                                         goto fail;
++                                }
++
++                                if (!utf8_is_valid(c)) {
++                                        log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
++                                        r = 0;
++                                        goto fail;
++                                }
+                         }
+                 }
+ 
+@@ -550,19 +558,25 @@ int config_parse_exec(
+ 
+                 if (!n[0]) {
+                         log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
+-                        strv_free(n);
+-                        free(path);
+-                        return 0;
++                        r = 0;
++                        goto fail;
+                 }
+ 
+-                if (!path)
+-                        if (!(path = strdup(n[0])))
++                if (!path) {
++                        path = strdup(n[0]);
++                        if (!path) {
++                                r = -ENOMEM;
+                                 goto fail;
++                        }
++                }
+ 
+                 assert(path_is_absolute(path));
+ 
+-                if (!(nce = new0(ExecCommand, 1)))
++                nce = new0(ExecCommand, 1);
++                if (!nce) {
++                        r = -ENOMEM;
+                         goto fail;
++                }
+ 
+                 nce->argv = n;
+                 nce->path = path;
+@@ -583,7 +597,7 @@ fail:
+         free(path);
+         free(nce);
+ 
+-        return -ENOMEM;
++        return r;
+ }
+ 
+ DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
+diff --git a/src/service.c b/src/service.c
+index af83b6e..9005b02 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -37,6 +37,7 @@
+ #include "exit-status.h"
+ #include "def.h"
+ #include "util.h"
++#include "utf8.h"
+ 
+ #ifdef HAVE_SYSV_COMPAT
+ 
+@@ -3033,11 +3034,19 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
+         }
+ 
+         /* Interpret STATUS= */
+-        if ((e = strv_find_prefix(tags, "STATUS="))) {
++        e = strv_find_prefix(tags, "STATUS=");
++        if (e) {
+                 char *t;
+ 
+                 if (e[7]) {
+-                        if (!(t = strdup(e+7))) {
++
++                        if (!utf8_is_valid(e+7)) {
++                                log_warning("Status message in notification is not UTF-8 clean.");
++                                return;
++                        }
++
++                        t = strdup(e+7);
++                        if (!t) {
+                                 log_error("Failed to allocate string.");
+                                 return;
+                         }
+diff --git a/src/utf8.c b/src/utf8.c
+new file mode 100644
+index 0000000..11619dc
+--- /dev/null
++++ b/src/utf8.c
+@@ -0,0 +1,214 @@
++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
++
++/***
++  This file is part of systemd.
++
++  Copyright 2012 Lennart Poettering
++
++  systemd is free software; you can redistribute it and/or modify it
++  under the terms of the GNU General Public License as published by
++  the Free Software Foundation; either version 2 of the License, or
++  (at your option) any later version.
++
++  systemd is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++  General Public License for more details.
++
++  You should have received a copy of the GNU General Public License
++  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++***/
++
++/* This file is based on the GLIB utf8 validation functions. The
++ * original license text follows. */
++
++/* gutf8.c - Operations on UTF-8 strings.
++ *
++ * Copyright (C) 1999 Tom Tromey
++ * Copyright (C) 2000 Red Hat, Inc.
++ *
++ * This library 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 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#include <errno.h>
++#include <stdlib.h>
++#include <inttypes.h>
++#include <string.h>
++#include <stdbool.h>
++
++#include "utf8.h"
++
++#define FILTER_CHAR '_'
++
++static inline bool is_unicode_valid(uint32_t ch) {
++
++        if (ch >= 0x110000) /* End of unicode space */
++                return false;
++        if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
++                return false;
++        if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
++                return false;
++        if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
++                return false;
++
++        return true;
++}
++
++static inline bool is_continuation_char(uint8_t ch) {
++        if ((ch & 0xc0) != 0x80) /* 10xxxxxx */
++                return false;
++        return true;
++}
++
++static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) {
++        *u_ch <<= 6;
++        *u_ch |= ch & 0x3f;
++}
++
++static char* utf8_validate(const char *str, char *output) {
++        uint32_t val = 0;
++        uint32_t min = 0;
++        const uint8_t *p, *last;
++        int size;
++        uint8_t *o;
++
++        assert(str);
++
++        o = (uint8_t*) output;
++        for (p = (const uint8_t*) str; *p; p++) {
++                if (*p < 128) {
++                        if (o)
++                                *o = *p;
++                } else {
++                        last = p;
++
++                        if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
++                                size = 2;
++                                min = 128;
++                                val = (uint32_t) (*p & 0x1e);
++                                goto ONE_REMAINING;
++                        } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
++                                size = 3;
++                                min = (1 << 11);
++                                val = (uint32_t) (*p & 0x0f);
++                                goto TWO_REMAINING;
++                        } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
++                                size = 4;
++                                min = (1 << 16);
++                                val = (uint32_t) (*p & 0x07);
++                        } else
++                                goto error;
++
++                        p++;
++                        if (!is_continuation_char(*p))
++                                goto error;
++                        merge_continuation_char(&val, *p);
++
++                TWO_REMAINING:
++                        p++;
++                        if (!is_continuation_char(*p))
++                                goto error;
++                        merge_continuation_char(&val, *p);
++
++                ONE_REMAINING:
++                        p++;
++                        if (!is_continuation_char(*p))
++                                goto error;
++                        merge_continuation_char(&val, *p);
++
++                        if (val < min)
++                                goto error;
++
++                        if (!is_unicode_valid(val))
++                                goto error;
++
++                        if (o) {
++                                memcpy(o, last, (size_t) size);
++                                o += size;
++                        }
++
++                        continue;
++
++                error:
++                        if (o) {
++                                *o = FILTER_CHAR;
++                                p = last; /* We retry at the next character */
++                        } else
++                                goto failure;
++                }
++
++                if (o)
++                        o++;
++        }
++
++        if (o) {
++                *o = '\0';
++                return output;
++        }
++
++        return (char*) str;
++
++failure:
++        return NULL;
++}
++
++char* utf8_is_valid (const char *str) {
++        return utf8_validate(str, NULL);
++}
++
++char* utf8_filter (const char *str) {
++        char *new_str;
++
++        assert(str);
++
++        new_str = malloc(strlen(str) + 1);
++        if (!new_str)
++                return NULL;
++
++        return utf8_validate(str, new_str);
++}
++
++char *ascii_is_valid(const char *str) {
++        const char *p;
++
++        assert(str);
++
++        for (p = str; *p; p++)
++                if ((unsigned char) *p >= 128)
++                        return NULL;
++
++        return (char*) str;
++}
++
++char *ascii_filter(const char *str) {
++        char *r, *s, *d;
++        size_t l;
++
++        assert(str);
++
++        l = strlen(str);
++        r = malloc(l + 1);
++        if (!r)
++                return NULL;
++
++        for (s = r, d = r; *s; s++)
++                if ((unsigned char) *s < 128)
++                        *(d++) = *s;
++
++        *d = 0;
++
++        return r;
++}
+diff --git a/src/utf8.h b/src/utf8.h
+new file mode 100644
+index 0000000..9a72bec
+--- /dev/null
++++ b/src/utf8.h
+@@ -0,0 +1,33 @@
++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
++
++#ifndef fooutf8hfoo
++#define fooutf8hfoo
++
++/***
++  This file is part of systemd.
++
++  Copyright 2012 Lennart Poettering
++
++  systemd is free software; you can redistribute it and/or modify it
++  under the terms of the GNU General Public License as published by
++  the Free Software Foundation; either version 2 of the License, or
++  (at your option) any later version.
++
++  systemd is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++  General Public License for more details.
++
++  You should have received a copy of the GNU General Public License
++  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++***/
++
++#include "macro.h"
++
++char *utf8_is_valid(const char *s) _pure_;
++char *ascii_is_valid(const char *s) _pure_;
++
++char *utf8_filter(const char *s);
++char *ascii_filter(const char *s);
++
++#endif
+diff --git a/src/util.c b/src/util.c
+index 6a2c61f..0c9537e 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -1773,7 +1773,8 @@ char *cunescape_length(const char *s, size_t length) {
+ 
+         /* Undoes C style string escaping */
+ 
+-        if (!(r = new(char, length+1)))
++        r = new(char, length+1);
++        if (!r)
+                 return r;
+ 
+         for (f = s, t = r; f < s + length; f++) {
+@@ -1827,8 +1828,10 @@ char *cunescape_length(const char *s, size_t length) {
+                         /* hexadecimal encoding */
+                         int a, b;
+ 
+-                        if ((a = unhexchar(f[1])) < 0 ||
+-                            (b = unhexchar(f[2])) < 0) {
++                        a = unhexchar(f[1]);
++                        b = unhexchar(f[2]);
++
++                        if (a < 0 || b < 0) {
+                                 /* Invalid escape code, let's take it literal then */
+                                 *(t++) = '\\';
+                                 *(t++) = 'x';
+@@ -1851,9 +1854,11 @@ char *cunescape_length(const char *s, size_t length) {
+                         /* octal encoding */
+                         int a, b, c;
+ 
+-                        if ((a = unoctchar(f[0])) < 0 ||
+-                            (b = unoctchar(f[1])) < 0 ||
+-                            (c = unoctchar(f[2])) < 0) {
++                        a = unoctchar(f[0]);
++                        b = unoctchar(f[1]);
++                        c = unoctchar(f[2]);
++
++                        if (a < 0 || b < 0 || c < 0) {
+                                 /* Invalid escape code, let's take it literal then */
+                                 *(t++) = '\\';
+                                 *(t++) = f[0];
diff --git a/0164-util-add-brute-force-fallback-for-close_all_fds.patch b/0164-util-add-brute-force-fallback-for-close_all_fds.patch
new file mode 100644
index 0000000..1254056
--- /dev/null
+++ b/0164-util-add-brute-force-fallback-for-close_all_fds.patch
@@ -0,0 +1,91 @@
+From 9697feabd63b19b4cbcebb8e6a369eb99e684a65 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Tue, 13 Mar 2012 02:29:27 +0100
+Subject: [PATCH] util: add brute-force fallback for close_all_fds()
+
+If /proc is not available (i.e. in chroot envs) let's fall back to brute
+forcing our way through the fd table.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=784921
+(cherry picked from commit b19be9eb9e231ccf350e0e051b687fc425c61904)
+---
+ src/util.c |   54 ++++++++++++++++++++++++++++++++++++++----------------
+ 1 files changed, 38 insertions(+), 16 deletions(-)
+
+diff --git a/src/util.c b/src/util.c
+index 0c9537e..3a66c3b 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -2147,13 +2147,47 @@ int fd_cloexec(int fd, bool cloexec) {
+         return 0;
+ }
+ 
++static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
++        unsigned i;
++
++        assert(n_fdset == 0 || fdset);
++
++        for (i = 0; i < n_fdset; i++)
++                if (fdset[i] == fd)
++                        return true;
++
++        return false;
++}
++
+ int close_all_fds(const int except[], unsigned n_except) {
+         DIR *d;
+         struct dirent *de;
+         int r = 0;
+ 
+-        if (!(d = opendir("/proc/self/fd")))
+-                return -errno;
++        assert(n_except == 0 || except);
++
++        d = opendir("/proc/self/fd");
++        if (!d) {
++                int fd;
++                struct rlimit rl;
++
++                /* When /proc isn't available (for example in chroots)
++                 * the fallback is brute forcing through the fd
++                 * table */
++
++                assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
++                for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
++
++                        if (fd_in_set(fd, except, n_except))
++                                continue;
++
++                        if (close_nointr(fd) < 0)
++                                if (errno != EBADF && r == 0)
++                                        r = -errno;
++                }
++
++                return r;
++        }
+ 
+         while ((de = readdir(d))) {
+                 int fd = -1;
+@@ -2171,20 +2205,8 @@ int close_all_fds(const int except[], unsigned n_except) {
+                 if (fd == dirfd(d))
+                         continue;
+ 
+-                if (except) {
+-                        bool found;
+-                        unsigned i;
+-
+-                        found = false;
+-                        for (i = 0; i < n_except; i++)
+-                                if (except[i] == fd) {
+-                                        found = true;
+-                                        break;
+-                                }
+-
+-                        if (found)
+-                                continue;
+-                }
++                if (fd_in_set(fd, except, n_except))
++                        continue;
+ 
+                 if (close_nointr(fd) < 0) {
+                         /* Valgrind has its own FD and doesn't want to have it closed */
diff --git a/0165-conf-parser-warn-if-an-assignment-is-place-outside-o.patch b/0165-conf-parser-warn-if-an-assignment-is-place-outside-o.patch
new file mode 100644
index 0000000..f0b56ec
--- /dev/null
+++ b/0165-conf-parser-warn-if-an-assignment-is-place-outside-o.patch
@@ -0,0 +1,31 @@
+From 0bf243e9c639dba0a80ce2ce50c8a7a97b7a8874 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Tue, 13 Mar 2012 02:41:29 +0100
+Subject: [PATCH] conf-parser: warn if an assignment is place outside of a
+ section
+
+https://bugzilla.redhat.com/show_bug.cgi?id=783134
+(cherry picked from commit 62f168a05b5a0b81a75a50791b80ae700dd00afb)
+---
+ src/conf-parser.c |    7 ++++++-
+ 1 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/src/conf-parser.c b/src/conf-parser.c
+index 9edf637..5561ae2 100644
+--- a/src/conf-parser.c
++++ b/src/conf-parser.c
+@@ -219,8 +219,13 @@ static int parse_line(
+                 return 0;
+         }
+ 
+-        if (sections && !*section)
++        if (sections && !*section) {
++
++                if (!relaxed)
++                        log_info("[%s:%u] Assignment outside of section. Ignoring.", filename, line);
++
+                 return 0;
++        }
+ 
+         e = strchr(l, '=');
+         if (!e) {
diff --git a/0166-mount-fix-assertion.patch b/0166-mount-fix-assertion.patch
new file mode 100644
index 0000000..75fee51
--- /dev/null
+++ b/0166-mount-fix-assertion.patch
@@ -0,0 +1,33 @@
+From a3e4e804ea93df6011a367a88190e2cb6174de9a Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Tue, 13 Mar 2012 03:34:42 +0100
+Subject: [PATCH] mount: fix assertion
+
+https://bugzilla.redhat.com/show_bug.cgi?id=768523
+(cherry picked from commit 9631c090fd61070797f3a6139f873a3cabc5d28a)
+---
+ src/mount.c |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/mount.c b/src/mount.c
+index ccf1e9c..bac3ad3 100644
+--- a/src/mount.c
++++ b/src/mount.c
+@@ -189,7 +189,7 @@ static int mount_add_mount_links(Mount *m) {
+                                 if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
+                                         return r;
+ 
+-                } else if (pm && path_startswith(pm->what, n->where)) {
++                } else if (pm && pm->what && path_startswith(pm->what, n->where)) {
+ 
+                         if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
+                                 return r;
+@@ -197,7 +197,7 @@ static int mount_add_mount_links(Mount *m) {
+                         if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
+                                 return r;
+ 
+-                } else if (pn && path_startswith(pn->what, m->where)) {
++                } else if (pn && pn->what && path_startswith(pn->what, m->where)) {
+ 
+                         if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
+                                 return r;
diff --git a/0167-socket-make-sure-that-the-name-for-per-connection-se.patch b/0167-socket-make-sure-that-the-name-for-per-connection-se.patch
new file mode 100644
index 0000000..62f670d
--- /dev/null
+++ b/0167-socket-make-sure-that-the-name-for-per-connection-se.patch
@@ -0,0 +1,51 @@
+From 2216ee3d049dda5d1a12fec5b862b101de355d43 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 14 Mar 2012 03:07:26 +0100
+Subject: [PATCH] socket: make sure that the name for per-connection services
+ are unique
+
+If a client connects to us repeatedly always using the same source port
+and we instantiate a service for the incoming connection this might
+clash with an old instance. Hence, include the connection number, the
+same way we do it for AF_UNIX to make connections unique.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=45297
+(cherry picked from commit 77b088c211a0939cb94969b487e5746bb05d12ae)
+---
+ src/socket.c |    9 ++++++---
+ 1 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/socket.c b/src/socket.c
+index b40b7a1..22e88b6 100644
+--- a/src/socket.c
++++ b/src/socket.c
+@@ -560,7 +560,8 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
+                         b = ntohl(remote.in.sin_addr.s_addr);
+ 
+                 if (asprintf(&r,
+-                             "%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
++                             "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
++                             nr,
+                              a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
+                              ntohs(local.in.sin_port),
+                              b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF,
+@@ -582,7 +583,8 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
+                                 *b = remote.in6.sin6_addr.s6_addr+12;
+ 
+                         if (asprintf(&r,
+-                                     "%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
++                                     "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
++                                     nr,
+                                      a[0], a[1], a[2], a[3],
+                                      ntohs(local.in6.sin6_port),
+                                      b[0], b[1], b[2], b[3],
+@@ -592,7 +594,8 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
+                         char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN];
+ 
+                         if (asprintf(&r,
+-                                     "%s:%u-%s:%u",
++                                     "%u-%s:%u-%s:%u",
++                                     nr,
+                                      inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)),
+                                      ntohs(local.in6.sin6_port),
+                                      inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)),
diff --git a/0168-man-document-where-we-read-kernel-cmdline-options-fr.patch b/0168-man-document-where-we-read-kernel-cmdline-options-fr.patch
new file mode 100644
index 0000000..5961688
--- /dev/null
+++ b/0168-man-document-where-we-read-kernel-cmdline-options-fr.patch
@@ -0,0 +1,33 @@
+From c0aa995c459ff01a2299bc5dc9a303b923f978c8 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 14 Mar 2012 14:13:12 +0100
+Subject: [PATCH] man: document where we read kernel cmdline options from
+ (cherry picked from commit
+ 45dc3a0478c61e83dedf26dc247fd3ddd2b20978)
+
+---
+ man/systemd.xml |   11 ++++++++++-
+ 1 files changed, 10 insertions(+), 1 deletions(-)
+
+diff --git a/man/systemd.xml b/man/systemd.xml
+index c1766e2..b1f57e3 100644
+--- a/man/systemd.xml
++++ b/man/systemd.xml
+@@ -948,7 +948,16 @@
+         <refsect1>
+                 <title>Kernel Command Line</title>
+ 
+-                <para>When run as system instance systemd parses a few kernel command line arguments:</para>
++                <para>When run as system instance systemd parses a
++                number of kernel command line
++                arguments<footnote><para>If run inside a Linux
++                container these arguments may be passed as command
++                line arguments to systemd itself, next to any of the
++                command line options listed in the Options section
++                above. If run outside of Linux containers, these
++                arguments are parsed from
++                <filename>/proc/cmdline</filename>
++                instead.</para></footnote>:</para>
+ 
+                 <variablelist>
+                         <varlistentry>
diff --git a/0169-nspawn-mount-etc-timezone-into-nspawn-environment-to.patch b/0169-nspawn-mount-etc-timezone-into-nspawn-environment-to.patch
new file mode 100644
index 0000000..caddd97
--- /dev/null
+++ b/0169-nspawn-mount-etc-timezone-into-nspawn-environment-to.patch
@@ -0,0 +1,39 @@
+From 5b283222a8834b3bfec59cac21c743d97e4a4a6d Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Thu, 15 Mar 2012 00:45:02 +0100
+Subject: [PATCH] nspawn: mount /etc/timezone into nspawn environment too
+ (cherry picked from commit
+ 4d1c38b8072dca18807371170d5e14fa8dc0baa5)
+
+---
+ src/nspawn.c |   10 +++++++++-
+ 1 files changed, 9 insertions(+), 1 deletions(-)
+
+diff --git a/src/nspawn.c b/src/nspawn.c
+index 52b4aa8..97efcd1 100644
+--- a/src/nspawn.c
++++ b/src/nspawn.c
+@@ -196,7 +196,7 @@ static int mount_all(const char *dest) {
+         }
+ 
+         /* Fix the timezone, if possible */
+-        if (asprintf(&where, "%s/%s", dest, "/etc/localtime") >= 0) {
++        if (asprintf(&where, "%s/etc/localtime", dest) >= 0) {
+ 
+                 if (mount("/etc/localtime", where, "bind", MS_BIND, NULL) >= 0)
+                         mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
+@@ -204,6 +204,14 @@ static int mount_all(const char *dest) {
+                 free(where);
+         }
+ 
++        if (asprintf(&where, "%s/etc/timezone", dest) >= 0) {
++
++                if (mount("/etc/timezone", where, "bind", MS_BIND, NULL) >= 0)
++                        mount("/etc/timezone", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
++
++                free(where);
++        }
++
+         return r;
+ }
+ 
diff --git a/systemd.spec b/systemd.spec
index bcc7915..d681e94 100644
--- a/systemd.spec
+++ b/systemd.spec
@@ -2,7 +2,7 @@ Name:           systemd
 Url:            http://www.freedesktop.org/wiki/Software/systemd
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Version:        37
-Release:        17%{?dist}
+Release:        18%{?dist}
 License:        GPLv2+
 Group:          System Environment/Base
 Summary:        A System and Service Manager
@@ -214,6 +214,14 @@ Patch0158:      0158-nspawn-be-less-cryptic-when-clone-fails.patch
 Patch0159:      0159-bash-completion-get-rid-of-awk-sed-and-grep.patch
 Patch0160:      0160-mount-properly-check-return-for-mount_add_.patch
 Patch0161:      0161-util-never-follow-symlinks-in-rm_rf_children.patch
+Patch0162:      0162-man-reword-tmpfiles-selinux-bits.patch
+Patch0163:      0163-conf-enforce-UTF8-validty-everywhere.patch
+Patch0164:      0164-util-add-brute-force-fallback-for-close_all_fds.patch
+Patch0165:      0165-conf-parser-warn-if-an-assignment-is-place-outside-o.patch
+Patch0166:      0166-mount-fix-assertion.patch
+Patch0167:      0167-socket-make-sure-that-the-name-for-per-connection-se.patch
+Patch0168:      0168-man-document-where-we-read-kernel-cmdline-options-fr.patch
+Patch0169:      0169-nspawn-mount-etc-timezone-into-nspawn-environment-to.patch
 
 # For sysvinit tools
 Obsoletes:      SysVinit < 2.86-24, sysvinit < 2.86-24
@@ -535,6 +543,15 @@ fi
 %{_bindir}/systemd-sysv-convert
 
 %changelog
+* Tue Mar 20 2012 Michal Schmidt <mschmidt at redhat.com> - 37-18
+- enforce UTF8 validity of configuration data to avoid crashing in dbus
+- util: add brute-force fallback for close_all_fds() (#784921)
+- conf-parser: warn if an assignment is place outside of a section (#783134)
+- mount: fix assertion (#768523)
+- make sure that the name for per-connection services are unique (fdo#45297)
+- nspawn: mount /etc/timezone into nspawn environment too
+- minor documentation fixes
+
 * Fri Mar 16 2012 Michal Schmidt <mschmidt at redhat.com> - 37-17
 - CVE-2012-1174 (#804118)
 


More information about the scm-commits mailing list