diff --git a/NEWS b/NEWS index 75432a09d..c24c865be 100644 --- a/NEWS +++ b/NEWS @@ -805,6 +805,9 @@ CHANGES WITH 243: * systemd-networkd's TUN support gained a new setting VnetHeader= for tweaking Generic Segment Offload support. + * The address family for policy rules may be specified using the new + Family= option in the [RoutingPolicyRule] section. + * networkctl gained a new "delete" command for removing virtual network devices, as well as a new "--stats" switch for showing device statistics. diff --git a/TODO b/TODO index e944245a5..51b23cfb3 100644 --- a/TODO +++ b/TODO @@ -446,9 +446,6 @@ Features: * support projid-based quota in machinectl for containers -* maybe use SOURCE_DATE_EPOCH (i.e. the env var the reproducible builds folks - introduced) as the RTC epoch, instead of the mtime of NEWS. - * add a way to lock down cgroup migration: a boolean, which when set for a unit makes sure the processes in it can never migrate out of it diff --git a/man/custom-html.xsl b/man/custom-html.xsl index fccaf51ff..7eebfdb5a 100644 --- a/man/custom-html.xsl +++ b/man/custom-html.xsl @@ -1,9 +1,5 @@ - - + @@ -96,6 +92,21 @@ + + + + https://manpages.debian.org/unstable/ + + / + + . + + .en.html + + + + + diff --git a/man/journald.conf.xml b/man/journald.conf.xml index e24c420ab..957ec36a6 100644 --- a/man/journald.conf.xml +++ b/man/journald.conf.xml @@ -140,7 +140,7 @@ us. To turn off any kind of rate limiting, set either value to 0. - Note that the effective rate limit is multiplied with a + Note that the effective rate limit is multiplied by a factor derived from the available free disk space for the journal. Currently, this factor is calculated using the base 2 logarithm. @@ -402,6 +402,18 @@ this option is enabled by default, it is disabled in all others. + + Audit= + + Takes a boolean value. If enabled systemd-journal will turn on + kernel auditing on start-up. If disabled it will turn it off. If unset it will neither enable nor + disable it, leaving the previous state unchanged. Note that this option does not control whether + 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. + + TTYPath= diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml index 694371c2c..70927d737 100644 --- a/man/pam_systemd.xml +++ b/man/pam_systemd.xml @@ -259,31 +259,31 @@ - systemd.memory_max + systemd.memory_max= Sets unit MemoryMax=. - systemd.tasks_max + systemd.tasks_max= Sets unit TasksMax=. - systemd.cpu_weight + systemd.cpu_weight= Sets unit CPUWeight=. - systemd.io_weight + systemd.io_weight= Sets unit IOWeight=. - systemd.runtime_max_sec + systemd.runtime_max_sec= Sets unit RuntimeMaxSec=. @@ -308,19 +308,24 @@ pam_set_data(handle, "systemd.runtime_max_sec", (void *)"3600", cleanup); systemd-logind.service: #%PAM-1.0 -auth sufficient pam_unix.so -auth required pam_deny.so +auth sufficient pam_unix.so +-auth sufficient pam_systemd_home.so +auth required pam_deny.so -account required pam_nologin.so -account sufficient pam_unix.so -account required pam_permit.so +account required pam_nologin.so +-account sufficient pam_systemd_home.so +account sufficient pam_unix.so +account required pam_permit.so -password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok -password required pam_deny.so +-password sufficient pam_systemd_home.so +password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok +password required pam_deny.so --session optional pam_loginuid.so --session optional pam_systemd.so -session required pam_unix.so +-session optional pam_keyinit.so revoke +-session optional pam_loginuid.so +-session optional pam_systemd_home.so +-session optional pam_systemd.so +session required pam_unix.so diff --git a/man/pam_systemd_home.xml b/man/pam_systemd_home.xml index 6dc1a830b..341f8a8e4 100644 --- a/man/pam_systemd_home.xml +++ b/man/pam_systemd_home.xml @@ -95,21 +95,21 @@ #%PAM-1.0 auth sufficient pam_unix.so --auth sufficient pam_systemd_home.so +-auth sufficient pam_systemd_home.so auth required pam_deny.so account required pam_nologin.so --account sufficient pam_systemd_home.so +-account sufficient pam_systemd_home.so account sufficient pam_unix.so account required pam_permit.so --password sufficient pam_systemd_home.so +-password sufficient pam_systemd_home.so password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok password required pam_deny.so -session optional pam_keyinit.so revoke -session optional pam_loginuid.so --session optional pam_systemd_home.so +-session optional pam_systemd_home.so -session optional pam_systemd.so session required pam_unix.so diff --git a/man/resolvectl.xml b/man/resolvectl.xml index 594e22c03..a7de5a309 100644 --- a/man/resolvectl.xml +++ b/man/resolvectl.xml @@ -288,17 +288,27 @@ - Compatibility with <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry> + Compatibility with + <citerefentry project="debian"><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry> resolvectl is a multi-call binary. When invoked as resolvconf (generally achieved by means of a symbolic link of this name to the resolvectl binary) it - is run in a limited resolvconf8 + is run in a limited + resolvconf8 compatibility mode. It accepts mostly the same arguments and pushes all data into systemd-resolved.service8, similar to how and commands operate. Note that systemd-resolved.service is the only supported backend, which is different from other - implementations of this command. Note that not all operations supported by other implementations are supported - natively. Specifically: + implementations of this command. + + /etc/resolv.conf will only be updated with servers added with this command + when /etc/resolv.conf is a symlink to + /run/systemd/resolve/resolv.conf, and not a static file. See the discussion of + /etc/resolv.conf handling in + systemd-resolved.service8. + + + Not all operations supported by other implementations are supported natively. Specifically: @@ -359,7 +369,9 @@ - See resolvconf8 for details on this command line options. + See + resolvconf8 + for details on those command line options. diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml index 64ed5f377..a01ec5878 100644 --- a/man/sd-daemon.xml +++ b/man/sd-daemon.xml @@ -70,10 +70,9 @@ These prefixes are intended to be used in conjunction with stderr-based logging (or stdout-based logging) as implemented by systemd. If a systemd service definition file is configured with - StandardError=journal, StandardError=syslog or - StandardError=kmsg (and similar with StandardOutput=), these - prefixes can be used to encode a log level in lines printed. This is similar to the kernel - printk()-style logging. See + StandardError=journal or StandardError=kmsg (and similar with + StandardOutput=), these prefixes can be used to encode a log level in lines + printed. This is similar to the kernel printk()-style logging. See klogctl2 for more information. diff --git a/man/sd_bus_message_append_array.xml b/man/sd_bus_message_append_array.xml index b9595d6a0..d81ddc558 100644 --- a/man/sd_bus_message_append_array.xml +++ b/man/sd_bus_message_append_array.xml @@ -34,7 +34,7 @@ int sd_bus_message_append_array sd_bus_message *m char type - char void *ptr + void *ptr size_t size diff --git a/man/sysctl.d.xml b/man/sysctl.d.xml index 4df71e21e..f6713d398 100644 --- a/man/sysctl.d.xml +++ b/man/sysctl.d.xml @@ -159,7 +159,7 @@ net.bridge.bridge-nf-call-arptables = 0 Set network routing properties for all interfaces - /etc/systemd/20-rp_filter.conf: + /etc/sysctl.d/20-rp_filter.conf: net.ipv4.conf.default.rp_filter = 2 net.ipv4.conf.*.rp_filter = 2 diff --git a/man/systemd-binfmt.service.xml b/man/systemd-binfmt.service.xml index 27e34195a..41a8247c5 100644 --- a/man/systemd-binfmt.service.xml +++ b/man/systemd-binfmt.service.xml @@ -41,6 +41,14 @@ Options + + + + If passed, instead of registering configured binary formats in the kernel, the + reverse operation is executed: all currently registered binary formats are unregistered from the + kernel. + + diff --git a/man/systemd-boot.xml b/man/systemd-boot.xml index fff7395f3..ee513ed40 100644 --- a/man/systemd-boot.xml +++ b/man/systemd-boot.xml @@ -175,8 +175,8 @@ - The following keys may be used during bootup or in the boot menu to - directly boot a specific entry: + The following keys may be pressed during bootup or in the boot menu to directly boot a specific + entry: @@ -213,6 +213,17 @@ + The boot menu is shown when a non-zero menu timeout has been configured. If the menu timeout has + been set to zero, it is sufficient to press any key — before the boot loader initializes — to bring up + the boot menu, except for the keys listed immediately above as they directly boot into the selected boot + menu item. Note that depending on the firmware implementation the time window where key presses are + accepted before the boot loader initializes might be short. If the window is missed, reboot and try + again, possibly pressing a suitable key (e.g. the space bar) continuously; on most systems it should be + possible to hit the time window after a few attempts. To avoid this problem, consider setting a non-zero + timeout, thus showing the boot menu unconditionally. Some desktop environments might offer an option to + directly boot into the boot menu, to avoid the problem altogether. Alternatively, use the command line + systemctl reboot --boot-loader-menu=0 from the shell. + In the editor, most keys simply insert themselves, but the following keys may be used to perform additional actions: diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml index f2ed76102..35690fd22 100644 --- a/man/systemd.automount.xml +++ b/man/systemd.automount.xml @@ -86,6 +86,10 @@ Automount units acquire automatic Before= and Conflicts= on umount.target in order to be stopped during shutdown. + + Automount units automatically gain an After= dependency + on local-fs-pre.target, and a Before= dependency on + local-fs.target. diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index fd1755e42..e693af49d 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -66,9 +66,9 @@ will also gain an automatic After= dependency on systemd-tmpfiles-setup.service8. - Units whose standard output or error output is connected to , - or (or their combinations with console output, see below) - automatically acquire dependencies of type After= on + Units whose standard output or error output is connected to or + (or their combinations with console output, see below) automatically acquire + dependencies of type After= on systemd-journald.socket. Units using LogNamespace= will automatically gain ordering and @@ -857,10 +857,11 @@ CapabilityBoundingSet=~CAP_B CAP_C ProtectSystem= Takes a boolean argument or the special values full or - strict. If true, mounts the /usr and /boot - directories read-only for processes invoked by this unit. If set to full, the - /etc directory is mounted read-only, too. If set to strict the entire - file system hierarchy is mounted read-only, except for the API file system subtrees /dev, + strict. If true, mounts the /usr and the boot loader + directories (/boot and /efi) read-only for processes + invoked by this unit. If set to full, the /etc directory is + mounted read-only, too. If set to strict the entire file system hierarchy is + mounted read-only, except for the API file system subtrees /dev, /proc and /sys (protect these directories using PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=). This setting ensures that any modification of the vendor-supplied diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 1dca495a0..acda31066 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -691,13 +691,15 @@ RxBufferSize= - Takes a integer. Specifies the NIC receive ring buffer size. When unset, the kernel's default will be used. + Takes an integer. Specifies the maximum number of pending packets in the NIC receive buffer. + When unset, the kernel's default will be used. TxBufferSize= - Takes a integer. Specifies the NIC transmit ring buffer size. When unset, the kernel's default will be used. + Takes an integer. Specifies the maximum number of pending packets in the NIC transmit buffer. + When unset, the kernel's default will be used. diff --git a/man/systemd.nspawn.xml b/man/systemd.nspawn.xml index 11df4623b..27eae50b5 100644 --- a/man/systemd.nspawn.xml +++ b/man/systemd.nspawn.xml @@ -469,18 +469,16 @@ VirtualEthernetExtra= - Takes a colon-separated pair of interface - names. Configures an additional virtual Ethernet connection - (veth) between host and the container. The - first specified name is the interface name on the host, the - second the interface name in the container. The latter may be - omitted in which case it is set to the same name as the host - side interface. This setting implies - Private=yes. This setting corresponds to - the command line - switch, and maybe be used multiple times. It is independent of - VirtualEthernet=. This option is privileged - (see above). + Takes a colon-separated pair of interface names. Configures an additional virtual + Ethernet connection (veth) between host and the container. The first specified + name is the interface name on the host, the second the interface name in the container. The latter + may be omitted in which case it is set to the same name as the host side interface. This setting + implies Private=yes. This setting corresponds to the + command line switch, and maybe be used multiple times. It is + independent of VirtualEthernet=. Note that this option is unrelated to the + Bridge= setting below, and thus any connections created this way are not + automatically added to any bridge device on the host side. This option is privileged (see + above). diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 02eb70678..bc05e3dcb 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -845,35 +845,41 @@ SuccessExitStatus= + Takes a list of exit status definitions that, when returned by the main service - process, will be considered successful termination, in addition to the normal successful exit code 0 - and the signals SIGHUP, SIGINT, + process, will be considered successful termination, in addition to the normal successful exit status + 0 and the signals SIGHUP, SIGINT, SIGTERM, and SIGPIPE. Exit status definitions can be - numeric exit codes, termination code names, or termination signal names, separated by spaces. See the - Process Exit Codes section in + numeric termination statuses, termination status names, or termination signal names, separated by + spaces. See the Process Exit Codes section in systemd.exec5 for - a list of termination codes names (for this setting only the part without the - EXIT_ or EX_ prefix should be used). See - signal7 for + a list of termination status names (for this setting only the part without the + EXIT_ or EX_ prefix should be used). See signal7 for a list of signal names. - This option may appear more than once, in which case the - list of successful exit statuses is merged. If the empty - string is assigned to this option, the list is reset, all - prior assignments of this option will have no - effect. + Note that this setting does not change the the mapping between numeric exit statuses and their + names, i.e. regardless how this setting is used 0 will still be mapped to SUCCESS + (and thus typically shown as 0/SUCCESS in tool outputs) and 1 to + FAILURE (and thus typically shown as 1/FAILURE), and so on. It + only controls what happens as effect of these exit statuses, and how it propagates to the state of + the service as a whole. + + This option may appear more than once, in which case the list of successful exit statuses is + merged. If the empty string is assigned to this option, the list is reset, all prior assignments of + this option will have no effect. A service with with the <varname>SuccessExitStatus=</varname> setting SuccessExitStatus=TEMPFAIL 250 SIGUSR1 - Exit codes 75 (TEMPFAIL), 250, and the termination signal + Exit status 75 (TEMPFAIL), 250, and the termination signal SIGKILL are considered clean service terminations. - Note: systemd-analyze exit-codes may be used to list exit - codes and translate between numerical code values and names. + Note: systemd-analyze exit-status may be used to list exit statuses and + translate between numerical status values and names. @@ -1106,10 +1112,10 @@ Basic environment variable substitution is supported. Use ${FOO} as part of a word, or as a word of its - own, on the command line, in which case it will be replaced by the - value of the environment variable including all whitespace it - contains, resulting in a single argument. Use - $FOO as a separate word on the command line, in + own, on the command line, in which case it will be erased and replaced + by the exact value of the environment variable (if any) including all + whitespace it contains, always resulting in exactly a single argument. + Use $FOO as a separate word on the command line, in which case it will be replaced by the value of the environment variable split at whitespace, resulting in zero or more arguments. For this type of expansion, quotes are respected when splitting diff --git a/man/systemd.time.xml b/man/systemd.time.xml index dc1e78a18..b4656b05d 100644 --- a/man/systemd.time.xml +++ b/man/systemd.time.xml @@ -199,15 +199,14 @@ tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00 continuous weekdays. , and .. may be combined freely. - In the date and time specifications, any component may be - specified as * in which case any value will - match. Alternatively, each component can be specified as a list of - values separated by commas. Values may be suffixed with - / and a repetition value, which indicates that - the value itself and the value plus all multiples of the repetition value - are matched. Two values separated by .. may be used - to indicate a range of values; ranges may also be followed with - / and a repetition value. + In the date and time specifications, any component may be specified as * in + which case any value will match. Alternatively, each component can be specified as a list of values + separated by commas. Values may be suffixed with / and a repetition value, which + indicates that the value itself and the value plus all multiples of the repetition value are matched. + Two values separated by .. may be used to indicate a range of values; ranges may also + be followed with / and a repetition value, in which case the expression matches all + times starting with the start value, and continuing with all multiples of the repetition value relative + to the start value, ending at the end value the latest. A date specification may use ~ to indicate the last day(s) in a month. For example, *-02~03 means diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 0d223d74d..86185e48a 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -1263,7 +1263,7 @@ ConditionNeedsUpdate= Takes one of /var or /etc as argument, - possibly prefixed with a ! (to inverting the condition). This condition may be + possibly prefixed with a ! (to invert the condition). This condition may be used to conditionalize units on whether the specified directory requires an update because /usr's modification time is newer than the stamp file .updated in the specified directory. This is useful to implement offline diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index a29c913ff..426df6cb4 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -120,16 +120,19 @@ A+ /path-or-glob/to/append/acls/recursively - - - - POSIX /usr/lib/tmpfiles.d and /run/tmpfiles.d. Files in /run/tmpfiles.d override files with the same name in /usr/lib/tmpfiles.d. Packages should install their configuration files in - /usr/lib/tmpfiles.d. Files in /etc/tmpfiles.d are reserved for the local - administrator, who may use this logic to override the configuration files installed by vendor packages. All - configuration files are sorted by their filename in lexicographic order, regardless of which of the directories - they reside in. If multiple files specify the same path, the entry in the file with the lexicographically earliest - name will be applied. All other conflicting entries will be logged as errors. When two lines are prefix path and - suffix path of each other, then the prefix line is always created first, the suffix later (and if removal applies - to the line, the order is reversed: the suffix is removed first, the prefix later). Lines that take globs are - applied after those accepting no globs. If multiple operations shall be applied on the same file (such as ACL, - xattr, file attribute adjustments), these are always done in the same fixed order. Except for those cases, the - files/directories are processed in the order they are listed. + /usr/lib/tmpfiles.d. Files in /etc/tmpfiles.d are reserved for + the local administrator, who may use this logic to override the configuration files installed by vendor + packages. All configuration files are sorted by their filename in lexicographic order, regardless of + which of the directories they reside in. If multiple files specify the same path, the entry in the file + with the lexicographically earliest name will be applied (note that lines suppressed due to the + ! are filtered before application, meaning that if an early line carries the + exclamation mark and is suppressed because of that, a later line matching in path will be applied). All + other conflicting entries will be logged as errors. When two lines are prefix path and suffix path of + each other, then the prefix line is always created first, the suffix later (and if removal applies to the + line, the order is reversed: the suffix is removed first, the prefix later). Lines that take globs are + applied after those accepting no globs. If multiple operations shall be applied on the same file (such as + ACL, xattr, file attribute adjustments), these are always done in the same fixed order. Except for those + cases, the files/directories are processed in the order they are listed. If the administrator wants to disable a configuration file supplied by the vendor, the recommended way is to place a symlink @@ -153,8 +156,8 @@ L /tmp/foobar - - - - /dev/null Type - The type consists of a single letter and optionally an - exclamation mark and/or minus sign. + The type consists of a single letter and optionally an exclamation mark (!) + and/or minus sign (-). The following line types are understood: @@ -452,13 +455,10 @@ L /tmp/foobar - - - - /dev/null - If the exclamation mark is used, this line is only safe to - execute during boot, and can break a running system. Lines - without the exclamation mark are presumed to be safe to execute - at any time, e.g. on package upgrades. - systemd-tmpfiles will execute line with an - exclamation mark only if option is - given. + If the exclamation mark (!) is used, this line is only safe to execute during + boot, and can break a running system. Lines without the exclamation mark are presumed to be safe to + execute at any time, e.g. on package upgrades. systemd-tmpfiles will take lines with + an exclamation mark only into consideration, if the option is given. For example: # Make sure these are created by default so that nobody else can @@ -470,9 +470,8 @@ r! /tmp/.X[0-9]*-lock running system, and will only be executed with . - If the minus sign is used, this line failing to run - successfully during create (and only create) will not cause - the execution of systemd-tmpfiles to return + If the minus sign (-) is used, this line failing to run successfully during + create (and only create) will not cause the execution of systemd-tmpfiles to return an error. For example: diff --git a/meson.build b/meson.build index fc216d22d..c09115e06 100644 --- a/meson.build +++ b/meson.build @@ -423,6 +423,9 @@ add_project_arguments(cc.get_supported_arguments(basic_disabled_warnings), langu add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c') add_project_link_arguments(cc.get_supported_link_arguments(possible_link_flags), language : 'c') +have = cc.has_argument('-Wzero-length-bounds') +conf.set10('HAVE_ZERO_LENGTH_BOUNDS', have) + if cc.compiles(''' #include #include @@ -671,8 +674,13 @@ conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme) time_epoch = get_option('time-epoch') if time_epoch == -1 - NEWS = files('NEWS') - time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout().to_int() + source_date_epoch = run_command('sh', ['-c', 'echo "$SOURCE_DATE_EPOCH"']).stdout().strip() + if source_date_epoch != '' + time_epoch = source_date_epoch.to_int() + else + NEWS = files('NEWS') + time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout().to_int() + endif endif conf.set('TIME_EPOCH', time_epoch) diff --git a/shell-completion/zsh/_resolvectl b/shell-completion/zsh/_resolvectl index 7458f436a..3ac069c6b 100644 --- a/shell-completion/zsh/_resolvectl +++ b/shell-completion/zsh/_resolvectl @@ -53,9 +53,10 @@ openpgp:"Retrieve openpgp keys for an email" query:"Resolve domain names, IPv4 and IPv6 addresses" reset-server-features:"Flushes all feature level information the resolver has learned about specific servers" - reset-statistics:"Resets the statistics counter show in statistics to zero" + reset-statistics:"Resets the statistics counter shown in statistics to zero" revert:"Revert the per-interfce DNS configuration" service:"Resolve DNS-SD and SRV services" + statistics:"Show resolver statistics" status:"Show the global and per-link DNS settings currently in effect" tlsa:"Query tlsa public keys stored as TLSA resource records" ) @@ -78,10 +79,6 @@ _arguments \ '--service[Resolve services]' \ '--service-address=no[Do not resolve address for services]' \ '--service-txt=no[Do not resolve TXT records for services]' \ - '--openpgp[Query OpenPGP public key]' \ - '--tlsa[Query TLS public key]' \ '--cname=no[Do not follow CNAME redirects]' \ '--search=no[Do not use search domains]' \ - '--statistics[Show resolver statistics]' \ - '--reset-statistics[Reset resolver statistics]' \ '*::default: _resolvectl_commands' diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in index 66bf03d05..1b6f9f083 100644 --- a/shell-completion/zsh/_systemctl.in +++ b/shell-completion/zsh/_systemctl.in @@ -221,7 +221,11 @@ __systemctl() _systemctl_failed_units() {_sys_failed_units=( ${${(f)"$(__systemctl list-units --state=failed "$PREFIX*" )"}%% *} ) } (( $+functions[_systemctl_unit_state] )) || - _systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files "$PREFIX*" ) ) } + _systemctl_unit_state() { + setopt localoptions extendedglob + typeset -gA _sys_unit_state + _sys_unit_state=( ${=${${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}%%[[:space:]]#}% *} ) + } local fun # Completion functions for ALL_UNITS diff --git a/shell-completion/zsh/_systemd-analyze b/shell-completion/zsh/_systemd-analyze index 89ba46c95..75e72439f 100644 --- a/shell-completion/zsh/_systemd-analyze +++ b/shell-completion/zsh/_systemd-analyze @@ -27,6 +27,16 @@ _describe -t state 'state' _states || compadd "$@" } +(( $+functions[_systemd-analyze_cat-config] )) || + _systemd-analyze_cat-config() { + _files -W '(/run/systemd/ /etc/systemd/ /usr/lib/systemd/)' -P 'systemd/' + } + +(( $+functions[_systemd-analyze_security] )) || + _systemd-analyze_security() { + _sd_unit_files + } + (( $+functions[_systemd-analyze_commands] )) || _systemd-analyze_commands(){ local -a _systemd_analyze_cmds @@ -38,13 +48,20 @@ 'plot:Output SVG graphic showing service initialization' 'dot:Dump dependency graph (in dot(1) format)' 'dump:Dump server status' + 'cat-config:Cat systemd config files' + 'unit-files:List files and symlinks for units' 'unit-paths:List unit load paths' - 'log-level:Get/set systemd log threshold' - 'log-target:Get/set systemd log target' - 'service-watchdogs:Get/set service watchdog status' + 'exit-status:List known exit statuses' 'syscall-filter:List syscalls in seccomp filter' + 'condition:Evaluate Condition*= and Assert*= assignments' 'verify:Check unit files for correctness' 'calendar:Validate repetitive calendar time events' + 'timestamp:Parse a systemd syntax timestamp' + 'timespan:Parse a systemd syntax timespan' + 'security:Analyze security settings of a service' + # 'log-level:Get/set systemd log threshold' + # 'log-target:Get/set systemd log target' + # 'service-watchdogs:Get/set service watchdog status' ) if (( CURRENT == 1 )); then diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c index 7d94c55a6..54431f5d0 100644 --- a/src/basic/blockdev-util.c +++ b/src/basic/blockdev-util.c @@ -29,6 +29,8 @@ int block_get_whole_disk(dev_t d, dev_t *ret) { *ret = d; return 0; } + if (errno != ENOENT) + return -errno; /* If it is a partition find the originating device */ xsprintf_sys_block_path(p, "/partition", d); diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index 9dbebfa16..ac96eabc0 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -107,6 +107,18 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) { unsigned long i; int r; + /* Remove capabilities requested in ambient set, but not in the bounding set */ + for (i = 0; i <= cap_last_cap(); i++) { + if (set == 0) + break; + + if (FLAGS_SET(set, (UINT64_C(1) << i)) && prctl(PR_CAPBSET_READ, i) != 1) { + log_debug("Ambient capability %s requested but missing from bounding set," + " suppressing automatically.", capability_to_name(i)); + set &= ~(UINT64_C(1) << i); + } + } + /* Add the capabilities to the ambient set (an possibly also the inheritable set) */ /* Check that we can use PR_CAP_AMBIENT or quit early. */ diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 54fc6ecf8..752133a8d 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1989,6 +1989,9 @@ int cg_unified_cached(bool flush) { unified_cache = CGROUP_UNIFIED_NONE; } } + } else if (F_TYPE_EQUAL(fs.f_type, SYSFS_MAGIC)) { + return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM), + "No filesystem is currently mounted on /sys/fs/cgroup."); } else return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM), "Unknown filesystem type %llx mounted on /sys/fs/cgroup.", diff --git a/src/basic/fileio.c b/src/basic/fileio.c index ec9d76688..de5bd78b5 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -381,7 +381,7 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re break; } - if (errno != -EINTR) + if (errno != EINTR) return -errno; } diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 558cafbca..ef3b5a518 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -692,28 +692,30 @@ int unlink_or_warn(const char *filename) { int inotify_add_watch_fd(int fd, int what, uint32_t mask) { char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; - int r; + int wd; /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */ xsprintf(path, "/proc/self/fd/%i", what); - r = inotify_add_watch(fd, path, mask); - if (r < 0) + wd = inotify_add_watch(fd, path, mask); + if (wd < 0) return -errno; - return r; + return wd; } int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) { + int wd; - if (inotify_add_watch(fd, pathname, mask) < 0) { + wd = inotify_add_watch(fd, pathname, mask); + if (wd < 0) { if (errno == ENOSPC) return log_error_errno(errno, "Failed to add a watch for %s: inotify watch limit reached", pathname); return log_error_errno(errno, "Failed to add a watch for %s: %m", pathname); } - return 0; + return wd; } static bool unsafe_transition(const struct stat *a, const struct stat *b) { diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c index e3aa6c2e1..1e7e301e0 100644 --- a/src/basic/glob-util.c +++ b/src/basic/glob-util.c @@ -61,11 +61,11 @@ int glob_exists(const char *path) { return true; } -int glob_extend(char ***strv, const char *path) { +int glob_extend(char ***strv, const char *path, int flags) { _cleanup_globfree_ glob_t g = {}; int k; - k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g); + k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE|flags, &g); if (k < 0) return k; diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h index 8b1bb02be..3d5f54350 100644 --- a/src/basic/glob-util.h +++ b/src/basic/glob-util.h @@ -11,7 +11,7 @@ int safe_glob(const char *path, int flags, glob_t *pglob); int glob_exists(const char *path); -int glob_extend(char ***strv, const char *path); +int glob_extend(char ***strv, const char *path, int flags); #define _cleanup_globfree_ _cleanup_(globfree) diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c index 5e425b023..96f7b9ed0 100644 --- a/src/basic/hexdecoct.c +++ b/src/basic/hexdecoct.c @@ -599,13 +599,13 @@ ssize_t base64mem(const void *p, size_t l, char **out) { static int base64_append_width( char **prefix, int plen, - const char *sep, int indent, + char sep, int indent, const void *p, size_t l, int width) { _cleanup_free_ char *x = NULL; char *t, *s; - ssize_t len, slen, avail, line, lines; + ssize_t len, avail, line, lines; len = base64mem(p, l, &x); if (len <= 0) @@ -613,21 +613,20 @@ static int base64_append_width( lines = DIV_ROUND_UP(len, width); - slen = strlen_ptr(sep); - if (plen >= SSIZE_MAX - 1 - slen || - lines > (SSIZE_MAX - plen - 1 - slen) / (indent + width + 1)) + if ((size_t) plen >= SSIZE_MAX - 1 - 1 || + lines > (SSIZE_MAX - plen - 1 - 1) / (indent + width + 1)) return -ENOMEM; - t = realloc(*prefix, (ssize_t) plen + 1 + slen + (indent + width + 1) * lines); + t = realloc(*prefix, (ssize_t) plen + 1 + 1 + (indent + width + 1) * lines); if (!t) return -ENOMEM; - memcpy_safe(t + plen, sep, slen); + t[plen] = sep; - for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) { + for (line = 0, s = t + plen + 1, avail = len; line < lines; line++) { int act = MIN(width, avail); - if (line > 0 || sep) { + if (line > 0 || sep == '\n') { memset(s, ' ', indent); s += indent; } @@ -650,10 +649,10 @@ int base64_append( if (plen > width / 2 || plen + indent > width) /* leave indent on the left, keep last column free */ - return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1); + return base64_append_width(prefix, plen, '\n', indent, p, l, width - indent - 1); else /* leave plen on the left, keep last column free */ - return base64_append_width(prefix, plen, " ", plen, p, l, width - plen - 1); + return base64_append_width(prefix, plen, ' ', plen + 1, p, l, width - plen - 1); } static int unbase64_next(const char **p, size_t *l) { diff --git a/src/basic/limits-util.c b/src/basic/limits-util.c index a74d8197e..3242e9c7f 100644 --- a/src/basic/limits-util.c +++ b/src/basic/limits-util.c @@ -41,6 +41,11 @@ uint64_t physical_memory(void) { } if (r > 0) { r = cg_get_attribute("memory", root, "memory.max", &value); + if (r == -ENOENT) /* Field does not exist on the system's top-level cgroup, hence don't + * complain. (Note that it might exist on our own root though, if we live + * in a cgroup namespace, hence check anyway instead of not even + * trying.) */ + return mem; if (r < 0) { log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m"); return mem; diff --git a/src/basic/path-util.c b/src/basic/path-util.c index ba13de01f..986dfe94a 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -1051,7 +1051,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version) if (!path) return -ENOMEM; - r = glob_extend(&names, path); + r = glob_extend(&names, path, 0); if (r == -ENOENT) continue; if (r < 0) diff --git a/src/basic/random-util.c b/src/basic/random-util.c index eae488ae5..8717a49ba 100644 --- a/src/basic/random-util.c +++ b/src/basic/random-util.c @@ -19,6 +19,7 @@ #endif #include "alloc-util.h" +#include "errno-util.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" @@ -237,7 +238,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { have_syscall = true; return -EIO; - } else if (errno == ENOSYS) { + } else if (ERRNO_IS_NOT_SUPPORTED(errno)) { /* We lack the syscall, continue with reading from /dev/urandom. */ have_syscall = false; break; diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index ad467ab85..b797a5218 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -901,9 +901,9 @@ ssize_t receive_one_fd_iov( * combination with send_one_fd(). */ - k = recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags); + k = recvmsg_safe(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags); if (k < 0) - return (ssize_t) -errno; + return k; CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == SOL_SOCKET && @@ -915,12 +915,13 @@ ssize_t receive_one_fd_iov( } } - if (!found) + if (!found) { cmsg_close_all(&mh); - /* If didn't receive an FD or any data, return an error. */ - if (k == 0 && !found) - return -EIO; + /* If didn't receive an FD or any data, return an error. */ + if (k == 0) + return -EIO; + } if (found) *ret_fd = *(int*) CMSG_DATA(found); @@ -1171,3 +1172,24 @@ int socket_bind_to_ifindex(int fd, int ifindex) { return socket_bind_to_ifname(fd, ifname); } + +ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) { + ssize_t n; + + /* A wrapper around recvmsg() that checks for MSG_CTRUNC, and turns it into an error, in a reasonably + * safe way, closing any SCM_RIGHTS fds in the error path. + * + * Note that unlike our usual coding style this might modify *msg on failure. */ + + n = recvmsg(sockfd, msg, flags); + if (n < 0) + return -errno; + + if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC)) { + cmsg_close_all(msg); + return -EXFULL; /* a recognizable error code */ + } + + return n; + +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 24e121395..95643135d 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -199,3 +199,5 @@ static inline int setsockopt_int(int fd, int level, int optname, int value) { int socket_bind_to_ifname(int fd, const char *ifname); int socket_bind_to_ifindex(int fd, int ifindex); + +ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 8ef90e96b..4b3d84034 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -94,10 +94,10 @@ bool null_or_empty(struct stat *st) { if (S_ISREG(st->st_mode) && st->st_size <= 0) return true; - /* We don't want to hardcode the major/minor of /dev/null, - * hence we do a simpler "is this a device node?" check. */ + /* We don't want to hardcode the major/minor of /dev/null, hence we do a simpler "is this a character + * device node?" check. */ - if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + if (S_ISCHR(st->st_mode)) return true; return false; @@ -108,6 +108,10 @@ int null_or_empty_path(const char *fn) { assert(fn); + /* If we have the path, let's do an easy text comparison first. */ + if (path_equal(fn, "/dev/null")) + return true; + if (stat(fn, &st) < 0) return -errno; @@ -178,13 +182,12 @@ int fd_is_fs_type(int fd, statfs_f_type_t magic_value) { } int path_is_fs_type(const char *path, statfs_f_type_t magic_value) { - _cleanup_close_ int fd = -1; + struct statfs s; - fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH); - if (fd < 0) + if (statfs(path, &s) < 0) return -errno; - return fd_is_fs_type(fd, magic_value); + return is_fs_type(&s, magic_value); } bool is_temporary_fs(const struct statfs *s) { diff --git a/src/basic/strv.h b/src/basic/strv.h index e7c2b1a60..637a98121 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -101,7 +101,7 @@ bool strv_overlap(char * const *a, char * const *b) _pure_; (s)--) #define STRV_FOREACH_PAIR(x, y, l) \ - for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) + for ((x) = (l), (y) = (x) ? (x+1) : NULL; (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) char **strv_sort(char **l); void strv_print(char * const *l); diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 7ff844c78..06aee22dc 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -10,6 +10,7 @@ #include #include "alloc-util.h" +#include "binfmt-util.h" #include "conf-files.h" #include "def.h" #include "fd-util.h" @@ -24,6 +25,7 @@ static bool arg_cat_config = false; static PagerFlags arg_pager_flags = 0; +static bool arg_unregister = false; static int delete_rule(const char *rule) { _cleanup_free_ char *x = NULL, *fn = NULL; @@ -32,18 +34,17 @@ static int delete_rule(const char *rule) { assert(rule); assert(rule[0]); - x = strdup(rule); + e = strchrnul(rule + 1, rule[0]); + x = strndup(rule + 1, e - rule - 1); if (!x) return log_oom(); - e = strchrnul(x+1, x[0]); - *e = 0; - - if (!filename_is_valid(x + 1)) + if (!filename_is_valid(x) || + STR_IN_SET(x, "register", "status")) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Rule file name '%s' is not valid, refusing.", x + 1); + "Rule file name '%s' is not valid, refusing.", x); - fn = path_join("/proc/sys/fs/binfmt_misc", x+1); + fn = path_join("/proc/sys/fs/binfmt_misc", x); if (!fn) return log_oom(); @@ -116,6 +117,7 @@ static int help(void) { " --version Show package version\n" " --cat-config Show configuration files\n" " --no-pager Do not pipe output into a pager\n" + " --unregister Unregister all existing entries\n" "\nSee the %s for details.\n" , program_invocation_short_name , link @@ -129,6 +131,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_CAT_CONFIG, ARG_NO_PAGER, + ARG_UNREGISTER, }; static const struct option options[] = { @@ -136,6 +139,7 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "unregister", no_argument, NULL, ARG_UNREGISTER }, {} }; @@ -162,6 +166,10 @@ static int parse_argv(int argc, char *argv[]) { arg_pager_flags |= PAGER_DISABLE; break; + case ARG_UNREGISTER: + arg_unregister = true; + break; + case '?': return -EINVAL; @@ -169,9 +177,9 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (arg_cat_config && argc > optind) + if ((arg_unregister || arg_cat_config) && argc > optind) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Positional arguments are not allowed with --cat-config"); + "Positional arguments are not allowed with --cat-config or --unregister"); return 1; } @@ -189,6 +197,9 @@ static int run(int argc, char *argv[]) { r = 0; + if (arg_unregister) + return disable_binfmt(); + if (argc > optind) { int i; diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 5874b9ec6..352502183 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -517,7 +517,7 @@ static int copy_file_with_version_check(const char *from, const char *to, bool f if (!force) { fd_to = open(to, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd_to < 0) { - if (errno != -ENOENT) + if (errno != ENOENT) return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", to); } else { r = version_check(fd_from, from, fd_to, to); diff --git a/src/core/automount.c b/src/core/automount.c index 0b3f498bf..99b4eb2c8 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -152,6 +152,10 @@ static int automount_add_default_dependencies(Automount *a) { if (!MANAGER_IS_SYSTEM(UNIT(a)->manager)) return 0; + r = unit_add_dependency_by_name(UNIT(a), UNIT_BEFORE, SPECIAL_LOCAL_FS_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + r = unit_add_dependency_by_name(UNIT(a), UNIT_AFTER, SPECIAL_LOCAL_FS_PRE_TARGET, true, UNIT_DEPENDENCY_DEFAULT); if (r < 0) return r; diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c index 8a2984a2d..eca27f4d7 100644 --- a/src/core/core-varlink.c +++ b/src/core/core-varlink.c @@ -289,11 +289,13 @@ int manager_varlink_init(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to register varlink methods: %m"); - (void) mkdir_p("/run/systemd/userdb", 0755); + if (!MANAGER_IS_TEST_RUN(m)) { + (void) mkdir_p("/run/systemd/userdb", 0755); - r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666); - if (r < 0) - return log_error_errno(r, "Failed to bind to varlink socket: %m"); + r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666); + if (r < 0) + return log_error_errno(r, "Failed to bind to varlink socket: %m"); + } r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) diff --git a/src/core/device.c b/src/core/device.c index 06bbbf8d2..45149e755 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -1064,7 +1064,6 @@ const UnitVTable device_vtable = { "Device\0" "Install\0", - .refuse_after = true, .gc_jobs = true, .init = device_init, diff --git a/src/core/execute.c b/src/core/execute.c index 2a65ee3fb..2cdf70866 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1647,8 +1647,6 @@ static int apply_lock_personality(const Unit* u, const ExecContext *c) { #endif static int apply_protect_hostname(const Unit *u, const ExecContext *c, int *ret_exit_status) { - int r; - assert(u); assert(c); @@ -1668,6 +1666,8 @@ static int apply_protect_hostname(const Unit *u, const ExecContext *c, int *ret_ log_unit_warning(u, "ProtectHostname=yes is configured, but the kernel does not support UTS namespaces, ignoring namespace setup."); #if HAVE_SECCOMP + int r; + if (skip_seccomp_unavailable(u, "ProtectHostname=")) return 0; @@ -1820,12 +1820,13 @@ static int build_environment( tty_path = exec_context_tty_path(c); - /* If we are forked off PID 1 and we are supposed to operate on /dev/console, then let's try to inherit - * the $TERM set for PID 1. This is useful for containers so that the $TERM the container manager - * passes to PID 1 ends up all the way in the console login shown. */ + /* If we are forked off PID 1 and we are supposed to operate on /dev/console, then let's try + * to inherit the $TERM set for PID 1. This is useful for containers so that the $TERM the + * container manager passes to PID 1 ends up all the way in the console login shown. */ - if (path_equal(tty_path, "/dev/console") && getppid() == 1) + if (path_equal_ptr(tty_path, "/dev/console") && getppid() == 1) term = getenv("TERM"); + if (!term) term = default_term_for_tty(tty_path); diff --git a/src/core/job.c b/src/core/job.c index 9fe30359d..bcfdb9d37 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -516,12 +516,20 @@ static bool job_is_runnable(Job *j) { return true; HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) - if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0) + if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0) { + log_unit_debug(j->unit, + "starting held back, waiting for: %s", + other->id); return false; + } HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) - if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0) + if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0) { + log_unit_debug(j->unit, + "stopping held back, waiting for: %s", + other->id); return false; + } return true; } diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index f3fe73535..d01e4cffb 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2850,7 +2850,7 @@ int config_parse_syscall_filter( void *userdata) { ExecContext *c = data; - const Unit *u = userdata; + _unused_ const Unit *u = userdata; bool invert = false; const char *p; int r; @@ -4729,7 +4729,7 @@ int unit_load_fragment(Unit *u) { &u->manager->unit_name_map, &u->manager->unit_path_cache); if (r < 0) - log_error_errno(r, "Failed to rebuild name map: %m"); + return log_error_errno(r, "Failed to rebuild name map: %m"); r = unit_file_find_fragment(u->manager->unit_id_map, u->manager->unit_name_map, @@ -5090,7 +5090,7 @@ int config_parse_swap_priority( r = safe_atoi(rvalue, &priority); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap pririty '%s', ignoring.", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap priority '%s', ignoring.", rvalue); return 0; } diff --git a/src/core/main.c b/src/core/main.c index 3c6b66e89..9efd92f26 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1196,6 +1196,7 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { static int bump_rlimit_memlock(struct rlimit *saved_rlimit) { struct rlimit new_rlimit; + uint64_t mm; int r; /* BPF_MAP_TYPE_LPM_TRIE bpf maps are charged against RLIMIT_MEMLOCK, even if we have CAP_IPC_LOCK which should @@ -1206,9 +1207,12 @@ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) { * must be unsigned, hence this is a given, but let's make this clear here. */ assert_cc(RLIM_INFINITY > 0); + mm = physical_memory() / 8; /* Let's scale how much we allow to be locked by the amount of physical + * RAM. We allow an eigth to be locked by us, just to pick a value. */ + new_rlimit = (struct rlimit) { - .rlim_cur = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_cur), - .rlim_max = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_max), + .rlim_cur = MAX3(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_cur, mm), + .rlim_max = MAX3(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_max, mm), }; if (saved_rlimit->rlim_max >= new_rlimit.rlim_cur && diff --git a/src/core/manager.c b/src/core/manager.c index 25afdbea0..4412e7a84 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -312,9 +312,9 @@ static int manager_check_ask_password(Manager *m) { m->ask_password_inotify_fd, EPOLLIN, manager_dispatch_ask_password_fd, m); if (r < 0) { - log_error_errno(errno, "Failed to add event source for /run/systemd/ask-password: %m"); + log_error_errno(r, "Failed to add event source for /run/systemd/ask-password: %m"); manager_close_ask_password(m); - return -errno; + return r; } (void) sd_event_source_set_description(m->ask_password_event_source, "manager-ask-password"); @@ -1967,7 +1967,6 @@ int manager_load_unit_prepare( int r; assert(m); - assert(name || path); assert(_ret); /* This will prepare the unit for loading, but not actually @@ -1976,8 +1975,13 @@ int manager_load_unit_prepare( if (path && !is_path(path)) return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); - if (!name) + if (!name) { + /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to + * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(), + * but this cannot be possible in any code path (See #6119). */ + assert_se(path); name = basename(path); + } t = unit_name_to_type(name); @@ -2359,20 +2363,20 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return 0; } - n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC); - if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; /* Spurious wakeup, try again */ - - /* If this is any other, real error, then let's stop processing this socket. This of course means we - * won't take notification messages anymore, but that's still better than busy looping around this: - * being woken up over and over again but being unable to actually read the message off the socket. */ - return log_error_errno(errno, "Failed to receive notification message: %m"); - } + n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC); + if (IN_SET(n, -EAGAIN, -EINTR)) + return 0; /* Spurious wakeup, try again */ + if (n < 0) + /* If this is any other, real error, then let's stop processing this socket. This of course + * means we won't take notification messages anymore, but that's still better than busy + * looping around this: being woken up over and over again but being unable to actually read + * the message off the socket. */ + return log_error_errno(n, "Failed to receive notification message: %m"); CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + assert(!fd_array); fd_array = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); @@ -2380,6 +2384,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + assert(!ucred); ucred = (struct ucred*) CMSG_DATA(cmsg); } } diff --git a/src/core/mount.c b/src/core/mount.c index 1c4aefd73..38024d1d2 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -66,6 +66,14 @@ static bool MOUNT_STATE_WITH_PROCESS(MountState state) { MOUNT_CLEANING); } +static bool mount_is_automount(const MountParameters *p) { + assert(p); + + return fstab_test_option(p->options, + "comment=systemd.automount\0" + "x-systemd.automount\0"); +} + static bool mount_is_network(const MountParameters *p) { assert(p); @@ -78,6 +86,15 @@ static bool mount_is_network(const MountParameters *p) { return false; } +static bool mount_is_nofail(const Mount *m) { + assert(m); + + if (!m->from_fragment) + return false; + + return fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0"); +} + static bool mount_is_loop(const MountParameters *p) { assert(p); @@ -400,42 +417,72 @@ static bool mount_is_extrinsic(Mount *m) { MountParameters *p; assert(m); - /* Returns true for all units that are "magic" and should be excluded from the usual start-up and shutdown - * dependencies. We call them "extrinsic" here, as they are generally mounted outside of the systemd dependency - * logic. We shouldn't attempt to manage them ourselves but it's fine if the user operates on them with us. */ + /* Returns true for all units that are "magic" and should be excluded from the usual + * start-up and shutdown dependencies. We call them "extrinsic" here, as they are generally + * mounted outside of the systemd dependency logic. We shouldn't attempt to manage them + * ourselves but it's fine if the user operates on them with us. */ - if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) /* We only automatically manage mounts if we are in system mode */ + /* We only automatically manage mounts if we are in system mode */ + if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) return true; if (UNIT(m)->perpetual) /* All perpetual units never change state */ return true; - if (PATH_IN_SET(m->where, /* Don't bother with the OS data itself */ - "/", /* (strictly speaking redundant: should already be covered by the perpetual flag check above) */ - "/usr", - "/etc")) - return true; - - if (PATH_STARTSWITH_SET(m->where, - "/run/initramfs", /* This should stay around from before we boot until after we shutdown */ - "/proc", /* All of this is API VFS */ - "/sys", /* … dito … */ - "/dev")) /* … dito … */ - return true; - - /* If this is an initrd mount, and we are not in the initrd, then leave this around forever, too. */ p = get_mount_parameters(m); - if (p && fstab_test_option(p->options, "x-initrd.mount\0") && !in_initrd()) + if (p && fstab_is_extrinsic(m->where, p->options)) return true; return false; } +static int mount_add_default_ordering_dependencies( + Mount *m, + MountParameters *p, + UnitDependencyMask mask) { + + const char *after, *before, *e; + int r; + + assert(m); + + e = path_startswith(m->where, "/sysroot"); + if (e && in_initrd()) { + /* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW, + * it's not technically part of the basic initrd filesystem itself, and so + * shouldn't inherit the default Before=local-fs.target dependency. */ + + after = NULL; + before = isempty(e) ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_INITRD_FS_TARGET; + + } else if (mount_is_network(p)) { + after = SPECIAL_REMOTE_FS_PRE_TARGET; + before = SPECIAL_REMOTE_FS_TARGET; + + } else { + after = SPECIAL_LOCAL_FS_PRE_TARGET; + before = SPECIAL_LOCAL_FS_TARGET; + } + + if (!mount_is_nofail(m) && !mount_is_automount(p)) { + r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask); + if (r < 0) + return r; + } + + if (after) { + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask); + if (r < 0) + return r; + } + + return unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, + SPECIAL_UMOUNT_TARGET, true, mask); +} + static int mount_add_default_dependencies(Mount *m) { - const char *after, *before; UnitDependencyMask mask; MountParameters *p; - bool nofail; int r; assert(m); @@ -443,9 +490,10 @@ static int mount_add_default_dependencies(Mount *m) { if (!UNIT(m)->default_dependencies) return 0; - /* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are guaranteed to stay - * mounted the whole time, since our system is on it. Also, don't bother with anything mounted below virtual - * file systems, it's also going to be virtual, and hence not worth the effort. */ + /* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are + * guaranteed to stay mounted the whole time, since our system is on it. Also, don't + * bother with anything mounted below virtual file systems, it's also going to be virtual, + * and hence not worth the effort. */ if (mount_is_extrinsic(m)) return 0; @@ -454,51 +502,31 @@ static int mount_add_default_dependencies(Mount *m) { return 0; mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT; - nofail = m->from_fragment ? fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0") : false; + + r = mount_add_default_ordering_dependencies(m, p, mask); + if (r < 0) + return r; if (mount_is_network(p)) { - /* We order ourselves after network.target. This is - * primarily useful at shutdown: services that take - * down the network should order themselves before - * network.target, so that they are shut down only - * after this mount unit is stopped. */ + /* We order ourselves after network.target. This is primarily useful at shutdown: + * services that take down the network should order themselves before + * network.target, so that they are shut down only after this mount unit is + * stopped. */ r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, true, mask); if (r < 0) return r; - /* We pull in network-online.target, and order - * ourselves after it. This is useful at start-up to - * actively pull in tools that want to be started - * before we start mounting network file systems, and - * whose purpose it is to delay this until the network - * is "up". */ + /* We pull in network-online.target, and order ourselves after it. This is useful + * at start-up to actively pull in tools that want to be started before we start + * mounting network file systems, and whose purpose it is to delay this until the + * network is "up". */ r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, true, mask); if (r < 0) return r; - - after = SPECIAL_REMOTE_FS_PRE_TARGET; - before = SPECIAL_REMOTE_FS_TARGET; - } else { - after = SPECIAL_LOCAL_FS_PRE_TARGET; - before = SPECIAL_LOCAL_FS_TARGET; } - if (!nofail) { - r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask); - if (r < 0) - return r; - } - - r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask); - if (r < 0) - return r; - - r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, mask); - if (r < 0) - return r; - /* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */ if (streq_ptr(p->fstype, "tmpfs")) { r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, true, mask); diff --git a/src/core/namespace.c b/src/core/namespace.c index a461a3cce..90909a07a 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1619,8 +1619,9 @@ int setup_namespace( r = 0; finish: - for (m = mounts; m < mounts + n_mounts; m++) - mount_entry_done(m); + if (n_mounts > 0) + for (m = mounts; m < mounts + n_mounts; m++) + mount_entry_done(m); free(mounts); diff --git a/src/core/path.c b/src/core/path.c index cb75d778a..0adfaa4c0 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -223,11 +223,10 @@ static void path_spec_mkdir(PathSpec *s, mode_t mode) { } static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) { - fprintf(f, - "%s%s: %s\n", - prefix, - path_type_to_string(s->type), - s->path); + const char *type; + + assert_se(type = path_type_to_string(s->type)); + fprintf(f, "%s%s: %s\n", prefix, type, s->path); } void path_spec_done(PathSpec *s) { @@ -607,14 +606,16 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) { (void) serialize_item(f, "result", path_result_to_string(p->result)); LIST_FOREACH(spec, s, p->specs) { + const char *type; _cleanup_free_ char *escaped = NULL; escaped = cescape(s->path); if (!escaped) return log_oom(); + assert_se(type = path_type_to_string(s->type)); (void) serialize_item_format(f, "path-spec", "%s %i %s", - path_type_to_string(s->type), + type, s->previous_exists, s->path); } diff --git a/src/core/unit.c b/src/core/unit.c index 97e1b0004..c30618355 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2704,7 +2704,7 @@ void unit_unwatch_pid(Unit *u, pid_t pid) { if (m == 0) { /* The array is now empty, remove the entire entry */ - assert(hashmap_remove(u->manager->watch_pids, PID_TO_PTR(-pid)) == array); + assert_se(hashmap_remove(u->manager->watch_pids, PID_TO_PTR(-pid)) == array); free(array); } } @@ -2957,13 +2957,10 @@ int unit_add_dependency( return 0; } - if (d == UNIT_AFTER && UNIT_VTABLE(u)->refuse_after) { - log_unit_warning(u, "Requested dependency After=%s ignored (%s units cannot be delayed).", other->id, unit_type_to_string(u->type)); - return 0; - } - - if (d == UNIT_BEFORE && UNIT_VTABLE(other)->refuse_after) { - log_unit_warning(u, "Requested dependency Before=%s ignored (%s units cannot be delayed).", other->id, unit_type_to_string(other->type)); + /* Note that ordering a device unit after a unit is permitted since it + * allows to start its job running timeout at a specific time. */ + if (d == UNIT_BEFORE && other->type == UNIT_DEVICE) { + log_unit_warning(u, "Dependency Before=%s ignored (.device units cannot be delayed)", other->id); return 0; } diff --git a/src/core/unit.h b/src/core/unit.h index 2e103f7ab..eb0a34477 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -610,9 +610,6 @@ typedef struct UnitVTable { /* True if the unit type knows a failure state, and thus can be source of an OnFailure= dependency */ bool can_fail:1; - /* True if After= dependencies should be refused */ - bool refuse_after:1; - /* True if units of this type shall be startable only once and then never again */ bool once_only:1; @@ -883,8 +880,9 @@ int unit_can_clean(Unit *u, ExecCleanMask *ret_mask); #define log_unit_full(unit, level, error, ...) \ ({ \ const Unit *_u = (unit); \ - _u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \ - log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ + (log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \ + _u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \ + log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ }) #define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 0e9a3c023..6b5124030 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -913,10 +913,10 @@ static int process_socket(int fd) { mh.msg_iov = &iovec; - n = recvmsg(fd, &mh, MSG_CMSG_CLOEXEC); + n = recvmsg_safe(fd, &mh, MSG_CMSG_CLOEXEC); if (n < 0) { free(iovec.iov_base); - r = log_error_errno(errno, "Failed to receive datagram: %m"); + r = log_error_errno(n, "Failed to receive datagram: %m"); goto finish; } @@ -937,15 +937,17 @@ static int process_socket(int fd) { } if (!found) { - log_error("Coredump file descriptor missing."); - r = -EBADMSG; + cmsg_close_all(&mh); + r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Coredump file descriptor missing."); goto finish; } assert(input_fd < 0); input_fd = *(int*) CMSG_DATA(found); break; - } + } else + cmsg_close_all(&mh); /* Add trailing NUL byte, in case these are strings */ ((char*) iovec.iov_base)[n] = 0; @@ -954,8 +956,6 @@ static int process_socket(int fd) { r = iovw_put(&iovw, iovec.iov_base, iovec.iov_len); if (r < 0) goto finish; - - cmsg_close_all(&mh); } /* Make sure we got all data we really need */ diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index a84826817..4172e8e84 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -237,7 +237,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_FILE: - r = glob_extend(&arg_file, optarg); + r = glob_extend(&arg_file, optarg, GLOB_NOCHECK); if (r < 0) return log_error_errno(r, "Failed to add paths: %m"); break; diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 5a0a87175..bc1bcb278 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -385,12 +385,6 @@ static int add_mount( "SourcePath=%s\n", source); - /* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW, it's not - * technically part of the basic initrd filesystem itself, and so shouldn't inherit the default - * Before=local-fs.target dependency. */ - if (in_initrd() && path_startswith(where, "/sysroot")) - fprintf(f, "DefaultDependencies=no\n"); - if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !(flags & AUTOMOUNT) && fstab_test_yes_no_option(opts, "bg\0" "fg\0")) { /* The default retry timeout that mount.nfs uses for 'bg' mounts @@ -405,9 +399,6 @@ static int add_mount( SET_FLAG(flags, NOFAIL, true); } - if (!(flags & NOFAIL) && !(flags & AUTOMOUNT)) - fprintf(f, "Before=%s\n", post); - if (!(flags & AUTOMOUNT) && opts) { r = write_after(f, opts); if (r < 0) @@ -529,8 +520,6 @@ static int add_mount( "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", source); - fprintf(f, "Before=%s\n", post); - if (opts) { r = write_after(f, opts); if (r < 0) diff --git a/src/home/homectl.c b/src/home/homectl.c index 66d4bb6bd..a8925b939 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -192,9 +192,9 @@ static int list_homes(int argc, char *argv[], void *userdata) { if (arg_legend && !arg_json) { if (table_get_rows(table) > 1) - printf("\n%zu homes listed.\n", table_get_rows(table) - 1); + printf("\n%zu home areas listed.\n", table_get_rows(table) - 1); else - printf("No homes.\n"); + printf("No home areas.\n"); } return 0; @@ -2263,20 +2263,20 @@ static int help(int argc, char *argv[], void *userdata) { printf("%1$s [OPTIONS...] COMMAND ...\n\n" "%2$sCreate, manipulate or inspect home directories.%3$s\n" "\n%4$sCommands:%5$s\n" - " list List homes\n" - " activate USER… Activate home\n" - " deactivate USER… Deactivate home\n" - " inspect USER… Inspect home\n" - " authenticate USER… Authenticate home\n" + " list List home areas\n" + " activate USER… Activate a home area\n" + " deactivate USER… Deactivate a home area\n" + " inspect USER… Inspect a home area\n" + " authenticate USER… Authenticate a home area\n" " create USER Create a home area\n" " remove USER… Remove a home area\n" " update USER Update a home area\n" " passwd USER Change password of a home area\n" " resize USER SIZE Resize a home area\n" - " lock USER… Temporarily lock an active home\n" - " unlock USER… Unlock a temporarily locked home\n" - " lock-all Lock all suitable homes\n" - " with USER [COMMAND…] Run shell or command with access to home\n" + " lock USER… Temporarily lock an active home area\n" + " unlock USER… Unlock a temporarily locked home area\n" + " lock-all Lock all suitable home areas\n" + " with USER [COMMAND…] Run shell or command with access to a home area\n" "\n%4$sOptions:%5$s\n" " -h --help Show this help\n" " --version Show package version\n" @@ -2377,7 +2377,7 @@ static int help(int argc, char *argv[], void *userdata) { "\n%4$sCIFS User Record Properties:%5$s\n" " --cifs-domain=DOMAIN CIFS (Windows) domain\n" " --cifs-user-name=USER CIFS (Windows) user name\n" - " --cifs-service=SERVICE CIFS (Windows) service to mount as home\n" + " --cifs-service=SERVICE CIFS (Windows) service to mount as home area\n" "\n%4$sLogin Behaviour User Record Properties:%5$s\n" " --stop-delay=SECS How long to leave user services running after\n" " logout\n" diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index c9bfb64e7..b1153f623 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -976,9 +976,9 @@ static ssize_t read_datagram(int fd, struct ucred *ret_sender, void **ret) { .msg_controllen = sizeof(control), }; - m = recvmsg(fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + m = recvmsg_safe(fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); if (m < 0) - return -errno; + return m; cmsg_close_all(&mh); diff --git a/src/home/homework.c b/src/home/homework.c index 835f86952..cd38d438b 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -985,7 +985,7 @@ static int home_remove(UserRecord *h) { assert(ip); if (stat(ip, &st) < 0) { - if (errno != -ENOENT) + if (errno != ENOENT) return log_error_errno(errno, "Failed to stat() %s: %m", ip); } else { diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c index 9f34ee2ad..5a3c817a5 100644 --- a/src/home/pam_systemd_home.c +++ b/src/home/pam_systemd_home.c @@ -258,8 +258,10 @@ static int handle_generic_user_record_error( if (strv_isempty(secret->password)) r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Password: "); - else - r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Password incorrect or not sufficient for authentication of user %s, please try again: ", user_name); + else { + (void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Password incorrect or not sufficient for authentication of user %s.", user_name); + r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, try again: "); + } if (r != PAM_SUCCESS) return PAM_CONV_ERR; /* no logging here */ @@ -277,10 +279,13 @@ static int handle_generic_user_record_error( } else if (sd_bus_error_has_name(error, BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN)) { _cleanup_(erase_and_freep) char *newp = NULL; - if (strv_isempty(secret->password)) - r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token of user %s not inserted, please enter password: ", user_name); - else - r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Password incorrect or not sufficient, and configured security token of user %s not inserted, please enter password: ", user_name); + if (strv_isempty(secret->password)) { + (void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token of user %s not inserted.", user_name); + r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Try again with password: "); + } else { + (void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Password incorrect or not sufficient, and configured security token of user %s not inserted.", user_name); + r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Try again with password: "); + } if (r != PAM_SUCCESS) return PAM_CONV_ERR; /* no logging here */ @@ -298,7 +303,7 @@ static int handle_generic_user_record_error( } else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_NEEDED)) { _cleanup_(erase_and_freep) char *newp = NULL; - r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Please enter security token PIN: "); + r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN: "); if (r != PAM_SUCCESS) return PAM_CONV_ERR; /* no logging here */ @@ -326,7 +331,8 @@ static int handle_generic_user_record_error( } else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_BAD_PIN)) { _cleanup_(erase_and_freep) char *newp = NULL; - r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN incorrect, please enter PIN for security token of user %s again: ", user_name); + (void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token PIN incorrect for user %s.", user_name); + r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, retry security token PIN: "); if (r != PAM_SUCCESS) return PAM_CONV_ERR; /* no logging here */ @@ -344,7 +350,8 @@ static int handle_generic_user_record_error( } else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_BAD_PIN_FEW_TRIES_LEFT)) { _cleanup_(erase_and_freep) char *newp = NULL; - r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN incorrect (only a few tries left!), please enter PIN for security token of user %s again: ", user_name); + (void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token PIN of user %s incorrect (only a few tries left!)", user_name); + r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, retry security token PIN: "); if (r != PAM_SUCCESS) return PAM_CONV_ERR; /* no logging here */ @@ -362,7 +369,8 @@ static int handle_generic_user_record_error( } else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_BAD_PIN_ONE_TRY_LEFT)) { _cleanup_(erase_and_freep) char *newp = NULL; - r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN incorrect (only one try left!), please enter PIN for security token of user %s again: ", user_name); + (void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token PIN of user %s incorrect (only one try left!)", user_name); + r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, retry security token PIN: "); if (r != PAM_SUCCESS) return PAM_CONV_ERR; /* no logging here */ @@ -411,7 +419,7 @@ static int acquire_home( /* If we already have acquired the fd, let's shortcut this */ r = pam_get_data(handle, "systemd-home-fd", &home_fd_ptr); - if (r == PAM_SUCCESS && PTR_TO_INT(home_fd_ptr) >= 0) + if (r == PAM_SUCCESS && PTR_TO_FD(home_fd_ptr) >= 0) return PAM_SUCCESS; r = pam_acquire_bus_connection(handle, &bus); diff --git a/src/home/pwquality-util.c b/src/home/pwquality-util.c index 5863a229b..fbf6f6c8c 100644 --- a/src/home/pwquality-util.c +++ b/src/home/pwquality-util.c @@ -148,7 +148,7 @@ int suggest_passwords(void) { pwquality_maybe_disable_dictionary(pwq); - suggestions = new0(char*, N_SUGGESTIONS); + suggestions = new0(char*, N_SUGGESTIONS+1); if (!suggestions) return log_oom(); diff --git a/src/import/import-fs.c b/src/import/import-fs.c index 468303a6d..db55fa50d 100644 --- a/src/import/import-fs.c +++ b/src/import/import-fs.c @@ -172,8 +172,8 @@ static int import_fs(int argc, char *argv[], void *userdata) { progress.limit = (RateLimit) { 200*USEC_PER_MSEC, 1 }; /* Hook into SIGINT/SIGTERM, so that we can cancel things then */ - assert(sigaction(SIGINT, &sa, &old_sigint_sa) >= 0); - assert(sigaction(SIGTERM, &sa, &old_sigterm_sa) >= 0); + assert_se(sigaction(SIGINT, &sa, &old_sigint_sa) >= 0); + assert_se(sigaction(SIGTERM, &sa, &old_sigterm_sa) >= 0); r = btrfs_subvol_snapshot_fd_full( fd, @@ -220,8 +220,8 @@ static int import_fs(int argc, char *argv[], void *userdata) { finish: /* Put old signal handlers into place */ - assert(sigaction(SIGINT, &old_sigint_sa, NULL) >= 0); - assert(sigaction(SIGTERM, &old_sigterm_sa, NULL) >= 0); + assert_se(sigaction(SIGINT, &old_sigint_sa, NULL) >= 0); + assert_se(sigaction(SIGTERM, &old_sigterm_sa, NULL) >= 0); return 0; } diff --git a/src/import/importd.c b/src/import/importd.c index 93e704ed6..6e868ee50 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -565,13 +565,11 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void ssize_t n; int r; - n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); - if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - - return -errno; - } + n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (IN_SET(n, -EAGAIN, -EINTR)) + return 0; + if (n < 0) + return (int) n; cmsg_close_all(&msghdr); diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c index 5bfe5acad..da37b3416 100644 --- a/src/journal-remote/journal-upload-journal.c +++ b/src/journal-remote/journal-upload-journal.c @@ -410,5 +410,5 @@ int open_journal_for_upload(Uploader *u, cursor); } - return process_journal_input(u, 1 + !!after_cursor); + return process_journal_input(u, !!after_cursor); } diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 031e82587..221421af4 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -679,7 +679,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_FILE: - r = glob_extend(&arg_file, optarg); + r = glob_extend(&arg_file, optarg, GLOB_NOCHECK); if (r < 0) return log_error_errno(r, "Failed to add paths: %m"); break; diff --git a/src/journal/fsprg.c b/src/journal/fsprg.c index 1dda2149d..0ef3df89d 100644 --- a/src/journal/fsprg.c +++ b/src/journal/fsprg.c @@ -60,7 +60,7 @@ static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) { static gcry_mpi_t mpi_import(const void *buf, size_t buflen) { gcry_mpi_t h; - unsigned len; + _unused_ unsigned len; assert_se(gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0); len = (gcry_mpi_get_nbits(h) + 7) / 8; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e5feec83b..25492dad1 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -705,7 +705,7 @@ static int parse_argv(int argc, char *argv[]) { * STDIN. To avoid confusion we hence don't document this feature. */ arg_file_stdin = true; else { - r = glob_extend(&arg_file, optarg); + r = glob_extend(&arg_file, optarg, GLOB_NOCHECK); if (r < 0) return log_error_errno(r, "Failed to add paths: %m"); } diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c index 339e091df..5c31c4370 100644 --- a/src/journal/journald-audit.c +++ b/src/journal/journald-audit.c @@ -539,10 +539,16 @@ int server_open_audit(Server *s) { if (r < 0) return log_error_errno(r, "Failed to add audit fd to event loop: %m"); - /* We are listening now, try to enable audit */ - r = enable_audit(s->audit_fd, true); - if (r < 0) - log_warning_errno(r, "Failed to issue audit enable call: %m"); + if (s->set_audit >= 0) { + /* We are listening now, try to enable audit if configured so */ + r = enable_audit(s->audit_fd, s->set_audit); + if (r < 0) + log_warning_errno(r, "Failed to issue audit enable call: %m"); + else if (s->set_audit > 0) + log_debug("Auditing in kernel turned on."); + else + log_debug("Auditing in kernel turned off."); + } return 0; } diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf index 0774444e8..c70ac9a5b 100644 --- a/src/journal/journald-gperf.gperf +++ b/src/journal/journald-gperf.gperf @@ -22,6 +22,7 @@ Journal.Storage, config_parse_storage, 0, offsetof(Server, storage Journal.Compress, config_parse_compress, 0, offsetof(Server, compress) Journal.Seal, config_parse_bool, 0, offsetof(Server, seal) Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg) +Journal.Audit, config_parse_tristate, 0, offsetof(Server, set_audit) Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec) # The following is a legacy name for compatibility Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, ratelimit_interval) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 489730df8..072b3d5ae 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1317,29 +1317,35 @@ int server_process_datagram( iovec = IOVEC_MAKE(s->buffer, s->buffer_size - 1); /* Leave room for trailing NUL we add later */ - n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); - if (n < 0) { - if (IN_SET(errno, EINTR, EAGAIN)) - return 0; - - return log_error_errno(errno, "recvmsg() failed: %m"); + n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (IN_SET(n, -EINTR, -EAGAIN)) + return 0; + if (n == -EXFULL) { + log_warning("Got message with truncated control data (too many fds sent?), ignoring."); + return 0; } + if (n < 0) + return log_error_errno(n, "recvmsg() failed: %m"); CMSG_FOREACH(cmsg, &msghdr) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + assert(!ucred); ucred = (struct ucred*) CMSG_DATA(cmsg); - else if (cmsg->cmsg_level == SOL_SOCKET && + } else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_SECURITY) { + assert(!label); label = (char*) CMSG_DATA(cmsg); label_len = cmsg->cmsg_len - CMSG_LEN(0); } else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) + cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) { + assert(!tv); tv = (struct timeval*) CMSG_DATA(cmsg); - else if (cmsg->cmsg_level == SOL_SOCKET && + } else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + assert(!fds); fds = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); } @@ -2208,6 +2214,8 @@ int server_init(Server *s, const char *namespace) { .compress.threshold_bytes = (uint64_t) -1, .seal = true, + .set_audit = true, + .watchdog_usec = USEC_INFINITY, .sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC, diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index f3405e967..b01ade5ae 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -108,6 +108,7 @@ struct Server { JournalCompressOptions compress; bool seal; bool read_kmsg; + int set_audit; bool forward_to_kmsg; bool forward_to_syslog; diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index 609af506a..ad9006217 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -512,8 +512,8 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, goto terminate; } - /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */ - if (s->length + 1 >= s->allocated) { + /* If the buffer is almost full, add room for another 1K */ + if (s->length + 512 >= s->allocated) { if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) { log_oom(); goto terminate; @@ -545,6 +545,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + assert(!ucred); ucred = (struct ucred *)CMSG_DATA(cmsg); break; } diff --git a/src/journal/journald.conf b/src/journal/journald.conf index 2f1c66115..2e1aacd8c 100644 --- a/src/journal/journald.conf +++ b/src/journal/journald.conf @@ -41,3 +41,4 @@ #MaxLevelWall=emerg #LineMax=48K #ReadKMsg=yes +#Audit=yes diff --git a/src/journal/test-audit-type.c b/src/journal/test-audit-type.c index 20e654b59..a8315d063 100644 --- a/src/journal/test-audit-type.c +++ b/src/journal/test-audit-type.c @@ -22,4 +22,5 @@ static void test_audit_type(void) { int main(int argc, char **argv) { test_audit_type(); + return 0; } diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 4122d08d9..b73591539 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1837,7 +1837,7 @@ static int client_receive_message_raw( sd_dhcp_client *client = userdata; _cleanup_free_ DHCPPacket *packet = NULL; - uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; + uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct tpacket_auxdata))]; struct iovec iov = {}; struct msghdr msg = { .msg_iov = &iov, diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 546b5d02c..e8b43ba9b 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -263,7 +263,7 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination, .iov_base = message, .iov_len = len, }; - uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))] = {}; + uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {}; struct msghdr msg = { .msg_name = &dest, .msg_namelen = sizeof(dest.in), @@ -930,7 +930,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, static int server_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_free_ DHCPMessage *message = NULL; - uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))]; + uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))]; sd_dhcp_server *server = userdata; struct iovec iov = {}; struct msghdr msg = { diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 873a2f40f..0d65b3f5b 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -590,8 +590,7 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) { cur->valid_until = valid_until; cur->preferred_until = preferred_until; - log_radv("%s prefix %s/%u preferred %s valid %s", - cur? "Updated": "Added", + log_radv("Updated prefix %s/%u preferred %s valid %s", addr_p, p->opt.prefixlen, format_timespan(time_string_preferred, FORMAT_TIMESPAN_MAX, preferred, USEC_PER_SEC), @@ -691,8 +690,7 @@ _public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int if (valid_until == USEC_INFINITY) return -EOVERFLOW; - log_radv("%s route prefix %s/%u valid %s", - cur? "Updated": "Added", + log_radv("Updated route prefix %s/%u valid %s", strempty(pretty), p->opt.prefixlen, format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, valid, USEC_PER_SEC)); diff --git a/src/libsystemd-network/test-sd-dhcp-lease.c b/src/libsystemd-network/test-sd-dhcp-lease.c index 0f881809a..534cc7856 100644 --- a/src/libsystemd-network/test-sd-dhcp-lease.c +++ b/src/libsystemd-network/test-sd-dhcp-lease.c @@ -87,4 +87,5 @@ int main(int argc, char *argv[]) { test_dhcp_lease_parse_search_domains_no_data(); test_dhcp_lease_parse_search_domains_loops(); test_dhcp_lease_parse_search_domains_wrong_len(); + return 0; } diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 73127dfe0..6a8f94ecc 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -451,7 +451,7 @@ int bus_message_from_header( if (!IN_SET(h->version, 1, 2)) return -EBADMSG; - if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID) + if (h->type <= _SD_BUS_MESSAGE_TYPE_INVALID || h->type >= _SD_BUS_MESSAGE_TYPE_MAX) return -EBADMSG; if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN)) @@ -590,7 +590,7 @@ _public_ int sd_bus_message_new( assert_return(bus, -ENOTCONN); assert_return(bus->state != BUS_UNSET, -ENOTCONN); assert_return(m, -EINVAL); - assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL); + assert_return(type > _SD_BUS_MESSAGE_TYPE_INVALID && type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL); t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header)); if (!t) @@ -1297,19 +1297,18 @@ static int message_add_offset(sd_bus_message *m, size_t offset) { } static void message_extend_containers(sd_bus_message *m, size_t expand) { - struct bus_container *c; - assert(m); if (expand <= 0) return; - /* Update counters */ - for (c = m->containers; c < m->containers + m->n_containers; c++) { + if (m->n_containers <= 0) + return; + /* Update counters */ + for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++) if (c->array_size) *c->array_size += expand; - } } static void *message_extend_body( @@ -1372,7 +1371,6 @@ static void *message_extend_body( if (r < 0) return NULL; } else { - struct bus_container *c; void *op; size_t os, start_part, end_part; @@ -1393,8 +1391,9 @@ static void *message_extend_body( } /* Readjust pointers */ - for (c = m->containers; c < m->containers + m->n_containers; c++) - c->array_size = adjust_pointer(c->array_size, op, os, part->data); + if (m->n_containers > 0) + for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++) + c->array_size = adjust_pointer(c->array_size, op, os, part->data); m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data); } @@ -5202,29 +5201,34 @@ int bus_message_parse_fields(sd_bus_message *m) { * table */ m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p); - /* Pull out the offset table for the fields array */ - sz = bus_gvariant_determine_word_size(m->fields_size, 0); - if (sz > 0) { - size_t framing; - void *q; + /* Pull out the offset table for the fields array, if any */ + if (m->fields_size > 0) { + sz = bus_gvariant_determine_word_size(m->fields_size, 0); + if (sz > 0) { + size_t framing; + void *q; - ri = m->fields_size - sz; - r = message_peek_fields(m, &ri, 1, sz, &q); - if (r < 0) - return r; + if (m->fields_size < sz) + return -EBADMSG; - framing = bus_gvariant_read_word_le(q, sz); - if (framing >= m->fields_size - sz) - return -EBADMSG; - if ((m->fields_size - framing) % sz != 0) - return -EBADMSG; + ri = m->fields_size - sz; + r = message_peek_fields(m, &ri, 1, sz, &q); + if (r < 0) + return r; - ri = framing; - r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets); - if (r < 0) - return r; + framing = bus_gvariant_read_word_le(q, sz); + if (framing >= m->fields_size - sz) + return -EBADMSG; + if ((m->fields_size - framing) % sz != 0) + return -EBADMSG; - n_offsets = (m->fields_size - framing) / sz; + ri = framing; + r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets); + if (r < 0) + return r; + + n_offsets = (m->fields_size - framing) / sz; + } } } else m->user_body_size = m->body_size; @@ -5492,6 +5496,9 @@ int bus_message_parse_fields(sd_bus_message *m) { if (m->reply_cookie == 0 || !m->error.name) return -EBADMSG; break; + + default: + assert_not_reached("Bad message type"); } /* Refuse non-local messages that claim they are local */ diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index 6d140348e..04d6adddc 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -56,12 +56,18 @@ static int node_vtable_get_userdata( static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) { assert(p); + if (!u) + return SIZE_TO_PTR(p->x.method.offset); /* don't add offset on NULL, to make ubsan happy */ + return (uint8_t*) u + p->x.method.offset; } static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) { assert(p); + if (!u) + return SIZE_TO_PTR(p->x.property.offset); /* as above */ + return (uint8_t*) u + p->x.property.offset; } diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 18d30d010..0adfc97be 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -557,17 +557,24 @@ static int bus_socket_read_auth(sd_bus *b) { mh.msg_control = &control; mh.msg_controllen = sizeof(control); - k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); - if (k < 0 && errno == ENOTSOCK) { + k = recvmsg_safe(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (k == -ENOTSOCK) { b->prefer_readv = true; k = readv(b->input_fd, &iov, 1); + if (k < 0) + k = -errno; } else handle_cmsg = true; } + if (k == -EAGAIN) + return 0; if (k < 0) - return errno == EAGAIN ? 0 : -errno; - if (k == 0) + return (int) k; + if (k == 0) { + if (handle_cmsg) + cmsg_close_all(&mh); /* paranoia, we shouldn't have gotten any fds on EOF */ return -ECONNRESET; + } b->rbuffer_size += k; @@ -1030,8 +1037,10 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { if (m->n_fds > 0 && *idx == 0) { struct cmsghdr *control; - mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds)); - mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds); + mh.msg_controllen = CMSG_SPACE(sizeof(int) * m->n_fds); + mh.msg_control = alloca0(mh.msg_controllen); + control = CMSG_FIRSTHDR(&mh); + control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds); control->cmsg_level = SOL_SOCKET; control->cmsg_type = SCM_RIGHTS; memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds); @@ -1193,17 +1202,24 @@ int bus_socket_read_message(sd_bus *bus) { mh.msg_control = &control; mh.msg_controllen = sizeof(control); - k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); - if (k < 0 && errno == ENOTSOCK) { + k = recvmsg_safe(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (k == -ENOTSOCK) { bus->prefer_readv = true; k = readv(bus->input_fd, &iov, 1); + if (k < 0) + k = -errno; } else handle_cmsg = true; } + if (k == -EAGAIN) + return 0; if (k < 0) - return errno == EAGAIN ? 0 : -errno; - if (k == 0) + return (int) k; + if (k == 0) { + if (handle_cmsg) + cmsg_close_all(&mh); /* On EOF we shouldn't have gotten an fd, but let's make sure */ return -ECONNRESET; + } bus->rbuffer_size += k; diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index 05127f0e0..2c1fbbefc 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -317,7 +317,7 @@ static void* client1(void *p) { finish: if (bus) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *q; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *q = NULL; r = sd_bus_message_new_method_call( bus, @@ -485,7 +485,7 @@ static void* client2(void *p) { finish: if (bus) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *q; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *q = NULL; r = sd_bus_message_new_method_call( bus, diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h index 93f495f25..b14ce435e 100644 --- a/src/libsystemd/sd-netlink/netlink-internal.h +++ b/src/libsystemd/sd-netlink/netlink-internal.h @@ -12,7 +12,6 @@ #define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) -#define RTNL_WQUEUE_MAX 1024 #define RTNL_RQUEUE_MAX 64*1024 #define RTNL_CONTAINER_DEPTH 32 diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 39e3c36ad..2648b338f 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -15,8 +15,7 @@ #include "socket-util.h" #include "strv.h" -#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL) -#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; +#define GET_CONTAINER(m, i) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset)) #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) @@ -452,7 +451,8 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); - assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE); + /* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */ + assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE); r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED); if (r < 0) { @@ -499,6 +499,7 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); + assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE); r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); if (r < 0) @@ -541,6 +542,7 @@ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) { assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); + assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE); r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0); if (r < 0) @@ -939,7 +941,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ int r; assert_return(m, -EINVAL); - assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); + assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL); r = type_system_get_type(m->containers[m->n_containers].type_system, &nl_type, @@ -1030,7 +1032,7 @@ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id int r; assert_return(m, -EINVAL); - assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); + assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL); r = netlink_message_read_internal(m, type_id, &container, NULL); if (r < 0) diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c index e03302bbe..9598ad8e0 100644 --- a/src/libsystemd/sd-netlink/test-netlink.c +++ b/src/libsystemd/sd-netlink/test-netlink.c @@ -128,7 +128,7 @@ static void test_address_get(sd_netlink *rtnl, int ifindex) { } static void test_route(sd_netlink *rtnl) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; struct in_addr addr, addr_data; uint32_t index = 2, u32_data; int r; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 047f83532..fb2312f52 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2567,7 +2567,7 @@ static int method_can_reboot_parameter( void *userdata, sd_bus_error *error) { - Manager *m = userdata; + _unused_ Manager *m = userdata; int r; assert(message); @@ -2699,7 +2699,7 @@ static int method_can_reboot_to_firmware_setup( void *userdata, sd_bus_error *error) { - Manager *m = userdata; + _unused_ Manager *m = userdata; int r; assert(message); @@ -2888,7 +2888,7 @@ static int method_can_reboot_to_boot_loader_menu( void *userdata, sd_bus_error *error) { - Manager *m = userdata; + _unused_ Manager *m = userdata; int r; assert(message); @@ -3079,7 +3079,7 @@ static int method_can_reboot_to_boot_loader_entry( void *userdata, sd_bus_error *error) { - Manager *m = userdata; + _unused_ Manager *m = userdata; int r; assert(message); diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index 84bea21ab..51d0610bf 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -963,11 +963,23 @@ _public_ PAM_EXTERN int pam_sm_close_session( int argc, const char **argv) { const void *existing = NULL; + bool debug = false; const char *id; int r; assert(handle); + if (parse_argv(handle, + argc, argv, + NULL, + NULL, + NULL, + &debug) < 0) + return PAM_SESSION_ERR; + + if (debug) + pam_syslog(handle, LOG_DEBUG, "pam-systemd shutting down"); + /* Only release session if it wasn't pre-existing when we * tried to create it */ (void) pam_get_data(handle, "systemd.existing", &existing); diff --git a/src/login/systemd-user.m4 b/src/login/systemd-user.m4 index 4f85b4b7f..f6313f79f 100644 --- a/src/login/systemd-user.m4 +++ b/src/login/systemd-user.m4 @@ -2,11 +2,19 @@ # # Used by systemd --user instances. -account required pam_unix.so +m4_ifdef(`ENABLE_HOMED', +-account sufficient pam_systemd_home.so +)m4_dnl +account sufficient pam_unix.so +account required pam_permit.so + m4_ifdef(`HAVE_SELINUX', session required pam_selinux.so close session required pam_selinux.so nottys open )m4_dnl session required pam_loginuid.so session optional pam_keyinit.so force revoke +m4_ifdef(`ENABLE_HOMED', +-session optional pam_systemd_home.so +)m4_dnl session optional pam_systemd.so diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index d0cc07678..07b090507 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -112,7 +112,7 @@ static int method_get_machine(sd_bus_message *message, void *userdata, sd_bus_er static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; - Manager *m = userdata; + _unused_ Manager *m = userdata; const char *name; int r; @@ -471,7 +471,7 @@ static int method_get_machine_os_release(sd_bus_message *message, void *userdata static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_hashmap_free_ Hashmap *images = NULL; - Manager *m = userdata; + _unused_ Manager *m = userdata; Image *image; Iterator i; int r; diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c index 19683c0a0..91788c368 100644 --- a/src/network/netdev/l2tp-tunnel.c +++ b/src/network/netdev/l2tp-tunnel.c @@ -44,7 +44,7 @@ static void l2tp_session_free(L2tpSession *s) { return; if (s->tunnel && s->section) - ordered_hashmap_remove(s->tunnel->sessions_by_section, s); + ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section); network_config_section_free(s->section); diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c index 7d1fec3af..3542f9652 100644 --- a/src/network/netdev/macsec.c +++ b/src/network/netdev/macsec.c @@ -828,7 +828,7 @@ int config_parse_macsec_key_id( _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL; _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; - _cleanup_free_ void *p; + _cleanup_free_ void *p = NULL; MACsec *s = userdata; uint8_t *dest; size_t l; diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 6244f7520..c61e517ea 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -949,8 +949,8 @@ int config_parse_lifetime(const char *unit, if (r < 0) return r; - /* We accept only "forever", "infinity", or "0". */ - if (STR_IN_SET(rvalue, "forever", "infinity")) + /* We accept only "forever", "infinity", empty, or "0". */ + if (STR_IN_SET(rvalue, "forever", "infinity", "")) k = CACHE_INFO_INFINITY_LIFE_TIME; else if (streq(rvalue, "0")) k = 0; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 99d4b29c3..05aaf459e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3969,7 +3969,7 @@ int link_save(Link *link) { if (link->dhcp6_client) { r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); if (r < 0 && r != -ENOMSG) - log_link_debug(link, "No DHCPv6 lease"); + log_link_debug_errno(link, r, "Failed to get DHCPv6 lease: %m"); } fprintf(f, "NETWORK_FILE=%s\n", link->network->filename); diff --git a/src/network/networkd-lldp-rx.c b/src/network/networkd-lldp-rx.c index 0631cc96a..fe8877797 100644 --- a/src/network/networkd-lldp-rx.c +++ b/src/network/networkd-lldp-rx.c @@ -12,6 +12,7 @@ #include "networkd-network.h" #include "string-table.h" #include "string-util.h" +#include "strv.h" #include "tmpfile-util.h" DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting."); @@ -36,10 +37,10 @@ bool link_lldp_rx_enabled(Link *link) { if (!link->network) return false; - /* LLDP should be handled on bridge slaves as those have a direct - * connection to their peers not on the bridge master. Linux doesn't - * even (by default) forward lldp packets to the bridge master.*/ - if (streq_ptr("bridge", link->kind)) + /* LLDP should be handled on bridge and bond slaves as those have a direct connection to their peers, + * not on the bridge/bond master. Linux doesn't even (by default) forward lldp packets to the bridge + * master.*/ + if (link->kind && STR_IN_SET(link->kind, "bridge", "bond")) return false; return link->network->lldp_mode != LLDP_MODE_NO; diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c index 51db60e1f..93ab2144a 100644 --- a/src/network/networkd-lldp-tx.c +++ b/src/network/networkd-lldp-tx.c @@ -7,6 +7,7 @@ #include "alloc-util.h" #include "env-file.h" +#include "escape.h" #include "fd-util.h" #include "hostname-util.h" #include "missing_network.h" @@ -17,6 +18,7 @@ #include "random-util.h" #include "socket-util.h" #include "string-util.h" +#include "strv.h" #include "unaligned.h" /* The LLDP spec calls this "txFastInit", see 9.2.5.19 */ @@ -52,6 +54,9 @@ bool link_lldp_emit_enabled(Link *link) { if (!link->network) return false; + if (link->kind && STR_IN_SET(link->kind, "bridge", "bond")) + return false; + return link->network->lldp_emit != LLDP_EMIT_NO; } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 5a442038c..5e5c75728 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -2190,7 +2190,7 @@ void manager_dirty(Manager *manager) { } static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - Manager *manager = userdata; + _unused_ Manager *manager = userdata; const sd_bus_error *e; assert(m); @@ -2236,7 +2236,7 @@ int manager_set_hostname(Manager *m, const char *hostname) { } static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - Manager *manager = userdata; + _unused_ Manager *manager = userdata; const sd_bus_error *e; assert(m); diff --git a/src/network/test-network.c b/src/network/test-network.c index e23bec768..160096628 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -253,4 +253,5 @@ int main(void) { test_network_get(manager, loopback); assert_se(manager_rtnl_enumerate_links(manager) >= 0); + return 0; } diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index a862355a6..59bd73d2e 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -569,7 +569,7 @@ int mount_all(const char *dest, static const MountPoint mount_table[] = { /* First we list inner child mounts (i.e. mounts applied *after* entering user namespacing) */ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, - MOUNT_FATAL|MOUNT_IN_USERNS }, + MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_MKDIR }, { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ @@ -599,23 +599,23 @@ int mount_all(const char *dest, PROC_READ_ONLY("/proc/scsi"), { "mqueue", "/dev/mqueue", "mqueue", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, - MOUNT_IN_USERNS }, + MOUNT_IN_USERNS|MOUNT_MKDIR }, /* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, - MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP }, + MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP|MOUNT_MKDIR }, { "tmpfs", "/sys", "tmpfs", "mode=555", MS_NOSUID|MS_NOEXEC|MS_NODEV, - MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS }, + MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS|MOUNT_MKDIR }, { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, - MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */ + MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO|MOUNT_MKDIR }, /* skipped if above was mounted */ { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, - MOUNT_FATAL }, /* skipped if above was mounted */ + MOUNT_FATAL|MOUNT_MKDIR }, /* skipped if above was mounted */ { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, - MOUNT_FATAL }, + MOUNT_FATAL|MOUNT_MKDIR }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, - MOUNT_FATAL }, + MOUNT_FATAL|MOUNT_MKDIR }, { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, - MOUNT_FATAL }, + MOUNT_FATAL|MOUNT_MKDIR }, #if HAVE_SELINUX { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, @@ -663,17 +663,19 @@ int mount_all(const char *dest, continue; } - r = mkdir_userns_p(dest, where, 0755, (use_userns && !in_userns) ? uid_shift : UID_INVALID); - if (r < 0 && r != -EEXIST) { - if (fatal && r != -EROFS) - return log_error_errno(r, "Failed to create directory %s: %m", where); + if (FLAGS_SET(mount_table[k].mount_settings, MOUNT_MKDIR)) { + r = mkdir_userns_p(dest, where, 0755, (use_userns && !in_userns) ? uid_shift : UID_INVALID); + if (r < 0 && r != -EEXIST) { + if (fatal && r != -EROFS) + return log_error_errno(r, "Failed to create directory %s: %m", where); - log_debug_errno(r, "Failed to create directory %s: %m", where); - /* If we failed mkdir() or chown() due to the root - * directory being read only, attempt to mount this fs - * anyway and let mount_verbose log any errors */ - if (r != -EROFS) - continue; + log_debug_errno(r, "Failed to create directory %s: %m", where); + + /* If we failed mkdir() or chown() due to the root directory being read only, + * attempt to mount this fs anyway and let mount_verbose log any errors */ + if (r != -EROFS) + continue; + } } o = mount_table[k].options; diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 680ff350e..e8bb90383 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -16,6 +16,7 @@ typedef enum MountSettingsMask { MOUNT_APPLY_TMPFS_TMP = 1 << 5, /* if set, /tmp will be mounted as tmpfs */ MOUNT_ROOT_ONLY = 1 << 6, /* if set, only root mounts are mounted */ MOUNT_NON_ROOT_ONLY = 1 << 7, /* if set, only non-root mounts are mounted */ + MOUNT_MKDIR = 1 << 8, /* if set, make directory to mount over first */ } MountSettingsMask; typedef enum CustomMountType { diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 734dee113..51d0c2a75 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3484,6 +3484,16 @@ static int outer_child( if (r < 0) return r; + r = mount_custom( + directory, + arg_custom_mounts, + arg_n_custom_mounts, + arg_uid_shift, + arg_selinux_apifs_context, + MOUNT_NON_ROOT_ONLY); + if (r < 0) + return r; + r = setup_timezone(directory); if (r < 0) return r; @@ -3500,16 +3510,6 @@ static int outer_child( if (r < 0) return r; - r = mount_custom( - directory, - arg_custom_mounts, - arg_n_custom_mounts, - arg_uid_shift, - arg_selinux_apifs_context, - MOUNT_NON_ROOT_ONLY); - if (r < 0) - return r; - if (!arg_use_cgns) { r = mount_cgroups( directory, @@ -3711,13 +3711,12 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r return 0; } - n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); - if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; + n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (IN_SET(n, -EAGAIN, -EINTR)) + return 0; + if (n < 0) + return log_warning_errno(n, "Couldn't read notification socket: %m"); - return log_warning_errno(errno, "Couldn't read notification socket: %m"); - } cmsg_close_all(&msghdr); CMSG_FOREACH(cmsg, &msghdr) { diff --git a/src/partition/makefs.c b/src/partition/makefs.c index d73d67c4e..df08a5fea 100644 --- a/src/partition/makefs.c +++ b/src/partition/makefs.c @@ -54,11 +54,11 @@ static int run(int argc, char *argv[]) { /* type and device must be copied because makefs calls safe_fork, which clears argv[] */ type = strdup(argv[1]); if (!type) - return -ENOMEM; + return log_oom(); device = strdup(argv[2]); if (!device) - return -ENOMEM; + return log_oom(); if (stat(device, &st) < 0) return log_error_errno(errno, "Failed to stat \"%s\": %m", device); diff --git a/src/partition/repart.c b/src/partition/repart.c index 3e52f26a1..1a0c937ae 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -714,7 +714,7 @@ static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) { assert(p->new_size != UINT64_MAX); m = p->new_size + span; - xsz = partition_max_size(a->after); + xsz = partition_max_size(p); if (xsz != UINT64_MAX && m > xsz) m = xsz; @@ -1722,7 +1722,7 @@ static int context_dump_partition_bar(Context *context, const char *node) { bool z = false; size_t c, j = 0; - assert((c = columns()) >= 2); + assert_se((c = columns()) >= 2); c -= 2; /* We do not use the leftmost and rightmost character cell */ bar = new0(Partition*, c); @@ -2210,7 +2210,6 @@ static int context_acquire_partition_uuids_and_labels(Context *context) { LIST_FOREACH(partitions, p, context->partitions) { assert(sd_id128_is_null(p->new_uuid)); - assert(!p->new_label); /* Never touch foreign partitions */ if (PARTITION_IS_FOREIGN(p)) { @@ -2233,6 +2232,9 @@ static int context_acquire_partition_uuids_and_labels(Context *context) { return r; } + if (p->new_label) /* Explicitly set by user? */ + continue; + if (!isempty(p->current_label)) { p->new_label = strdup(p->current_label); /* never change initialized labels */ if (!p->new_label) @@ -2256,7 +2258,7 @@ static int device_kernel_partitions_supported(int fd) { if (fstat(fd, &st) < 0) return log_error_errno(fd, "Failed to fstat() image file: %m"); if (!S_ISBLK(st.st_mode)) - return false; + return -ENOTBLK; /* we do not log in this one special case about errors */ if (ioctl(fd, LOOP_GET_STATUS64, &info) < 0) { @@ -2461,9 +2463,11 @@ static int context_write_partition_table( return log_error_errno(r, "Failed to write partition table: %m"); capable = device_kernel_partitions_supported(fdisk_get_devfd(context->fdisk_context)); - if (capable < 0) + if (capable == -ENOTBLK) + log_debug("Not telling kernel to reread partition table, since we are not operating on a block device."); + else if (capable < 0) return capable; - if (capable > 0) { + else if (capable > 0) { log_info("Telling kernel to reread partition table."); if (from_scratch) @@ -2946,8 +2950,10 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; - if (context->n_partitions <= 0 && arg_empty != EMPTY_FORCE) + if (context->n_partitions <= 0 && arg_empty != EMPTY_FORCE) { + log_info("Didn't find any partition definition files, nothing to do."); return 0; + } r = find_root(&node); if (r < 0) diff --git a/src/portable/portable.c b/src/portable/portable.c index e18826ab2..45a35deed 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -190,9 +190,9 @@ static int recv_item( assert(ret_name); assert(ret_fd); - n = recvmsg(socket_fd, &mh, MSG_CMSG_CLOEXEC); + n = recvmsg_safe(socket_fd, &mh, MSG_CMSG_CLOEXEC); if (n < 0) - return -errno; + return (int) n; CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == SOL_SOCKET && diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index e5693bf72..d6fba7ead 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -678,6 +678,9 @@ int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) { return 0; } +/* + * This function is not used in the code base, but is useful when debugging. Do not delete. + */ void dns_answer_dump(DnsAnswer *answer, FILE *f) { DnsResourceRecord *rr; DnsAnswerFlags flags; @@ -707,7 +710,7 @@ void dns_answer_dump(DnsAnswer *answer, FILE *f) { if (flags & DNS_ANSWER_AUTHENTICATED) fputs(" authenticated", f); if (flags & DNS_ANSWER_CACHEABLE) - fputs(" cachable", f); + fputs(" cacheable", f); if (flags & DNS_ANSWER_SHARED_OWNER) fputs(" shared-owner", f); diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 4a41921cf..d6eca6dfd 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -212,31 +212,6 @@ static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) { return state; } -static bool dns_query_candidate_is_routable(DnsQueryCandidate *c, uint16_t type) { - int family; - - assert(c); - - /* Checks whether the specified RR type matches an address family that is routable on the link(s) the scope of - * this candidate belongs to. Specifically, whether there's a routable IPv4 address on it if we query an A RR, - * or a routable IPv6 address if we query an AAAA RR. */ - - if (!c->query->suppress_unroutable_family) - return true; - - if (c->scope->protocol != DNS_PROTOCOL_DNS) - return true; - - family = dns_type_to_af(type); - if (family < 0) - return true; - - if (c->scope->link) - return link_relevant(c->scope->link, family, false); - else - return manager_routable(c->scope->manager, family); -} - static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) { DnsQuestion *question; DnsResourceKey *key; @@ -253,9 +228,6 @@ static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *new_key = NULL; DnsResourceKey *qkey; - if (!dns_query_candidate_is_routable(c, key->type)) - continue; - if (c->search_domain) { r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name); if (r < 0) diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index fb54d160d..5898308d5 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -1350,7 +1350,16 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) { } if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) { - dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED); + DnsTransactionState result; + + if (t->scope->protocol == DNS_PROTOCOL_LLMNR) + /* If we didn't find anything on LLMNR, it's not an error, but a failure to resolve + * the name. */ + result = DNS_TRANSACTION_NOT_FOUND; + else + result = DNS_TRANSACTION_ATTEMPTS_MAX_REACHED; + + dns_transaction_complete(t, result); return 0; } diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c index aad3bb448..2a4a95989 100644 --- a/src/resolve/resolved-dnstls-gnutls.c +++ b/src/resolve/resolved-dnstls-gnutls.c @@ -27,7 +27,7 @@ static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *io } int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { - _cleanup_(gnutls_deinitp) gnutls_session_t gs; + _cleanup_(gnutls_deinitp) gnutls_session_t gs = NULL; int r; assert(stream); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index df25907a4..0d9d1c48e 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -775,17 +775,14 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { iov = IOVEC_MAKE(DNS_PACKET_DATA(p), p->allocated); - l = recvmsg(fd, &mh, 0); - if (l < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - - return -errno; - } + l = recvmsg_safe(fd, &mh, 0); + if (IN_SET(l, -EAGAIN, -EINTR)) + return 0; + if (l < 0) + return l; if (l == 0) return 0; - assert(!(mh.msg_flags & MSG_CTRUNC)); assert(!(mh.msg_flags & MSG_TRUNC)); p->size = (size_t) l; @@ -965,10 +962,10 @@ static int manager_ipv4_send( struct in_pktinfo *pi; mh.msg_control = &control; - mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo)); + mh.msg_controllen = sizeof(control); cmsg = CMSG_FIRSTHDR(&mh); - cmsg->cmsg_len = mh.msg_controllen; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_PKTINFO; @@ -1024,10 +1021,10 @@ static int manager_ipv6_send( struct in6_pktinfo *pi; mh.msg_control = &control; - mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo)); + mh.msg_controllen = sizeof(control); cmsg = CMSG_FIRSTHDR(&mh); - cmsg->cmsg_len = mh.msg_controllen; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; diff --git a/src/run/run.c b/src/run/run.c index 2b806fb6a..3b2110129 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -1109,7 +1109,11 @@ static int start_transient_service( assert_not_reached("Can't allocate tty via ssh"); } - if (!arg_no_block) { + /* Optionally, wait for the start job to complete. If we are supposed to read the service's stdin + * lets skip this however, because we should start that already when the start job is running, and + * there's little point in waiting for the start job to complete in that case anyway, as we'll wait + * for EOF anyway, which is going to be much later. */ + if (!arg_no_block && arg_stdio == ARG_STDIO_NONE) { r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_error_errno(r, "Could not watch jobs: %m"); diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 0fc5501e6..1175f2336 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -923,12 +923,11 @@ int ask_password_agent( msghdr.msg_control = &control; msghdr.msg_controllen = sizeof(control); - n = recvmsg(socket_fd, &msghdr, 0); + n = recvmsg_safe(socket_fd, &msghdr, 0); + if (IN_SET(n, -EAGAIN, -EINTR)) + continue; if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - continue; - - r = -errno; + r = (int) n; goto finish; } diff --git a/src/shared/binfmt-util.c b/src/shared/binfmt-util.c new file mode 100644 index 000000000..0229726b4 --- /dev/null +++ b/src/shared/binfmt-util.c @@ -0,0 +1,33 @@ +#include +#include +#include + +#include "binfmt-util.h" +#include "fileio.h" +#include "missing_magic.h" +#include "stat-util.h" + +int disable_binfmt(void) { + int r; + + /* Flush out all rules. This is important during shutdown to cover for rules using "F", since those + * might pin a file and thus block us from unmounting stuff cleanly. + * + * We are a bit careful here, since binfmt_misc might still be an autofs which we don't want to + * trigger. */ + + r = path_is_fs_type("/proc/sys/fs/binfmt_misc", BINFMTFS_MAGIC); + if (r == 0 || r == -ENOENT) { + log_debug("binfmt_misc is not mounted, not detaching entries."); + return 0; + } + if (r < 0) + return log_warning_errno(r, "Failed to determine whether binfmt_misc is mounted: %m"); + + r = write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_warning_errno(r, "Failed to unregister binfmt_misc entries: %m"); + + log_debug("Unregistered all remaining binfmt_misc entries."); + return 0; +} diff --git a/src/shared/binfmt-util.h b/src/shared/binfmt-util.h new file mode 100644 index 000000000..70feaad31 --- /dev/null +++ b/src/shared/binfmt-util.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int disable_binfmt(void); diff --git a/src/shared/bus-wait-for-units.c b/src/shared/bus-wait-for-units.c index 78b2a6040..3ee3c0ccb 100644 --- a/src/shared/bus-wait-for-units.c +++ b/src/shared/bus-wait-for-units.c @@ -80,6 +80,15 @@ static WaitForItem *wait_for_item_free(WaitForItem *item) { DEFINE_TRIVIAL_CLEANUP_FUNC(WaitForItem*, wait_for_item_free); +static void call_unit_callback_and_wait(BusWaitForUnits *d, WaitForItem *item, bool good) { + d->current = item; + + if (item->unit_callback) + item->unit_callback(d, item->bus_path, good, item->userdata); + + wait_for_item_free(item); +} + static void bus_wait_for_units_clear(BusWaitForUnits *d) { WaitForItem *item; @@ -88,12 +97,8 @@ static void bus_wait_for_units_clear(BusWaitForUnits *d) { d->slot_disconnected = sd_bus_slot_unref(d->slot_disconnected); d->bus = sd_bus_unref(d->bus); - while ((item = hashmap_first(d->items))) { - d->current = item; - - item->unit_callback(d, item->bus_path, false, item->userdata); - wait_for_item_free(item); - } + while ((item = hashmap_first(d->items))) + call_unit_callback_and_wait(d, item, false); d->items = hashmap_free(d->items); } @@ -212,13 +217,7 @@ static void wait_for_item_check_ready(WaitForItem *item) { return; } - if (item->unit_callback) { - d->current = item; - item->unit_callback(d, item->bus_path, true, item->userdata); - } - - wait_for_item_free(item); - + call_unit_callback_and_wait(d, item, true); bus_wait_for_units_check_ready(d); } @@ -303,10 +302,7 @@ static int on_get_all_properties(sd_bus_message *m, void *userdata, sd_bus_error log_debug_errno(sd_bus_error_get_errno(error), "GetAll() failed for %s: %s", item->bus_path, error->message); - d->current = item; - item->unit_callback(d, item->bus_path, false, item->userdata); - wait_for_item_free(item); - + call_unit_callback_and_wait(d, item, false); bus_wait_for_units_check_ready(d); return 0; } diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c index 217ab3fba..7dd87afd0 100644 --- a/src/shared/calendarspec.c +++ b/src/shared/calendarspec.c @@ -87,6 +87,16 @@ static void normalize_chain(CalendarComponent **c) { if (i->stop > i->start && i->repeat > 0) i->stop -= (i->stop - i->start) % i->repeat; + /* If a repeat value is specified, but it cannot even be triggered once, let's suppress + * it. + * + * Similar, if the stop value is the same as the start value, then let's just make this a + * non-repeating chain element */ + if ((i->stop > i->start && i->repeat > 0 && i->start + i->repeat > i->stop) || + i->start == i->stop) { + i->repeat = 0; + i->stop = -1; + } } if (n <= 1) @@ -365,14 +375,13 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) { } r = fflush_and_check(f); + fclose(f); + if (r < 0) { free(buf); - fclose(f); return r; } - fclose(f); - *p = buf; return 0; } @@ -642,6 +651,16 @@ static int prepend_component(const char **p, bool usec, unsigned nesting, Calend if (repeat == 0) return -ERANGE; + } else { + /* If no repeat value is specified for the µs component, then let's explicitly refuse ranges + * below 1s because our default repeat granularity is beyond that. */ + + /* Overflow check */ + if (start > INT_MAX - repeat) + return -ERANGE; + + if (usec && stop >= 0 && start + repeat > stop) + return -EINVAL; } if (!IN_SET(*e, 0, ' ', ',', '-', '~', ':')) diff --git a/src/shared/efi-loader.c b/src/shared/efi-loader.c index b05dc91ec..12d48f32d 100644 --- a/src/shared/efi-loader.c +++ b/src/shared/efi-loader.c @@ -534,15 +534,11 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) { if (r < 0) return log_debug_errno(r, "Failed to read LoaderTimeExecUSec: %m"); - if (y == 0 || y < x) + if (y == 0 || y < x || y - x > USEC_PER_HOUR) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Bad LoaderTimeInitUSec=%"PRIu64", LoaderTimeExecUSec=%" PRIu64"; refusing.", x, y); - if (y > USEC_PER_HOUR) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "LoaderTimeExecUSec=%"PRIu64" too large, refusing.", x); - *firmware = x; *loader = y; diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index 00a71d64a..c985b5aea 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -209,7 +209,7 @@ int ethtool_get_link_info(int *ethtool_fd, const char *ifname, speed = ethtool_cmd_speed(&ecmd); *ret_speed = speed == (uint32_t) SPEED_UNKNOWN ? - SIZE_MAX : (size_t) speed * 1000 * 1000; + UINT64_MAX : (uint64_t) speed * 1000 * 1000; } if (ret_duplex) @@ -256,8 +256,13 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et if (epaddr.addr.size != 6) return -EOPNOTSUPP; +#pragma GCC diagnostic push +#if HAVE_ZERO_LENGTH_BOUNDS +# pragma GCC diagnostic ignored "-Wzero-length-bounds" +#endif for (size_t i = 0; i < epaddr.addr.size; i++) ret->ether_addr_octet[i] = epaddr.addr.data[i]; +#pragma GCC diagnostic pop return 0; } @@ -431,18 +436,14 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, netdev_ring if (r < 0) return -errno; - if (ring->rx_pending_set) { - if (ecmd.rx_pending != ring->rx_pending) { - ecmd.rx_pending = ring->rx_pending; - need_update = true; - } + if (ring->rx_pending_set && ecmd.rx_pending != ring->rx_pending) { + ecmd.rx_pending = ring->rx_pending; + need_update = true; } - if (ring->tx_pending_set) { - if (ecmd.tx_pending != ring->tx_pending) { - ecmd.tx_pending = ring->tx_pending; - need_update = true; - } + if (ring->tx_pending_set && ecmd.tx_pending != ring->tx_pending) { + ecmd.tx_pending = ring->tx_pending; + need_update = true; } if (need_update) { @@ -479,7 +480,12 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st if (!buffer.info.sset_mask) return -EINVAL; +#pragma GCC diagnostic push +#if HAVE_ZERO_LENGTH_BOUNDS +# pragma GCC diagnostic ignored "-Wzero-length-bounds" +#endif len = buffer.info.data[0]; +#pragma GCC diagnostic pop strings = malloc0(sizeof(struct ethtool_gstrings) + len * ETH_GSTRING_LEN); if (!strings) diff --git a/src/shared/format-table.c b/src/shared/format-table.c index a4b412ecb..64aa2b68e 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -2194,7 +2194,7 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) { case TABLE_SIZE: case TABLE_BPS: - if (d->size == (size_t) -1) + if (d->size == (uint64_t) -1) return json_variant_new_null(ret); return json_variant_new_unsigned(ret, d->size); diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c index 86a57e6b2..b19127be0 100644 --- a/src/shared/fstab-util.c +++ b/src/shared/fstab-util.c @@ -35,6 +35,30 @@ int fstab_has_fstype(const char *fstype) { return false; } +bool fstab_is_extrinsic(const char *mount, const char *opts) { + + /* Don't bother with the OS data itself */ + if (PATH_IN_SET(mount, + "/", + "/usr", + "/etc")) + return true; + + if (PATH_STARTSWITH_SET(mount, + "/run/initramfs", /* This should stay around from before we boot until after we shutdown */ + "/proc", /* All of this is API VFS */ + "/sys", /* … dito … */ + "/dev")) /* … dito … */ + return true; + + /* If this is an initrd mount, and we are not in the initrd, then leave + * this around forever, too. */ + if (opts && fstab_test_option(opts, "x-initrd.mount\0") && !in_initrd()) + return true; + + return false; +} + int fstab_is_mount_point(const char *mount) { _cleanup_endmntent_ FILE *f = NULL; struct mntent *m; diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h index f575ed0bb..a73575e95 100644 --- a/src/shared/fstab-util.h +++ b/src/shared/fstab-util.h @@ -6,6 +6,7 @@ #include "macro.h" +bool fstab_is_extrinsic(const char *mount, const char *opts); int fstab_is_mount_point(const char *mount); int fstab_has_fstype(const char *fstype); diff --git a/src/shared/generator.c b/src/shared/generator.c index acdd0096f..04d2f86a4 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -260,6 +260,9 @@ int generator_write_device_deps( _cleanup_free_ char *node = NULL, *unit = NULL; int r; + if (fstab_is_extrinsic(where, opts)) + return 0; + if (!fstab_test_option(opts, "_netdev\0")) return 0; diff --git a/src/shared/gpt.c b/src/shared/gpt.c index e62f21e88..725374485 100644 --- a/src/shared/gpt.c +++ b/src/shared/gpt.c @@ -29,7 +29,8 @@ const GptPartitionType gpt_partition_type_table[] = { { GPT_SRV, "srv" }, { GPT_VAR, "var" }, { GPT_TMP, "tmp" }, - { GPT_LINUX_GENERIC, "linux-generic", }, + { GPT_USER_HOME, "user-home" }, + { GPT_LINUX_GENERIC, "linux-generic" }, {} }; diff --git a/src/shared/install.c b/src/shared/install.c index 48cb6aca7..78532573c 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -232,7 +232,7 @@ static int path_is_runtime(const LookupPaths *p, const char *path, bool check_pa path_equal_ptr(path, p->runtime_control); } -static int path_is_vendor(const LookupPaths *p, const char *path) { +static int path_is_vendor_or_generator(const LookupPaths *p, const char *path) { const char *rpath; assert(p); @@ -250,6 +250,9 @@ static int path_is_vendor(const LookupPaths *p, const char *path) { return true; #endif + if (path_is_generator(p, rpath)) + return true; + return path_equal(rpath, SYSTEM_DATA_UNIT_PATH); } @@ -1018,10 +1021,14 @@ static int install_info_add( int r; assert(c); - assert(name || path); - if (!name) + if (!name) { + /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to + * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(), + * but this cannot be possible in any code path (See #6119). */ + assert_se(path); name = basename(path); + } if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; @@ -1231,7 +1238,7 @@ static int unit_file_load( return -EINVAL; if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Unit type %s cannot be templated.", unit_type_to_string(type)); + "%s: unit type %s cannot be templated, ignoring.", path, unit_type_to_string(type)); if (!(flags & SEARCH_LOAD)) { r = lstat(path, &st); @@ -2376,7 +2383,7 @@ int unit_file_revert( return -errno; } else if (S_ISREG(st.st_mode)) { /* Check if there's a vendor version */ - r = path_is_vendor(&paths, path); + r = path_is_vendor_or_generator(&paths, path); if (r < 0) return r; if (r > 0) diff --git a/src/shared/meson.build b/src/shared/meson.build index 94174347a..0af8ed77c 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -12,6 +12,8 @@ shared_sources = files(''' barrier.h base-filesystem.c base-filesystem.h + binfmt-util.c + binfmt-util.h bitmap.c bitmap.h blkid-util.h diff --git a/src/shared/resize-fs.c b/src/shared/resize-fs.c index 5ed26a6c9..0abd289fe 100644 --- a/src/shared/resize-fs.c +++ b/src/shared/resize-fs.c @@ -15,7 +15,6 @@ int resize_fs(int fd, uint64_t sz, uint64_t *ret_size) { struct statfs sfs; - int r; assert(fd >= 0); @@ -42,6 +41,7 @@ int resize_fs(int fd, uint64_t sz, uint64_t *ret_size) { *ret_size = u * sfs.f_bsize; } else if (is_fs_type(&sfs, BTRFS_SUPER_MAGIC)) { + _unused_ int r; struct btrfs_ioctl_vol_args args = {}; /* 256M is the minimize size enforced by the btrfs kernel code when resizing (which is diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index eeca17f34..320b1767c 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -384,6 +384,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { .value = "lookup_dcookie\0" "perf_event_open\0" + "pidfd_getfd\0" "ptrace\0" "rtas\0" #ifdef __NR_s390_runtime_instr @@ -449,6 +450,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "oldstat\0" "open\0" "openat\0" + "openat2\0" "readlink\0" "readlinkat\0" "removexattr\0" @@ -1741,7 +1743,7 @@ int seccomp_restrict_archs(Set *archs) { } int parse_syscall_archs(char **l, Set **archs) { - _cleanup_set_free_ Set *_archs; + _cleanup_set_free_ Set *_archs = NULL; char **s; int r; diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c index 7ad0ecc8f..7b64bbf7f 100644 --- a/src/shared/unit-file.c +++ b/src/shared/unit-file.c @@ -320,7 +320,7 @@ int unit_file_build_name_map( /* We don't explicitly check for alias loops here. unit_ids_map_get() which * limits the number of hops should be used to access the map. */ - _cleanup_free_ char *target = NULL, *target_abs = NULL; + _cleanup_free_ char *target = NULL; r = readlinkat_malloc(dirfd(d), de->d_name, &target); if (r < 0) { @@ -329,8 +329,9 @@ int unit_file_build_name_map( continue; } - if (!path_is_absolute(target)) { - target_abs = path_join(*dir, target); + const bool is_abs = path_is_absolute(target); + if (lp->root_dir || !is_abs) { + char *target_abs = path_join(is_abs ? lp->root_dir : *dir, target); if (!target_abs) return log_oom(); diff --git a/src/shared/verbs.c b/src/shared/verbs.c index 1d23ed48a..06d89b473 100644 --- a/src/shared/verbs.c +++ b/src/shared/verbs.c @@ -68,9 +68,9 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) { /* At the end of the list? */ if (!verbs[i].dispatch) { if (name) - log_error("Unknown operation %s.", name); + log_error("Unknown command verb %s.", name); else - log_error("Requires operation parameter."); + log_error("Command verb required."); return -EINVAL; } diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c index 15e6c1799..523040b57 100644 --- a/src/shutdown/shutdown.c +++ b/src/shutdown/shutdown.c @@ -16,6 +16,7 @@ #include "alloc-util.h" #include "async.h" +#include "binfmt-util.h" #include "cgroup-setup.h" #include "cgroup-util.h" #include "def.h" @@ -373,6 +374,7 @@ int main(int argc, char *argv[]) { sync_with_progress(); disable_coredumps(); + disable_binfmt(); log_info("Sending SIGTERM to remaining processes..."); broadcast_signal(SIGTERM, true, true, arg_timeout); @@ -510,7 +512,7 @@ int main(int argc, char *argv[]) { } if (need_umount || need_swapoff || need_loop_detach || need_dm_detach) - log_error("Failed to finalize %s%s%s%s ignoring", + log_error("Failed to finalize%s%s%s%s ignoring.", need_umount ? " file systems," : "", need_swapoff ? " swap devices," : "", need_loop_detach ? " loop devices," : "", diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 0cdb740d2..e92c402e8 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -138,7 +138,7 @@ static int apply_all(OrderedHashmap *sysctl_options) { if (!pattern) return log_oom(); - k = glob_extend(&paths, pattern); + k = glob_extend(&paths, pattern, GLOB_NOCHECK); if (k < 0) { if (option->ignore_failure || ERRNO_IS_PRIVILEGE(r)) log_debug_errno(k, "Failed to resolve glob '%s', ignoring: %m", diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7ccdbe5fc..6887fdf18 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -410,7 +410,7 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { if (arg_full) table_set_width(table, 0); - for (u = unit_infos; u < unit_infos + c; u++) { + for (u = unit_infos; unit_infos && u < unit_infos + c; u++) { _cleanup_free_ char *j = NULL; const char *on_underline = "", *on_loaded = "", *on_active = ""; const char *on_circle = "", *id; @@ -1478,7 +1478,7 @@ static int output_unit_file_list(const UnitFileList *units, unsigned c) { id = basename(u->path); - r = unit_file_query_preset(arg_scope, NULL, id); + r = unit_file_query_preset(arg_scope, arg_root, id); if (r < 0) { unit_preset_str = "n/a"; on_preset_color = underline ? on_underline : ansi_normal(); @@ -5799,7 +5799,8 @@ static int show(int argc, char *argv[], void *userdata) { if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "This command expects one or more unit names. Did you mean --help?"); + "'help' command expects one or more unit names.\n" + "(Alternatively, help for systemctl itself may be shown with --help)"); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index c3e5457fc..fc0855d61 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -529,7 +529,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char ORDERED_HASHMAP_FOREACH(i, todo_uids, iterator) { struct spwd n = { .sp_namp = i->name, - .sp_pwdp = (char*) "!!", /* lock this password, and make it invalid */ + .sp_pwdp = (char*) "!*", /* lock this password, and make it invalid */ .sp_lstchg = lstchg, .sp_min = -1, .sp_max = -1, @@ -1443,7 +1443,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (name) { r = specifier_printf(name, specifier_table, NULL, &resolved_name); if (r < 0) - log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, name); + return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name); if (!valid_user_group_name(resolved_name, 0)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -1458,7 +1458,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (id) { r = specifier_printf(id, specifier_table, NULL, &resolved_id); if (r < 0) - return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name); } @@ -1469,7 +1469,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (description) { r = specifier_printf(description, specifier_table, NULL, &resolved_description); if (r < 0) - return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, description); if (!valid_gecos(resolved_description)) @@ -1485,7 +1485,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (home) { r = specifier_printf(home, specifier_table, NULL, &resolved_home); if (r < 0) - return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, home); if (!valid_home(resolved_home)) @@ -1501,7 +1501,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (shell) { r = specifier_printf(shell, specifier_table, NULL, &resolved_shell); if (r < 0) - return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, shell); if (!valid_shell(resolved_shell)) diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c index 758b75323..d85f70550 100644 --- a/src/test/test-alloc-util.c +++ b/src/test/test-alloc-util.c @@ -99,13 +99,13 @@ static void test_bool_assign(void) { g = cp; /* cast from pointer */ h = NULL; /* cast from pointer */ - assert(b); - assert(c); - assert(d); - assert(e); - assert(!f); - assert(g); - assert(!h); + assert_se(b); + assert_se(c); + assert_se(d); + assert_se(e); + assert_se(!f); + assert_se(g); + assert_se(!h); } static int cleanup_counter = 0; diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c index 3c7f7a98c..29074eccc 100644 --- a/src/test/test-boot-timestamps.c +++ b/src/test/test-boot-timestamps.c @@ -17,7 +17,7 @@ static int test_acpi_fpdt(void) { r = acpi_get_boot_usec(&loader_start, &loader_exit); if (r < 0) { - bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -ENODATA; + bool ok = r == -ENOENT || r == -EACCES || r == -ENODATA; log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read ACPI FPDT: %m"); return ok ? 0 : r; @@ -37,7 +37,7 @@ static int test_efi_loader(void) { r = efi_loader_get_boot_usec(&loader_start, &loader_exit); if (r < 0) { - bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP; + bool ok = r == -ENOENT || r == -EACCES || r == -EOPNOTSUPP; log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read EFI loader data: %m"); return ok ? 0 : r; @@ -59,7 +59,7 @@ static int test_boot_timestamps(void) { r = boot_timestamps(NULL, &fw, &l); if (r < 0) { - bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP; + bool ok = r == -ENOENT || r == -EACCES || r == -EOPNOTSUPP; log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read variables: %m"); return ok ? 0 : r; diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 9c2be7f44..9e2ae55ab 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -185,6 +185,8 @@ int main(int argc, char* argv[]) { test_one("@1493187147 UTC", "2017-04-26 06:12:27 UTC"); test_one("@0", "1970-01-01 00:00:00 UTC"); test_one("@0 UTC", "1970-01-01 00:00:00 UTC"); + test_one("*:05..05", "*-*-* *:05:00"); + test_one("*:05..10/6", "*-*-* *:05:00"); test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000); test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000); @@ -237,8 +239,6 @@ int main(int argc, char* argv[]) { assert_se(calendar_spec_from_string("*~29", &c) < 0); assert_se(calendar_spec_from_string("*~16..31", &c) < 0); assert_se(calendar_spec_from_string("12..1/2-*", &c) < 0); - assert_se(calendar_spec_from_string("*:05..05", &c) < 0); - assert_se(calendar_spec_from_string("*:05..10/6", &c) < 0); assert_se(calendar_spec_from_string("20/4:00", &c) < 0); assert_se(calendar_spec_from_string("00:00/60", &c) < 0); assert_se(calendar_spec_from_string("00:00:2300", &c) < 0); diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c index 713795814..44c74987c 100644 --- a/src/test/test-fd-util.c +++ b/src/test/test-fd-util.c @@ -233,17 +233,17 @@ static void assert_equal_fd(int fd1, int fd2) { ssize_t x, y; x = read(fd1, a, sizeof(a)); - assert(x >= 0); + assert_se(x >= 0); y = read(fd2, b, sizeof(b)); - assert(y >= 0); + assert_se(y >= 0); - assert(x == y); + assert_se(x == y); if (x == 0) break; - assert(memcmp(a, b, x) == 0); + assert_se(memcmp(a, b, x) == 0); } } diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c index c1c7ec911..187be69d1 100644 --- a/src/test/test-fstab-util.c +++ b/src/test/test-fstab-util.c @@ -21,7 +21,7 @@ static void do_fstab_filter_options(const char *opts, int r; const char *name; - _cleanup_free_ char *value, *filtered; + _cleanup_free_ char *value = NULL, *filtered = NULL; r = fstab_filter_options(opts, remove, &name, &value, &filtered); log_info("\"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"", diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c index 014b1aa7a..2e63aace0 100644 --- a/src/test/test-sleep.c +++ b/src/test/test-sleep.c @@ -20,7 +20,7 @@ static void test_parse_sleep_config(void) { _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; log_info("/* %s */", __func__); - assert(parse_sleep_config(&sleep_config) == 0); + assert_se(parse_sleep_config(&sleep_config) == 0); _cleanup_free_ char *sum, *sus, *him, *his, *hym, *hys; diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c index a422cc8dd..e3b1f6f8c 100644 --- a/src/test/test-time-util.c +++ b/src/test/test-time-util.c @@ -433,7 +433,7 @@ static void assert_similar(usec_t a, usec_t b) { else d = b - a; - assert(d < 10*USEC_PER_SEC); + assert_se(d < 10*USEC_PER_SEC); } static void test_usec_shift_clock(void) { diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c index e18e1e6c0..2980f79b1 100644 --- a/src/timesync/timesyncd-manager.c +++ b/src/timesync/timesyncd-manager.c @@ -438,12 +438,11 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re return manager_connect(m); } - len = recvmsg(fd, &msghdr, MSG_DONTWAIT); + len = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT); + if (len == -EAGAIN) + return 0; if (len < 0) { - if (errno == EAGAIN) - return 0; - - log_warning("Error receiving message. Disconnecting."); + log_warning_errno(len, "Error receiving message, disconnecting: %m"); return manager_connect(m); } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index d1ba5841f..3325087b7 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2556,7 +2556,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool if (r < 0) { if (IN_SET(r, -EINVAL, -EBADSLT)) *invalid_config = true; - return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, path); + return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, path); } r = patch_var_run(fname, line, &i.path); diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index cb564a7c5..01fd759f3 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -203,7 +203,7 @@ static int link_unsigned_attribute(sd_device *device, const char *attr, unsigned } int link_config_load(link_config_ctx *ctx) { - _cleanup_strv_free_ char **files; + _cleanup_strv_free_ char **files = NULL; char **f; int r; diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index b8c0d83a0..d067279f3 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -212,13 +212,11 @@ static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32 if (size == 0) return 0; /* Client disconnects? */ - size = recvmsg(fd, &smsg, 0); - if (size < 0) { - if (errno != EINTR) - return log_error_errno(errno, "Failed to receive ctrl message: %m"); - + size = recvmsg_safe(fd, &smsg, 0); + if (size == -EINTR) return 0; - } + if (size < 0) + return log_error_errno(size, "Failed to receive ctrl message: %m"); cmsg_close_all(&smsg); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index b990f68e9..04e1c976f 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1092,7 +1092,9 @@ static int rule_add_line(UdevRules *rules, const char *line_str, unsigned line_n if (isempty(line_str)) return 0; - line = strdup(line_str); + /* We use memdup_suffix0() here, since we want to add a second NUL byte to the end, since possibly + * some parsers might turn this into a "nulstr", which requires an extra NUL at the end. */ + line = memdup_suffix0(line_str, strlen(line_str) + 1); if (!line) return log_oom(); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index ca65474f2..2ac1cac97 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -443,13 +443,18 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device * assert(manager); r = worker_process_device(manager, dev); - if (r < 0) - log_device_warning_errno(dev, r, "Failed to process device, ignoring: %m"); + if (r == -EAGAIN) + /* if we couldn't acquire the flock(), then proceed quietly */ + log_device_debug_errno(dev, r, "Device currently locked, not processing."); + else { + if (r < 0) + log_device_warning_errno(dev, r, "Failed to process device, ignoring: %m"); - /* send processed event back to libudev listeners */ - r = device_monitor_send_device(monitor, NULL, dev); - if (r < 0) - log_device_warning_errno(dev, r, "Failed to send device, ignoring: %m"); + /* send processed event back to libudev listeners */ + r = device_monitor_send_device(monitor, NULL, dev); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to send device, ignoring: %m"); + } /* send udevd the result of the event execution */ r = worker_send_message(manager->worker_watch[WRITE_END]); @@ -910,16 +915,18 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat struct ucred *ucred = NULL; struct worker *worker; - size = recvmsg(fd, &msghdr, MSG_DONTWAIT); - if (size < 0) { - if (errno == EINTR) - continue; - else if (errno == EAGAIN) - /* nothing more to read */ - break; + size = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT); + if (size == -EINTR) + continue; + if (size == -EAGAIN) + /* nothing more to read */ + break; + if (size < 0) + return log_error_errno(size, "Failed to receive message: %m"); - return log_error_errno(errno, "Failed to receive message: %m"); - } else if (size != sizeof(struct worker_message)) { + cmsg_close_all(&msghdr); + + if (size != sizeof(struct worker_message)) { log_warning("Ignoring worker message with invalid size %zi bytes", size); continue; } diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c index 793ef6b07..39dff013a 100644 --- a/src/userdb/userdbctl.c +++ b/src/userdb/userdbctl.c @@ -581,24 +581,24 @@ static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] COMMAND ...\n\n" "%sShow user and group information.%s\n" "\nCommands:\n" - " user [USER…] Inspect user\n" - " group [GROUP…] Inspect group\n" - " users-in-group [GROUP…] Show users that are members of specified group(s)\n" - " groups-of-user [USER…] Show groups the specified user(s) is a member of\n" - " services Show enabled database services\n" + " user [USER…] Inspect user\n" + " group [GROUP…] Inspect group\n" + " users-in-group [GROUP…] Show users that are members of specified group(s)\n" + " groups-of-user [USER…] Show groups the specified user(s) is a member of\n" + " services Show enabled database services\n" "\nOptions:\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - " --no-legend Do not show the headers and footers\n" - " --output=MODE Select output mode (classic, friendly, table, json)\n" - " -j Equivalent to --output=json\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not show the headers and footers\n" + " --output=MODE Select output mode (classic, friendly, table, json)\n" + " -j Equivalent to --output=json\n" " -s --service=SERVICE[:SERVICE…]\n" - " Query the specified service\n" - " --with-nss=BOOL Control whether to include glibc NSS data\n" - " -N Disable inclusion of glibc NSS data and disable synthesizing\n" - " (Same as --with-nss=no --synthesize=no)\n" - " --synthesize=BOOL Synthesize root/nobody user\n" + " Query the specified service\n" + " --with-nss=BOOL Control whether to include glibc NSS data\n" + " -N Do not synthesize or include glibc NSS data\n" + " (Same as --synthesize=no --with-nss=no)\n" + " --synthesize=BOOL Synthesize root/nobody user\n" "\nSee the %s for details.\n" , program_invocation_short_name , ansi_highlight(), ansi_normal() diff --git a/test/fuzz/fuzz-bus-message/oss-fuzz-19446 b/test/fuzz/fuzz-bus-message/oss-fuzz-19446 new file mode 100644 index 000000000..f937ef8c7 Binary files /dev/null and b/test/fuzz/fuzz-bus-message/oss-fuzz-19446 differ diff --git a/test/fuzz/fuzz-calendarspec/oss-fuzz-22208 b/test/fuzz/fuzz-calendarspec/oss-fuzz-22208 new file mode 100644 index 000000000..2bbe7628d --- /dev/null +++ b/test/fuzz/fuzz-calendarspec/oss-fuzz-22208 @@ -0,0 +1 @@ +4:3:2147..2 \ No newline at end of file diff --git a/units/systemd-binfmt.service.in b/units/systemd-binfmt.service.in index 0c0f26451..e54e95e11 100644 --- a/units/systemd-binfmt.service.in +++ b/units/systemd-binfmt.service.in @@ -28,4 +28,5 @@ ConditionDirectoryNotEmpty=|/run/binfmt.d Type=oneshot RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-binfmt +ExecStop=@rootlibexecdir@/systemd-binfmt --unregister TimeoutSec=90s diff --git a/units/systemd-homed.service.in b/units/systemd-homed.service.in index 6490f48a1..0942e22d9 100644 --- a/units/systemd-homed.service.in +++ b/units/systemd-homed.service.in @@ -25,7 +25,6 @@ LimitNOFILE=@HIGH_RLIMIT_NOFILE@ LockPersonality=yes MemoryDenyWriteExecute=yes NoNewPrivileges=yes -PrivateNetwork=yes RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_ALG RestrictNamespaces=mnt RestrictRealtime=yes