Compare commits

..

No commits in common. "842067e6753d8cad951c83ac62681c539e1b1a07" and "0393e6a2742c5f4ec2903a700a7f41821cd141f2" have entirely different histories.

11 changed files with 114 additions and 353 deletions

View File

@ -72,14 +72,14 @@
# A device with a fixed keyboard layout that must not be changed by # A device with a fixed keyboard layout that must not be changed by
# the desktop environment may specify that layout as: # the desktop environment may specify that layout as:
# XKB_FIXED_LAYOUT=us # XKB_FIXED_LAYOUT="us"
# XKB_FIXED_VARIANT= # XKB_FIXED_VARIANT=""
# Examples of such devices: the Yubikey or other key-code generating # Examples of such devices: the Yubikey or other key-code generating
# devices. # devices.
# A device where the scan code to key code mapping is insufficient and # A device where the scan code to key code mapping is insufficient and
# requires a special key code to symbol configuration may specify that with: # requires a special key code to symbol configuration may specify that with:
# XKB_FIXED_MODEL=xkbmodel # XKB_FIXED_MODEL="xkbmodel"
# Examples of such devices: Chromebooks where the top row is used for both # Examples of such devices: Chromebooks where the top row is used for both
# media and F1-F10 keys. # media and F1-F10 keys.
@ -1796,8 +1796,8 @@ evdev:input:b0003v1050p0111:*
evdev:input:b0003v1050p0116:* evdev:input:b0003v1050p0116:*
# OKE Electron Company USB barcode reader # OKE Electron Company USB barcode reader
evdev:input:b0003v05FEp1010:* evdev:input:b0003v05FEp1010:*
XKB_FIXED_LAYOUT=us XKB_FIXED_LAYOUT="us"
XKB_FIXED_VARIANT= XKB_FIXED_VARIANT=""
######################### LACK OF MODIFIER LEDS ############################ ######################### LACK OF MODIFIER LEDS ############################
# This section lists keyboard which do not have their own LEDs for some # This section lists keyboard which do not have their own LEDs for some
@ -1846,4 +1846,4 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:*
# Chromebooks # Chromebooks
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPeppy:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPeppy:*
XKB_FIXED_MODEL=chromebook XKB_FIXED_MODEL="chromebook"

View File

@ -32,7 +32,7 @@ try:
from pyparsing import (Word, White, Literal, ParserElement, Regex, LineEnd, from pyparsing import (Word, White, Literal, ParserElement, Regex, LineEnd,
OneOrMore, Combine, Or, Optional, Suppress, Group, OneOrMore, Combine, Or, Optional, Suppress, Group,
nums, alphanums, printables, nums, alphanums, printables,
stringEnd, pythonStyleComment, stringEnd, pythonStyleComment, QuotedString,
ParseBaseException) ParseBaseException)
except ImportError: except ImportError:
print('pyparsing is not available') print('pyparsing is not available')
@ -54,6 +54,7 @@ EOL = LineEnd().suppress()
EMPTYLINE = LineEnd() EMPTYLINE = LineEnd()
COMMENTLINE = pythonStyleComment + EOL COMMENTLINE = pythonStyleComment + EOL
INTEGER = Word(nums) INTEGER = Word(nums)
STRING = QuotedString('"')
REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER)) REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER))
SIGNED_REAL = Combine(Optional(Word('-+')) + REAL) SIGNED_REAL = Combine(Optional(Word('-+')) + REAL)
UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_') UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
@ -93,8 +94,7 @@ def hwdb_grammar():
matchline = (matchline_typed | matchline_general) + EOL matchline = (matchline_typed | matchline_general) + EOL
propertyline = (White(' ', exact=1).suppress() + propertyline = (White(' ', exact=1).suppress() +
Combine(UDEV_TAG - '=' - Optional(Word(alphanums + '_=:@*.!-;, "')) Combine(UDEV_TAG - '=' - Word(alphanums + '_=:@*.!-;, "') - Optional(pythonStyleComment)) +
- Optional(pythonStyleComment)) +
EOL) EOL)
propertycomment = White(' ', exact=1) + pythonStyleComment + EOL propertycomment = White(' ', exact=1) + pythonStyleComment + EOL
@ -114,7 +114,6 @@ def property_grammar():
dpi_setting = (Optional('*')('DEFAULT') + INTEGER('DPI') + Suppress('@') + INTEGER('HZ'))('SETTINGS*') dpi_setting = (Optional('*')('DEFAULT') + INTEGER('DPI') + Suppress('@') + INTEGER('HZ'))('SETTINGS*')
mount_matrix_row = SIGNED_REAL + ',' + SIGNED_REAL + ',' + SIGNED_REAL mount_matrix_row = SIGNED_REAL + ',' + SIGNED_REAL + ',' + SIGNED_REAL
mount_matrix = (mount_matrix_row + ';' + mount_matrix_row + ';' + mount_matrix_row)('MOUNT_MATRIX') mount_matrix = (mount_matrix_row + ';' + mount_matrix_row + ';' + mount_matrix_row)('MOUNT_MATRIX')
xkb_setting = Optional(Word(alphanums + '+-/@._'))
props = (('MOUSE_DPI', Group(OneOrMore(dpi_setting))), props = (('MOUSE_DPI', Group(OneOrMore(dpi_setting))),
('MOUSE_WHEEL_CLICK_ANGLE', INTEGER), ('MOUSE_WHEEL_CLICK_ANGLE', INTEGER),
@ -139,9 +138,9 @@ def property_grammar():
('POINTINGSTICK_CONST_ACCEL', REAL), ('POINTINGSTICK_CONST_ACCEL', REAL),
('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))), ('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))),
('ID_INPUT_TOUCHPAD_INTEGRATION', Or(('internal', 'external'))), ('ID_INPUT_TOUCHPAD_INTEGRATION', Or(('internal', 'external'))),
('XKB_FIXED_LAYOUT', xkb_setting), ('XKB_FIXED_LAYOUT', STRING),
('XKB_FIXED_VARIANT', xkb_setting), ('XKB_FIXED_VARIANT', STRING),
('XKB_FIXED_MODEL', xkb_setting), ('XKB_FIXED_MODEL', STRING),
('KEYBOARD_LED_NUMLOCK', Literal('0')), ('KEYBOARD_LED_NUMLOCK', Literal('0')),
('KEYBOARD_LED_CAPSLOCK', Literal('0')), ('KEYBOARD_LED_CAPSLOCK', Literal('0')),
('ACCEL_MOUNT_MATRIX', mount_matrix), ('ACCEL_MOUNT_MATRIX', mount_matrix),

