Commit 3998a823 authored by Chris Coulson's avatar Chris Coulson Committed by Simon McVittie
Browse files

Import Debian changes 237-3ubuntu10.19

systemd (237-3ubuntu10.19) bionic-security; urgency=medium

  * SECURITY UDPATE: Unsafe environment usage in pam_systemd.so leads to
    incorrect Policykit authorization
    - debian/patches/CVE-2019-3842.patch: Use secure_getenv() rather than
      getenv() in pam_systemd.c
    - CVE-2019-3842

systemd (237-3ubuntu10.17) bionic; urgency=medium

  [ Michael Vogt ]
  * d/p/Support-system-image-read-only-etc.patch:
    - re-add support for /etc/writable for core18 (LP: #1778936)
  * d/p/fix-race-daemon-reload-8803.patch:
    - backport systemd upstream PR#8803 and PR#11121 to fix race
      when doing systemctl and systemctl daemon-reload at the
      same time LP: #1819728

  [ Balint Reczey ]
   * d/p/virt-detect-WSL-environment-as-a-container.patch:
     - virt: detect WSL environment as a container (LP: #1816753)

systemd (237-3ubuntu10.16) bionic; urgency=medium

  * d/p/Support-system-image-read-only-etc.patch:
    - re-add support for /etc/writable for core18 (LP: #1778936)
  * d/p/fix-race-daemon-reload-8803.patch:
    - backport systemd upstream PR#8803 to fix race when doing
      systemctl and systemctl daemon-reload at the same time
      LP: #1819728
parent b9844d1f
systemd (237-3ubuntu10.19) bionic-security; urgency=medium
* SECURITY UDPATE: Unsafe environment usage in pam_systemd.so leads to
incorrect Policykit authorization
- debian/patches/CVE-2019-3842.patch: Use secure_getenv() rather than
getenv() in pam_systemd.c
- CVE-2019-3842
-- Chris Coulson <chris.coulson@canonical.com> Fri, 29 Mar 2019 16:40:26 +0000
systemd (237-3ubuntu10.17) bionic; urgency=medium
[ Michael Vogt ]
* d/p/Support-system-image-read-only-etc.patch:
- re-add support for /etc/writable for core18 (LP: #1778936)
* d/p/fix-race-daemon-reload-8803.patch:
- backport systemd upstream PR#8803 and PR#11121 to fix race
when doing systemctl and systemctl daemon-reload at the
same time LP: #1819728
[ Balint Reczey ]
* d/p/virt-detect-WSL-environment-as-a-container.patch:
- virt: detect WSL environment as a container (LP: #1816753)
-- Michael Vogt <michael.vogt@ubuntu.com> Mon, 18 Mar 2019 08:40:44 +0100
systemd (237-3ubuntu10.16) bionic; urgency=medium
* d/p/Support-system-image-read-only-etc.patch:
- re-add support for /etc/writable for core18 (LP: #1778936)
* d/p/fix-race-daemon-reload-8803.patch:
- backport systemd upstream PR#8803 to fix race when doing
systemctl and systemctl daemon-reload at the same time
LP: #1819728
-- Michael Vogt <michael.vogt@ubuntu.com> Wed, 13 Mar 2019 07:42:11 +0100
systemd (237-3ubuntu10.15) bionic; urgency=medium
[ Victor Tapia ]
......
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -354,27 +354,27 @@
seat = pam_getenv(handle, "XDG_SEAT");
if (isempty(seat))
- seat = getenv("XDG_SEAT");
+ seat = secure_getenv("XDG_SEAT");
cvtnr = pam_getenv(handle, "XDG_VTNR");
if (isempty(cvtnr))
- cvtnr = getenv("XDG_VTNR");
+ cvtnr = secure_getenv("XDG_VTNR");
type = pam_getenv(handle, "XDG_SESSION_TYPE");
if (isempty(type))
- type = getenv("XDG_SESSION_TYPE");
+ type = secure_getenv("XDG_SESSION_TYPE");
if (isempty(type))
type = type_pam;
class = pam_getenv(handle, "XDG_SESSION_CLASS");
if (isempty(class))
- class = getenv("XDG_SESSION_CLASS");
+ class = secure_getenv("XDG_SESSION_CLASS");
if (isempty(class))
class = class_pam;
desktop = pam_getenv(handle, "XDG_SESSION_DESKTOP");
if (isempty(desktop))
- desktop = getenv("XDG_SESSION_DESKTOP");
+ desktop = secure_getenv("XDG_SESSION_DESKTOP");
tty = strempty(tty);
From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Sat, 26 Apr 2014 23:49:32 +0200
Subject: Support system-image read-only /etc
On Ubuntu Phone with readonly /etc we symlink
/etc/{adjtime,localtime,timezone,hostname,machine-info} to /etc/writable/, so
we need to update those files instead if the original files are symlinks into
/etc/writable/.
Forwarded: OMGno, this is a rather nasty hack until we fix system-image to get a writable /etc
Bug-Ubuntu: https://launchpad.net/bugs/1227520
---
src/hostname/hostnamed.c | 28 ++++++++++++++++++++++++----
src/timedate/timedated.c | 31 +++++++++++++++++++++++++------
2 files changed, 49 insertions(+), 10 deletions(-)
Index: systemd-237/src/hostname/hostnamed.c
===================================================================
--- systemd-237.orig/src/hostname/hostnamed.c
+++ systemd-237/src/hostname/hostnamed.c
@@ -31,6 +31,7 @@
#include "hostname-util.h"
#include "parse-util.h"
#include "path-util.h"
+#include "fs-util.h"
#include "selinux-util.h"
#include "strv.h"
#include "user-util.h"
@@ -76,6 +77,25 @@ static void context_free(Context *c) {
bus_verify_polkit_async_registry_free(c->polkit_registry);
}
+/* Hack for Ubuntu phone: check if path is an existing symlink to
+ * /etc/writable; if it is, update that instead */
+static const char* writable_filename(const char *path) {
+ ssize_t r;
+ static char realfile_buf[PATH_MAX];
+ _cleanup_free_ char *realfile = NULL;
+ const char *result = path;
+ int orig_errno = errno;
+
+ r = readlink_and_make_absolute(path, &realfile);
+ if (r >= 0 && startswith(realfile, "/etc/writable")) {
+ snprintf(realfile_buf, sizeof(realfile_buf), "%s", realfile);
+ result = realfile_buf;
+ }
+
+ errno = orig_errno;
+ return result;
+}
+
static int context_read_data(Context *c) {
int r;
struct utsname u;
@@ -303,12 +323,12 @@ static int context_write_data_static_hos
if (isempty(c->data[PROP_STATIC_HOSTNAME])) {
- if (unlink("/etc/hostname") < 0)
+ if (unlink(writable_filename("/etc/hostname")) < 0)
return errno == ENOENT ? 0 : -errno;
return 0;
}
- return write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
+ return write_string_file_atomic_label(writable_filename("/etc/hostname"), c->data[PROP_STATIC_HOSTNAME]);
}
static int context_write_data_machine_info(Context *c) {
@@ -354,13 +374,13 @@ static int context_write_data_machine_in
}
if (strv_isempty(l)) {
- if (unlink("/etc/machine-info") < 0)
+ if (unlink(writable_filename("/etc/machine-info")) < 0)
return errno == ENOENT ? 0 : -errno;
return 0;
}
- return write_env_file_label("/etc/machine-info", l);
+ return write_env_file_label(writable_filename("/etc/machine-info"), l);
}
static int property_get_icon_name(
Index: systemd-237/src/timedate/timedated.c
===================================================================
--- systemd-237.orig/src/timedate/timedated.c
+++ systemd-237/src/timedate/timedated.c
@@ -82,6 +82,25 @@ static int context_read_data(Context *c)
return 0;
}
+/* Hack for Ubuntu phone: check if path is an existing symlink to
+ * /etc/writable; if it is, update that instead */
+static const char* writable_filename(const char *path) {
+ ssize_t r;
+ static char realfile_buf[PATH_MAX];
+ _cleanup_free_ char *realfile = NULL;
+ const char *result = path;
+ int orig_errno = errno;
+
+ r = readlink_and_make_absolute(path, &realfile);
+ if (r >= 0 && startswith(realfile, "/etc/writable")) {
+ snprintf(realfile_buf, sizeof(realfile_buf), "%s", realfile);
+ result = realfile_buf;
+ }
+
+ errno = orig_errno;
+ return result;
+}
+
static int context_write_data_timezone(Context *c) {
_cleanup_free_ char *p = NULL;
int r = 0;
@@ -90,10 +109,10 @@ static int context_write_data_timezone(C
assert(c);
if (isempty(c->zone)) {
- if (unlink("/etc/localtime") < 0 && errno != ENOENT)
+ if (unlink(writable_filename("/etc/localtime")) < 0 && errno != ENOENT)
r = -errno;
- if (unlink("/etc/timezone") < 0 && errno != ENOENT)
+ if (unlink(writable_filename("/etc/timezone")) < 0 && errno != ENOENT)
r = -errno;
return r;
@@ -103,12 +122,12 @@ static int context_write_data_timezone(C
if (!p)
return log_oom();
- r = symlink_atomic(p, "/etc/localtime");
+ r = symlink_atomic(p, writable_filename("/etc/localtime"));
if (r < 0)
return r;
- if (stat("/etc/timezone", &st) == 0 && S_ISREG(st.st_mode)) {
- r = write_string_file("/etc/timezone", c->zone, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+ if (stat(writable_filename("/etc/timezone"), &st) == 0 && S_ISREG(st.st_mode)) {
+ r = write_string_file(writable_filename("/etc/timezone"), c->zone, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
if (r < 0)
return r;
}
@@ -174,7 +193,7 @@ static int context_write_data_local_rtc(
*(char*) mempcpy(stpcpy(stpcpy(mempcpy(w, s, a), prepend), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
if (streq(w, NULL_ADJTIME_UTC)) {
- if (unlink("/etc/adjtime") < 0)
+ if (unlink(writable_filename("/etc/adjtime")) < 0)
if (errno != ENOENT)
return -errno;
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Mon, 18 Mar 2019 08:30:41 +0100
Subject: Backport daemon reload race fix (PR#11121)
There is a race in the systemd code when daemon-reload happens
in parallel with other systemctl operations (like start/stop).
Upstream fixed this first in PR#8803 but the fix is incomplete
and sometimes causes a segfault (see systemd issue #10716).
The full fix is in PR#11121 and this patch first applied #8803
and then PR #11121 on top.
Index: systemd-237/src/core/job.c
===================================================================
--- systemd-237.orig/src/core/job.c
+++ systemd-237/src/core/job.c
@@ -78,7 +78,7 @@ Job* job_new(Unit *unit, JobType type) {
return j;
}
-void job_free(Job *j) {
+void job_unlink(Job *j) {
assert(j);
assert(!j->installed);
assert(!j->transaction_prev);
@@ -86,21 +86,38 @@ void job_free(Job *j) {
assert(!j->subject_list);
assert(!j->object_list);
- if (j->in_run_queue)
+ if (j->in_run_queue) {
LIST_REMOVE(run_queue, j->manager->run_queue, j);
+ j->in_run_queue = false;
+ }
- if (j->in_dbus_queue)
+ if (j->in_dbus_queue) {
LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
+ j->in_dbus_queue = false;
+ }
- if (j->in_gc_queue)
+ if (j->in_gc_queue) {
LIST_REMOVE(gc_queue, j->manager->gc_job_queue, j);
+ j->in_gc_queue = false;
+ }
- sd_event_source_unref(j->timer_event_source);
+ j->timer_event_source = sd_event_source_unref(j->timer_event_source);
+}
+
+Job* job_free(Job *j) {
+ assert(j);
+ assert(!j->installed);
+ assert(!j->transaction_prev);
+ assert(!j->transaction_next);
+ assert(!j->subject_list);
+ assert(!j->object_list);
+
+ job_unlink(j);
sd_bus_track_unref(j->bus_track);
strv_free(j->deserialized_clients);
- free(j);
+ return mfree(j);
}
static void job_set_state(Job *j, JobState state) {
@@ -149,7 +166,7 @@ void job_uninstall(Job *j) {
unit_add_to_gc_queue(j->unit);
- hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
+ hashmap_remove_value(j->manager->jobs, UINT32_TO_PTR(j->id), j);
j->installed = false;
}
@@ -239,6 +256,7 @@ Job* job_install(Job *j) {
int job_install_deserialized(Job *j) {
Job **pj;
+ int r;
assert(!j->installed);
@@ -248,10 +266,15 @@ int job_install_deserialized(Job *j) {
}
pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
- if (*pj) {
- log_unit_debug(j->unit, "Unit already has a job installed. Not installing deserialized job.");
- return -EEXIST;
- }
+ if (*pj)
+ return log_unit_debug_errno(j->unit, EEXIST,
+ "Unit already has a job installed. Not installing deserialized job.");
+
+ r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j);
+ if (r == -EEXIST)
+ return log_unit_debug_errno(j->unit, r, "Job ID %" PRIu32 " already used, cannot deserialize job.", j->id);
+ if (r < 0)
+ return log_unit_debug_errno(j->unit, r, "Failed to insert job into jobs hash table: %m");
*pj = j;
j->installed = true;
Index: systemd-237/src/core/job.h
===================================================================
--- systemd-237.orig/src/core/job.h
+++ systemd-237/src/core/job.h
@@ -178,7 +178,8 @@ struct Job {
Job* job_new(Unit *unit, JobType type);
Job* job_new_raw(Unit *unit);
-void job_free(Job *job);
+void job_unlink(Job *job);
+Job* job_free(Job *job);
Job* job_install(Job *j);
int job_install_deserialized(Job *j);
void job_uninstall(Job *j);
@@ -239,6 +240,8 @@ void job_add_to_gc_queue(Job *j);
int job_get_before(Job *j, Job*** ret);
int job_get_after(Job *j, Job*** ret);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Job*, job_free);
+
const char* job_type_to_string(JobType t) _const_;
JobType job_type_from_string(const char *s) _pure_;
Index: systemd-237/src/core/unit.c
===================================================================
--- systemd-237.orig/src/core/unit.c
+++ systemd-237/src/core/unit.c
@@ -2325,9 +2325,77 @@ static void unit_update_on_console(Unit
}
+static bool unit_process_job(Job *j, UnitActiveState ns, bool reload_success) {
+ bool unexpected = false;
+
+ assert(j);
+
+ if (j->state == JOB_WAITING)
+
+ /* So we reached a different state for this
+ * job. Let's see if we can run it now if it
+ * failed previously due to EAGAIN. */
+ job_add_to_run_queue(j);
+
+ /* Let's check whether this state change constitutes a
+ * finished job, or maybe contradicts a running job and
+ * hence needs to invalidate jobs. */
+
+ switch (j->type) {
+
+ case JOB_START:
+ case JOB_VERIFY_ACTIVE:
+
+ if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
+ job_finish_and_invalidate(j, JOB_DONE, true, false);
+ else if (j->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
+ unexpected = true;
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns))
+ job_finish_and_invalidate(j, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
+ }
+
+ break;
+
+ case JOB_RELOAD:
+ case JOB_RELOAD_OR_START:
+ case JOB_TRY_RELOAD:
+
+ if (j->state == JOB_RUNNING) {
+ if (ns == UNIT_ACTIVE)
+ job_finish_and_invalidate(j, reload_success ? JOB_DONE : JOB_FAILED, true, false);
+ else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)) {
+ unexpected = true;
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns))
+ job_finish_and_invalidate(j, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
+ }
+ }
+
+ break;
+
+ case JOB_STOP:
+ case JOB_RESTART:
+ case JOB_TRY_RESTART:
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns))
+ job_finish_and_invalidate(j, JOB_DONE, true, false);
+ else if (j->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
+ unexpected = true;
+ job_finish_and_invalidate(j, JOB_FAILED, true, false);
+ }
+
+ break;
+
+ default:
+ assert_not_reached("Job type unknown");
+ }
+
+ return unexpected;
+}
+
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
Manager *m;
- bool unexpected;
assert(u);
assert(os < _UNIT_ACTIVE_STATE_MAX);
@@ -2367,74 +2435,18 @@ void unit_notify(Unit *u, UnitActiveStat
unit_update_on_console(u);
- if (u->job) {
- unexpected = false;
-
- if (u->job->state == JOB_WAITING)
-
- /* So we reached a different state for this
- * job. Let's see if we can run it now if it
- * failed previously due to EAGAIN. */
- job_add_to_run_queue(u->job);
-
- /* Let's check whether this state change constitutes a
- * finished job, or maybe contradicts a running job and
- * hence needs to invalidate jobs. */
-
- switch (u->job->type) {
-
- case JOB_START:
- case JOB_VERIFY_ACTIVE:
-
- if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
- job_finish_and_invalidate(u->job, JOB_DONE, true, false);
- else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
- unexpected = true;
-
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
- }
-
- break;
-
- case JOB_RELOAD:
- case JOB_RELOAD_OR_START:
- case JOB_TRY_RELOAD:
-
- if (u->job->state == JOB_RUNNING) {
- if (ns == UNIT_ACTIVE)
- job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true, false);
- else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)) {
- unexpected = true;
-
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
- }
- }
-
- break;
-
- case JOB_STOP:
- case JOB_RESTART:
- case JOB_TRY_RESTART:
-
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, JOB_DONE, true, false);
- else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
- unexpected = true;
- job_finish_and_invalidate(u->job, JOB_FAILED, true, false);
- }
-
- break;
+ if (!MANAGER_IS_RELOADING(m)) {
+ bool unexpected;
- default:
- assert_not_reached("Job type unknown");
- }
+ /* Let's propagate state changes to the job */
+ if (u->job)
+ unexpected = unit_process_job(u->job, ns, reload_success);
+ else
+ unexpected = true;
- } else
- unexpected = true;
-
- if (!MANAGER_IS_RELOADING(m)) {
+ /* If this state change happened without being requested by a job, then let's retroactively start or
+ * stop dependencies. We skip that step when deserializing, since we don't want to create any
+ * additional jobs just because something is already activated. */
/* If this state change happened without being
* requested by a job, then let's retroactively start
@@ -3332,6 +3344,29 @@ void unit_serialize_item_format(Unit *u,
fputc('\n', f);
}
+static int unit_deserialize_job(Unit *u, FILE *f) {
+ _cleanup_(job_freep) Job *j = NULL;
+ int r;
+
+ assert(u);
+ assert(f);
+
+ j = job_new_raw(u);
+ if (!j)
+ return log_oom();
+
+ r = job_deserialize(j, f);
+ if (r < 0)
+ return r;
+
+ r = job_install_deserialized(j);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(j);
+ return 0;
+}
+
int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
ExecRuntime **rt = NULL;
size_t offset;
@@ -3371,32 +3406,11 @@ int unit_deserialize(Unit *u, FILE *f, F
if (streq(l, "job")) {
if (v[0] == '\0') {
- /* new-style serialized job */
- Job *j;
-
- j = job_new_raw(u);
- if (!j)
- return log_oom();
-
- r = job_deserialize(j, f);
- if (r < 0) {
- job_free(j);
- return r;
- }
-
- r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j);
- if (r < 0) {
- job_free(j);
- return r;
- }
-
- r = job_install_deserialized(j);
- if (r < 0) {
- hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id));
- job_free(j);
+ /* New-style serialized job */
+ r = unit_deserialize_job(u, f);
+ if (r < 0)
return r;
- }
- } else /* legacy for pre-44 */
+ } else /* Legacy for pre-44 */
log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v);
continue;
} else if (streq(l, "state-change-timestamp")) {
......@@ -97,3 +97,7 @@ CVE-2019-6454.patch
sd-bus-if-we-receive-an-invalid-dbus-message-ignore-.patch
journal-do-not-remove-multiple-spaces-after-identifi.patch
stop-mount-error-propagation.patch
Support-system-image-read-only-etc.patch
fix-race-daemon-reload-11121.patch
virt-detect-WSL-environment-as-a-container-id-wsl.patch
CVE-2019-3842.patch
From: Balint Reczey <balint.reczey@canonical.com>
Date: Wed, 6 Mar 2019 18:46:04 +0100
Subject: virt: detect WSL environment as a container (id: wsl)
---
man/systemd-detect-virt.xml | 13 ++++++++++++-
man/systemd.unit.xml | 3 ++-
src/basic/virt.c | 12 ++++++++++++
src/basic/virt.h | 1 +
4 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml
index 4426827..c92ea8d 100644
--- a/man/systemd-detect-virt.xml
+++ b/man/systemd-detect-virt.xml
@@ -149,7 +149,7 @@
</row>
<row>