diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml index 50dd50b026..899e6b46df 100644 --- a/.github/workflows/mkosi.yml +++ b/.github/workflows/mkosi.yml @@ -49,7 +49,7 @@ jobs: steps: - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b - - uses: systemd/mkosi@93098e2406e12ea7f06f962d4808952b8a06d345 + - uses: systemd/mkosi@d13ff85610c6fb01a2fff0a8187729ebe4a05595 - name: Install run: sudo apt-get update && sudo apt-get install --no-install-recommends python3-pexpect python3-jinja2 diff --git a/man/homectl.xml b/man/homectl.xml index dacbd17b1e..6fd5340370 100644 --- a/man/homectl.xml +++ b/man/homectl.xml @@ -686,7 +686,7 @@ CIPHER MODE - BITS + BYTES TYPE ALGORITHM SECONDS @@ -696,7 +696,12 @@ Configures various cryptographic parameters for the LUKS2 storage mechanism. See cryptsetup8 - for details on the specific attributes. + for details on the specific attributes. + + Note that homectl uses bytes for key size, like + /proc/crypto, but cryptsetup8 + uses bits. diff --git a/man/journald.conf.xml b/man/journald.conf.xml index 4b0dd90cbb..0abed9cf7d 100644 --- a/man/journald.conf.xml +++ b/man/journald.conf.xml @@ -353,7 +353,7 @@ traditional syslog daemon, to the kernel log buffer (kmsg), to the system console, or sent as wall messages to all logged-in users. These options take boolean arguments. If forwarding to syslog is enabled but nothing reads messages from the socket, forwarding to syslog has no effect. By default, - only forwarding to wall is enabled. These settings may be overridden at boot time with the kernel + only forwarding to syslog and wall is enabled. These settings may be overridden at boot time with the kernel command line options systemd.journald.forward_to_syslog, systemd.journald.forward_to_kmsg, systemd.journald.forward_to_console, and @@ -426,7 +426,7 @@ systemd-journald collects generated audit records, it just controls whether it tells the kernel to generate them. This means if another tool turns on auditing even if systemd-journald left it off, it will still collect the generated - messages. Defaults to on. + messages. Defaults to off. diff --git a/man/loader.conf.xml b/man/loader.conf.xml index d5abb1c04e..509412ec9d 100644 --- a/man/loader.conf.xml +++ b/man/loader.conf.xml @@ -121,7 +121,7 @@ will be stored as an EFI variable in that case, overriding this option. - If set to menu-hidden or 0 no menu + If set to menu-hidden or 0 (the default) no menu is shown and the default entry will be booted immediately. The menu can be shown by pressing and holding a key before systemd-boot is launched. Setting this to menu-force disables the timeout while always showing the menu. @@ -211,7 +211,7 @@ beep - Beep n times when the n-th entry in the boot menu is shown (default disabled). + Takes a boolean argument. If timeout enabled beep every second, otherwise beep n times when n-th entry in boot menu is selected (default disabled). Currently, only x86 is supported, where it uses the PC speaker. diff --git a/man/rules/meson.build b/man/rules/meson.build index 55376c0ecc..4e912638ed 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -884,6 +884,7 @@ manpages = [ '8', ['systemd-fsck', 'systemd-fsck-root.service'], ''], + ['systemd-fsckd.service', '8', ['systemd-fsckd.socket', 'systemd-fsckd'], ''], ['systemd-fstab-generator', '8', [], ''], ['systemd-getty-generator', '8', [], ''], ['systemd-gpt-auto-generator', '8', [], 'HAVE_BLKID'], diff --git a/man/sd_bus_error-example.c b/man/sd_bus_error-example.c new file mode 100644 index 0000000000..abea13ca45 --- /dev/null +++ b/man/sd_bus_error-example.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: CC0-1.0 */ + +#include +#include +#include +#include + +int writer_with_negative_errno_return(int fd, sd_bus_error *error) { + const char *message = "Hello, World!\n"; + + ssize_t n = write(fd, message, strlen(message)); + if (n >= 0) + return n; /* On success, return the number of bytes written, possibly 0. */ + + /* On error, initialize the error structure, and also propagate the errno + * value that write(2) set for us. */ + return sd_bus_error_set_errnof(error, errno, "Failed to write to fd %i: %m", fd); +} diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml index 5697ce7323..f4d0fea2e6 100644 --- a/man/sd_bus_error.xml +++ b/man/sd_bus_error.xml @@ -246,10 +246,15 @@ values in e, if e has been set with an error value before. Otherwise, it will return immediately. If the strings in e were set using sd_bus_error_set_const(), they will be shared. Otherwise, they will be - copied. Returns a converted errno-like, negative error code or 0. - Before this call, dst must be unset, i.e. either freshly initialized with + copied. Before this call, dst must be unset, i.e. either freshly initialized with NULL or reset using sd_bus_error_free(). + sd_bus_error_copy() generally returns 0 or a negative + errno-like value based on the input parameter e: + 0 if it was unset and a negative integer if it was set to some error, similarly to + sd_bus_error_set(). It may however also return an error generated internally, for + example -ENOMEM if a memory allocation fails. + sd_bus_error_move() is similar to sd_bus_error_copy(), but will move any error information from e into dst, resetting the former. This function cannot fail, as no new memory is allocated. Note that if @@ -286,6 +291,18 @@ to NULL. The structure may be reused afterwards. + + Reference ownership + + sd_bus_error is not reference-counted. Users should destroy resources held + by it by calling sd_bus_error_free(). Usually, error structures are allocated on the + stack or passed in as function parameters, but they may also be allocated dynamically, in which case it + is the duty of the caller to free3 the memory + held by the structure itself after freeing its contents with + sd_bus_error_free(). + + Return Value @@ -297,7 +314,8 @@ sd_bus_error_set_errnofv(), return 0 when the specified error value is 0, and a negative errno-like value corresponding to the error parameter otherwise. If an error occurs internally, one of the negative - error values listed below will be returned. + error values listed below will be returned. This allows those functions to be conveniently used in a + return statement, see the example below. sd_bus_error_get_errno() returns false when e is @@ -305,7 +323,9 @@ e->name otherwise. sd_bus_error_copy() and sd_bus_error_move() return a - negative error value converted from the source error, and zero if the error has not been set. + negative error value converted from the source error, and zero if the error has not been set. This + allows those functions to be conveniently used in a return statement, see the + example below. sd_bus_error_is_set() returns a non-zero value when e and the @@ -316,32 +336,18 @@ sd_bus_error_has_names_sentinel() return a non-zero value when e is non-NULL and the name field is equal to one of the given names, zero otherwise. - - - - Reference ownership - sd_bus_error is not reference - counted. Users should destroy resources held by it by calling - sd_bus_error_free(). Usually, error structures - are allocated on the stack or passed in as function parameters, - but they may also be allocated dynamically, in which case it is - the duty of the caller to free3 - the memory held by the structure itself after freeing its contents - with sd_bus_error_free(). Errors - Returned errors may indicate the following problems: + Return value may indicate the following problems in the invocation of the function itself: - -EINVAL - Error was already set in sd_bus_error structure when one - the error-setting functions was called. + Error was already set in the sd_bus_error structure when + one the error-setting functions was called. @@ -350,9 +356,29 @@ Memory allocation failed. + + On success, sd_bus_error_set(), sd_bus_error_setf(), + sd_bus_error_set_const(), sd_bus_error_set_errno(), + sd_bus_error_set_errnof(), sd_bus_error_set_errnofv(), + sd_bus_error_copy(), and sd_bus_error_move() will return a + negative converted errno-style value, or 0 if the error + parameter is NULL or unset. D-Bus errors are converted to the integral + errno-style value, and the mapping mechanism is extensible, see the discussion + above. This effectively means that almost any negative errno-style value can be + returned. + + Examples + + + Using the negative return value to propagate an error + + + + + diff --git a/man/shutdown.xml b/man/shutdown.xml index b07736ee68..97f33e802a 100644 --- a/man/shutdown.xml +++ b/man/shutdown.xml @@ -18,7 +18,7 @@ shutdown - Halt, power-off or reboot the machine + Halt, power off or reboot the machine @@ -33,8 +33,7 @@ Description - shutdown may be used to halt, power-off - or reboot the machine. + shutdown may be used to halt, power off, or reboot the machine. The first argument may be a time string (which is usually now). Optionally, this may be followed by a @@ -81,47 +80,41 @@ - Power-off the machine (the - default). + Power the machine off (the default). - Reboot the - machine. + Reboot the machine. - Equivalent to , - unless is specified. + The same as , but does not override the action to take if + it is "halt". E.g. shutdown --reboot -h means "poweroff", but shutdown + --halt -h means "halt". - Do not halt, power-off, reboot, just write - wall message. + Do not halt, power off, or reboot, but just write the wall message. - Do not send wall - message before - halt, power-off, reboot. + Do not send wall message before halt, power off, or reboot. - Cancel a pending shutdown. This may be used - to cancel the effect of an invocation of - shutdown with a time argument that is not - +0 or + Cancel a pending shutdown. This may be used to cancel the effect of an invocation of + shutdown with a time argument that is not +0 or now. diff --git a/man/systemd-creds.xml b/man/systemd-creds.xml index 2ccbb223e8..d803b5c127 100644 --- a/man/systemd-creds.xml +++ b/man/systemd-creds.xml @@ -25,6 +25,8 @@ systemd-creds OPTIONS + COMMAND + ARGS diff --git a/man/systemd-fsckd.service.xml b/man/systemd-fsckd.service.xml new file mode 100644 index 0000000000..b7ad58d272 --- /dev/null +++ b/man/systemd-fsckd.service.xml @@ -0,0 +1,162 @@ + + + + + + + + systemd-fsckd.service + systemd + + + + Developer + Didier + Roche + didrocks@ubuntu.com + + + + + + systemd-fsckd.service + 8 + + + + systemd-fsckd.service + systemd-fsckd.socket + systemd-fsckd + File system check progress reporting + + + + systemd-fsckd.service + systemd-fsckd.socket + /usr/lib/systemd/systemd-fsckd + + + + Description + + systemd-fsckd.service is a service responsible + for receiving file system check progress, and communicating some + consolidated data to console and plymouth (if running). It also handles + possible check cancellations. + + systemd-fsckd receives messages about file + system check progress from fsck through an + UNIX domain socket. It can display the progress of the least advanced + fsck as well as the total number of devices being checked in parallel + to the console. It will also send progress messages to plymouth. + Both the raw data and translated messages are sent, so compiled + plymouth themes can use the raw data to display custom messages, and + scripted themes, not supporting i18n, can display the translated + versions. + + systemd-fsckd will instruct plymouth to grab + Control+C keypresses. When the key is pressed, running checks will be + terminated. It will also cancel any newly connected fsck instances for + the lifetime of systemd-fsckd. + + + + Protocol for communication with plymouth + + systemd-fsckd passes the + following messages to the theme: + + Progress update, sent as a plymouth update message: + fsckd:<num_devices>:<progress>:<string> + + + <num_devices> + the current number of devices + being checked (int) + + + <progress> + the current minimum percentage of + all devices being checking (float, from 0 to 100) + + + <string> + a translated message ready to be displayed + by the plymouth theme displaying the data above. It can be overridden + by themes supporting i18n. + + + + + Cancel message, sent as a traditional plymouth message: + fsckd-cancel-msg:<string> + + + <strings> + a translated string ready to be displayed + by the plymouth theme indicating that Control+C can be used to cancel + current checks. It can be overridden (matching only + fsckd-cancel-msg prefix) + by themes supporting i18n. + + + + + + + Options + + The following options are understood: + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure + code otherwise. Note that the daemon stays idle for + a while to accept new fsck + connections before exiting. + + + + See Also + + systemd1, + systemd-fsck8, + fsck8, + systemd-quotacheck.service8, + fsck.btrfs8, + fsck.cramfs8, + fsck.ext48, + fsck.fat8, + fsck.hfsplus8, + fsck.minix8, + fsck.ntfs8, + fsck.xfs8 + + + + diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml index da35a7d26b..c7c8b91e14 100644 --- a/man/systemd.automount.xml +++ b/man/systemd.automount.xml @@ -26,10 +26,9 @@ Description - A unit configuration file whose name ends in - .automount encodes information about a file - system automount point controlled and supervised by - systemd. + A unit configuration file whose name ends in .automount encodes information + about a file system automount point controlled and supervised by systemd. Automount units may be used to + implement on-demand mounting as well as parallelized mounting of file systems. This man page lists the configuration options specific to this unit type. See @@ -55,9 +54,6 @@ accesses /home/lennart the mount unit home-lennart.mount will be activated. - Automount units may be used to implement on-demand mounting - as well as parallelized mounting of file systems. - Note that automount units are separate from the mount itself, so you should not set After= or Requires= for mount dependencies here. For example, you should not set @@ -65,8 +61,11 @@ filesystems. Doing so may result in an ordering cycle. Note that automount support on Linux is privileged, automount units are hence only available in the - system service manager (and root's user service manager), but not in unprivileged user's service - manager. + system service manager (and root's user service manager), but not in unprivileged users' service + managers. + + Note that automount units should not be nested. (The establishment of the inner automount point + would unconditionally pin the outer mount point, defeating its purpose.) @@ -78,12 +77,12 @@ The following dependencies are implicitly added: - If an automount unit is beneath another mount unit in the - file system hierarchy, both a requirement and an ordering - dependency between both units are created automatically. + If an automount unit is beneath another mount unit in the file system hierarchy, a + requirement and ordering dependencies are created to the on the unit higher in the hierarchy. + - An implicit Before= dependency is created - between an automount unit and the mount unit it activates. + An implicit Before= dependency is created between an automount + unit and the mount unit it activates. @@ -161,6 +160,7 @@ creating these directories. Takes an access mode in octal notation. Defaults to 0755. + TimeoutIdleSec= Configures an idle timeout. Once the mount has been diff --git a/meson.build b/meson.build index 36cbfa4893..03208c0135 100644 --- a/meson.build +++ b/meson.build @@ -146,6 +146,7 @@ rootlibdir = get_option('rootlibdir') if rootlibdir == '' rootlibdir = rootprefixdir / libdir.split('/')[-1] endif +rootpkglibdir = rootlibdir / 'systemd' install_sysconfdir = get_option('install-sysconfdir') != 'false' install_sysconfdir_samples = get_option('install-sysconfdir') == 'true' @@ -1981,7 +1982,7 @@ if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1 tpm2, versiondep], link_depends : cryptsetup_token_sym, - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : libcryptsetup_plugins_dir) endif @@ -1999,7 +2000,7 @@ if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1 libfido2, versiondep], link_depends : cryptsetup_token_sym, - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : libcryptsetup_plugins_dir) endif @@ -2017,7 +2018,7 @@ if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1 libp11kit, versiondep], link_depends : cryptsetup_token_sym, - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : libcryptsetup_plugins_dir) endif @@ -2152,7 +2153,7 @@ exe = executable( libshared], dependencies : [versiondep, libseccomp], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) dbus_programs += exe @@ -2170,7 +2171,7 @@ public_programs += executable( libshared], dependencies : [versiondep, libseccomp], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : conf.get('ENABLE_ANALYZE')) executable( @@ -2184,7 +2185,7 @@ executable( liblz4, libselinux, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2195,7 +2196,7 @@ public_programs += executable( link_with : [libjournal_core, libshared], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -2209,7 +2210,7 @@ public_programs += executable( liblz4, libzstd, libdl], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -2218,7 +2219,7 @@ executable( 'src/getty-generator/getty-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2227,7 +2228,7 @@ executable( 'src/debug-generator/debug-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2236,7 +2237,7 @@ executable( 'src/run-generator/run-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2245,7 +2246,7 @@ exe = executable( 'src/fstab-generator/fstab-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2263,7 +2264,7 @@ if conf.get('ENABLE_ENVIRONMENT_D') == 1 'src/environment-d-generator/environment-d-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : userenvgeneratordir) @@ -2278,7 +2279,7 @@ if conf.get('ENABLE_HIBERNATE') == 1 'src/hibernate-resume/hibernate-resume-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2287,7 +2288,7 @@ if conf.get('ENABLE_HIBERNATE') == 1 'src/hibernate-resume/hibernate-resume.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2299,7 +2300,7 @@ if conf.get('HAVE_BLKID') == 1 include_directories : includes, link_with : [libshared], dependencies : libblkid, - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2308,7 +2309,7 @@ if conf.get('HAVE_BLKID') == 1 'src/dissect/dissect.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) endif @@ -2321,7 +2322,7 @@ if conf.get('ENABLE_RESOLVE') == 1 libbasic_gcrypt, libsystemd_resolve_core], dependencies : systemd_resolved_dependencies, - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2336,7 +2337,7 @@ if conf.get('ENABLE_RESOLVE') == 1 lib_openssl_or_gcrypt, libm, libidn], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) meson.add_install_script(meson_make_symlink, @@ -2357,7 +2358,7 @@ if conf.get('ENABLE_LOGIND') == 1 libshared], dependencies : [threads, libacl], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2370,7 +2371,7 @@ if conf.get('ENABLE_LOGIND') == 1 liblz4, libxz, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -2379,7 +2380,7 @@ if conf.get('ENABLE_LOGIND') == 1 'src/login/inhibit.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -2416,7 +2417,7 @@ if conf.get('ENABLE_LOGIND') == 1 user_runtime_dir_sources, include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2427,7 +2428,7 @@ if conf.get('HAVE_PAM') == 1 'src/user-sessions/user-sessions.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2445,7 +2446,7 @@ if conf.get('HAVE_BLKID') == 1 and conf.get('HAVE_GNU_EFI') == 1 include_directories : includes, link_with : [boot_link_with], dependencies : [libblkid], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -2454,7 +2455,7 @@ if conf.get('HAVE_BLKID') == 1 and conf.get('HAVE_GNU_EFI') == 1 include_directories : includes, link_with : [boot_link_with], dependencies : [libblkid], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2463,7 +2464,7 @@ if conf.get('HAVE_BLKID') == 1 and conf.get('HAVE_GNU_EFI') == 1 'src/boot/bless-boot-generator.c', include_directories : includes, link_with : [boot_link_with], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) endif @@ -2474,7 +2475,7 @@ executable( include_directories : includes, link_with : [libshared], dependencies : [libblkid], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2484,7 +2485,7 @@ public_programs += executable( include_directories : includes, link_with : [libshared], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) systemctl = executable( @@ -2498,7 +2499,7 @@ systemctl = executable( libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) public_programs += systemctl @@ -2510,7 +2511,7 @@ if conf.get('ENABLE_PORTABLED') == 1 include_directories : includes, link_with : [libshared], dependencies : [threads, libselinux], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2520,7 +2521,7 @@ if conf.get('ENABLE_PORTABLED') == 1 include_directories : includes, link_with : [libshared], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) endif @@ -2531,7 +2532,7 @@ if conf.get('ENABLE_SYSEXT') == 1 systemd_sysext_sources, include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) endif @@ -2543,7 +2544,7 @@ if conf.get('ENABLE_USERDB') == 1 include_directories : includes, link_with : [libshared], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2553,7 +2554,7 @@ if conf.get('ENABLE_USERDB') == 1 include_directories : includes, link_with : [libshared], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2563,9 +2564,8 @@ if conf.get('ENABLE_USERDB') == 1 include_directories : includes, link_with : [libshared], dependencies : [threads], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootbindir) + install_rpath : rootpkglibdir, + install : true) endif if conf.get('ENABLE_HOMED') == 1 @@ -2580,7 +2580,7 @@ if conf.get('ENABLE_HOMED') == 1 libopenssl, libfdisk, libp11kit], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2593,7 +2593,7 @@ if conf.get('ENABLE_HOMED') == 1 libcrypt, libopenssl, libm], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2607,9 +2607,8 @@ if conf.get('ENABLE_HOMED') == 1 libopenssl, libp11kit, libdl], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootbindir) + install_rpath : rootpkglibdir, + install : true) if conf.get('HAVE_PAM') == 1 version_script_arg = project_source_root / pam_systemd_home_sym @@ -2650,7 +2649,7 @@ if conf.get('ENABLE_BACKLIGHT') == 1 'src/backlight/backlight.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2661,7 +2660,7 @@ if conf.get('ENABLE_RFKILL') == 1 'src/rfkill/rfkill.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2671,7 +2670,7 @@ executable( 'src/system-update-generator/system-update-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2683,7 +2682,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 link_with : [libshared], dependencies : [libcryptsetup, libp11kit], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2692,7 +2691,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 'src/cryptsetup/cryptsetup-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2702,7 +2701,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 include_directories : includes, link_with : [libshared], dependencies : [libcryptsetup], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2711,7 +2710,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 'src/veritysetup/veritysetup-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2724,7 +2723,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 libdl, libopenssl, libp11kit], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) executable( @@ -2733,7 +2732,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 include_directories : includes, link_with : [libshared], dependencies : [libcryptsetup], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2742,7 +2741,7 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 ['src/integritysetup/integritysetup-generator.c', 'src/integritysetup/integrity-util.c'], include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) endif @@ -2753,7 +2752,7 @@ if conf.get('HAVE_SYSV_COMPAT') == 1 'src/sysv-generator/sysv-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) @@ -2769,7 +2768,7 @@ if conf.get('HAVE_SYSV_COMPAT') == 1 'src/rc-local-generator/rc-local-generator.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : systemgeneratordir) endif @@ -2780,7 +2779,7 @@ if conf.get('ENABLE_XDG_AUTOSTART') == 1 systemd_xdg_autostart_generator_sources, include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : usergeneratordir) @@ -2789,7 +2788,7 @@ if conf.get('ENABLE_XDG_AUTOSTART') == 1 'src/xdg-autostart-generator/xdg-autostart-condition.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2800,7 +2799,7 @@ if conf.get('ENABLE_HOSTNAMED') == 1 'src/hostname/hostnamed.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2809,7 +2808,7 @@ if conf.get('ENABLE_HOSTNAMED') == 1 'src/hostname/hostnamectl.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) endif @@ -2828,7 +2827,7 @@ if conf.get('ENABLE_LOCALED') == 1 include_directories : includes, link_with : [libshared], dependencies : deps, - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2837,7 +2836,7 @@ if conf.get('ENABLE_LOCALED') == 1 localectl_sources, include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) endif @@ -2847,7 +2846,7 @@ if conf.get('ENABLE_TIMEDATED') == 1 'src/timedate/timedated.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2857,7 +2856,7 @@ if conf.get('ENABLE_TIMEDATECTL') == 1 'timedatectl', 'src/timedate/timedatectl.c', include_directories : includes, - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, link_with : [libshared], dependencies : [libm], install : true) @@ -2871,7 +2870,7 @@ if conf.get('ENABLE_TIMESYNCD') == 1 link_with : [libtimesyncd_core], dependencies : [threads, libm], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2880,7 +2879,7 @@ if conf.get('ENABLE_TIMESYNCD') == 1 'src/timesync/wait-sync.c', include_directories : includes, link_with : [libtimesyncd_core], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -2892,7 +2891,7 @@ if conf.get('ENABLE_MACHINED') == 1 include_directories : includes, link_with : [libmachine_core, libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2905,7 +2904,7 @@ if conf.get('ENABLE_MACHINED') == 1 libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) endif @@ -2917,7 +2916,7 @@ if conf.get('ENABLE_IMPORTD') == 1 include_directories : includes, link_with : [libshared], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2933,7 +2932,7 @@ if conf.get('ENABLE_IMPORTD') == 1 libz, libbzip2, libxz], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2947,7 +2946,7 @@ if conf.get('ENABLE_IMPORTD') == 1 libz, libbzip2, libxz], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2957,7 +2956,7 @@ if conf.get('ENABLE_IMPORTD') == 1 include_directories : includes, link_with : [libshared, lib_import_common], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2971,7 +2970,7 @@ if conf.get('ENABLE_IMPORTD') == 1 libz, libbzip2, libxz], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -2991,7 +2990,7 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_LIBCURL') == 1 libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -3009,7 +3008,7 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1 libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3024,7 +3023,7 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1 libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -3041,7 +3040,7 @@ if conf.get('ENABLE_COREDUMP') == 1 libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3055,7 +3054,7 @@ if conf.get('ENABLE_COREDUMP') == 1 libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) endif @@ -3070,7 +3069,7 @@ if conf.get('ENABLE_PSTORE') == 1 libxz, liblz4, libzstd], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -3081,7 +3080,7 @@ if conf.get('ENABLE_OOMD') == 1 include_directories : includes, link_with : [libshared], dependencies : [], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3091,7 +3090,7 @@ if conf.get('ENABLE_OOMD') == 1 include_directories : includes, link_with : [libshared], dependencies : [], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) endif @@ -3101,7 +3100,7 @@ if conf.get('ENABLE_BINFMT') == 1 'src/binfmt/binfmt.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3123,7 +3122,7 @@ if conf.get('ENABLE_SYSUPDATE') == 1 libblkid, libfdisk, libopenssl], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) public_programs += exe @@ -3135,7 +3134,7 @@ if conf.get('ENABLE_VCONSOLE') == 1 'src/vconsole/vconsole-setup.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -3146,7 +3145,7 @@ if conf.get('ENABLE_RANDOMSEED') == 1 'src/random-seed/random-seed.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -3158,7 +3157,7 @@ if conf.get('ENABLE_FIRSTBOOT') == 1 include_directories : includes, link_with : [libshared], dependencies : [libcrypt], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) endif @@ -3168,7 +3167,7 @@ executable( 'src/remount-fs/remount-fs.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3177,7 +3176,7 @@ executable( 'src/machine-id-setup/machine-id-setup-main.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -3186,7 +3185,7 @@ executable( 'src/fsck/fsck.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3194,7 +3193,7 @@ executable('systemd-growfs', 'src/partition/growfs.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3203,7 +3202,16 @@ executable( 'src/partition/makefs.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, + install : true, + install_dir : rootlibexecdir) + +executable( + 'systemd-fsckd', + 'src/fsckd/fsckd.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3212,7 +3220,7 @@ executable( 'src/sleep/sleep.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3226,7 +3234,7 @@ public_programs += executable( 'src/sysctl/sysctl.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3235,7 +3243,7 @@ executable( 'src/ac-power/ac-power.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3244,7 +3252,7 @@ public_programs += executable( 'src/detect-virt/detect-virt.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -3252,7 +3260,7 @@ public_programs += executable( 'src/delta/delta.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -3260,7 +3268,7 @@ public_programs += executable( 'src/escape/escape.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -3269,7 +3277,7 @@ public_programs += executable( 'src/notify/notify.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -3280,7 +3288,7 @@ public_programs += executable( link_with : [libshared], dependencies : [threads, libopenssl], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -3289,7 +3297,7 @@ executable( 'src/volatile-root/volatile-root.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : conf.get('ENABLE_INITRD') == 1, install_dir : rootlibexecdir) @@ -3298,7 +3306,7 @@ executable( 'src/cgroups-agent/cgroups-agent.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3307,7 +3315,7 @@ systemd_id128 = executable( 'src/id128/id128.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += systemd_id128 @@ -3324,7 +3332,7 @@ public_programs += executable( 'src/path/path.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -3332,7 +3340,7 @@ public_programs += executable( 'src/ask-password/ask-password.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -3341,7 +3349,7 @@ executable( 'src/reply-password/reply-password.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3350,7 +3358,7 @@ public_programs += executable( 'src/tty-ask-password-agent/tty-ask-password-agent.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) @@ -3359,7 +3367,7 @@ public_programs += executable( 'src/cgls/cgls.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -3367,7 +3375,7 @@ public_programs += executable( 'src/cgtop/cgtop.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) executable( @@ -3375,7 +3383,7 @@ executable( 'src/initctl/initctl.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : (conf.get('HAVE_SYSV_COMPAT') == 1), install_dir : rootlibexecdir) @@ -3385,7 +3393,7 @@ public_programs += executable( include_directories : includes, link_with : [libshared], dependencies: [libmount], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) meson.add_install_script(meson_make_symlink, @@ -3396,7 +3404,7 @@ public_programs += executable( 'src/run/run.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -3405,7 +3413,7 @@ public_programs += executable( include_directories : includes, link_with : [libshared], dependencies : [versiondep], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) public_programs += executable( @@ -3414,7 +3422,7 @@ public_programs += executable( include_directories : includes, link_with : [libshared], dependencies : [versiondep], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) if enable_sysusers @@ -3423,7 +3431,7 @@ if enable_sysusers 'src/sysusers/sysusers.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) public_programs += exe @@ -3465,7 +3473,7 @@ if conf.get('ENABLE_TMPFILES') == 1 include_directories : includes, link_with : [libshared], dependencies : [libacl], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) public_programs += exe @@ -3527,7 +3535,7 @@ if conf.get('ENABLE_QUOTACHECK') == 1 'src/quotacheck/quotacheck.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) endif @@ -3538,7 +3546,7 @@ public_programs += executable( include_directories : includes, link_with : [libshared], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3567,7 +3575,7 @@ if conf.get('ENABLE_REPART') == 1 dependencies : [threads, libblkid, libfdisk], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) public_programs += exe @@ -3585,7 +3593,7 @@ executable( include_directories : includes, link_with : [libshared], dependencies : [libmount], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3594,7 +3602,7 @@ executable( 'src/update-done/update-done.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3604,7 +3612,7 @@ executable( include_directories : includes, link_with : [libshared], dependencies : [libaudit], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : (conf.get('ENABLE_UTMP') == 1), install_dir : rootlibexecdir) @@ -3615,7 +3623,7 @@ if conf.get('HAVE_KMOD') == 1 include_directories : includes, link_with : [libshared], dependencies : [libkmod], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3635,7 +3643,7 @@ public_programs += executable( libshared], dependencies : [libblkid, libseccomp], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true) if conf.get('ENABLE_NETWORKD') == 1 @@ -3647,7 +3655,7 @@ if conf.get('ENABLE_NETWORKD') == 1 libsystemd_network, networkd_link_with], dependencies : [threads], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3656,7 +3664,7 @@ if conf.get('ENABLE_NETWORKD') == 1 systemd_networkd_wait_online_sources, include_directories : includes, link_with : [networkd_link_with], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3666,7 +3674,7 @@ if conf.get('ENABLE_NETWORKD') == 1 include_directories : libsystemd_network_includes, link_with : [libsystemd_network, networkd_link_with], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootbindir) endif @@ -3676,7 +3684,7 @@ exe = executable( network_generator_sources, include_directories : includes, link_with : [networkd_link_with], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3693,7 +3701,7 @@ executable( 'src/sulogin-shell/sulogin-shell.c', include_directories : includes, link_with : [libshared], - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : true, install_dir : rootlibexecdir) @@ -3756,7 +3764,7 @@ foreach tuple : tests dependencies], c_args : defs, build_by_default : want_tests != 'false', - install_rpath : rootlibexecdir, + install_rpath : rootpkglibdir, install : install_tests, install_dir : testsdir / type, link_depends : runtest_env) diff --git a/meson_options.txt b/meson_options.txt index 26d1170c50..80ec0c259c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -436,17 +436,17 @@ option('efi-includedir', type : 'string', value : '/usr/include/efi', description : 'path to the EFI header directory') option('efi-tpm-pcr-compat', type : 'boolean', value : 'false', description : 'Measure kernel command line also into TPM PCR 8 (in addition to 12)') -option('sbat-distro', type : 'string', value : 'auto', +option('sbat-distro', type : 'string', value : 'endless', description : 'SBAT distribution ID, e.g. fedora, or auto for autodetection') option('sbat-distro-generation', type : 'integer', value : 1, description : 'SBAT distribution generation') -option('sbat-distro-summary', type : 'string', +option('sbat-distro-summary', type : 'string', value : 'Endless OS Foundation LLC', description : 'SBAT distribution summary, e.g. Fedora') -option('sbat-distro-pkgname', type : 'string', +option('sbat-distro-pkgname', type : 'string', value : 'systemd-boot', description : 'SBAT distribution package name, e.g. systemd') option('sbat-distro-version', type : 'string', description : 'SBAT distribution package version, e.g. 248-7.fc34') -option('sbat-distro-url', type : 'string', +option('sbat-distro-url', type : 'string', value : 'https://github.com/endlessm/systemd', description : 'SBAT distribution URL, e.g. https://src.fedoraproject.org/rpms/systemd') option('efi-color-normal', type : 'string', value : 'lightgray,black', description : 'general boot loader color in "foreground,background" form, see constants from eficon.h') diff --git a/po/POTFILES.in b/po/POTFILES.in index e045852443..131e4bc503 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -12,3 +12,4 @@ src/portable/org.freedesktop.portable1.policy src/resolve/org.freedesktop.resolve1.policy src/timedate/org.freedesktop.timedate1.policy src/core/dbus-unit.c +src/fsckd/fsckd.c diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in index 0394530479..2522b1de81 100644 --- a/rules.d/50-udev-default.rules.in +++ b/rules.d/50-udev-default.rules.in @@ -26,7 +26,7 @@ SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620" SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620" SUBSYSTEM=="tty", KERNEL=="3270/tty[0-9]*", GROUP="tty", MODE="0620" SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty" -KERNEL=="tty[A-Z]*[0-9]|ttymxc[0-9]*|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout" +KERNEL=="tty[A-Z]*[0-9]|ttymxc[0-9]*|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout", MODE="0666" SUBSYSTEM=="mem", KERNEL=="mem|kmem|port", GROUP="kmem", MODE="0640" diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules index de08428207..0725fd89e3 100644 --- a/rules.d/60-persistent-storage.rules +++ b/rules.d/60-persistent-storage.rules @@ -103,7 +103,7 @@ KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \ IMPORT{builtin}="blkid --hint=session_offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" # single-session CDs do not have ID_CDROM_MEDIA_SESSION_LAST_OFFSET -KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ +KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ IMPORT{builtin}="blkid --noraid" # probe filesystem metadata of disks diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 95bf177a6b..b03cc70e2e 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -357,20 +357,29 @@ int cg_kill( Set *s, cg_kill_log_func_t log_kill, void *userdata) { - int r; + + int r, ret; r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.procs"); if (r < 0 || sig != SIGKILL) return r; + ret = r; + /* Only in case of killing with SIGKILL and when using cgroupsv2, kill remaining threads manually as a workaround for kernel bug. It was fixed in 5.2-rc5 (c03cd7738a83), backported to 4.19.66 (4340d175b898) and 4.14.138 (feb6b123b7dd). */ r = cg_unified_controller(controller); - if (r <= 0) + if (r < 0) + return r; + if (r == 0) + return ret; + + r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads"); + if (r < 0) return r; - return cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads"); + return r > 0 || ret > 0; } int cg_kill_kernel_sigkill(const char *controller, const char *path) { diff --git a/src/basic/time-util.c b/src/basic/time-util.c index c309369406..6e3fbd1e88 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -1477,19 +1477,43 @@ int get_timezone(char **ret) { const char *e; char *z; int r; + bool use_utc_fallback = false; r = readlink_malloc("/etc/localtime", &t); - if (r == -ENOENT) { - /* If the symlink does not exist, assume "UTC", like glibc does */ - z = strdup("UTC"); + if (r < 0) { + if (r == -ENOENT) + use_utc_fallback = true; + else if (r != -EINVAL) + return r; /* returns EINVAL if not a symlink */ + + r = read_one_line_file("/etc/timezone", &t); + if (r < 0) { + if (r != -ENOENT) + log_warning_errno(r, "Failed to read /etc/timezone: %m"); + + if (use_utc_fallback) { + /* If the /etc/localtime symlink does not exist and we failed + * to read /etc/timezone, assume "UTC", like glibc does */ + z = strdup("UTC"); + if (!z) + return -ENOMEM; + + *ret = z; + return 0; + } + + return -EINVAL; + } + + if (!timezone_is_valid(t, LOG_DEBUG)) + return -EINVAL; + z = strdup(t); if (!z) return -ENOMEM; *ret = z; return 0; } - if (r < 0) - return r; /* returns EINVAL if not a symlink */ e = PATH_STARTSWITH_SET(t, "/usr/share/zoneinfo/", "../usr/share/zoneinfo/"); if (!e) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index b6bd1dfd65..2d7432bb02 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -1969,13 +1969,16 @@ static int verb_install(int argc, char *argv[], void *userdata) { (void) sync_everything(); - if (arg_touch_variables) - r = install_variables(arg_esp_path, - part, pstart, psize, uuid, - "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", - install); + if (!arg_touch_variables) + return 0; - return r; + r = install_variables(arg_esp_path, part, pstart, psize, uuid, + "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", + install); + if (r < 0) + return r; + + return 0; } static int verb_remove(int argc, char *argv[], void *userdata) { diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index fb08b99333..6b3c4bc8bc 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -1573,8 +1573,39 @@ static void config_entry_add_from_file( TAKE_PTR(entry); } +static CHAR16 *resolve_link(EFI_FILE *root_dir, CHAR16 *link, CHAR16 *file) { + EFI_STATUS err; + _cleanup_freepool_ CHAR8 *contents = NULL; + _cleanup_freepool_ CHAR16 *linkname = NULL; + _cleanup_freepool_ CHAR16 *target = NULL; + CHAR16 *out = NULL; + + linkname = AllocatePool(StrSize(link) + StrSize(L".sln")); + if (!linkname) + return NULL; + StrCpy(linkname, link); + StrCat(linkname, L".sln"); + + err = file_read(root_dir, linkname, 0, 0, &contents, NULL); + if (EFI_ERROR(err)) + return NULL; + + target = xstra_to_str(contents); + if (!target) + return NULL; + + out = AllocatePool(StrSize(target) + StrSize(file)); + if (!out) + return NULL; + StrCpy(out, target); + StrCat(out, file); + + return out; +} + static void config_load_defaults(Config *config, EFI_FILE *root_dir) { _cleanup_freepool_ CHAR8 *content = NULL; + _cleanup_freepool_ CHAR16 *link = NULL; UINTN value; EFI_STATUS err; @@ -1593,7 +1624,10 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { .timeout_sec_efivar = TIMEOUT_UNSET, }; - err = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content, NULL); + link = resolve_link(root_dir, L"\\loader", L"\\entries"); + if (!link) + link = L"\\loader\\entries"; + err = file_read(root_dir, link, 0, 0, &content, NULL); if (!EFI_ERROR(err)) config_defaults_load_from_file(config, content); @@ -1639,6 +1673,7 @@ static void config_load_entries( _cleanup_freepool_ EFI_FILE_INFO *f = NULL; UINTN f_size = 0; EFI_STATUS err; + _cleanup_freepool_ CHAR16 *link = NULL; assert(config); assert(device); @@ -1646,7 +1681,10 @@ static void config_load_entries( /* Adds Boot Loader Type #1 entries (i.e. /loader/entries/….conf) */ - err = open_directory(root_dir, L"\\loader\\entries", &entries_dir); + link = resolve_link(root_dir, L"\\loader", L"\\entries"); + if (!link) + link = L"\\loader\\entries"; + err = open_directory(root_dir, link, &entries_dir); if (EFI_ERROR(err)) return; diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 299a01b9be..5501ef70b7 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -215,7 +215,7 @@ endif if get_option('debug') and get_option('mode') == 'developer' efi_cflags += ['-ggdb', '-DEFI_DEBUG'] endif -if get_option('optimization') != '0' +if get_option('optimization') in ['1', '2', '3', 's', 'g'] efi_cflags += ['-O' + get_option('optimization')] endif if get_option('b_ndebug') == 'true' or ( @@ -260,6 +260,13 @@ efi_ldflags = [ '-z', 'nocombreloc', efi_crt0, ] + +possible_link_flags = [ + '-Wl,--no-warn-execstack', + '-Wl,--no-warn-rwx-segments', +] +efi_ldflags += cc.get_supported_link_arguments(possible_link_flags) + if efi_arch[1] in ['aarch64', 'arm', 'riscv64'] efi_ldflags += ['-shared'] # Aarch64, ARM32 and 64bit RISC-V don't have an EFI capable objcopy. diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 40f615b2b3..3f103396e3 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -17,6 +17,31 @@ /* magic string to find in the binary image */ _used_ _section_(".sdmagic") static const char magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####"; +/* Allowed kernel cmdline options */ +static CHAR16 *allowed_opts[] = { + L"ostree", + L"rw", + L"quiet", + L"splash", + L"plymouth.ignore-serial-consoles", + L"loglevel", + NULL +}; + +static BOOLEAN validate_option(CHAR16 *pos, UINTN len) +{ + UINTN optlen = 0, i; + + while (optlen < len && pos[optlen] != ' ' && pos[optlen] != '=') + optlen++; + + for (i = 0; i < ELEMENTSOF(allowed_opts); i++) + if (StrnCmp(pos, allowed_opts[i], optlen) == 0) + return TRUE; + + return FALSE; +} + static EFI_STATUS combine_initrd( EFI_PHYSICAL_ADDRESS initrd_base, UINTN initrd_size, const void *credential_initrd, UINTN credential_initrd_size, @@ -210,20 +235,42 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { cmdline_len = szs[SECTION_CMDLINE]; } - /* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */ - if ((!secure_boot_enabled() || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 && - *(CHAR16 *) loaded_image->LoadOptions > 0x1F) { - cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8); - cmdline = cmdline_owned = xallocate_pool(cmdline_len); - - for (UINTN i = 0; i < cmdline_len; i++) - cmdline[i] = ((CHAR16 *) loaded_image->LoadOptions)[i]; - - /* Let's measure the passed kernel command line into the TPM. Note that this possibly - * duplicates what we already did in the boot menu, if that was already used. However, since - * we want the boot menu to support an EFI binary, and want to this stub to be usable from - * any boot menu, let's measure things anyway. */ - (void) tpm_log_load_options(loaded_image->LoadOptions); + /* PAYG: combine options from both the image and the loader configuration */ + if (loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) { + CHAR8 *line; + CHAR16 *options; + UINTN max_len, options_len, options_left, i; + BOOLEAN secure = secure_boot_enabled(); + + options_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8); + options_left = options_len; + max_len = options_len + szs[0] + 1; + line = AllocatePool(max_len); + + /* Lose the terminating null byte */ + cmdline_len--; + for (i = 0; i < cmdline_len; i++) + line[i] = cmdline[i]; + + options = (CHAR16 *)loaded_image->LoadOptions; + for (i = 0; i < options_len; i++) { + BOOLEAN safe; + + /* If we're not secure booting, all options are ok */ + safe = !secure || validate_option(&options[i], options_left); + if (safe) + line[cmdline_len++] = ' '; + + while (i < options_len && options[i] != ' ') { + if (safe) + line[cmdline_len++] = options[i]; + i++; + options_left--; + } + } + /* Make sure we're terminated */ + line[cmdline_len++] = '\0'; + cmdline = line; } export_variables(loaded_image); diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index 258d09dd45..ce3b76c512 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -543,7 +543,7 @@ int bpf_firewall_compile(Unit *u) { return supported; if (supported == BPF_FIREWALL_UNSUPPORTED) return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), - "BPF firewalling not supported on this manager, proceeding without."); + "bpf-firewall: BPF firewalling not supported, proceeding without."); if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE) /* If BPF_F_ALLOW_MULTI is not supported we don't support any BPF magic on inner nodes (i.e. on slice * units), since that would mean leaf nodes couldn't do any BPF anymore at all. Under the assumption @@ -551,7 +551,7 @@ int bpf_firewall_compile(Unit *u) { * consistent with old systemd behaviour from before v238, where BPF wasn't supported in inner nodes at * all, either. */ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), - "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units."); + "bpf-firewall: BPF_F_ALLOW_MULTI is not supported, not doing BPF firewall on slice units."); /* If BPF_F_ALLOW_MULTI flag is supported program name is also supported (both were added to v4.15 * kernel). */ @@ -582,24 +582,24 @@ int bpf_firewall_compile(Unit *u) { r = bpf_firewall_prepare_access_maps(u, ACCESS_ALLOWED, &u->ipv4_allow_map_fd, &u->ipv6_allow_map_fd, &ip_allow_any); if (r < 0) - return log_unit_error_errno(u, r, "Preparation of eBPF allow maps failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF allow maps failed: %m"); r = bpf_firewall_prepare_access_maps(u, ACCESS_DENIED, &u->ipv4_deny_map_fd, &u->ipv6_deny_map_fd, &ip_deny_any); if (r < 0) - return log_unit_error_errno(u, r, "Preparation of eBPF deny maps failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF deny maps failed: %m"); } r = bpf_firewall_prepare_accounting_maps(u, cc->ip_accounting, &u->ip_accounting_ingress_map_fd, &u->ip_accounting_egress_map_fd); if (r < 0) - return log_unit_error_errno(u, r, "Preparation of eBPF accounting maps failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF accounting maps failed: %m"); r = bpf_firewall_compile_bpf(u, ingress_name, true, &u->ip_bpf_ingress, ip_allow_any, ip_deny_any); if (r < 0) - return log_unit_error_errno(u, r, "Compilation for ingress BPF program failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Compilation of ingress BPF program failed: %m"); r = bpf_firewall_compile_bpf(u, egress_name, false, &u->ip_bpf_egress, ip_allow_any, ip_deny_any); if (r < 0) - return log_unit_error_errno(u, r, "Compilation for egress BPF program failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Compilation of egress BPF program failed: %m"); return 0; } @@ -613,15 +613,15 @@ static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &prog); if (r < 0) - return log_unit_error_errno(u, r, "Can't allocate CGROUP SKB BPF program: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Allocation of SKB BPF program failed: %m"); r = bpf_program_load_from_bpf_fs(prog, *bpf_fs_path); if (r < 0) - return log_unit_error_errno(u, r, "Loading of ingress BPF program %s failed: %m", *bpf_fs_path); + return log_unit_error_errno(u, r, "bpf-firewall: Loading of ingress BPF program %s failed: %m", *bpf_fs_path); r = set_ensure_consume(set, &bpf_program_hash_ops, TAKE_PTR(prog)); if (r < 0) - return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m"); + return log_oom(); } return 0; @@ -645,7 +645,8 @@ int bpf_firewall_load_custom(Unit *u) { return supported; if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF_F_ALLOW_MULTI not supported, cannot attach custom BPF programs."); r = load_bpf_progs_from_fs_to_set(u, cc->ip_filters_ingress, &u->ip_bpf_custom_ingress); if (r < 0) @@ -671,7 +672,7 @@ static int attach_custom_bpf_progs(Unit *u, const char *path, int attach_type, S SET_FOREACH_MOVE(prog, *set_installed, *set) { r = bpf_program_cgroup_attach(prog, attach_type, path, BPF_F_ALLOW_MULTI); if (r < 0) - return log_unit_error_errno(u, r, "Attaching custom egress BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, "bpf-firewall: Attaching custom egress BPF program to cgroup %s failed: %m", path); } return 0; } @@ -697,16 +698,19 @@ int bpf_firewall_install(Unit *u) { if (supported < 0) return supported; if (supported == BPF_FIREWALL_UNSUPPORTED) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF firewalling not supported on this manager, proceeding without."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF firewalling not supported, proceeding without."); if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF_F_ALLOW_MULTI not supported, not doing BPF firewall on slice units."); if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && (!set_isempty(u->ip_bpf_custom_ingress) || !set_isempty(u->ip_bpf_custom_egress))) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF_F_ALLOW_MULTI not supported, cannot attach custom BPF programs."); r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Failed to determine cgroup path: %m"); flags = supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI ? BPF_F_ALLOW_MULTI : 0; @@ -728,7 +732,8 @@ int bpf_firewall_install(Unit *u) { if (u->ip_bpf_egress) { r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, flags); if (r < 0) - return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, + "bpf-firewall: Attaching egress BPF program to cgroup %s failed: %m", path); /* Remember that this BPF program is installed now. */ u->ip_bpf_egress_installed = TAKE_PTR(u->ip_bpf_egress); @@ -737,7 +742,8 @@ int bpf_firewall_install(Unit *u) { if (u->ip_bpf_ingress) { r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, flags); if (r < 0) - return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, + "bpf-firewall: Attaching ingress BPF program to cgroup %s failed: %m", path); u->ip_bpf_ingress_installed = TAKE_PTR(u->ip_bpf_ingress); } @@ -824,11 +830,11 @@ int bpf_firewall_supported(void) { r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); if (r < 0) - return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m"); + return log_error_errno(r, "bpf-firewall: Can't determine whether the unified hierarchy is used: %m"); if (r == 0) { bpf_firewall_unsupported_reason = log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), - "Not running with unified cgroups, BPF firewalling is not supported."); + "bpf-firewall: Not running with unified cgroup hierarchy, BPF firewalling is not supported."); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -836,21 +842,21 @@ int bpf_firewall_supported(void) { r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &program); if (r < 0) { bpf_firewall_unsupported_reason = - log_debug_errno(r, "Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + log_debug_errno(r, "bpf-firewall: Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } r = bpf_program_add_instructions(program, trivial, ELEMENTSOF(trivial)); if (r < 0) { bpf_firewall_unsupported_reason = - log_debug_errno(r, "Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + log_debug_errno(r, "bpf-firewall: Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } r = bpf_program_load_kernel(program, NULL, 0); if (r < 0) { bpf_firewall_unsupported_reason = - log_debug_errno(r, "Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + log_debug_errno(r, "bpf-firewall: Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -874,7 +880,7 @@ int bpf_firewall_supported(void) { if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0) { if (errno != EBADF) { bpf_firewall_unsupported_reason = - log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m"); + log_debug_errno(errno, "bpf-firewall: Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -882,7 +888,7 @@ int bpf_firewall_supported(void) { } else { bpf_firewall_unsupported_reason = log_debug_errno(SYNTHETIC_ERRNO(EBADE), - "Wut? Kernel accepted our invalid BPF_PROG_DETACH call? " + "bpf-firewall: Wut? Kernel accepted our invalid BPF_PROG_DETACH call? " "Something is weird, assuming BPF firewalling is broken and hence not supported."); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -902,20 +908,20 @@ int bpf_firewall_supported(void) { if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) { if (errno == EBADF) { - log_debug_errno(errno, "Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!"); + log_debug_errno(errno, "bpf-firewall: Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!"); return supported = BPF_FIREWALL_SUPPORTED_WITH_MULTI; } if (errno == EINVAL) - log_debug_errno(errno, "Got EINVAL error when using BPF_F_ALLOW_MULTI, which indicates it's not supported."); + log_debug_errno(errno, "bpf-firewall: Got EINVAL error when using BPF_F_ALLOW_MULTI, which indicates it's not supported."); else - log_debug_errno(errno, "Got unexpected error when using BPF_F_ALLOW_MULTI, assuming it's not supported: %m"); + log_debug_errno(errno, "bpf-firewall: Got unexpected error when using BPF_F_ALLOW_MULTI, assuming it's not supported: %m"); return supported = BPF_FIREWALL_SUPPORTED; } else { bpf_firewall_unsupported_reason = log_debug_errno(SYNTHETIC_ERRNO(EBADE), - "Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? " + "bpf-firewall: Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? " "Something is weird, assuming BPF firewalling is broken and hence not supported."); return supported = BPF_FIREWALL_UNSUPPORTED; } diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c index 7f50f57389..83c3bac87f 100644 --- a/src/core/bpf-foreign.c +++ b/src/core/bpf-foreign.c @@ -63,7 +63,7 @@ static int attach_programs(Unit *u, const char *path, Hashmap* foreign_by_key, u HASHMAP_FOREACH_KEY(prog, key, foreign_by_key) { r = bpf_program_cgroup_attach(prog, key->attach_type, path, attach_flags); if (r < 0) - return log_unit_error_errno(u, r, "Attaching foreign BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, "bpf-foreign: Attaching foreign BPF program to cgroup %s failed: %m", path); } return 0; @@ -89,31 +89,31 @@ static int bpf_foreign_prepare( r = path_is_fs_type(bpffs_path, BPF_FS_MAGIC); if (r < 0) return log_unit_error_errno(u, r, - "Failed to determine filesystem type of %s: %m", bpffs_path); + "bpf-foreign: Failed to determine filesystem type of %s: %m", bpffs_path); if (r == 0) return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL), - "Path in BPF filesystem is expected."); + "bpf-foreign: Path in BPF filesystem is expected."); r = bpf_program_new_from_bpffs_path(bpffs_path, &prog); if (r < 0) - return log_unit_error_errno(u, r, "Failed to create foreign BPFProgram: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to create foreign BPF program: %m"); r = bpf_program_get_id_by_fd(prog->kernel_fd, &prog_id); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get BPF program id by fd: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to get BPF program id from fd: %m"); r = bpf_foreign_key_new(prog_id, attach_type, &key); if (r < 0) return log_unit_error_errno(u, r, - "Failed to create foreign BPF program key from path '%s': %m", bpffs_path); + "bpf-foreign: Failed to create foreign BPF program key from path '%s': %m", bpffs_path); r = hashmap_ensure_put(&u->bpf_foreign_by_key, &bpf_foreign_by_key_hash_ops, key, prog); if (r == -EEXIST) { - log_unit_warning_errno(u, r, "Foreign BPF program already exists, ignoring: %m"); + log_unit_warning_errno(u, r, "bpf-foreign: Foreign BPF program already exists, ignoring: %m"); return 0; } if (r < 0) - return log_unit_error_errno(u, r, "Failed to put foreign BPFProgram into map: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to put foreign BPF program into map: %m"); TAKE_PTR(key); TAKE_PTR(prog); @@ -134,17 +134,17 @@ int bpf_foreign_install(Unit *u) { r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get cgroup path: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to get cgroup path: %m"); LIST_FOREACH(programs, p, cc->bpf_foreign_programs) { r = bpf_foreign_prepare(u, p->attach_type, p->bpffs_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to prepare foreign BPF hashmap: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to prepare foreign BPF hashmap: %m"); } r = attach_programs(u, cgroup_path, u->bpf_foreign_by_key, BPF_F_ALLOW_MULTI); if (r < 0) - return log_unit_error_errno(u, r, "Failed to install foreign BPF programs: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to install foreign BPF programs: %m"); return 0; } diff --git a/src/core/bpf-lsm.c b/src/core/bpf-lsm.c index d3e92b98a6..f3b9339558 100644 --- a/src/core/bpf-lsm.c +++ b/src/core/bpf-lsm.c @@ -26,6 +26,7 @@ /* libbpf, clang and llc compile time dependencies are satisfied */ #include "bpf-dlopen.h" #include "bpf-link.h" +#include "bpf-util.h" #include "bpf/restrict_fs/restrict-fs-skel.h" #define CGROUP_HASH_SIZE_MAX 2048 @@ -61,29 +62,29 @@ static int prepare_restrict_fs_bpf(struct restrict_fs_bpf **ret_obj) { obj = restrict_fs_bpf__open(); if (!obj) - return log_error_errno(errno, "Failed to open BPF object: %m"); + return log_error_errno(errno, "bpf-lsm: Failed to open BPF object: %m"); /* TODO Maybe choose a number based on runtime information? */ r = sym_bpf_map__resize(obj->maps.cgroup_hash, CGROUP_HASH_SIZE_MAX); assert(r <= 0); if (r < 0) - return log_error_errno(r, "Failed to resize BPF map '%s': %m", + return log_error_errno(r, "bpf-lsm: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.cgroup_hash)); /* Dummy map to satisfy the verifier */ inner_map_fd = sym_bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint32_t), 128, 0); if (inner_map_fd < 0) - return log_error_errno(errno, "Failed to create BPF map: %m"); + return log_error_errno(errno, "bpf-lsm: Failed to create BPF map: %m"); r = sym_bpf_map__set_inner_map_fd(obj->maps.cgroup_hash, inner_map_fd); assert(r <= 0); if (r < 0) - return log_error_errno(r, "Failed to set inner map fd: %m"); + return log_error_errno(r, "bpf-lsm: Failed to set inner map fd: %m"); r = restrict_fs_bpf__load(obj); assert(r <= 0); if (r < 0) - return log_error_errno(r, "Failed to load BPF object"); + return log_error_errno(r, "bpf-lsm: Failed to load BPF object: %m"); *ret_obj = TAKE_PTR(obj); @@ -103,7 +104,7 @@ static int mac_bpf_use(void) { r = read_one_line_file("/sys/kernel/security/lsm", &lsm_list); if (r < 0) { if (r != -ENOENT) - log_notice_errno(r, "Failed to read /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); + log_notice_errno(r, "bpf-lsm: Failed to read /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); return 0; } @@ -116,7 +117,7 @@ static int mac_bpf_use(void) { if (r == -ENOMEM) return log_oom(); if (r < 0) { - log_notice_errno(r, "Failed to parse /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); + log_notice_errno(r, "bpf-lsm: Failed to parse /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); return 0; } @@ -135,33 +136,18 @@ bool lsm_bpf_supported(bool initialize) { if (!initialize) return false; - r = dlopen_bpf(); - if (r < 0) { - log_info_errno(r, "Failed to open libbpf, LSM BPF is not supported: %m"); - return (supported = false); - } - - r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); - if (r < 0) { - log_warning_errno(r, "Can't determine whether the unified hierarchy is used: %m"); + if (!cgroup_bpf_supported()) return (supported = false); - } - - if (r == 0) { - log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Not running with unified cgroup hierarchy, LSM BPF is not supported"); - return (supported = false); - } r = mac_bpf_use(); if (r < 0) { - log_warning_errno(r, "Can't determine whether the BPF LSM module is used: %m"); + log_warning_errno(r, "bpf-lsm: Can't determine whether the BPF LSM module is used: %m"); return (supported = false); } if (r == 0) { log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "BPF LSM hook not enabled in the kernel, LSM BPF not supported"); + "bpf-lsm: BPF LSM hook not enabled in the kernel, BPF LSM not supported"); return (supported = false); } @@ -171,7 +157,7 @@ bool lsm_bpf_supported(bool initialize) { if (!bpf_can_link_lsm_program(obj->progs.restrict_filesystems)) { log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Failed to link BPF program. Assuming BPF is not available"); + "bpf-lsm: Failed to link program; assuming BPF LSM is not available"); return (supported = false); } @@ -192,10 +178,10 @@ int lsm_bpf_setup(Manager *m) { link = sym_bpf_program__attach_lsm(obj->progs.restrict_filesystems); r = sym_libbpf_get_error(link); if (r != 0) - return log_error_errno(r, "Failed to link '%s' LSM BPF program: %m", + return log_error_errno(r, "bpf-lsm: Failed to link '%s' LSM BPF program: %m", sym_bpf_program__name(obj->progs.restrict_filesystems)); - log_info("LSM BPF program attached"); + log_info("bpf-lsm: LSM BPF program attached"); obj->links.restrict_filesystems = TAKE_PTR(link); m->restrict_fs = TAKE_PTR(obj); @@ -214,7 +200,7 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo if (!u->manager->restrict_fs) return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL), - "Restrict filesystems BPF object is not set, BPF LSM setup has failed?"); + "bpf-lsm: BPF LSM object is not installed, has setup failed?"); int inner_map_fd = sym_bpf_create_map( BPF_MAP_TYPE_HASH, @@ -223,39 +209,39 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo 128, /* Should be enough for all filesystem types */ 0); if (inner_map_fd < 0) - return log_unit_error_errno(u, errno, "Failed to create inner LSM map: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Failed to create inner BPF map: %m"); int outer_map_fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash); if (outer_map_fd < 0) - return log_unit_error_errno(u, errno, "Failed to get BPF map fd: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m"); if (sym_bpf_map_update_elem(outer_map_fd, &u->cgroup_id, &inner_map_fd, BPF_ANY) != 0) - return log_unit_error_errno(u, errno, "Error populating LSM BPF map: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Error populating BPF map: %m"); uint32_t allow = allow_list; /* Use key 0 to store whether this is an allow list or a deny list */ if (sym_bpf_map_update_elem(inner_map_fd, &zero, &allow, BPF_ANY) != 0) - return log_unit_error_errno(u, errno, "Error initializing BPF map: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Error initializing map: %m"); SET_FOREACH(fs, filesystems) { r = fs_type_from_string(fs, &magic); if (r < 0) { - log_unit_warning(u, "Invalid filesystem name '%s', ignoring.", fs); + log_unit_warning(u, "bpf-lsm: Invalid filesystem name '%s', ignoring.", fs); continue; } - log_unit_debug(u, "Restricting filesystem access to '%s'", fs); + log_unit_debug(u, "bpf-lsm: Restricting filesystem access to '%s'", fs); for (int i = 0; i < FILESYSTEM_MAGIC_MAX; i++) { if (magic[i] == 0) break; if (sym_bpf_map_update_elem(inner_map_fd, &magic[i], &dummy_value, BPF_ANY) != 0) { - r = log_unit_error_errno(u, errno, "Failed to update BPF map: %m"); + r = log_unit_error_errno(u, errno, "bpf-lsm: Failed to update BPF map: %m"); if (sym_bpf_map_delete_elem(outer_map_fd, &u->cgroup_id) != 0) - log_unit_debug_errno(u, errno, "Failed to delete cgroup entry from LSM BPF map: %m"); + log_unit_debug_errno(u, errno, "bpf-lsm: Failed to delete cgroup entry from BPF map: %m"); return r; } @@ -278,10 +264,10 @@ int lsm_bpf_cleanup(const Unit *u) { int fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash); if (fd < 0) - return log_unit_error_errno(u, errno, "Failed to get BPF map fd: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m"); if (sym_bpf_map_delete_elem(fd, &u->cgroup_id) != 0) - return log_unit_debug_errno(u, errno, "Failed to delete cgroup entry from LSM BPF map: %m"); + return log_unit_debug_errno(u, errno, "bpf-lsm: Failed to delete cgroup entry from LSM BPF map: %m"); return 0; } @@ -305,11 +291,11 @@ bool lsm_bpf_supported(bool initialize) { } int lsm_bpf_setup(Manager *m) { - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set up LSM BPF: %m"); + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to set up LSM BPF: %m"); } int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, const bool allow_list) { - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to restrict filesystems using LSM BPF: %m"); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to restrict filesystems using LSM BPF: %m"); } int lsm_bpf_cleanup(const Unit *u) { @@ -344,7 +330,7 @@ int lsm_bpf_parse_filesystem( set = filesystem_set_find(name); if (!set) { log_syntax(unit, flags & FILESYSTEM_PARSE_LOG ? LOG_WARNING : LOG_DEBUG, filename, line, 0, - "Unknown filesystem group, ignoring: %s", name); + "bpf-lsm: Unknown filesystem group, ignoring: %s", name); return 0; } diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c index 09f83dc667..3aa1bfa1f1 100644 --- a/src/core/bpf-socket-bind.c +++ b/src/core/bpf-socket-bind.c @@ -11,8 +11,9 @@ /* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */ #include "bpf-dlopen.h" #include "bpf-link.h" -#include "bpf/socket_bind/socket-bind-skel.h" +#include "bpf-util.h" #include "bpf/socket_bind/socket-bind-api.bpf.h" +#include "bpf/socket_bind/socket-bind-skel.h" static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) { /* socket_bind_bpf__destroy handles object == NULL case */ @@ -68,27 +69,27 @@ static int prepare_socket_bind_bpf( if (allow_count > SOCKET_BIND_MAX_RULES) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL), - "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); + "bpf-socket-bind: Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); if (deny_count > SOCKET_BIND_MAX_RULES) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL), - "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); + "bpf-socket-bind: Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); obj = socket_bind_bpf__open(); if (!obj) - return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "Failed to open BPF object: %m"); + return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "bpf-socket-bind: Failed to open BPF object: %m"); if (sym_bpf_map__resize(obj->maps.sd_bind_allow, MAX(allow_count, 1u)) != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno, - "Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_allow)); + "bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_allow)); if (sym_bpf_map__resize(obj->maps.sd_bind_deny, MAX(deny_count, 1u)) != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno, - "Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_deny)); + "bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_deny)); if (socket_bind_bpf__load(obj) != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, - "Failed to load BPF object: %m"); + "bpf-socket-bind: Failed to load BPF object: %m"); allow_map_fd = sym_bpf_map__fd(obj->maps.sd_bind_allow); assert(allow_map_fd >= 0); @@ -96,7 +97,7 @@ static int prepare_socket_bind_bpf( r = update_rules_map(allow_map_fd, allow); if (r < 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r, - "Failed to put socket bind allow rules into BPF map '%s'", + "bpf-socket-bind: Failed to put socket bind allow rules into BPF map '%s'", sym_bpf_map__name(obj->maps.sd_bind_allow)); deny_map_fd = sym_bpf_map__fd(obj->maps.sd_bind_deny); @@ -105,7 +106,7 @@ static int prepare_socket_bind_bpf( r = update_rules_map(deny_map_fd, deny); if (r < 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r, - "Failed to put socket bind deny rules into BPF map '%s'", + "bpf-socket-bind: Failed to put socket bind deny rules into BPF map '%s'", sym_bpf_map__name(obj->maps.sd_bind_deny)); *ret_obj = TAKE_PTR(obj); @@ -116,25 +117,17 @@ int bpf_socket_bind_supported(void) { _cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL; int r; - r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); - if (r < 0) - return log_debug_errno(r, "Can't determine whether the unified hierarchy is used: %m"); - if (r == 0) { - log_debug("Not running with unified cgroup hierarchy, BPF is not supported"); - return false; - } - - if (dlopen_bpf() < 0) + if (!cgroup_bpf_supported()) return false; if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, /*ifindex=*/0)) { - log_debug("BPF program type cgroup_sock_addr is not supported"); + log_debug("bpf-socket-bind: BPF program type cgroup_sock_addr is not supported"); return false; } r = prepare_socket_bind_bpf(/*unit=*/NULL, /*allow_rules=*/NULL, /*deny_rules=*/NULL, &obj); if (r < 0) { - log_debug_errno(r, "BPF based socket_bind is not supported: %m"); + log_debug_errno(r, "bpf-socket-bind: socket bind filtering is not supported: %m"); return false; } @@ -154,7 +147,7 @@ int bpf_socket_bind_add_initial_link_fd(Unit *u, int fd) { r = fdset_put(u->initial_socket_bind_link_fds, fd); if (r < 0) - return log_unit_error_errno(u, r, "Failed to put socket-bind BPF link fd %d to initial fdset", fd); + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to put BPF fd %d to initial fdset", fd); return 0; } @@ -175,29 +168,29 @@ static int socket_bind_install_impl(Unit *u) { r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get cgroup path: %m"); + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to get cgroup path: %m"); if (!cc->socket_bind_allow && !cc->socket_bind_deny) return 0; r = prepare_socket_bind_bpf(u, cc->socket_bind_allow, cc->socket_bind_deny, &obj); if (r < 0) - return log_unit_error_errno(u, r, "Failed to load BPF object: %m"); + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to load BPF object: %m"); cgroup_fd = open(cgroup_path, O_RDONLY | O_CLOEXEC, 0); if (cgroup_fd < 0) - return log_unit_error_errno(u, errno, "Failed to open cgroup=%s for reading: %m", cgroup_path); + return log_unit_error_errno(u, errno, "bpf-socket-bind: Failed to open cgroup %s for reading: %m", cgroup_path); ipv4 = sym_bpf_program__attach_cgroup(obj->progs.sd_bind4, cgroup_fd); r = sym_libbpf_get_error(ipv4); if (r != 0) - return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program: %m", + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to link '%s' cgroup-bpf program: %m", sym_bpf_program__name(obj->progs.sd_bind4)); ipv6 = sym_bpf_program__attach_cgroup(obj->progs.sd_bind6, cgroup_fd); r = sym_libbpf_get_error(ipv6); if (r != 0) - return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program: %m", + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to link '%s' cgroup-bpf program: %m", sym_bpf_program__name(obj->progs.sd_bind6)); u->ipv4_socket_bind_link = TAKE_PTR(ipv4); @@ -241,7 +234,8 @@ int bpf_socket_bind_add_initial_link_fd(Unit *u, int fd) { } int bpf_socket_bind_install(Unit *u) { - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to install socket bind: BPF framework is not supported"); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-socket-bind: Failed to install; BPF framework is not supported"); } int bpf_serialize_socket_bind(Unit *u, FILE *f, FDSet *fds) { diff --git a/src/core/bpf-util.c b/src/core/bpf-util.c new file mode 100644 index 0000000000..9130aa373f --- /dev/null +++ b/src/core/bpf-util.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "bpf-dlopen.h" +#include "bpf-util.h" +#include "cgroup-util.h" +#include "log.h" + +bool cgroup_bpf_supported(void) { + static int supported = -1; + int r; + + if (supported >= 0) + return supported; + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) { + log_warning_errno(r, "Can't determine whether the unified hierarchy is used: %m"); + return (supported = false); + } + + if (r == 0) { + log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Not running with unified cgroup hierarchy, disabling cgroup BPF features."); + return (supported = false); + } + + r = dlopen_bpf(); + if (r < 0) { + log_info_errno(r, "Failed to open libbpf, cgroup BPF features disabled: %m"); + return (supported = false); + } + + return (supported = true); +} diff --git a/src/core/bpf-util.h b/src/core/bpf-util.h new file mode 100644 index 0000000000..a6c55cd7e5 --- /dev/null +++ b/src/core/bpf-util.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +bool cgroup_bpf_supported(void); diff --git a/src/core/device.c b/src/core/device.c index 4c261ec554..fcde8a420e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -201,12 +201,11 @@ static int device_coldplug(Unit *u) { * Of course, deserialized parameters may be outdated, but the unit state can be adjusted later by * device_catchup() or uevents. */ - if (!m->honor_device_enumeration && !MANAGER_IS_USER(m)) { + if (!m->honor_device_enumeration && !MANAGER_IS_USER(m) && + !FLAGS_SET(d->enumerated_found, DEVICE_FOUND_UDEV)) { found &= ~DEVICE_FOUND_UDEV; /* ignore DEVICE_FOUND_UDEV bit */ if (state == DEVICE_PLUGGED) state = DEVICE_TENTATIVE; /* downgrade state */ - if (found == DEVICE_NOT_FOUND) - state = DEVICE_DEAD; /* If nobody sees the device, downgrade more */ } if (d->found == found && d->state == state) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 3ff6eae8fc..09ba381762 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -522,6 +522,7 @@ static int patch_var_run( const char *e; char *z; + int log_level; e = path_startswith(*path, "/var/run/"); if (!e) @@ -531,7 +532,8 @@ static int patch_var_run( if (!z) return log_oom(); - log_syntax(unit, LOG_NOTICE, filename, line, 0, + log_level = path_startswith(filename, "/etc") ? LOG_NOTICE : LOG_DEBUG; + log_syntax(unit, log_level, filename, line, 0, "%s= references a path below legacy directory /var/run/, updating %s → %s; " "please update the unit file accordingly.", lvalue, *path, z); diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c index 716febbefa..9818602470 100644 --- a/src/core/locale-setup.c +++ b/src/core/locale-setup.c @@ -57,6 +57,27 @@ int locale_setup(char ***environment) { log_warning_errno(r, "Failed to read /etc/locale.conf: %m"); } + if (r <= 0) { + r = parse_env_file(NULL, "/etc/default/locale", + "LANG", &variables[VARIABLE_LANG], + "LANGUAGE", &variables[VARIABLE_LANGUAGE], + "LC_CTYPE", &variables[VARIABLE_LC_CTYPE], + "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], + "LC_TIME", &variables[VARIABLE_LC_TIME], + "LC_COLLATE", &variables[VARIABLE_LC_COLLATE], + "LC_MONETARY", &variables[VARIABLE_LC_MONETARY], + "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], + "LC_PAPER", &variables[VARIABLE_LC_PAPER], + "LC_NAME", &variables[VARIABLE_LC_NAME], + "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], + "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], + "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], + "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]); + + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read /etc/default/locale: %m"); + } + for (LocaleVariable i = 0; i < _VARIABLE_LC_MAX; i++) { char *s; diff --git a/src/core/main.c b/src/core/main.c index 409b84a006..7989bbe815 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1619,24 +1619,6 @@ static void cmdline_take_random_seed(void) { "This functionality should not be used outside of testing environments."); } -static void initialize_coredump(bool skip_setup) { -#if ENABLE_COREDUMP - if (getpid_cached() != 1) - return; - - /* Don't limit the core dump size, so that coredump handlers such as systemd-coredump (which honour - * the limit) will process core dumps for system services by default. */ - if (setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0) - log_warning_errno(errno, "Failed to set RLIMIT_CORE: %m"); - - /* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored - * until the systemd-coredump tool is enabled via sysctl. However it can be changed via the kernel - * command line later so core dumps can still be generated during early startup and in initramfs. */ - if (!skip_setup) - disable_coredumps(); -#endif -} - static void initialize_core_pattern(bool skip_setup) { int r; @@ -2765,8 +2747,6 @@ int main(int argc, char *argv[]) { kernel_timestamp = DUAL_TIMESTAMP_NULL; } - initialize_coredump(skip_setup); - r = fixup_environment(); if (r < 0) { log_emergency_errno(r, "Failed to fix up PID 1 environment: %m"); diff --git a/src/core/meson.build b/src/core/meson.build index 1e8b6dc310..162090a139 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -135,6 +135,13 @@ libcore_sources = ''' unit.h '''.split() +if conf.get('BPF_FRAMEWORK') == 1 + libcore_sources += files( + 'bpf-util.c', + 'bpf-util.h', + ) +endif + subdir('bpf') subdir('bpf/socket_bind') @@ -195,7 +202,7 @@ libcore = shared_library( libblkid, libacl], install : true, - install_dir : rootlibexecdir) + install_dir : rootpkglibdir) core_includes = [includes, include_directories('.')] diff --git a/src/core/restrict-ifaces.c b/src/core/restrict-ifaces.c index efa5c8d85a..a0ecaff814 100644 --- a/src/core/restrict-ifaces.c +++ b/src/core/restrict-ifaces.c @@ -9,7 +9,7 @@ #include "bpf-dlopen.h" #include "bpf-link.h" - +#include "bpf-util.h" #include "bpf/restrict_ifaces/restrict-ifaces-skel.h" static struct restrict_ifaces_bpf *restrict_ifaces_bpf_free(struct restrict_ifaces_bpf *obj) { @@ -34,19 +34,19 @@ static int prepare_restrict_ifaces_bpf( obj = restrict_ifaces_bpf__open(); if (!obj) - return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "Failed to open BPF object: %m"); + return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "restrict-interfaces: Failed to open BPF object: %m"); r = sym_bpf_map__resize(obj->maps.sd_restrictif, MAX(set_size(restrict_network_interfaces), 1u)); if (r != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r, - "Failed to resize BPF map '%s': %m", + "restrict-interfaces: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_restrictif)); obj->rodata->is_allow_list = is_allow_list; r = restrict_ifaces_bpf__load(obj); if (r != 0) - return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, r, "Failed to load BPF object: %m"); + return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, r, "restrict-interfaces: Failed to load BPF object: %m"); map_fd = sym_bpf_map__fd(obj->maps.sd_restrictif); @@ -56,13 +56,15 @@ static int prepare_restrict_ifaces_bpf( ifindex = rtnl_resolve_interface(&rtnl, iface); if (ifindex < 0) { - log_unit_warning_errno(u, ifindex, "Couldn't find index of network interface '%s', ignoring: %m", iface); + log_unit_warning_errno(u, ifindex, + "restrict-interfaces: Couldn't find index of network interface '%s', ignoring: %m", + iface); continue; } if (sym_bpf_map_update_elem(map_fd, &ifindex, &dummy, BPF_ANY)) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno, - "Failed to update BPF map '%s' fd: %m", + "restrict-interfaces: Failed to update BPF map '%s' fd: %m", sym_bpf_map__name(obj->maps.sd_restrictif)); } @@ -78,29 +80,21 @@ int restrict_network_interfaces_supported(void) { if (supported >= 0) return supported; - r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); - if (r < 0) - return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m"); - if (r == 0) { - log_debug("Not running with unified cgroup hierarchy, BPF is not supported"); - return supported = 0; - } - - if (dlopen_bpf() < 0) - return false; + if (!cgroup_bpf_supported()) + return (supported = false); if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*ifindex=*/0)) { - log_debug("BPF program type cgroup_skb is not supported"); - return supported = 0; + log_debug("restrict-interfaces: BPF program type cgroup_skb is not supported"); + return (supported = false); } r = prepare_restrict_ifaces_bpf(NULL, true, NULL, &obj); if (r < 0) { - log_debug_errno(r, "Failed to load BPF object: %m"); - return supported = 0; + log_debug_errno(r, "restrict-interfaces: Failed to load BPF object: %m"); + return (supported = false); } - return supported = bpf_can_link_program(obj->progs.sd_restrictif_i); + return (supported = bpf_can_link_program(obj->progs.sd_restrictif_i)); } static int restrict_network_interfaces_install_impl(Unit *u) { @@ -117,7 +111,7 @@ static int restrict_network_interfaces_install_impl(Unit *u) { r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get cgroup path: %m"); + return log_unit_error_errno(u, r, "restrict-interfaces: Failed to get cgroup path: %m"); if (!cc->restrict_network_interfaces) return 0; @@ -136,12 +130,12 @@ static int restrict_network_interfaces_install_impl(Unit *u) { ingress_link = sym_bpf_program__attach_cgroup(obj->progs.sd_restrictif_i, cgroup_fd); r = sym_libbpf_get_error(ingress_link); if (r != 0) - return log_unit_error_errno(u, r, "Failed to create ingress cgroup link: %m"); + return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create ingress cgroup link: %m"); egress_link = sym_bpf_program__attach_cgroup(obj->progs.sd_restrictif_e, cgroup_fd); r = sym_libbpf_get_error(egress_link); if (r != 0) - return log_unit_error_errno(u, r, "Failed to create egress cgroup link: %m"); + return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create egress cgroup link: %m"); u->restrict_ifaces_ingress_bpf_link = TAKE_PTR(ingress_link); u->restrict_ifaces_egress_bpf_link = TAKE_PTR(egress_link); @@ -180,7 +174,8 @@ int restrict_network_interfaces_add_initial_link_fd(Unit *u, int fd) { r = fdset_put(u->initial_restric_ifaces_link_fds, fd); if (r < 0) - return log_unit_error_errno(u, r, "Failed to put restrict-ifaces-bpf-fd %d to restored fdset: %m", fd); + return log_unit_error_errno(u, r, + "restrict-interfaces: Failed to put restrict-ifaces-bpf-fd %d to restored fdset: %m", fd); return 0; } @@ -192,7 +187,7 @@ int restrict_network_interfaces_supported(void) { int restrict_network_interfaces_install(Unit *u) { return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), - "Failed to install RestrictInterfaces: BPF programs built from source code are not supported: %m"); + "restrict-interfaces: Failed to install; BPF programs built from source code are not supported: %m"); } int serialize_restrict_network_interfaces(Unit *u, FILE *f, FDSet *fds) { diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in index fc0f8c34fa..65996bbed8 100644 --- a/src/core/systemd.pc.in +++ b/src/core/systemd.pc.in @@ -65,16 +65,16 @@ systemdshutdowndir=${systemd_shutdown_dir} tmpfiles_dir=${prefix}/lib/tmpfiles.d tmpfilesdir=${tmpfiles_dir} -sysusers_dir=${rootprefix}/lib/sysusers.d +sysusers_dir=${prefix}/lib/sysusers.d sysusersdir=${sysusers_dir} -sysctl_dir=${rootprefix}/lib/sysctl.d +sysctl_dir=${prefix}/lib/sysctl.d sysctldir=${sysctl_dir} -binfmt_dir=${rootprefix}/lib/binfmt.d +binfmt_dir=${prefix}/lib/binfmt.d binfmtdir=${binfmt_dir} -modules_load_dir=${rootprefix}/lib/modules-load.d +modules_load_dir=${prefix}/lib/modules-load.d modulesloaddir=${modules_load_dir} catalog_dir=${prefix}/lib/systemd/catalog diff --git a/src/core/unit.c b/src/core/unit.c index b0756bc6f4..90ec261558 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4606,16 +4606,7 @@ int unit_kill_context( } else if (r > 0) { - /* FIXME: For now, on the legacy hierarchy, we will not wait for the cgroup members to die if - * we are running in a container or if this is a delegation unit, simply because cgroup - * notification is unreliable in these cases. It doesn't work at all in containers, and outside - * of containers it can be confused easily by left-over directories in the cgroup — which - * however should not exist in non-delegated units. On the unified hierarchy that's different, - * there we get proper events. Hence rely on them. */ - - if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0 || - (detect_container() == 0 && !unit_cgroup_delegate(u))) - wait_for_exit = true; + wait_for_exit = true; if (send_sighup) { set_free(pid_set); diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 745d01ff50..7bf0e1196a 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -419,7 +419,7 @@ static int run(int argc, char *argv[]) { if (exit_status & FSCK_ERROR_CORRECTED) (void) touch("/run/systemd/quotacheck"); - return !!(exit_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED)); + return EXIT_SUCCESS; } DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c new file mode 100644 index 0000000000..8a85b692e7 --- /dev/null +++ b/src/fsckd/fsckd.c @@ -0,0 +1,697 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2015 Canonical + + Author: + Didier Roche + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" +#include "build.h" +#include "def.h" +#include "sd-event.h" +#include "log.h" +#include "list.h" +#include "macro.h" +#include "socket-netlink.h" +#include "socket-util.h" +#include "fd-util.h" +#include "string-util.h" +#include "io-util.h" +#include "util.h" +#include "alloc-util.h" +#include "locale-util.h" + +#define FSCKD_SOCKET_PATH "/run/systemd/fsck.progress" +#define IDLE_TIME_SECONDS 30 +#define PLYMOUTH_REQUEST_KEY "K\2\2\3" +#define CLIENTS_MAX 128 + +struct Manager; + +typedef struct Client { + struct Manager *manager; + char *device_name; + /* device id refers to "fd " until it gets a name as "device_name" */ + char *device_id; + + pid_t fsck_pid; + FILE *fsck_f; + + size_t cur; + size_t max; + int pass; + + double percent; + + bool cancelled; + bool bad_input; + + sd_event_source *event_source; + + LIST_FIELDS(struct Client, clients); +} Client; + +typedef struct Manager { + sd_event *event; + + LIST_HEAD(Client, clients); + unsigned n_clients; + + size_t clear; + + int connection_fd; + sd_event_source *connection_event_source; + + bool show_status_console; + + double percent; + int numdevices; + + int plymouth_fd; + sd_event_source *plymouth_event_source; + bool plymouth_cancel_sent; + + bool cancel_requested; +} Manager; + +static Client* client_free(Client *c); +static Manager* manager_free(Manager *m); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Client*, client_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + +static bool plymouth_running(void) { + return access("/run/plymouth/pid", F_OK) >= 0; +} + +static int manager_write_console(Manager *m, const char *message) { + _cleanup_fclose_ FILE *console = NULL; + int l; + size_t j; + + assert(m); + + if (!m->show_status_console) + return 0; + + /* Nothing to display, and nothing to clear: return now. */ + if (message == NULL && m->clear == 0) { + return 0; + } + + /* Reduce the SAK window by opening and closing console on every request */ + console = fopen("/dev/console", "we"); + if (!console) + return -errno; + + if (message) { + fprintf(console, "\r%s\r%n", message, &l); + if (m->clear < (size_t)l) + m->clear = (size_t)l; + } else { + fputc('\r', console); + for (j = 0; j < m->clear; j++) + fputc(' ', console); + fputc('\r', console); + } + fflush(console); + + return 0; +} + +static double compute_percent(int pass, size_t cur, size_t max) { + /* Values stolen from e2fsck */ + + static const double pass_table[] = { + 0, 70, 90, 92, 95, 100 + }; + + if (pass <= 0) + return 0.0; + + if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0) + return 100.0; + + return pass_table[pass-1] + + (pass_table[pass] - pass_table[pass-1]) * + (double) cur / max; +} + +static int client_request_cancel(Client *c) { + assert(c); + + if (c->cancelled) + return 0; + + log_info("Request to cancel fsck for %s from fsckd", c->device_id); + if (kill(c->fsck_pid, SIGTERM) < 0) { + /* ignore the error and consider that cancel was sent if fsck just exited */ + if (errno != ESRCH) + return log_error_errno(errno, "Cannot send cancel to fsck for %s: %m", c->device_id); + } + + c->cancelled = true; + return 1; +} + +static Client* client_free(Client *c) { + assert(c); + + if (c->manager) { + LIST_REMOVE(clients, c->manager->clients, c); + c->manager->n_clients--; + } + + sd_event_source_unref(c->event_source); + fclose(c->fsck_f); + if (c->device_name) + free(c->device_name); + if (c->device_id) + free(c->device_id); + return mfree(c); +} + +static void manager_disconnect_plymouth(Manager *m) { + assert(m); + + m->plymouth_event_source = sd_event_source_unref(m->plymouth_event_source); + m->plymouth_fd = safe_close(m->plymouth_fd); + m->plymouth_cancel_sent = false; +} + +static int manager_plymouth_feedback_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + char buffer[6]; + ssize_t l; + + assert(m); + + l = read(m->plymouth_fd, buffer, sizeof(buffer)); + if (l < 0) { + log_warning_errno(errno, "Got error while reading from plymouth: %m"); + manager_disconnect_plymouth(m); + return -errno; + } + if (l == 0) { + manager_disconnect_plymouth(m); + return 0; + } + + if (l > 1 && buffer[0] == '\15') + log_error("Message update to plymouth wasn't delivered successfully"); + + /* the only answer support type we requested is a key interruption */ + if (l > 2 && buffer[0] == '\2' && buffer[5] == '\3') { + m->cancel_requested = true; + + /* cancel all connected clients */ + LIST_FOREACH(clients, current, m->clients) + client_request_cancel(current); + } + + return 0; +} + +static int manager_connect_plymouth(Manager *m) { + union sockaddr_union sa = PLYMOUTH_SOCKET; + int r; + + if (!plymouth_running()) + return 0; + + /* try to connect or reconnect if sending a message */ + if (m->plymouth_fd >= 0) + return 1; + + m->plymouth_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + if (m->plymouth_fd < 0) + return log_warning_errno(errno, "Connection to plymouth socket failed: %m"); + + if (connect(m->plymouth_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) { + r = log_warning_errno(errno, "Couldn't connect to plymouth: %m"); + goto fail; + } + + r = sd_event_add_io(m->event, &m->plymouth_event_source, m->plymouth_fd, EPOLLIN, manager_plymouth_feedback_handler, m); + if (r < 0) { + log_warning_errno(r, "Can't listen to plymouth socket: %m"); + goto fail; + } + + return 1; + +fail: + manager_disconnect_plymouth(m); + return r; +} + +static int plymouth_send_message(int plymouth_fd, const char *message, bool update) { + _cleanup_free_ char *packet = NULL; + int n; + char mode = 'M'; + + if (update) + mode = 'U'; + + if (asprintf(&packet, "%c\002%c%s%n", mode, (int) (strlen(message) + 1), message, &n) < 0) + return log_oom(); + + return loop_write(plymouth_fd, packet, n + 1, true); +} + +static int manager_send_plymouth_message(Manager *m, const char *message) { + const char *plymouth_cancel_message = NULL, *l10n_cancel_message = NULL; + int r; + + r = manager_connect_plymouth(m); + if (r < 0) + return r; + /* 0 means that plymouth isn't running, do not send any message yet */ + else if (r == 0) + return 0; + + if (!m->plymouth_cancel_sent) { + + /* Indicate to plymouth that we listen to Ctrl+C */ + r = loop_write(m->plymouth_fd, PLYMOUTH_REQUEST_KEY, sizeof(PLYMOUTH_REQUEST_KEY), true); + if (r < 0) + return log_warning_errno(r, "Can't send to plymouth cancel key: %m"); + + m->plymouth_cancel_sent = true; + + l10n_cancel_message = _("Press Ctrl+C to cancel all filesystem checks in progress"); + plymouth_cancel_message = strjoina("fsckd-cancel-msg:", l10n_cancel_message); + + r = plymouth_send_message(m->plymouth_fd, plymouth_cancel_message, false); + if (r < 0) + log_warning_errno(r, "Can't send filesystem cancel message to plymouth: %m"); + + } else if (m->numdevices == 0) { + + m->plymouth_cancel_sent = false; + + r = plymouth_send_message(m->plymouth_fd, "", false); + if (r < 0) + log_warning_errno(r, "Can't clear plymouth filesystem cancel message: %m"); + } + + r = plymouth_send_message(m->plymouth_fd, message, true); + if (r < 0) + return log_warning_errno(r, "Couldn't send \"%s\" to plymouth: %m", message); + + return 0; +} + +static int manager_update_global_progress(Manager *m) { + _cleanup_free_ char *console_message = NULL; + _cleanup_free_ char *fsck_message = NULL; + int current_numdevices = 0, r; + double current_percent = 100; + + /* get the overall percentage */ + LIST_FOREACH(clients, current, m->clients) { + current_numdevices++; + + /* right now, we only keep the minimum % of all fsckd processes. We could in the future trying to be + linear, but max changes and corresponds to the pass. We have all the informations into fsckd + already if we can treat that in a smarter way. */ + current_percent = MIN(current_percent, current->percent); + } + + /* update if there is anything user-visible to update */ + if (fabs(current_percent - m->percent) > 0.001 || current_numdevices != m->numdevices) { + m->numdevices = current_numdevices; + m->percent = current_percent; + + if (asprintf(&console_message, + ngettext("Checking in progress on %d disk (%3.1f%% complete)", + "Checking in progress on %d disks (%3.1f%% complete)", m->numdevices), + m->numdevices, m->percent) < 0) + return -ENOMEM; + + if (asprintf(&fsck_message, "fsckd:%d:%3.1f:%s", m->numdevices, m->percent, console_message) < 0) + return -ENOMEM; + + r = manager_write_console(m, console_message); + if (r < 0) + return r; + + /* try to connect to plymouth and send message */ + r = manager_send_plymouth_message(m, fsck_message); + if (r < 0) + return r; + } + return 0; +} + +static int client_progress_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Client *client = userdata; + char line[LINE_MAX]; + Manager *m; + + assert(client); + m = client->manager; + + /* check first if we need to cancel this client */ + if (m->cancel_requested) + client_request_cancel(client); + + while (fgets(line, sizeof(line), client->fsck_f) != NULL) { + int pass; + size_t cur, max; + _cleanup_free_ char *device = NULL, *old_device_id = NULL; + + if (sscanf(line, "%i %zu %zu %ms", &pass, &cur, &max, &device) == 4) { + if (!client->device_name) { + client->device_name = strdup(device); + if (!client->device_name) { + log_oom(); + continue; + } + old_device_id = client->device_id; + client->device_id = strdup(device); + if (!client->device_id) { + log_oom(); + client->device_id = old_device_id; + old_device_id = NULL; + continue; + } + } + client->pass = pass; + client->cur = cur; + client->max = max; + client->bad_input = false; + client->percent = compute_percent(client->pass, client->cur, client->max); + log_debug("Getting progress for %s (%zu, %zu, %d) : %3.1f%%", client->device_id, + client->cur, client->max, client->pass, client->percent); + } else { + if (errno == ENOMEM) { + log_oom(); + continue; + } + + /* if previous input was already garbage, kick it off from progress report */ + if (client->bad_input) { + log_warning("Closing connection on incorrect input of fsck connection for %s", client->device_id); + client_free(client); + manager_update_global_progress(m); + return 0; + } + client->bad_input = true; + } + + } + + if (feof(client->fsck_f)) { + log_debug("Fsck client %s disconnected", client->device_id); + client_free(client); + } + + manager_update_global_progress(m); + return 0; +} + +static int manager_new_connection_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(client_freep) Client *c = NULL; + _cleanup_close_ int new_fsck_fd = -1; + _cleanup_fclose_ FILE *new_fsck_f = NULL; + struct ucred ucred = {}; + Manager *m = userdata; + int r; + + assert(m); + + /* Initialize and list new clients */ + new_fsck_fd = accept4(m->connection_fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); + if (new_fsck_fd < 0) { + log_error_errno(errno, "Couldn't accept a new connection: %m"); + return 0; + } + + if (m->n_clients >= CLIENTS_MAX) { + log_error("Too many clients, refusing connection."); + return 0; + } + + + new_fsck_f = fdopen(new_fsck_fd, "r"); + if (!new_fsck_f) { + log_error_errno(errno, "Couldn't fdopen new connection for fd %d: %m", new_fsck_fd); + return 0; + } + new_fsck_fd = -1; + + r = getpeercred(fileno(new_fsck_f), &ucred); + if (r < 0) { + log_error_errno(r, "Couldn't get credentials for fsck: %m"); + return 0; + } + + c = new0(Client, 1); + if (!c) { + log_oom(); + return 0; + } + + c->fsck_pid = ucred.pid; + c->fsck_f = new_fsck_f; + new_fsck_f = NULL; + + if (asprintf(&(c->device_id), "fd %d", fileno(c->fsck_f)) < 0) { + log_oom(); + return 0; + } + + r = sd_event_add_io(m->event, &c->event_source, fileno(c->fsck_f), EPOLLIN, client_progress_handler, c); + if (r < 0) { + log_oom(); + return 0; + } + + LIST_PREPEND(clients, m->clients, c); + m->n_clients++; + c->manager = m; + + log_debug("New fsck client connected: %s", c->device_id); + + /* only request the client to cancel now in case the request is dropped by the client (chance to recancel) */ + if (m->cancel_requested) + client_request_cancel(c); + + c = NULL; + return 0; +} + +static Manager* manager_free(Manager *m) { + if (!m) + return NULL; + + /* clear last line */ + manager_write_console(m, NULL); + + sd_event_source_unref(m->connection_event_source); + safe_close(m->connection_fd); + + while (m->clients) + client_free(m->clients); + + manager_disconnect_plymouth(m); + + sd_event_unref(m->event); + + return mfree(m); +} + +static int manager_new(Manager **ret, int fd) { + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + assert(ret); + + m = new0(Manager, 1); + if (!m) + return -ENOMEM; + + m->plymouth_fd = -1; + m->connection_fd = fd; + m->percent = 100; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + if (access("/run/systemd/show-status", F_OK) >= 0) + m->show_status_console = true; + + r = sd_event_add_io(m->event, &m->connection_event_source, fd, EPOLLIN, manager_new_connection_handler, m); + if (r < 0) + return r; + + *ret = m; + m = NULL; + + return 0; +} + +static int run_event_loop_with_timeout(Manager *m, usec_t timeout) { + int r, code; + sd_event *e = m->event; + + assert(e); + + for (;;) { + r = sd_event_get_state(e); + if (r < 0) + return r; + if (r == SD_EVENT_FINISHED) + break; + + r = sd_event_run(e, timeout); + if (r < 0) + return r; + + /* Exit if we reached the idle timeout and no more clients are + connected. If there is still an fsck process running but + simply slow to send us progress updates, exiting would mean + that this fsck process receives SIGPIPE resulting in an + aborted file system check. */ + if (r == 0 && m->n_clients == 0) { + sd_event_exit(e, 0); + break; + } + } + + r = sd_event_get_exit_code(e, &code); + if (r < 0) + return r; + + return code; +} + +static void help(void) { + printf("%s [OPTIONS...]\n\n" + "Capture fsck progress and forward one stream to plymouth\n\n" + " -h --help Show this help\n" + " --version Show package version\n", + program_invocation_short_name); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_ROOT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_VERSION: + version(); + return 0; + + case '?': + return -EINVAL; + + default: + assert_not_reached(); + } + + if (optind < argc) { + log_error("Extraneous arguments"); + return -EINVAL; + } + + return 1; +} + +int main(int argc, char *argv[]) { + _cleanup_(manager_freep) Manager *m = NULL; + int fd = -1; + int r, n; + + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + log_open(); + init_gettext(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + n = sd_listen_fds(0); + if (n > 1) { + log_error("Too many file descriptors received."); + r = -EINVAL; + goto finish; + } else if (n == 1) + fd = SD_LISTEN_FDS_START + 0; + else { + fd = make_socket_fd(LOG_DEBUG, FSCKD_SOCKET_PATH, SOCK_STREAM, SOCK_CLOEXEC); + if (fd < 0) { + r = log_error_errno(fd, "Couldn't create listening socket fd on %s: %m", FSCKD_SOCKET_PATH); + goto finish; + } + } + + r = manager_new(&m, fd); + if (r < 0) { + log_error_errno(r, "Failed to allocate manager: %m"); + goto finish; + } + + r = run_event_loop_with_timeout(m, IDLE_TIME_SECONDS * USEC_PER_SEC); + if (r < 0) { + log_error_errno(r, "Failed to run event loop: %m"); + goto finish; + } + + sd_event_get_exit_code(m->event, &r); + +finish: + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 75523d0c07..f010561611 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -358,6 +358,7 @@ static int add_mount( _cleanup_strv_free_ char **wanted_by = NULL, **required_by = NULL; _cleanup_fclose_ FILE *f = NULL; int r; + struct stat sb; assert(what); assert(where); @@ -440,9 +441,13 @@ static int add_mount( fprintf(f, "Before=%s\n", post); if (passno != 0) { - r = generator_write_fsck_deps(f, dest, what, where, fstype); - if (r < 0) - return r; + if (streq(where, "/usr") && stat("/run/initramfs/fsck-usr", &sb) == 0) + ; /* skip /usr fsck if it has already been checked in the initramfs */ + else { + r = generator_write_fsck_deps(f, dest, what, where, fstype); + if (r < 0) + return r; + } } r = generator_write_blockdev_dependency(f, what); @@ -802,6 +807,10 @@ static int add_sysroot_mount(void) { default_rw = false; /* read-only, unless overridden */ } + /* Enforce /sysroot mount as rw, so that we can generate machine- + * during first boot. */ + arg_root_rw = true; + if (!arg_root_options) opts = arg_root_rw > 0 || (arg_root_rw < 0 && default_rw) ? "rw" : "ro"; else if (arg_root_rw >= 0 || diff --git a/src/fundamental/bootspec-fundamental.c b/src/fundamental/bootspec-fundamental.c index 89e29f5982..c0138926a5 100644 --- a/src/fundamental/bootspec-fundamental.c +++ b/src/fundamental/bootspec-fundamental.c @@ -46,7 +46,7 @@ sd_bool bootspec_pick_name_version_sort_key( good_version = os_image_version ?: (os_version ?: (os_version_id ? : os_build_id)); good_sort_key = os_image_id ?: os_id; - if (!good_name || !good_version) + if (!good_name) return sd_false; if (ret_name) diff --git a/src/fundamental/sha256.c b/src/fundamental/sha256.c index 0577a24920..58b1a80d33 100644 --- a/src/fundamental/sha256.c +++ b/src/fundamental/sha256.c @@ -47,6 +47,20 @@ # define SWAP64(n) (n) #endif +/* The condition below is from glibc's string/string-inline.c. + * See definition of _STRING_INLINE_unaligned. */ +#if !defined(__mc68020__) && !defined(__s390__) && !defined(__i386__) + +/* To check alignment gcc has an appropriate operator. Other compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0) +# else +# define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0) +# endif +#else +# define UNALIGNED_P(p) sd_false +#endif + /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (FIPS 180-2:5.1.1) */ static const uint8_t fillbuf[64] = { @@ -94,10 +108,7 @@ void sha256_init_ctx(struct sha256_ctx *ctx) { } /* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ + prolog according to the standard and write the result to RESBUF. */ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) { /* Take yet unprocessed bytes into account. */ uint32_t bytes = ctx->buflen; @@ -122,7 +133,10 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) { /* Put result from CTX in first 32 bytes following RESBUF. */ for (size_t i = 0; i < 8; ++i) - ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]); + if (UNALIGNED_P(resbuf)) + memcpy((uint8_t*) resbuf + i * sizeof(uint32_t), (uint32_t[]) { SWAP(ctx->H[i]) }, sizeof(uint32_t)); + else + ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]); return resbuf; } @@ -156,17 +170,6 @@ void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx /* Process available complete blocks. */ if (len >= 64) { - -/* The condition below is from glibc's string/string-inline.c. - * See definition of _STRING_INLINE_unaligned. */ -#if !defined(__mc68020__) && !defined(__s390__) && !defined(__i386__) - -/* To check alignment gcc has an appropriate operator. Other compilers don't. */ -# if __GNUC__ >= 2 -# define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0) -# else -# define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0) -# endif if (UNALIGNED_P(buffer)) while (len > 64) { memcpy(ctx->buffer, buffer, 64); @@ -174,9 +177,7 @@ void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx buffer = (const char *) buffer + 64; len -= 64; } - else -#endif - { + else { sha256_process_block(buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 589a2cc582..2c1b899808 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -474,7 +474,7 @@ static const char *esp_or_xbootldr_options(const DissectedPartition *p) { * use kernel defaults. */ if (!p->fstype || streq(p->fstype, "vfat")) - return "umask=0077"; + return "umask=0022"; return NULL; } @@ -561,17 +561,16 @@ static int add_esp(DissectedPartition *p, bool has_xbootldr) { if (is_efi_boot()) { sd_id128_t loader_uuid; - /* If this is an EFI boot, be extra careful, and only mount the ESP if it was the ESP used for booting. */ + /* If this is an EFI boot and the bootloader has set LoaderDevicePartUUID, only mount the ESP + * if it was the ESP used for booting. */ r = efi_loader_get_device_part_uuid(&loader_uuid); - if (r == -ENOENT) { - log_debug("EFI loader partition unknown."); - return 0; - } - if (r < 0) + if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to read ESP partition UUID: %m"); - if (!sd_id128_equal(p->uuid, loader_uuid)) { + if (r == -ENOENT) + log_debug("EFI loader partition unknown, assuming %s was the booted ESP.", p->node); + else if (!sd_id128_equal(p->uuid, loader_uuid)) { log_debug("Partition for %s does not appear to be the partition we are booted from.", p->node); return 0; } diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c index 48e4b1414c..271e304273 100644 --- a/src/journal-remote/microhttpd-util.c +++ b/src/journal-remote/microhttpd-util.c @@ -298,7 +298,7 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn } #else -int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) { +_noreturn_ int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) { assert_not_reached(); } diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index dc9433701d..5d373f4821 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -2293,7 +2293,7 @@ int server_init(Server *s, const char *namespace) { .compress.threshold_bytes = UINT64_MAX, .seal = true, - .set_audit = true, + .set_audit = false, .watchdog_usec = USEC_INFINITY, @@ -2303,6 +2303,7 @@ int server_init(Server *s, const char *namespace) { .ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL, .ratelimit_burst = DEFAULT_RATE_LIMIT_BURST, + .forward_to_syslog = true, .forward_to_wall = true, .max_file_usec = DEFAULT_MAX_FILE_USEC, diff --git a/src/journal/journald.conf b/src/journal/journald.conf index 5a60a9d39c..269dc1b616 100644 --- a/src/journal/journald.conf +++ b/src/journal/journald.conf @@ -22,17 +22,17 @@ #SyncIntervalSec=5m #RateLimitIntervalSec=30s #RateLimitBurst=10000 -#SystemMaxUse= +SystemMaxUse=50M #SystemKeepFree= -#SystemMaxFileSize= +SystemMaxFileSize=1M #SystemMaxFiles=100 -#RuntimeMaxUse= +RuntimeMaxUse=4M #RuntimeKeepFree= #RuntimeMaxFileSize= #RuntimeMaxFiles=100 #MaxRetentionSec= #MaxFileSec=1month -#ForwardToSyslog=no +#ForwardToSyslog=yes #ForwardToKMsg=no #ForwardToConsole=no #ForwardToWall=yes @@ -44,4 +44,4 @@ #MaxLevelWall=emerg #LineMax=48K #ReadKMsg=yes -#Audit=yes +#Audit=no diff --git a/src/kernel-install/kernel-install.in b/src/kernel-install/kernel-install.in index f43c6b8b42..3da233ef6e 100755 --- a/src/kernel-install/kernel-install.in +++ b/src/kernel-install/kernel-install.in @@ -80,7 +80,10 @@ fi if [ "${0##*/}" = "installkernel" ]; then COMMAND=add - # make install doesn't pass any initrds + # kernel's install.sh invokes us as + # /sbin/installkernel + # We ignore the last two arguments. + set -- "$1" else COMMAND="$1" [ $# -ge 1 ] && shift @@ -112,6 +115,7 @@ fi if [ -n "$install_conf" ]; then [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Reading $install_conf…" + # shellcheck source=/dev/null . "$install_conf" # FIXME: This may override configuration in environment variables, e.g. $BOOT_ROOT. fi @@ -130,6 +134,7 @@ fi # generated one. If the user configured an explicit machine ID to use in # /etc/machine-info to use for our purpose, we'll use that instead (for # compatibility). +# shellcheck source=/dev/null if [ -z "$MACHINE_ID" ] && [ -r /etc/machine-info ] && . /etc/machine-info && MACHINE_ID="$KERNEL_INSTALL_MACHINE_ID"; then [ -n "$MACHINE_ID" ] && [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ echo "machine-id $MACHINE_ID acquired from /etc/machine-info" @@ -157,6 +162,7 @@ if [ -z "$ENTRY_TOKEN" ]; then # the IMAGE_ID= and ID= fields from /etc/os-release and finally the fixed # string "Default" ENTRY_TOKEN_SEARCH="$MACHINE_ID" + # shellcheck source=/dev/null [ -r /etc/os-release ] && . /etc/os-release [ -n "$IMAGE_ID" ] && ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH $IMAGE_ID" [ -n "$ID" ] && ENTRY_TOKEN_SEARCH="$ENTRY_TOKEN_SEARCH $ID" @@ -291,7 +297,7 @@ PLUGINS="$( IFS=" " -[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo -e "Plugin files:\n$PLUGINS" +[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && printf '%s\n' "Plugin files:" "$PLUGINS" case "$COMMAND" in add) @@ -318,8 +324,9 @@ case "$COMMAND" in fi for f in $PLUGINS; do - [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "+$f add $KERNEL_VERSION $ENTRY_DIR_ABS $*" + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "+$f add $KERNEL_VERSION $ENTRY_DIR_ABS" "$@" "$f" add "$KERNEL_VERSION" "$ENTRY_DIR_ABS" "$@" + err=$? [ $err -eq $skip_remaining ] && break ret=$(( ret + err )) @@ -351,8 +358,8 @@ case "$COMMAND" in # Assert that ENTRY_DIR_ABS actually matches what we are printing here [ "${ENTRY_DIR_ABS%/*}" = "$KERNEL_INSTALL_BOOT_ROOT/$ENTRY_TOKEN" ] || { echo "Assertion didn't pass." >&2; exit 1; } - ;; + *) echo "Error: unknown command '$COMMAND'" >&2 exit 1 diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index 8a03890d8b..c3eef87b84 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -222,7 +222,8 @@ tests += [ libglib, libgobject, libgio, - libdbus]], + libdbus, + libm]], [files('sd-bus/test-bus-signature.c'), [], diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index b77372c3a0..026ec101e3 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -428,7 +428,7 @@ int bus_message_from_header( _cleanup_free_ sd_bus_message *m = NULL; struct bus_header *h; - size_t a, label_sz; + size_t a, label_sz = 0; /* avoid false maybe-uninitialized warning */ assert(bus); assert(header || header_accessible <= 0); @@ -506,7 +506,10 @@ int bus_message_from_header( m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size); m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size); - if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size) + assert(message_size >= sizeof(struct bus_header)); + if (m->fields_size > message_size - sizeof(struct bus_header) || + ALIGN8(m->fields_size) > message_size - sizeof(struct bus_header) || + m->body_size != message_size - sizeof(struct bus_header) - ALIGN8(m->fields_size)) return -EBADMSG; } @@ -3061,15 +3064,21 @@ void bus_body_part_unmap(struct bus_body_part *part) { return; } -static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) { +static int buffer_peek(const void *p, size_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) { size_t k, start, end; assert(rindex); assert(align > 0); - start = ALIGN_TO((size_t) *rindex, align); - end = start + nbytes; + start = ALIGN_TO(*rindex, align); + if (start > sz) + return -EBADMSG; + + /* Avoid overflow below */ + if (nbytes > SIZE_MAX - start) + return -EBADMSG; + end = start + nbytes; if (end > sz) return -EBADMSG; @@ -3272,10 +3281,17 @@ static int message_peek_body( assert(rindex); assert(align > 0); - start = ALIGN_TO((size_t) *rindex, align); + start = ALIGN_TO(*rindex, align); + if (start > m->user_body_size) + return -EBADMSG; + padding = start - *rindex; - end = start + nbytes; + /* Avoid overflow below */ + if (nbytes > SIZE_MAX - start) + return -EBADMSG; + + end = start + nbytes; if (end > m->user_body_size) return -EBADMSG; diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h index 5ddc2211e6..62d27f7b89 100644 --- a/src/libsystemd/sd-hwdb/hwdb-internal.h +++ b/src/libsystemd/sd-hwdb/hwdb-internal.h @@ -2,6 +2,7 @@ #pragma once #include +#include #include "def.h" #include "hashmap.h" diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index 09c3401ca1..2d4b11721d 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -108,7 +108,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { assert_return(ret, -EINVAL); if (sd_id128_is_null(saved_machine_id)) { - r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id); + r = id128_read(getenv("SYSTEMD_MACHINE_ID_PATH") ?: "/etc/machine-id", ID128_PLAIN, &saved_machine_id); if (r < 0) return r; diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c index ac33e349c0..f0615ffb22 100644 --- a/src/libsystemd/sd-path/sd-path.c +++ b/src/libsystemd/sd-path/sd-path.c @@ -362,19 +362,19 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { return 0; case SD_PATH_SYSUSERS: - *ret = ROOTPREFIX_NOSLASH "/lib/sysusers.d"; + *ret = "/usr/lib/sysusers.d"; return 0; case SD_PATH_SYSCTL: - *ret = ROOTPREFIX_NOSLASH "/lib/sysctl.d"; + *ret = "/usr/lib/sysctl.d"; return 0; case SD_PATH_BINFMT: - *ret = ROOTPREFIX_NOSLASH "/lib/binfmt.d"; + *ret = "/usr/lib/binfmt.d"; return 0; case SD_PATH_MODULES_LOAD: - *ret = ROOTPREFIX_NOSLASH "/lib/modules-load.d"; + *ret = "/usr/lib/modules-load.d"; return 0; case SD_PATH_CATALOG: diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c index 9759f46163..4eb48bb0ff 100644 --- a/src/locale/keymap-util.c +++ b/src/locale/keymap-util.c @@ -91,6 +91,7 @@ void locale_simplify(char *locale[_VARIABLE_LC_MAX]) { int locale_read_data(Context *c, sd_bus_message *m) { struct stat st; int r; + const char *path = "/etc/locale.conf"; /* Do not try to re-read the file within single bus operation. */ if (m) { @@ -101,7 +102,11 @@ int locale_read_data(Context *c, sd_bus_message *m) { c->locale_cache = sd_bus_message_ref(m); } - r = stat("/etc/locale.conf", &st); + r = stat(path, &st); + if (r < 0 && errno == ENOENT) { + path = "/etc/default/locale"; + r = stat(path, &st); + } if (r < 0 && errno != ENOENT) return -errno; @@ -116,7 +121,7 @@ int locale_read_data(Context *c, sd_bus_message *m) { c->locale_mtime = t; context_free_locale(c); - r = parse_env_file(NULL, "/etc/locale.conf", + r = parse_env_file(NULL, path, "LANG", &c->locale[VARIABLE_LANG], "LANGUAGE", &c->locale[VARIABLE_LANGUAGE], "LC_CTYPE", &c->locale[VARIABLE_LC_CTYPE], @@ -190,8 +195,6 @@ int vconsole_read_data(Context *c, sd_bus_message *m) { } int x11_read_data(Context *c, sd_bus_message *m) { - _cleanup_fclose_ FILE *f = NULL; - bool in_section = false; struct stat st; usec_t t; int r; @@ -205,7 +208,7 @@ int x11_read_data(Context *c, sd_bus_message *m) { c->x11_cache = sd_bus_message_ref(m); } - if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) < 0) { + if (stat("/etc/default/keyboard", &st) < 0) { if (errno != ENOENT) return -errno; @@ -222,60 +225,14 @@ int x11_read_data(Context *c, sd_bus_message *m) { c->x11_mtime = t; context_free_x11(c); - f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re"); - if (!f) - return -errno; + r = parse_env_file(NULL, "/etc/default/keyboard", + "XKBMODEL", &c->x11_model, + "XKBLAYOUT", &c->x11_layout, + "XKBVARIANT", &c->x11_variant, + "XKBOPTIONS", &c->x11_options); - for (;;) { - _cleanup_free_ char *line = NULL; - char *l; - - r = read_line(f, LONG_LINE_MAX, &line); - if (r < 0) - return r; - if (r == 0) - break; - - l = strstrip(line); - if (IN_SET(l[0], 0, '#')) - continue; - - if (in_section && first_word(l, "Option")) { - _cleanup_strv_free_ char **a = NULL; - - r = strv_split_full(&a, l, WHITESPACE, EXTRACT_UNQUOTE); - if (r < 0) - return r; - - if (strv_length(a) == 3) { - char **p = NULL; - - if (streq(a[1], "XkbLayout")) - p = &c->x11_layout; - else if (streq(a[1], "XkbModel")) - p = &c->x11_model; - else if (streq(a[1], "XkbVariant")) - p = &c->x11_variant; - else if (streq(a[1], "XkbOptions")) - p = &c->x11_options; - - if (p) - free_and_replace(*p, a[2]); - } - - } else if (!in_section && first_word(l, "Section")) { - _cleanup_strv_free_ char **a = NULL; - - r = strv_split_full(&a, l, WHITESPACE, EXTRACT_UNQUOTE); - if (r < 0) - return -ENOMEM; - - if (strv_length(a) == 2 && streq(a[1], "InputClass")) - in_section = true; - - } else if (in_section && first_word(l, "EndSection")) - in_section = false; - } + if (r < 0) + return r; return 0; } @@ -284,9 +241,19 @@ int locale_write_data(Context *c, char ***settings) { _cleanup_strv_free_ char **l = NULL; struct stat st; int r; + const char *path = "/etc/locale.conf"; + /* Set values will be returned as strv in *settings on success. */ + r = load_env_file(NULL, path, &l); + if (r < 0 && r == -ENOENT) { + path = "/etc/default/locale"; + r = load_env_file(NULL, path, &l); + } + if (r < 0 && r != -ENOENT) + return r; + for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) if (!isempty(c->locale[p])) { r = strv_env_assign(&l, locale_variable_to_string(p), c->locale[p]); @@ -295,20 +262,20 @@ int locale_write_data(Context *c, char ***settings) { } if (strv_isempty(l)) { - if (unlink("/etc/locale.conf") < 0) + if (unlink(path) < 0) return errno == ENOENT ? 0 : -errno; c->locale_mtime = USEC_INFINITY; return 0; } - r = write_env_file_label("/etc/locale.conf", l); + r = write_env_file_label(path, l); if (r < 0) return r; *settings = TAKE_PTR(l); - if (stat("/etc/locale.conf", &st) >= 0) + if (stat(path, &st) >= 0) c->locale_mtime = timespec_load(&st.st_mtim); return 0; @@ -350,68 +317,92 @@ int vconsole_write_data(Context *c) { } int x11_write_data(Context *c) { - _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *temp_path = NULL; struct stat st; int r; + char *t, **l = NULL; - if (isempty(c->x11_layout) && - isempty(c->x11_model) && - isempty(c->x11_variant) && - isempty(c->x11_options)) { + r = load_env_file(NULL, "/etc/default/keyboard", &l); + if (r < 0 && r != -ENOENT) + return r; - if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) - return errno == ENOENT ? 0 : -errno; + /* This could perhaps be done more elegantly using an array + * like we do for the locale, instead of struct + */ + if (isempty(c->x11_layout)) { + l = strv_env_unset(l, "XKBLAYOUT"); + } else { + if (asprintf(&t, "XKBLAYOUT=%s", c->x11_layout) < 0) { + strv_free(l); + return -ENOMEM; + } - c->vc_mtime = USEC_INFINITY; - return 0; + r = strv_env_replace_consume(&l, t); + if (r < 0) { + strv_free(l); + return r; + } } - (void) mkdir_p_label("/etc/X11/xorg.conf.d", 0755); - r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path); - if (r < 0) - return r; - - (void) fchmod(fileno(f), 0644); + if (isempty(c->x11_model)) { + l = strv_env_unset(l, "XKBMODEL"); + } else { + if (asprintf(&t, "XKBMODEL=%s", c->x11_model) < 0) { + strv_free(l); + return -ENOMEM; + } - fputs("# Written by systemd-localed(8), read by systemd-localed and Xorg. It's\n" - "# probably wise not to edit this file manually. Use localectl(1) to\n" - "# instruct systemd-localed to update it.\n" - "Section \"InputClass\"\n" - " Identifier \"system-keyboard\"\n" - " MatchIsKeyboard \"on\"\n", f); + r = strv_env_replace_consume(&l, t); + if (r < 0) { + strv_free(l); + return r; + } + } - if (!isempty(c->x11_layout)) - fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout); + if (isempty(c->x11_variant)) { + l = strv_env_unset(l, "XKBVARIANT"); + } else { + if (asprintf(&t, "XKBVARIANT=%s", c->x11_variant) < 0) { + strv_free(l); + return -ENOMEM; + } - if (!isempty(c->x11_model)) - fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model); + r = strv_env_replace_consume(&l, t); + if (r < 0) { + strv_free(l); + return r; + } + } - if (!isempty(c->x11_variant)) - fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant); + if (isempty(c->x11_options)) { + l = strv_env_unset(l, "XKBOPTIONS"); + } else { + if (asprintf(&t, "XKBOPTIONS=%s", c->x11_options) < 0) { + strv_free(l); + return -ENOMEM; + } - if (!isempty(c->x11_options)) - fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options); + r = strv_env_replace_consume(&l, t); + if (r < 0) { + strv_free(l); + return r; + } + } - fputs("EndSection\n", f); + if (strv_isempty(l)) { + strv_free(l); - r = fflush_sync_and_check(f); - if (r < 0) - goto fail; + if (unlink("/etc/default/keyboard") < 0) + return errno == ENOENT ? 0 : -errno; - if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) { - r = -errno; - goto fail; + c->vc_mtime = USEC_INFINITY; + return 0; } - if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) >= 0) - c->x11_mtime = timespec_load(&st.st_mtim); + r = write_env_file("/etc/default/keyboard", l); + strv_free(l); - return 0; - -fail: - if (temp_path) - (void) unlink(temp_path); + if (r >= 0 && stat("/etc/default/keyboard", &st) >= 0) + c->x11_mtime = timespec_load(&st.st_mtim); return r; } diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index f7cff58005..c40d8defaf 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2342,8 +2342,6 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - reset_scheduled_shutdown(m); - if (m->enable_wall_messages) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_free_ char *username = NULL; @@ -2361,6 +2359,8 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd username, tty, logind_wall_tty_filter, m); } + reset_scheduled_shutdown(m); + return sd_bus_reply_method_return(message, "b", true); } diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c index 1db5050c3b..7d761a0d67 100644 --- a/src/login/logind-utmp.c +++ b/src/login/logind-utmp.c @@ -42,20 +42,28 @@ _const_ static usec_t when_wall(usec_t n, usec_t elapse) { return left % USEC_PER_HOUR; } -bool logind_wall_tty_filter(const char *tty, void *userdata) { - Manager *m = userdata; - const char *p; - - assert(m); +bool logind_wall_tty_filter(const char *tty, bool is_local, void *userdata) { + Manager *m = ASSERT_PTR(userdata); - if (!m->scheduled_shutdown_tty) - return true; + assert(m->scheduled_shutdown_action); - p = path_startswith(tty, "/dev/"); + const char *p = path_startswith(tty, "/dev/"); if (!p) return true; - return !streq(p, m->scheduled_shutdown_tty); + /* Do not send information about events which do not destroy local sessions to local terminals. We + * can assume that if the system enters sleep or hibernation, this will be visible in an obvious way + * for any local user. And once the systems exits sleep or hibernation, the notication would be just + * noise, in particular for auto-suspend. */ + if (is_local && + IN_SET(m->scheduled_shutdown_action->handle, + HANDLE_SUSPEND, + HANDLE_HIBERNATE, + HANDLE_HYBRID_SLEEP, + HANDLE_SUSPEND_THEN_HIBERNATE)) + return false; + + return !streq_ptr(p, m->scheduled_shutdown_tty); } static int warn_wall(Manager *m, usec_t n) { diff --git a/src/login/logind.h b/src/login/logind.h index 2136486c60..27f9e9729f 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -180,6 +180,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_n_autovts); CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size); int manager_setup_wall_message_timer(Manager *m); -bool logind_wall_tty_filter(const char *tty, void *userdata); +bool logind_wall_tty_filter(const char *tty, bool is_local, void *userdata); int manager_read_efi_boot_loader_entries(Manager *m); diff --git a/src/nspawn/nspawn-util.c b/src/nspawn/nspawn-util.c index 402554fa38..830ac39e73 100644 --- a/src/nspawn/nspawn-util.c +++ b/src/nspawn/nspawn-util.c @@ -20,9 +20,12 @@ int systemd_installation_has_version(const char *root, const char *minimal_versi /* /lib works for systems without usr-merge, and for systems with a sane * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary * for Gentoo which does a merge without making /lib a symlink. + * Also support multiarch paths von Debian/Ubuntu; *-linux-* is a small + * optimization based on the naming scheme of existing multiarch tuples. */ "/lib/systemd/libsystemd-shared-*.so", "/lib64/systemd/libsystemd-shared-*.so", + "/usr/lib/*-linux-*/systemd/libsystemd-shared-*.so", "/usr/lib/systemd/libsystemd-shared-*.so", "/usr/lib64/systemd/libsystemd-shared-*.so") { @@ -47,7 +50,7 @@ int systemd_installation_has_version(const char *root, const char *minimal_versi /* This is most likely to run only once, hence let's not optimize anything. */ char *t, *t2; - t = startswith(*name, path); + t = startswith(basename(*name), "libsystemd-shared-"); if (!t) continue; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 9e34161eb3..89d1f1cdfc 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -528,18 +528,26 @@ static int dns_stub_send( if (s) r = dns_stream_write_packet(s, reply); else { - int fd; + int fd, ifindex; fd = find_socket_fd(m, l, p->family, &p->sender, SOCK_DGRAM); if (fd < 0) return fd; + if (address_is_proxy(p->family, &p->destination)) + /* Force loopback iface if this is the loopback proxy stub + * and ifindex was normalized to 0 by manager_recv(). */ + ifindex = p->ifindex ?: LOOPBACK_IFINDEX; + else + /* Force loopback iface if this is the main listener stub. */ + ifindex = l ? p->ifindex : LOOPBACK_IFINDEX; + /* Note that it is essential here that we explicitly choose the source IP address for this * packet. This is because otherwise the kernel will choose it automatically based on the - * routing table and will thus pick 127.0.0.1 rather than 127.0.0.53. */ + * routing table and will thus pick 127.0.0.1 rather than 127.0.0.53/54. */ r = manager_send(m, fd, - l || address_is_proxy(p->family, &p->destination) ? p->ifindex : LOOPBACK_IFINDEX, /* force loopback iface if this is the main listener stub */ + ifindex, p->family, &p->sender, p->sender_port, &p->destination, reply); } diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index 6dacc1d20a..33c5bc2ce9 100644 --- a/src/shared/base-filesystem.c +++ b/src/shared/base-filesystem.c @@ -59,8 +59,7 @@ static const BaseFilesystem table[] = { /* No /lib64 on arm. The linker is /lib/ld-linux-armhf.so.3. */ # define KNOW_LIB64_DIRS 1 #elif defined(__i386__) || defined(__x86_64__) - { "lib64", 0, "usr/lib/"LIB_ARCH_TUPLE"\0" - "usr/lib64\0", "ld-linux-x86-64.so.2" }, + { "lib64", 0, "usr/lib64\0", "ld-linux-x86-64.so.2" }, # define KNOW_LIB64_DIRS 1 #elif defined(__ia64__) #elif defined(__loongarch64) diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 09eb36eb56..123db59575 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -530,9 +530,11 @@ static int boot_entry_load_unified( if (!tmp.sort_key) return log_oom(); - tmp.version = strdup(good_version); - if (!tmp.version) - return log_oom(); + if (good_version) { + tmp.version = strdup(good_version); + if (!tmp.version) + return log_oom(); + } *ret = tmp; tmp = (BootEntry) {}; diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c index 6f82002ff8..d8e778794c 100644 --- a/src/shared/bpf-dlopen.c +++ b/src/shared/bpf-dlopen.c @@ -9,7 +9,6 @@ static void *bpf_dl = NULL; struct bpf_link* (*sym_bpf_program__attach_cgroup)(struct bpf_program *, int); struct bpf_link* (*sym_bpf_program__attach_lsm)(struct bpf_program *); -long (*sym_libbpf_get_error)(const void *); int (*sym_bpf_link__fd)(const struct bpf_link *); int (*sym_bpf_link__destroy)(struct bpf_link *); int (*sym_bpf_map__fd)(const struct bpf_map *); @@ -26,9 +25,27 @@ void (*sym_bpf_object__detach_skeleton)(struct bpf_object_skeleton *); void (*sym_bpf_object__destroy_skeleton)(struct bpf_object_skeleton *); bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32); const char* (*sym_bpf_program__name)(const struct bpf_program *); +libbpf_print_fn_t (*sym_libbpf_set_print)(libbpf_print_fn_t); +long (*sym_libbpf_get_error)(const void *); + +_printf_(2,0) +static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_list ap) { +#if !LOG_TRACE + /* libbpf logs a lot of details at its debug level, which we don't need to see. */ + if (level == LIBBPF_DEBUG) + return 0; +#endif + /* All other levels are downgraded to LOG_DEBUG */ + + /* errno is used here, on the assumption that if the log message uses %m, errno will be set to + * something useful. Otherwise, it shouldn't matter, we may pass 0 or some bogus value. */ + return log_internalv(LOG_DEBUG, errno, NULL, 0, NULL, fmt, ap); +} int dlopen_bpf(void) { - return dlopen_many_sym_or_warn( + int r; + + r = dlopen_many_sym_or_warn( &bpf_dl, "libbpf.so.0", LOG_DEBUG, DLSYM_ARG(bpf_link__destroy), DLSYM_ARG(bpf_link__fd), @@ -48,7 +65,14 @@ int dlopen_bpf(void) { DLSYM_ARG(bpf_program__attach_cgroup), DLSYM_ARG(bpf_program__attach_lsm), DLSYM_ARG(bpf_program__name), + DLSYM_ARG(libbpf_set_print), DLSYM_ARG(libbpf_get_error)); + if (r < 0) + return r; + + /* We set the print helper unconditionally. Otherwise libbpf will emit not useful log messages. */ + (void) sym_libbpf_set_print(bpf_print_func); + return r; } #else diff --git a/src/shared/bpf-dlopen.h b/src/shared/bpf-dlopen.h index 713c41c3f4..f0d40325d9 100644 --- a/src/shared/bpf-dlopen.h +++ b/src/shared/bpf-dlopen.h @@ -8,7 +8,6 @@ extern struct bpf_link* (*sym_bpf_program__attach_cgroup)(struct bpf_program *, int); extern struct bpf_link* (*sym_bpf_program__attach_lsm)(struct bpf_program *); -extern long (*sym_libbpf_get_error)(const void *); extern int (*sym_bpf_link__fd)(const struct bpf_link *); extern int (*sym_bpf_link__destroy)(struct bpf_link *); extern int (*sym_bpf_map__fd)(const struct bpf_map *); @@ -27,6 +26,8 @@ extern void (*sym_bpf_object__detach_skeleton)(struct bpf_object_skeleton *); extern void (*sym_bpf_object__destroy_skeleton)(struct bpf_object_skeleton *); extern bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32); extern const char* (*sym_bpf_program__name)(const struct bpf_program *); +extern libbpf_print_fn_t (*sym_libbpf_set_print)(libbpf_print_fn_t); +extern long (*sym_libbpf_get_error)(const void *); #endif diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c index 75e639dd99..3b0c6d3fa9 100644 --- a/src/shared/find-esp.c +++ b/src/shared/find-esp.c @@ -571,7 +571,11 @@ static int verify_xbootldr_udev( r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v); if (r < 0) return log_error_errno(r, "Failed to get device property: %m"); - if (id128_equal_string(v, GPT_XBOOTLDR)) + + r = id128_equal_string(v, GPT_XBOOTLDR); + if (r < 0) + return log_error_errno(r, "Failed to parse ID_PART_ENTRY_TYPE=%s: %m", v); + if (r == 0) return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" has wrong type for extended boot loader partition.", node); diff --git a/src/shared/meson.build b/src/shared/meson.build index 1d4e4a07c0..e738180ed5 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -483,4 +483,7 @@ libshared = shared_library( libsystemd_static], dependencies : libshared_deps, install : true, - install_dir : rootlibexecdir) + install_dir : rootpkglibdir) + +install_data('sleep-products.conf', + install_dir : pkgsysconfdir) diff --git a/src/shared/mount-setup.c b/src/shared/mount-setup.c index 975c027f47..cb975e3698 100644 --- a/src/shared/mount-setup.c +++ b/src/shared/mount-setup.c @@ -86,6 +86,8 @@ static const MountPoint mount_table[] = { #endif { "tmpfs", "/run", "tmpfs", "mode=755" TMPFS_LIMITS_RUN, MS_NOSUID|MS_NODEV|MS_STRICTATIME, NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "tmpfs", "/run/lock", "tmpfs", "mode=1777,size=5242880", MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate,memory_recursiveprot", MS_NOSUID|MS_NOEXEC|MS_NODEV, cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate", MS_NOSUID|MS_NOEXEC|MS_NODEV, diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 49044a45ae..b76189d6b3 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -1123,7 +1123,7 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter if (ERRNO_IS_SECCOMP_FATAL(r)) return r; if (r < 0) - log_debug_errno(r, "Failed to install systemc call filter for architecture %s, skipping: %m", + log_debug_errno(r, "Failed to install system call filter for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); } diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index a56f2ff618..fc2cb2f180 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -17,6 +17,8 @@ #include "alloc-util.h" #include "blockdev-util.h" +#include "bus-error.h" +#include "bus-util.h" #include "btrfs-util.h" #include "conf-parser.h" #include "def.h" @@ -28,6 +30,7 @@ #include "log.h" #include "macro.h" #include "path-util.h" +#include "sd-bus.h" #include "sleep-config.h" #include "stat-util.h" #include "stdio-util.h" @@ -102,6 +105,56 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) { return 0; } +static int parse_sleep_products_config(SleepOperation operation, char ***_blacklist, char ***_whitelist) { + + _cleanup_strv_free_ char + **suspend_blacklist = NULL, **suspend_whitelist = NULL, + **hibernate_blacklist = NULL, **hibernate_whitelist = NULL, + **hybrid_blacklist = NULL, **hybrid_whitelist = NULL; + char **blacklist, **whitelist; + + const ConfigTableItem items[] = { + { "CanSuspend", "BlackListProducts", config_parse_strv, 0, &suspend_blacklist }, + { "CanSuspend", "WhiteListProducts", config_parse_strv, 0, &suspend_whitelist }, + { "CanHibernate", "BlackListProducts", config_parse_strv, 0, &hibernate_blacklist }, + { "CanHibernate", "WhiteListProducts", config_parse_strv, 0, &hibernate_whitelist }, + { "CanHybridSleep", "BlackListProducts", config_parse_strv, 0, &hybrid_blacklist }, + { "CanHybridSleep", "WhiteListProducts", config_parse_strv, 0, &hybrid_whitelist }, + {} + }; + + int r; + _cleanup_fclose_ FILE *f; + + f = fopen(PKGSYSCONFDIR "/sleep-products.conf", "re"); + if (!f) + log_full(errno == ENOENT ? LOG_DEBUG: LOG_WARNING, + "Failed to open configuration file " PKGSYSCONFDIR "/sleep-products.conf: %m"); + else { + r = config_parse + (NULL, PKGSYSCONFDIR "/sleep-products.conf", f, "CanSuspend\0CanHibernate\0CanHybridSleep\0", + config_item_table_lookup, (void*) items, 0, NULL, NULL); + if (r < 0) + log_warning("Failed to parse configuration file: %s", strerror(-r)); + } + + if (operation == SLEEP_SUSPEND) { + blacklist = TAKE_PTR(suspend_blacklist); + whitelist = TAKE_PTR(suspend_whitelist); + } else if (operation == SLEEP_HIBERNATE) { + blacklist = TAKE_PTR(hibernate_blacklist); + whitelist = TAKE_PTR(hibernate_whitelist); + } else if (operation == SLEEP_HYBRID_SLEEP) { + blacklist = TAKE_PTR(hybrid_blacklist); + whitelist = TAKE_PTR(hybrid_whitelist); + } else + assert_not_reached(); + + *_blacklist = blacklist; + *_whitelist = whitelist; + return 0; +} + int can_sleep_state(char **types) { _cleanup_free_ char *text = NULL; int r; @@ -476,6 +529,12 @@ static bool enough_swap_for_hibernation(void) { if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0) return true; + /* TuxOnIce is an alternate implementation for hibernation. + * It can be configured to compress the image to a file or an inactive + * swap partition, so there's nothing more we can do here. */ + if (access("/sys/power/tuxonice", F_OK) == 0) + return true; + r = find_hibernate_location(&hibernate_location); if (r < 0) return false; @@ -622,10 +681,37 @@ static bool can_s2h(const SleepConfig *sleep_config) { return true; } +static bool is_product_listed(char **products) { + int r; + _cleanup_free_ char *p = NULL; + + if (strv_isempty(products)) + return false; + + if (access("/sys/class/dmi/id/product_name", R_OK) < 0) + return false; + + r = read_one_line_file("/sys/class/dmi/id/product_name", &p); + if (r < 0) + return false; + + STRV_FOREACH(product, products) { + size_t l, k; + + l = strlen(p); + k = strlen(*product); + if (l == k && memcmp(p, *product, l) == 0) + return true; + } + + return false; +} + static int can_sleep_internal( const SleepConfig *sleep_config, SleepOperation operation, bool check_allowed) { + _cleanup_strv_free_ char **blacklist = NULL, **whitelist = NULL; assert(operation >= 0); assert(operation < _SLEEP_OPERATION_MAX); @@ -642,13 +728,24 @@ static int can_sleep_internal( can_sleep_disk(sleep_config->modes[operation]) <= 0) return false; + /* We keep an optional white and black list (by product) to + * control if we want to explicitly support sleep operations. */ + if (parse_sleep_products_config(operation, &blacklist, &whitelist) < 0) + return false; + + if (is_product_listed(blacklist)) + return false; + if (operation == SLEEP_SUSPEND) return true; if (!enough_swap_for_hibernation()) return -ENOSPC; - return true; + /* Endless does not support hibernate or hybrid-sleep by default, + * so allow it only if whitelisted. + * https://phabricator.endlessm.com/T13184#266832 */ + return is_product_listed(whitelist); } int can_sleep(SleepOperation operation) { diff --git a/src/shared/sleep-products.conf b/src/shared/sleep-products.conf new file mode 100644 index 0000000000..aa0a926351 --- /dev/null +++ b/src/shared/sleep-products.conf @@ -0,0 +1,37 @@ +# This file is part of Endless's fork of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# The contents of this file allow implementing a mechanism to blacklist +# certain products from supporting sleep operations, as well as to whitelist +# others that would be blacklisted. By default, Endless allows only laptops to +# suspend, and no products are allowed to hibernate. +# +# To achieve that, up to three sections can be defined here, controlling +# what gets blacklisted/whitelisted for each sleep operation. Each of those +# three sections can contain up to two variables, 'BlackListProducts' and +# 'WhiteListProducts', listing the product names as exposed by the kernel +# via the /sys/class/dmi/id/product_name file. +# +# The example below shows how we could blacklist two laptops and whitelist +# one desktop computer: +# +# [CanSuspend] +# WhiteListProducts=GB-BXBT-2807 +# BlackListProducts=20AQ0069UK 3249CTO +# +# [CanHibernate] +# WhiteListProducts=GB-BXBT-2807 +# BlackListProducts=20AQ0069UK 3249CTO +# +# [CanHybridSleep] +# WhiteListProducts=GB-BXBT-2807 +# BlackListProducts=20AQ0069UK 3249CTO +# +# Note: All the sections and variables are optional + +[CanSuspend] +BlackListProducts="Mission one" GB-BXBT-2807 diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c index f2f53380ad..c7e89ba6a6 100644 --- a/src/shared/utmp-wtmp.c +++ b/src/shared/utmp-wtmp.c @@ -337,7 +337,7 @@ int utmp_wall( const char *message, const char *username, const char *origin_tty, - bool (*match_tty)(const char *tty, void *userdata), + bool (*match_tty)(const char *tty, bool is_local, void *userdata), void *userdata) { _unused_ _cleanup_(utxent_cleanup) bool utmpx = false; @@ -381,17 +381,20 @@ int utmp_wall( if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0) continue; - /* this access is fine, because STRLEN("/dev/") << 32 (UT_LINESIZE) */ + /* This access is fine, because strlen("/dev/") < 32 (UT_LINESIZE) */ if (path_startswith(u->ut_line, "/dev/")) path = u->ut_line; else { if (asprintf(&buf, "/dev/%.*s", (int) sizeof(u->ut_line), u->ut_line) < 0) return -ENOMEM; - path = buf; } - if (!match_tty || match_tty(path, userdata)) { + /* It seems that the address field is always set for remote logins. + * For local logins and other local entries, we get [0,0,0,0]. */ + bool is_local = memeqzero(u->ut_addr_v6, sizeof(u->ut_addr_v6)); + + if (!match_tty || match_tty(path, is_local, userdata)) { q = write_to_terminal(path, text); if (q < 0) r = q; diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h index 3e71f76b27..36e4203b4f 100644 --- a/src/shared/utmp-wtmp.h +++ b/src/shared/utmp-wtmp.h @@ -23,7 +23,7 @@ int utmp_wall( const char *message, const char *username, const char *origin_tty, - bool (*match_tty)(const char *tty, void *userdata), + bool (*match_tty)(const char *tty, bool is_local, void *userdata), void *userdata); static inline bool utxent_start(void) { diff --git a/src/systemctl/systemctl-compat-halt.c b/src/systemctl/systemctl-compat-halt.c index 8a0e4e6294..7eeec9a45d 100644 --- a/src/systemctl/systemctl-compat-halt.c +++ b/src/systemctl/systemctl-compat-halt.c @@ -148,9 +148,11 @@ int halt_main(void) { if (arg_force == 0) { /* always try logind first */ - if (arg_when > 0) + if (arg_when > 0) { r = logind_schedule_shutdown(); - else { + if (r < 0) + return r; + } else { r = logind_check_inhibitors(arg_action); if (r < 0) return r; diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index 14ae873dc0..aa9e94bba6 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -760,7 +760,7 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { if (!fpath) return log_oom(); - log_warning("SysV service '%s' lacks a native systemd unit file. " + log_debug("SysV service '%s' lacks a native systemd unit file. " "Automatically generating a unit file for compatibility. " "Please update package to include a native systemd unit file, in order to make it more safe and robust.", fpath); diff --git a/src/test/meson.build b/src/test/meson.build index 74da544a46..6a467ea567 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -211,7 +211,9 @@ tests += [ [files('test-mkdir.c')], - [files('test-json.c')], + [files('test-json.c'), + [], + [libm]], [files('test-modhex.c')], @@ -275,7 +277,9 @@ tests += [ [files('test-parse-helpers.c')], - [files('test-parse-util.c')], + [files('test-parse-util.c'), + [], + [libm]], [files('test-sysctl-util.c')], @@ -664,6 +668,8 @@ tests += [ [], [], [], 'ENABLE_NSCD', 'manual'], [files('test-hmac.c')], + + [files('test-sha256.c')], ] ############################################################ diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c index 5b5a712469..4090029ef7 100644 --- a/src/test/test-fd-util.c +++ b/src/test/test-fd-util.c @@ -318,72 +318,6 @@ static int seccomp_prohibit_close_range(void) { #endif } -TEST(close_all_fds) { - int r; - - /* Runs the test four times. Once as is. Once with close_range() syscall blocked via seccomp, once - * with /proc overmounted, and once with the combination of both. This should trigger all fallbacks in - * the close_range_all() function. */ - - r = safe_fork("(caf-plain)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); - if (r == 0) { - test_close_all_fds_inner(); - _exit(EXIT_SUCCESS); - } - assert_se(r >= 0); - - if (geteuid() != 0) { - log_notice("Lacking privileges, skipping running tests with blocked close_range() and with /proc/ overnmounted."); - return; - } - - r = safe_fork("(caf-noproc)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL); - if (r == 0) { - r = mount_nofollow_verbose(LOG_WARNING, "tmpfs", "/proc", "tmpfs", 0, NULL); - if (r < 0) - log_notice("Overmounting /proc didn#t work, skipping close_all_fds() with masked /proc/."); - else - test_close_all_fds_inner(); - _exit(EXIT_SUCCESS); - } - assert_se(r >= 0); - - if (!is_seccomp_available()) { - log_notice("Seccomp not available, skipping seccomp tests in %s", __func__); - return; - } - - r = safe_fork("(caf-seccomp)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); - if (r == 0) { - r = seccomp_prohibit_close_range(); - if (r < 0) - log_notice("Applying seccomp filter didn't work, skipping close_all_fds() test with masked close_range()."); - else - test_close_all_fds_inner(); - - _exit(EXIT_SUCCESS); - } - assert_se(r >= 0); - - r = safe_fork("(caf-scnp)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL); - if (r == 0) { - r = seccomp_prohibit_close_range(); - if (r < 0) - log_notice("Applying seccomp filter didn't work, skipping close_all_fds() test with masked close_range()."); - else { - r = mount_nofollow_verbose(LOG_WARNING, "tmpfs", "/proc", "tmpfs", 0, NULL); - if (r < 0) - log_notice("Overmounting /proc didn#t work, skipping close_all_fds() with masked /proc/."); - else - test_close_all_fds_inner(); - } - - test_close_all_fds_inner(); - _exit(EXIT_SUCCESS); - } - assert_se(r >= 0); -} - TEST(format_proc_fd_path) { assert_se(streq_ptr(FORMAT_PROC_FD_PATH(0), "/proc/self/fd/0")); assert_se(streq_ptr(FORMAT_PROC_FD_PATH(1), "/proc/self/fd/1")); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 5d9d99e272..9466db6ecc 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -215,7 +215,7 @@ TEST(chase_symlinks) { assert_se(streq(result, "/test-chase.fsldajfl")); result = mfree(result); - r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result, NULL); + r = chase_symlinks("/etc/passwd/foo", NULL, 0, &result, NULL); assert_se(r == -ENOTDIR); result = mfree(result); @@ -288,23 +288,26 @@ TEST(chase_symlinks) { assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); } - p = strjoina(temp, "/machine-id-test"); - assert_se(symlink("/usr/../etc/./machine-id", p) >= 0); + p = strjoina(temp, "/passwd-test"); + assert_se(symlink("/usr/../etc/./passwd", p) >= 0); r = chase_symlinks(p, NULL, 0, NULL, &pfd); if (r != -ENOENT) { _cleanup_close_ int fd = -1; +/* sd_id128_t a, b; +*/ assert_se(pfd >= 0); fd = fd_reopen(pfd, O_RDONLY|O_CLOEXEC); assert_se(fd >= 0); safe_close(pfd); - +/* assert_se(id128_read_fd(fd, ID128_PLAIN, &a) >= 0); assert_se(sd_id128_get_machine(&b) >= 0); assert_se(sd_id128_equal(a, b)); +*/ } /* Test CHASE_NOFOLLOW */ diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c index 7e06fc419c..20c99f3a71 100644 --- a/src/test/test-mount-util.c +++ b/src/test/test-mount-util.c @@ -125,92 +125,6 @@ TEST(mount_flags_to_string) { "MS_I_VERSION|MS_STRICTATIME|MS_LAZYTIME|fc000200"); } -TEST(bind_remount_recursive) { - _cleanup_(rm_rf_physical_and_freep) char *tmp = NULL; - _cleanup_free_ char *subdir = NULL; - - if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) { - (void) log_tests_skipped("not running privileged"); - return; - } - - assert_se(mkdtemp_malloc("/tmp/XXXXXX", &tmp) >= 0); - subdir = path_join(tmp, "subdir"); - assert_se(subdir); - assert_se(mkdir(subdir, 0755) >= 0); - - FOREACH_STRING(p, "/usr", "/sys", "/", tmp) { - pid_t pid; - - pid = fork(); - assert_se(pid >= 0); - - if (pid == 0) { - struct statvfs svfs; - /* child */ - assert_se(detach_mount_namespace() >= 0); - - /* Check that the subdir is writable (it must be because it's in /tmp) */ - assert_se(statvfs(subdir, &svfs) >= 0); - assert_se(!FLAGS_SET(svfs.f_flag, ST_RDONLY)); - - /* Make the subdir a bind mount */ - assert_se(mount_nofollow(subdir, subdir, NULL, MS_BIND|MS_REC, NULL) >= 0); - - /* Ensure it's still writable */ - assert_se(statvfs(subdir, &svfs) >= 0); - assert_se(!FLAGS_SET(svfs.f_flag, ST_RDONLY)); - - /* Now mark the path we currently run for read-only */ - assert_se(bind_remount_recursive(p, MS_RDONLY, MS_RDONLY, path_equal(p, "/sys") ? STRV_MAKE("/sys/kernel") : NULL) >= 0); - - /* Ensure that this worked on the top-level */ - assert_se(statvfs(p, &svfs) >= 0); - assert_se(FLAGS_SET(svfs.f_flag, ST_RDONLY)); - - /* And ensure this had an effect on the subdir exactly if we are talking about a path above the subdir */ - assert_se(statvfs(subdir, &svfs) >= 0); - assert_se(FLAGS_SET(svfs.f_flag, ST_RDONLY) == !!path_startswith(subdir, p)); - - _exit(EXIT_SUCCESS); - } - - assert_se(wait_for_terminate_and_check("test-remount-rec", pid, WAIT_LOG) == EXIT_SUCCESS); - } -} - -TEST(bind_remount_one) { - pid_t pid; - - if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) { - (void) log_tests_skipped("not running privileged"); - return; - } - - pid = fork(); - assert_se(pid >= 0); - - if (pid == 0) { - /* child */ - - _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; - - assert_se(detach_mount_namespace() >= 0); - - assert_se(fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo) >= 0); - - assert_se(bind_remount_one_with_mountinfo("/run", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) >= 0); - assert_se(bind_remount_one_with_mountinfo("/run", MS_NOEXEC, MS_RDONLY|MS_NOEXEC, proc_self_mountinfo) >= 0); - assert_se(bind_remount_one_with_mountinfo("/proc/idontexist", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) == -ENOENT); - assert_se(bind_remount_one_with_mountinfo("/proc/self", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) == -EINVAL); - assert_se(bind_remount_one_with_mountinfo("/", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) >= 0); - - _exit(EXIT_SUCCESS); - } - - assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS); -} - TEST(make_mount_point_inode) { _cleanup_(rm_rf_physical_and_freep) char *d = NULL; const char *src_file, *src_dir, *dst_file, *dst_dir; diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c index 3c2523006a..791db564f7 100644 --- a/src/test/test-mountpoint-util.c +++ b/src/test/test-mountpoint-util.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include @@ -295,17 +294,6 @@ TEST(fd_is_mount_point) { } static int intro(void) { - /* let's move into our own mount namespace with all propagation from the host turned off, so - * that /proc/self/mountinfo is static and constant for the whole time our test runs. */ - - if (unshare(CLONE_NEWNS) < 0) { - if (!ERRNO_IS_PRIVILEGE(errno)) - return log_error_errno(errno, "Failed to detach mount namespace: %m"); - - log_notice("Lacking privilege to create separate mount namespace, proceeding in originating mount namespace."); - } else - assert_se(mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL) >= 0); - return EXIT_SUCCESS; } diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 4c56a7d520..41d4da04db 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -204,31 +204,6 @@ TEST(find_executable_full) { assert_se(streq(basename(p), "sh")); free(p); - assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0); - puts(p); - assert_se(streq(basename(p), "sh")); - free(p); - - _cleanup_free_ char *oldpath = NULL; - p = getenv("PATH"); - if (p) - assert_se(oldpath = strdup(p)); - - assert_se(unsetenv("PATH") == 0); - - assert_se(find_executable_full("sh", NULL, NULL, true, &p, NULL) == 0); - puts(p); - assert_se(streq(basename(p), "sh")); - free(p); - - assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0); - puts(p); - assert_se(streq(basename(p), "sh")); - free(p); - - if (oldpath) - assert_se(setenv("PATH", oldpath, true) >= 0); - assert_se((fd = mkostemp_safe(fn)) >= 0); assert_se(fchmod(fd, 0755) >= 0); @@ -441,8 +416,9 @@ TEST(path_extend) { } TEST(fsck_exists) { - /* Ensure we use a sane default for PATH. */ - assert_se(unsetenv("PATH") == 0); + /* The build environment might not use the same split-usr approach + * as the current build, so lets use the most inclusive PATH. */ + assert_se(setenv("PATH", DEFAULT_PATH_SPLIT_USR, 1) == 0); /* fsck.minix is provided by util-linux and will probably exist. */ assert_se(fsck_exists("minix") == 1); diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index 7ccfeadbb8..45fe8f7c59 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -655,7 +655,7 @@ TEST(memory_deny_write_execute_shmat) { log_notice("Seccomp not available, skipping %s", __func__); return; } - if (!have_seccomp_privs()) { + if (!have_seccomp_privs() || have_effective_cap(CAP_IPC_OWNER) <= 0) { log_notice("Not privileged, skipping %s", __func__); return; } diff --git a/src/test/test-sha256.c b/src/test/test-sha256.c new file mode 100644 index 0000000000..f168e4c355 --- /dev/null +++ b/src/test/test-sha256.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "hexdecoct.h" +#include "sha256.h" +#include "string-util.h" +#include "tests.h" + +static void sha256_process_string(const char *key, struct sha256_ctx *ctx) { + sha256_process_bytes(key, strlen(key), ctx); +} + +static void test_sha256_one(const char *key, const char *expect) { + uint8_t result[SHA256_DIGEST_SIZE + 3]; + _cleanup_free_ char *str = NULL; + struct sha256_ctx ctx; + + log_debug("\"%s\" → %s", key, expect); + + assert_se(str = new(char, strlen(key) + 4)); + + /* This tests unaligned buffers. */ + + for (size_t i = 0; i < 4; i++) { + strcpy(str + i, key); + + for (size_t j = 0; j < 4; j++) { + _cleanup_free_ char *hex_result = NULL; + + sha256_init_ctx(&ctx); + sha256_process_string(str + i, &ctx); + sha256_finish_ctx(&ctx, result + j); + + hex_result = hexmem(result + j, SHA256_DIGEST_SIZE); + assert_se(streq_ptr(hex_result, expect)); + } + } +} + +TEST(sha256) { + /* Results compared with output of 'echo -n "" | sha256sum -' */ + + test_sha256_one("abcdefghijklmnopqrstuvwxyz", + "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73"); + test_sha256_one("ほげほげあっちょんぶりけ", + "ce7225683653be3b74861c5a4323b6baf3c3ceb361413ca99e3a5b52c04411bd"); + test_sha256_one("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", + "9cfe7faff7054298ca87557e15a10262de8d3eee77827417fbdfea1c41b9ec23"); +} + +DEFINE_TEST_MAIN(LOG_INFO); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 9ca5d37b75..7b09a4cf1e 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -296,6 +296,8 @@ static int context_read_data(Context *c) { static int context_write_data_timezone(Context *c) { _cleanup_free_ char *p = NULL; const char *source; + int r = 0; + struct stat st; assert(c); @@ -309,9 +311,12 @@ static int context_write_data_timezone(Context *c) { if (access("/usr/share/zoneinfo/UTC", F_OK) < 0) { if (unlink("/etc/localtime") < 0 && errno != ENOENT) - return -errno; + r = -errno; - return 0; + if (unlink("/etc/timezone") < 0 && errno != ENOENT) + r = -errno; + + return r; } source = "../usr/share/zoneinfo/UTC"; @@ -323,7 +328,17 @@ static int context_write_data_timezone(Context *c) { source = p; } - return symlink_atomic(source, "/etc/localtime"); + r = symlink_atomic(source, "/etc/localtime"); + if (r < 0) + return r; + + if (stat("/etc/timezone", &st) == 0 && S_ISREG(st.st_mode)) { + r = write_string_file("/etc/timezone", c->zone, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); + if (r < 0) + return r; + } + + return 0; } static int context_write_data_local_rtc(Context *c) { diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 94973c2aa5..0d27daa87b 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2760,6 +2760,7 @@ static int specifier_expansion_from_arg(const Specifier *specifier_table, Item * static int patch_var_run(const char *fname, unsigned line, char **path) { const char *k; char *n; + int log_level; assert(path); assert(*path); @@ -2785,7 +2786,8 @@ static int patch_var_run(const char *fname, unsigned line, char **path) { /* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence * there's no immediate need for action by the user. However, in the interest of making things less confusing * to the user, let's still inform the user that these snippets should really be updated. */ - log_syntax(NULL, LOG_NOTICE, fname, line, 0, + log_level = path_startswith(fname, "/etc") ? LOG_NOTICE : LOG_DEBUG; + log_syntax(NULL, log_level, fname, line, 0, "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", *path, n); diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 7fc0ed7c8d..13ade29b50 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -94,7 +94,7 @@ static int send_passwords(const char *socket_name, char **passwords) { return (int) n; } -static bool wall_tty_match(const char *path, void *userdata) { +static bool wall_tty_match(const char *path, bool is_local, void *userdata) { _cleanup_free_ char *p = NULL; _cleanup_close_ int fd = -1; struct stat st; diff --git a/src/udev/meson.build b/src/udev/meson.build index 79964a7d8e..c6711beb5a 100644 --- a/src/udev/meson.build +++ b/src/udev/meson.build @@ -100,7 +100,7 @@ link_config_gperf_c = custom_target( if get_option('link-udev-shared') udev_link_with = [libshared] - udev_rpath = rootlibexecdir + udev_rpath = rootpkglibdir else udev_link_with = [libshared_static, libsystemd_static] diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c index 18d58c308c..490e42b014 100644 --- a/src/userdb/userwork.c +++ b/src/userdb/userwork.c @@ -556,7 +556,7 @@ static int run(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parent already died?"); if (kill(parent, SIGUSR2) < 0) - return log_error_errno(errno, "Failed to kill our own parent."); + return log_error_errno(errno, "Failed to kill our own parent: %m"); } } diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c index aa16582d9e..e29d4df692 100644 --- a/src/volatile-root/volatile-root.c +++ b/src/volatile-root/volatile-root.c @@ -127,7 +127,7 @@ static int run(int argc, char *argv[]) { r = query_volatile_mode(&m); if (r < 0) - return log_error_errno(r, "Failed to determine volatile mode from kernel command line."); + return log_error_errno(r, "Failed to determine volatile mode from kernel command line: %m"); if (r == 0 && argc >= 2) { /* The kernel command line always wins. However if nothing was set there, the argument passed here wins instead. */ m = volatile_mode_from_string(argv[1]); diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in index 5fb551a8cf..13495f1267 100644 --- a/sysctl.d/50-coredump.conf.in +++ b/sysctl.d/50-coredump.conf.in @@ -13,7 +13,7 @@ # the core dump. # # See systemd-coredump(8) and core(5). -kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h +kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t 9223372036854775808 %h # Allow 16 coredumps to be dispatched in parallel by the kernel. # We collect metadata from /proc/%P/, and thus need to make sure the crashed diff --git a/sysctl.d/51-coredump.conf b/sysctl.d/51-coredump.conf new file mode 100644 index 0000000000..ef89c6cbfd --- /dev/null +++ b/sysctl.d/51-coredump.conf @@ -0,0 +1,12 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See sysctl.d(5) for the description of the files in this directory, +# and systemd-coredump(8) and core(5) for the explanation of the +# setting below. + +kernel.core_pattern=|/bin/false diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build index ecec903d1b..6b168076b5 100644 --- a/sysctl.d/meson.build +++ b/sysctl.d/meson.build @@ -3,6 +3,7 @@ install_data( 'README', '50-default.conf', + '51-coredump.conf', install_dir : sysctldir) # Kernel determines PID_MAX_LIMIT by diff --git a/test/TEST-02-UNITTESTS/deny-list-upstream-ci-ppc64el b/test/TEST-02-UNITTESTS/deny-list-upstream-ci-ppc64el new file mode 100644 index 0000000000..52877fc766 --- /dev/null +++ b/test/TEST-02-UNITTESTS/deny-list-upstream-ci-ppc64el @@ -0,0 +1 @@ +# unknown reason for failing, tracked in https://github.com/systemd/systemd/issues/11612 diff --git a/test/TEST-24-CRYPTSETUP/test.sh b/test/TEST-24-CRYPTSETUP/test.sh index 96d255dd96..b81b811654 100755 --- a/test/TEST-24-CRYPTSETUP/test.sh +++ b/test/TEST-24-CRYPTSETUP/test.sh @@ -10,6 +10,11 @@ TEST_FORCE_NEWIMAGE=1 # shellcheck source=test/test-functions . "${TEST_BASE_DIR:?}/test-functions" +PART_UUID="deadbeef-dead-dead-beef-000000000000" +DM_NAME="test24_varcrypt" +KERNEL_APPEND+=" rd.luks=1 luks.name=$PART_UUID=$DM_NAME luks.key=$PART_UUID=/keyfile:LABEL=varcrypt_keydev" +QEMU_OPTIONS+=" -drive format=raw,cache=unsafe,file=${STATEDIR:?}/keydev.img" + check_result_qemu() { local ret=1 @@ -17,13 +22,13 @@ check_result_qemu() { [[ -e "${initdir:?}/testok" ]] && ret=0 [[ -f "$initdir/failed" ]] && cp -a "$initdir/failed" "${TESTDIR:?}" - cryptsetup luksOpen "${LOOPDEV:?}p2" varcrypt <"$TESTDIR/keyfile" - mount /dev/mapper/varcrypt "$initdir/var" + cryptsetup luksOpen "${LOOPDEV:?}p2" "${DM_NAME:?}" <"$TESTDIR/keyfile" + mount "/dev/mapper/$DM_NAME" "$initdir/var" save_journal "$initdir/var/log/journal" check_coverage_reports "${initdir:?}" || ret=5 _umount_dir "$initdir/var" _umount_dir "$initdir" - cryptsetup luksClose /dev/mapper/varcrypt + cryptsetup luksClose "/dev/mapper/$DM_NAME" [[ -f "$TESTDIR/failed" ]] && cat "$TESTDIR/failed" echo "${JOURNAL_LIST:-No journals were saved}" @@ -36,45 +41,65 @@ test_create_image() { create_empty_image_rootdir echo -n test >"${TESTDIR:?}/keyfile" - cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 "${LOOPDEV:?}p2" "$TESTDIR/keyfile" - cryptsetup luksOpen "${LOOPDEV}p2" varcrypt <"$TESTDIR/keyfile" - mkfs.ext4 -L var /dev/mapper/varcrypt + cryptsetup -q luksFormat --uuid="$PART_UUID" --pbkdf pbkdf2 --pbkdf-force-iterations 1000 "${LOOPDEV:?}p2" "$TESTDIR/keyfile" + cryptsetup luksOpen "${LOOPDEV}p2" "${DM_NAME:?}" <"$TESTDIR/keyfile" + mkfs.ext4 -L var "/dev/mapper/$DM_NAME" mkdir -p "${initdir:?}/var" - mount /dev/mapper/varcrypt "$initdir/var" - - # Create what will eventually be our root filesystem onto an overlay - ( - LOG_LEVEL=5 - # shellcheck source=/dev/null - source <(udevadm info --export --query=env --name=/dev/mapper/varcrypt) - # shellcheck source=/dev/null - source <(udevadm info --export --query=env --name="${LOOPDEV}p2") - - setup_basic_environment - mask_supporting_services - - install_dmevent - generate_module_dependencies - cat >"$initdir/etc/crypttab" <"$initdir/etc/varkey" - ddebug <"$initdir/etc/crypttab" + mount "/dev/mapper/$DM_NAME" "$initdir/var" + + LOG_LEVEL=5 + + setup_basic_environment + mask_supporting_services + + install_dmevent + generate_module_dependencies + + # Create a keydev + dd if=/dev/zero of="${STATEDIR:?}/keydev.img" bs=1M count=16 + mkfs.ext4 -L varcrypt_keydev "$STATEDIR/keydev.img" + mkdir -p "$STATEDIR/keydev" + mount "$STATEDIR/keydev.img" "$STATEDIR/keydev" + echo -n test >"$STATEDIR/keydev/keyfile" + umount "$STATEDIR/keydev" - cat >>"$initdir/etc/fstab" <>"$initdir/etc/fstab" <> "$initdir/etc/systemd/journald.conf" - ) + # Forward journal messages to the console, so we have something + # to investigate even if we fail to mount the encrypted /var + echo ForwardToConsole=yes >> "$initdir/etc/systemd/journald.conf" + + # If $INITRD wasn't provided explicitly, generate a custom one with dm-crypt + # support + if [[ -z "$INITRD" ]]; then + INITRD="${TESTDIR:?}/initrd.img" + dinfo "Generating a custom initrd with dm-crypt support in '${INITRD:?}'" + + if command -v dracut >/dev/null; then + dracut --force --verbose --add crypt "$INITRD" + elif command -v mkinitcpio >/dev/null; then + mkinitcpio --addhooks sd-encrypt --generate "$INITRD" + elif command -v mkinitramfs >/dev/null; then + # The cryptroot hook is provided by the cryptsetup-initramfs package + if ! dpkg-query -s cryptsetup-initramfs; then + derror "Missing 'cryptsetup-initramfs' package for dm-crypt support in initrd" + return 1 + fi + + mkinitramfs -o "$INITRD" + else + dfatal "Unrecognized initrd generator, can't continue" + return 1 + fi + fi } cleanup_root_var() { ddebug "umount ${initdir:?}/var" mountpoint "$initdir/var" && umount "$initdir/var" - [[ -b /dev/mapper/varcrypt ]] && cryptsetup luksClose /dev/mapper/varcrypt + [[ -b "/dev/mapper/${DM_NAME:?}" ]] && cryptsetup luksClose "/dev/mapper/$DM_NAME" } test_cleanup() { diff --git a/test/TEST-25-IMPORT/deny-list-upstream-ci b/test/TEST-25-IMPORT/deny-list-upstream-ci new file mode 100644 index 0000000000..47a5f15875 --- /dev/null +++ b/test/TEST-25-IMPORT/deny-list-upstream-ci @@ -0,0 +1 @@ +# unknown failure; tracked in https://github.com/systemd/systemd/issues/13973 diff --git a/test/fuzz/fuzz-bus-message/issue-23486-case-1 b/test/fuzz/fuzz-bus-message/issue-23486-case-1 new file mode 100644 index 0000000000..fe8338b42b Binary files /dev/null and b/test/fuzz/fuzz-bus-message/issue-23486-case-1 differ diff --git a/test/fuzz/fuzz-bus-message/issue-23486-case-2 b/test/fuzz/fuzz-bus-message/issue-23486-case-2 new file mode 100644 index 0000000000..1791244613 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/issue-23486-case-2 differ diff --git a/test/fuzz/fuzz-bus-message/issue-23486-case-3 b/test/fuzz/fuzz-bus-message/issue-23486-case-3 new file mode 100644 index 0000000000..cff8b38037 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/issue-23486-case-3 differ diff --git a/test/test-functions b/test/test-functions index 06a06e706a..daed481a29 100644 --- a/test/test-functions +++ b/test/test-functions @@ -337,6 +337,11 @@ qemu_min_version() { # Return 0 if qemu did run (then you must check the result state/logs for actual # success), or 1 if qemu is not available. run_qemu() { + # If the test provided its own initrd, use it (e.g. TEST-24) + if [[ -z "$INITRD" && -f "${TESTDIR:?}/initrd.img" ]]; then + INITRD="$TESTDIR/initrd.img" + fi + if [ -f /etc/machine-id ]; then read -r MACHINE_ID