Compare commits

...

14 Commits

Author SHA1 Message Date
Luca Boccassi 847bba3f00
Merge 33319701ca into c946b13575 2024-11-22 11:05:58 -08:00
Christian Hesse c946b13575 link README.logs from tmpfiles.d/legacy.conf only if available
The file README.logs is installed only if SysVInit support is enabled.
Thus the link should depend on it as well.
2024-11-22 18:33:20 +00:00
Lennart Poettering e39cbb1442 varlink: apparently on old kernels SO_PEERPIDFD returns EINVAL 2024-11-23 03:09:49 +09:00
Marco Tomaschett bc4a027f9c
hwdb: add support for PineTab2 to 60-sensor.hwdb (#35304)
Add accelerometer support for PineTab2
2024-11-23 03:08:06 +09:00
Lennart Poettering d209e197f8
userdbctl: two trivial fixlets (#35296)
Fixes: #35294
2024-11-22 16:06:01 +01:00
Antonio Alvarez Feijoo 9ed090230e tpm2-util: fix parameter name 2024-11-22 16:04:16 +01:00
Luca Boccassi 9bf6ffe166
man: split cryptenroll man page into sections (#35297) 2024-11-22 12:01:07 +00:00
Lennart Poettering 47c5ca237b userdbctl: respect selected disposition also when showing gid boundaries
Follow-up for: ad5de3222f
2024-11-22 11:28:30 +01:00
Lennart Poettering 7f8a4f12df userdbctl: fix counting
Fixes: #35294
2024-11-22 11:28:28 +01:00
Lennart Poettering e412fc5e04 userbdctl: show 'mapped' user range only inside of userns
Outside of userns the concept makes no sense, there cannot be users
mapped from further outside.
2024-11-22 11:28:17 +01:00
Lennart Poettering cc6baba720 cryptenroll: it's called PKCS#11, not PKCS11
In the --help text we really should use the official spelling, just like
in the man page.
2024-11-22 10:42:37 +01:00
Lennart Poettering 3ae48d071c man: add enrollment type sections to cryptenroll man page
We have the same sections in the --help text, hence we even more so
should have them in the man page.
2024-11-22 10:42:37 +01:00
Antonio Alvarez Feijoo 2ccacdd57c bash-completion: add --list-devices to systemd-cryptenroll
And also use it to list suitable block devices.
2024-11-22 10:38:19 +01:00
Luca Boccassi 33319701ca veritysetup: parse signature from DPS partition
If the signature is not specified manually, and sd-veritysetup is running
on a device, try to find the parent and if it's a DPS-compliant GPT
image with a signature partition, parse it and use it.
This allows automatically using the signature on boot, which allows
setting an IPE policy that enforces a validated signature on the
rootfs too.
2024-09-15 12:02:15 +02:00
10 changed files with 193 additions and 41 deletions

View File

@ -953,6 +953,15 @@ sensor:modalias:acpi:MXC6655*:dmi:*:svnDefaultstring*:pnP612F:*
sensor:modalias:acpi:SMO8500*:dmi:*:svnPEAQ:pnPEAQPMMC1010MD99187:* sensor:modalias:acpi:SMO8500*:dmi:*:svnPEAQ:pnPEAQPMMC1010MD99187:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
# Pine64
#########################################
# PineTab2
sensor:modalias:of:NaccelerometerT_null_Csilan,sc7a20:*
ACCEL_MOUNT_MATRIX=0, 0, -1; 1, 0, 0; 0, -1, 0
######################################### #########################################
# Pipo # Pipo
######################################### #########################################

View File

@ -265,32 +265,11 @@
</refsect1> </refsect1>
<refsect1> <refsect1>
<title>Options</title> <title>Unlocking</title>
<para>The following options are understood:</para> <para>The following options are understood that may be used to unlock the device in preparation of the enrollment operations:</para>
<variablelist> <variablelist>
<varlistentry>
<term><option>--password</option></term>
<listitem><para>Enroll a regular password/passphrase. This command is mostly equivalent to
<command>cryptsetup luksAddKey</command>, however may be combined with
<option>--wipe-slot=</option> in one call, see below.</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--recovery-key</option></term>
<listitem><para>Enroll a recovery key. Recovery keys are mostly identical to passphrases, but are
computer-generated instead of being chosen by a human, and thus have a guaranteed high entropy. The
key uses a character set that is easy to type in, and may be scanned off screen via a QR code.
</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--unlock-key-file=<replaceable>PATH</replaceable></option></term> <term><option>--unlock-key-file=<replaceable>PATH</replaceable></option></term>
@ -328,7 +307,45 @@
<xi:include href="version-info.xml" xpointer="v256"/></listitem> <xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Simple Enrollment</title>
<para>The following options are understood that may be used to enroll simple user input based
unlocking:</para>
<variablelist>
<varlistentry>
<term><option>--password</option></term>
<listitem><para>Enroll a regular password/passphrase. This command is mostly equivalent to
<command>cryptsetup luksAddKey</command>, however may be combined with
<option>--wipe-slot=</option> in one call, see below.</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--recovery-key</option></term>
<listitem><para>Enroll a recovery key. Recovery keys are mostly identical to passphrases, but are
computer-generated instead of being chosen by a human, and thus have a guaranteed high entropy. The
key uses a character set that is easy to type in, and may be scanned off screen via a QR code.
</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>PKCS#11 Enrollment</title>
<para>The following option is understood that may be used to enroll PKCS#11 tokens:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--pkcs11-token-uri=<replaceable>URI</replaceable></option></term> <term><option>--pkcs11-token-uri=<replaceable>URI</replaceable></option></term>
@ -361,7 +378,15 @@
<xi:include href="version-info.xml" xpointer="v248"/></listitem> <xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>FIDO2 Enrollment</title>
<para>The following options are understood that may be used to enroll PKCS#11 tokens:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--fido2-credential-algorithm=<replaceable>STRING</replaceable></option></term> <term><option>--fido2-credential-algorithm=<replaceable>STRING</replaceable></option></term>
<listitem><para>Specify COSE algorithm used in credential generation. The default value is <listitem><para>Specify COSE algorithm used in credential generation. The default value is
@ -461,7 +486,15 @@
<xi:include href="version-info.xml" xpointer="v249"/></listitem> <xi:include href="version-info.xml" xpointer="v249"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>TPM2 Enrollment</title>
<para>The following options are understood that may be used to enroll TPM2 devices:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--tpm2-device=<replaceable>PATH</replaceable></option></term> <term><option>--tpm2-device=<replaceable>PATH</replaceable></option></term>
@ -636,7 +669,15 @@
<xi:include href="version-info.xml" xpointer="v255"/></listitem> <xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Other Options</title>
<para>The following additional options are understood:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--wipe-slot=<replaceable>SLOT<optional>,SLOT...</optional></replaceable></option></term> <term><option>--wipe-slot=<replaceable>SLOT<optional>,SLOT...</optional></replaceable></option></term>

View File

@ -217,7 +217,10 @@ This is based on crypttab(5).
<listitem><para>A base64 string encoding the root hash signature prefixed by <literal>base64:</literal> or a <listitem><para>A base64 string encoding the root hash signature prefixed by <literal>base64:</literal> or a
path to roothash signature file used to verify the root hash (in kernel). This feature requires Linux kernel path to roothash signature file used to verify the root hash (in kernel). This feature requires Linux kernel
version 5.4 or more recent.</para> version 5.4 or more recent. Since version 257, if not specified and the data device is in a GPT image with a
<ulink url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">
Discoverable Partitions Specification</ulink> compliant matching signature partition, it will be
automatically loaded and used.</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem> <xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry> </varlistentry>

View File

@ -38,19 +38,12 @@ __get_tpm2_devices() {
done done
} }
__get_block_devices() {
local i
for i in /dev/*; do
[ -b "$i" ] && printf '%s\n' "$i"
done
}
_systemd_cryptenroll() { _systemd_cryptenroll() {
local comps local comps
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
local -A OPTS=( local -A OPTS=(
[STANDALONE]='-h --help --version [STANDALONE]='-h --help --version
--password --recovery-key' --password --recovery-key --list-devices'
[ARG]='--unlock-key-file [ARG]='--unlock-key-file
--unlock-fido2-device --unlock-fido2-device
--unlock-tpm2-device --unlock-tpm2-device
@ -116,7 +109,7 @@ _systemd_cryptenroll() {
return 0 return 0
fi fi
comps=$(__get_block_devices) comps=$(systemd-cryptenroll --list-devices)
COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0 return 0
} }

View File

@ -193,7 +193,7 @@ static int help(void) {
"\n%3$sSimple Enrollment:%4$s\n" "\n%3$sSimple Enrollment:%4$s\n"
" --password Enroll a user-supplied password\n" " --password Enroll a user-supplied password\n"
" --recovery-key Enroll a recovery key\n" " --recovery-key Enroll a recovery key\n"
"\n%3$sPKCS11 Enrollment:%4$s\n" "\n%3$sPKCS#11 Enrollment:%4$s\n"
" --pkcs11-token-uri=URI\n" " --pkcs11-token-uri=URI\n"
" Specify PKCS#11 security token URI\n" " Specify PKCS#11 security token URI\n"
"\n%3$sFIDO2 Enrollment:%4$s\n" "\n%3$sFIDO2 Enrollment:%4$s\n"

View File

@ -16,7 +16,7 @@ int varlink_get_peer_pidref(sd_varlink *v, PidRef *ret) {
int pidfd = sd_varlink_get_peer_pidfd(v); int pidfd = sd_varlink_get_peer_pidfd(v);
if (pidfd < 0) { if (pidfd < 0) {
if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd)) if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd) && pidfd != -EINVAL)
return pidfd; return pidfd;
pid_t pid; pid_t pid;

View File

@ -392,7 +392,7 @@ int tpm2_make_pcr_json_array(uint32_t pcr_mask, sd_json_variant **ret);
int tpm2_parse_pcr_json_array(sd_json_variant *v, uint32_t *ret); int tpm2_parse_pcr_json_array(sd_json_variant *v, uint32_t *ret);
int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const struct iovec *pubkey, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const struct iovec blobs[], size_t n_blobs, const struct iovec policy_hash[], size_t n_policy_hash, const struct iovec *salt, const struct iovec *srk, const struct iovec *pcrlock_nv, TPM2Flags flags, sd_json_variant **ret); int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const struct iovec *pubkey, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const struct iovec blobs[], size_t n_blobs, const struct iovec policy_hash[], size_t n_policy_hash, const struct iovec *salt, const struct iovec *srk, const struct iovec *pcrlock_nv, TPM2Flags flags, sd_json_variant **ret);
int tpm2_parse_luks2_json(sd_json_variant *v, int *ret_keyslot, uint32_t *ret_hash_pcr_mask, uint16_t *ret_pcr_bank, struct iovec *ret_pubkey, uint32_t *ret_pubkey_pcr_mask, uint16_t *ret_primary_alg, struct iovec **ret_blobs, size_t *ret_n_blobs, struct iovec **ret_policy_hash, size_t *ret_n_policy_hash, struct iovec *ret_salt, struct iovec *ret_srk, struct iovec *pcrlock_nv, TPM2Flags *ret_flags); int tpm2_parse_luks2_json(sd_json_variant *v, int *ret_keyslot, uint32_t *ret_hash_pcr_mask, uint16_t *ret_pcr_bank, struct iovec *ret_pubkey, uint32_t *ret_pubkey_pcr_mask, uint16_t *ret_primary_alg, struct iovec **ret_blobs, size_t *ret_n_blobs, struct iovec **ret_policy_hash, size_t *ret_n_policy_hash, struct iovec *ret_salt, struct iovec *ret_srk, struct iovec *ret_pcrlock_nv, TPM2Flags *ret_flags);
/* Default to PCR 7 only */ /* Default to PCR 7 only */
#define TPM2_PCR_INDEX_DEFAULT UINT32_C(7) #define TPM2_PCR_INDEX_DEFAULT UINT32_C(7)

View File

@ -23,6 +23,7 @@
#include "user-util.h" #include "user-util.h"
#include "userdb.h" #include "userdb.h"
#include "verbs.h" #include "verbs.h"
#include "virt.h"
static enum { static enum {
OUTPUT_CLASSIC, OUTPUT_CLASSIC,
@ -139,10 +140,16 @@ static int show_user(UserRecord *ur, Table *table) {
return 0; return 0;
} }
static bool test_show_mapped(void) {
/* Show mapped user range only in environments where user mapping is a thing. */
return running_in_userns() > 0;
}
static const struct { static const struct {
uid_t first, last; uid_t first, last;
const char *name; const char *name;
UserDisposition disposition; UserDisposition disposition;
bool (*test)(void);
} uid_range_table[] = { } uid_range_table[] = {
{ {
.first = 1, .first = 1,
@ -175,11 +182,12 @@ static const struct {
.last = MAP_UID_MAX, .last = MAP_UID_MAX,
.name = "mapped", .name = "mapped",
.disposition = USER_REGULAR, .disposition = USER_REGULAR,
.test = test_show_mapped,
}, },
}; };
static int table_add_uid_boundaries(Table *table, const UIDRange *p) { static int table_add_uid_boundaries(Table *table, const UIDRange *p) {
int r; int r, n_added = 0;
assert(table); assert(table);
@ -192,6 +200,9 @@ static int table_add_uid_boundaries(Table *table, const UIDRange *p) {
if (!uid_range_covers(p, i->first, i->last - i->first + 1)) if (!uid_range_covers(p, i->first, i->last - i->first + 1))
continue; continue;
if (i->test && !i->test())
continue;
name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN), name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN),
" begin ", i->name, " users ", " begin ", i->name, " users ",
special_glyph(SPECIAL_GLYPH_ARROW_DOWN)); special_glyph(SPECIAL_GLYPH_ARROW_DOWN));
@ -249,9 +260,11 @@ static int table_add_uid_boundaries(Table *table, const UIDRange *p) {
TABLE_INT, 1); /* sort after any other entry with the same UID */ TABLE_INT, 1); /* sort after any other entry with the same UID */
if (r < 0) if (r < 0)
return table_log_add_error(r); return table_log_add_error(r);
n_added += 2;
} }
return ELEMENTSOF(uid_range_table) * 2; return n_added;
} }
static int add_unavailable_uid(Table *table, uid_t start, uid_t end) { static int add_unavailable_uid(Table *table, uid_t start, uid_t end) {
@ -565,16 +578,22 @@ static int show_group(GroupRecord *gr, Table *table) {
} }
static int table_add_gid_boundaries(Table *table, const UIDRange *p) { static int table_add_gid_boundaries(Table *table, const UIDRange *p) {
int r; int r, n_added = 0;
assert(table); assert(table);
FOREACH_ELEMENT(i, uid_range_table) { FOREACH_ELEMENT(i, uid_range_table) {
_cleanup_free_ char *name = NULL, *comment = NULL; _cleanup_free_ char *name = NULL, *comment = NULL;
if (!FLAGS_SET(arg_disposition_mask, UINT64_C(1) << i->disposition))
continue;
if (!uid_range_covers(p, i->first, i->last - i->first + 1)) if (!uid_range_covers(p, i->first, i->last - i->first + 1))
continue; continue;
if (i->test && !i->test())
continue;
name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN), name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN),
" begin ", i->name, " groups ", " begin ", i->name, " groups ",
special_glyph(SPECIAL_GLYPH_ARROW_DOWN)); special_glyph(SPECIAL_GLYPH_ARROW_DOWN));
@ -626,9 +645,11 @@ static int table_add_gid_boundaries(Table *table, const UIDRange *p) {
TABLE_INT, 1); /* sort after any other entry with the same GID */ TABLE_INT, 1); /* sort after any other entry with the same GID */
if (r < 0) if (r < 0)
return table_log_add_error(r); return table_log_add_error(r);
n_added += 2;
} }
return ELEMENTSOF(uid_range_table) * 2; return n_added;
} }
static int add_unavailable_gid(Table *table, uid_t start, uid_t end) { static int add_unavailable_gid(Table *table, uid_t start, uid_t end) {

View File

@ -5,12 +5,16 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "blockdev-util.h"
#include "cryptsetup-util.h" #include "cryptsetup-util.h"
#include "dissect-image.h"
#include "fileio.h" #include "fileio.h"
#include "fstab-util.h" #include "fstab-util.h"
#include "hexdecoct.h" #include "hexdecoct.h"
#include "log.h" #include "log.h"
#include "loop-util.h"
#include "main-func.h" #include "main-func.h"
#include "missing_loop.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "pretty-print.h" #include "pretty-print.h"
@ -274,6 +278,79 @@ static int parse_options(const char *options) {
return r; return r;
} }
static int find_dps_signature(
const char *data_device,
void *root_hash,
size_t root_hash_size,
char **ret_root_hash_signature) {
_cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
_cleanup_free_ char *base64_signature = NULL, *string_signature = NULL;
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
DissectImageFlags dissect_image_flags =
DISSECT_IMAGE_GPT_ONLY |
DISSECT_IMAGE_USR_NO_ROOT |
DISSECT_IMAGE_ADD_PARTITION_DEVICES |
DISSECT_IMAGE_DEVICE_READ_ONLY;
ssize_t len;
int r;
assert(data_device);
assert(root_hash);
assert(root_hash_size > 0);
assert(ret_root_hash_signature);
if (!startswith(data_device, "/dev/"))
return -EINVAL;
verity.root_hash_size = root_hash_size;
verity.root_hash = malloc(root_hash_size);
if (!verity.root_hash)
return log_oom_debug();
memcpy(verity.root_hash, root_hash, root_hash_size);
r = block_device_new_from_path(data_device, BLOCK_DEVICE_LOOKUP_WHOLE_DISK, &device);
if (r < 0)
return log_debug_errno(r, "Failed to get udev device for data device: %m");
r = loop_device_open(device, O_RDONLY, LOCK_SH, &loop_device);
if (r < 0)
return log_debug_errno(r, "Failed to create loop device for root image: %m");
r = dissect_loop_device(
loop_device,
&verity,
/* mount_options= */ NULL,
/* image_policy= */ NULL,
dissect_image_flags,
&dissected_image);
if (r < 0)
return log_debug_errno(r, "Failed to dissect image: %m");
r = dissected_image_load_verity_sig_partition(
dissected_image,
loop_device->fd,
&verity);
if (r < 0)
return log_debug_errno(r, "Failed to load verity signature partition: %m");
if (r == 0)
return -ENOENT;
len = base64mem(verity.root_hash_sig, verity.root_hash_sig_size, &base64_signature);
if (len < 0)
return log_debug_errno(len, "Failed to encode root hash signature: %m");
string_signature = strjoin("base64:", base64_signature);
if (!string_signature)
return log_oom_debug();
*ret_root_hash_signature = TAKE_PTR(string_signature);
return 0;
}
static int run(int argc, char *argv[]) { static int run(int argc, char *argv[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL; _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
const char *verb; const char *verb;
@ -371,6 +448,13 @@ static int run(int argc, char *argv[]) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to configure data device: %m"); return log_error_errno(r, "Failed to configure data device: %m");
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
/* If we can support signature checks but we weren't given one, try to find it following the
* DPS on the same GPT device */
if (!arg_root_hash_signature)
(void) find_dps_signature(data_device, m, l, &arg_root_hash_signature);
#endif
if (arg_root_hash_signature) { if (arg_root_hash_signature) {
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
_cleanup_free_ char *hash_sig = NULL; _cleanup_free_ char *hash_sig = NULL;

View File

@ -13,11 +13,12 @@
d /run/lock 0755 root root - d /run/lock 0755 root root -
L /var/lock - - - - ../run/lock L /var/lock - - - - ../run/lock
{% if HAVE_SYSV_COMPAT %}
{% if CREATE_LOG_DIRS %} {% if CREATE_LOG_DIRS %}
L$ /var/log/README - - - - ../..{{DOC_DIR}}/README.logs L$ /var/log/README - - - - ../..{{DOC_DIR}}/README.logs
{% endif %} {% endif %}
{% if HAVE_SYSV_COMPAT %}
# /run/lock/subsys is used for serializing SysV service execution, and # /run/lock/subsys is used for serializing SysV service execution, and
# hence without use on SysV-less systems. # hence without use on SysV-less systems.
d /run/lock/subsys 0755 root root - d /run/lock/subsys 0755 root root -