From: Zbigniew Jędrzejewski-Szmek Date: Mon, 31 Jul 2017 06:05:35 +0000 (-0400) Subject: core: properly handle deserialization of unknown unit types (#6476) X-Git-Tag: v235~288 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0742986650b36b604613f9aaa1f6bd45b51c0e67;p=thirdparty%2Fsystemd.git core: properly handle deserialization of unknown unit types (#6476) We just abort startup, without printing any error. Make sure we always print something, and when we cannot deserialize some unit, just ignore it and continue. Fixup for 4bc5d27b942afa83cc3d95debd2ad48d42ac07a8. Without this, we would hang in daemon-reexec after upgrade. --- diff --git a/src/core/manager.c b/src/core/manager.c index d29acf500fd..1aadb7076ef 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1343,8 +1343,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { dual_timestamp_get(&m->units_load_finish_timestamp); /* Second, deserialize if there is something to deserialize */ - if (serialization) + if (serialization) { r = manager_deserialize(m, serialization, fds); + if (r < 0) + log_error_errno(r, "Deserialization failed: %m"); + } /* Any fds left? Find some unit which wants them. This is * useful to allow container managers to pass some file @@ -2779,6 +2782,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { for (;;) { Unit *u; char name[UNIT_NAME_MAX+2]; + const char* unit_name; /* Start marker */ if (!fgets(name, sizeof(name), f)) { @@ -2791,14 +2795,23 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { } char_array_0(name); + unit_name = strstrip(name); - r = manager_load_unit(m, strstrip(name), NULL, NULL, &u); - if (r < 0) - goto finish; + r = manager_load_unit(m, unit_name, NULL, NULL, &u); + if (r < 0) { + log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name); + if (r == -ENOMEM) + goto finish; + unit_deserialize_skip(f); + continue; + } r = unit_deserialize(u, f, fds); - if (r < 0) - goto finish; + if (r < 0) { + log_notice_errno(r, "Failed to deserialize unit \"%s\": %m", unit_name); + if (r == -ENOMEM) + goto finish; + } } finish: @@ -2871,8 +2884,12 @@ int manager_reload(Manager *m) { /* Second, deserialize our stored data */ q = manager_deserialize(m, f, fds); - if (q < 0 && r >= 0) - r = q; + if (q < 0) { + log_error_errno(q, "Deserialization failed: %m"); + + if (r >= 0) + r = q; + } fclose(f); f = NULL; diff --git a/src/core/unit.c b/src/core/unit.c index 394832e8ba5..a42c667754a 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3111,6 +3111,27 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { return 0; } +void unit_deserialize_skip(FILE *f) { + assert(f); + + /* Skip serialized data for this unit. We don't know what it is. */ + + for (;;) { + char line[LINE_MAX], *l; + + if (!fgets(line, sizeof line, f)) + return; + + char_array_0(line); + l = strstrip(line); + + /* End marker */ + if (isempty(l)) + return; + } +} + + int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) { Unit *device; _cleanup_free_ char *e = NULL; diff --git a/src/core/unit.h b/src/core/unit.h index 5ecaba11e90..a384f264ee4 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -563,6 +563,7 @@ bool unit_can_serialize(Unit *u) _pure_; int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs); int unit_deserialize(Unit *u, FILE *f, FDSet *fds); +void unit_deserialize_skip(FILE *f); int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value); int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);