1
0
mirror of https://github.com/systemd/systemd synced 2025-11-20 01:04:46 +01:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Thomas Mühlbacher
226e050a0d stub: check load options a little more carefully
This can lead to booting with a completely garbled command line with characters
being interpreted as miscellaneous CJK or symbols.

According to the UEFI spec, the optional data of the load option is just a
binary data buffer.
2025-10-20 10:28:41 +02:00
Nick Labich
942ad8503a sysext: Configure overlayfs mount options via envvar
Implements #39314
2025-10-20 09:59:02 +02:00
Yu Watanabe
5b09b43106
Don't tag i2c mice as pointing sticks (#39264)
There are no real i2c mice but there are i2c `FooBar Mouse` devices that
are an artifact of how the HID kernel drivers split up event nodes.
These nodes will be seen for some i2c keyboards and touchpads, depending
on the HID report descriptor.

Let's not tag those as pointing sticks.

Closes #36677
2025-10-20 15:04:27 +09:00
Yu Watanabe
b200f57bfa man: fix position of </para> tag
Follow-up for 65664bba4090816f7e1fe40ed743480c19d702ee.
2025-10-20 14:26:46 +09:00
Peter Hutterer
c4f072aaad hwdb: don't tag a named Mouse device as pointingstick
The generic kernel hid drivers split up devices based on the application
collection, appending a suffix for each collection (e.g. Touchpad,
Mouse, ...). Many i2c touchpads get a "... Mouse" event node which is
mislabelled as pointingstick by the input_id builtin, see commit
3d7ac1c655ec40f3829543072494dcdfb92dbc6b.

Closes: https://github.com/systemd/systemd/issues/36677
2025-10-20 14:14:39 +10:00
Peter Hutterer
5b647b84a9 rules: extend 60-input-id.rules to allow for bus/vid/pid/name matches
Same approach as used in 70-mouse.rules, allow for a name-based match
optionally combined with bus/vid/pid (which the existing modalias rule
would already allow us anyway). Note that ID_BUS isn't assigned until
after this rule has run so we need to use the id/bustype attribute
directly.

Related to https://github.com/systemd/systemd/issues/36677
2025-10-20 14:14:39 +10:00
Yu Watanabe
aeef3c313b man: fix typo
Follow-up for 938f7fea7c953e5f5e9e199a5fcd22ac84fd1240.
2025-10-20 11:25:46 +09:00
Marien Zwart
1599b6fbe2 docs: fix conversion / calculation errors
0x1770 is 6000, not 60000. It looks like 60000 is intended (the next
range starts at 60000 in both decimal and hex), so use that.

1000 to 60000 is 59001 users, as the range is inclusive on both sides.
Similar off-by-one for one of the "unused" ranges. After these changes,
the sizes of the ranges up to and including the "-1" ID sum up to 65536,
as expected.

I'm not sure where the size of the unused range after the container UID
range came from, but it is not correct (the "Container UID" and this
reserved range combined would be larger than the "HIC SVNT LEONES" 2^31
to 2^32-2 range...). Fix it.

It is unfortunate that the first half of this table makes more sense in
decimal while the second half makes more sense in hex (which would also
make the size in 65536 chunks easy to obtain): I'm tempted to add a
"sizes in hex" column...
2025-10-20 10:36:08 +09:00
10 changed files with 169 additions and 35 deletions

View File

@ -413,6 +413,14 @@ All tools:
variable. Similarly, `$SYSTEMD_CONFEXT_MUTABLE_MODE` works for confext images
and supports the systemd-confext multi-call functionality of sysext.
* `$SYSTEMD_SYSEXT_OVERLAYFS_MOUNT_OPTIONS` — this variable may be used to
override the overlayfs mount options applied for hierarchies managed by
`systemd-sysext`. Similarly, `$SYSTEMD_CONFEXT_OVERLAYFS_MOUNT_OPTIONS` works
for confext images and supports the systemd-confext multi-call functionality
of sysext. Read-only hierarchies have no mount options added by
default. Mutable hierarchies have the following mount options added by
default: `redirect_dir=on,noatime,metacopy=off,index=off`.
`systemd-tmpfiles`:
* `$SYSTEMD_TMPFILES_FORCE_SUBVOL` — if unset, `v`/`q`/`Q` lines will create

View File

