mirror of
https://github.com/systemd/systemd
synced 2026-04-25 16:34:50 +02:00
Compare commits
9 Commits
ebf3ee4105
...
7f40cb7c86
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f40cb7c86 | ||
|
|
7d3e856e82 | ||
|
|
55fc776bbc | ||
|
|
231a1caf5e | ||
|
|
eb81249e8a | ||
|
|
6e0cb81505 | ||
|
|
0ea911d14c | ||
|
|
e1be2c779c | ||
|
|
ba57855628 |
4
TODO
4
TODO
@ -78,6 +78,10 @@ Janitorial Clean-ups:
|
||||
|
||||
Features:
|
||||
|
||||
* drop support for kernels that lack ambient capabilities support (i.e. make
|
||||
4.3 new baseline). Then drop support for "!!" modifier for ExecStart= which
|
||||
is only supported for such old kernels
|
||||
|
||||
* sd-event: compat wd reuse in inotify code: keep a set of removed watch
|
||||
descriptors, and clear this set piecemeal when we see the IN_IGNORED event
|
||||
for it, or when read() returns EAGAIN or on IN_Q_OVERFLOW. Then, whenever we
|
||||
|
||||
@ -163,6 +163,20 @@
|
||||
and thus decryption is entirely automatic.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>has-tpm2</command></term>
|
||||
|
||||
<listitem><para>Reports whether the system is equipped with a TPM2 device usable for protecting
|
||||
credentials. If the a TPM2 device has been discovered, is supported, and is being used by firmware,
|
||||
by the OS kernel drivers and by userspace (i.e. systemd) this prints <literal>yes</literal> and exits
|
||||
with exit status zero. If no such device is discovered/supported/used, prints
|
||||
<literal>no</literal>. Otherwise prints <literal>partial</literal>. In either of these two cases
|
||||
exits with non-zero exit status. It also shows three lines indicating separately whether drivers,
|
||||
firmware and the system discovered/support/use TPM2.</para>
|
||||
|
||||
<para>Combine with <option>--quiet</option> to suppress the output.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
</variablelist>
|
||||
@ -314,6 +328,14 @@
|
||||
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--quiet</option></term>
|
||||
<term><option>-q</option></term>
|
||||
|
||||
<listitem><para>When used with <command>has-tpm2</command> suppresses the output, and only returns an
|
||||
exit status indicating support for TPM2.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-legend" />
|
||||
<xi:include href="standard-options.xml" xpointer="json" />
|
||||
@ -324,6 +346,12 @@
|
||||
<title>Exit status</title>
|
||||
|
||||
<para>On success, 0 is returned.</para>
|
||||
|
||||
<para>In case of the <command>has-tpm2</command> command returns 0 if a TPM2 device is discovered,
|
||||
supported and used by firmware, driver, and userspace (i.e. systemd). Otherwise returns the OR
|
||||
combination of the value 1 (in case firmware support is missing), 2 (in case driver support is missing)
|
||||
and 4 (in case userspace support is missing). If no TPM2 support is available at all, value 7 is hence
|
||||
returned.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@ -399,7 +399,7 @@ static inline int __coverity_check_and_return__(int condition) {
|
||||
/* For type check. */ \
|
||||
unsigned *q = &p->n_ref; \
|
||||
assert(*q > 0); \
|
||||
assert(*q < UINT_MAX); \
|
||||
assert_se(*q < UINT_MAX); \
|
||||
\
|
||||
(*q)++; \
|
||||
return p; \
|
||||
|
||||
@ -47,6 +47,7 @@
|
||||
#include "terminal-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "tmpfile-util-label.h"
|
||||
#include "tpm2-util.h"
|
||||
#include "umask-util.h"
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
@ -1697,10 +1698,10 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
{ EFI_LOADER_FEATURE_RANDOM_SEED, "Support for passing random seed to OS" },
|
||||
{ EFI_LOADER_FEATURE_LOAD_DRIVER, "Load drop-in drivers" },
|
||||
};
|
||||
|
||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
|
||||
sd_id128_t loader_part_uuid = SD_ID128_NULL;
|
||||
uint64_t loader_features = 0;
|
||||
Tpm2Support s;
|
||||
int have;
|
||||
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderFirmwareType), &fw_type);
|
||||
@ -1723,7 +1724,15 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
printf(" Secure Boot: %sd (%s)\n",
|
||||
enable_disable(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)),
|
||||
secure_boot_mode_to_string(secure));
|
||||
printf(" TPM2 Support: %s\n", yes_no(efi_has_tpm2()));
|
||||
|
||||
s = tpm2_support();
|
||||
printf(" TPM2 Support: %s%s%s\n",
|
||||
FLAGS_SET(s, TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER) ? ansi_highlight_green() :
|
||||
(s & (TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER)) != 0 ? ansi_highlight_red() : ansi_highlight_yellow(),
|
||||
FLAGS_SET(s, TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER) ? "yes" :
|
||||
(s & TPM2_SUPPORT_FIRMWARE) ? "firmware only, driver unavailable" :
|
||||
(s & TPM2_SUPPORT_DRIVER) ? "driver only, firmware unavailable" : "no",
|
||||
ansi_normal());
|
||||
|
||||
k = efi_get_reboot_to_firmware();
|
||||
if (k > 0)
|
||||
|
||||
@ -48,6 +48,7 @@ static bool arg_name_any = false;
|
||||
static usec_t arg_timestamp = USEC_INFINITY;
|
||||
static usec_t arg_not_after = USEC_INFINITY;
|
||||
static bool arg_pretty = false;
|
||||
static bool arg_quiet = false;
|
||||
|
||||
static const char* transcode_mode_table[_TRANSCODE_MAX] = {
|
||||
[TRANSCODE_OFF] = "off",
|
||||
@ -525,6 +526,34 @@ static int verb_setup(int argc, char **argv, void *userdata) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int verb_has_tpm2(int argc, char **argv, void *userdata) {
|
||||
Tpm2Support s;
|
||||
|
||||
s = tpm2_support();
|
||||
|
||||
if (!arg_quiet) {
|
||||
if (s == TPM2_SUPPORT_FULL)
|
||||
puts("yes");
|
||||
else if (s == TPM2_SUPPORT_NONE)
|
||||
puts("no");
|
||||
else
|
||||
puts("partial");
|
||||
|
||||
printf("%sfirmware\n"
|
||||
"%sdriver\n"
|
||||
"%ssystem\n",
|
||||
plus_minus(s & TPM2_SUPPORT_FIRMWARE),
|
||||
plus_minus(s & TPM2_SUPPORT_DRIVER),
|
||||
plus_minus(s & TPM2_SUPPORT_SYSTEM));
|
||||
}
|
||||
|
||||
/* Return inverted bit flags. So that TPM2_SUPPORT_FULL becomes EXIT_SUCCESS and the other values
|
||||
* become some reasonable values 1…7. i.e. the flags we return here tell what is missing rather than
|
||||
* what is there, acknowledging the fact that for process exit statusses it is customary to return
|
||||
* zero (EXIT_FAILURE) when all is good, instead of all being bad. */
|
||||
return ~s & TPM2_SUPPORT_FULL;
|
||||
}
|
||||
|
||||
static int verb_help(int argc, char **argv, void *userdata) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
@ -543,6 +572,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
|
||||
" ciphertext credential file\n"
|
||||
" decrypt INPUT [OUTPUT] Decrypt ciphertext credential file and write to\n"
|
||||
" plaintext credential file\n"
|
||||
" has-tpm2 Report whether TPM2 support is available\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
@ -568,6 +598,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
|
||||
" Pick TPM2 device\n"
|
||||
" --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
|
||||
" Specify TPM2 PCRs to seal against\n"
|
||||
" -q --quiet Suppress output for 'has-tpm2' verb\n"
|
||||
"\nSee the %2$s for details.\n"
|
||||
, program_invocation_short_name
|
||||
, link
|
||||
@ -612,6 +643,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "name", required_argument, NULL, ARG_NAME },
|
||||
{ "timestamp", required_argument, NULL, ARG_TIMESTAMP },
|
||||
{ "not-after", required_argument, NULL, ARG_NOT_AFTER },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -620,7 +652,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hHTp", options, NULL)) >= 0) {
|
||||
while ((c = getopt_long(argc, argv, "hHTpq", options, NULL)) >= 0) {
|
||||
|
||||
switch (c) {
|
||||
|
||||
@ -761,6 +793,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
arg_quiet = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@ -778,12 +814,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
static int creds_main(int argc, char *argv[]) {
|
||||
|
||||
static const Verb verbs[] = {
|
||||
{ "list", VERB_ANY, 1, VERB_DEFAULT, verb_list },
|
||||
{ "cat", 2, VERB_ANY, 0, verb_cat },
|
||||
{ "encrypt", 3, 3, 0, verb_encrypt },
|
||||
{ "decrypt", 2, 3, 0, verb_decrypt },
|
||||
{ "setup", VERB_ANY, 1, 0, verb_setup },
|
||||
{ "help", VERB_ANY, 1, 0, verb_help },
|
||||
{ "list", VERB_ANY, 1, VERB_DEFAULT, verb_list },
|
||||
{ "cat", 2, VERB_ANY, 0, verb_cat },
|
||||
{ "encrypt", 3, 3, 0, verb_encrypt },
|
||||
{ "decrypt", 2, 3, 0, verb_decrypt },
|
||||
{ "setup", VERB_ANY, 1, 0, verb_setup },
|
||||
{ "help", VERB_ANY, 1, 0, verb_help },
|
||||
{ "has-tpm2", VERB_ANY, 1, 0, verb_has_tpm2 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ static struct track_item* track_item_free(struct track_item *i) {
|
||||
return mfree(i);
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct track_item, track_item, track_item_free);
|
||||
DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(struct track_item, track_item, track_item_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_unref);
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(track_item_hash_ops, char, string_hash_func, string_compare_func,
|
||||
struct track_item, track_item_free);
|
||||
@ -190,8 +190,18 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
|
||||
|
||||
i = hashmap_get(track->names, name);
|
||||
if (i) {
|
||||
if (track->recursive)
|
||||
track_item_ref(i);
|
||||
if (track->recursive) {
|
||||
assert(i->n_ref > 0);
|
||||
|
||||
/* Manual oveflow check (instead of a DEFINE_TRIVIAL_REF_FUNC() helper or so), so
|
||||
* that we can return a proper error, given this is almost always called in a
|
||||
* directly client controllable way, and thus better should never hit an assertion
|
||||
* here. */
|
||||
if (i->n_ref >= UINT_MAX)
|
||||
return -EOVERFLOW;
|
||||
|
||||
i->n_ref++;
|
||||
}
|
||||
|
||||
bus_track_remove_from_queue(track);
|
||||
return 0;
|
||||
|
||||
@ -50,6 +50,7 @@
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "tomoyo-util.h"
|
||||
#include "tpm2-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "uid-alloc-range.h"
|
||||
#include "user-util.h"
|
||||
@ -623,29 +624,14 @@ static int condition_test_ac_power(Condition *c, char **env) {
|
||||
}
|
||||
|
||||
static int has_tpm2(void) {
|
||||
int r;
|
||||
|
||||
/* Checks whether the system has at least one TPM2 resource manager device, i.e. at least one "tpmrm"
|
||||
* class device */
|
||||
* class device. Alternatively, we are also happy if the firmware reports support (this is to cover
|
||||
* for cases where we simply haven't loaded the driver for it yet, i.e. during early boot where we
|
||||
* very likely want to use this condition check).
|
||||
*
|
||||
* Note that we don't check if we ourselves are built with TPM2 support here! */
|
||||
|
||||
r = dir_is_empty("/sys/class/tpmrm");
|
||||
if (r == 0)
|
||||
return true; /* nice! we have a device */
|
||||
|
||||
/* Hmm, so Linux doesn't know of the TPM2 device (or we couldn't check for it), most likely because
|
||||
* the driver wasn't loaded yet. Let's see if the firmware knows about a TPM2 device, in this
|
||||
* case. This way we can answer the TPM2 question already during early boot (where we most likely
|
||||
* need it) */
|
||||
if (efi_has_tpm2())
|
||||
return true;
|
||||
|
||||
/* OK, this didn't work either, in this case propagate the original errors */
|
||||
if (r == -ENOENT)
|
||||
return false;
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine whether system has TPM2 support: %m");
|
||||
|
||||
return !r;
|
||||
return (tpm2_support() & (TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_FIRMWARE)) != 0;
|
||||
}
|
||||
|
||||
static int condition_test_security(Condition *c, char **env) {
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "efi-api.h"
|
||||
#include "extract-word.h"
|
||||
#include "parse-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "tpm2-util.h"
|
||||
|
||||
#if HAVE_TPM2
|
||||
@ -1453,3 +1455,24 @@ int tpm2_primary_alg_from_string(const char *alg) {
|
||||
return TPM2_ALG_RSA;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
Tpm2Support tpm2_support(void) {
|
||||
Tpm2Support support = TPM2_SUPPORT_NONE;
|
||||
int r;
|
||||
|
||||
r = dir_is_empty("/sys/class/tpmrm");
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
|
||||
} else if (r == 0) /* populated! */
|
||||
support |= TPM2_SUPPORT_DRIVER;
|
||||
|
||||
if (efi_has_tpm2())
|
||||
support |= TPM2_SUPPORT_FIRMWARE;
|
||||
|
||||
#if HAVE_TPM2
|
||||
support |= TPM2_SUPPORT_SYSTEM;
|
||||
#endif
|
||||
|
||||
return support;
|
||||
}
|
||||
|
||||
@ -89,3 +89,15 @@ typedef struct {
|
||||
uint32_t search_pcr_mask;
|
||||
const char *device;
|
||||
} systemd_tpm2_plugin_params;
|
||||
|
||||
typedef enum Tpm2Support {
|
||||
/* NOTE! The systemd-creds tool returns these flags 1:1 as exit status. Hence these flags are pretty
|
||||
* much ABI! Hence, be extra careful when changing/extending these definitions. */
|
||||
TPM2_SUPPORT_NONE = 0, /* no support */
|
||||
TPM2_SUPPORT_FIRMWARE = 1 << 0, /* firmware reports TPM2 was used */
|
||||
TPM2_SUPPORT_DRIVER = 1 << 1, /* the kernel has a driver loaded for it */
|
||||
TPM2_SUPPORT_SYSTEM = 1 << 2, /* we support it ourselves */
|
||||
TPM2_SUPPORT_FULL = TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_SYSTEM,
|
||||
} Tpm2Support;
|
||||
|
||||
Tpm2Support tpm2_support(void);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user