1
0
mirror of https://github.com/systemd/systemd synced 2025-11-08 19:34:45 +01:00

Compare commits

..

No commits in common. "d08a6ec39c2cb786bbf8ba2a8d480ada2973ad59" and "44dcb318cc44c0830ec9ebfbf35eca2b3f67f9fd" have entirely different histories.

45 changed files with 262 additions and 726 deletions

3
NEWS
View File

@ -819,9 +819,6 @@ CHANGES WITH 243:
* systemd-networkd's TUN support gained a new setting VnetHeader= for
tweaking Generic Segment Offload support.
* The address family for policy rules may be specified using the new
Family= option in the [RoutingPolicyRule] section.
* networkctl gained a new "delete" command for removing virtual network
devices, as well as a new "--stats" switch for showing device
statistics.

21
TODO
View File

@ -22,12 +22,6 @@ Janitorial Clean-ups:
Features:
* machined: add API to acquire UID range. add API to mount/dissect loopback
file. Both protected by PK. Then make nspawn use these APIs to run
unprivileged containers. i.e. push the truly privileged bits into machined,
so that the client side can remain entirely unprivileged, with SUID or
anything like that.
* add "throttling" to sd-event event sources: optionally, when we wake up too
often for one, let's turn it off entirely for a while. Use that for the
/proc/self/mountinfo logic.
@ -1209,14 +1203,17 @@ Features:
* networkd:
- add more keys to [Route] and [Address] sections
- add support for more DHCPv4 options (and, longer term, other kinds of dynamic config)
- add proper initrd support (in particular generate .network/.link files based on /proc/cmdline)
- add reduced [Link] support to .network files
- add Scope= parsing option for [Network]
- properly handle routerless dhcp leases
- work with non-Ethernet devices
- add support for more bond options
- dhcp: do we allow configuring dhcp routes on interfaces that are not the one we got the dhcp info from?
- the DHCP lease data (such as NTP/DNS) is still made available when
a carrier is lost on a link. It should be removed instantly.
- expose in the API the following bits:
- option 15, domain name
- option 15, domain name and/or option 119, search list
- option 12, hostname and/or option 81, fqdn
- option 123, 144, geolocation
- option 252, configure http proxy (PAC/wpad)
@ -1225,8 +1222,12 @@ Features:
- allow Name= to be specified repeatedly in the [Match] section. Maybe also
support Name=foo*|bar*|baz ?
- duplicate address check for static IPs (like ARPCHECK in network-scripts)
- allow DUID/IAID to be customized, see issue #394.
- whenever uplink info changes, make DHCP server send out FORCERENEW
* networkd-wait-online:
- make operstates to wait for configurable?
* dhcp:
- figure out how much we can increase Maximum Message Size
@ -1250,14 +1251,20 @@ External:
- natively watch for dbus-*.service symlinks (PENDING)
- teach dbus to activate all services it finds in /etc/systemd/services/org-*.service
* fix alsa mixer restore to not print error when no config is stored
* make cryptsetup lower --iter-time
* patch kernel for xattr support in /dev, /proc/, /sys?
* kernel: add device_type = "fb", "fbcon" to class "graphics"
* /usr/bin/service should actually show the new command line
* fedora: suggest auto-restart on failure, but not on success and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus=
* fedora: F20: go timer units all the way, leave cron.daily for cron
* neither pkexec nor sudo initialize environ[] from the PAM environment?
* fedora: update policy to declare access mode and ownership of unit files to root:root 0644, and add an rpmlint check for it

View File

@ -41,7 +41,7 @@
character are ignored. Each of the remaining lines describes one
encrypted block device. Fields are delimited by white space.</para>
<para>Each line is in the form<programlisting><replaceable>volume-name</replaceable> <replaceable>encrypted-device</replaceable> <replaceable>key-file</replaceable> <replaceable>options</replaceable></programlisting>
<para>Each line is in the form<programlisting><replaceable>name</replaceable> <replaceable>encrypted-device</replaceable> <replaceable>password</replaceable> <replaceable>options</replaceable></programlisting>
The first two fields are mandatory, the remaining two are
optional.</para>
@ -53,20 +53,24 @@
it is opened as a LUKS device; otherwise, it is assumed to be in
raw dm-crypt (plain mode) format.</para>
<para>The first field contains the name of the resulting encrypted volume; its block device is set up
below <filename>/dev/mapper/</filename>.</para>
<para>The first field contains the name of the resulting encrypted
block device; the device is set up within
<filename>/dev/mapper/</filename>.</para>
<para>The second field contains a path to the underlying block
device or file, or a specification of a block device via
<literal>UUID=</literal> followed by the UUID.</para>
<para>The third field specifies an absolute path to a file to read the encryption key from. If the field
is not present or set to <literal>none</literal> or <literal>-</literal>, a key file named after the
volume to unlock (i.e. the first column of the line), suffixed with <filename>.key</filename> is
automatically loaded from the <filename>/etc/cryptsetup-keys.d/</filename> and
<filename>/run/cryptsetup-keys.d/</filename> directories, if present. Otherwise, the password has to be
manually entered during system boot. For swap encryption, <filename>/dev/urandom</filename> may be used
as key file.</para>
<para>The third field specifies the encryption password. If the
field is not present or the password is set to
<literal>none</literal> or <literal>-</literal>, the password has
to be manually entered during system boot. Otherwise, the field is
interpreted as an absolute path to a file containing the encryption
password. For swap encryption, <filename>/dev/urandom</filename>
or the hardware device <filename>/dev/hw_random</filename> can be
used as the password file; using <filename>/dev/random</filename>
may prevent boot completion if the system does not have enough
entropy to generate a truly random encryption key.</para>
<para>The fourth field, if present, is a comma-delimited list of
options. The following options are recognized:</para>
@ -134,15 +138,6 @@
size is then given by the key size.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>keyfile-erase</option></term>
<listitem><para>If enabled, the specified key file is erased after the volume is activated or when
activation fails. This is in particular useful when the key file is only acquired transiently before
activation (e.g. via a file in <filename>/run/</filename>, generated by a service running before
activation), and shall be removed after use. Defaults to off.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>key-slot=</option></term>
@ -436,15 +431,6 @@
before it is used to unlock the LUKS volume.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>try-empty-password=</option></term>
<listitem><para>Takes a boolean argument. If enabled, right before asking the user for a password it
is first attempted to unlock the volume with an empty password. This is useful for systems that are
initialized with an encrypted volume with only an empty password set, which shall be replaced with a
suitable password during first boot, but after activation.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>x-systemd.device-timeout=</option></term>

View File

@ -159,7 +159,7 @@ net.bridge.bridge-nf-call-arptables = 0
<example>
<title>Set network routing properties for all interfaces</title>
<para><filename>/etc/sysctl.d/20-rp_filter.conf</filename>:</para>
<para><filename>/etc/systemd/20-rp_filter.conf</filename>:</para>
<programlisting>net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.*.rp_filter = 2

