core: rework serialization

Let's be more careful with what we serialize: let's ensure we never
serialize strings that are longer than LONG_LINE_MAX, so that we know we
can read them back with read_line(…, LONG_LINE_MAX, …) safely.

In order to implement this all serialization functions are move to
serialize.[ch], and internally will do line size checks. We'd rather
skip a serialization line (with a loud warning) than write an overly
long line out. Of course, this is just a second level protection, after
all the data we serialize shouldn't be this long in the first place.

While we are at it also clean up logging: while serializing make sure to
always log about errors immediately. Also, (void)ify all calls we don't
expect errors in (or catch errors as part of the general
fflush_and_check() at the end.
This commit is contained in:
Lennart Poettering
2018-10-26 10:52:41 +02:00
parent cdd620e346
commit d68c645bd3
31 changed files with 519 additions and 462 deletions
+11 -17
View File
@@ -9,6 +9,7 @@
#include "fs-util.h"
#include "parse-util.h"
#include "random-util.h"
#include "serialize.h"
#include "special.h"
#include "string-table.h"
#include "string-util.h"
@@ -661,21 +662,20 @@ static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
assert(f);
assert(fds);
unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
(void) serialize_item(f, "state", timer_state_to_string(t->state));
(void) serialize_item(f, "result", timer_result_to_string(t->result));
if (t->last_trigger.realtime > 0)
unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
(void) serialize_usec(f, "last-trigger-realtime", t->last_trigger.realtime);
if (t->last_trigger.monotonic > 0)
unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
(void) serialize_usec(f, "last-trigger-monotonic", t->last_trigger.monotonic);
return 0;
}
static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Timer *t = TIMER(u);
int r;
assert(u);
assert(key);
@@ -690,6 +690,7 @@ static int timer_deserialize_item(Unit *u, const char *key, const char *value, F
log_unit_debug(u, "Failed to parse state value: %s", value);
else
t->deserialized_state = state;
} else if (streq(key, "result")) {
TimerResult f;
@@ -698,19 +699,12 @@ static int timer_deserialize_item(Unit *u, const char *key, const char *value, F
log_unit_debug(u, "Failed to parse result value: %s", value);
else if (f != TIMER_SUCCESS)
t->result = f;
} else if (streq(key, "last-trigger-realtime")) {
r = safe_atou64(value, &t->last_trigger.realtime);
if (r < 0)
log_unit_debug(u, "Failed to parse last-trigger-realtime value: %s", value);
} else if (streq(key, "last-trigger-monotonic")) {
r = safe_atou64(value, &t->last_trigger.monotonic);
if (r < 0)
log_unit_debug(u, "Failed to parse last-trigger-monotonic value: %s", value);
} else
} else if (streq(key, "last-trigger-realtime"))
(void) deserialize_usec(value, &t->last_trigger.realtime);
else if (streq(key, "last-trigger-monotonic"))
(void) deserialize_usec(value, &t->last_trigger.monotonic);
else
log_unit_debug(u, "Unknown serialization key: %s", key);
return 0;