@ -275,18 +275,18 @@ i.e. somewhere below `/var/` or similar.
| 1…4 | 0x00000001…0x00000004 | 4 | System users | Distributions | `/etc/passwd` |
| 5 | 0x00000005 | 1 | `tty` group | `systemd` | `/etc/passwd` |
| 6…999 | 0x00000006…0x000003E7 | 994 | System users | Distributions | `/etc/passwd` |
| 1000…60000 | 0x000003E8…0x00001770 | 59000 | Regular users | Distributions | `/etc/passwd` + LDAP/NIS/… |
| 1000…60000 | 0x000003E8…0x0000EA60 | 59001 | Regular users | Distributions | `/etc/passwd` + LDAP/NIS/… |
| 60001…60513 | 0x0000EA61…0x0000EC61 | 513 | Human users (homed) | `systemd` | `nss-systemd` |
| 60514…60577 | 0x0000EC62…0x0000ECA1 | 64 | Host users mapped into containers | `systemd` | `systemd-nspawn` |
| 60578…60705 | 0x0000ECA2…0x0000ED21 | 128 | Dynamic greeter users | `systemd` | `nss-systemd` |
| 60706…61183 | 0x0000ED22…0x0000EEFF | 478 | *unused* | | |
| 61184…65519 | 0x0000EF00…0x0000FFEF | 4336 | Dynamic service users | `systemd` | `nss-systemd` |
| 65520…65533 | 0x0000FFF0…0x0000FFFD | 13 | *unused* | | |
| 65520…65533 | 0x0000FFF0…0x0000FFFD | 14 | *unused* | | |
| 65534 | 0x0000FFFE | 1 | `nobody` user | Linux | `/etc/passwd` + `nss-systemd` |
| 65535 | 0x0000FFFF | 1 | 16-bit `(uid_t) -1` | Linux | |
| 65536…524287 | 0x00010000…0x0007FFFF | 458752 | *unused* | | |
| 524288…1879048191 | 0x00080000…0x6FFFFFFF | 1878523904 | Container UID ranges | `systemd` | `nss-systemd` |
| 1879048192…2147352575 | 0x70000000…0x7FFDFFFF | 1879048192 | *unused* | | |
| 1879048192…2147352575 | 0x70000000…0x7FFDFFFF | 268304384 | *unused* | | |
| 2147352576…2147418111 | 0x7FFE0000…0x7FFEFFFF | 65536 | Foreign UID range | `systemd` | `nss-systemd` |
| 2147418112…2147483647 | 0x7FFF0000…0x7FFFFFFF | 65536 | *unused* | | |
| 2147483648…4294967294 | 0x80000000…0xFFFFFFFE | 2147483647 | *HIC SVNT LEONES* | | |

View File

@ -5,6 +5,7 @@
#
# Match string formats:
# id-input:modalias:<modalias>
# id-input:<bus>:v<vid>p<pid>:name:<name>:*
#
# To add local entries, create a new file
# /etc/udev/hwdb.d/61-input-id-local.hwdb
@ -47,9 +48,20 @@
# id-input:modalias:input:b0003v1234pABCD*
# ID_INPUT_TOUCHPAD=1
# ID_INPUT=1
#
# id-input:usb:v12abp34cd:name:SomeVendor *:*
# ID_INPUT_TOUCHPAD=1
# ID_INPUT=1
#
# For technical reasons the hexadecimal vid/pid in the modalias match are
# uppercase but lowercase in the bus/vid/pid/name match.
# Sort by brand, model
# Any i2c device with a Mouse suffix in the name is not a pointing stick
id-input:i2c:*:name:*Mouse:
ID_INPUT_POINTINGSTICK=0
# Code Mercenaries Hard- und Software GmbH Virtual RC USB
id-input:modalias:input:b0003v07C0p1125*
ID_INPUT_MOUSE=

View File

@ -75,7 +75,7 @@ UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'),
'evdev': ('name', 'atkbd', 'input'),
'fb': ('pci', 'vmbus'),
'id-input': ('modalias'),
'id-input': ('modalias', 'bluetooth', 'i2c', 'usb'),
'touchpad': ('i8042', 'rmi', 'bluetooth', 'usb'),
'joystick': ('i8042', 'rmi', 'bluetooth', 'usb'),
'keyboard': ('name', ),

View File

@ -924,7 +924,7 @@
<para><citerefentry><refentrytitle>systemd-dissect</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<option>--shift</option> switch may be used to shift UID/GID ownership from or to the 0, foreign or
specific container UID/GID base outside of any <command>systemd-nspawn</command></para> invocation.
specific container UID/GID base outside of any <command>systemd-nspawn</command> invocation.</para>
<xi:include href="version-info.xml" xpointer="v230"/></listitem>
</varlistentry>

View File

