Compare commits
34 Commits
31334d18d1
...
52ec7dd995
Author | SHA1 | Date |
---|---|---|
Yu Watanabe | 52ec7dd995 | |
Yu Watanabe | caab80415e | |
PavlNekrasov | d80a9042ca | |
Yu Watanabe | a7afe5a3e7 | |
Yu Watanabe | a65b864835 | |
Yu Watanabe | 9959681a0d | |
Daan De Meyer | b3ebd480d6 | |
Arian van Putten | 6695ff4c15 | |
Yu Watanabe | 4d6ad22f8d | |
Yu Watanabe | 099ee34ca1 | |
Yu Watanabe | a2fbe9f3f9 | |
Yu Watanabe | 7c778cecdb | |
Yu Watanabe | 46718d344f | |
Yu Watanabe | 9295c7ae09 | |
Yu Watanabe | 41afafbf2a | |
Yu Watanabe | 9671efff78 | |
Yu Watanabe | 4f0bc2582e | |
Yu Watanabe | 3292120adf | |
Yu Watanabe | f6cc5e1c8d | |
Yu Watanabe | 590f430cac | |
Mike Yuan | 93d2d36638 | |
Lennart Poettering | 369b12375b | |
Yu Watanabe | b5ec8f77e0 | |
Lennart Poettering | 3e0a3a0259 | |
Celeste Liu | 6573f0c82c | |
Daan De Meyer | e0258ac886 | |
Lennart Poettering | a859d0d378 | |
Lennart Poettering | db15657dfb | |
Lennart Poettering | 2aa3005ad2 | |
Lennart Poettering | 90cf998875 | |
Lennart Poettering | c8d60ae79d | |
Lennart Poettering | bfcf48b842 | |
Yu Watanabe | 5f5c5c48b9 | |
Yu Watanabe | 68fdef46a7 |
13
NEWS
13
NEWS
|
@ -2,6 +2,15 @@ systemd System and Service Manager
|
|||
|
||||
CHANGES WITH 257 in spe:
|
||||
|
||||
Incompatible changes:
|
||||
|
||||
* The --purge switch of systemd-tmpfiles (which was added in v256) has
|
||||
been reworked: it will now only apply to tmpfiles.d/ lines marked
|
||||
with the new "$" flag. This is an incompatible change, and means any
|
||||
tmpfiles.d/ files which shall be used together with --purge need to
|
||||
be updated accordingly. This change has been made to make it harder
|
||||
to accidentally delete too many files when using --purge incorrectly.
|
||||
|
||||
Announcements of Future Feature Removals and Incompatible Changes:
|
||||
|
||||
* Support for automatic flushing of the nscd user/group database caches
|
||||
|
@ -85,7 +94,7 @@ CHANGES WITH 257 in spe:
|
|||
/usr/lib/clock-epoch, and /var/lib/systemd/timesync/clock. See
|
||||
systemd(1) for an detailed updated description.
|
||||
|
||||
* Ctrl-Alt-Delete is reenabled during late shutdown, so that the user
|
||||
* Ctrl-Alt-Delete is re-enabled during late shutdown, so that the user
|
||||
can still initiate a reboot if the system freezes.
|
||||
|
||||
* Unit option PrivateUsers=identity can be used to request a user
|
||||
|
@ -202,7 +211,7 @@ CHANGES WITH 257 in spe:
|
|||
versions.
|
||||
|
||||
* systemd-sysupdate gained a new --transfer-source= option to set the
|
||||
directory to which transfer sources cofigured with
|
||||
directory to which transfer sources configured with
|
||||
PathRelativeTo=explicit will be interpreted.
|
||||
|
||||
Miscellaneous:
|
||||
|
|
2
TODO
2
TODO
|
@ -1860,7 +1860,7 @@ Features:
|
|||
|
||||
* fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline
|
||||
|
||||
* docs: bring https://systemd.io/MY_SERVICE_CANT_GET_REATLIME up to date
|
||||
* docs: bring https://systemd.io/MY_SERVICE_CANT_GET_REALTIME up to date
|
||||
|
||||
* add a job mode that will fail if a transaction would mean stopping
|
||||
running units. Use this in timedated to manage the NTP service
|
||||
|
|
|
@ -247,4 +247,4 @@ Note that scope units created by `machined`'s `CreateMachine()` call have this f
|
|||
|
||||
### Example
|
||||
|
||||
Please see the [systemd-run sources](http://cgit.freedesktop.org/systemd/systemd/plain/src/run/run.c) for a relatively simple example how to create scope or service units transiently and pass properties to them.
|
||||
Please see the [systemd-run sources](https://github.com/systemd/systemd/blob/main/src/run/run.c) for a relatively simple example how to create scope or service units transiently and pass properties to them.
|
||||
|
|
|
@ -104,7 +104,7 @@ A: Use:
|
|||
|
||||
**Q: Whenever my service tries to acquire RT scheduling for one of its threads this is refused with EPERM even though my service is running with full privileges. This works fine on my non-systemd system!**
|
||||
|
||||
A: By default, systemd places all systemd daemons in their own cgroup in the "cpu" hierarchy. Unfortunately, due to a kernel limitation, this has the effect of disallowing RT entirely for the service. See [My Service Can't Get Realtime!](/MY_SERVICE_CANT_GET_REATLIME) for a longer discussion and what to do about this.
|
||||
A: By default, systemd places all systemd daemons in their own cgroup in the "cpu" hierarchy. Unfortunately, due to a kernel limitation, this has the effect of disallowing RT entirely for the service. See [My Service Can't Get Realtime!](/MY_SERVICE_CANT_GET_REALTIME) for a longer discussion and what to do about this.
|
||||
|
||||
**Q: My service is ordered after `network.target` but at boot it is still called before the network is up. What's going on?**
|
||||
|
||||
|
|
|
@ -310,6 +310,10 @@ mouse:bluetooth:v047dp8019:name:Expert Wireless TB Mouse:*
|
|||
ID_INPUT_TRACKBALL=1
|
||||
MOUSE_DPI=400@125
|
||||
|
||||
# Kensington SlimBlade Pro trackball (via Bluetooth)
|
||||
mouse:bluetooth:v047dp80d4:name:SlimBlade Pro:*
|
||||
ID_INPUT_TRACKBALL=1
|
||||
|
||||
##########################################
|
||||
# Lenovo
|
||||
##########################################
|
||||
|
|
|
@ -267,7 +267,8 @@
|
|||
<term><option>kernel-identify</option> <replaceable>kernel</replaceable></term>
|
||||
|
||||
<listitem><para>Takes a kernel image as argument. Checks what kind of kernel the image is. Returns
|
||||
one of <literal>uki</literal>, <literal>pe</literal>, and <literal>unknown</literal>.
|
||||
one of <literal>uki</literal>, <literal>addon</literal>, <literal>pe</literal>, and
|
||||
<literal>unknown</literal>.
|
||||
</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||
|
@ -360,6 +361,24 @@
|
|||
<xi:include href="version-info.xml" xpointer="v242"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--print-loader-path</option></term>
|
||||
<listitem><para>This option modifies the behaviour of <command>status</command>: it shows the
|
||||
absolute path to the boot loader EFI binary used for the current boot if this information is
|
||||
available. Note that no attempt is made to verify whether the binary still exists.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--print-stub-path</option></term>
|
||||
<listitem><para>This option modifies the behaviour of <command>status</command>: it shows the
|
||||
absolute path to the UKI/stub EFI binary used for the current boot if this information is
|
||||
available. Note that no attempt is made to verify whether the binary still exists.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-R</option></term>
|
||||
<term><option>--print-root-device</option></term>
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
result can be pre-calculated without too much effort. The <literal>.pcrsig</literal> section is not
|
||||
included in this PCR measurement, since it is supposed to contain signatures for the output of the
|
||||
measurement operation, and thus cannot also be input to it. If an UKI contains multiple profiles, only
|
||||
the PE sections of the selected profile (and those of the base profile, except if overriden) are
|
||||
the PE sections of the selected profile (and those of the base profile, except if overridden) are
|
||||
measured.</para>
|
||||
|
||||
<para>If non-zero, the selected numeric profile is measured into PCR 12.</para>
|
||||
|
|
|
@ -152,10 +152,11 @@
|
|||
<varlistentry>
|
||||
<term><option>--purge</option></term>
|
||||
|
||||
<listitem><para>If this option is passed, all files and directories marked for
|
||||
<emphasis>creation</emphasis> by the <filename>tmpfiles.d/</filename> files specified on the command
|
||||
line will be <emphasis>deleted</emphasis>. Specifically, this acts on all files and directories
|
||||
marked with <varname>f</varname>, <varname>F</varname>, <varname>d</varname>, <varname>D</varname>,
|
||||
<listitem><para>If this option is passed, all files and directories declared for
|
||||
<emphasis>creation</emphasis> and marked with the <literal>$</literal> character by the
|
||||
<filename>tmpfiles.d/</filename> files specified on the command line will be
|
||||
<emphasis>deleted</emphasis>. Specifically, this acts on all files and directories marked with
|
||||
<varname>f</varname>, <varname>F</varname>, <varname>d</varname>, <varname>D</varname>,
|
||||
<varname>v</varname>, <varname>q</varname>, <varname>Q</varname>, <varname>p</varname>,
|
||||
<varname>L</varname>, <varname>c</varname>, <varname>b</varname>, <varname>C</varname>,
|
||||
<varname>w</varname>, <varname>e</varname>. If this switch is used at least one
|
||||
|
|
|
@ -539,6 +539,10 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
|
|||
service, the line is silently skipped. If <literal>^</literal> and <literal>~</literal> are combined
|
||||
Base64 decoding is applied to the credential contents.</para>
|
||||
|
||||
<para>If the dollar sign (<literal>$</literal>) is used, the file becomes subject to removal when
|
||||
<command>systemd-tmpfiles</command> is invoked with the <option>--purge</option> switch. Lines without
|
||||
this character are unaffected by that switch.</para>
|
||||
|
||||
<para>Note that for all line types that result in creation of any kind of file node
|
||||
(i.e. <varname>f</varname>,
|
||||
<varname>d</varname>/<varname>D</varname>/<varname>v</varname>/<varname>q</varname>/<varname>Q</varname>,
|
||||
|
|
|
@ -141,6 +141,12 @@
|
|||
For example, e"string\n" is parsed as 7 characters: 6 lowercase letters and a newline.
|
||||
This can be useful for writing special characters when a kernel driver requires them.</para>
|
||||
|
||||
<para>The string can be prefixed with a lowercase i (i"string") to mark that the string or pattern
|
||||
will match case-insensitively. For example, i"foo" will match
|
||||
<literal>foo</literal>, <literal>FOO</literal>, <literal>FoO</literal> and so on. The prefix can be
|
||||
used only for match (<literal>==</literal>) or unmatch (<literal>!=</literal>) rules, e.g.
|
||||
<varname>ATTR{foo}==i"abcd"</varname>.</para>
|
||||
|
||||
<para>Please note that <constant>NUL</constant> is not allowed in either string variant.</para>
|
||||
</refsect2>
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
ACTION=="remove", GOTO="net_bridge_end"
|
||||
SUBSYSTEM!="net", GOTO="net_bridge_end"
|
||||
|
||||
# Some devices require the port is up before joining the bridge.
|
||||
# In such cases, ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE to "1".
|
||||
# Some devices require the port to be up before joining the bridge.
|
||||
# In such cases, set ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE to "1".
|
||||
|
||||
# Texas Instruments Ethernet device with switchdev mode
|
||||
# Texas Instruments Ethernet device with switchdev mode:
|
||||
# https://software-dl.ti.com/jacinto7/esd/processor-sdk-linux-j721s2/latest/exports/docs/linux/Foundational_Components/Kernel/Kernel_Drivers/Network/CPSWng-Native-Ethernet.html#switch-mode
|
||||
ENV{ID_NET_DRIVER}=="am65-cpsw-nuss", ENV{ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE}="1"
|
||||
|
||||
|
|
|
@ -221,6 +221,12 @@ const char* const systemd_features =
|
|||
" -BPF_FRAMEWORK"
|
||||
#endif
|
||||
|
||||
#if HAVE_VMLINUX_H
|
||||
" +BTF"
|
||||
#else
|
||||
" -BTF"
|
||||
#endif
|
||||
|
||||
#if HAVE_XKBCOMMON
|
||||
" +XKBCOMMON"
|
||||
#else
|
||||
|
|
|
@ -145,8 +145,10 @@ int efi_get_variable(
|
|||
int efi_get_variable_string(const char *variable, char **ret) {
|
||||
_cleanup_free_ void *s = NULL;
|
||||
size_t ss = 0;
|
||||
int r;
|
||||
char *x;
|
||||
int r;
|
||||
|
||||
assert(variable);
|
||||
|
||||
r = efi_get_variable(variable, NULL, &s, &ss);
|
||||
if (r < 0)
|
||||
|
@ -156,10 +158,27 @@ int efi_get_variable_string(const char *variable, char **ret) {
|
|||
if (!x)
|
||||
return -ENOMEM;
|
||||
|
||||
if (ret)
|
||||
*ret = x;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int efi_get_variable_path(const char *variable, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(variable);
|
||||
|
||||
r = efi_get_variable_string(variable, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret)
|
||||
efi_tilt_backslashes(*ret);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int efi_verify_variable(const char *variable, uint32_t attr, const void *value, size_t size) {
|
||||
_cleanup_free_ void *buf = NULL;
|
||||
size_t n;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "sd-id128.h"
|
||||
|
||||
#include "efivars-fundamental.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
|
@ -47,6 +48,7 @@
|
|||
|
||||
int efi_get_variable(const char *variable, uint32_t *attribute, void **ret_value, size_t *ret_size);
|
||||
int efi_get_variable_string(const char *variable, char **ret);
|
||||
int efi_get_variable_path(const char *variable, char **ret);
|
||||
int efi_set_variable(const char *variable, const void *value, size_t size);
|
||||
int efi_set_variable_string(const char *variable, const char *p);
|
||||
|
||||
|
@ -68,6 +70,10 @@ static inline int efi_get_variable_string(const char *variable, char **ret) {
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int efi_get_variable_path(const char *variable, char **ret) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int efi_set_variable(const char *variable, const void *value, size_t size) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -100,3 +106,7 @@ static inline int systemd_efi_options_efivarfs_if_newer(char **line) {
|
|||
return -ENODATA;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline char *efi_tilt_backslashes(char *s) {
|
||||
return string_replace_char(s, '\\', '/');
|
||||
}
|
||||
|
|
|
@ -219,14 +219,12 @@ static int acquire_boot_count_path(
|
|||
uint64_t left, done;
|
||||
int r;
|
||||
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderBootCountPath), &path);
|
||||
r = efi_get_variable_path(EFI_LOADER_VARIABLE(LoaderBootCountPath), &path);
|
||||
if (r == -ENOENT)
|
||||
return -EUNATCH; /* in this case, let the caller print a message */
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read LoaderBootCountPath EFI variable: %m");
|
||||
|
||||
efi_tilt_backslashes(path);
|
||||
|
||||
if (!path_is_normalized(path))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Path read from LoaderBootCountPath is not normalized, refusing: %s",
|
||||
|
|
|
@ -298,12 +298,24 @@ fail:
|
|||
return r;
|
||||
}
|
||||
|
||||
static void read_efi_var(const char *variable, char **ret) {
|
||||
static int efi_get_variable_string_and_warn(const char *variable, char **ret) {
|
||||
int r;
|
||||
|
||||
r = efi_get_variable_string(variable, ret);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read EFI variable %s: %m", variable);
|
||||
return log_warning_errno(r, "Failed to read EFI variable '%s', ignoring: %m", variable);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int efi_get_variable_path_and_warn(const char *variable, char **ret) {
|
||||
int r;
|
||||
|
||||
r = efi_get_variable_path(variable, ret);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_warning_errno(r, "Failed to read EFI variable '%s', ignoring: %m", variable);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void print_yes_no_line(bool first, bool good, const char *name) {
|
||||
|
@ -396,26 +408,23 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
|||
{ EFI_STUB_FEATURE_MULTI_PROFILE_UKI, "Stub understands profile selector" },
|
||||
{ EFI_STUB_FEATURE_REPORT_STUB_PARTITION, "Stub sets stub partition information" },
|
||||
};
|
||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
|
||||
sd_id128_t loader_part_uuid = SD_ID128_NULL;
|
||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL, *stub_path = NULL,
|
||||
*current_entry = NULL, *oneshot_entry = NULL, *default_entry = NULL;
|
||||
uint64_t loader_features = 0, stub_features = 0;
|
||||
Tpm2Support s;
|
||||
int have;
|
||||
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderFirmwareType), &fw_type);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderFirmwareInfo), &fw_info);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderInfo), &loader);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(StubInfo), &stub);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderImageIdentifier), &loader_path);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderFirmwareType), &fw_type);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderFirmwareInfo), &fw_info);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderInfo), &loader);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(StubInfo), &stub);
|
||||
(void) efi_get_variable_path_and_warn(EFI_LOADER_VARIABLE(LoaderImageIdentifier), &loader_path);
|
||||
(void) efi_get_variable_path_and_warn(EFI_LOADER_VARIABLE(StubImageIdentifier), &stub_path);
|
||||
(void) efi_loader_get_features(&loader_features);
|
||||
(void) efi_stub_get_features(&stub_features);
|
||||
|
||||
if (loader_path)
|
||||
efi_tilt_backslashes(loader_path);
|
||||
|
||||
k = efi_loader_get_device_part_uuid(&loader_part_uuid);
|
||||
if (k < 0 && k != -ENOENT)
|
||||
r = log_warning_errno(k, "Failed to read EFI variable LoaderDevicePartUUID: %m");
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderEntrySelected), ¤t_entry);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &oneshot_entry);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderEntryDefault), &default_entry);
|
||||
|
||||
SecureBootMode secure = efi_get_secure_boot_mode();
|
||||
printf("%sSystem:%s\n", ansi_underline(), ansi_normal());
|
||||
|
@ -463,34 +472,58 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
|||
}
|
||||
printf("\n");
|
||||
|
||||
if (loader) {
|
||||
printf("%sCurrent Boot Loader:%s\n", ansi_underline(), ansi_normal());
|
||||
printf(" Product: %s%s%s\n", ansi_highlight(), strna(loader), ansi_normal());
|
||||
|
||||
printf(" Product: %s%s%s\n", ansi_highlight(), loader, ansi_normal());
|
||||
for (size_t i = 0; i < ELEMENTSOF(loader_flags); i++)
|
||||
print_yes_no_line(i == 0, FLAGS_SET(loader_features, loader_flags[i].flag), loader_flags[i].name);
|
||||
|
||||
sd_id128_t bootloader_esp_uuid;
|
||||
bool have_bootloader_esp_uuid = efi_loader_get_device_part_uuid(&bootloader_esp_uuid) >= 0;
|
||||
sd_id128_t loader_partition_uuid;
|
||||
bool have_loader_partition_uuid = efi_loader_get_device_part_uuid(&loader_partition_uuid) >= 0;
|
||||
|
||||
print_yes_no_line(false, have_bootloader_esp_uuid, "Boot loader sets ESP information");
|
||||
if (have_bootloader_esp_uuid && !sd_id128_is_null(esp_uuid) &&
|
||||
!sd_id128_equal(esp_uuid, bootloader_esp_uuid))
|
||||
printf("WARNING: The boot loader reports a different ESP UUID than detected ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR")!\n",
|
||||
SD_ID128_FORMAT_VAL(bootloader_esp_uuid),
|
||||
SD_ID128_FORMAT_VAL(esp_uuid));
|
||||
print_yes_no_line(false, have_loader_partition_uuid, "Boot loader set ESP information");
|
||||
|
||||
if (current_entry)
|
||||
printf("Current Entry: %s\n", current_entry);
|
||||
if (default_entry)
|
||||
printf("Default Entry: %s\n", default_entry);
|
||||
if (oneshot_entry && !streq_ptr(oneshot_entry, default_entry))
|
||||
printf("OneShot Entry: %s\n", oneshot_entry);
|
||||
|
||||
if (have_loader_partition_uuid && !sd_id128_is_null(esp_uuid) && !sd_id128_equal(esp_uuid, loader_partition_uuid))
|
||||
printf("WARNING: The boot loader reports a different partition UUID than the detected ESP ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR")!\n",
|
||||
SD_ID128_FORMAT_VAL(loader_partition_uuid), SD_ID128_FORMAT_VAL(esp_uuid));
|
||||
|
||||
if (!sd_id128_is_null(loader_partition_uuid))
|
||||
printf(" Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
|
||||
SD_ID128_FORMAT_VAL(loader_partition_uuid));
|
||||
else
|
||||
printf(" Partition: n/a\n");
|
||||
printf(" Loader: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (stub) {
|
||||
printf(" Stub: %s\n", stub);
|
||||
printf("%sCurrent Stub:%s\n", ansi_underline(), ansi_normal());
|
||||
printf(" Product: %s%s%s\n", ansi_highlight(), stub, ansi_normal());
|
||||
for (size_t i = 0; i < ELEMENTSOF(stub_flags); i++)
|
||||
print_yes_no_line(i == 0, FLAGS_SET(stub_features, stub_flags[i].flag), stub_flags[i].name);
|
||||
}
|
||||
if (!sd_id128_is_null(loader_part_uuid))
|
||||
printf(" ESP: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
|
||||
SD_ID128_FORMAT_VAL(loader_part_uuid));
|
||||
|
||||
sd_id128_t stub_partition_uuid;
|
||||
bool have_stub_partition_uuid = efi_stub_get_device_part_uuid(&stub_partition_uuid) >= 0;
|
||||
|
||||
if (have_stub_partition_uuid && (!(!sd_id128_is_null(esp_uuid) && sd_id128_equal(esp_uuid, stub_partition_uuid)) &&
|
||||
!(!sd_id128_is_null(xbootldr_uuid) && sd_id128_equal(xbootldr_uuid, stub_partition_uuid))))
|
||||
printf("WARNING: The stub loader reports a different UUID than the detected ESP or XBOOTDLR partition ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR"/"SD_ID128_UUID_FORMAT_STR")!\n",
|
||||
SD_ID128_FORMAT_VAL(stub_partition_uuid), SD_ID128_FORMAT_VAL(esp_uuid), SD_ID128_FORMAT_VAL(xbootldr_uuid));
|
||||
if (!sd_id128_is_null(stub_partition_uuid))
|
||||
printf(" Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
|
||||
SD_ID128_FORMAT_VAL(stub_partition_uuid));
|
||||
else
|
||||
printf(" ESP: n/a\n");
|
||||
printf(" File: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
|
||||
printf(" Partition: n/a\n");
|
||||
printf(" Stub: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(stub_path));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("%sRandom Seed:%s\n", ansi_underline(), ansi_normal());
|
||||
have = access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderSystemToken)), F_OK) >= 0;
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
#include "build.h"
|
||||
#include "devnum-util.h"
|
||||
#include "dissect-image.h"
|
||||
#include "efi-loader.h"
|
||||
#include "escape.h"
|
||||
#include "find-esp.h"
|
||||
#include "main-func.h"
|
||||
#include "mount-util.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "utf8.h"
|
||||
#include "varlink-io.systemd.BootControl.h"
|
||||
|
@ -38,6 +40,8 @@ char *arg_esp_path = NULL;
|
|||
char *arg_xbootldr_path = NULL;
|
||||
bool arg_print_esp_path = false;
|
||||
bool arg_print_dollar_boot_path = false;
|
||||
bool arg_print_loader_path = false;
|
||||
bool arg_print_stub_path = false;
|
||||
unsigned arg_print_root_device = 0;
|
||||
bool arg_touch_variables = true;
|
||||
bool arg_install_random_seed = true;
|
||||
|
@ -133,6 +137,71 @@ int acquire_xbootldr(
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int print_loader_or_stub_path(void) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
sd_id128_t uuid;
|
||||
int r;
|
||||
|
||||
if (arg_print_loader_path) {
|
||||
r = efi_loader_get_device_part_uuid(&uuid);
|
||||
if (r == -ENOENT)
|
||||
return log_error_errno(r, "No loader partition UUID passed.");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to determine loader partition UUID: %m");
|
||||
|
||||
r = efi_get_variable_path(EFI_LOADER_VARIABLE(LoaderImageIdentifier), &p);
|
||||
if (r == -ENOENT)
|
||||
return log_error_errno(r, "No loader EFI binary path passed.");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to determine loader EFI binary path: %m");
|
||||
} else {
|
||||
assert(arg_print_stub_path);
|
||||
|
||||
r = efi_stub_get_device_part_uuid(&uuid);
|
||||
if (r == -ENOENT)
|
||||
return log_error_errno(r, "No stub partition UUID passed.");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to determine stub partition UUID: %m");
|
||||
|
||||
r = efi_get_variable_path(EFI_LOADER_VARIABLE(StubImageIdentifier), &p);
|
||||
if (r == -ENOENT)
|
||||
return log_error_errno(r, "No stub EFI binary path passed.");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to determine stub EFI binary path: %m");
|
||||
}
|
||||
|
||||
sd_id128_t esp_uuid;
|
||||
r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false,
|
||||
/* ret_part= */ NULL, /* ret_pstart= */ NULL, /* ret_psize= */ NULL,
|
||||
&esp_uuid, /* ret_devid= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
const char *found_path = NULL;
|
||||
if (sd_id128_equal(esp_uuid, uuid))
|
||||
found_path = arg_esp_path;
|
||||
else if (arg_print_stub_path) { /* In case of the stub, also look for things in the xbootldr partition */
|
||||
sd_id128_t xbootldr_uuid;
|
||||
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ false, &xbootldr_uuid, /* ret_devid= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sd_id128_equal(xbootldr_uuid, uuid))
|
||||
found_path = arg_xbootldr_path;
|
||||
}
|
||||
|
||||
if (!found_path)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Failed to discover partition " SD_ID128_FORMAT_STR " among mounted boot partitions.", SD_ID128_FORMAT_VAL(uuid));
|
||||
|
||||
_cleanup_free_ char *j = path_join(found_path, p);
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
puts(j);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
|
@ -182,6 +251,9 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||
" Where to pick files when using --root=/--image=\n"
|
||||
" -p --print-esp-path Print path to the EFI System Partition mount point\n"
|
||||
" -x --print-boot-path Print path to the $BOOT partition mount point\n"
|
||||
" --print-loader-path\n"
|
||||
" Print path to currently booted boot loader binary\n"
|
||||
" --print-stub-path Print path to currently booted unified kernel binary\n"
|
||||
" -R --print-root-device\n"
|
||||
" Print path to the block device node backing the\n"
|
||||
" root file system (returns e.g. /dev/nvme0n1p5)\n"
|
||||
|
@ -235,6 +307,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
ARG_ARCH_ALL,
|
||||
ARG_EFI_BOOT_OPTION_DESCRIPTION,
|
||||
ARG_DRY_RUN,
|
||||
ARG_PRINT_LOADER_PATH,
|
||||
ARG_PRINT_STUB_PATH,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
|
@ -250,6 +324,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
{ "print-esp-path", no_argument, NULL, 'p' },
|
||||
{ "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */
|
||||
{ "print-boot-path", no_argument, NULL, 'x' },
|
||||
{ "print-loader-path", no_argument, NULL, ARG_PRINT_LOADER_PATH },
|
||||
{ "print-stub-path", no_argument, NULL, ARG_PRINT_STUB_PATH },
|
||||
{ "print-root-device", no_argument, NULL, 'R' },
|
||||
{ "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
|
||||
{ "random-seed", required_argument, NULL, ARG_RANDOM_SEED },
|
||||
|
@ -332,6 +408,14 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
arg_print_dollar_boot_path = true;
|
||||
break;
|
||||
|
||||
case ARG_PRINT_LOADER_PATH:
|
||||
arg_print_loader_path = true;
|
||||
break;
|
||||
|
||||
case ARG_PRINT_STUB_PATH:
|
||||
arg_print_stub_path = true;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
arg_print_root_device++;
|
||||
break;
|
||||
|
@ -414,9 +498,9 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (!!arg_print_esp_path + !!arg_print_dollar_boot_path + (arg_print_root_device > 0) > 1)
|
||||
if (!!arg_print_esp_path + !!arg_print_dollar_boot_path + (arg_print_root_device > 0) + arg_print_loader_path + arg_print_stub_path > 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"--print-esp-path/-p, --print-boot-path/-x, --print-root-device=/-R cannot be combined.");
|
||||
"--print-esp-path/-p, --print-boot-path/-x, --print-root-device=/-R, --print-loader-path, --print-stub-path cannot be combined.");
|
||||
|
||||
if ((arg_root || arg_image) && argv[optind] && !STR_IN_SET(argv[optind], "status", "list",
|
||||
"install", "update", "remove", "is-installed", "random-seed", "unlink", "cleanup"))
|
||||
|
@ -541,6 +625,9 @@ static int run(int argc, char *argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (arg_print_loader_path || arg_print_stub_path)
|
||||
return print_loader_or_stub_path();
|
||||
|
||||
/* Open up and mount the image */
|
||||
if (arg_image) {
|
||||
assert(!arg_root);
|
||||
|
|
|
@ -1046,7 +1046,6 @@ static int process_socket(int fd) {
|
|||
_cleanup_close_ int input_fd = -EBADF, mount_tree_fd = -EBADF;
|
||||
Context context = {};
|
||||
struct iovec_wrapper iovw = {};
|
||||
struct iovec iovec;
|
||||
bool first = true;
|
||||
int r;
|
||||
|
||||
|
@ -1063,8 +1062,7 @@ static int process_socket(int fd) {
|
|||
.msg_controllen = sizeof(control),
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
ssize_t n;
|
||||
ssize_t l;
|
||||
ssize_t n, l;
|
||||
|
||||
l = next_datagram_size_fd(fd);
|
||||
if (l < 0) {
|
||||
|
@ -1072,8 +1070,10 @@ static int process_socket(int fd) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
iovec.iov_len = l;
|
||||
iovec.iov_base = malloc(l + 1);
|
||||
_cleanup_(iovec_done) struct iovec iovec = {
|
||||
.iov_len = l,
|
||||
.iov_base = malloc(l + 1),
|
||||
};
|
||||
if (!iovec.iov_base) {
|
||||
r = log_oom();
|
||||
goto finish;
|
||||
|
@ -1083,7 +1083,6 @@ static int process_socket(int fd) {
|
|||
|
||||
n = recvmsg_safe(fd, &mh, MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
free(iovec.iov_base);
|
||||
r = log_error_errno(n, "Failed to receive datagram: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
@ -1093,8 +1092,6 @@ static int process_socket(int fd) {
|
|||
if (n == 0) {
|
||||
struct cmsghdr *found;
|
||||
|
||||
free(iovec.iov_base);
|
||||
|
||||
found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int) * 2));
|
||||
if (found) {
|
||||
int fds[2] = EBADF_PAIR;
|
||||
|
@ -1134,6 +1131,8 @@ static int process_socket(int fd) {
|
|||
r = iovw_put(&iovw, iovec.iov_base, iovec.iov_len);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
TAKE_STRUCT(iovec);
|
||||
}
|
||||
|
||||
/* Make sure we got all data we really need */
|
||||
|
|
|
@ -36,23 +36,22 @@ struct str {
|
|||
static long cut_last(u32 i, struct str *str) {
|
||||
char *s;
|
||||
|
||||
/* Sanity check for the preverifier */
|
||||
if (i >= str->l)
|
||||
return 1; /* exit from the loop */
|
||||
|
||||
i = str->l - i - 1;
|
||||
s = str->s + i;
|
||||
|
||||
/* Sanity check for the preverifier */
|
||||
if (i >= str->l)
|
||||
return 1;
|
||||
|
||||
if (*s == 0)
|
||||
return 0;
|
||||
return 0; /* continue */
|
||||
|
||||
if (*s == '\n' || *s == '\r' || *s == ' ' || *s == '\t') {
|
||||
*s = 0;
|
||||
|
||||
return 0;
|
||||
return 0; /* continue */
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1; /* exit from the loop */
|
||||
}
|
||||
|
||||
/* Cut off trailing whitespace and newlines */
|
||||
|
|
|
@ -221,7 +221,7 @@ int link_set_ipv6ll_stable_secret(Link *link) {
|
|||
}
|
||||
|
||||
return sysctl_write_ip_property(AF_INET6, link->ifname, "stable_secret",
|
||||
IN6_ADDR_TO_STRING(&a), &link->manager->sysctl_shadow);
|
||||
IN6_ADDR_TO_STRING(&a), manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_set_ipv6ll_addrgen_mode(Link *link, IPv6LinkLocalAddressGenMode mode) {
|
||||
|
@ -232,7 +232,7 @@ int link_set_ipv6ll_addrgen_mode(Link *link, IPv6LinkLocalAddressGenMode mode) {
|
|||
if (mode == link->ipv6ll_address_gen_mode)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "addr_gen_mode", mode, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "addr_gen_mode", mode, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX] = {
|
||||
|
|
|
@ -604,7 +604,9 @@ int manager_new(Manager **ret, bool test_mode) {
|
|||
.duid_product_uuid.type = DUID_TYPE_UUID,
|
||||
.dhcp_server_persist_leases = true,
|
||||
.ip_forwarding = { -1, -1, },
|
||||
#if HAVE_VMLINUX_H
|
||||
.cgroup_fd = -EBADF,
|
||||
#endif
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
|
@ -624,8 +626,6 @@ Manager* manager_free(Manager *m) {
|
|||
HASHMAP_FOREACH(link, m->links_by_index)
|
||||
(void) link_stop_engines(link, true);
|
||||
|
||||
hashmap_free(m->sysctl_shadow);
|
||||
|
||||
m->request_queue = ordered_set_free(m->request_queue);
|
||||
m->remove_request_queue = ordered_set_free(m->remove_request_queue);
|
||||
|
||||
|
|
|
@ -122,12 +122,14 @@ struct Manager {
|
|||
|
||||
/* sysctl */
|
||||
int ip_forwarding[2];
|
||||
#if HAVE_VMLINUX_H
|
||||
Hashmap *sysctl_shadow;
|
||||
sd_event_source *sysctl_event_source;
|
||||
struct ring_buffer *sysctl_buffer;
|
||||
struct sysctl_monitor_bpf *sysctl_skel;
|
||||
struct bpf_link *sysctl_link;
|
||||
int cgroup_fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
int manager_new(Manager **ret, bool test_mode);
|
||||
|
@ -150,4 +152,12 @@ int manager_set_timezone(Manager *m, const char *timezone);
|
|||
|
||||
int manager_reload(Manager *m, sd_bus_message *message);
|
||||
|
||||
static inline Hashmap** manager_get_sysctl_shadow(Manager *manager) {
|
||||
#if HAVE_VMLINUX_H
|
||||
return &ASSERT_PTR(manager)->sysctl_shadow;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||
|
|
|
@ -987,7 +987,7 @@ static int ndisc_router_process_reachable_time(Link *link, sd_ndisc_router *rt)
|
|||
}
|
||||
|
||||
/* Set the reachable time for Neighbor Solicitations. */
|
||||
r = sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "base_reachable_time_ms", (uint32_t) msec, &link->manager->sysctl_shadow);
|
||||
r = sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "base_reachable_time_ms", (uint32_t) msec, manager_get_sysctl_shadow(link->manager));
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to apply neighbor reachable time (%"PRIu64"), ignoring: %m", msec);
|
||||
|
||||
|
@ -1021,7 +1021,7 @@ static int ndisc_router_process_retransmission_time(Link *link, sd_ndisc_router
|
|||
}
|
||||
|
||||
/* Set the retransmission time for Neighbor Solicitations. */
|
||||
r = sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "retrans_time_ms", (uint32_t) msec, &link->manager->sysctl_shadow);
|
||||
r = sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "retrans_time_ms", (uint32_t) msec, manager_get_sysctl_shadow(link->manager));
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to apply neighbor retransmission time (%"PRIu64"), ignoring: %m", msec);
|
||||
|
||||
|
@ -1057,7 +1057,7 @@ static int ndisc_router_process_hop_limit(Link *link, sd_ndisc_router *rt) {
|
|||
if (hop_limit <= 0)
|
||||
return 0;
|
||||
|
||||
r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "hop_limit", (uint32_t) hop_limit, &link->manager->sysctl_shadow);
|
||||
r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "hop_limit", (uint32_t) hop_limit, manager_get_sysctl_shadow(link->manager));
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to apply hop_limit (%u), ignoring: %m", hop_limit);
|
||||
|
||||
|
|
|
@ -587,7 +587,7 @@ static int link_is_ready_to_set_link(Link *link, Request *req) {
|
|||
}
|
||||
|
||||
if (link->network->bridge && !FLAGS_SET(link->flags, IFF_UP) && link->dev) {
|
||||
/* Some devices require the port is up before joining the bridge.
|
||||
/* Some devices require the port to be up before joining the bridge.
|
||||
*
|
||||
* E.g. Texas Instruments SoC Ethernet running in switch mode:
|
||||
* https://software-dl.ti.com/jacinto7/esd/processor-sdk-linux-j721s2/latest/exports/docs/linux/Foundational_Components/Kernel/Kernel_Drivers/Network/CPSWng-Native-Ethernet.html#switch-mode
|
||||
|
|
|
@ -34,13 +34,7 @@ static struct sysctl_monitor_bpf* sysctl_monitor_bpf_free(struct sysctl_monitor_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct ring_buffer* rb_free(struct ring_buffer *rb) {
|
||||
sym_ring_buffer__free(rb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct sysctl_monitor_bpf *, sysctl_monitor_bpf_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ring_buffer *, rb_free);
|
||||
|
||||
static int sysctl_event_handler(void *ctx, void *data, size_t data_sz) {
|
||||
struct sysctl_write_event *we = ASSERT_PTR(data);
|
||||
|
@ -99,10 +93,10 @@ static int on_ringbuf_io(sd_event_source *s, int fd, uint32_t revents, void *use
|
|||
int sysctl_add_monitor(Manager *manager) {
|
||||
_cleanup_(sysctl_monitor_bpf_freep) struct sysctl_monitor_bpf *obj = NULL;
|
||||
_cleanup_(bpf_link_freep) struct bpf_link *sysctl_link = NULL;
|
||||
_cleanup_(rb_freep) struct ring_buffer *sysctl_buffer = NULL;
|
||||
_cleanup_close_ int cgroup_fd = -EBADF, rootcg = -EBADF;
|
||||
_cleanup_(bpf_ring_buffer_freep) struct ring_buffer *sysctl_buffer = NULL;
|
||||
_cleanup_close_ int cgroup_fd = -EBADF, root_cgroup_fd = -EBADF;
|
||||
_cleanup_free_ char *cgroup = NULL;
|
||||
int idx = 0, r;
|
||||
int idx = 0, r, fd;
|
||||
|
||||
assert(manager);
|
||||
|
||||
|
@ -116,9 +110,9 @@ int sysctl_add_monitor(Manager *manager) {
|
|||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to get cgroup path, ignoring: %m.");
|
||||
|
||||
rootcg = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
|
||||
if (rootcg < 0)
|
||||
return log_warning_errno(rootcg, "Failed to open cgroup, ignoring: %m.");
|
||||
root_cgroup_fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
|
||||
if (root_cgroup_fd < 0)
|
||||
return log_warning_errno(root_cgroup_fd, "Failed to open cgroup, ignoring: %m.");
|
||||
|
||||
obj = sysctl_monitor_bpf__open_and_load();
|
||||
if (!obj) {
|
||||
|
@ -133,21 +127,27 @@ int sysctl_add_monitor(Manager *manager) {
|
|||
if (sym_bpf_map_update_elem(sym_bpf_map__fd(obj->maps.cgroup_map), &idx, &cgroup_fd, BPF_ANY))
|
||||
return log_warning_errno(errno, "Failed to update cgroup map: %m");
|
||||
|
||||
sysctl_link = sym_bpf_program__attach_cgroup(obj->progs.sysctl_monitor, rootcg);
|
||||
sysctl_link = sym_bpf_program__attach_cgroup(obj->progs.sysctl_monitor, root_cgroup_fd);
|
||||
r = bpf_get_error_translated(sysctl_link);
|
||||
if (r < 0) {
|
||||
log_info_errno(r, "Unable to attach sysctl monitor BPF program to cgroup, ignoring: %m.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sysctl_buffer = sym_ring_buffer__new(
|
||||
sym_bpf_map__fd(obj->maps.written_sysctls),
|
||||
sysctl_event_handler, &manager->sysctl_shadow, NULL);
|
||||
fd = sym_bpf_map__fd(obj->maps.written_sysctls);
|
||||
if (fd < 0)
|
||||
return log_warning_errno(fd, "Failed to get fd of sysctl maps: %m");
|
||||
|
||||
sysctl_buffer = sym_ring_buffer__new(fd, sysctl_event_handler, &manager->sysctl_shadow, NULL);
|
||||
if (!sysctl_buffer)
|
||||
return log_warning_errno(errno, "Failed to create ring buffer: %m");
|
||||
|
||||
fd = sym_ring_buffer__epoll_fd(sysctl_buffer);
|
||||
if (fd < 0)
|
||||
return log_warning_errno(fd, "Failed to get poll fd of ring buffer: %m");
|
||||
|
||||
r = sd_event_add_io(manager->event, &manager->sysctl_event_source,
|
||||
sym_ring_buffer__epoll_fd(sysctl_buffer), EPOLLIN, on_ringbuf_io, sysctl_buffer);
|
||||
fd, EPOLLIN, on_ringbuf_io, sysctl_buffer);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to watch sysctl event ringbuffer: %m");
|
||||
|
||||
|
@ -163,23 +163,11 @@ void sysctl_remove_monitor(Manager *manager) {
|
|||
assert(manager);
|
||||
|
||||
manager->sysctl_event_source = sd_event_source_disable_unref(manager->sysctl_event_source);
|
||||
|
||||
if (manager->sysctl_buffer) {
|
||||
sym_ring_buffer__free(manager->sysctl_buffer);
|
||||
manager->sysctl_buffer = NULL;
|
||||
}
|
||||
|
||||
if (manager->sysctl_link) {
|
||||
sym_bpf_link__destroy(manager->sysctl_link);
|
||||
manager->sysctl_link = NULL;
|
||||
}
|
||||
|
||||
if (manager->sysctl_skel) {
|
||||
sysctl_monitor_bpf__destroy(manager->sysctl_skel);
|
||||
manager->sysctl_skel = NULL;
|
||||
}
|
||||
|
||||
manager->sysctl_buffer = bpf_ring_buffer_free(manager->sysctl_buffer);
|
||||
manager->sysctl_link = bpf_link_free(manager->sysctl_link);
|
||||
manager->sysctl_skel = sysctl_monitor_bpf_free(manager->sysctl_skel);
|
||||
manager->cgroup_fd = safe_close(manager->cgroup_fd);
|
||||
manager->sysctl_shadow = hashmap_free(manager->sysctl_shadow);
|
||||
}
|
||||
|
||||
int sysctl_clear_link_shadows(Link *link) {
|
||||
|
@ -222,13 +210,13 @@ static void manager_set_ip_forwarding(Manager *manager, int family) {
|
|||
return; /* keep */
|
||||
|
||||
/* First, set the default value. */
|
||||
r = sysctl_write_ip_property_boolean(family, "default", "forwarding", t, &manager->sysctl_shadow);
|
||||
r = sysctl_write_ip_property_boolean(family, "default", "forwarding", t, manager_get_sysctl_shadow(manager));
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to %s the default %s forwarding: %m",
|
||||
enable_disable(t), af_to_ipv4_ipv6(family));
|
||||
|
||||
/* Then, set the value to all interfaces. */
|
||||
r = sysctl_write_ip_property_boolean(family, "all", "forwarding", t, &manager->sysctl_shadow);
|
||||
r = sysctl_write_ip_property_boolean(family, "all", "forwarding", t, manager_get_sysctl_shadow(manager));
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to %s %s forwarding for all interfaces: %m",
|
||||
enable_disable(t), af_to_ipv4_ipv6(family));
|
||||
|
@ -273,7 +261,7 @@ static int link_update_ipv6_sysctl(Link *link) {
|
|||
if (!link_ipv6_enabled(link))
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_proxy_arp(Link *link) {
|
||||
|
@ -286,7 +274,7 @@ static int link_set_proxy_arp(Link *link) {
|
|||
if (link->network->proxy_arp < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_proxy_arp_pvlan(Link *link) {
|
||||
|
@ -299,7 +287,7 @@ static int link_set_proxy_arp_pvlan(Link *link) {
|
|||
if (link->network->proxy_arp_pvlan < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp_pvlan", link->network->proxy_arp_pvlan > 0, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp_pvlan", link->network->proxy_arp_pvlan > 0, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_get_ip_forwarding(Link *link, int family) {
|
||||
|
@ -341,7 +329,7 @@ static int link_set_ip_forwarding_impl(Link *link, int family) {
|
|||
if (t < 0)
|
||||
return 0; /* keep */
|
||||
|
||||
r = sysctl_write_ip_property_boolean(family, link->ifname, "forwarding", t, &link->manager->sysctl_shadow);
|
||||
r = sysctl_write_ip_property_boolean(family, link->ifname, "forwarding", t, manager_get_sysctl_shadow(link->manager));
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to %s %s forwarding, ignoring: %m",
|
||||
enable_disable(t), af_to_ipv4_ipv6(family));
|
||||
|
@ -418,7 +406,7 @@ static int link_set_ipv4_rp_filter(Link *link) {
|
|||
if (link->network->ipv4_rp_filter < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_int(AF_INET, link->ifname, "rp_filter", link->network->ipv4_rp_filter, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_int(AF_INET, link->ifname, "rp_filter", link->network->ipv4_rp_filter, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv6_privacy_extensions(Link *link) {
|
||||
|
@ -438,7 +426,7 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
|
|||
if (val == IPV6_PRIVACY_EXTENSIONS_KERNEL)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) val, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) val, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv6_accept_ra(Link *link) {
|
||||
|
@ -448,7 +436,7 @@ static int link_set_ipv6_accept_ra(Link *link) {
|
|||
if (!link_is_configured_for_family(link, AF_INET6))
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0", &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0", manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv6_dad_transmits(Link *link) {
|
||||
|
@ -461,7 +449,7 @@ static int link_set_ipv6_dad_transmits(Link *link) {
|
|||
if (link->network->ipv6_dad_transmits < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv6_hop_limit(Link *link) {
|
||||
|
@ -474,7 +462,7 @@ static int link_set_ipv6_hop_limit(Link *link) {
|
|||
if (link->network->ipv6_hop_limit <= 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv6_retransmission_time(Link *link) {
|
||||
|
@ -493,7 +481,7 @@ static int link_set_ipv6_retransmission_time(Link *link) {
|
|||
if (retrans_time_ms <= 0 || retrans_time_ms > UINT32_MAX)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "retrans_time_ms", retrans_time_ms, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "retrans_time_ms", retrans_time_ms, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv6_proxy_ndp(Link *link) {
|
||||
|
@ -510,7 +498,7 @@ static int link_set_ipv6_proxy_ndp(Link *link) {
|
|||
else
|
||||
v = !set_isempty(link->network->ipv6_proxy_ndp_addresses);
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_set_ipv6_mtu(Link *link, int log_level) {
|
||||
|
@ -538,7 +526,7 @@ int link_set_ipv6_mtu(Link *link, int log_level) {
|
|||
mtu = link->mtu;
|
||||
}
|
||||
|
||||
return sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", mtu, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", mtu, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv4_accept_local(Link *link) {
|
||||
|
@ -551,7 +539,7 @@ static int link_set_ipv4_accept_local(Link *link) {
|
|||
if (link->network->ipv4_accept_local < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local > 0, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local > 0, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv4_route_localnet(Link *link) {
|
||||
|
@ -564,7 +552,7 @@ static int link_set_ipv4_route_localnet(Link *link) {
|
|||
if (link->network->ipv4_route_localnet < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "route_localnet", link->network->ipv4_route_localnet > 0, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "route_localnet", link->network->ipv4_route_localnet > 0, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_ipv4_promote_secondaries(Link *link) {
|
||||
|
@ -579,7 +567,7 @@ static int link_set_ipv4_promote_secondaries(Link *link) {
|
|||
* otherwise. The way systemd-networkd works is that the new IP of a lease is added as a
|
||||
* secondary IP and when the primary one expires it relies on the kernel to promote the
|
||||
* secondary IP. See also https://github.com/systemd/systemd/issues/7163 */
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "promote_secondaries", true, &link->manager->sysctl_shadow);
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "promote_secondaries", true, manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_set_sysctl(Link *link) {
|
||||
|
|
|
@ -5602,7 +5602,7 @@ static int run_container(
|
|||
}
|
||||
|
||||
/* Note: we do not use SD_EVENT_SIGNAL_PROCMASK or sd_event_set_signal_exit(), since we want the
|
||||
* signals to be block continously, even if we destroy the event loop and allocate a new one on
|
||||
* signals to be block continuously, even if we destroy the event loop and allocate a new one on
|
||||
* container reboot. */
|
||||
|
||||
if (arg_kill_signal > 0) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "sd-daemon.h"
|
||||
|
||||
#include "bpf-dlopen.h"
|
||||
#include "bpf-link.h"
|
||||
#include "build-path.h"
|
||||
#include "common-signal.h"
|
||||
#include "env-util.h"
|
||||
|
@ -141,8 +142,7 @@ Manager* manager_free(Manager *m) {
|
|||
|
||||
#if HAVE_VMLINUX_H
|
||||
sd_event_source_disable_unref(m->userns_restrict_bpf_ring_buffer_event_source);
|
||||
if (m->userns_restrict_bpf_ring_buffer)
|
||||
sym_ring_buffer__free(m->userns_restrict_bpf_ring_buffer);
|
||||
bpf_ring_buffer_free(m->userns_restrict_bpf_ring_buffer);
|
||||
userns_restrict_bpf_free(m->userns_restrict_bpf);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -5408,7 +5408,7 @@ static int partition_populate_directory(Context *context, Partition *p, char **r
|
|||
|
||||
assert(ret);
|
||||
|
||||
log_info("Populating %s filesystem.", p->format);
|
||||
log_info("Preparing to populate %s filesystem.", p->format);
|
||||
|
||||
r = var_tmp_dir(&vt);
|
||||
if (r < 0)
|
||||
|
@ -5434,7 +5434,7 @@ static int partition_populate_directory(Context *context, Partition *p, char **r
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_info("Successfully populated %s filesystem.", p->format);
|
||||
log_info("Ready to populate %s filesystem.", p->format);
|
||||
|
||||
*ret = TAKE_PTR(root);
|
||||
return 0;
|
||||
|
|
|
@ -41,3 +41,10 @@ struct bpf_link *bpf_link_free(struct bpf_link *link) {
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ring_buffer* bpf_ring_buffer_free(struct ring_buffer *rb) {
|
||||
if (rb) /* See the comment in bpf_link_free(). */
|
||||
sym_ring_buffer__free(rb);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -14,3 +14,6 @@ int bpf_serialize_link(FILE *f, FDSet *fds, const char *key, struct bpf_link *li
|
|||
|
||||
struct bpf_link* bpf_link_free(struct bpf_link *p);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct bpf_link *, bpf_link_free);
|
||||
|
||||
struct ring_buffer* bpf_ring_buffer_free(struct ring_buffer *rb);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ring_buffer *, bpf_ring_buffer_free);
|
||||
|
|
|
@ -66,9 +66,5 @@ static inline bool efi_has_tpm2(void) {
|
|||
|
||||
#endif
|
||||
|
||||
static inline char *efi_tilt_backslashes(char *s) {
|
||||
return string_replace_char(s, '\\', '/');
|
||||
}
|
||||
|
||||
sd_id128_t efi_guid_to_id128(const void *guid);
|
||||
void efi_id128_to_guid(sd_id128_t id, void *ret_guid);
|
||||
|
|
|
@ -61,30 +61,19 @@ int efi_loader_get_boot_usec(usec_t *ret_firmware, usec_t *ret_loader) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int efi_loader_get_device_part_uuid(sd_id128_t *ret) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
unsigned parsed[16];
|
||||
|
||||
static int get_device_part_uuid(const char *variable, sd_id128_t *ret) {
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderDevicePartUUID), &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return efi_get_variable_id128(variable, ret);
|
||||
}
|
||||
|
||||
if (sscanf(p, SD_ID128_UUID_FORMAT_STR,
|
||||
&parsed[0], &parsed[1], &parsed[2], &parsed[3],
|
||||
&parsed[4], &parsed[5], &parsed[6], &parsed[7],
|
||||
&parsed[8], &parsed[9], &parsed[10], &parsed[11],
|
||||
&parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16)
|
||||
return -EIO;
|
||||
int efi_loader_get_device_part_uuid(sd_id128_t *ret) {
|
||||
return get_device_part_uuid(EFI_LOADER_VARIABLE(LoaderDevicePartUUID), ret);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
for (unsigned i = 0; i < ELEMENTSOF(parsed); i++)
|
||||
ret->bytes[i] = parsed[i];
|
||||
|
||||
return 0;
|
||||
int efi_stub_get_device_part_uuid(sd_id128_t *ret) {
|
||||
return get_device_part_uuid(EFI_LOADER_VARIABLE(StubDevicePartUUID), ret);
|
||||
}
|
||||
|
||||
int efi_loader_get_entries(char ***ret) {
|
||||
|
@ -353,6 +342,22 @@ int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat
|
|||
return 0;
|
||||
}
|
||||
|
||||
int efi_get_variable_id128(const char *variable, sd_id128_t *ret) {
|
||||
int r;
|
||||
|
||||
assert(variable);
|
||||
|
||||
/* This is placed here (rather than in basic/efivars.c) because code in basic/ is not allowed to link
|
||||
* against libsystemd.so */
|
||||
|
||||
_cleanup_free_ char *p = NULL;
|
||||
r = efi_get_variable_string(variable, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_id128_from_string(p, ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool efi_loader_entry_name_valid(const char *s) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#if ENABLE_EFI
|
||||
|
||||
int efi_loader_get_device_part_uuid(sd_id128_t *ret);
|
||||
int efi_stub_get_device_part_uuid(sd_id128_t *ret);
|
||||
int efi_loader_get_boot_usec(usec_t *ret_firmware, usec_t *ret_loader);
|
||||
|
||||
int efi_loader_get_entries(char ***ret);
|
||||
|
@ -23,6 +24,8 @@ int efi_measured_uki(int log_level);
|
|||
int efi_loader_get_config_timeout_one_shot(usec_t *ret);
|
||||
int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat);
|
||||
|
||||
int efi_get_variable_id128(const char *variable, sd_id128_t *ret);
|
||||
|
||||
#else
|
||||
|
||||
static inline int efi_loader_get_device_part_uuid(sd_id128_t *u) {
|
||||
|
@ -58,6 +61,10 @@ static inline int efi_loader_update_entry_one_shot_cache(char **cache, struct st
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int efi_get_variable_id128(const char *variable, sd_id128_t *ret) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool efi_loader_entry_name_valid(const char *s);
|
||||
|
|
|
@ -968,7 +968,9 @@ void log_setup_generator(void) {
|
|||
|
||||
/* This effectively means: journal for per-user generators, kmsg otherwise */
|
||||
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
|
||||
}
|
||||
} else
|
||||
log_set_target(LOG_TARGET_AUTO);
|
||||
|
||||
log_setup();
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
static const char * const kernel_image_type_table[_KERNEL_IMAGE_TYPE_MAX] = {
|
||||
[KERNEL_IMAGE_TYPE_UNKNOWN] = "unknown",
|
||||
[KERNEL_IMAGE_TYPE_UKI] = "uki",
|
||||
[KERNEL_IMAGE_TYPE_ADDON] = "addon",
|
||||
[KERNEL_IMAGE_TYPE_PE] = "pe",
|
||||
};
|
||||
|
||||
|
@ -159,6 +160,16 @@ int inspect_kernel(
|
|||
|
||||
t = KERNEL_IMAGE_TYPE_UKI;
|
||||
goto done;
|
||||
} else if (pe_is_addon(pe_header, sections)) {
|
||||
r = inspect_uki(fd, pe_header, sections, ret_cmdline, ret_uname, /* ret_pretty_name= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_pretty_name)
|
||||
*ret_pretty_name = NULL;
|
||||
|
||||
t = KERNEL_IMAGE_TYPE_ADDON;
|
||||
goto done;
|
||||
} else
|
||||
t = KERNEL_IMAGE_TYPE_PE;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
typedef enum KernelImageType {
|
||||
KERNEL_IMAGE_TYPE_UNKNOWN,
|
||||
KERNEL_IMAGE_TYPE_UKI,
|
||||
KERNEL_IMAGE_TYPE_ADDON,
|
||||
KERNEL_IMAGE_TYPE_PE,
|
||||
_KERNEL_IMAGE_TYPE_MAX,
|
||||
_KERNEL_IMAGE_TYPE_INVALID = -EINVAL,
|
||||
|
|
|
@ -28,17 +28,16 @@ static int output_waiting_jobs(sd_bus *bus, Table *table, uint32_t id, const cha
|
|||
|
||||
while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, NULL, NULL, NULL)) > 0) {
|
||||
_cleanup_free_ char *row = NULL;
|
||||
int rc;
|
||||
|
||||
if (asprintf(&row, "%s %u (%s/%s)", prefix, other_id, name, type) < 0)
|
||||
return log_oom();
|
||||
|
||||
rc = table_add_many(table,
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, special_glyph(SPECIAL_GLYPH_TREE_RIGHT),
|
||||
TABLE_STRING, row,
|
||||
TABLE_EMPTY,
|
||||
TABLE_EMPTY);
|
||||
if (rc < 0)
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
|
|
|
@ -170,6 +170,8 @@ typedef struct Item {
|
|||
|
||||
bool try_replace:1;
|
||||
|
||||
bool purge:1;
|
||||
|
||||
OperationMask done;
|
||||
} Item;
|
||||
|
||||
|
@ -3046,6 +3048,9 @@ static int purge_item(Context *c, Item *i) {
|
|||
if (!needs_purge(i->type))
|
||||
return 0;
|
||||
|
||||
if (!i->purge)
|
||||
return 0;
|
||||
|
||||
log_debug("Running purge action for entry %c %s", (char) i->type, i->path);
|
||||
|
||||
if (needs_glob(i->type))
|
||||
|
@ -3602,7 +3607,7 @@ static int parse_line(
|
|||
ItemArray *existing;
|
||||
OrderedHashmap *h;
|
||||
bool append_or_force = false, boot = false, allow_failure = false, try_replace = false,
|
||||
unbase64 = false, from_cred = false, missing_user_or_group = false;
|
||||
unbase64 = false, from_cred = false, missing_user_or_group = false, purge = false;
|
||||
int r;
|
||||
|
||||
assert(fname);
|
||||
|
@ -3668,6 +3673,8 @@ static int parse_line(
|
|||
unbase64 = true;
|
||||
else if (action[pos] == '^' && !from_cred)
|
||||
from_cred = true;
|
||||
else if (action[pos] == '$' && !purge)
|
||||
purge = true;
|
||||
else {
|
||||
*invalid_config = true;
|
||||
return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
|
||||
|
@ -3684,6 +3691,7 @@ static int parse_line(
|
|||
i.append_or_force = append_or_force;
|
||||
i.allow_failure = allow_failure;
|
||||
i.try_replace = try_replace;
|
||||
i.purge = purge;
|
||||
|
||||
r = specifier_printf(path, PATH_MAX-1, specifier_table, arg_root, NULL, &i.path);
|
||||
if (ERRNO_IS_NOINFO(r))
|
||||
|
@ -3838,6 +3846,12 @@ static int parse_line(
|
|||
"Unknown command type '%c'.", (char) i.type);
|
||||
}
|
||||
|
||||
if (i.purge && !needs_purge(i.type)) {
|
||||
*invalid_config = true;
|
||||
return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
|
||||
"Purge flag '$' combined with line type '%c' which does not support purging.", (char) i.type);
|
||||
}
|
||||
|
||||
if (!should_include_path(i.path))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||
int r;
|
||||
char *value = UINT_TO_PTR(0x12345678U);
|
||||
char *endpos = UINT_TO_PTR(0x87654321U);
|
||||
bool is_case_sensitive;
|
||||
|
||||
fuzz_setup_logging();
|
||||
|
||||
|
@ -18,7 +19,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||
memcpy(str, data, size);
|
||||
str[size] = '\0';
|
||||
|
||||
r = udev_rule_parse_value(str, &value, &endpos);
|
||||
r = udev_rule_parse_value(str, &value, &endpos, &is_case_sensitive);
|
||||
if (r < 0) {
|
||||
/* not modified on failure */
|
||||
assert_se(value == UINT_TO_PTR(0x12345678U));
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
#include "tests.h"
|
||||
#include "udev-rules.h"
|
||||
|
||||
static void test_udev_rule_parse_value_one(const char *in, const char *expected_value, int expected_retval) {
|
||||
static void test_udev_rule_parse_value_one(const char *in, const char *expected_value, bool expected_case_insensitive, int expected_retval) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
char *value = UINT_TO_PTR(0x12345678U);
|
||||
char *endpos = UINT_TO_PTR(0x87654321U);
|
||||
bool i;
|
||||
|
||||
log_info("/* %s (%s, %s, %d) */", __func__, in, strnull(expected_value), expected_retval);
|
||||
|
||||
assert_se(str = strdup(in));
|
||||
assert_se(udev_rule_parse_value(str, &value, &endpos) == expected_retval);
|
||||
assert_se(udev_rule_parse_value(str, &value, &endpos, &i) == expected_retval);
|
||||
if (expected_retval < 0) {
|
||||
/* not modified on failure */
|
||||
assert_se(value == UINT_TO_PTR(0x12345678U));
|
||||
|
@ -25,6 +26,7 @@ static void test_udev_rule_parse_value_one(const char *in, const char *expected_
|
|||
* so it could be safely interpreted as nulstr.
|
||||
*/
|
||||
assert_se(value[strlen(value) + 1] == '\0');
|
||||
assert_se(i == expected_case_insensitive);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,45 +35,61 @@ TEST(udev_rule_parse_value) {
|
|||
* parsed: valid operand
|
||||
* use the following command to help generate textual C strings:
|
||||
* python3 -c 'import json; print(json.dumps(input()))' */
|
||||
test_udev_rule_parse_value_one("\"valid operand\"", "valid operand", 0);
|
||||
test_udev_rule_parse_value_one("\"valid operand\"", "valid operand", /* case_insensitive = */ false, 0);
|
||||
/* input: "va'l\'id\"op\"erand"
|
||||
* parsed: va'l\'id"op"erand */
|
||||
test_udev_rule_parse_value_one("\"va'l\\'id\\\"op\\\"erand\"", "va'l\\'id\"op\"erand", 0);
|
||||
test_udev_rule_parse_value_one("no quotes", NULL, -EINVAL);
|
||||
test_udev_rule_parse_value_one("\"\\\\a\\b\\x\\y\"", "\\\\a\\b\\x\\y", 0);
|
||||
test_udev_rule_parse_value_one("\"reject\0nul\"", NULL, -EINVAL);
|
||||
test_udev_rule_parse_value_one("\"va'l\\'id\\\"op\\\"erand\"", "va'l\\'id\"op\"erand", /* case_insensitive = */ false, 0);
|
||||
test_udev_rule_parse_value_one("no quotes", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
test_udev_rule_parse_value_one("\"\\\\a\\b\\x\\y\"", "\\\\a\\b\\x\\y", /* case_insensitive = */ false, 0);
|
||||
test_udev_rule_parse_value_one("\"reject\0nul\"", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: e"" */
|
||||
test_udev_rule_parse_value_one("e\"\"", "", 0);
|
||||
test_udev_rule_parse_value_one("e\"\"", "", /* case_insensitive = */ false, 0);
|
||||
/* input: e"1234" */
|
||||
test_udev_rule_parse_value_one("e\"1234\"", "1234", 0);
|
||||
test_udev_rule_parse_value_one("e\"1234\"", "1234", /* case_insensitive = */ false, 0);
|
||||
/* input: e"\"" */
|
||||
test_udev_rule_parse_value_one("e\"\\\"\"", "\"", 0);
|
||||
test_udev_rule_parse_value_one("e\"\\\"\"", "\"", /* case_insensitive = */ false, 0);
|
||||
/* input: e"\ */
|
||||
test_udev_rule_parse_value_one("e\"\\", NULL, -EINVAL);
|
||||
test_udev_rule_parse_value_one("e\"\\", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: e"\" */
|
||||
test_udev_rule_parse_value_one("e\"\\\"", NULL, -EINVAL);
|
||||
test_udev_rule_parse_value_one("e\"\\\"", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: e"\\" */
|
||||
test_udev_rule_parse_value_one("e\"\\\\\"", "\\", 0);
|
||||
test_udev_rule_parse_value_one("e\"\\\\\"", "\\", /* case_insensitive = */ false, 0);
|
||||
/* input: e"\\\" */
|
||||
test_udev_rule_parse_value_one("e\"\\\\\\\"", NULL, -EINVAL);
|
||||
test_udev_rule_parse_value_one("e\"\\\\\\\"", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: e"\\\"" */
|
||||
test_udev_rule_parse_value_one("e\"\\\\\\\"\"", "\\\"", 0);
|
||||
test_udev_rule_parse_value_one("e\"\\\\\\\"\"", "\\\"", /* case_insensitive = */ false, 0);
|
||||
/* input: e"\\\\" */
|
||||
test_udev_rule_parse_value_one("e\"\\\\\\\\\"", "\\\\", 0);
|
||||
test_udev_rule_parse_value_one("e\"\\\\\\\\\"", "\\\\", /* case_insensitive = */ false, 0);
|
||||
/* input: e"operand with newline\n" */
|
||||
test_udev_rule_parse_value_one("e\"operand with newline\\n\"", "operand with newline\n", 0);
|
||||
test_udev_rule_parse_value_one("e\"operand with newline\\n\"", "operand with newline\n", /* case_insensitive = */ false, 0);
|
||||
/* input: e"single\rcharacter\t\aescape\bsequence" */
|
||||
test_udev_rule_parse_value_one(
|
||||
"e\"single\\rcharacter\\t\\aescape\\bsequence\"", "single\rcharacter\t\aescape\bsequence", 0);
|
||||
"e\"single\\rcharacter\\t\\aescape\\bsequence\"", "single\rcharacter\t\aescape\bsequence", /* case_insensitive = */ false, 0);
|
||||
/* input: e"reject\invalid escape sequence" */
|
||||
test_udev_rule_parse_value_one("e\"reject\\invalid escape sequence", NULL, -EINVAL);
|
||||
test_udev_rule_parse_value_one("e\"reject\\invalid escape sequence", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: e"\ */
|
||||
test_udev_rule_parse_value_one("e\"\\", NULL, -EINVAL);
|
||||
test_udev_rule_parse_value_one("e\"\\", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: "s\u1d1c\u1d04\u029c \u1d1c\u0274\u026a\u1d04\u1d0f\u1d05\u1d07 \U0001d568\U0001d560\U0001d568" */
|
||||
test_udev_rule_parse_value_one(
|
||||
"e\"s\\u1d1c\\u1d04\\u029c \\u1d1c\\u0274\\u026a\\u1d04\\u1d0f\\u1d05\\u1d07 \\U0001d568\\U0001d560\\U0001d568\"",
|
||||
"s\xe1\xb4\x9c\xe1\xb4\x84\xca\x9c \xe1\xb4\x9c\xc9\xb4\xc9\xaa\xe1\xb4\x84\xe1\xb4\x8f\xe1\xb4\x85\xe1\xb4\x87 \xf0\x9d\x95\xa8\xf0\x9d\x95\xa0\xf0\x9d\x95\xa8",
|
||||
0);
|
||||
/* case_insensitive = */ false, 0);
|
||||
/* input: i"ABCD1234" */
|
||||
test_udev_rule_parse_value_one("i\"ABCD1234\"", "ABCD1234", /* case_insensitive = */ true, 0);
|
||||
/* input: i"ABCD1234" */
|
||||
test_udev_rule_parse_value_one("e\"ABCD1234\"", "ABCD1234", /* case_insensitive = */ false, 0);
|
||||
/* input: ei"\\"ABCD1234 */
|
||||
test_udev_rule_parse_value_one("ei\"\\\\ABCD1234\"", "\\ABCD1234", /* case_insensitive = */ true, 0);
|
||||
/* input: ie"\\"ABCD1234 */
|
||||
test_udev_rule_parse_value_one("ie\"\\\\ABCD1234\"", "\\ABCD1234", /* case_insensitive = */ true, 0);
|
||||
/* input: i */
|
||||
test_udev_rule_parse_value_one("i", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: ee"" */
|
||||
test_udev_rule_parse_value_one("ee\"\"", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: iei"" */
|
||||
test_udev_rule_parse_value_one("iei\"\"", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
/* input: a"" */
|
||||
test_udev_rule_parse_value_one("a\"\"", NULL, /* case_insensitive = */ false, -EINVAL);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
|
|
@ -63,9 +63,15 @@ typedef enum {
|
|||
MATCH_TYPE_GLOB_WITH_EMPTY, /* shell globs ?,*,[] with empty string, e.g., "|foo*" */
|
||||
MATCH_TYPE_SUBSYSTEM, /* "subsystem", "bus", or "class" */
|
||||
_MATCH_TYPE_MAX,
|
||||
|
||||
_MATCH_TYPE_MASK = (1 << 5) - 1,
|
||||
MATCH_REMOVE_TRAILING_WHITESPACE = 1 << 5, /* Remove trailing whitespaces in attribute */
|
||||
MATCH_CASE_INSENSITIVE = 1 << 6, /* string or pattern is matched case-insensitively */
|
||||
_MATCH_TYPE_INVALID = -EINVAL,
|
||||
} UdevRuleMatchType;
|
||||
|
||||
assert_cc(_MATCH_TYPE_MAX <= _MATCH_TYPE_MASK);
|
||||
|
||||
typedef enum {
|
||||
SUBST_TYPE_PLAIN, /* no substitution */
|
||||
SUBST_TYPE_FORMAT, /* % or $ */
|
||||
|
@ -155,8 +161,7 @@ struct UdevRuleToken {
|
|||
UdevRuleTokenType type:8;
|
||||
UdevRuleOperatorType op:8;
|
||||
UdevRuleMatchType match_type:8;
|
||||
UdevRuleSubstituteType attr_subst_type:7;
|
||||
bool attr_match_remove_trailing_whitespace:1;
|
||||
UdevRuleSubstituteType attr_subst_type:8;
|
||||
const char *value;
|
||||
void *data;
|
||||
|
||||
|
@ -295,6 +300,7 @@ struct UdevRules {
|
|||
|
||||
#define log_line_invalid_op(line, key) _log_line_invalid_token(line, key, "operator")
|
||||
#define log_line_invalid_attr(line, key) _log_line_invalid_token(line, key, "attribute")
|
||||
#define log_line_invalid_prefix(line, key) _log_line_invalid_token(line, key, "prefix 'i'")
|
||||
|
||||
#define log_line_invalid_attr_format(line, key, attr, offset, hint) \
|
||||
log_line_error_errno(line, SYNTHETIC_ERRNO(EINVAL), \
|
||||
|
@ -488,12 +494,10 @@ static bool type_has_nulstr_value(UdevRuleTokenType type) {
|
|||
return type < TK_M_TEST || type == TK_M_RESULT;
|
||||
}
|
||||
|
||||
static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type, UdevRuleOperatorType op, char *value, void *data) {
|
||||
static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type, UdevRuleOperatorType op, char *value, void *data, bool is_case_insensitive) {
|
||||
_cleanup_(udev_rule_token_freep) UdevRuleToken *token = NULL;
|
||||
UdevRuleMatchType match_type = _MATCH_TYPE_INVALID;
|
||||
UdevRuleSubstituteType subst_type = _SUBST_TYPE_INVALID;
|
||||
bool remove_trailing_whitespace = false;
|
||||
size_t len;
|
||||
|
||||
assert(rule_line);
|
||||
assert(type >= 0 && type < _TK_TYPE_MAX);
|
||||
|
@ -552,16 +556,21 @@ static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type,
|
|||
}
|
||||
|
||||
if (IN_SET(type, TK_M_ATTR, TK_M_PARENTS_ATTR)) {
|
||||
size_t len;
|
||||
|
||||
assert(value);
|
||||
assert(data);
|
||||
assert(match_type >= 0 && match_type < _MATCH_TYPE_MAX);
|
||||
|
||||
len = strlen(value);
|
||||
if (len > 0 && !isspace(value[len - 1]))
|
||||
remove_trailing_whitespace = true;
|
||||
match_type |= MATCH_REMOVE_TRAILING_WHITESPACE;
|
||||
|
||||
subst_type = rule_get_substitution_type(data);
|
||||
}
|
||||
|
||||
SET_FLAG(match_type, MATCH_CASE_INSENSITIVE, is_case_insensitive);
|
||||
|
||||
token = new(UdevRuleToken, 1);
|
||||
if (!token)
|
||||
return -ENOMEM;
|
||||
|
@ -573,7 +582,6 @@ static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type,
|
|||
.data = data,
|
||||
.match_type = match_type,
|
||||
.attr_subst_type = subst_type,
|
||||
.attr_match_remove_trailing_whitespace = remove_trailing_whitespace,
|
||||
.rule_line = rule_line,
|
||||
};
|
||||
|
||||
|
@ -621,7 +629,7 @@ static int check_attr_format_and_warn(UdevRuleLine *line, const char *key, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, UdevRuleOperatorType op, char *value) {
|
||||
static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, UdevRuleOperatorType op, char *value, bool is_case_insensitive) {
|
||||
ResolveNameTiming resolve_name_timing = LINE_GET_RULES(rule_line)->resolve_name_timing;
|
||||
bool is_match = IN_SET(op, OP_MATCH, OP_NOMATCH);
|
||||
int r;
|
||||
|
@ -629,35 +637,39 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
assert(key);
|
||||
assert(value);
|
||||
|
||||
if (!is_match && is_case_insensitive)
|
||||
return log_line_error_errno(rule_line, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid prefix 'i' for '%s'. The 'i' prefix can be specified only for '==' or '!=' operator.", key);
|
||||
|
||||
if (streq(key, "ACTION")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_ACTION, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_ACTION, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "DEVPATH")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_DEVPATH, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_DEVPATH, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "KERNEL")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_KERNEL, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_KERNEL, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "SYMLINK")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match) {
|
||||
check_value_format_and_warn(rule_line, key, value, false);
|
||||
r = rule_line_add_token(rule_line, TK_A_DEVLINK, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_DEVLINK, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
} else
|
||||
r = rule_line_add_token(rule_line, TK_M_DEVLINK, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_DEVLINK, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "NAME")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
|
@ -677,9 +689,9 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
"Ignoring NAME=\"\", as udev will not delete any network interfaces.");
|
||||
check_value_format_and_warn(rule_line, key, value, false);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_A_NAME, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_NAME, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
} else
|
||||
r = rule_line_add_token(rule_line, TK_M_NAME, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_NAME, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "ENV")) {
|
||||
if (isempty(attr))
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
|
@ -697,15 +709,15 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
|
||||
check_value_format_and_warn(rule_line, key, value, false);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_A_ENV, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_A_ENV, op, value, attr, /* is_case_insensitive = */ false);
|
||||
} else
|
||||
r = rule_line_add_token(rule_line, TK_M_ENV, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_M_ENV, op, value, attr, is_case_insensitive);
|
||||
} else if (streq(key, "CONST")) {
|
||||
if (isempty(attr) || !STR_IN_SET(attr, "arch", "virt"))
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
r = rule_line_add_token(rule_line, TK_M_CONST, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_M_CONST, op, value, attr, is_case_insensitive);
|
||||
} else if (streq(key, "TAG")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
|
@ -717,9 +729,9 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
if (!is_match) {
|
||||
check_value_format_and_warn(rule_line, key, value, true);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_A_TAG, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_TAG, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
} else
|
||||
r = rule_line_add_token(rule_line, TK_M_TAG, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_TAG, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "SUBSYSTEM")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
|
@ -729,14 +741,14 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
if (STR_IN_SET(value, "bus", "class"))
|
||||
log_line_warning(rule_line, "\"%s\" must be specified as \"subsystem\".", value);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_SUBSYSTEM, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_SUBSYSTEM, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "DRIVER")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_DRIVER, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_DRIVER, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "ATTR")) {
|
||||
r = check_attr_format_and_warn(rule_line, key, attr);
|
||||
if (r < 0)
|
||||
|
@ -750,9 +762,9 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
|
||||
if (!is_match) {
|
||||
check_value_format_and_warn(rule_line, key, value, false);
|
||||
r = rule_line_add_token(rule_line, TK_A_ATTR, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_A_ATTR, op, value, attr, /* is_case_insensitive = */ false);
|
||||
} else
|
||||
r = rule_line_add_token(rule_line, TK_M_ATTR, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_M_ATTR, op, value, attr, is_case_insensitive);
|
||||
} else if (streq(key, "SYSCTL")) {
|
||||
r = check_attr_format_and_warn(rule_line, key, attr);
|
||||
if (r < 0)
|
||||
|
@ -766,30 +778,30 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
|
||||
if (!is_match) {
|
||||
check_value_format_and_warn(rule_line, key, value, false);
|
||||
r = rule_line_add_token(rule_line, TK_A_SYSCTL, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_A_SYSCTL, op, value, attr, /* is_case_insensitive = */ false);
|
||||
} else
|
||||
r = rule_line_add_token(rule_line, TK_M_SYSCTL, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_M_SYSCTL, op, value, attr, is_case_insensitive);
|
||||
} else if (streq(key, "KERNELS")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_KERNEL, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_KERNEL, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "SUBSYSTEMS")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_SUBSYSTEM, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_SUBSYSTEM, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "DRIVERS")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_DRIVER, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_DRIVER, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "ATTRS")) {
|
||||
r = check_attr_format_and_warn(rule_line, key, attr);
|
||||
if (r < 0)
|
||||
|
@ -802,14 +814,14 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
if (strstr(attr, "../"))
|
||||
log_line_warning(rule_line, "Direct reference to parent sysfs directory, may break in future kernels.");
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_ATTR, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_ATTR, op, value, attr, is_case_insensitive);
|
||||
} else if (streq(key, "TAGS")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_TAG, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_PARENTS_TAG, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "TEST")) {
|
||||
mode_t mode = MODE_INVALID;
|
||||
|
||||
|
@ -821,8 +833,10 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
check_value_format_and_warn(rule_line, key, value, true);
|
||||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
if (is_case_insensitive)
|
||||
return log_line_invalid_prefix(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_TEST, op, value, MODE_TO_PTR(mode));
|
||||
r = rule_line_add_token(rule_line, TK_M_TEST, op, value, MODE_TO_PTR(mode), is_case_insensitive);
|
||||
} else if (streq(key, "PROGRAM")) {
|
||||
if (attr)
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
|
@ -831,8 +845,10 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
return log_line_invalid_op(rule_line, key);
|
||||
if (!is_match)
|
||||
op = OP_MATCH;
|
||||
if (is_case_insensitive)
|
||||
return log_line_invalid_prefix(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_PROGRAM, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_PROGRAM, op, value, NULL, /* is_case_insensitive */ false);
|
||||
} else if (streq(key, "IMPORT")) {
|
||||
if (isempty(attr))
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
|
@ -841,18 +857,20 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
return log_line_invalid_op(rule_line, key);
|
||||
if (!is_match)
|
||||
op = OP_MATCH;
|
||||
if (is_case_insensitive)
|
||||
return log_line_invalid_prefix(rule_line, key);
|
||||
|
||||
if (streq(attr, "file"))
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_FILE, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_FILE, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
else if (streq(attr, "program")) {
|
||||
UdevBuiltinCommand cmd;
|
||||
|
||||
cmd = udev_builtin_lookup(value);
|
||||
if (cmd >= 0) {
|
||||
log_line_debug(rule_line, "Found builtin command '%s' for %s, replacing attribute.", value, key);
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd));
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false);
|
||||
} else
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_PROGRAM, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_PROGRAM, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
} else if (streq(attr, "builtin")) {
|
||||
UdevBuiltinCommand cmd;
|
||||
|
||||
|
@ -860,13 +878,13 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
if (cmd < 0)
|
||||
return log_line_error_errno(rule_line, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Unknown builtin command: %s", value);
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd));
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false);
|
||||
} else if (streq(attr, "db"))
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_DB, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_DB, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
else if (streq(attr, "cmdline"))
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_CMDLINE, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_CMDLINE, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
else if (streq(attr, "parent"))
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_PARENT, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_IMPORT_PARENT, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
else
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
} else if (streq(key, "RESULT")) {
|
||||
|
@ -875,7 +893,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
if (!is_match)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_M_RESULT, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_M_RESULT, op, value, NULL, is_case_insensitive);
|
||||
} else if (streq(key, "OPTIONS")) {
|
||||
char *tmp;
|
||||
|
||||
|
@ -887,24 +905,24 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
op = OP_ASSIGN;
|
||||
|
||||
if (streq(value, "string_escape=none"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_NONE, op, NULL, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_NONE, op, NULL, NULL, /* is_case_insensitive = */ false);
|
||||
else if (streq(value, "string_escape=replace"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_REPLACE, op, NULL, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_REPLACE, op, NULL, NULL, /* is_case_insensitive = */ false);
|
||||
else if (streq(value, "db_persist"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_DB_PERSIST, op, NULL, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_DB_PERSIST, op, NULL, NULL, /* is_case_insensitive = */ false);
|
||||
else if (streq(value, "watch"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(1));
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(1), /* is_case_insensitive = */ false);
|
||||
else if (streq(value, "nowatch"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(0));
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(0), /* is_case_insensitive = */ false);
|
||||
else if ((tmp = startswith(value, "static_node=")))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_STATIC_NODE, op, tmp, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_STATIC_NODE, op, tmp, NULL, /* is_case_insensitive = */ false);
|
||||
else if ((tmp = startswith(value, "link_priority="))) {
|
||||
int prio;
|
||||
|
||||
r = safe_atoi(tmp, &prio);
|
||||
if (r < 0)
|
||||
return log_line_error_errno(rule_line, r, "Failed to parse link priority '%s': %m", tmp);
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_DEVLINK_PRIORITY, op, NULL, INT_TO_PTR(prio));
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_DEVLINK_PRIORITY, op, NULL, INT_TO_PTR(prio), /* is_case_insensitive = */ false);
|
||||
} else if ((tmp = startswith(value, "log_level="))) {
|
||||
int level;
|
||||
|
||||
|
@ -915,7 +933,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
if (level < 0)
|
||||
return log_line_error_errno(rule_line, level, "Failed to parse log level '%s': %m", tmp);
|
||||
}
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_LOG_LEVEL, op, NULL, INT_TO_PTR(level));
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_LOG_LEVEL, op, NULL, INT_TO_PTR(level), /* is_case_insensitive = */ false);
|
||||
} else {
|
||||
log_line_warning(rule_line, "Invalid value for OPTIONS key, ignoring: '%s'", value);
|
||||
return 0;
|
||||
|
@ -933,17 +951,17 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
}
|
||||
|
||||
if (parse_uid(value, &uid) >= 0)
|
||||
r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid));
|
||||
r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid), /* is_case_insensitive = */ false);
|
||||
else if (resolve_name_timing == RESOLVE_NAME_EARLY &&
|
||||
rule_get_substitution_type(value) == SUBST_TYPE_PLAIN) {
|
||||
r = rule_resolve_user(rule_line, value, &uid);
|
||||
if (r < 0)
|
||||
return log_line_error_errno(rule_line, r, "Failed to resolve user name '%s': %m", value);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid));
|
||||
r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid), /* is_case_insensitive = */ false);
|
||||
} else if (resolve_name_timing != RESOLVE_NAME_NEVER) {
|
||||
check_value_format_and_warn(rule_line, key, value, true);
|
||||
r = rule_line_add_token(rule_line, TK_A_OWNER, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_OWNER, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
} else {
|
||||
log_line_debug(rule_line, "User name resolution is disabled, ignoring %s=\"%s\".", key, value);
|
||||
return 0;
|
||||
|
@ -961,17 +979,17 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
}
|
||||
|
||||
if (parse_gid(value, &gid) >= 0)
|
||||
r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid));
|
||||
r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid), /* is_case_insensitive = */ false);
|
||||
else if (resolve_name_timing == RESOLVE_NAME_EARLY &&
|
||||
rule_get_substitution_type(value) == SUBST_TYPE_PLAIN) {
|
||||
r = rule_resolve_group(rule_line, value, &gid);
|
||||
if (r < 0)
|
||||
return log_line_error_errno(rule_line, r, "Failed to resolve group name '%s': %m", value);
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid));
|
||||
r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid), /* is_case_insensitive = */ false);
|
||||
} else if (resolve_name_timing != RESOLVE_NAME_NEVER) {
|
||||
check_value_format_and_warn(rule_line, key, value, true);
|
||||
r = rule_line_add_token(rule_line, TK_A_GROUP, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_GROUP, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
} else {
|
||||
log_line_debug(rule_line, "Resolving group name is disabled, ignoring GROUP=\"%s\".", value);
|
||||
return 0;
|
||||
|
@ -989,10 +1007,10 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
}
|
||||
|
||||
if (parse_mode(value, &mode) >= 0)
|
||||
r = rule_line_add_token(rule_line, TK_A_MODE_ID, op, NULL, MODE_TO_PTR(mode));
|
||||
r = rule_line_add_token(rule_line, TK_A_MODE_ID, op, NULL, MODE_TO_PTR(mode), /* is_case_insensitive = */ false);
|
||||
else {
|
||||
check_value_format_and_warn(rule_line, key, value, true);
|
||||
r = rule_line_add_token(rule_line, TK_A_MODE, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_MODE, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
}
|
||||
} else if (streq(key, "SECLABEL")) {
|
||||
if (isempty(attr))
|
||||
|
@ -1005,13 +1023,13 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
op = OP_ASSIGN;
|
||||
}
|
||||
|
||||
r = rule_line_add_token(rule_line, TK_A_SECLABEL, op, value, attr);
|
||||
r = rule_line_add_token(rule_line, TK_A_SECLABEL, op, value, attr, /* is_case_insensitive = */ false);
|
||||
} else if (streq(key, "RUN")) {
|
||||
if (is_match || op == OP_REMOVE)
|
||||
return log_line_invalid_op(rule_line, key);
|
||||
check_value_format_and_warn(rule_line, key, value, true);
|
||||
if (!attr || streq(attr, "program"))
|
||||
r = rule_line_add_token(rule_line, TK_A_RUN_PROGRAM, op, value, NULL);
|
||||
r = rule_line_add_token(rule_line, TK_A_RUN_PROGRAM, op, value, NULL, /* is_case_insensitive = */ false);
|
||||
else if (streq(attr, "builtin")) {
|
||||
UdevBuiltinCommand cmd;
|
||||
|
||||
|
@ -1019,7 +1037,7 @@ static int parse_token(UdevRuleLine *rule_line, const char *key, char *attr, Ude
|
|||
if (cmd < 0)
|
||||
return log_line_error_errno(rule_line, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Unknown builtin command '%s', ignoring.", value);
|
||||
r = rule_line_add_token(rule_line, TK_A_RUN_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd));
|
||||
r = rule_line_add_token(rule_line, TK_A_RUN_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd), /* is_case_insensitive = */ false);
|
||||
} else
|
||||
return log_line_invalid_attr(rule_line, key);
|
||||
} else if (streq(key, "GOTO")) {
|
||||
|
@ -1119,13 +1137,30 @@ static void check_token_delimiters(UdevRuleLine *rule_line, const char *line) {
|
|||
}
|
||||
}
|
||||
|
||||
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
|
||||
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos, bool *ret_is_case_insensitive) {
|
||||
char *i, *j;
|
||||
bool is_escaped;
|
||||
bool is_escaped = false, is_case_insensitive = false;
|
||||
|
||||
assert(str);
|
||||
assert(ret_value);
|
||||
assert(ret_endpos);
|
||||
assert(ret_is_case_insensitive);
|
||||
|
||||
/* check if string is prefixed with:
|
||||
* - "e" for escaped
|
||||
* - "i" for case insensitive match
|
||||
*
|
||||
* Note both e and i can be set but do not allow duplicates ("eei", "eii"). */
|
||||
for (const char *k = str; *k != '"' && k < str + 2; k++)
|
||||
if (*k == 'e' && !is_escaped)
|
||||
is_escaped = true;
|
||||
else if (*k == 'i' && !is_case_insensitive)
|
||||
is_case_insensitive = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* value must be double quotated */
|
||||
is_escaped = str[0] == 'e';
|
||||
str += is_escaped;
|
||||
str += is_escaped + is_case_insensitive;
|
||||
if (str[0] != '"')
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1172,10 +1207,11 @@ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
|
|||
|
||||
*ret_value = str;
|
||||
*ret_endpos = i + 1;
|
||||
*ret_is_case_insensitive = is_case_insensitive;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_line(char **line, char **ret_key, char **ret_attr, UdevRuleOperatorType *ret_op, char **ret_value) {
|
||||
static int parse_line(char **line, char **ret_key, char **ret_attr, UdevRuleOperatorType *ret_op, char **ret_value, bool *ret_is_case_insensitive) {
|
||||
char *key_begin, *key_end, *attr, *tmp;
|
||||
UdevRuleOperatorType op;
|
||||
int r;
|
||||
|
@ -1185,6 +1221,7 @@ static int parse_line(char **line, char **ret_key, char **ret_attr, UdevRuleOper
|
|||
assert(ret_key);
|
||||
assert(ret_op);
|
||||
assert(ret_value);
|
||||
assert(ret_is_case_insensitive);
|
||||
|
||||
key_begin = skip_leading_chars(*line, WHITESPACE ",");
|
||||
|
||||
|
@ -1219,7 +1256,7 @@ static int parse_line(char **line, char **ret_key, char **ret_attr, UdevRuleOper
|
|||
|
||||
tmp += op == OP_ASSIGN ? 1 : 2;
|
||||
tmp = skip_leading_chars(tmp, NULL);
|
||||
r = udev_rule_parse_value(tmp, ret_value, line);
|
||||
r = udev_rule_parse_value(tmp, ret_value, line, ret_is_case_insensitive);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -1291,17 +1328,18 @@ static int rule_add_line(UdevRuleFile *rule_file, const char *line_str, unsigned
|
|||
for (p = rule_line->line; !isempty(p); ) {
|
||||
char *key, *attr, *value;
|
||||
UdevRuleOperatorType op;
|
||||
bool is_case_insensitive;
|
||||
|
||||
if (extra_checks)
|
||||
check_token_delimiters(rule_line, p);
|
||||
|
||||
r = parse_line(&p, &key, &attr, &op, &value);
|
||||
r = parse_line(&p, &key, &attr, &op, &value, &is_case_insensitive);
|
||||
if (r < 0)
|
||||
return log_line_error_errno(rule_line, r, "Invalid key/value pair, ignoring.");
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = parse_token(rule_line, key, attr, op, value);
|
||||
r = parse_token(rule_line, key, attr, op, value, is_case_insensitive);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -1412,7 +1450,6 @@ static bool tokens_eq(const UdevRuleToken *a, const UdevRuleToken *b) {
|
|||
assert(b);
|
||||
|
||||
return a->attr_subst_type == b->attr_subst_type &&
|
||||
a->attr_match_remove_trailing_whitespace == b->attr_match_remove_trailing_whitespace &&
|
||||
token_type_and_value_eq(a, b) &&
|
||||
token_type_and_data_eq(a, b);
|
||||
}
|
||||
|
@ -1427,7 +1464,6 @@ static bool nulstr_tokens_conflict(const UdevRuleToken *a, const UdevRuleToken *
|
|||
a->op == OP_MATCH &&
|
||||
a->match_type == b->match_type &&
|
||||
a->attr_subst_type == b->attr_subst_type &&
|
||||
a->attr_match_remove_trailing_whitespace == b->attr_match_remove_trailing_whitespace &&
|
||||
token_type_and_data_eq(a, b)))
|
||||
return false;
|
||||
|
||||
|
@ -1696,7 +1732,7 @@ bool udev_rules_should_reload(UdevRules *rules) {
|
|||
|
||||
static bool token_match_string(UdevRuleToken *token, const char *str) {
|
||||
const char *value;
|
||||
bool match = false;
|
||||
bool match = false, case_insensitive;
|
||||
|
||||
assert(token);
|
||||
assert(token->value);
|
||||
|
@ -1704,12 +1740,16 @@ static bool token_match_string(UdevRuleToken *token, const char *str) {
|
|||
|
||||
str = strempty(str);
|
||||
value = token->value;
|
||||
case_insensitive = FLAGS_SET(token->match_type, MATCH_CASE_INSENSITIVE);
|
||||
|
||||
switch (token->match_type) {
|
||||
switch (token->match_type & _MATCH_TYPE_MASK) {
|
||||
case MATCH_TYPE_EMPTY:
|
||||
match = isempty(str);
|
||||
break;
|
||||
case MATCH_TYPE_SUBSYSTEM:
|
||||
if (case_insensitive)
|
||||
match = STRCASE_IN_SET(str, "subsystem", "class", "bus");
|
||||
else
|
||||
match = STR_IN_SET(str, "subsystem", "class", "bus");
|
||||
break;
|
||||
case MATCH_TYPE_PLAIN_WITH_EMPTY:
|
||||
|
@ -1720,7 +1760,7 @@ static bool token_match_string(UdevRuleToken *token, const char *str) {
|
|||
_fallthrough_;
|
||||
case MATCH_TYPE_PLAIN:
|
||||
NULSTR_FOREACH(i, value)
|
||||
if (streq(i, str)) {
|
||||
if (case_insensitive ? strcaseeq(i, str) : streq(i, str)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1733,7 +1773,7 @@ static bool token_match_string(UdevRuleToken *token, const char *str) {
|
|||
_fallthrough_;
|
||||
case MATCH_TYPE_GLOB:
|
||||
NULSTR_FOREACH(i, value)
|
||||
if ((fnmatch(i, str, 0) == 0)) {
|
||||
if ((fnmatch(i, str, case_insensitive ? FNM_CASEFOLD : 0) == 0)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1773,7 +1813,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev
|
|||
return false;
|
||||
|
||||
/* remove trailing whitespace, if not asked to match for it */
|
||||
if (token->attr_match_remove_trailing_whitespace) {
|
||||
if (FLAGS_SET(token->match_type, MATCH_REMOVE_TRAILING_WHITESPACE)) {
|
||||
strscpy(vbuf, sizeof(vbuf), value);
|
||||
value = delete_trailing_chars(vbuf, NULL);
|
||||
}
|
||||
|
@ -1785,7 +1825,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev
|
|||
return false;
|
||||
|
||||
/* remove trailing whitespace, if not asked to match for it */
|
||||
if (token->attr_match_remove_trailing_whitespace)
|
||||
if (FLAGS_SET(token->match_type, MATCH_REMOVE_TRAILING_WHITESPACE))
|
||||
delete_trailing_chars(vbuf, NULL);
|
||||
|
||||
return token_match_string(token, vbuf);
|
||||
|
|
|
@ -29,7 +29,7 @@ typedef enum ResolveNameTiming {
|
|||
_RESOLVE_NAME_TIMING_INVALID = -EINVAL,
|
||||
} ResolveNameTiming;
|
||||
|
||||
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos);
|
||||
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos, bool *ret_is_case_insensitive);
|
||||
int udev_rules_parse_file(UdevRules *rules, const char *filename, bool extra_checks, UdevRuleFile **ret);
|
||||
unsigned udev_rule_file_get_issues(UdevRuleFile *rule_file);
|
||||
UdevRules* udev_rules_new(ResolveNameTiming resolve_name_timing);
|
||||
|
|
|
@ -2313,6 +2313,17 @@ SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c \"printf %%s 'foo1 foo2' | grep 'foo1 f
|
|||
SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sd*", SYMLINK+="blockdev"
|
||||
KERNEL=="sda6", OPTIONS+="link_priority=10"
|
||||
"""),
|
||||
|
||||
Rules.new(
|
||||
"case insensitive match",
|
||||
Device(
|
||||
"/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||
exp_links = ["ok"],
|
||||
),
|
||||
|
||||
rules = r"""
|
||||
KERNEL==i"SDA1", SUBSYSTEMS==i"SCSI", ATTRS{vendor}==i"a?a", SYMLINK+="ok"
|
||||
"""),
|
||||
]
|
||||
|
||||
def fork_and_run_udev(action: str, rules: Rules) -> None:
|
||||
|
|
|
@ -237,6 +237,8 @@ test_syntax_error 'ENV=="b"' 'Invalid attribute for ENV.'
|
|||
test_syntax_error 'ENV{a}-="b"' 'Invalid operator for ENV.'
|
||||
test_syntax_error 'ENV{a}:="b"' "ENV key takes '==', '!=', '=', or '+=' operator, assuming '='."
|
||||
test_syntax_error 'ENV{ACTION}="b"' "Invalid ENV attribute. 'ACTION' cannot be set."
|
||||
test_syntax_error 'ENV{a}=i"b"' "Invalid prefix 'i' for 'ENV'. The 'i' prefix can be specified only for '==' or '!=' operator."
|
||||
test_syntax_error 'ENV{a}+=i"b"' "Invalid prefix 'i' for 'ENV'. The 'i' prefix can be specified only for '==' or '!=' operator."
|
||||
test_syntax_error 'CONST=="b"' 'Invalid attribute for CONST.'
|
||||
test_syntax_error 'CONST{a}=="b"' 'Invalid attribute for CONST.'
|
||||
test_syntax_error 'CONST{arch}="b"' 'Invalid operator for CONST.'
|
||||
|
@ -275,10 +277,12 @@ test_syntax_error 'TEST{0644}="b"' 'Invalid operator for TEST.'
|
|||
test_syntax_error 'PROGRAM{a}=="b"' 'Invalid attribute for PROGRAM.'
|
||||
test_syntax_error 'PROGRAM-="b"' 'Invalid operator for PROGRAM.'
|
||||
test_syntax_error 'PROGRAM=="%", NAME="b"' 'Invalid value "%" for PROGRAM (char 1: invalid substitution type), ignoring.'
|
||||
test_syntax_error 'PROGRAM==i"b"' "Invalid prefix 'i' for PROGRAM."
|
||||
test_syntax_error 'IMPORT="b"' 'Invalid attribute for IMPORT.'
|
||||
test_syntax_error 'IMPORT{a}="b"' 'Invalid attribute for IMPORT.'
|
||||
test_syntax_error 'IMPORT{a}-="b"' 'Invalid operator for IMPORT.'
|
||||
test_syntax_error 'IMPORT{file}=="%", NAME="b"' 'Invalid value "%" for IMPORT (char 1: invalid substitution type), ignoring.'
|
||||
test_syntax_error 'IMPORT{file}==i"a", NAME="b"' "Invalid prefix 'i' for IMPORT."
|
||||
test_syntax_error 'IMPORT{builtin}!="foo"' 'Unknown builtin command: foo'
|
||||
test_syntax_error 'RESULT{a}=="b"' 'Invalid attribute for RESULT.'
|
||||
test_syntax_error 'RESULT:="b"' 'Invalid operator for RESULT.'
|
||||
|
|
|
@ -9,26 +9,39 @@ set -o pipefail
|
|||
export SYSTEMD_LOG_LEVEL=debug
|
||||
|
||||
c='
|
||||
d /tmp/somedir
|
||||
f /tmp/somedir/somefile - - - - baz
|
||||
d$ /tmp/somedir
|
||||
f$ /tmp/somedir/somefile - - - - baz
|
||||
f /tmp/someotherfile - - - - qux
|
||||
'
|
||||
|
||||
systemd-tmpfiles --create - <<<"$c"
|
||||
test -f /tmp/somedir/somefile
|
||||
grep -q baz /tmp/somedir/somefile
|
||||
grep -q qux /tmp/someotherfile
|
||||
|
||||
systemd-tmpfiles --purge --dry-run - <<<"$c"
|
||||
test -f /tmp/somedir/somefile
|
||||
grep -q baz /tmp/somedir/somefile
|
||||
grep -q qux /tmp/someotherfile
|
||||
|
||||
systemd-tmpfiles --purge - <<<"$c"
|
||||
test ! -f /tmp/somedir/somefile
|
||||
test ! -d /tmp/somedir/
|
||||
grep -q qux /tmp/someotherfile
|
||||
|
||||
systemd-tmpfiles --create --purge --dry-run - <<<"$c"
|
||||
test ! -f /tmp/somedir/somefile
|
||||
test ! -d /tmp/somedir/
|
||||
grep -q qux /tmp/someotherfile
|
||||
|
||||
systemd-tmpfiles --create --purge - <<<"$c"
|
||||
test -f /tmp/somedir/somefile
|
||||
grep -q baz /tmp/somedir/somefile
|
||||
grep -q qux /tmp/someotherfile
|
||||
|
||||
systemd-tmpfiles --purge - <<<"$c"
|
||||
test ! -f /tmp/somedir/somefile
|
||||
test ! -d /tmp/somedir/
|
||||
grep -q qux /tmp/someotherfile
|
||||
|
||||
rm /tmp/someotherfile
|
||||
|
|
|
@ -1325,9 +1325,12 @@ testcase_compression() {
|
|||
|
||||
# TODO: add btrfs once btrfs-progs v6.11 is available in distributions.
|
||||
for format in squashfs erofs; do
|
||||
if ! command -v "mkfs.$format" && ! command -v mksquashfs >/dev/null; then
|
||||
continue
|
||||
fi
|
||||
case "$format" in
|
||||
squashfs)
|
||||
command -v mksquashfs >/dev/null || continue ;;
|
||||
*)
|
||||
command -v "mkfs.$format" || continue ;;
|
||||
esac
|
||||
|
||||
[[ "$format" == "squashfs" ]] && compression=zstd
|
||||
[[ "$format" == "erofs" ]] && compression=lz4hc
|
||||
|
|
|
@ -8,5 +8,5 @@
|
|||
# See tmpfiles.d(5) for details
|
||||
|
||||
{% if LINK_SHELL_EXTRA_DROPIN %}
|
||||
L {{SHELLPROFILEDIR}}/70-systemd-shell-extra.sh - - - - {{LIBEXECDIR}}/profile.d/70-systemd-shell-extra.sh
|
||||
L$ {{SHELLPROFILEDIR}}/70-systemd-shell-extra.sh - - - - {{LIBEXECDIR}}/profile.d/70-systemd-shell-extra.sh
|
||||
{% endif %}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# See tmpfiles.d(5) for details
|
||||
|
||||
{% if LINK_SSH_PROXY_DROPIN %}
|
||||
L {{SSHCONFDIR}}/20-systemd-ssh-proxy.conf - - - - {{LIBEXECDIR}}/ssh_config.d/20-systemd-ssh-proxy.conf
|
||||
L$ {{SSHCONFDIR}}/20-systemd-ssh-proxy.conf - - - - {{LIBEXECDIR}}/ssh_config.d/20-systemd-ssh-proxy.conf
|
||||
{% endif %}
|
||||
{% if CREATE_SSHDPRIVSEPDIR %}
|
||||
d {{SSHDPRIVSEPDIR}} 0755
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
d /run/lock 0755 root root -
|
||||
L /var/lock - - - - ../run/lock
|
||||
{% if CREATE_LOG_DIRS %}
|
||||
L /var/log/README - - - - ../..{{DOC_DIR}}/README.logs
|
||||
L$ /var/log/README - - - - ../..{{DOC_DIR}}/README.logs
|
||||
{% endif %}
|
||||
|
||||
# /run/lock/subsys is used for serializing SysV service execution, and
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# See tmpfiles.d(5) for details
|
||||
|
||||
d /run/systemd/netif 0755 systemd-network systemd-network -
|
||||
d /run/systemd/netif/links 0755 systemd-network systemd-network -
|
||||
d /run/systemd/netif/leases 0755 systemd-network systemd-network -
|
||||
d /var/lib/systemd/network 0755 systemd-network systemd-network -
|
||||
d$ /run/systemd/netif 0755 systemd-network systemd-network -
|
||||
d$ /run/systemd/netif/links 0755 systemd-network systemd-network -
|
||||
d$ /run/systemd/netif/leases 0755 systemd-network systemd-network -
|
||||
d$ /var/lib/systemd/network 0755 systemd-network systemd-network -
|
||||
|
|
|
@ -19,5 +19,5 @@ Q /var/lib/machines 0700 - - -
|
|||
# systemd-nspawn --ephemeral places snapshots) we are more strict, to
|
||||
# avoid removing unrelated temporary files.
|
||||
|
||||
R! /var/lib/machines/.#*
|
||||
R! /.#machine.*
|
||||
R!$ /var/lib/machines/.#*
|
||||
R!$ /.#machine.*
|
||||
|
|
|
@ -14,10 +14,10 @@ x /var/tmp/systemd-private-%b-*
|
|||
X /var/tmp/systemd-private-%b-*/tmp
|
||||
|
||||
# Remove top-level private temporary directories on each boot
|
||||
R! /tmp/systemd-private-*
|
||||
R! /var/tmp/systemd-private-*
|
||||
R!$ /tmp/systemd-private-*
|
||||
R!$ /var/tmp/systemd-private-*
|
||||
|
||||
# Handle lost systemd-coredump temp files. They could be lost on old filesystems,
|
||||
# for example, after hard reboot.
|
||||
x /var/lib/systemd/coredump/.#core*.%b*
|
||||
r! /var/lib/systemd/coredump/.#*
|
||||
r!$ /var/lib/systemd/coredump/.#*
|
||||
|
|
|
@ -13,11 +13,11 @@ f+! /run/utmp 0664 root utmp -
|
|||
{% endif %}
|
||||
|
||||
d /run/systemd/ask-password 0755 root root -
|
||||
d /run/systemd/seats 0755 root root -
|
||||
d /run/systemd/sessions 0755 root root -
|
||||
d /run/systemd/users 0755 root root -
|
||||
d$ /run/systemd/seats 0755 root root -
|
||||
d$ /run/systemd/sessions 0755 root root -
|
||||
d$ /run/systemd/users 0755 root root -
|
||||
d /run/systemd/machines 0755 root root -
|
||||
d /run/systemd/shutdown 0755 root root -
|
||||
d$ /run/systemd/shutdown 0755 root root -
|
||||
|
||||
d /run/log 0755 root root -
|
||||
|
||||
|
|
Loading…
Reference in New Issue