journal: log filtering options support in PID1
Define new unit parameter (LogFilterPatterns) to filter logs processed by journald. This option is used to store a regular expression which is carried from PID1 to systemd-journald through a cgroup xattrs: `user.journald_log_filter_patterns`.
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "namespace.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pcre2-util.h"
|
||||
#include "process-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#if HAVE_SECCOMP
|
||||
@@ -799,6 +800,53 @@ static int property_get_log_extra_fields(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int sd_bus_message_append_log_filter_patterns(sd_bus_message *reply, Set *patterns, bool is_allowlist) {
|
||||
const char *pattern;
|
||||
int r;
|
||||
|
||||
assert(reply);
|
||||
|
||||
SET_FOREACH(pattern, patterns) {
|
||||
r = sd_bus_message_append(reply, "(bs)", is_allowlist, pattern);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int property_get_log_filter_patterns(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
ExecContext *c = userdata;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(reply);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(bs)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append_log_filter_patterns(reply, c->log_filter_allowed_patterns,
|
||||
/* is_allowlist = */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append_log_filter_patterns(reply, c->log_filter_denied_patterns,
|
||||
/* is_allowlist = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int property_get_set_credential(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@@ -1195,6 +1243,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("LogRateLimitIntervalUSec", "t", bus_property_get_usec, offsetof(ExecContext, log_ratelimit_interval_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("LogRateLimitBurst", "u", bus_property_get_unsigned, offsetof(ExecContext, log_ratelimit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("LogFilterPatterns", "a(bs)", property_get_log_filter_patterns, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("LogNamespace", "s", NULL, offsetof(ExecContext, log_namespace), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -1792,6 +1841,61 @@ int bus_exec_context_set_transient_property(
|
||||
if (streq(name, "LogRateLimitBurst"))
|
||||
return bus_set_transient_unsigned(u, name, &c->log_ratelimit_burst, message, flags, error);
|
||||
|
||||
if (streq(name, "LogFilterPatterns")) {
|
||||
/* Use _cleanup_free_, not _cleanup_strv_free_, as we don't want the content of the strv
|
||||
* to be freed. */
|
||||
_cleanup_free_ char **allow_list = NULL, **deny_list = NULL;
|
||||
const char *pattern;
|
||||
int is_allowlist;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(bs)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(bs)", &is_allowlist, &pattern)) > 0) {
|
||||
_cleanup_(pattern_freep) pcre2_code *compiled_pattern = NULL;
|
||||
|
||||
if (isempty(pattern))
|
||||
continue;
|
||||
|
||||
r = pattern_compile_and_log(pattern, 0, &compiled_pattern);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strv_push(is_allowlist ? &allow_list : &deny_list, (char *)pattern);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (strv_isempty(allow_list) && strv_isempty(deny_list)) {
|
||||
c->log_filter_allowed_patterns = set_free(c->log_filter_allowed_patterns);
|
||||
c->log_filter_denied_patterns = set_free(c->log_filter_denied_patterns);
|
||||
unit_write_settingf(u, flags, name, "%s=", name);
|
||||
} else {
|
||||
r = set_put_strdupv(&c->log_filter_allowed_patterns, allow_list);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = set_put_strdupv(&c->log_filter_denied_patterns, deny_list);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(unit_pattern, allow_list)
|
||||
unit_write_settingf(u, flags, name, "%s=%s", name, *unit_pattern);
|
||||
STRV_FOREACH(unit_pattern, deny_list)
|
||||
unit_write_settingf(u, flags, name, "%s=~%s", name, *unit_pattern);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (streq(name, "Personality"))
|
||||
return bus_set_transient_personality(u, name, &c->personality, message, flags, error);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user