View File

@ -112,12 +112,7 @@
relevant for LUKS devices. See relevant for LUKS devices. See
<citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry> <citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default value of this for possible values and the default value of this
option.</para> option.</para></listitem>
<para>Optionally, the path may be followed by <literal>:</literal> and an fstab device specification
(e.g. starting with <literal>UUID=</literal> or similar); in which case, the path is relative to the
device file system root. The device gets mounted automatically for LUKS device activation duration only.
</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -130,7 +130,7 @@
<term><option>-r</option></term> <term><option>-r</option></term>
<term><option>--raw</option></term> <term><option>--raw</option></term>
<listitem><para>Format byte counts (as in memory usage and I/O metrics) and CPU time <listitem><para>Format byte counts (as in memory usage and I/O metrics)
with raw numeric values rather than human-readable with raw numeric values rather than human-readable
numbers.</para></listitem> numbers.</para></listitem>
</varlistentry> </varlistentry>

View File

@ -105,9 +105,6 @@
LUKS device given by the UUID appear under the provided LUKS device given by the UUID appear under the provided
name.</para> name.</para>
<para>This parameter is the analogue of the first <citerefentry><refentrytitle>crypttab</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> field <replaceable>volume-name</replaceable>.</para>
<para><varname>rd.luks.name=</varname> is honored only by <para><varname>rd.luks.name=</varname> is honored only by
initial RAM disk (initrd) while <varname>luks.name=</varname> initial RAM disk (initrd) while <varname>luks.name=</varname>
is honored by both the main system and the initrd.</para> is honored by both the main system and the initrd.</para>
@ -115,30 +112,20 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>luks.data=</varname></term> <term><varname>luks.options=</varname></term>
<term><varname>rd.luks.data=</varname></term> <term><varname>rd.luks.options=</varname></term>
<listitem><para>Takes a LUKS super block UUID followed by a <literal>=</literal> and a block device <listitem><para>Takes a LUKS super block UUID followed by an
specification for device hosting encrypted data.</para> <literal>=</literal> and a string of options separated by
commas as argument. This will override the options for the
<para>For those entries specified with <varname>rd.luks.uuid=</varname> or given UUID.</para>
<varname>luks.uuid=</varname>, the data device will be set to the one specified by <para>If only a list of options, without an UUID, is
<varname>rd.luks.data=</varname> or <varname>luks.data=</varname> of the corresponding UUID.</para> specified, they apply to any UUIDs not specified elsewhere,
and without an entry in
<para>LUKS data device parameter is usefull for specifying encrypted data devices with detached headers specified in <filename>/etc/crypttab</filename>.</para><para>
<varname>luks.options</varname> entry containing <literal>header=</literal> argument. For example, <varname>rd.luks.options=</varname> is honored only by initial
<varname>rd.luks.uuid=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40 RAM disk (initrd) while <varname>luks.options=</varname> is
<varname>rd.luks.options=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=header=/path/to/luks.hdr honored by both the main system and the initrd.</para>
<varname>rd.luks.data=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=/dev/sdx.
Hence, in this case, we will attempt to unlock LUKS device assembled from data device <literal>/dev/sdx</literal>
and LUKS header (metadata) put in <literal>/path/to/luks.hdr</literal> file. This syntax is for now
only supported on a per-device basis, i.e. you have to specify LUKS device UUID.</para>
<para>This parameter is the analogue of the second <citerefentry><refentrytitle>crypttab</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> field <replaceable>encrypted-device</replaceable>.</para>
<para><varname>rd.luks.data=</varname> is honored only by initial RAM disk (initrd) while
<varname>luks.data=</varname> is honored by both the main system and the initrd.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -170,9 +157,6 @@
This syntax is for now only supported on a per-device basis, This syntax is for now only supported on a per-device basis,
i.e. you have to specify LUKS device UUID.</para> i.e. you have to specify LUKS device UUID.</para>
<para>This parameter is the analogue of the third <citerefentry><refentrytitle>crypttab</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> field <replaceable>key-file</replaceable>.</para>
<para><varname>rd.luks.key=</varname> <para><varname>rd.luks.key=</varname>
is honored only by initial RAM disk is honored only by initial RAM disk
(initrd) while (initrd) while
@ -181,44 +165,6 @@
the initrd.</para> the initrd.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>luks.options=</varname></term>
<term><varname>rd.luks.options=</varname></term>
<listitem><para>Takes a LUKS super block UUID followed by an
<literal>=</literal> and a string of options separated by
commas as argument. This will override the options for the
given UUID.</para>
<para>If only a list of options, without an UUID, is
specified, they apply to any UUIDs not specified elsewhere,
and without an entry in
<filename>/etc/crypttab</filename>.</para>
<para>This parameter is the analogue of the fourth <citerefentry><refentrytitle>crypttab</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> field <replaceable>options</replaceable>.</para>
<para>It is possible to specify an external device which
should be mounted before we attempt to unlock the LUKS device.
systemd-cryptsetup will assemble LUKS device by combining
data device specified in <varname>luks.data</varname> with
detached LUKS header found in <literal>header=</literal>
argument. For example,
<varname>rd.luks.uuid=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40
<varname>rd.luks.options=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=header=/luks.hdr:LABEL=hdrdev
<varname>rd.luks.data=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=/dev/sdx.
Hence, in this case, we will attempt to mount file system
residing on the block device with label <literal>hdrdev</literal>, and look
for <literal>luks.hdr</literal> on that file system. Said header will be used
to unlock (decrypt) encrypted data stored on /dev/sdx.
This syntax is for now only supported on a per-device basis,
i.e. you have to specify LUKS device UUID.</para>
<para><varname>rd.luks.options=</varname> is honored only by initial
RAM disk (initrd) while <varname>luks.options=</varname> is
honored by both the main system and the initrd.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -281,12 +281,6 @@ static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) {
MAX(_c, z); \ MAX(_c, z); \
}) })
#define MAX4(x, y, z, a) \
({ \
const typeof(x) _d = MAX3(x, y, z); \
MAX(_d, a); \
})
#undef MIN #undef MIN
#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b)) #define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
#define __MIN(aq, a, bq, b) \ #define __MIN(aq, a, bq, b) \