@ -673,7 +673,7 @@
These variables are merged into the existing environment block of the manager process. In particular,
in case of the system manager, this block includes variables set by the kernel based on the kernel
command line, and in case of the user manager, the variables passed by the system manager. After
those variables have been merged, they will persist until overriden, even if the manager is reloaded
those variables have been merged, they will persist until overridden, even if the manager is reloaded
or reexecuted. In case of the user manager, these variables are also inherited by processes spawned
by the manager. As with <varname>DefaultEnvironment=</varname>, this environment block is internal,
and changes are not reflected in the manager's <filename>/proc/PID/environ</filename>.</para>

View File

@ -5,4 +5,15 @@ ACTION=="remove", GOTO="id_input_end"
SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
SUBSYSTEM=="input", IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=id-input:modalias:"
# id-input:<bus>:v<vid>p<pid>:name:<name>:*
KERNELS=="input*", ATTRS{id/bustype}=="0003", \
IMPORT{builtin}="hwdb 'id-input:usb:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
GOTO="id_input_end"
KERNELS=="input*", ATTRS{id/bustype}=="0005", \
IMPORT{builtin}="hwdb 'id-input:bluetooth:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
GOTO="id_input_end"
KERNELS=="input*", ATTRS{id/bustype}=="0018", \
IMPORT{builtin}="hwdb 'id-input:i2c:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
GOTO="id_input_end"
LABEL="id_input_end"

View File