View File

@ -44,32 +44,6 @@
<para>At early boot and when the system manager configuration is reloaded, <filename>/etc/crypttab</filename> is
translated into <filename>systemd-cryptsetup@.service</filename> units by
<citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<para>In order to unlock a volume a password or binary key is
required. <filename>systemd-cryptsetup@.service</filename> tries to acquire a suitable password or binary
key via the following mechanisms, tried in order:</para>
<orderedlist>
<listitem><para>If a key file is explicitly configured (via the third column in
<filename>/etc/crypttab</filename>), a key read from it is used. If a PKCS#11 token is configured
(using the <varname>pkcs11-uri=</varname> option) the key is decrypted before use.</para></listitem>
<listitem><para>If no key file is configured explicitly this way, a key file is automatically loaded
from <filename>/etc/cryptsetup-keys.d/<replaceable>volume</replaceable>.key</filename> and
<filename>/run/cryptsetup-keys.d/<replaceable>volume</replaceable>.key</filename>, if present. Here
too, if a PKCS#11 token is configured, any key found this way is decrypted before
use.</para></listitem>
<listitem><para>If the <varname>try-empty-password</varname> option is specified it is then attempted
to unlock the volume with an empty password.</para></listitem>
<listitem><para>The kernel keyring is then checked for a suitable cached password from previous
attempts.</para></listitem>
<listitem><para>Finally, the user is queried for a password, possibly multiple times.</para></listitem>
</orderedlist>
<para>If no suitable key may be acquired via any of the mechanisms describes above, volume activation fails.</para>
</refsect1>
<refsect1>

View File

@ -1774,20 +1774,6 @@
option numbers, the option number is an integer in the range 1..65536.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UserClass=</varname></term>
<listitem>
<para>A DHCPv6 client can use User Class option to identify the type or category of user or applications
it represents. The information contained in this option is a string that represents the user class of which
the client is a member. Each class sets an identifying string of information to be used by the DHCP
service to classify clients. Special characters in the data string may be escaped using
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
then all options specified earlier are cleared. Takes a whitespace-separated list of strings. Note that
currently NUL bytes are not allowed.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -23,9 +23,8 @@ dd if=/dev/urandom of=plaintext.bin bs=128 count=1
base64 < plaintext.bin | tr -d '\n\r\t ' > plaintext.base64
# Encrypt this newly generated (binary) LUKS decryption key using the public key whose private key is on the
# Yubikey, store the result in /etc/cryptsetup-keys.d/mytest.key, where we'll look for it during boot.
mkdir -p /etc/cryptsetup-keys.d
sudo openssl rsautl -encrypt -pubin -inkey pubkey.pem -in plaintext.bin -out /etc/cryptsetup-keys.d/mytest.key
# Yubikey, store the result in /etc/encrypted-luks-key.bin, where we'll look for it during boot.
sudo openssl rsautl -encrypt -pubin -inkey pubkey.pem -in plaintext.bin -out /etc/encrypted-luks-key.bin
# Configure the LUKS decryption key on the LUKS device. We use very low pbkdf settings since the key already
# has quite a high quality (it comes directly from /dev/urandom after all), and thus we don't need to do much
@ -41,10 +40,8 @@ shred -u plaintext.bin plaintext.base64
rm pubkey.pem
# Test: Let's run systemd-cryptsetup to test if this all worked. The option string should contain the full
# PKCS#11 URI we have in the clipboard; it tells the tool how to decipher the encrypted LUKS key. Note that
# systemd-cryptsetup automatically searches for the encrypted key in /etc/cryptsetup-keys.d/, hence we do
# not need to specify the key file path explicitly here.
sudo systemd-cryptsetup attach mytest /dev/sdXn - 'pkcs11-uri=pkcs11:…'
# PKCS#11 URI we have in the clipboard, it tells the tool how to decipher the encrypted LUKS key.
sudo systemd-cryptsetup attach mytest /dev/sdXn /etc/encrypted-luks-key.bin 'pkcs11-uri=pkcs11:…'
# If that worked, let's now add the same line persistently to /etc/crypttab, for the future.
sudo bash -c 'echo "mytest /dev/sdXn - \'pkcs11-uri=pkcs11:…\'" >> /etc/crypttab'
sudo bash -c 'echo "mytest /dev/sdXn /etc/encrypted-luks-key \'pkcs11-uri=pkcs11:…\'" >> /etc/crypttab'

View File

