From: Lennart Poettering Date: Tue, 4 Jul 2023 09:46:37 +0000 (+0200) Subject: import-creds: add support for binary credentials specified on the kernel cmdline X-Git-Tag: v254-rc1~33^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=de70ecb328d16dedcdea4c99cf9ff9d55491f120;p=thirdparty%2Fsystemd.git import-creds: add support for binary credentials specified on the kernel cmdline --- diff --git a/docs/CREDENTIALS.md b/docs/CREDENTIALS.md index da5152c1645..9d06c45f1f0 100644 --- a/docs/CREDENTIALS.md +++ b/docs/CREDENTIALS.md @@ -322,10 +322,11 @@ services where they are ultimately consumed. be sure they can be accessed securely from initrd context. 4. Credentials can also be passed into a system via the kernel command line, - via the `systemd.set-credential=` kernel command line option. Note though - that any data specified here is visible to all userspace applications (even - unprivileged ones) via `/proc/cmdline`. Typically, this is hence not useful - to pass sensitive information, and should be avoided. + via the `systemd.set_credential=` and `systemd.set_credential_binary=` + kernel command line options (the latter takes Base64 encoded binary + data). Note though that any data specified here is visible to all userspace + applications (even unprivileged ones) via `/proc/cmdline`. Typically, this + is hence not useful to pass sensitive information, and should be avoided. Credentials passed to the system may be enumerated/displayed via `systemd-creds --system`. They may also be propagated down to services, via the diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml index 93ed4f6acb5..43247fe5341 100644 --- a/man/kernel-command-line.xml +++ b/man/kernel-command-line.xml @@ -72,6 +72,7 @@ systemd.setenv= systemd.machine_id= systemd.set_credential= + systemd.set_credential_binary= systemd.import_credentials= systemd.reload_limit_interval_sec= systemd.reload_limit_burst= diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index ccec6ec4235..e0774073677 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -3285,7 +3285,8 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX systemd-stub7, from the initrd (see systemd1), or be - specified on the kernel command line using the systemd.set_credential= switch (see + specified on the kernel command line using the systemd.set_credential= and + systemd.set_credential_binary= switches (see systemd1 – this is not recommended since unprivileged userspace can read the kernel command line). diff --git a/man/systemd.xml b/man/systemd.xml index 754aadbb6aa..21c98efecd4 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -932,12 +932,15 @@ systemd.set_credential= + systemd.set_credential_binary= Sets a system credential, which can then be propagated to system services using the ImportCredential= or LoadCredential= setting, see systemd.exec5 for - details. Takes a pair of credential name and value, separated by a colon. Note that the kernel - command line is typically accessible by unprivileged programs in + details. Takes a pair of credential name and value, separated by a colon. The + systemd.set_credential= parameter expects the credential value in literal text + form, the systemd.set_credential_binary= parameter takes binary data encoded in + Base64. Note that the kernel command line is typically accessible by unprivileged programs in /proc/cmdline. Thus, this mechanism is not suitable for transferring sensitive data. Use it only for data that is not sensitive (e.g. public keys/certificates, rather than private keys), or in testing/debugging environments. diff --git a/src/core/import-creds.c b/src/core/import-creds.c index 6bf6ded44c5..40cbf10dad8 100644 --- a/src/core/import-creds.c +++ b/src/core/import-creds.c @@ -278,15 +278,21 @@ static int import_credentials_boot(void) { static int proc_cmdline_callback(const char *key, const char *value, void *data) { ImportCredentialContext *c = ASSERT_PTR(data); + _cleanup_free_ void *binary = NULL; _cleanup_free_ char *n = NULL; _cleanup_close_ int nfd = -EBADF; - const char *colon; + const char *colon, *d; + bool base64; size_t l; int r; assert(key); - if (!proc_cmdline_key_streq(key, "systemd.set_credential")) + if (proc_cmdline_key_streq(key, "systemd.set_credential")) + base64 = false; + else if (proc_cmdline_key_streq(key, "systemd.set_credential_binary")) + base64 = true; + else return 0; colon = value ? strchr(value, ':') : NULL; @@ -305,7 +311,19 @@ static int proc_cmdline_callback(const char *key, const char *value, void *data) } colon++; - l = strlen(colon); + + if (base64) { + r = unbase64mem(colon, SIZE_MAX, &binary, &l); + if (r < 0) { + log_warning_errno(r, "Failed to decode binary credential '%s' data, ignoring: %m", n); + return 0; + } + + d = binary; + } else { + d = colon; + l = strlen(colon); + } if (!credential_size_ok(c, n, l)) return 0; @@ -320,7 +338,7 @@ static int proc_cmdline_callback(const char *key, const char *value, void *data) if (nfd < 0) return nfd; - r = loop_write(nfd, colon, l, /* do_poll= */ false); + r = loop_write(nfd, d, l, /* do_poll= */ false); if (r < 0) { (void) unlinkat(c->target_dir_fd, n, 0); return log_error_errno(r, "Failed to write credential: %m"); diff --git a/test/TEST-54-CREDS/test.sh b/test/TEST-54-CREDS/test.sh index 55882422305..c0a9d7a53d5 100755 --- a/test/TEST-54-CREDS/test.sh +++ b/test/TEST-54-CREDS/test.sh @@ -25,6 +25,7 @@ KERNEL_CREDS=( "systemd.set_credential=sysctl.extra:kernel.domainname=sysctltest" "systemd.set_credential=login.motd:hello" "systemd.set_credential=login.issue:welcome" + "systemd.set_credential_binary=waldi:d29vb29mZmZ3dWZmZnd1ZmYK" "rd.systemd.import_credentials=no" ) KERNEL_APPEND="${KERNEL_APPEND:-} ${KERNEL_CREDS[*]}" diff --git a/test/units/testsuite-54.sh b/test/units/testsuite-54.sh index 8ba327a3b11..6c4e0065009 100755 --- a/test/units/testsuite-54.sh +++ b/test/units/testsuite-54.sh @@ -176,6 +176,7 @@ if systemd-detect-virt -q -c ; then elif [ -d /sys/firmware/qemu_fw_cfg/by_name ]; then # Verify that passing creds through kernel cmdline works [ "$(systemd-creds --system cat kernelcmdlinecred)" = "uff" ] + [ "$(systemd-creds --system cat waldi)" = "woooofffwufffwuff" ] # And that it also works via SMBIOS [ "$(systemd-creds --system cat smbioscredential)" = "magicdata" ]