@ -257,11 +257,21 @@ static void process_arguments(
EFI_SHELL_PARAMETERS_PROTOCOL *shell;
if (BS->HandleProtocol(stub_image, MAKE_GUID_PTR(EFI_SHELL_PARAMETERS_PROTOCOL), (void **) &shell) != EFI_SUCCESS) {
/* We also do a superficial check whether first character of passed command line
* is printable character (for compat with some Dell systems which fill in garbage?). */
if (loaded_image->LoadOptionsSize < sizeof(char16_t) || ((const char16_t *) loaded_image->LoadOptions)[0] <= 0x1F)
if (loaded_image->LoadOptionsSize < sizeof(char16_t))
goto nothing;
/* Superficial check to ensure the load options data looks like it might be a printable
* string. Some Dell and other systems fill in binary data in UEFI entries that are generated
* by the firmware. The UEFI specification allows this. See
* https://uefi.org/specs/UEFI/2.10/03_Boot_Manager.html#load-options */
for (size_t i = 0; i < loaded_image->LoadOptionsSize / sizeof(char16_t); i++) {
char16_t c = ((const char16_t *) loaded_image->LoadOptions)[i];
if (c == L'\0')
break;
if (c <= 0x1F)
goto nothing;
}
/* Not running from EFI shell, use entire LoadOptions. Note that LoadOptions is a void*, so
* it could actually be anything! */
char16_t *c = xstrndup16(loaded_image->LoadOptions, loaded_image->LoadOptionsSize / sizeof(char16_t));

View File

@ -92,12 +92,17 @@ static int arg_noexec = -1;
static ImagePolicy *arg_image_policy = NULL;
static bool arg_varlink = false;
static MutableMode arg_mutable = MUTABLE_NO;
static const char *arg_overlayfs_mount_options = NULL;
/* Is set to IMAGE_CONFEXT when systemd is called with the confext functionality instead of the default */
static ImageClass arg_image_class = IMAGE_SYSEXT;
#define MUTABLE_EXTENSIONS_BASE_DIR "/var/lib/extensions.mutable"
/* redirect_dir=on and noatime prevent unnecessary upcopies, metacopy=off prevents broken
* files from partial upcopies after umount, index=off allows reuse of the upper/work dirs */
#define MUTABLE_EXTENSIONS_MOUNT_OPTIONS "redirect_dir=on,noatime,metacopy=off,index=off"
STATIC_DESTRUCTOR_REGISTER(arg_hierarchies, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
@ -114,6 +119,7 @@ static const struct {
const char *scope_env;
const char *name_env;
const char *mode_env;
const char *opts_env;
const ImagePolicy *default_image_policy;
unsigned long default_mount_flags;
} image_class_info[_IMAGE_CLASS_MAX] = {
@ -127,6 +133,7 @@ static const struct {
.scope_env = "SYSEXT_SCOPE",
.name_env = "SYSTEMD_SYSEXT_HIERARCHIES",
.mode_env = "SYSTEMD_SYSEXT_MUTABLE_MODE",
.opts_env = "SYSTEMD_SYSEXT_OVERLAYFS_MOUNT_OPTIONS",
.default_image_policy = &image_policy_sysext,
.default_mount_flags = MS_RDONLY|MS_NODEV,
},
@ -140,6 +147,7 @@ static const struct {
.scope_env = "CONFEXT_SCOPE",
.name_env = "SYSTEMD_CONFEXT_HIERARCHIES",
.mode_env = "SYSTEMD_CONFEXT_MUTABLE_MODE",
.opts_env = "SYSTEMD_CONFEXT_OVERLAYFS_MOUNT_OPTIONS",
.default_image_policy = &image_policy_confext,
.default_mount_flags = MS_RDONLY|MS_NODEV|MS_NOSUID|MS_NOEXEC,
}
@ -733,7 +741,8 @@ static int mount_overlayfs(
const char *where,
char **layers,
const char *upper_dir,
const char *work_dir) {
const char *work_dir,
const char *mount_options) {
_cleanup_free_ char *options = NULL;
bool separator = false;
@ -769,12 +778,15 @@ static int mount_overlayfs(
r = append_overlayfs_path_option(&options, ",", "workdir", work_dir);
if (r < 0)
return r;
/* redirect_dir=on and noatime prevent unnecessary upcopies, metacopy=off prevents broken
* files from partial upcopies after umount, index=off allows reuse of the upper/work dirs */
if (!strextend(&options, ",redirect_dir=on,noatime,metacopy=off,index=off"))
return log_oom();
if (!mount_options)
mount_options = MUTABLE_EXTENSIONS_MOUNT_OPTIONS;
}
if (!isempty(mount_options) && !strextend(&options, ",", mount_options))
return log_oom();
/* Now mount the actual overlayfs */
r = mount_nofollow_verbose(LOG_ERR, image_class_info[image_class].short_identifier, where, "overlay", flags, options);
if (r < 0)
@ -1339,7 +1351,8 @@ static int mount_overlayfs_with_op(
ImageClass image_class,
int noexec,
const char *overlay_path,
const char *meta_path) {
const char *meta_path,
const char *mount_options) {
int r;
const char *top_layer = NULL;
@ -1389,7 +1402,7 @@ static int mount_overlayfs_with_op(
if (chmod(top_layer, op->hierarchy_mode) < 0)
return log_error_errno(errno, "Failed to set permissions of '%s' to %04o: %m", top_layer, op->hierarchy_mode);
r = mount_overlayfs(image_class, noexec, overlay_path, op->lower_dirs, op->upper_dir, op->work_dir);
r = mount_overlayfs(image_class, noexec, overlay_path, op->lower_dirs, op->upper_dir, op->work_dir, mount_options);
if (r < 0)
return r;
@ -1664,7 +1677,7 @@ static int merge_hierarchy(
if (r < 0)
return r;
r = mount_overlayfs_with_op(op, image_class, noexec, overlay_path, meta_path);
r = mount_overlayfs_with_op(op, image_class, noexec, overlay_path, meta_path, arg_overlayfs_mount_options);
if (r < 0)
return r;
@ -2606,6 +2619,34 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
static int parse_env(void) {
const char *env_var;
int r;
env_var = secure_getenv(image_class_info[arg_image_class].mode_env);
if (env_var) {
r = parse_mutable_mode(env_var);
if (r < 0)
log_warning("Failed to parse %s environment variable value '%s'. Ignoring.",
image_class_info[arg_image_class].mode_env, env_var);
else
arg_mutable = r;
}
env_var = secure_getenv(image_class_info[arg_image_class].opts_env);
if (env_var)
arg_overlayfs_mount_options = env_var;
/* For debugging purposes it might make sense to do this for other hierarchies than /usr/ and
* /opt/, but let's make that a hacker/debugging feature, i.e. env var instead of cmdline
* switch. */
r = parse_env_extension_hierarchies(&arg_hierarchies, image_class_info[arg_image_class].name_env);
if (r < 0)
return log_error_errno(r, "Failed to parse %s environment variable: %m", image_class_info[arg_image_class].name_env);
return 0;
}
static int sysext_main(int argc, char *argv[]) {
static const Verb verbs[] = {
@ -2622,23 +2663,16 @@ static int sysext_main(int argc, char *argv[]) {
}
static int run(int argc, char *argv[]) {
const char *env_var;
int r;
log_setup();
arg_image_class = invoked_as(argv, "systemd-confext") ? IMAGE_CONFEXT : IMAGE_SYSEXT;
/* Parse environment variable first */
env_var = getenv(image_class_info[arg_image_class].mode_env);
if (env_var) {
r = parse_mutable_mode(env_var);
if (r < 0)
log_warning("Failed to parse %s environment variable value '%s'. Ignoring.",
image_class_info[arg_image_class].mode_env, env_var);
else
arg_mutable = r;
}
/* Parse environment variables first */
r = parse_env();
if (r < 0)
return r;
/* Parse configuration file */
r = parse_config_file(arg_image_class);
@ -2650,13 +2684,6 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
/* For debugging purposes it might make sense to do this for other hierarchies than /usr/ and
* /opt/, but let's make that a hacker/debugging feature, i.e. env var instead of cmdline
* switch. */
r = parse_env_extension_hierarchies(&arg_hierarchies, image_class_info[arg_image_class].name_env);
if (r < 0)
return log_error_errno(r, "Failed to parse environment variable: %m");
if (arg_varlink) {
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;

View File

@ -287,6 +287,18 @@ extension_verify_after_unmerge() (
extension_verify "$root" "$hierarchy" "after unmerge" "$@"
)
extension_verify_mount_option() (
local target=${1:?}
local option=${2:?}
grep "^sysext" /proc/mounts | while read -r _ tgt _ opts _ _; do
if [[ "$target" == "$tgt" && ! "$opts" =~ .*"$option".* ]]; then
echo >&2 "Mount options ($opts) do not include expected option ($option)"
exit 1
fi
done
)
run_systemd_sysext() {
local root=${1:-}
shift
@ -331,6 +343,26 @@ extension_verify_after_unmerge "$fake_root" "$hierarchy" -h
)
( init_trap
: "No extension data in /var/lib/extensions.mutable/…, R/O hierarchy, mutability disabled by default, read-only merged, default, mount options"
fake_root=${roots_dir:+"$roots_dir/simple-read-only-with-read-only-hierarchy-options"}
hierarchy=/opt
prepare_root "$fake_root" "$hierarchy"
prepare_extension_image "$fake_root" "$hierarchy"
prepare_read_only_hierarchy "$fake_root" "$hierarchy"
SYSTEMD_SYSEXT_OVERLAYFS_MOUNT_OPTIONS="metacopy=off,noatime"\
run_systemd_sysext "$fake_root" merge
extension_verify_mount_option "$hierarchy" metacopy=off \
|| (! extension_verify_mount_option "$hierarchy" metacopy=on)
extension_verify_mount_option "$hierarchy" noatime
run_systemd_sysext "$fake_root" unmerge
)
( init_trap
: "No extension data in /var/lib/extensions.mutable/…, mutable hierarchy, mutability disabled by default, read-only merged"
fake_root=${roots_dir:+"$roots_dir/simple-read-only-with-mutable-hierarchy"}
@ -437,6 +469,40 @@ test ! -f "$fake_root$hierarchy/now-is-mutable"
)
( init_trap
: "Extension data in /var/lib/extensions.mutable/…, R/O hierarchy, auto-mutability, mutable merged, mount options"
fake_root=${roots_dir:+"$roots_dir/simple-mutable-with-read-only-hierarchy-options"}
hierarchy=/opt
extension_data_dir="$fake_root/var/lib/extensions.mutable$hierarchy"
[[ "$FSTYPE" == "fuseblk" ]] && exit 0
prepare_root "$fake_root" "$hierarchy"
prepare_extension_image "$fake_root" "$hierarchy"
prepare_extension_mutable_dir "$extension_data_dir"
prepare_read_only_hierarchy "$fake_root" "$hierarchy"
run_systemd_sysext "$fake_root" --mutable=auto merge
extension_verify_mount_option "$fake_root$hierarchy" index=off \
|| (! extension_verify_mount_option "$fake_root$hierarchy" index=on)
extension_verify_mount_option "$fake_root$hierarchy" metacopy=off \
|| (! extension_verify_mount_option "$fake_root$hierarchy" metacopy=on)
extension_verify_mount_option "$fake_root$hierarchy" noatime
(! extension_verify_mount_option "$fake_root$hierarchy" redirect_dir=off)
SYSTEMD_SYSEXT_OVERLAYFS_MOUNT_OPTIONS="relatime,metacopy=on"\
run_systemd_sysext "$fake_root" --mutable=auto refresh
(! extension_verify_mount_option "$fake_root$hierarchy" metacopy=off) \
|| extension_verify_mount_option "$fake_root$hierarchy" metacopy=on
(! extension_verify_mount_option "$fake_root$hierarchy" noatime)
extension_verify_mount_option "$fake_root$hierarchy" relatime
run_systemd_sysext "$fake_root" unmerge
)
( init_trap
: "Extension data in /var/lib/extensions.mutable/…, missing hierarchy, auto-mutability, mutable merged"
fake_root=${roots_dir:+"$roots_dir/simple-mutable-with-missing-hierarchy"}