@ -2227,10 +2227,8 @@ executable(
if conf.get('HAVE_LIBCRYPTSETUP') == 1
systemd_cryptsetup_sources = files('''
src/cryptsetup/cryptsetup-pkcs11.h
src/cryptsetup/cryptsetup-util.c
src/cryptsetup/cryptsetup-util.h
src/cryptsetup/cryptsetup.c
src/cryptsetup/cryptsetup-pkcs11.h
'''.split())
if conf.get('HAVE_P11KIT') == 1

View File

@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <sys/file.h>
#include <unistd.h>
#include "alloc-util.h"
@ -30,8 +29,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
*ret = d;
return 0;
}
if (errno != ENOENT)
return -errno;
/* If it is a partition find the originating device */
xsprintf_sys_block_path(p, "/partition", d);
@ -188,29 +185,3 @@ int get_block_device_harder(const char *path, dev_t *ret) {
return 1;
}
int lock_whole_block_device(dev_t devt, int operation) {
_cleanup_free_ char *whole_node = NULL;
_cleanup_close_ int lock_fd = -1;
dev_t whole_devt;
int r;
/* Let's get a BSD file lock on the whole block device, as per: https://systemd.io/BLOCK_DEVICE_LOCKING */
r = block_get_whole_disk(devt, &whole_devt);
if (r < 0)
return r;
r = device_path_make_major_minor(S_IFBLK, whole_devt, &whole_node);
if (r < 0)
return r;
lock_fd = open(whole_node, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (lock_fd < 0)
return -errno;
if (flock(lock_fd, operation) < 0)
return -errno;
return TAKE_FD(lock_fd);
}

View File

@ -18,5 +18,3 @@ int block_get_originating(dev_t d, dev_t *ret);
int get_block_device(const char *path, dev_t *dev);
int get_block_device_harder(const char *path, dev_t *dev);
int lock_whole_block_device(dev_t devt, int operation);

View File

@ -319,7 +319,7 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
return -errno;
if (!S_ISBLK(st.st_mode))
return -ENOTBLK;
return -ENODEV;
if (major(st.st_rdev) == 0)
return -ENODEV;

View File

@ -23,7 +23,6 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
@ -1304,13 +1303,11 @@ void unlink_tempfilep(char (*p)[]) {
(void) unlink_noerrno(*p);
}
int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
int unlinkat_deallocate(int fd, const char *name, int flags) {
_cleanup_close_ int truncate_fd = -1;
struct stat st;
off_t l, bs;
assert((flags & ~(UNLINK_REMOVEDIR|UNLINK_ERASE)) == 0);
/* Operates like unlinkat() but also deallocates the file contents if it is a regular file and there's no other
* link to it. This is useful to ensure that other processes that might have the file open for reading won't be
* able to keep the data pinned on disk forever. This call is particular useful whenever we execute clean-up
@ -1327,7 +1324,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
* Note that we attempt deallocation, but failure to succeed with that is not considered fatal, as long as the
* primary job to delete the file is accomplished. */
if (!FLAGS_SET(flags, UNLINK_REMOVEDIR)) {
if ((flags & AT_REMOVEDIR) == 0) {
truncate_fd = openat(fd, name, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK);
if (truncate_fd < 0) {
@ -1343,7 +1340,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
}
}
if (unlinkat(fd, name, FLAGS_SET(flags, UNLINK_REMOVEDIR) ? AT_REMOVEDIR : 0) < 0)
if (unlinkat(fd, name, flags) < 0)
return -errno;
if (truncate_fd < 0) /* Don't have a file handle, can't do more ☹️ */
@ -1354,45 +1351,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
return 0;
}
if (!S_ISREG(st.st_mode))
return 0;
if (FLAGS_SET(flags, UNLINK_ERASE) && st.st_size > 0 && st.st_nlink == 0) {
uint64_t left = st.st_size;
char buffer[64 * 1024];
/* If erasing is requested, let's overwrite the file with random data once before deleting
* it. This isn't going to give you shred(1) semantics, but hopefully should be good enough
* for stuff backed by tmpfs at least.
*
* Note that we only erase like this if the link count of the file is zero. If it is higer it
* is still linked by someone else and we'll leave it to them to remove it securely
* eventually! */
random_bytes(buffer, sizeof(buffer));
while (left > 0) {
ssize_t n;
n = write(truncate_fd, buffer, MIN(sizeof(buffer), left));
if (n < 0) {
log_debug_errno(errno, "Failed to erase data in file '%s', ignoring.", name);
break;
}
assert(left >= (size_t) n);
left -= n;
}
/* Let's refresh metadata */
if (fstat(truncate_fd, &st) < 0) {
log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring: %m", name);
return 0;
}
}
/* Don't dallocate if there's nothing to deallocate or if the file is linked elsewhere */
if (st.st_blocks == 0 || st.st_nlink > 0)
if (!S_ISREG(st.st_mode) || st.st_blocks == 0 || st.st_nlink > 0)
return 0;
/* If this is a regular file, it actually took up space on disk and there are no other links it's time to

View File

@ -113,13 +113,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free);
int access_fd(int fd, int mode);
void unlink_tempfilep(char (*p)[]);
typedef enum UnlinkDeallocateFlags {
UNLINK_REMOVEDIR = 1 << 0,
UNLINK_ERASE = 1 << 1,
} UnlinkDeallocateFlags;
int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
int fsync_full(int fd);

View File

@ -61,11 +61,11 @@ int glob_exists(const char *path) {
return true;
}
int glob_extend(char ***strv, const char *path, int flags) {
int glob_extend(char ***strv, const char *path) {
_cleanup_globfree_ glob_t g = {};
int k;
k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE|flags, &g);
k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
if (k < 0)
return k;

View File

@ -11,7 +11,7 @@
int safe_glob(const char *path, int flags, glob_t *pglob);
int glob_exists(const char *path);
int glob_extend(char ***strv, const char *path, int flags);
int glob_extend(char ***strv, const char *path);
#define _cleanup_globfree_ _cleanup_(globfree)

View File

@ -1051,7 +1051,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
if (!path)
return -ENOMEM;
r = glob_extend(&names, path, 0);
r = glob_extend(&names, path);
if (r == -ENOENT)
continue;
if (r < 0)

View File

@ -856,24 +856,20 @@ static int on_interface(const char *interface, uint64_t flags, void *userdata) {
assert(interface);
assert(members);
m = new(Member, 1);
m = new0(Member, 1);
if (!m)
return log_oom();
*m = (Member) {
.type = "interface",
.flags = flags,
};
m->type = "interface";
m->flags = flags;
r = free_and_strdup(&m->interface, interface);
if (r < 0)
return log_oom();
r = set_put(members, m);
if (r == -EEXIST)
return log_error_errno(r, "Invalid introspection data: duplicate interface '%s'.", interface);
if (r < 0)
return log_oom();
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate interface");
m = NULL;
return 0;
@ -887,14 +883,12 @@ static int on_method(const char *interface, const char *name, const char *signat
assert(interface);
assert(name);
m = new(Member, 1);
m = new0(Member, 1);
if (!m)
return log_oom();
*m = (Member) {
.type = "method",
.flags = flags,
};
m->type = "method";
m->flags = flags;
r = free_and_strdup(&m->interface, interface);
if (r < 0)
@ -913,10 +907,8 @@ static int on_method(const char *interface, const char *name, const char *signat
return log_oom();
r = set_put(members, m);
if (r == -EEXIST)
return log_error_errno(r, "Invalid introspection data: duplicate method '%s' on interface '%s'.", name, interface);
if (r < 0)
return log_oom();
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate method");
m = NULL;
return 0;
@ -930,14 +922,12 @@ static int on_signal(const char *interface, const char *name, const char *signat
assert(interface);
assert(name);
m = new(Member, 1);
m = new0(Member, 1);
if (!m)
return log_oom();
*m = (Member) {
.type = "signal",
.flags = flags,
};
m->type = "signal";
m->flags = flags;
r = free_and_strdup(&m->interface, interface);
if (r < 0)
@ -952,10 +942,8 @@ static int on_signal(const char *interface, const char *name, const char *signat
return log_oom();
r = set_put(members, m);
if (r == -EEXIST)
return log_error_errno(r, "Invalid introspection data: duplicate signal '%s' on interface '%s'.", name, interface);
if (r < 0)
return log_oom();
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate signal");
m = NULL;
return 0;
@ -969,15 +957,13 @@ static int on_property(const char *interface, const char *name, const char *sign
assert(interface);
assert(name);
m = new(Member, 1);
m = new0(Member, 1);
if (!m)
return log_oom();
*m = (Member) {
.type = "property",
.flags = flags,
.writable = writable,
};
m->type = "property";
m->flags = flags;
m->writable = writable;
r = free_and_strdup(&m->interface, interface);
if (r < 0)
@ -992,10 +978,8 @@ static int on_property(const char *interface, const char *name, const char *sign
return log_oom();
r = set_put(members, m);
if (r == -EEXIST)
return log_error_errno(r, "Invalid introspection data: duplicate property '%s' on interface '%s'.", name, interface);
if (r < 0)
return log_oom();
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate property");
m = NULL;
return 0;

View File

@ -237,7 +237,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_FILE:
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
r = glob_extend(&arg_file, optarg);
if (r < 0)
return log_error_errno(r, "Failed to add paths: %m");
break;

View File

@ -188,11 +188,7 @@ static int print_dependencies(FILE *f, const char* device_path) {
/* None, nothing to do */
return 0;
if (PATH_IN_SET(device_path,
"/dev/urandom",
"/dev/random",
"/dev/hw_random",
"/dev/hwrng")) {
if (PATH_IN_SET(device_path, "/dev/urandom", "/dev/random", "/dev/hw_random")) {
/* RNG device, add random dep */
fputs("After=systemd-random-seed.service\n", f);
return 0;
@ -213,9 +209,7 @@ static int print_dependencies(FILE *f, const char* device_path) {
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
fprintf(f,
"After=%1$s\n"
"Requires=%1$s\n", unit);
fprintf(f, "After=%1$s\nRequires=%1$s\n", unit);
} else {
/* Regular file, add mount dependency */
_cleanup_free_ char *escaped_path = specifier_escape(device_path);
@ -373,12 +367,12 @@ static int create_disk(
if (tmp)
fprintf(f,
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs ext2 '/dev/mapper/%s'\n",
"ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
name_escaped);
if (swap)
fprintf(f,
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs swap '/dev/mapper/%s'\n",
"ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
name_escaped);
if (keydev)

View File

@ -10,7 +10,6 @@
#include "alloc-util.h"
#include "ask-password-api.h"
#include "cryptsetup-pkcs11.h"
#include "cryptsetup-util.h"
#include "escape.h"
#include "fd-util.h"
#include "format-util.h"
@ -20,6 +19,73 @@
#include "stat-util.h"
#include "strv.h"
#define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
static int load_key_file(
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
void **ret_encrypted_key,
size_t *ret_encrypted_key_size) {
_cleanup_(erase_and_freep) char *buffer = NULL;
_cleanup_close_ int fd = -1;
ssize_t n;
int r;
assert(key_file);
assert(ret_encrypted_key);
assert(ret_encrypted_key_size);
fd = open(key_file, O_RDONLY|O_CLOEXEC);
if (fd < 0)
return log_error_errno(errno, "Failed to load encrypted PKCS#11 key: %m");
if (key_file_size == 0) {
struct stat st;
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to stat key file: %m");
r = stat_verify_regular(&st);
if (r < 0)
return log_error_errno(r, "Key file is not a regular file: %m");
if (st.st_size == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file is empty, refusing.");
if ((uint64_t) st.st_size > KEY_FILE_SIZE_MAX) {
char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
"Key file larger (%s) than allowed maximum size (%s), refusing.",
format_bytes(buf1, sizeof(buf1), st.st_size),
format_bytes(buf2, sizeof(buf2), KEY_FILE_SIZE_MAX));
}
if (key_file_offset >= (uint64_t) st.st_size)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file offset too large for file, refusing.");
key_file_size = st.st_size - key_file_offset;
}
buffer = malloc(key_file_size);
if (!buffer)
return log_oom();
if (key_file_offset > 0)
n = pread(fd, buffer, key_file_size, key_file_offset);
else
n = read(fd, buffer, key_file_size);
if (n < 0)
return log_error_errno(errno, "Failed to read PKCS#11 key file: %m");
if (n == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty encrypted key found, refusing.");
*ret_encrypted_key = TAKE_PTR(buffer);
*ret_encrypted_key_size = (size_t) n;
return 0;
}
struct pkcs11_callback_data {
const char *friendly_name;
usec_t until;
@ -27,14 +93,11 @@ struct pkcs11_callback_data {
size_t encrypted_key_size;
void *decrypted_key;
size_t decrypted_key_size;
bool free_encrypted_key;
};
static void pkcs11_callback_data_release(struct pkcs11_callback_data *data) {
free(data->decrypted_key);
if (data->free_encrypted_key)
free(data->encrypted_key);
free(data->encrypted_key);
}
static int pkcs11_callback(
@ -97,11 +160,9 @@ static int pkcs11_callback(
int decrypt_pkcs11_key(
const char *friendly_name,
const char *pkcs11_uri,
const char *key_file, /* We either expect key_file and associated parameters to be set (for file keys) … */
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
const void *key_data, /* … or key_data and key_data_size (for literal keys) */
size_t key_data_size,
usec_t until,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {
@ -114,24 +175,15 @@ int decrypt_pkcs11_key(
assert(friendly_name);
assert(pkcs11_uri);
assert(key_file || key_data);
assert(key_file);
assert(ret_decrypted_key);
assert(ret_decrypted_key_size);
/* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
if (key_data) {
data.encrypted_key = (void*) key_data;
data.encrypted_key_size = key_data_size;
data.free_encrypted_key = false;
} else {
r = load_key_file(key_file, NULL, key_file_size, key_file_offset, &data.encrypted_key, &data.encrypted_key_size);
if (r < 0)
return r;
data.free_encrypted_key = true;
}
r = load_key_file(key_file, key_file_size, key_file_offset, &data.encrypted_key, &data.encrypted_key_size);
if (r < 0)
return r;
r = pkcs11_find_token(pkcs11_uri, pkcs11_callback, &data);
if (r < 0)

View File

@ -14,8 +14,6 @@ int decrypt_pkcs11_key(
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
const void *key_data,
size_t key_data_size,
usec_t until,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size);
@ -28,8 +26,6 @@ static inline int decrypt_pkcs11_key(
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
const void *key_data,
size_t key_data_size,
usec_t until,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {

View File

@ -1,110 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <unistd.h>
#include "cryptsetup-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "memory-util.h"
#include "path-util.h"
#include "stat-util.h"
#include "strv.h"
#define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
int load_key_file(
const char *key_file,
char **search_path,
size_t key_file_size,
uint64_t key_file_offset,
void **ret_key,
size_t *ret_key_size) {
_cleanup_(erase_and_freep) char *buffer = NULL;
_cleanup_free_ char *discovered_path = NULL;
_cleanup_close_ int fd = -1;
ssize_t n;
int r;
assert(key_file);
assert(ret_key);
assert(ret_key_size);
if (strv_isempty(search_path) || path_is_absolute(key_file)) {
fd = open(key_file, O_RDONLY|O_CLOEXEC);
if (fd < 0)
return log_error_errno(errno, "Failed to load key file '%s': %m", key_file);
} else {
char **i;
STRV_FOREACH(i, search_path) {
_cleanup_free_ char *joined;
joined = path_join(*i, key_file);
if (!joined)
return log_oom();
fd = open(joined, O_RDONLY|O_CLOEXEC);
if (fd >= 0) {
discovered_path = TAKE_PTR(joined);
break;
}
if (errno != ENOENT)
return log_error_errno(errno, "Failed to load key file '%s': %m", joined);
}
if (!discovered_path) {
/* Search path supplied, but file not found, report by returning NULL, but not failing */
*ret_key = NULL;
*ret_key_size = 0;
return 0;
}
assert(fd >= 0);
key_file = discovered_path;
}
if (key_file_size == 0) {
struct stat st;
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to stat key file '%s': %m", key_file);
r = stat_verify_regular(&st);
if (r < 0)
return log_error_errno(r, "Key file is not a regular file: %m");
if (st.st_size == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file is empty, refusing.");
if ((uint64_t) st.st_size > KEY_FILE_SIZE_MAX) {
char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
"Key file larger (%s) than allowed maximum size (%s), refusing.",
format_bytes(buf1, sizeof(buf1), st.st_size),
format_bytes(buf2, sizeof(buf2), KEY_FILE_SIZE_MAX));
}
if (key_file_offset >= (uint64_t) st.st_size)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file offset too large for file, refusing.");
key_file_size = st.st_size - key_file_offset;
}
buffer = malloc(key_file_size);
if (!buffer)
return log_oom();
if (key_file_offset > 0)
n = pread(fd, buffer, key_file_size, key_file_offset);
else
n = read(fd, buffer, key_file_size);
if (n < 0)
return log_error_errno(errno, "Failed to read key file '%s': %m", key_file);
if (n == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty encrypted key found, refusing.");
*ret_key = TAKE_PTR(buffer);
*ret_key_size = (size_t) n;
return 1;
}

View File

@ -1,13 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <inttypes.h>
#include <sys/types.h>
int load_key_file(
const char *key_file,
char **search_path,
size_t key_file_size,
uint64_t key_file_offset,
void **ret_key,
size_t *ret_key_size);

View File

@ -13,16 +13,13 @@
#include "ask-password-api.h"
#include "crypt-util.h"
#include "cryptsetup-pkcs11.h"
#include "cryptsetup-util.h"
#include "device-util.h"
#include "escape.h"
#include "fileio.h"
#include "fs-util.h"
#include "fstab-util.h"
#include "hexdecoct.h"
#include "log.h"
#include "main-func.h"
#include "memory-util.h"
#include "mount-util.h"
#include "nulstr-util.h"
#include "parse-util.h"
@ -45,8 +42,6 @@ static unsigned arg_sector_size = CRYPT_SECTOR_SIZE;
static int arg_key_slot = CRYPT_ANY_SLOT;
static unsigned arg_keyfile_size = 0;
static uint64_t arg_keyfile_offset = 0;
static bool arg_keyfile_erase = false;
static bool arg_try_empty_password = false;
static char *arg_hash = NULL;
static char *arg_header = NULL;
static unsigned arg_tries = 3;
@ -72,14 +67,12 @@ STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
/* Options Debian's crypttab knows we don't:
precheck=
check=
checkargs=
noearly
loud
quiet
noearly=
loud=
keyscript=
tmp= (the version without argument is supported)
initramfs
*/
static int parse_one_option(const char *option) {
@ -133,8 +126,7 @@ static int parse_one_option(const char *option) {
return 0;
}
} else if ((val = startswith(option, "key-slot=")) ||
(val = startswith(option, "keyslot="))) {
} else if ((val = startswith(option, "key-slot="))) {
arg_type = ANY_LUKS;
r = safe_atoi(val, &arg_key_slot);
@ -168,20 +160,7 @@ static int parse_one_option(const char *option) {
return 0;
}
} else if ((val = startswith(option, "keyfile-erase="))) {
r = parse_boolean(val);
if (r < 0) {
log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
return 0;
}
arg_keyfile_erase = r;
} else if (streq(option, "keyfile-erase"))
arg_keyfile_erase = true;
else if ((val = startswith(option, "hash="))) {
} else if ((val = startswith(option, "hash="))) {
r = free_and_strdup(&arg_hash, val);
if (r < 0)
return log_oom();
@ -223,13 +202,13 @@ static int parse_one_option(const char *option) {
arg_type = ANY_LUKS;
else if (streq(option, "tcrypt"))
arg_type = CRYPT_TCRYPT;
else if (STR_IN_SET(option, "tcrypt-hidden", "tcrypthidden")) {
else if (streq(option, "tcrypt-hidden")) {
arg_type = CRYPT_TCRYPT;
arg_tcrypt_hidden = true;
} else if (streq(option, "tcrypt-system")) {
arg_type = CRYPT_TCRYPT;
arg_tcrypt_system = true;
} else if (STR_IN_SET(option, "tcrypt-veracrypt", "veracrypt")) {
} else if (streq(option, "tcrypt-veracrypt")) {
arg_type = CRYPT_TCRYPT;
arg_tcrypt_veracrypt = true;
} else if (STR_IN_SET(option, "plain", "swap", "tmp"))
@ -263,20 +242,7 @@ static int parse_one_option(const char *option) {
if (r < 0)
return log_oom();
} else if ((val = startswith(option, "try-empty-password="))) {
r = parse_boolean(val);
if (r < 0) {
log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
return 0;
}
arg_try_empty_password = r;
} else if (streq(option, "try-empty-password"))
arg_try_empty_password = true;
else if (!streq(option, "x-initrd.attach"))
} else if (!streq(option, "x-initrd.attach"))
log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
return 0;
@ -474,8 +440,6 @@ static int attach_tcrypt(
struct crypt_device *cd,
const char *name,
const char *key_file,
const void *key_data,
size_t key_data_size,
char **passwords,
uint32_t flags) {
@ -489,7 +453,7 @@ static int attach_tcrypt(
assert(cd);
assert(name);
assert(key_file || key_data || !strv_isempty(passwords));
assert(key_file || (passwords && passwords[0]));
if (arg_pkcs11_uri)
/* Ask for a regular password */
@ -505,33 +469,22 @@ static int attach_tcrypt(
if (arg_tcrypt_veracrypt)
params.flags |= CRYPT_TCRYPT_VERA_MODES;
if (key_data) {
params.passphrase = key_data;
params.passphrase_size = key_data_size;
} else {
if (key_file) {
r = read_one_line_file(key_file, &passphrase);
if (r < 0) {
log_error_errno(r, "Failed to read password file '%s': %m", key_file);
return -EAGAIN; /* log with the actual error, but return EAGAIN */
}
if (key_file) {
r = read_one_line_file(key_file, &passphrase);
if (r < 0) {
log_error_errno(r, "Failed to read password file '%s': %m", key_file);
return -EAGAIN; /* log with the actual error, but return EAGAIN */
}
params.passphrase = passphrase;
} else
params.passphrase = passwords[0];
params.passphrase_size = strlen(params.passphrase);
}
params.passphrase = passphrase;
} else
params.passphrase = passwords[0];
params.passphrase_size = strlen(params.passphrase);
r = crypt_load(cd, CRYPT_TCRYPT, &params);
if (r < 0) {
if (r == -EPERM) {
if (key_data)
log_error_errno(r, "Failed to activate using discovered key. (Key not correct?)");
if (key_file)
log_error_errno(r, "Failed to activate using password file '%s'. (Key data not correct?)", key_file);
if (key_file && r == -EPERM) {
log_error_errno(r, "Failed to activate using password file '%s'. (Key data not correct?)", key_file);
return -EAGAIN; /* log the actual error, but return EAGAIN */
}
@ -549,8 +502,6 @@ static int attach_luks_or_plain(
struct crypt_device *cd,
const char *name,
const char *key_file,
const void *key_data,
size_t key_data_size,
char **passwords,
uint32_t flags,
usec_t until) {
@ -620,7 +571,7 @@ static int attach_luks_or_plain(
_cleanup_free_ char *friendly = NULL;
size_t decrypted_key_size = 0;
if (!key_file && !key_data)
if (!key_file)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing.");
friendly = friendly_disk_name(crypt_get_device_name(cd), name);
@ -633,8 +584,8 @@ static int attach_luks_or_plain(
r = decrypt_pkcs11_key(
friendly,
arg_pkcs11_uri,
key_file, arg_keyfile_size, arg_keyfile_offset,
key_data, key_data_size,
key_file,
arg_keyfile_size, arg_keyfile_offset,
until,
&decrypted_key, &decrypted_key_size);
if (r >= 0)
@ -669,7 +620,7 @@ static int attach_luks_or_plain(
return log_error_errno(r, "Failed to start device monitor: %m");
log_notice("Security token %s not present for unlocking volume %s, please plug it in.",
arg_pkcs11_uri, friendly);
arg_pkcs11_uri, friendly);
/* Let's immediately rescan in case the token appeared in the time we needed
* to create and configure the monitor */
@ -717,18 +668,6 @@ static int attach_luks_or_plain(
if (r < 0)
return log_error_errno(r, "Failed to activate with PKCS#11 acquired key: %m");
} else if (key_data) {
if (pass_volume_key)
r = crypt_activate_by_volume_key(cd, name, key_data, key_data_size, flags);
else
r = crypt_activate_by_passphrase(cd, name, arg_key_slot, key_data, key_data_size, flags);
if (r == -EPERM) {
log_error_errno(r, "Failed to activate. (Key incorrect?)");
return -EAGAIN; /* Log actual error, but return EAGAIN */
}
if (r < 0)
return log_error_errno(r, "Failed to activate: %m");
} else if (key_file) {
r = crypt_activate_by_keyfile_device_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags);
if (r == -EPERM) {
@ -809,17 +748,6 @@ static uint32_t determine_flags(void) {
return flags;
}
static void remove_and_erasep(const char **p) {
int r;
if (!*p)
return;
r = unlinkat_deallocate(AT_FDCWD, *p, UNLINK_ERASE);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Unable to erase key file '%s', ignoring: %m", *p);
}
static int run(int argc, char *argv[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
int r;
@ -846,19 +774,13 @@ static int run(int argc, char *argv[]) {
unsigned tries;
usec_t until;
crypt_status_info status;
_cleanup_(remove_and_erasep) const char *destroy_key_file = NULL;
const char *key_file = NULL;
_cleanup_(erase_and_freep) void *key_data = NULL;
size_t key_data_size = 0;
/* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
if (argc < 4)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least two arguments.");
if (!filename_is_valid(argv[2]))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", argv[2]);
if (argc >= 5 && !STR_IN_SET(argv[4], "", "-", "none")) {
if (path_is_absolute(argv[4]))
key_file = argv[4];
@ -875,24 +797,6 @@ static int run(int argc, char *argv[]) {
/* A delicious drop of snake oil */
(void) mlockall(MCL_FUTURE);
if (!key_file) {
const char *fn;
/* If a key file is not explicitly specified, search for a key in a well defined
* search path, and load it. */
fn = strjoina(argv[2], ".key");
r = load_key_file(fn,
STRV_MAKE("/etc/cryptsetup-keys.d", "/run/cryptsetup-keys.d"),
0, 0, /* Note we leave arg_keyfile_offset/arg_keyfile_size as something that only applies to arg_keyfile! */
&key_data, &key_data_size);
if (r < 0)
return r;
if (r > 0)
log_debug("Automatically discovered key for volume '%s'.", argv[2]);
} else if (arg_keyfile_erase)
destroy_key_file = key_file; /* let's get this baby erased when we leave */
if (arg_header) {
log_debug("LUKS header: %s", arg_header);
r = crypt_init(&cd, arg_header);
@ -939,7 +843,7 @@ static int run(int argc, char *argv[]) {
}
/* Tokens are available in LUKS2 only, but it is ok to call (and fail) with LUKS1. */
if (!key_file && !key_data) {
if (!key_file) {
r = crypt_activate_by_token(cd, argv[2], CRYPT_ANY_TOKEN, NULL, flags);
if (r >= 0) {
log_debug("Volume %s activated with LUKS token id %i.", argv[2], r);
@ -953,53 +857,26 @@ static int run(int argc, char *argv[]) {
for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) {
_cleanup_strv_free_erase_ char **passwords = NULL;
/* When we were able to acquire multiple keys, let's always process them in this order:
*
* 1. A key acquired via PKCS#11 token
* 2. The discovered key: i.e. key_data + key_data_size
* 3. The configured key: i.e. key_file + arg_keyfile_offset + arg_keyfile_size
* 4. The empty password, in case arg_try_empty_password is set
* 5. We enquire the user for a password
*/
if (!key_file && !key_data && !arg_pkcs11_uri) {
if (arg_try_empty_password) {
/* Hmm, let's try an empty password now, but only once */
arg_try_empty_password = false;
key_data = strdup("");
if (!key_data)
return log_oom();
key_data_size = 0;
} else {
/* Ask the user for a passphrase only as last resort, if we have
* nothing else to check for */
r = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords);
if (r == -EAGAIN)
continue;
if (r < 0)
return r;
}
if (!key_file && !arg_pkcs11_uri) {
r = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords);
if (r == -EAGAIN)
continue;
if (r < 0)
return r;
}
if (streq_ptr(arg_type, CRYPT_TCRYPT))
r = attach_tcrypt(cd, argv[2], key_file, key_data, key_data_size, passwords, flags);
r = attach_tcrypt(cd, argv[2], key_file, passwords, flags);
else
r = attach_luks_or_plain(cd, argv[2], key_file, key_data, key_data_size, passwords, flags, until);
r = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags, until);
if (r >= 0)
break;
if (r != -EAGAIN)
return r;
/* Key not correct? Let's try again! */
/* Passphrase not correct? Let's try again! */
key_file = NULL;
key_data = erase_and_free(key_data);
key_data_size = 0;
arg_pkcs11_uri = mfree(arg_pkcs11_uri);
arg_pkcs11_uri = NULL;
}
if (arg_tries != 0 && tries >= arg_tries)
@ -1007,9 +884,6 @@ static int run(int argc, char *argv[]) {
} else if (streq(argv[1], "detach")) {
if (!filename_is_valid(argv[2]))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", argv[2]);
r = crypt_init_by_name(&cd, argv[2]);
if (r == -ENODEV) {
log_info("Volume %s already inactive.", argv[2]);

View File

@ -720,7 +720,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_FILE:
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
r = glob_extend(&arg_file, optarg);
if (r < 0)
return log_error_errno(r, "Failed to add paths: %m");
break;

View File

@ -705,7 +705,7 @@ static int parse_argv(int argc, char *argv[]) {
* STDIN. To avoid confusion we hence don't document this feature. */
arg_file_stdin = true;
else {
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
r = glob_extend(&arg_file, optarg);
if (r < 0)
return log_error_errno(r, "Failed to add paths: %m");
}

View File

@ -97,7 +97,6 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class);
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
int dhcp6_option_parse_status(DHCP6Option *option, size_t len);

View File

@ -167,36 +167,6 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
return r;
}
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class) {
_cleanup_free_ uint8_t *p = NULL;
size_t total = 0, offset = 0;
char **s;
assert_return(buf && *buf && buflen && user_class, -EINVAL);
STRV_FOREACH(s, user_class) {
size_t len = strlen(*s);
uint8_t *q;
if (len > 0xffff)
return -ENAMETOOLONG;
q = realloc(p, total + len + 2);
if (!q)
return -ENOMEM;
p = q;
unaligned_write_be16(&p[offset], len);
memcpy(&p[offset + 2], *s, len);
offset += 2 + len;
total += 2 + len;
}
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p);
}
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) {
DHCP6Option *option = (DHCP6Option *)buf;
size_t i = sizeof(*option) + sizeof(pd->ia_pd);

View File

@ -67,7 +67,6 @@ struct sd_dhcp6_client {
size_t req_opts_len;
char *fqdn;
char *mudurl;
char **user_class;
sd_event_source *receive_message;
usec_t retransmit_time;
uint8_t retransmit_count;
@ -386,27 +385,6 @@ int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mud
return free_and_strdup(&client->mudurl, mudurl);
}
int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_class) {
_cleanup_strv_free_ char **s = NULL;
char **p;
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(user_class, -EINVAL);
STRV_FOREACH(p, user_class)
if (strlen(*p) > UINT16_MAX)
return -ENAMETOOLONG;
s = strv_copy((char **) user_class);
if (!s)
return -ENOMEM;
client->user_class = TAKE_PTR(s);
return 0;
}
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
assert_return(client, -EINVAL);
assert_return(delegation, -EINVAL);
@ -587,12 +565,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->user_class) {
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
if (r < 0)
@ -639,12 +611,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->user_class) {
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
@ -679,12 +645,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->user_class) {
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
@ -1642,10 +1602,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
free(client->req_opts);
free(client->fqdn);
free(client->mudurl);
ordered_hashmap_free(client->extra_options);
strv_free(client->user_class);
return mfree(client);
}

View File

@ -267,68 +267,6 @@ int config_parse_dhcp6_pd_hint(
return 0;
}
int config_parse_dhcp_user_class(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char ***l = data;
int r;
assert(l);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
*l = strv_free(*l);
return 0;
}
for (;;) {
_cleanup_free_ char *w = NULL;
r = extract_first_word(&rvalue, &w, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to split user classes option, ignoring: %s", rvalue);
break;
}
if (r == 0)
break;
if (ltype == AF_INET) {
if (strlen(w) > UINT8_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"%s length is not in the range 1-255, ignoring.", w);
continue;
}
} else {
if (strlen(w) > UINT16_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"%s length is not in the range 1-65535, ignoring.", w);
continue;
}
}
r = strv_push(l, w);
if (r < 0)
return log_oom();
w = NULL;
}
return 0;
}
int config_parse_dhcp6_mud_url(
const char *unit,
const char *filename,
@ -340,6 +278,7 @@ int config_parse_dhcp6_mud_url(
const char *rvalue,
void *data,
void *userdata) {
_cleanup_free_ char *unescaped = NULL;
Network *network = data;
int r;
@ -360,7 +299,7 @@ int config_parse_dhcp6_mud_url(
return 0;
}
if (!http_url_is_valid(unescaped) || strlen(unescaped) > UINT8_MAX) {
if (!http_url_is_valid(unescaped) || strlen(unescaped) > 255) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Failed to parse MUD URL '%s', ignoring: %m", rvalue);
@ -423,7 +362,7 @@ int config_parse_dhcp_send_option(
"Invalid DHCP option, ignoring assignment: %s", rvalue);
return 0;
}
if (u16 < 1 || u16 >= UINT16_MAX) {
if (u16 < 1 || u16 >= 65535) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP option, valid range is 1-65535, ignoring assignment: %s", rvalue);
return 0;
@ -435,7 +374,7 @@ int config_parse_dhcp_send_option(
"Invalid DHCP option, ignoring assignment: %s", rvalue);
return 0;
}
if (u8 < 1 || u8 >= UINT8_MAX) {
if (u8 < 1 || u8 >= 255) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue);
return 0;
@ -631,7 +570,7 @@ int config_parse_dhcp_request_options(
continue;
}
if (i < 1 || i >= UINT8_MAX) {
if (i < 1 || i >= 255) {
log_syntax(unit, LOG_ERR, filename, line, r,
"DHCP request option is invalid, valid range is 1-254, ignoring assignment: %s", n);
continue;

View File

@ -50,6 +50,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);

View File

@ -1605,6 +1605,60 @@ int config_parse_dhcp_black_listed_ip_address(
return 0;
}
int config_parse_dhcp_user_class(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char ***l = data;
int r;
assert(l);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
*l = strv_free(*l);
return 0;
}
for (;;) {
_cleanup_free_ char *w = NULL;
r = extract_first_word(&rvalue, &w, NULL, 0);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to split user classes option, ignoring: %s", rvalue);
break;
}
if (r == 0)
break;
if (strlen(w) > 255) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"%s length is not in the range 1-255, ignoring.", w);
continue;
}
r = strv_push(l, w);
if (r < 0)
return log_oom();
w = NULL;
}
return 0;
}
int config_parse_dhcp_ip_service_type(
const char *unit,
const char *filename,

View File

@ -25,5 +25,6 @@ int dhcp4_set_promote_secondaries(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url);

View File

@ -706,12 +706,6 @@ int dhcp6_configure(Link *link) {
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for '%u': %m", option);
}
if (link->network->dhcp6_user_class) {
r = sd_dhcp6_client_set_request_user_class(client, link->network->dhcp6_user_class);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set user class: %m");
}
r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set callback: %m");

View File

@ -174,7 +174,7 @@ DHCPv4.RequestBroadcast, config_parse_bool,
DHCPv4.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
DHCPv4.MUDURL, config_parse_dhcp_mud_url, 0, 0
DHCPv4.MaxAttempts, config_parse_dhcp_max_attempts, 0, 0
DHCPv4.UserClass, config_parse_dhcp_user_class, AF_INET, offsetof(Network, dhcp_user_class)
DHCPv4.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCPv4.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
@ -194,7 +194,6 @@ DHCPv6.UseNTP, config_parse_bool,
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0
DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0
DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class)
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)
@ -385,7 +384,7 @@ DHCP.Hostname, config_parse_hostname,
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
DHCP.UserClass, config_parse_dhcp_user_class, AF_INET, offsetof(Network, dhcp_user_class)
DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)

View File

@ -653,7 +653,6 @@ static Network *network_free(Network *network) {
set_free(network->dhcp6_request_options);
free(network->mac);
free(network->dhcp6_mudurl);
strv_free(network->dhcp6_user_class);
if (network->dhcp_acd)
sd_ipv4acd_unref(network->dhcp_acd);

View File

@ -132,7 +132,6 @@ struct Network {
bool dhcp6_without_ra;
uint8_t dhcp6_pd_length;
char *dhcp6_mudurl;
char **dhcp6_user_class;
struct in6_addr dhcp6_pd_address;
OrderedHashmap *dhcp6_client_send_options;
Set *dhcp6_request_options;

View File

@ -7,9 +7,7 @@
#include <unistd.h>
#include "alloc-util.h"
#include "blockdev-util.h"
#include "dissect-image.h"
#include "fd-util.h"
#include "main-func.h"
#include "process-util.h"
#include "signal-util.h"
@ -44,7 +42,6 @@ static int makefs(const char *type, const char *device) {
static int run(int argc, char *argv[]) {
_cleanup_free_ char *device = NULL, *type = NULL, *detected = NULL;
_cleanup_close_ int lock_fd = -1;
struct stat st;
int r;
@ -57,31 +54,28 @@ static int run(int argc, char *argv[]) {
/* type and device must be copied because makefs calls safe_fork, which clears argv[] */
type = strdup(argv[1]);
if (!type)
return log_oom();
return -ENOMEM;
device = strdup(argv[2]);
if (!device)
return log_oom();
return -ENOMEM;
if (stat(device, &st) < 0)
return log_error_errno(errno, "Failed to stat \"%s\": %m", device);
if (S_ISBLK(st.st_mode)) {
/* Lock the device so that udev doesn't interfere with our work */
lock_fd = lock_whole_block_device(st.st_rdev, LOCK_EX);
if (lock_fd < 0)
return log_error_errno(lock_fd, "Failed to lock whole block device of \"%s\": %m", device);
} else
if (!S_ISBLK(st.st_mode))
log_info("%s is not a block device.", device);
r = probe_filesystem(device, &detected);
if (r == -EUCLEAN)
return log_error_errno(r, "Ambiguous results of probing for file system on \"%s\", refusing to proceed.", device);
if (r < 0)
return log_error_errno(r, "Failed to probe \"%s\": %m", device);
return log_warning_errno(r,
r == -EUCLEAN ?
"Cannot reliably determine probe \"%s\", refusing to proceed." :
"Failed to probe \"%s\": %m",
device);
if (detected) {
log_info("'%s' is not empty (contains file system of type %s), exiting.", device, detected);
log_info("%s is not empty (type %s), exiting", device, detected);
return 0;
}

View File

@ -2233,6 +2233,7 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
LIST_FOREACH(partitions, p, context->partitions) {
assert(sd_id128_is_null(p->new_uuid));
assert(!p->new_label);
/* Never touch foreign partitions */
if (PARTITION_IS_FOREIGN(p)) {
@ -2255,9 +2256,6 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
return r;
}
if (p->new_label) /* Explicitly set by user? */
continue;
if (!isempty(p->current_label)) {
p->new_label = strdup(p->current_label); /* never change initialized labels */
if (!p->new_label)

View File

@ -75,9 +75,10 @@ int probe_filesystem(const char *node, char **ret_fstype) {
log_debug("No type detected on partition %s", node);
goto not_found;
}
if (r == -2)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Results ambiguous for partition %s", node);
if (r == -2) {
log_debug("Results ambiguous for partition %s", node);
return -EUCLEAN;
}
if (r != 0)
return errno_or_else(EIO);

View File

@ -138,7 +138,7 @@ static int apply_all(OrderedHashmap *sysctl_options) {
if (!pattern)
return log_oom();
k = glob_extend(&paths, pattern, GLOB_NOCHECK);
k = glob_extend(&paths, pattern);
if (k < 0) {
if (option->ignore_failure || ERRNO_IS_PRIVILEGE(k))
log_debug_errno(k, "Failed to resolve glob '%s', ignoring: %m",

View File

@ -4192,7 +4192,7 @@ static void print_status_info(
fs = !isempty(i->freezer_state) && !streq(i->freezer_state, "running") ? i->freezer_state : NULL;
if (fs)
printf(" %s(%s)%s", ansi_highlight_yellow(), fs, ansi_normal());
printf(" %s(%s)%s", ansi_highlight_yellow(), fs, active_off);
if (!isempty(i->result) && !streq(i->result, "success"))
printf(" (Result: %s)", i->result);

View File

@ -125,10 +125,6 @@ int sd_dhcp6_client_set_request_option(
int sd_dhcp6_client_set_request_mud_url(
sd_dhcp6_client *client,
const char *mudurl);
int sd_dhcp6_client_set_request_user_class(
sd_dhcp6_client *client,
char** user_class);
int sd_dhcp6_client_set_prefix_delegation_hint(
sd_dhcp6_client *client,
uint8_t prefixlen,

View File

@ -670,7 +670,7 @@ static void test_unlinkat_deallocate(void) {
assert_se(st.st_blocks > 0);
assert_se(st.st_nlink == 1);
assert_se(unlinkat_deallocate(AT_FDCWD, p, UNLINK_ERASE) >= 0);
assert_se(unlinkat_deallocate(AT_FDCWD, p, 0) >= 0);
assert_se(fstat(fd, &st) >= 0);
assert_se(IN_SET(st.st_size, 0, 6)); /* depending on whether hole punching worked the size will be 6
@ -850,12 +850,6 @@ static void test_path_is_encrypted_one(const char *p, int expect) {
int r;
r = path_is_encrypted(p);
if (r == -ENOENT) /* This might fail, if btrfs is used and we run in a container. In that case we
* cannot resolve the device node paths that BTRFS_IOC_DEV_INFO returns, because
* the device nodes are unlikely to exist in the container. But if we can't stat()
* them we cannot determine the dev_t of them, and thus cannot figure out if they
* are enrypted. Hence let's just ignore ENOENT here. */
return;
assert_se(r >= 0);
printf("%s encrypted: %s\n", p, yes_no(r));

View File

@ -115,7 +115,6 @@ WithoutRA=
MUDURL=
SendOption=
RequestOptions=
UserClass=
[Route]
Destination=
Protocol=