]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysctl: add --strict option to fail if sysctl does not exists
authorQuentin Deslandes <qdeslandes@naccy.de>
Fri, 22 Jul 2022 15:18:15 +0000 (17:18 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 25 Jul 2022 08:15:43 +0000 (10:15 +0200)
systemd-sysctl currently fails silently under any of these conditions:
- Missing permission to write a sysctl.
- Invalid sysctl (path doesn't exists).
- Ignore failure flag ('-' in front of the sysctl name).

Because of this behaviour, configuration issues can go unnoticed as
there is no way to detect those unless going through the logs.

--strict option forces systemd-sysctl to fail if a sysctl is invalid or
if permission are insufficient. Errors on sysctl marked as "ignore
failure" will still be ignored.

man/systemd-sysctl.service.xml
src/sysctl/sysctl.c
test/TEST-76-SYSCTL/Makefile [new file with mode: 0644]
test/TEST-76-SYSCTL/test.sh [new file with mode: 0755]
test/units/testsuite-76.service [new file with mode: 0644]
test/units/testsuite-76.sh [new file with mode: 0755]

index 312bc3ba43f43f7e24146aa5b79c4a708e05b702..fede8b092d730036c662bbb6f34f8c87f7d06582 100644 (file)
           <para>Only apply rules with the specified prefix.</para>
         </listitem>
       </varlistentry>
+      <varlistentry id='strict'>
+        <term><option>--strict=</option></term>
+        <listitem>
+          <para>Always return non-zero exit code on failure (including invalid sysctl variable
+          name and insufficient permissions), unless the sysctl variable name is prefixed with a "-"
+          character.</para>
+        </listitem>
+      </varlistentry>
 
       <xi:include href="standard-options.xml" xpointer="cat-config" />
       <xi:include href="standard-options.xml" xpointer="no-pager" />
index e92640d9489e9fb840ef2d9bbc996ad9cb74d4ff..de0e03ec95b0437d7607c8251b1b0e0109d2a190 100644 (file)
@@ -28,6 +28,7 @@
 
 static char **arg_prefixes = NULL;
 static bool arg_cat_config = false;
+static bool arg_strict = false;
 static PagerFlags arg_pager_flags = 0;
 
 STATIC_DESTRUCTOR_REGISTER(arg_prefixes, strv_freep);
@@ -101,13 +102,16 @@ static int sysctl_write_or_warn(const char *key, const char *value, bool ignore_
 
         r = sysctl_write(key, value);
         if (r < 0) {
-                /* If the sysctl is not available in the kernel or we are running with reduced privileges and
-                 * cannot write it, then log about the issue, and proceed without failing. (EROFS is treated
-                 * as a permission problem here, since that's how container managers usually protected their
-                 * sysctls.) In all other cases log an error and make the tool fail. */
-                if (ignore_failure || r == -EROFS || ERRNO_IS_PRIVILEGE(r))
+                /* Proceed without failing if ignore_failure is true.
+                 * If the sysctl is not available in the kernel or we are running with reduced privileges and
+                 * cannot write it, then log about the issue, and proceed without failing. Unless strict mode
+                 * (arg_strict = true) is enabled, in which case we should fail. (EROFS is treated as a
+                 * permission problem here, since that's how container managers usually protected their
+                 * sysctls.)
+                 * In all other cases log an error and make the tool fail. */
+                if (ignore_failure || (!arg_strict && (r == -EROFS || ERRNO_IS_PRIVILEGE(r))))
                         log_debug_errno(r, "Couldn't write '%s' to '%s', ignoring: %m", value, key);
-                else if (r == -ENOENT)
+                else if (!arg_strict && r == -ENOENT)
                         log_warning_errno(r, "Couldn't write '%s' to '%s', ignoring: %m", value, key);
                 else
                         return log_error_errno(r, "Couldn't write '%s' to '%s': %m", value, key);
@@ -326,6 +330,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_CAT_CONFIG,
                 ARG_PREFIX,
                 ARG_NO_PAGER,
+                ARG_STRICT,
         };
 
         static const struct option options[] = {
@@ -334,6 +339,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "cat-config", no_argument,       NULL, ARG_CAT_CONFIG },
                 { "prefix",     required_argument, NULL, ARG_PREFIX     },
                 { "no-pager",   no_argument,       NULL, ARG_NO_PAGER   },
+                { "strict",     no_argument,       NULL, ARG_STRICT     },
                 {}
         };
 
@@ -382,6 +388,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_pager_flags |= PAGER_DISABLE;
                         break;
 
+                case ARG_STRICT:
+                        arg_strict = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
diff --git a/test/TEST-76-SYSCTL/Makefile b/test/TEST-76-SYSCTL/Makefile
new file mode 100644 (file)
index 0000000..9f65d4c
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+all setup run clean clean-again:
+       @TEST_BASE_DIR=../ ./test.sh --$@
+
+.PHONY: all setup run clean clean-again
diff --git a/test/TEST-76-SYSCTL/test.sh b/test/TEST-76-SYSCTL/test.sh
new file mode 100755 (executable)
index 0000000..11a44af
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -e
+
+TEST_DESCRIPTION="Sysctl-related tests"
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
diff --git a/test/units/testsuite-76.service b/test/units/testsuite-76.service
new file mode 100644 (file)
index 0000000..3c8a9e8
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Unit]
+Description=TEST-76-SYSCTL
+
+[Service]
+ExecStartPre=rm -f /failed /testok
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
diff --git a/test/units/testsuite-76.sh b/test/units/testsuite-76.sh
new file mode 100755 (executable)
index 0000000..6ebdbc6
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+export SYSTEMD_LOG_LEVEL=debug
+
+echo "foo.bar=42" > /etc/sysctl.d/foo.conf
+[[ $(/usr/lib/systemd/systemd-sysctl /etc/sysctl.d/foo.conf)$? -eq 0 ]]
+[[ $(/usr/lib/systemd/systemd-sysctl --strict /etc/sysctl.d/foo.conf)$? -ne 0 ]]
+
+echo "-foo.foo=42" > /etc/sysctl.d/foo.conf
+[[ $(/usr/lib/systemd/systemd-sysctl /etc/sysctl.d/foo.conf)$? -eq 0 ]]
+[[ $(/usr/lib/systemd/systemd-sysctl --strict /etc/sysctl.d/foo.conf)$? -eq 0 ]]
+
+touch /testok