core: limit number of LogExtraFields
We have two places where those fields can be set: config and the dbus interface. Let's clamp down on the number in both places. But in principle, we could also be upgrading (through serialization/deserialization) from an older systemd which didn't enforce this limit, so also check on deserialization. A user could have a unit with lots and lots of ExtraFields, but not enough to cause the issue in #40916. To handle this gracefully, ignore the extra fields, like we do in the parser. Where the field is used, assert that we are within the expected bounds. Fixes #40916. Reproducer: $ python3 -c 'from pydbus import SystemBus; from gi.repository import GLib; SystemBus().get("org.freedesktop.systemd1", "/org/freedesktop/systemd1").StartTransientUnit("crash.service", "fail", [("ExecStart", GLib.Variant("a(sasb)", [("/bin/true", ["/bin/true"], False)])), ("LogExtraFields", GLib.Variant("aay", [b"F%d=x" % i for i in range(140000)]))], [])' Traceback (most recent call last): File "<string>", line 1, in <module> from pydbus import SystemBus; from gi.repository import GLib; SystemBus().get("org.freedesktop.systemd1", "/org/freedesktop/systemd1").StartTransientUnit("crash.service", "fail", [("ExecStart", GLib.Variant("a(sasb)", [("/bin/true", ["/bin/true"], False)])), ("LogExtraFields", GLib.Variant("aay", [b"F%d=x" % i for i in range(140000)]))], []) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/pydbus/proxy_method.py", line 102, in __call__ raise error File "/usr/lib/python3.14/site-packages/pydbus/proxy_method.py", line 97, in __call__ result = instance._bus.con.call_sync(*call_args) gi.repository.GLib.GError: g-dbus-error-quark: GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Too many extra log fields. (16)
This commit is contained in:
@@ -2806,6 +2806,9 @@ int bus_exec_context_set_transient_property(
|
||||
return sd_bus_error_set(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (c->n_log_extra_fields >= LOG_EXTRA_FIELDS_MAX)
|
||||
return sd_bus_error_set(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Too many extra log fields.");
|
||||
|
||||
if (!GREEDY_REALLOC(c->log_extra_fields, c->n_log_extra_fields + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
#include "unit.h"
|
||||
|
||||
static int exec_cgroup_context_serialize(const CGroupContext *c, FILE *f) {
|
||||
_cleanup_free_ char *disable_controllers_str = NULL, *delegate_controllers_str = NULL,
|
||||
@@ -3104,6 +3105,11 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if ((val = startswith(l, "exec-context-log-extra-fields="))) {
|
||||
if (c->n_log_extra_fields >= LOG_EXTRA_FIELDS_MAX) {
|
||||
log_warning("Too many extra log fields, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(c->log_extra_fields, c->n_log_extra_fields + 1))
|
||||
return log_oom_debug();
|
||||
|
||||
|
||||
@@ -2941,6 +2941,11 @@ int config_parse_log_extra_fields(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->n_log_extra_fields >= LOG_EXTRA_FIELDS_MAX) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Too many extra log fields, ignoring some.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(c->log_extra_fields, c->n_log_extra_fields + 1))
|
||||
return log_oom();
|
||||
|
||||
|
||||
@@ -5843,6 +5843,8 @@ static int unit_export_log_extra_fields(Unit *u, const ExecContext *c) {
|
||||
if (c->n_log_extra_fields <= 0)
|
||||
return 0;
|
||||
|
||||
assert(c->n_log_extra_fields <= LOG_EXTRA_FIELDS_MAX);
|
||||
|
||||
sizes = newa(le64_t, c->n_log_extra_fields);
|
||||
iovec = newa(struct iovec, c->n_log_extra_fields * 2);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "install.h"
|
||||
#include "iterator.h"
|
||||
#include "job.h"
|
||||
#include "journal-importer.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "log-context.h"
|
||||
@@ -1097,6 +1098,11 @@ int unit_queue_job_check_and_mangle_type(Unit *u, JobType *type, bool reload_if_
|
||||
int parse_unit_marker(const char *marker, unsigned *settings, unsigned *mask);
|
||||
unsigned unit_normalize_markers(unsigned existing_markers, unsigned new_markers);
|
||||
|
||||
/* Trying to log with too many fields is going to fail. We need at least also MESSAGE=,
|
||||
* but we generally log a few extra in most cases. So let's reserve 10. Anything
|
||||
* above a few would be very unusual, but let's not be overly strict. */
|
||||
#define LOG_EXTRA_FIELDS_MAX (ENTRY_FIELD_COUNT_MAX - 10)
|
||||
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
|
||||
#define log_unit_full_errno_zerook(unit, level, error, ...) \
|
||||
|
||||
Reference in New Issue
Block a user