chiark / gitweb /
basic/log: use getenv instead of secure_getenv
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 5 Jul 2017 03:54:00 +0000 (23:54 -0400)
committerSven Eden <yamakuzure@gmx.net>
Tue, 25 Jul 2017 07:46:53 +0000 (09:46 +0200)
secure_getenv does not work when the process has a nonempty permitted
capability set, which means that it's unduly hard to configure logging in
elogind-logind, elogind-resolved, and others.

secure_getenv is useful for code in libraries which might get called from a
setuid application. log_parse_environment() is never called from our library
code, but directly form various top-level executables. None of them are
installed suid, and none are prepared to be used this way, since many
additional changes would be required to make that safe. We may just as well
drop the check and allow SYSTEMD_LOG_* to properly parsed.

Fixes #4900.

src/basic/log.c

index 887731390615cedb356099fcc55f0d7c41879c25..2169ecef3e6a503e55ba52a8267f8e018ba572bc 100644 (file)
@@ -58,7 +58,8 @@
 #define SNDBUF_SIZE (8*1024*1024)
 
 static LogTarget log_target = LOG_TARGET_CONSOLE;
-static int log_max_level = LOG_INFO;
+static int log_max_level[] = {LOG_INFO, LOG_INFO};
+assert_cc(ELEMENTSOF(log_max_level) == _LOG_REALM_MAX);
 static int log_facility = LOG_DAEMON;
 
 static int console_fd = STDERR_FILENO;
@@ -327,10 +328,11 @@ void log_forget_fds(void) {
 }
 #endif // 0
 
-void log_set_max_level(int level) {
+void log_set_max_level_realm(LogRealm realm, int level) {
         assert((level & LOG_PRIMASK) == level);
+        assert(realm < ELEMENTSOF(log_max_level));
 
-        log_max_level = level;
+        log_max_level[realm] = level;
 }
 
 void log_set_facility(int facility) {
@@ -652,13 +654,14 @@ int log_dispatch_internal(
 }
 
 int log_dump_internal(
-        int level,
-        int error,
-        const char *file,
-        int line,
-        const char *func,
-        char *buffer) {
+                int level,
+                int error,
+                const char *file,
+                int line,
+                const char *func,
+                char *buffer) {
 
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
         PROTECT_ERRNO;
 
         /* This modifies the buffer... */
@@ -666,13 +669,13 @@ int log_dump_internal(
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return -error;
 
         return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
 }
 
-int log_internalv(
+int log_internalv_realm(
                 int level,
                 int error,
                 const char *file,
@@ -681,13 +684,14 @@ int log_internalv(
                 const char *format,
                 va_list ap) {
 
-        PROTECT_ERRNO;
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
         char buffer[LINE_MAX];
+        PROTECT_ERRNO;
 
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return -error;
 
         /* Make sure that %m maps to the specified error */
@@ -699,7 +703,7 @@ int log_internalv(
         return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
 }
 
-int log_internal(
+int log_internal_realm(
                 int level,
                 int error,
                 const char *file,
@@ -711,7 +715,7 @@ int log_internal(
         int r;
 
         va_start(ap, format);
-        r = log_internalv(level, error, file, line, func, format, ap);
+        r = log_internalv_realm(level, error, file, line, func, format, ap);
         va_end(ap);
 
         return r;
@@ -736,7 +740,7 @@ int log_object_internalv(
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
                 return -error;
 
         /* Make sure that %m maps to the specified error */
@@ -790,8 +794,9 @@ static void log_assert(
                 const char *format) {
 
         static char buffer[LINE_MAX];
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return;
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
@@ -803,23 +808,42 @@ static void log_assert(
         log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
 }
 
-noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
-        log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
+noreturn void log_assert_failed_realm(
+                LogRealm realm,
+                const char *text,
+                const char *file,
+                int line,
+                const char *func) {
+        log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
+                   "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
         abort();
 }
 
-noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
-        log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
+noreturn void log_assert_failed_unreachable_realm(
+                LogRealm realm,
+                const char *text,
+                const char *file,
+                int line,
+                const char *func) {
+        log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
+                   "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
         abort();
 }
 
-void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
+void log_assert_failed_return_realm(
+                LogRealm realm,
+                const char *text,
+                const char *file,
+                int line,
+                const char *func) {
         PROTECT_ERRNO;
-        log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
+        log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
+                   "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
 }
 
-int log_oom_internal(const char *file, int line, const char *func) {
-        log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
+int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
+        log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
+                           ENOMEM, file, line, func, "Out of memory.");
         return -ENOMEM;
 }
 
@@ -879,13 +903,14 @@ int log_struct_internal(
 
         char buf[LINE_MAX];
         bool found = false;
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
         PROTECT_ERRNO;
         va_list ap;
 
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return -error;
 
         if (log_target == LOG_TARGET_NULL)
@@ -971,14 +996,14 @@ int log_set_target_from_string(const char *e) {
         return 0;
 }
 
-int log_set_max_level_from_string(const char *e) {
+int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
         int t;
 
         t = log_level_from_string(e);
         if (t < 0)
                 return -EINVAL;
 
-        log_set_max_level(t);
+        log_set_max_level_realm(realm, t);
         return 0;
 }
 
@@ -1026,7 +1051,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
         return 0;
 }
 
-void log_parse_environment(void) {
+void log_parse_environment_realm(LogRealm realm) {
         const char *e;
 
         if (get_ctty_devnr(0, NULL) < 0)
@@ -1034,19 +1059,19 @@ void log_parse_environment(void) {
                    user stuff. */
                 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
 
-        e = secure_getenv("SYSTEMD_LOG_TARGET");
+        e = getenv("SYSTEMD_LOG_TARGET");
         if (e && log_set_target_from_string(e) < 0)
                 log_warning("Failed to parse log target '%s'. Ignoring.", e);
 
-        e = secure_getenv("SYSTEMD_LOG_LEVEL");
-        if (e && log_set_max_level_from_string(e) < 0)
+        e = getenv("SYSTEMD_LOG_LEVEL");
+        if (e && log_set_max_level_from_string_realm(realm, e) < 0)
                 log_warning("Failed to parse log level '%s'. Ignoring.", e);
 
-        e = secure_getenv("SYSTEMD_LOG_COLOR");
+        e = getenv("SYSTEMD_LOG_COLOR");
         if (e && log_show_color_from_string(e) < 0)
                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
 
-        e = secure_getenv("SYSTEMD_LOG_LOCATION");
+        e = getenv("SYSTEMD_LOG_LOCATION");
         if (e && log_show_location_from_string(e) < 0)
                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
 }
@@ -1055,8 +1080,8 @@ LogTarget log_get_target(void) {
         return log_target;
 }
 
-int log_get_max_level(void) {
-        return log_max_level;
+int log_get_max_level_realm(LogRealm realm) {
+        return log_max_level[realm];
 }
 
 void log_show_color(bool b) {
@@ -1164,7 +1189,7 @@ int log_syntax_internal(
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
                 return -error;
 
         if (log_target == LOG_TARGET_NULL)
@@ -1181,7 +1206,8 @@ int log_syntax_internal(
                 unit_fmt = getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
 
         return log_struct_internal(
-                        level, error,
+                        LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+                        error,
                         file, line, func,
                         "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
                         "CONFIG_FILE=%s", config_file,