View File

@ -91,15 +91,6 @@ static Group *group_free(Group *g) {
return mfree(g); return mfree(g);
} }
static const char *maybe_format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
if (arg_raw) {
snprintf(buf, l, USEC_FMT, t);
return buf;
}
return format_timespan(buf, l, t, accuracy);
}
static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64_t t) { static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64_t t) {
if (!is_valid) if (!is_valid)
return "-"; return "-";
@ -595,7 +586,7 @@ static void display(Hashmap *a) {
Group **array; Group **array;
signed path_columns; signed path_columns;
unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */ unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */
char buffer[MAX4(21U, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX, DECIMAL_STR_MAX(usec_t))]; char buffer[MAX3(21U, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)];
assert(a); assert(a);
@ -614,7 +605,7 @@ static void display(Hashmap *a) {
for (j = 0; j < n; j++) { for (j = 0; j < n; j++) {
unsigned cputlen, pathtlen; unsigned cputlen, pathtlen;
maybe_format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0);
cputlen = strlen(buffer); cputlen = strlen(buffer);
maxtcpu = MAX(maxtcpu, cputlen); maxtcpu = MAX(maxtcpu, cputlen);
@ -683,7 +674,7 @@ static void display(Hashmap *a) {
else else
fputs(" -", stdout); fputs(" -", stdout);
} else } else
printf(" %*s", maxtcpu, maybe_format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0));
printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory));
printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps));

View File

@ -29,8 +29,6 @@ typedef struct crypto_device {
char *uuid; char *uuid;
char *keyfile; char *keyfile;
char *keydev; char *keydev;
char *headerdev;
char *datadev;
char *name; char *name;
char *options; char *options;
bool create; bool create;
@ -50,64 +48,62 @@ STATIC_DESTRUCTOR_REGISTER(arg_disks, hashmap_freep);
STATIC_DESTRUCTOR_REGISTER(arg_default_options, freep); STATIC_DESTRUCTOR_REGISTER(arg_default_options, freep);
STATIC_DESTRUCTOR_REGISTER(arg_default_keyfile, freep); STATIC_DESTRUCTOR_REGISTER(arg_default_keyfile, freep);
static int split_locationspec(const char *locationspec, char **ret_file, char **ret_device) { static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_keydev) {
_cleanup_free_ char *file = NULL, *device = NULL; _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
const char *c; const char *c;
assert(ret_file); assert(ret_keyfile);
assert(ret_device); assert(ret_keydev);
if (!locationspec) { if (!keyspec) {
*ret_file = *ret_device = NULL; *ret_keyfile = *ret_keydev = NULL;
return 0; return 0;
} }
c = strrchr(locationspec, ':'); c = strrchr(keyspec, ':');
if (c) { if (c) {
/* The device part has to be either an absolute path to device node (/dev/something, /* The keydev part has to be either an absolute path to device node (/dev/something,
* /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device * /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device
* specification starting with LABEL= or similar. The file part has the same syntax. * specification starting with LABEL= or similar. The keyfile part has the same syntax.
* *
* Let's try to guess if the second part looks like a device specification, or just part of a * Let's try to guess if the second part looks like a keydev specification, or just part of a
* filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to * filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to
* an absolute path. If we didn't get an absolute path, assume that it is just part of the * an absolute path. If we didn't get an absolute path, assume that it is just part of the
* first file argument. */ * first keyfile argument. */
device = fstab_node_to_udev_node(c + 1); keydev = fstab_node_to_udev_node(c + 1);
if (!device) if (!keydev)
return log_oom(); return log_oom();
if (path_is_absolute(device)) if (path_is_absolute(keydev))
file = strndup(locationspec, c-locationspec); keyfile = strndup(keyspec, c-keyspec);
else { else {
log_debug("Location specification argument contains a colon, but \"%s\" doesn't look like a device specification.\n" log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n"
"Assuming that \"%s\" is a single device specification.", "Assuming that \"%s\" is a single device specification.",
c + 1, locationspec); c + 1, keyspec);
device = mfree(device); keydev = mfree(keydev);
c = NULL; c = NULL;
} }
} }
if (!c) if (!c)
/* No device specified */ /* No keydev specified */
file = strdup(locationspec); keyfile = strdup(keyspec);
if (!file) if (!keyfile)
return log_oom(); return log_oom();
*ret_file = TAKE_PTR(file); *ret_keyfile = TAKE_PTR(keyfile);
*ret_device = TAKE_PTR(device); *ret_keydev = TAKE_PTR(keydev);
return 0; return 0;
} }
static int generate_device_mount( static int generate_keydev_mount(
const char *name, const char *name,
const char *device, const char *keydev,
const char *type_prefix, /* "keydev" or "headerdev" */ const char *keydev_timeout,
const char *device_timeout,
bool canfail, bool canfail,
bool readonly,
char **unit, char **unit,
char **mount) { char **mount) {
@ -117,7 +113,7 @@ static int generate_device_mount(
usec_t timeout_us; usec_t timeout_us;
assert(name); assert(name);
assert(device); assert(keydev);
assert(unit); assert(unit);
assert(mount); assert(mount);
@ -133,7 +129,7 @@ static int generate_device_mount(
if (!name_escaped) if (!name_escaped)
return -ENOMEM; return -ENOMEM;
where = strjoin(arg_runtime_directory, "/", type_prefix, "-", name_escaped); where = strjoin(arg_runtime_directory, "/keydev-", name_escaped);
if (!where) if (!where)
return -ENOMEM; return -ENOMEM;
@ -155,23 +151,23 @@ static int generate_device_mount(
"[Mount]\n" "[Mount]\n"
"What=%s\n" "What=%s\n"
"Where=%s\n" "Where=%s\n"
"Options=%s%s\n", device, where, readonly ? "ro" : "rw", canfail ? ",nofail" : ""); "Options=ro%s\n", keydev, where, canfail ? ",nofail" : "");
if (device_timeout) { if (keydev_timeout) {
r = parse_sec_fix_0(device_timeout, &timeout_us); r = parse_sec_fix_0(keydev_timeout, &timeout_us);
if (r >= 0) { if (r >= 0) {
r = unit_name_from_path(device, ".device", &device_unit); r = unit_name_from_path(keydev, ".device", &device_unit);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m"); return log_error_errno(r, "Failed to generate unit name: %m");
r = write_drop_in_format(arg_dest, device_unit, 90, "device-timeout", r = write_drop_in_format(arg_dest, device_unit, 90, "device-timeout",
"# Automatically generated by systemd-cryptsetup-generator \n\n" "# Automatically generated by systemd-cryptsetup-generator \n\n"
"[Unit]\nJobRunningTimeoutSec=%s", device_timeout); "[Unit]\nJobRunningTimeoutSec=%s", keydev_timeout);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to write device drop-in: %m"); return log_error_errno(r, "Failed to write device drop-in: %m");
} else } else
log_warning_errno(r, "Failed to parse %s, ignoring: %m", device_timeout); log_warning_errno(r, "Failed to parse %s, ignoring: %m", keydev_timeout);
} }
@ -185,9 +181,8 @@ static int generate_device_mount(
return 0; return 0;
} }
static int generate_device_umount(const char *name, static int generate_keydev_umount(const char *name,
const char *device_mount, const char *keydev_mount,
const char *type_prefix, /* "keydev" or "headerdev" */
char **ret_umount_unit) { char **ret_umount_unit) {
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *u = NULL, *name_escaped = NULL, *mount = NULL; _cleanup_free_ char *u = NULL, *name_escaped = NULL, *mount = NULL;
@ -200,11 +195,11 @@ static int generate_device_umount(const char *name,
if (!name_escaped) if (!name_escaped)
return -ENOMEM; return -ENOMEM;
u = strjoin(type_prefix, "-", name_escaped, "-umount.service"); u = strjoin("keydev-", name_escaped, "-umount.service");
if (!u) if (!u)
return -ENOMEM; return -ENOMEM;
r = unit_name_from_path(device_mount, ".mount", &mount); r = unit_name_from_path(keydev_mount, ".mount", &mount);
if (r < 0) if (r < 0)
return r; return r;
@ -217,7 +212,7 @@ static int generate_device_umount(const char *name,
"DefaultDependencies=no\n" "DefaultDependencies=no\n"
"After=%s\n\n" "After=%s\n\n"
"[Service]\n" "[Service]\n"
"ExecStart=-" UMOUNT_PATH " %s\n\n", mount, device_mount); "ExecStart=-" UMOUNT_PATH " %s\n\n", mount, keydev_mount);
r = fflush_and_check(f); r = fflush_and_check(f);
if (r < 0) if (r < 0)
@ -279,14 +274,13 @@ static int create_disk(
const char *device, const char *device,
const char *password, const char *password,
const char *keydev, const char *keydev,
const char *headerdev,
const char *options, const char *options,
const char *source) { const char *source) {
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL, _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
*keydev_mount = NULL, *keyfile_timeout_value = NULL, *keydev_mount = NULL, *keyfile_timeout_value = NULL,
*filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL, *filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL,
*tmp_fstype = NULL, *filtered_header = NULL, *headerdev_mount = NULL; *tmp_fstype = NULL;
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
const char *dmname; const char *dmname;
bool noauto, nofail, swap, netdev, attach_in_initrd; bool noauto, nofail, swap, netdev, attach_in_initrd;
@ -305,12 +299,7 @@ static int create_disk(
if (keyfile_can_timeout < 0) if (keyfile_can_timeout < 0)
return log_error_errno(keyfile_can_timeout, "Failed to parse keyfile-timeout= option value: %m"); return log_error_errno(keyfile_can_timeout, "Failed to parse keyfile-timeout= option value: %m");
detached_header = fstab_filter_options( detached_header = fstab_filter_options(options, "header\0", NULL, &header_path, NULL);
options,
"header\0",
NULL,
&header_path,
headerdev ? &filtered_header : NULL);
if (detached_header < 0) if (detached_header < 0)
return log_error_errno(detached_header, "Failed to parse header= option value: %m"); return log_error_errno(detached_header, "Failed to parse header= option value: %m");
@ -369,19 +358,11 @@ static int create_disk(
if (keydev) { if (keydev) {
_cleanup_free_ char *unit = NULL, *umount_unit = NULL; _cleanup_free_ char *unit = NULL, *umount_unit = NULL;
r = generate_device_mount( r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount);
name,
keydev,
"keydev",
keyfile_timeout_value,
/* canfail = */ keyfile_can_timeout > 0,
/* readonly= */ true,
&unit,
&keydev_mount);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to generate keydev mount unit: %m"); return log_error_errno(r, "Failed to generate keydev mount unit: %m");
r = generate_device_umount(name, keydev_mount, "keydev", &umount_unit); r = generate_keydev_umount(name, keydev_mount, &umount_unit);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to generate keydev umount unit: %m"); return log_error_errno(r, "Failed to generate keydev umount unit: %m");
@ -406,55 +387,6 @@ static int create_disk(
); );
} }
if (headerdev) {
_cleanup_free_ char *unit = NULL, *umount_unit = NULL, *p = NULL;
r = generate_device_mount(
name,
headerdev,
"headerdev",
NULL,
/* canfail= */ false, /* header is always necessary */
/* readonly= */ false, /* LUKS2 recovery requires rw header access */
&unit,
&headerdev_mount);
if (r < 0)
return log_error_errno(r, "Failed to generate header device mount unit: %m");
r = generate_device_umount(name, headerdev_mount, "headerdev", &umount_unit);
if (r < 0)
return log_error_errno(r, "Failed to generate header device umount unit: %m");
p = path_join(headerdev_mount, header_path);
if (!p)
return log_oom();
free_and_replace(header_path, p);
if (isempty(filtered_header))
p = strjoin("header=", header_path);
else
p = strjoin(filtered_header, ",header=", header_path);
if (!p)
return log_oom();
free_and_replace(filtered_header, p);
options = filtered_header;
fprintf(f, "After=%s\n"
"Requires=%s\n", unit, unit);
if (umount_unit) {
fprintf(f,
"Wants=%s\n"
"Before=%s\n",
umount_unit,
umount_unit
);
}
}
if (!nofail) if (!nofail)
fprintf(f, fprintf(f,
"Before=%s\n", "Before=%s\n",
@ -467,7 +399,7 @@ static int create_disk(
} }
/* Check if a header option was specified */ /* Check if a header option was specified */
if (detached_header > 0 && !headerdev) { if (detached_header > 0) {
r = print_dependencies(f, header_path); r = print_dependencies(f, header_path);
if (r < 0) if (r < 0)
return r; return r;
@ -582,52 +514,6 @@ static crypto_device *get_crypto_device(const char *uuid) {
return d; return d;
} }
static bool warn_uuid_invalid(const char *uuid, const char *key) {
assert(key);
if (!id128_is_valid(uuid)) {
log_warning("Failed to parse %s= kernel command line switch. UUID is invalid, ignoring.", key);
return true;
}
return false;
}
static int filter_header_device(const char *options,
char **ret_headerdev,
char **ret_filtered_headerdev_options) {
int r;
_cleanup_free_ char *headerfile = NULL, *headerdev = NULL, *headerspec = NULL,
*filtered_headerdev = NULL, *filtered_headerspec = NULL;
assert(ret_headerdev);
assert(ret_filtered_headerdev_options);
r = fstab_filter_options(options, "header\0", NULL, &headerspec, &filtered_headerspec);
if (r < 0)
return log_error_errno(r, "Failed to parse header= option value: %m");
if (r > 0) {
r = split_locationspec(headerspec, &headerfile, &headerdev);
if (r < 0)
return r;
if (isempty(filtered_headerspec))
filtered_headerdev = strjoin("header=", headerfile);
else
filtered_headerdev = strjoin(filtered_headerspec, ",header=", headerfile);
if (!filtered_headerdev)
return log_oom();
} else
filtered_headerdev = TAKE_PTR(filtered_headerspec);
*ret_filtered_headerdev_options = TAKE_PTR(filtered_headerdev);
*ret_headerdev = TAKE_PTR(headerdev);
return 0;
}
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
_cleanup_free_ char *uuid = NULL, *uuid_value = NULL; _cleanup_free_ char *uuid = NULL, *uuid_value = NULL;
crypto_device *d; crypto_device *d;
@ -661,28 +547,20 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
d->create = arg_allow_list = true; d->create = arg_allow_list = true;
} else if (streq(key, "luks.options")) { } else if (streq(key, "luks.options")) {
_cleanup_free_ char *headerdev = NULL, *filtered_headerdev_options = NULL;
if (proc_cmdline_value_missing(key, value)) if (proc_cmdline_value_missing(key, value))
return 0; return 0;
r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
if (r != 2) if (r == 2) {
return free_and_strdup(&arg_default_options, value) < 0 ? log_oom() : 0; d = get_crypto_device(uuid);
if (!d)
return log_oom();
if (warn_uuid_invalid(uuid, key)) free_and_replace(d->options, uuid_value);
return 0; } else if (free_and_strdup(&arg_default_options, value) < 0)
d = get_crypto_device(uuid);
if (!d)
return log_oom(); return log_oom();
r = filter_header_device(uuid_value, &headerdev, &filtered_headerdev_options);
if (r < 0)
return r;
free_and_replace(d->options, filtered_headerdev_options);
free_and_replace(d->headerdev, headerdev);
} else if (streq(key, "luks.key")) { } else if (streq(key, "luks.key")) {
size_t n; size_t n;
_cleanup_free_ char *keyfile = NULL, *keydev = NULL; _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
@ -691,7 +569,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value)) if (proc_cmdline_value_missing(key, value))
return 0; return 0;
n = strspn(value, ALPHANUMERICAL "-"); n = strspn(value, LETTERS DIGITS "-");
if (value[n] != '=') { if (value[n] != '=') {
if (free_and_strdup(&arg_default_keyfile, value) < 0) if (free_and_strdup(&arg_default_keyfile, value) < 0)
return log_oom(); return log_oom();
@ -702,49 +580,23 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (!uuid) if (!uuid)
return log_oom(); return log_oom();
if (warn_uuid_invalid(uuid, key)) if (!id128_is_valid(uuid)) {
log_warning("Failed to parse luks.key= kernel command line switch. UUID is invalid, ignoring.");
return 0; return 0;
}
d = get_crypto_device(uuid); d = get_crypto_device(uuid);
if (!d) if (!d)
return log_oom(); return log_oom();
keyspec = value + n + 1; keyspec = value + n + 1;
r = split_locationspec(keyspec, &keyfile, &keydev); r = split_keyspec(keyspec, &keyfile, &keydev);
if (r < 0) if (r < 0)
return r; return r;
free_and_replace(d->keyfile, keyfile); free_and_replace(d->keyfile, keyfile);
free_and_replace(d->keydev, keydev); free_and_replace(d->keydev, keydev);
} else if (streq(key, "luks.data")) {
size_t n;
_cleanup_free_ char *datadev = NULL;
if (proc_cmdline_value_missing(key, value))
return 0;
n = strspn(value, ALPHANUMERICAL "-");
if (value[n] != '=') {
log_warning("Failed to parse luks.data= kernel command line switch. UUID is invalid, ignoring.");
return 0;
}
uuid = strndup(value, n);
if (!uuid)
return log_oom();
if (warn_uuid_invalid(uuid, key))
return 0;
d = get_crypto_device(uuid);
if (!d)
return log_oom();
datadev = fstab_node_to_udev_node(value + n + 1);
if (!datadev)
return log_oom();
free_and_replace(d->datadev, datadev);
} else if (streq(key, "luks.name")) { } else if (streq(key, "luks.name")) {
if (proc_cmdline_value_missing(key, value)) if (proc_cmdline_value_missing(key, value))
@ -782,8 +634,7 @@ static int add_crypttab_devices(void) {
} }
for (;;) { for (;;) {
_cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL, _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL, *keyfile = NULL, *keydev = NULL;
*keyfile = NULL, *keydev = NULL, *headerdev = NULL, *filtered_header = NULL;
crypto_device *d = NULL; crypto_device *d = NULL;
char *l, *uuid; char *l, *uuid;
int k; int k;
@ -819,24 +670,11 @@ static int add_crypttab_devices(void) {
continue; continue;
} }
r = split_locationspec(keyspec, &keyfile, &keydev); r = split_keyspec(keyspec, &keyfile, &keydev);
if (r < 0) if (r < 0)
return r; return r;
if (options && (!d || !d->options)) { r = create_disk(name, device, keyfile, keydev, (d && d->options) ? d->options : options, arg_crypttab);
r = filter_header_device(options, &headerdev, &filtered_header);
if (r < 0)
return r;
free_and_replace(options, filtered_header);
}
r = create_disk(name,
device,
keyfile,
keydev,
(d && d->options) ? d->headerdev : headerdev,
(d && d->options) ? d->options : options,
arg_crypttab);
if (r < 0) if (r < 0)
return r; return r;
@ -868,10 +706,9 @@ static int add_proc_cmdline_devices(void) {
return log_oom(); return log_oom();
r = create_disk(d->name, r = create_disk(d->name,
d->datadev ?: device, device,
d->keyfile ?: arg_default_keyfile, d->keyfile ?: arg_default_keyfile,
d->keydev, d->keydev,
d->headerdev,
d->options ?: arg_default_options, d->options ?: arg_default_options,
"/proc/cmdline"); "/proc/cmdline");
if (r < 0) if (r < 0)

View File

@ -833,6 +833,8 @@ _public_ PAM_EXTERN int pam_sm_acct_mgmt(
pam_syslog(handle, LOG_DEBUG, "pam-systemd-homed account management"); pam_syslog(handle, LOG_DEBUG, "pam-systemd-homed account management");
r = acquire_home(handle, /* please_authenticate = */ false, please_suspend, debug); r = acquire_home(handle, /* please_authenticate = */ false, please_suspend, debug);
if (r == PAM_USER_UNKNOWN)
return PAM_SUCCESS; /* we don't have anything to say about users we don't manage */
if (r != PAM_SUCCESS) if (r != PAM_SUCCESS)
return r; return r;

View File

@ -105,10 +105,12 @@ static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) {
} }
static void trie_node_cleanup(struct trie_node *node) { static void trie_node_cleanup(struct trie_node *node) {
size_t i;
if (!node) if (!node)
return; return;
for (size_t i = 0; i < node->children_count; i++) for (i = 0; i < node->children_count; i++)
trie_node_cleanup(node->children[i].child); trie_node_cleanup(node->children[i].child);
free(node->children); free(node->children);
free(node->values); free(node->values);
@ -189,9 +191,10 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node,
static int trie_insert(struct trie *trie, struct trie_node *node, const char *search, static int trie_insert(struct trie *trie, struct trie_node *node, const char *search,
const char *key, const char *value, const char *key, const char *value,
const char *filename, uint16_t file_priority, uint32_t line_number, bool compat) { const char *filename, uint16_t file_priority, uint32_t line_number, bool compat) {
size_t i = 0;
int r = 0; int r = 0;
for (size_t i = 0;; i++) { for (;;) {
size_t p; size_t p;
uint8_t c; uint8_t c;
struct trie_node *child; struct trie_node *child;
@ -270,6 +273,7 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se
} }
node = child; node = child;
i++;
} }
} }
@ -285,17 +289,20 @@ struct trie_f {
/* calculate the storage space for the nodes, children arrays, value arrays */ /* calculate the storage space for the nodes, children arrays, value arrays */
static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node, bool compat) { static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node, bool compat) {
for (uint64_t i = 0; i < node->children_count; i++) uint64_t i;
for (i = 0; i < node->children_count; i++)
trie_store_nodes_size(trie, node->children[i].child, compat); trie_store_nodes_size(trie, node->children[i].child, compat);
trie->strings_off += sizeof(struct trie_node_f); trie->strings_off += sizeof(struct trie_node_f);
for (uint64_t i = 0; i < node->children_count; i++) for (i = 0; i < node->children_count; i++)
trie->strings_off += sizeof(struct trie_child_entry_f); trie->strings_off += sizeof(struct trie_child_entry_f);
for (uint64_t i = 0; i < node->values_count; i++) for (i = 0; i < node->values_count; i++)
trie->strings_off += compat ? sizeof(struct trie_value_entry_f) : sizeof(struct trie_value_entry2_f); trie->strings_off += compat ? sizeof(struct trie_value_entry_f) : sizeof(struct trie_value_entry2_f);
} }
static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node, bool compat) { static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node, bool compat) {
uint64_t i;
struct trie_node_f n = { struct trie_node_f n = {
.prefix_off = htole64(trie->strings_off + node->prefix_off), .prefix_off = htole64(trie->strings_off + node->prefix_off),
.children_count = node->children_count, .children_count = node->children_count,
@ -311,7 +318,7 @@ static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node, boo
} }
/* post-order recursion */ /* post-order recursion */
for (uint64_t i = 0; i < node->children_count; i++) { for (i = 0; i < node->children_count; i++) {
int64_t child_off; int64_t child_off;
child_off = trie_store_nodes(trie, node->children[i].child, compat); child_off = trie_store_nodes(trie, node->children[i].child, compat);
@ -336,7 +343,7 @@ static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node, boo
} }
/* append values array */ /* append values array */
for (uint64_t i = 0; i < node->values_count; i++) { for (i = 0; i < node->values_count; i++) {
struct trie_value_entry2_f v = { struct trie_value_entry2_f v = {
.key_off = htole64(trie->strings_off + node->values[i].key_off), .key_off = htole64(trie->strings_off + node->values[i].key_off),
.value_off = htole64(trie->strings_off + node->values[i].value_off), .value_off = htole64(trie->strings_off + node->values[i].value_off),
@ -440,7 +447,7 @@ static int insert_data(struct trie *trie, char **match_list, char *line, const c
value = strchr(line, '='); value = strchr(line, '=');
if (!value) if (!value)
return log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL), return log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
"Key-value pair expected but got \"%s\", ignoring.", line); "Key-value pair expected but got \"%s\", ignoring", line);
value[0] = '\0'; value[0] = '\0';
value++; value++;
@ -449,9 +456,10 @@ static int insert_data(struct trie *trie, char **match_list, char *line, const c
while (isblank(line[0]) && isblank(line[1])) while (isblank(line[0]) && isblank(line[1]))
line++; line++;
if (isempty(line + 1)) if (isempty(line + 1) || isempty(value))
return log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL), return log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
"Empty key in \"%s=%s\", ignoring.", "Empty %s in \"%s=%s\", ignoring",
isempty(line + 1) ? "key" : "value",
line, value); line, value);
STRV_FOREACH(entry, match_list) STRV_FOREACH(entry, match_list)
@ -486,7 +494,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (r == 0) if (r == 0)
break; break;
line_number ++; ++line_number;
/* comment line */ /* comment line */
if (line[0] == '#') if (line[0] == '#')
@ -510,7 +518,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (line[0] == ' ') { if (line[0] == ' ') {
r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL), r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
"Match expected but got indented property \"%s\", ignoring line.", line); "Match expected but got indented property \"%s\", ignoring line", line);
break; break;
} }
@ -526,7 +534,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
case HW_MATCH: case HW_MATCH:
if (len == 0) { if (len == 0) {
r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL), r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
"Property expected, ignoring record with no properties."); "Property expected, ignoring record with no properties");
state = HW_NONE; state = HW_NONE;
match_list = strv_free(match_list); match_list = strv_free(match_list);
break; break;
@ -558,7 +566,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (line[0] != ' ') { if (line[0] != ' ') {
r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL), r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
"Property or empty line expected, got \"%s\", ignoring record.", line); "Property or empty line expected, got \"%s\", ignoring record", line);
state = HW_NONE; state = HW_NONE;
match_list = strv_free(match_list); match_list = strv_free(match_list);
break; break;
@ -573,7 +581,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (state == HW_MATCH) if (state == HW_MATCH)
log_syntax(NULL, LOG_WARNING, filename, line_number, 0, log_syntax(NULL, LOG_WARNING, filename, line_number, 0,
"Property expected, ignoring record with no properties."); "Property expected, ignoring record with no properties");
return r; return r;
} }

View File

@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#include <sched.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <unistd.h> #include <unistd.h>
@ -259,16 +258,6 @@ static void test_path_is_mount_point(void) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG); test_setup_logging(LOG_DEBUG);
/* let's move into our own mount namespace with all propagation from the host turned off, so that
* /proc/self/mountinfo is static and constant for the whole time our test runs. */
if (unshare(CLONE_NEWNS) < 0) {
if (!ERRNO_IS_PRIVILEGE(errno))
return log_error_errno(errno, "Failed to detach mount namespace: %m");
log_notice("Lacking privilege to create separate mount namespace, proceeding in originating mount namespace.");
} else
assert_se(mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL) >= 0);
test_mount_propagation_flags("shared", 0, MS_SHARED); test_mount_propagation_flags("shared", 0, MS_SHARED);
test_mount_propagation_flags("slave", 0, MS_SLAVE); test_mount_propagation_flags("slave", 0, MS_SLAVE);
test_mount_propagation_flags("private", 0, MS_PRIVATE); test_mount_propagation_flags("private", 0, MS_PRIVATE);