From b9a53a403bf644109f10895336a4b0b990274914 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 28 2020 09:34:21 +0000 Subject: import systemd-239-29.el8 --- diff --git a/SOURCES/0216-core-never-propagate-reload-failure-to-service-resul.patch b/SOURCES/0216-core-never-propagate-reload-failure-to-service-resul.patch new file mode 100644 index 0000000..2d967cf --- /dev/null +++ b/SOURCES/0216-core-never-propagate-reload-failure-to-service-resul.patch @@ -0,0 +1,26 @@ +From cffe5d0e781f6fa7f2275b94d2dcc26e00859a78 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 17 Jul 2019 19:16:33 +0200 +Subject: [PATCH] core: never propagate reload failure to service result + +Fixes: #11238 +(cherry picked from commit d611cfa748aaf600832160132774074e808c82c7) + +Resolves: #1735787 +--- + src/core/service.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 8342c131c8..24f167572a 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -3310,7 +3310,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + "Control process exited, code=%s status=%i", + sigchld_code_to_string(code), status); + +- if (s->result == SERVICE_SUCCESS) ++ if (s->state != SERVICE_RELOAD && s->result == SERVICE_SUCCESS) + s->result = f; + + if (s->control_command && diff --git a/SOURCES/0216-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch b/SOURCES/0216-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch deleted file mode 100644 index b46c491..0000000 --- a/SOURCES/0216-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch +++ /dev/null @@ -1,49 +0,0 @@ -From c4b02a7b15c21db44542d0a136d032f8098985b8 Mon Sep 17 00:00:00 2001 -From: Evgeny Vereshchagin -Date: Mon, 24 Dec 2018 00:29:56 +0100 -Subject: [PATCH] journal: rely on _cleanup_free_ to free a temporary string - used in client_context_read_cgroup - -Closes https://github.com/systemd/systemd/issues/11253. - -(cherry picked from commit ef30f7cac18a810814ada7e6a68a31d48cc9fccd) -(cherry picked from commit 3513426adcecc322937635c11ebb89f174f849ed) - -Resolves: #1767716 ---- - src/journal/journald-context.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - -diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c -index dba3525ed8..4f1278492f 100644 ---- a/src/journal/journald-context.c -+++ b/src/journal/journald-context.c -@@ -276,7 +276,7 @@ static int client_context_read_label( - } - - static int client_context_read_cgroup(Server *s, ClientContext *c, const char *unit_id) { -- char *t = NULL; -+ _cleanup_free_ char *t = NULL; - int r; - - assert(c); -@@ -284,7 +284,6 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u - /* Try to acquire the current cgroup path */ - r = cg_pid_get_path_shifted(c->pid, s->cgroup_root, &t); - if (r < 0 || empty_or_root(t)) { -- - /* We use the unit ID passed in as fallback if we have nothing cached yet and cg_pid_get_path_shifted() - * failed or process is running in a root cgroup. Zombie processes are automatically migrated to root cgroup - * on cgroupsv1 and we want to be able to map log messages from them too. */ -@@ -298,10 +297,8 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u - } - - /* Let's shortcut this if the cgroup path didn't change */ -- if (streq_ptr(c->cgroup, t)) { -- free(t); -+ if (streq_ptr(c->cgroup, t)) - return 0; -- } - - free_and_replace(c->cgroup, t); - diff --git a/SOURCES/0217-man-document-systemd-analyze-security.patch b/SOURCES/0217-man-document-systemd-analyze-security.patch new file mode 100644 index 0000000..07ec674 --- /dev/null +++ b/SOURCES/0217-man-document-systemd-analyze-security.patch @@ -0,0 +1,59 @@ +From d11fdacaf3c804b60dfe8371062f34ac2b624ac9 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 13 Sep 2019 09:23:32 +0200 +Subject: [PATCH] man: document systemd-analyze security + +(cherry-picked from commit ee93c1e664a7bbc59f1578e285c871999507b14d) + +Resolves: #1750343 +--- + man/systemd-analyze.xml | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml +index 7aa10fc68e..f3b595880f 100644 +--- a/man/systemd-analyze.xml ++++ b/man/systemd-analyze.xml +@@ -106,6 +106,12 @@ + service-watchdogs + BOOL + ++ ++ systemd-analyze ++ OPTIONS ++ security ++ UNIT ++ + + + +@@ -253,6 +259,29 @@ NAutoVTs=8 + systemd.service5. + The hardware watchdog is not affected by this setting. + ++ systemd-analyze security analyzes the security and sandboxing settings of one or more ++ specified service units. If at least one unit name is specified the security settings of the specified service ++ units are inspected and a detailed analysis is shown. If no unit name is specified, all currently loaded, ++ long-running service units are inspected and a terse table with results shown. The command checks for various ++ security-related service settings, assigning each a numeric "exposure level" value, depending on how important a ++ setting is. It then calculates an overall exposure level for the whole unit, which is an estimation in the range ++ 0.0…10.0 indicating how exposed a service is security-wise. High exposure levels indicate very little applied ++ sandboxing. Low exposure levels indicate tight sandboxing and strongest security restrictions. Note that this only ++ analyzes the per-service security features systemd itself implements. This means that any additional security ++ mechanisms applied by the service code itself are not accounted for. The exposure level determined this way should ++ not be misunderstood: a high exposure level neither means that there is no effective sandboxing applied by the ++ service code itself, nor that the service is actually vulnerable to remote or local attacks. High exposure levels ++ do indicate however that most likely the service might benefit from additional settings applied to them. Please ++ note that many of the security and sandboxing settings individually can be circumvented — unless combined with ++ others. For example, if a service retains the privilege to establish or undo mount points many of the sandboxing ++ options can be undone by the service code itself. Due to that is essential that each service uses the most ++ comprehensive and strict sandboxing and security settings possible. The tool will take into account some of these ++ combinations and relationships between the settings, but not all. Also note that the security and sandboxing ++ settings analyzed here only apply to the operations executed by the service code itself. If a service has access to ++ an IPC system (such as D-Bus) it might request operations from other services that are not subject to the same ++ restrictions. Any comprehensive security and sandboxing analysis is hence incomplete if the IPC access policy is ++ not validated too. ++ + If no command is passed, systemd-analyze + time is implied. + diff --git a/SOURCES/0217-shared-but-util-drop-trusted-annotation-from-bus_ope.patch b/SOURCES/0217-shared-but-util-drop-trusted-annotation-from-bus_ope.patch deleted file mode 100644 index f161aaf..0000000 --- a/SOURCES/0217-shared-but-util-drop-trusted-annotation-from-bus_ope.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 4eedaaad7c0abb937482bc93c29c213acfe6c308 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Tue, 27 Aug 2019 19:00:34 +0200 -Subject: [PATCH] shared/but-util: drop trusted annotation from - bus_open_system_watch_bind_with_description() - -https://bugzilla.redhat.com/show_bug.cgi?id=1746057 - -This only affects systemd-resolved. bus_open_system_watch_bind_with_description() -is also used in timesyncd, but it has no methods, only read-only properties, and -in networkd, but it annotates all methods with SD_BUS_VTABLE_UNPRIVILEGED and does -polkit checks. - -Resolves: #1746857 ---- - src/shared/bus-util.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c -index a4f2deba31..302dbb4c2e 100644 ---- a/src/shared/bus-util.c -+++ b/src/shared/bus-util.c -@@ -1699,10 +1699,6 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri - if (r < 0) - return r; - -- r = sd_bus_set_trusted(bus, true); -- if (r < 0) -- return r; -- - r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS); - if (r < 0) - return r; diff --git a/SOURCES/0218-man-reorder-and-add-examples-to-systemd-analyze-1.patch b/SOURCES/0218-man-reorder-and-add-examples-to-systemd-analyze-1.patch new file mode 100644 index 0000000..4cfc715 --- /dev/null +++ b/SOURCES/0218-man-reorder-and-add-examples-to-systemd-analyze-1.patch @@ -0,0 +1,772 @@ +From a2e00522971897909db2a81b4daf10e5700f453e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 15 Mar 2019 10:13:55 +0100 +Subject: [PATCH] man: reorder and add examples to systemd-analyze(1) + +The number of verbs supported by systemd-analyze has grown quite a bit, and the +man page has become an unreadable wall of text. Let's put each verb in a +separate subsection, grouping similar verbs together, and add a lot of examples +to guide the user. + +(cherry picked from commit d323a99001c1f7625e8ac902e18deb514a4ca18d) + +Related: #1750343 +--- + man/systemd-analyze.xml | 678 +++++++++++++++++++++++++--------------- + 1 file changed, 429 insertions(+), 249 deletions(-) + +diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml +index f3b595880f..7c873cbdd1 100644 +--- a/man/systemd-analyze.xml ++++ b/man/systemd-analyze.xml +@@ -41,46 +41,50 @@ + critical-chain + UNIT + ++ + + systemd-analyze + OPTIONS +- plot +- > file.svg ++ log-level ++ LEVEL + + + systemd-analyze + OPTIONS +- dot +- PATTERN +- > file.dot ++ log-target ++ TARGET + + + systemd-analyze + OPTIONS +- dump ++ service-watchdogs ++ BOOL + ++ + + systemd-analyze + OPTIONS +- cat-config +- NAME|PATH ++ dump + ++ + + systemd-analyze + OPTIONS +- unit-paths ++ plot ++ >file.svg + + + systemd-analyze + OPTIONS +- log-level +- LEVEL ++ dot ++ PATTERN ++ >file.dot + ++ + + systemd-analyze + OPTIONS +- log-target +- TARGET ++ unit-paths + + + systemd-analyze +@@ -91,20 +95,20 @@ + + systemd-analyze + OPTIONS +- verify +- FILES ++ calendar ++ SPECS + + + systemd-analyze + OPTIONS +- calendar +- SPECS ++ timespan ++ SPAN + + + systemd-analyze + OPTIONS +- service-watchdogs +- BOOL ++ cat-config ++ NAME|PATH + + + systemd-analyze +@@ -123,73 +127,299 @@ + verify the correctness of unit files. It is also used to access + special functions useful for advanced system manager debugging. + +- systemd-analyze time prints the time +- spent in the kernel before userspace has been reached, the time +- spent in the initial RAM disk (initrd) before normal system +- userspace has been reached, and the time normal system userspace +- took to initialize. Note that these measurements simply measure +- the time passed up to the point where all system services have +- been spawned, but not necessarily until they fully finished +- initialization or the disk is idle. +- +- systemd-analyze blame prints a list of +- all running units, ordered by the time they took to initialize. +- This information may be used to optimize boot-up times. Note that +- the output might be misleading as the initialization of one +- service might be slow simply because it waits for the +- initialization of another service to complete. +- Also note: systemd-analyze blame doesn't display +- results for services with Type=simple, +- because systemd considers such services to be started immediately, +- hence no measurement of the initialization delays can be done. +- +- systemd-analyze critical-chain +- [UNIT…] prints a tree of +- the time-critical chain of units (for each of the specified +- UNITs or for the default target +- otherwise). The time after the unit is active or started is +- printed after the "@" character. The time the unit takes to start +- is printed after the "+" character. Note that the output might be +- misleading as the initialization of one service might depend on +- socket activation and because of the parallel execution of +- units. +- +- systemd-analyze plot prints an SVG +- graphic detailing which system services have been started at what +- time, highlighting the time they spent on initialization. +- +- systemd-analyze dot generates textual +- dependency graph description in dot format for further processing +- with the GraphViz +- dot1 +- tool. Use a command line like systemd-analyze dot | dot +- -Tsvg > systemd.svg to generate a graphical dependency +- tree. Unless or +- is passed, the generated graph will +- show both ordering and requirement dependencies. Optional pattern +- globbing style specifications (e.g. *.target) +- may be given at the end. A unit dependency is included in the +- graph if any of these patterns match either the origin or +- destination node. +- +- systemd-analyze dump outputs a (usually +- very long) human-readable serialization of the complete server +- state. Its format is subject to change without notice and should +- not be parsed by applications. +- +- systemd-analyze cat-config is similar +- to systemctl cat, but operates on config files. +- It will copy the contents of a config file and any drop-ins to standard +- output, using the usual systemd set of directories and rules for +- precedence. Each argument must be either an absolute path including +- the prefix (such as /etc/systemd/logind.conf or +- /usr/lib/systemd/logind.conf), or a name +- relative to the prefix (such as systemd/logind.conf). +- ++ If no command is passed, systemd-analyze ++ time is implied. ++ ++ ++ <command>systemd-analyze time</command> ++ ++ This command prints the time spent in the kernel before userspace has been reached, the time ++ spent in the initial RAM disk (initrd) before normal system userspace has been reached, and the time ++ normal system userspace took to initialize. Note that these measurements simply measure the time passed ++ up to the point where all system services have been spawned, but not necessarily until they fully ++ finished initialization or the disk is idle. ++ ++ ++ <command>Show how long the boot took</command> ++ ++ # in a container ++$ systemd-analyze time ++Startup finished in 296ms (userspace) ++multi-user.target reached after 275ms in userspace ++ ++# on a real machine ++$ systemd-analyze time ++Startup finished in 2.584s (kernel) + 19.176s (initrd) + 47.847s (userspace) = 1min 9.608s ++multi-user.target reached after 47.820s in userspace ++ ++ ++ ++ ++ ++ <command>systemd-analyze blame</command> ++ ++ This command prints a list of all running units, ordered by the time they took to initialize. ++ This information may be used to optimize boot-up times. Note that the output might be misleading as the ++ initialization of one service might be slow simply because it waits for the initialization of another ++ service to complete. Also note: systemd-analyze blame doesn't display results for ++ services with Type=simple, because systemd considers such services to be started ++ immediately, hence no measurement of the initialization delays can be done. ++ ++ ++ <command>Show which units took the most time during boot</command> ++ ++ $ systemd-analyze blame ++ 32.875s pmlogger.service ++ 20.905s systemd-networkd-wait-online.service ++ 13.299s dev-vda1.device ++ ... ++ 23ms sysroot.mount ++ 11ms initrd-udevadm-cleanup-db.service ++ 3ms sys-kernel-config.mount ++ ++ ++ ++ ++ ++ <command>systemd-analyze critical-chain <optional><replaceable>UNIT</replaceable>...</optional></command> ++ ++ This command prints a tree of the time-critical chain of units (for each of the specified ++ UNITs or for the default target otherwise). The time after the unit is ++ active or started is printed after the "@" character. The time the unit takes to start is printed after ++ the "+" character. Note that the output might be misleading as the initialization of services might ++ depend on socket activation and because of the parallel execution of units. ++ ++ ++ <command>systemd-analyze time</command> ++ ++ $ systemd-analyze critical-chain ++multi-user.target @47.820s ++└─pmie.service @35.968s +548ms ++ └─pmcd.service @33.715s +2.247s ++ └─network-online.target @33.712s ++ └─systemd-networkd-wait-online.service @12.804s +20.905s ++ └─systemd-networkd.service @11.109s +1.690s ++ └─systemd-udevd.service @9.201s +1.904s ++ └─systemd-tmpfiles-setup-dev.service @7.306s +1.776s ++ └─kmod-static-nodes.service @6.976s +177ms ++ └─systemd-journald.socket ++ └─system.slice ++ └─-.slice ++ ++ ++ ++ ++ ++ <command>systemd-analyze log-level [<replaceable>LEVEL</replaceable>]</command> ++ ++ systemd-analyze log-level prints the current log level of the ++ systemd daemon. If an optional argument LEVEL is ++ provided, then the command changes the current log level of the systemd daemon to ++ LEVEL (accepts the same values as described in ++ systemd1). ++ ++ ++ ++ <command>systemd-analyze log-target [<replaceable>TARGET</replaceable>]</command> ++ ++ systemd-analyze log-target prints the current log target of the ++ systemd daemon. If an optional argument TARGET is ++ provided, then the command changes the current log target of the systemd daemon to ++ TARGET (accepts the same values as , described ++ in systemd1). ++ ++ ++ ++ <command>systemd-analyze service-watchdogs [yes|no]</command> ++ ++ systemd-analyze service-watchdogs prints the current state of service runtime ++ watchdogs of the systemd daemon. If an optional boolean argument is provided, then ++ globally enables or disables the service runtime watchdogs () and ++ emergency actions (e.g. or ); see ++ systemd.service5. ++ The hardware watchdog is not affected by this setting. ++ ++ ++ ++ <command>systemd-analyze dump</command> ++ ++ This command outputs a (usually very long) human-readable serialization of the complete server ++ state. Its format is subject to change without notice and should not be parsed by applications. ++ ++ ++ Show the internal state of user manager ++ ++ $ systemd-analyze --user dump ++Timestamp userspace: Thu 2019-03-14 23:28:07 CET ++Timestamp finish: Thu 2019-03-14 23:28:07 CET ++Timestamp generators-start: Thu 2019-03-14 23:28:07 CET ++Timestamp generators-finish: Thu 2019-03-14 23:28:07 CET ++Timestamp units-load-start: Thu 2019-03-14 23:28:07 CET ++Timestamp units-load-finish: Thu 2019-03-14 23:28:07 CET ++-> Unit proc-timer_list.mount: ++ Description: /proc/timer_list ++ ... ++-> Unit default.target: ++ Description: Main user target ++... ++ ++ ++ ++ ++ ++ <command>systemd-analyze plot</command> ++ ++ This command prints an SVG graphic detailing which system services have been started at what ++ time, highlighting the time they spent on initialization. ++ ++ ++ <command>Plot a bootchart</command> ++ ++ $ systemd-analyze plot >bootup.svg ++$ eog bootup.svg& ++ ++ ++ ++ ++ ++ <command>systemd-analyze dot [<replaceable>pattern</replaceable>...]</command> ++ ++ This command generates textual dependency graph description in dot format for further processing ++ with the GraphViz ++ dot1 ++ tool. Use a command line like systemd-analyze dot | dot -Tsvg >systemd.svg to ++ generate a graphical dependency tree. Unless or is ++ passed, the generated graph will show both ordering and requirement dependencies. Optional pattern ++ globbing style specifications (e.g. *.target) may be given at the end. A unit ++ dependency is included in the graph if any of these patterns match either the origin or destination ++ node. ++ ++ ++ Plot all dependencies of any unit whose name starts with <literal>avahi-daemon</literal> ++ ++ ++ $ systemd-analyze dot 'avahi-daemon.*' | dot -Tsvg >avahi.svg ++$ eog avahi.svg ++ ++ ++ ++ Plot the dependencies between all known target units + +- +- Showing logind configuration +- $ systemd-analyze cat-config systemd/logind.conf ++ $ systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' \ ++ | dot -Tsvg >targets.svg ++$ eog targets.svg ++ ++ ++ ++ ++ <command>systemd-analyze unit-paths</command> ++ ++ This command outputs a list of all directories from which unit files, .d ++ overrides, and .wants, .requires symlinks may be ++ loaded. Combine with to retrieve the list for the user manager instance, and ++ for the global configuration of user manager instances. ++ ++ ++ <command>Show all paths for generated units</command> ++ ++ $ systemd-analyze unit-paths | grep '^/run' ++/run/systemd/system.control ++/run/systemd/transient ++/run/systemd/generator.early ++/run/systemd/system ++/run/systemd/system.attached ++/run/systemd/generator ++/run/systemd/generator.late ++ ++ ++ ++ Note that this verb prints the list that is compiled into systemd-analyze ++ itself, and does not comunicate with the running manager. Use ++ systemctl [--user] [--global] show -p UnitPath --value ++ to retrieve the actual list that the manager uses, with any empty directories omitted. ++ ++ ++ ++ <command>systemd-analyze syscall-filter <optional><replaceable>SET</replaceable>...</optional></command> ++ ++ This command will list system calls contained in the specified system call set ++ SET, or all known sets if no sets are specified. Argument ++ SET must include the @ prefix. ++ ++ ++ ++ <command>systemd-analyze calendar <replaceable>EXPRESSION</replaceable>...</command> ++ ++ This command will parse and normalize repetitive calendar time events, and will calculate when ++ they elapse next. This takes the same input as the OnCalendar= setting in ++ systemd.timer5, ++ following the syntax described in ++ systemd.time7. By ++ default, only the next time the calendar expression will elapse is shown; use ++ to show the specified number of next times the expression ++ elapses. ++ ++ ++ Show leap days in the near future ++ ++ $ systemd-analyze calendar --iterations=5 '*-2-29 0:0:0' ++ Original form: *-2-29 0:0:0 ++Normalized form: *-02-29 00:00:00 ++ Next elapse: Sat 2020-02-29 00:00:00 UTC ++ From now: 11 months 15 days left ++ Iter. #2: Thu 2024-02-29 00:00:00 UTC ++ From now: 4 years 11 months left ++ Iter. #3: Tue 2028-02-29 00:00:00 UTC ++ From now: 8 years 11 months left ++ Iter. #4: Sun 2032-02-29 00:00:00 UTC ++ From now: 12 years 11 months left ++ Iter. #5: Fri 2036-02-29 00:00:00 UTC ++ From now: 16 years 11 months left ++ ++ ++ ++ ++ ++ <command>systemd-analyze timespan <replaceable>EXPRESSION</replaceable>...</command> ++ ++ This command parses a time span and outputs the normalized form and the equivalent value in ++ microseconds. The time span should adhere to the same syntax documented in ++ systemd.time7. ++ Values without associated magnitudes are parsed as seconds. ++ ++ ++ Show parsing of timespans ++ ++ $ systemd-analyze timespan 1s 300s '1year 0.000001s' ++Original: 1s ++ μs: 1000000 ++ Human: 1s ++ ++Original: 300s ++ μs: 300000000 ++ Human: 5min ++ ++Original: 1year 0.000001s ++ μs: 31557600000001 ++ Human: 1y 1us ++ ++ ++ ++ ++ ++ <command>systemd-analyze cat-config</command> ++ <replaceable>NAME</replaceable>|<replaceable>PATH</replaceable>... ++ ++ This command is similar to systemctl cat, but operates on config files. It ++ will copy the contents of a config file and any drop-ins to standard output, using the usual systemd ++ set of directories and rules for precedence. Each argument must be either an absolute path including ++ the prefix (such as /etc/systemd/logind.conf or ++ /usr/lib/systemd/logind.conf), or a name relative to the prefix (such as ++ systemd/logind.conf). ++ ++ ++ Showing logind configuration ++ $ systemd-analyze cat-config systemd/logind.conf + # /etc/systemd/logind.conf + ... + [Login] +@@ -201,90 +431,122 @@ NAutoVTs=8 + + # /etc/systemd/logind.conf.d/50-override.conf + ... some administrator override +- +- +- +- systemd-analyze unit-paths outputs a list of all +- directories from which unit files, .d overrides, and +- .wants, .requires symlinks may be +- loaded. Combine with to retrieve the list for the user +- manager instance, and for the global configuration of +- user manager instances. Note that this verb prints the list that is compiled into +- systemd-analyze itself, and does not comunicate with the +- running manager. Use +- systemctl [--user] [--global] show -p UnitPath --value +- to retrieve the actual list that the manager uses, with any empty directories +- omitted. +- +- systemd-analyze log-level +- prints the current log level of the systemd daemon. +- If an optional argument LEVEL is provided, then the command changes the current log +- level of the systemd daemon to LEVEL (accepts the same values as +- described in +- systemd1). +- +- systemd-analyze log-target +- prints the current log target of the systemd daemon. +- If an optional argument TARGET is provided, then the command changes the current log +- target of the systemd daemon to TARGET (accepts the same values as +- , described in +- systemd1). +- +- systemd-analyze syscall-filter SET +- will list system calls contained in the specified system call set SET, +- or all known sets if no sets are specified. Argument SET must include +- the @ prefix. +- +- systemd-analyze verify will load unit files and print +- warnings if any errors are detected. Files specified on the command line will be +- loaded, but also any other units referenced by them. The full unit search path is +- formed by combining the directories for all command line arguments, and the usual unit +- load paths (variable $SYSTEMD_UNIT_PATH is supported, and may be +- used to replace or augment the compiled in set of unit load paths; see +- systemd.unit5). +- All units files present in the directories containing the command line arguments will +- be used in preference to the other paths. +- +- systemd-analyze calendar will parse and normalize repetitive calendar time events, and +- will calculate when they will elapse next. This takes the same input as the OnCalendar= setting +- in systemd.timer5, following the +- syntax described in +- systemd.time7. +- +- systemd-analyze service-watchdogs +- prints the current state of service runtime watchdogs of the systemd daemon. +- If an optional boolean argument is provided, then globally enables or disables the service +- runtime watchdogs () and emergency actions (e.g. +- or ); see +- systemd.service5. +- The hardware watchdog is not affected by this setting. +- +- systemd-analyze security analyzes the security and sandboxing settings of one or more +- specified service units. If at least one unit name is specified the security settings of the specified service +- units are inspected and a detailed analysis is shown. If no unit name is specified, all currently loaded, +- long-running service units are inspected and a terse table with results shown. The command checks for various +- security-related service settings, assigning each a numeric "exposure level" value, depending on how important a +- setting is. It then calculates an overall exposure level for the whole unit, which is an estimation in the range +- 0.0…10.0 indicating how exposed a service is security-wise. High exposure levels indicate very little applied +- sandboxing. Low exposure levels indicate tight sandboxing and strongest security restrictions. Note that this only +- analyzes the per-service security features systemd itself implements. This means that any additional security +- mechanisms applied by the service code itself are not accounted for. The exposure level determined this way should +- not be misunderstood: a high exposure level neither means that there is no effective sandboxing applied by the +- service code itself, nor that the service is actually vulnerable to remote or local attacks. High exposure levels +- do indicate however that most likely the service might benefit from additional settings applied to them. Please +- note that many of the security and sandboxing settings individually can be circumvented — unless combined with +- others. For example, if a service retains the privilege to establish or undo mount points many of the sandboxing +- options can be undone by the service code itself. Due to that is essential that each service uses the most +- comprehensive and strict sandboxing and security settings possible. The tool will take into account some of these +- combinations and relationships between the settings, but not all. Also note that the security and sandboxing +- settings analyzed here only apply to the operations executed by the service code itself. If a service has access to +- an IPC system (such as D-Bus) it might request operations from other services that are not subject to the same +- restrictions. Any comprehensive security and sandboxing analysis is hence incomplete if the IPC access policy is +- not validated too. ++ ++ ++ + +- If no command is passed, systemd-analyze +- time is implied. ++ ++ <command>systemd-analyze verify <replaceable>FILE</replaceable>...</command> ++ ++ This command will load unit files and print warnings if any errors are detected. Files specified ++ on the command line will be loaded, but also any other units referenced by them. The full unit search ++ path is formed by combining the directories for all command line arguments, and the usual unit load ++ paths (variable $SYSTEMD_UNIT_PATH is supported, and may be used to replace or ++ augment the compiled in set of unit load paths; see ++ systemd.unit5). All ++ units files present in the directories containing the command line arguments will be used in preference ++ to the other paths. ++ ++ The following errors are currently detected: ++ ++ unknown sections and directives, ++ ++ missing dependencies which are required to start the given unit, ++ ++ man pages listed in Documentation= which are not found in the ++ system, ++ ++ commands listed in ExecStart= and similar which are not found in ++ the system or not executable. ++ + ++ ++ Misspelt directives ++ ++ $ cat ./user.slice ++[Unit] ++WhatIsThis=11 ++Documentation=man:nosuchfile(1) ++Requires=different.service ++ ++[Service] ++Description=x ++ ++$ systemd-analyze verify ./user.slice ++[./user.slice:9] Unknown lvalue 'WhatIsThis' in section 'Unit' ++[./user.slice:13] Unknown section 'Service'. Ignoring. ++Error: org.freedesktop.systemd1.LoadFailed: ++ Unit different.service failed to load: ++ No such file or directory. ++Failed to create user.slice/start: Invalid argument ++user.slice: man nosuchfile(1) command failed with code 16 ++ ++ ++ ++ ++ Missing service units ++ ++ $ tail ./a.socket ./b.socket ++==> ./a.socket <== ++[Socket] ++ListenStream=100 ++ ++==> ./b.socket <== ++[Socket] ++ListenStream=100 ++Accept=yes ++ ++$ systemd-analyze verify ./a.socket ./b.socket ++Service a.service not loaded, a.socket cannot be started. ++Service b@0.service not loaded, b.socket cannot be started. ++ ++ ++ ++ ++ ++ <command>systemd-analyze security <optional><replaceable>UNIT</replaceable>...</optional></command> ++ ++ This command analyzes the security and sandboxing settings of one or more specified service ++ units. If at least one unit name is specified the security settings of the specified service units are ++ inspected and a detailed analysis is shown. If no unit name is specified, all currently loaded, ++ long-running service units are inspected and a terse table with results shown. The command checks for ++ various security-related service settings, assigning each a numeric "exposure level" value, depending ++ on how important a setting is. It then calculates an overall exposure level for the whole unit, which ++ is an estimation in the range 0.0…10.0 indicating how exposed a service is security-wise. High exposure ++ levels indicate very little applied sandboxing. Low exposure levels indicate tight sandboxing and ++ strongest security restrictions. Note that this only analyzes the per-service security features systemd ++ itself implements. This means that any additional security mechanisms applied by the service code ++ itself are not accounted for. The exposure level determined this way should not be misunderstood: a ++ high exposure level neither means that there is no effective sandboxing applied by the service code ++ itself, nor that the service is actually vulnerable to remote or local attacks. High exposure levels do ++ indicate however that most likely the service might benefit from additional settings applied to ++ them. ++ ++ Please note that many of the security and sandboxing settings individually can be circumvented — ++ unless combined with others. For example, if a service retains the privilege to establish or undo mount ++ points many of the sandboxing options can be undone by the service code itself. Due to that is ++ essential that each service uses the most comprehensive and strict sandboxing and security settings ++ possible. The tool will take into account some of these combinations and relationships between the ++ settings, but not all. Also note that the security and sandboxing settings analyzed here only apply to ++ the operations executed by the service code itself. If a service has access to an IPC system (such as ++ D-Bus) it might request operations from other services that are not subject to the same ++ restrictions. Any comprehensive security and sandboxing analysis is hence incomplete if the IPC access ++ policy is not validated too. ++ ++ ++ Analyze <filename noindex="true">systemd-logind.service</filename> ++ ++ $ systemd-analyze security --no-pager systemd-logind.service ++ NAME DESCRIPTION EXPOSURE ++✗ PrivateNetwork= Service has access to the host's network 0.5 ++✗ User=/DynamicUser= Service runs as root user 0.4 ++✗ DeviceAllow= Service has no device ACL 0.2 ++✓ IPAddressDeny= Service blocks all IP address ranges ++... ++→ Overall exposure level for systemd-logind.service: 4.1 OK 🙂 ++ ++ ++ + + + +@@ -408,88 +670,6 @@ NAutoVTs=8 + otherwise. + + +- +- Examples for <command>dot</command> +- +- +- Plots all dependencies of any unit whose name starts with +- <literal>avahi-daemon</literal> +- +- $ systemd-analyze dot 'avahi-daemon.*' | dot -Tsvg > avahi.svg +-$ eog avahi.svg +- +- +- +- Plots the dependencies between all known target units +- +- $ systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' | dot -Tsvg > targets.svg +-$ eog targets.svg +- +- +- +- +- Examples for <command>verify</command> +- +- The following errors are currently detected: +- +- unknown sections and directives, +- +- +- missing dependencies which are required to start +- the given unit, +- +- man pages listed in +- Documentation= which are not found in the +- system, +- +- commands listed in ExecStart= +- and similar which are not found in the system or not +- executable. +- +- +- +- Misspelt directives +- +- $ cat ./user.slice +-[Unit] +-WhatIsThis=11 +-Documentation=man:nosuchfile(1) +-Requires=different.service +- +-[Service] +-Description=x +- +-$ systemd-analyze verify ./user.slice +-[./user.slice:9] Unknown lvalue 'WhatIsThis' in section 'Unit' +-[./user.slice:13] Unknown section 'Service'. Ignoring. +-Error: org.freedesktop.systemd1.LoadFailed: +- Unit different.service failed to load: +- No such file or directory. +-Failed to create user.slice/start: Invalid argument +-user.slice: man nosuchfile(1) command failed with code 16 +- +- +- +- +- Missing service units +- +- $ tail ./a.socket ./b.socket +-==> ./a.socket <== +-[Socket] +-ListenStream=100 +- +-==> ./b.socket <== +-[Socket] +-ListenStream=100 +-Accept=yes +- +-$ systemd-analyze verify ./a.socket ./b.socket +-Service a.service not loaded, a.socket cannot be started. +-Service b@0.service not loaded, b.socket cannot be started. +- +- +- +- + + + diff --git a/SOURCES/0218-sd-bus-adjust-indentation-of-comments.patch b/SOURCES/0218-sd-bus-adjust-indentation-of-comments.patch deleted file mode 100644 index 14b6174..0000000 --- a/SOURCES/0218-sd-bus-adjust-indentation-of-comments.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0bd92f0fbaf7105b6d1dd6a2d96dad7e5522e027 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Tue, 27 Aug 2019 19:00:50 +0200 -Subject: [PATCH] sd-bus: adjust indentation of comments - -Related: #1746857 ---- - src/libsystemd/sd-bus/sd-bus.c | 3 +-- - src/shared/bus-util.c | 7 ++++--- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index 3583e24e64..1c9e967ae0 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -1341,8 +1341,7 @@ _public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *descrip - b->bus_client = true; - b->is_user = true; - -- /* We don't do any per-method access control on the user -- * bus. */ -+ /* We don't do any per-method access control on the user bus. */ - b->trusted = true; - b->is_local = true; - -diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c -index 302dbb4c2e..2d908eb45c 100644 ---- a/src/shared/bus-util.c -+++ b/src/shared/bus-util.c -@@ -1675,7 +1675,8 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri - - assert(ret); - -- /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */ -+ /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal -+ * turned on. */ - - r = sd_bus_new(&bus); - if (r < 0) -@@ -1890,8 +1891,8 @@ int bus_reply_pair_array(sd_bus_message *m, char **l) { - - assert(m); - -- /* Reply to the specified message with a message containing a dictionary put together from the specified -- * strv */ -+ /* Reply to the specified message with a message containing a dictionary put together from the -+ * specified strv */ - - r = sd_bus_message_new_method_return(m, &reply); - if (r < 0) diff --git a/SOURCES/0219-resolved-do-not-run-loop-twice.patch b/SOURCES/0219-resolved-do-not-run-loop-twice.patch deleted file mode 100644 index 4a706d4..0000000 --- a/SOURCES/0219-resolved-do-not-run-loop-twice.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 1ae0cf8c3ae565a19283d628f833668babf81b82 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Tue, 27 Aug 2019 19:02:53 +0200 -Subject: [PATCH] resolved: do not run loop twice - -This doesn't matter much, but let's just do the loop once and allocate -the populate the result set on the fly. If we find an error, it'll get -cleaned up automatically. - -Related: #1746857 ---- - src/resolve/resolved-link-bus.c | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - -diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c -index b1581740d8..46d2b11636 100644 ---- a/src/resolve/resolved-link-bus.c -+++ b/src/resolve/resolved-link-bus.c -@@ -492,6 +492,10 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v - if (r < 0) - return r; - -+ ns = set_new(&dns_name_hash_ops); -+ if (!ns) -+ return -ENOMEM; -+ - r = sd_bus_message_read_strv(message, &ntas); - if (r < 0) - return r; -@@ -501,14 +505,9 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v - if (r < 0) - return r; - if (r == 0) -- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i); -- } -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, -+ "Invalid negative trust anchor domain: %s", *i); - -- ns = set_new(&dns_name_hash_ops); -- if (!ns) -- return -ENOMEM; -- -- STRV_FOREACH(i, ntas) { - r = set_put_strdup(ns, *i); - if (r < 0) - return r; diff --git a/SOURCES/0219-travis-move-to-CentOS-8-docker-images.patch b/SOURCES/0219-travis-move-to-CentOS-8-docker-images.patch new file mode 100644 index 0000000..f5ba536 --- /dev/null +++ b/SOURCES/0219-travis-move-to-CentOS-8-docker-images.patch @@ -0,0 +1,132 @@ +From ac7db0c5b48f1090f77dbcfa0a1e0dc08d5c471e Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 14 Oct 2019 15:26:48 +0200 +Subject: [PATCH] travis: move to CentOS 8 docker images + +As the CentOS 8 Docker images is finally out, we can use it and drop the +plethora of workarounds we had to implement to compile RHEL8 systemd on +CentOS 7. + +Resolves: #1761519 +--- + .travis.yml | 22 ++++++++++------------ + ci/travis-centos-rhel8.sh | 32 +++++++++----------------------- + 2 files changed, 19 insertions(+), 35 deletions(-) + +diff --git a/.travis.yml b/.travis.yml +index 0010da5784..70c60cf24e 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -9,42 +9,40 @@ env: + + jobs: + include: +- - name: CentOS 7 ++ - name: CentOS 8 + language: bash + env: +- - CENTOS_RELEASE="centos7" ++ - CENTOS_RELEASE="centos8" + - CONT_NAME="systemd-centos-$CENTOS_RELEASE" + - DOCKER_EXEC="docker exec -ti $CONT_NAME" + before_install: + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + - docker --version + install: +- - if [ -f meson.build ]; then RHEL_VERSION=rhel8; else RHEL_VERSION=rhel7; fi +- - $CI_ROOT/travis-centos-${RHEL_VERSION}.sh SETUP ++ - $CI_ROOT/travis-centos-rhel8.sh SETUP + script: + - set -e + # Build systemd +- - $CI_ROOT/travis-centos-${RHEL_VERSION}.sh RUN ++ - $CI_ROOT/travis-centos-rhel8.sh RUN + - set +e + after_script: +- - $CI_ROOT/travis-centos-${RHEL_VERSION}.sh CLEANUP ++ - $CI_ROOT/travis-centos-rhel8.sh CLEANUP + +- - name: CentOS 7 (ASan+UBSan) ++ - name: CentOS 8 (ASan+UBSan) + language: bash + env: +- - CENTOS_RELEASE="centos7" ++ - CENTOS_RELEASE="centos8" + - CONT_NAME="systemd-centos-$CENTOS_RELEASE" + - DOCKER_EXEC="docker exec -ti $CONT_NAME" + before_install: + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + - docker --version + install: +- - if [ -f meson.build ]; then RHEL_VERSION=rhel8; else RHEL_VERSION=rhel7; fi +- - $CI_ROOT/travis-centos-${RHEL_VERSION}.sh SETUP ++ - $CI_ROOT/travis-centos-rhel8.sh SETUP + script: + - set -e + # Build systemd +- - $CI_ROOT/travis-centos-${RHEL_VERSION}.sh RUN_ASAN ++ - $CI_ROOT/travis-centos-rhel8.sh RUN_ASAN + - set +e + after_script: +- - $CI_ROOT/travis-centos-${RHEL_VERSION}.sh CLEANUP ++ - $CI_ROOT/travis-centos-rhel8.sh CLEANUP +diff --git a/ci/travis-centos-rhel8.sh b/ci/travis-centos-rhel8.sh +index c3d1018682..ade44a0413 100755 +--- a/ci/travis-centos-rhel8.sh ++++ b/ci/travis-centos-rhel8.sh +@@ -15,10 +15,7 @@ CONT_NAME="${CONT_NAME:-centos-$CENTOS_RELEASE-$RANDOM}" + DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}" + DOCKER_RUN="${DOCKER_RUN:-docker run}" + REPO_ROOT="${REPO_ROOT:-$PWD}" +-ADDITIONAL_DEPS=(systemd-ci-environment libidn2-devel python-lxml python36 ninja-build libasan net-tools strace nc busybox e2fsprogs quota dnsmasq) +-# Repo with additional depencencies to compile newer systemd on CentOS 7 +-COPR_REPO="https://copr.fedorainfracloud.org/coprs/mrc0mmand/systemd-centos-ci/repo/epel-7/mrc0mmand-systemd-centos-ci-epel-7.repo" +-COPR_REPO_PATH="/etc/yum.repos.d/${COPR_REPO##*/}" ++ADDITIONAL_DEPS=(libasan libubsan net-tools strace nc e2fsprogs quota dnsmasq) + # RHEL8 options + CONFIGURE_OPTS=( + -Dsysvinit-path=/etc/rc.d/init.d +@@ -95,18 +92,14 @@ for phase in "${PHASES[@]}"; do + -dit --net=host centos:$CENTOS_RELEASE /sbin/init + # Beautiful workaround for Fedora's version of Docker + sleep 1 +- $DOCKER_EXEC yum makecache +- $DOCKER_EXEC curl "$COPR_REPO" -o "$COPR_REPO_PATH" +- $DOCKER_EXEC yum -q -y install epel-release yum-utils +- $DOCKER_EXEC yum-config-manager -q --enable epel +- $DOCKER_EXEC yum -y upgrade +- # Install necessary build/test requirements +- $DOCKER_EXEC yum -y install "${ADDITIONAL_DEPS[@]}" +- $DOCKER_EXEC python3.6 -m ensurepip +- $DOCKER_EXEC python3.6 -m pip install meson +- # Create necessary symlinks +- $DOCKER_EXEC ln --force -s /usr/bin/python3.6 /usr/bin/python3 +- $DOCKER_EXEC ln --force -s /usr/bin/ninja-build /usr/bin/ninja ++ $DOCKER_EXEC dnf makecache ++ # Install and enable EPEL ++ $DOCKER_EXEC dnf -q -y install epel-release dnf-utils "${ADDITIONAL_DEPS[@]}" ++ $DOCKER_EXEC dnf config-manager -q --enable epel ++ # Upgrade the container to get the most recent environment ++ $DOCKER_EXEC dnf -y upgrade ++ # Install systemd's build dependencies ++ $DOCKER_EXEC dnf -q -y --enablerepo "PowerTools" builddep systemd + ;; + RUN) + info "Run phase" +@@ -117,16 +110,9 @@ for phase in "${PHASES[@]}"; do + # unexpected fails due to incompatibilities with older systemd + $DOCKER_EXEC ninja -C build install + docker restart $CONT_NAME +- # "Mask" the udev-test.pl, as it requires newer version of systemd-detect-virt +- # and it's pointless to run it on a VM in a Docker container... +- echo -ne "#!/usr/bin/perl\nexit(0);\n" > "test/udev-test.pl" + $DOCKER_EXEC ninja -C build test + ;; + RUN_ASAN|RUN_CLANG_ASAN) +- # Let's install newer gcc for proper ASan/UBSan support +- $DOCKER_EXEC yum -y install centos-release-scl +- $DOCKER_EXEC yum -y install devtoolset-8 devtoolset-8-libasan-devel libasan5 devtoolset-8-libubsan-devel libubsan1 +- $DOCKER_EXEC bash -c "echo 'source scl_source enable devtoolset-8' >> /root/.bashrc" + # Note to my future frustrated self: docker exec runs the given command + # as sh -c 'command' - which means both .bash_profile and .bashrc will + # be ignored. That's because .bash_profile is sourced for LOGIN shells (i.e. diff --git a/SOURCES/0220-resolved-allow-access-to-Set-Link-and-Revert-methods.patch b/SOURCES/0220-resolved-allow-access-to-Set-Link-and-Revert-methods.patch deleted file mode 100644 index 0d8cbcd..0000000 --- a/SOURCES/0220-resolved-allow-access-to-Set-Link-and-Revert-methods.patch +++ /dev/null @@ -1,347 +0,0 @@ -From aa39a552bb52287c1a1da56e109c0fb4c0dc9621 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Tue, 27 Aug 2019 19:25:05 +0200 -Subject: [PATCH] resolved: allow access to Set*Link and Revert methods through - polkit - -This matches what is done in networkd very closely. In fact even the -policy descriptions are all identical (with s/network/resolve), except -for the last one: -resolved has org.freedesktop.resolve1.revert while -networkd has org.freedesktop.network1.revert-ntp and -org.freedesktop.network1.revert-dns so the description is a bit different. - -Conflicts: - src/resolve/resolved-bus.c - src/resolve/resolved-link-bus.c - -Related: #1746857 ---- - src/resolve/org.freedesktop.resolve1.policy | 99 +++++++++++++++++++++ - src/resolve/resolved-bus.c | 22 ++--- - src/resolve/resolved-link-bus.c | 97 +++++++++++++++++--- - 3 files changed, 197 insertions(+), 21 deletions(-) - -diff --git a/src/resolve/org.freedesktop.resolve1.policy b/src/resolve/org.freedesktop.resolve1.policy -index b65ba3e56a..592c4eb8b0 100644 ---- a/src/resolve/org.freedesktop.resolve1.policy -+++ b/src/resolve/org.freedesktop.resolve1.policy -@@ -40,4 +40,103 @@ - unix-user:systemd-resolve - - -+ -+ Set DNS servers -+ Authentication is required to set DNS servers. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Set domains -+ Authentication is required to set domains. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Set default route -+ Authentication is required to set default route. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Enable/disable LLMNR -+ Authentication is required to enable or disable LLMNR. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Enable/disable multicast DNS -+ Authentication is required to enable or disable multicast DNS. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Enable/disable DNS over TLS -+ Authentication is required to enable or disable DNS over TLS. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Enable/disable DNSSEC -+ Authentication is required to enable or disable DNSSEC. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Set DNSSEC Negative Trust Anchors -+ Authentication is required to set DNSSEC Negative Trust Anchros. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ -+ -+ Revert name resolution settings -+ Authentication is required to revert name resolution settings. -+ -+ auth_admin -+ auth_admin -+ auth_admin_keep -+ -+ unix-user:systemd-resolve -+ -+ - -diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c -index da0a909dd6..4d6cc4fd48 100644 ---- a/src/resolve/resolved-bus.c -+++ b/src/resolve/resolved-bus.c -@@ -1848,18 +1848,18 @@ static const sd_bus_vtable resolve_vtable[] = { - SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED), -- SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0), -- SD_BUS_METHOD("FlushCaches", NULL, NULL, bus_method_flush_caches, 0), -- SD_BUS_METHOD("ResetServerFeatures", NULL, NULL, bus_method_reset_server_features, 0), -+ SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("FlushCaches", NULL, NULL, bus_method_flush_caches, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("ResetServerFeatures", NULL, NULL, bus_method_reset_server_features, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED), -- SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0), -- SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, 0), -- SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0), -- SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0), -- SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, 0), -- SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0), -- SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, 0), -- SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, 0), -+ SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, SD_BUS_VTABLE_UNPRIVILEGED), - - SD_BUS_METHOD("RegisterService", "sssqqqaa{say}", "o", bus_method_register_service, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("UnregisterService", "o", NULL, bus_method_unregister_service, SD_BUS_VTABLE_UNPRIVILEGED), -diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c -index 46d2b11636..bf3e42264e 100644 ---- a/src/resolve/resolved-link-bus.c -+++ b/src/resolve/resolved-link-bus.c -@@ -1,5 +1,9 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - -+#include -+#include -+#include -+ - #include "alloc-util.h" - #include "bus-common-errors.h" - #include "bus-util.h" -@@ -9,6 +13,7 @@ - #include "resolved-link-bus.h" - #include "resolved-resolv-conf.h" - #include "strv.h" -+#include "user-util.h" - - static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported); - static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string); -@@ -235,6 +240,15 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ - if (r < 0) - return r; - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.set-dns-servers", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - dns_server_mark_all(l->dns_servers); - - for (i = 0; i < n; i++) { -@@ -298,12 +312,21 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_ - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain"); - } - -- dns_search_domain_mark_all(l->search_domains); -- - r = sd_bus_message_rewind(message, false); - if (r < 0) - return r; - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.set-domains", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ -+ dns_search_domain_mark_all(l->search_domains); -+ - for (;;) { - DnsSearchDomain *d; - const char *name; -@@ -371,6 +394,15 @@ int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_er - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr); - } - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.set-llmnr", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - l->llmnr_support = mode; - link_allocate_scopes(l); - link_add_rrs(l, false); -@@ -405,6 +437,15 @@ int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_err - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns); - } - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.set-mdns", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - l->mdns_support = mode; - link_allocate_scopes(l); - link_add_rrs(l, false); -@@ -439,6 +480,15 @@ int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls); - } - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.set-dns-over-tls", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - link_set_dns_over_tls_mode(l, mode); - - (void) link_save_user(l); -@@ -471,6 +521,15 @@ int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_e - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec); - } - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.set-dnssec", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - link_set_dnssec_mode(l, mode); - - (void) link_save_user(l); -@@ -513,6 +572,15 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v - return r; - } - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.set-dnssec-negative-trust-anchors", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - set_free_free(l->dnssec_negative_trust_anchors); - l->dnssec_negative_trust_anchors = TAKE_PTR(ns); - -@@ -532,6 +600,15 @@ int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error - if (r < 0) - return r; - -+ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, -+ "org.freedesktop.resolve1.revert", -+ NULL, true, UID_INVALID, -+ &l->manager->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - link_flush_settings(l); - link_allocate_scopes(l); - link_add_rrs(l, false); -@@ -556,14 +633,14 @@ const sd_bus_vtable link_vtable[] = { - SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0), - SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0), - -- SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0), -- SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, 0), -- SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0), -- SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0), -- SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, 0), -- SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0), -- SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, 0), -- SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, 0), -+ SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, SD_BUS_VTABLE_UNPRIVILEGED), - - SD_BUS_VTABLE_END - }; diff --git a/SOURCES/0220-travis-drop-SCL-remains.patch b/SOURCES/0220-travis-drop-SCL-remains.patch new file mode 100644 index 0000000..30d5378 --- /dev/null +++ b/SOURCES/0220-travis-drop-SCL-remains.patch @@ -0,0 +1,50 @@ +From 5b14988845b591f6fa2fc1e032618fe882827f4a Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 14 Oct 2019 16:22:51 +0200 +Subject: [PATCH] travis: drop SCL remains + +The `bash -ic` wrapper existed solely to make SCL work as expected + +Resolves: #1761519 +--- + ci/travis-centos-rhel8.sh | 16 +++------------- + 1 file changed, 3 insertions(+), 13 deletions(-) + +diff --git a/ci/travis-centos-rhel8.sh b/ci/travis-centos-rhel8.sh +index ade44a0413..da131c726b 100755 +--- a/ci/travis-centos-rhel8.sh ++++ b/ci/travis-centos-rhel8.sh +@@ -113,22 +113,12 @@ for phase in "${PHASES[@]}"; do + $DOCKER_EXEC ninja -C build test + ;; + RUN_ASAN|RUN_CLANG_ASAN) +- # Note to my future frustrated self: docker exec runs the given command +- # as sh -c 'command' - which means both .bash_profile and .bashrc will +- # be ignored. That's because .bash_profile is sourced for LOGIN shells (i.e. +- # sh -l), whereas .bashrc is sourced for NON-LOGIN INTERACTIVE shells +- # (i.e. sh -i). +- # As the default docker exec command lacks either of those options, +- # we need to use a wrapper command which runs the wanted command +- # under an explicit bash -i, so the SCL source above works properly. +- docker exec -it $CONT_NAME bash -ic 'gcc --version' +- + if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then + ENV_VARS="-e CC=clang -e CXX=clang++" + MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764 + fi +- docker exec $ENV_VARS -it $CONT_NAME bash -ic "meson build --werror -Dtests=unsafe -Db_sanitize=address,undefined $MESON_ARGS ${CONFIGURE_OPTS[@]}" +- docker exec -it $CONT_NAME bash -ic 'ninja -v -C build' ++ docker exec $ENV_VARS -it $CONT_NAME meson build --werror -Dtests=unsafe -Db_sanitize=address,undefined $MESON_ARGS ${CONFIGURE_OPTS[@]} ++ docker exec -it $CONT_NAME ninja -v -C build + + # Never remove halt_on_error from UBSAN_OPTIONS. See https://github.com/systemd/systemd/commit/2614d83aa06592aedb. + travis_wait docker exec --interactive=false \ +@@ -136,7 +126,7 @@ for phase in "${PHASES[@]}"; do + -e ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 \ + -e "TRAVIS=$TRAVIS" \ + -t $CONT_NAME \ +- bash -ic 'meson test --timeout-multiplier=3 -C ./build/ --print-errorlogs' ++ meson test --timeout-multiplier=3 -C ./build/ --print-errorlogs + ;; + CLEANUP) + info "Cleanup phase" diff --git a/SOURCES/0221-resolved-query-polkit-only-after-parsing-the-data.patch b/SOURCES/0221-resolved-query-polkit-only-after-parsing-the-data.patch deleted file mode 100644 index c94d670..0000000 --- a/SOURCES/0221-resolved-query-polkit-only-after-parsing-the-data.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 7c9077683df0c3959b1bcae973a05e114b15a600 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Tue, 27 Aug 2019 19:28:19 +0200 -Subject: [PATCH] resolved: query polkit only after parsing the data - -That's what we do everywhere else because it leads to nicer user experience. - -Related: #1746857 ---- - src/resolve/resolved-bus.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c -index 4d6cc4fd48..3f6a6f9e12 100644 ---- a/src/resolve/resolved-bus.c -+++ b/src/resolve/resolved-bus.c -@@ -1632,15 +1632,6 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, - if (m->mdns_support != RESOLVE_SUPPORT_YES) - return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled"); - -- r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, -- "org.freedesktop.resolve1.register-service", -- NULL, false, UID_INVALID, -- &m->polkit_registry, error); -- if (r < 0) -- return r; -- if (r == 0) -- return 1; /* Polkit will call us back */ -- - service = new0(DnssdService, 1); - if (!service) - return log_oom(); -@@ -1765,6 +1756,15 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, - if (r < 0) - return r; - -+ r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, -+ "org.freedesktop.resolve1.register-service", -+ NULL, false, UID_INVALID, -+ &m->polkit_registry, error); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return 1; /* Polkit will call us back */ -+ - r = hashmap_ensure_allocated(&m->dnssd_services, &string_hash_ops); - if (r < 0) - return r; diff --git a/SOURCES/0221-syslog-fix-segfault-in-syslog_parse_priority.patch b/SOURCES/0221-syslog-fix-segfault-in-syslog_parse_priority.patch new file mode 100644 index 0000000..97f64e0 --- /dev/null +++ b/SOURCES/0221-syslog-fix-segfault-in-syslog_parse_priority.patch @@ -0,0 +1,110 @@ +From 8bd791fb3a8e85063e297204bdef8004aacd22b1 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 8 Aug 2018 18:27:15 +0900 +Subject: [PATCH] syslog: fix segfault in syslog_parse_priority() + +(cherry picked from commit a5ee33b951cfa22db53d0274c9c6c0d9d4dae39d) + +Resolves: #1761519 +--- + src/basic/syslog-util.c | 20 +++++++++++--------- + src/journal/test-journal-syslog.c | 20 ++++++++++++++++++++ + 2 files changed, 31 insertions(+), 9 deletions(-) + +diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c +index 21461fa581..fe129482f3 100644 +--- a/src/basic/syslog-util.c ++++ b/src/basic/syslog-util.c +@@ -10,7 +10,8 @@ + + int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + int a = 0, b = 0, c = 0; +- int k; ++ const char *end; ++ size_t k; + + assert(p); + assert(*p); +@@ -19,21 +20,22 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + if ((*p)[0] != '<') + return 0; + +- if (!strchr(*p, '>')) ++ end = strchr(*p, '>'); ++ if (!end) + return 0; + +- if ((*p)[2] == '>') { ++ k = end - *p; ++ assert(k > 0); ++ ++ if (k == 2) + c = undecchar((*p)[1]); +- k = 3; +- } else if ((*p)[3] == '>') { ++ else if (k == 3) { + b = undecchar((*p)[1]); + c = undecchar((*p)[2]); +- k = 4; +- } else if ((*p)[4] == '>') { ++ } else if (k == 4) { + a = undecchar((*p)[1]); + b = undecchar((*p)[2]); + c = undecchar((*p)[3]); +- k = 5; + } else + return 0; + +@@ -46,7 +48,7 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + else + *priority = (*priority & LOG_FACMASK) | c; + +- *p += k; ++ *p += k + 1; + return 1; + } + +diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c +index 7294cde032..120477cc9f 100644 +--- a/src/journal/test-journal-syslog.c ++++ b/src/journal/test-journal-syslog.c +@@ -4,6 +4,7 @@ + #include "journald-syslog.h" + #include "macro.h" + #include "string-util.h" ++#include "syslog-util.h" + + static void test_syslog_parse_identifier(const char *str, + const char *ident, const char *pid, const char *rest, int ret) { +@@ -19,6 +20,17 @@ static void test_syslog_parse_identifier(const char *str, + assert_se(streq(buf, rest)); + } + ++static void test_syslog_parse_priority(const char *str, int priority, int ret) { ++ const char *buf = str; ++ int priority2, ret2; ++ ++ ret2 = syslog_parse_priority(&buf, &priority2, false); ++ ++ assert_se(ret == ret2); ++ if (ret2 == 1) ++ assert_se(priority == priority2); ++} ++ + int main(void) { + test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", "xxx", 11); + test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, "xxx", 6); +@@ -33,5 +45,13 @@ int main(void) { + test_syslog_parse_identifier("pidu: ", "pidu", NULL, "", 6); + test_syslog_parse_identifier("pidu : ", NULL, NULL, "pidu : ", 0); + ++ test_syslog_parse_priority("<>", 0, 0); ++ test_syslog_parse_priority("<>aaa", 0, 0); ++ test_syslog_parse_priority("", 0, 0); ++ test_syslog_parse_priority("aaa", 0, 0); ++ test_syslog_parse_priority(" ", 0, 0); ++ test_syslog_parse_priority(" aaa", 0, 0); ++ /* TODO: add test cases of valid priorities */ ++ + return 0; + } diff --git a/SOURCES/0222-ask-password-prevent-buffer-overrow-when-reading-fro.patch b/SOURCES/0222-ask-password-prevent-buffer-overrow-when-reading-fro.patch deleted file mode 100644 index aa2bc12..0000000 --- a/SOURCES/0222-ask-password-prevent-buffer-overrow-when-reading-fro.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 7200c0b173bec49c63ac5ecdf6d510d26e8c8271 Mon Sep 17 00:00:00 2001 -From: Thadeu Lima de Souza Cascardo -Date: Mon, 13 May 2019 16:58:01 -0300 -Subject: [PATCH] ask-password: prevent buffer overrow when reading from - keyring - -When we read from keyring, a temporary buffer is allocated in order to -determine the size needed for the entire data. However, when zeroing that area, -we use the data size returned by the read instead of the lesser size allocate -for the buffer. - -That will cause memory corruption that causes systemd-cryptsetup to crash -either when a single large password is used or when multiple passwords have -already been pushed to the keyring. - -Signed-off-by: Thadeu Lima de Souza Cascardo -(cherry picked from commit 59c55e73eaee345e1ee67c23eace8895ed499693) -(cherry picked from commit c6c8e0d097d6ba12471c6112c3fd339ea40329d5) - -Resolves: #1777037 ---- - src/shared/ask-password-api.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c -index 682dc754fc..764ebd08e1 100644 ---- a/src/shared/ask-password-api.c -+++ b/src/shared/ask-password-api.c -@@ -79,7 +79,7 @@ static int retrieve_key(key_serial_t serial, char ***ret) { - if (n < m) - break; - -- explicit_bzero(p, n); -+ explicit_bzero(p, m); - free(p); - m *= 2; - } diff --git a/SOURCES/0222-sd-bus-make-strict-asan-shut-up.patch b/SOURCES/0222-sd-bus-make-strict-asan-shut-up.patch new file mode 100644 index 0000000..bfe310a --- /dev/null +++ b/SOURCES/0222-sd-bus-make-strict-asan-shut-up.patch @@ -0,0 +1,45 @@ +From fbe5fa22f5b99d4e444db54aadb661e9c932eb6c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 16 Nov 2018 13:00:40 +0100 +Subject: [PATCH] sd-bus: make strict asan shut up + +asan doesn't like it if we use strndup() (i.e. a string function) on a +non-NULL terminated buffer (i.e. something that isn't really a string). + +Let's hence use memdup_suffix0() instead of strndup(), which is more +appropriate for binary data that is to become a string. + +Fixes: #10385 +(cherry picked from commit ac0a94f7438b49a0890d9806db1fa211a5bca10a) + +Resolves: #1761519 +--- + src/libsystemd/sd-bus/bus-message.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index 53cbd675b7..19cb2b9a97 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -5101,6 +5101,7 @@ int bus_message_parse_fields(sd_bus_message *m) { + return -EBADMSG; + + if (*p == 0) { ++ char *k; + size_t l; + + /* We found the beginning of the signature +@@ -5114,9 +5115,11 @@ int bus_message_parse_fields(sd_bus_message *m) { + p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END) + return -EBADMSG; + +- if (free_and_strndup(&m->root_container.signature, +- p + 1 + 1, l - 2) < 0) ++ k = memdup_suffix0(p + 1 + 1, l - 2); ++ if (!k) + return -ENOMEM; ++ ++ free_and_replace(m->root_container.signature, k); + break; + } + diff --git a/SOURCES/0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch b/SOURCES/0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch deleted file mode 100644 index 117dca9..0000000 --- a/SOURCES/0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch +++ /dev/null @@ -1,136 +0,0 @@ -From c4a7251ed4ca98d6d4faf6228ffe68166c1906cb Mon Sep 17 00:00:00 2001 -From: HATAYAMA Daisuke -Date: Mon, 28 Oct 2019 19:35:24 +0900 -Subject: [PATCH] core, job: fix breakage of ordering dependencies by systemctl - reload command - -Currently, systemctl reload command breaks ordering dependencies if it's -executed when its target service unit is in activating state. - -For example, prepare A.service, B.service and C.target as follows: - - # systemctl cat A.service B.service C.target - # /etc/systemd/system/A.service - [Unit] - Description=A - - [Service] - Type=oneshot - ExecStart=/usr/bin/echo A1 - ExecStart=/usr/bin/sleep 60 - ExecStart=/usr/bin/echo A2 - ExecReload=/usr/bin/echo A reloaded - RemainAfterExit=yes - - # /etc/systemd/system/B.service - [Unit] - Description=B - After=A.service - - [Service] - Type=oneshot - ExecStart=/usr/bin/echo B - RemainAfterExit=yes - - # /etc/systemd/system/C.target - [Unit] - Description=C - Wants=A.service B.service - -Start them. - - # systemctl daemon-reload - # systemctl start C.target - -Then, we have: - - # LANG=C journalctl --no-pager -u A.service -u B.service -u C.target -b - -- Logs begin at Mon 2019-09-09 00:25:06 EDT, end at Thu 2019-10-24 22:28:47 EDT. -- - Oct 24 22:27:47 localhost.localdomain systemd[1]: Starting A... - Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Child 967 belongs to A.service. - Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS - Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Running next main command for state start. - Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Passing 0 fds to service - Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: About to execute: /usr/bin/sleep 60 - Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Forked /usr/bin/sleep as 968 - Oct 24 22:27:47 localhost.localdomain systemd[968]: A.service: Executing: /usr/bin/sleep 60 - Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Trying to enqueue job A.service/reload/replace - Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Merged into running job, re-running: A.service/reload as 1288 - Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Enqueued job A.service/reload as 1288 - Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Unit cannot be reloaded because it is inactive. - Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Job 1288 A.service/reload finished, result=invalid - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Passing 0 fds to service - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: About to execute: /usr/bin/echo B - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Forked /usr/bin/echo as 970 - Oct 24 22:27:52 localhost.localdomain systemd[970]: B.service: Executing: /usr/bin/echo B - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Failed to send unit change signal for B.service: Connection reset by peer - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Changed dead -> start - Oct 24 22:27:52 localhost.localdomain systemd[1]: Starting B... - Oct 24 22:27:52 localhost.localdomain echo[970]: B - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Child 970 belongs to B.service. - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Main process exited, code=exited, status=0/SUCCESS - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Changed start -> exited - Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Job 1371 B.service/start finished, result=done - Oct 24 22:27:52 localhost.localdomain systemd[1]: Started B. - Oct 24 22:27:52 localhost.localdomain systemd[1]: C.target: Job 1287 C.target/start finished, result=done - Oct 24 22:27:52 localhost.localdomain systemd[1]: Reached target C. - Oct 24 22:27:52 localhost.localdomain systemd[1]: C.target: Failed to send unit change signal for C.target: Connection reset by peer - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Child 968 belongs to A.service. - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Running next main command for state start. - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Passing 0 fds to service - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: About to execute: /usr/bin/echo A2 - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Forked /usr/bin/echo as 972 - Oct 24 22:28:47 localhost.localdomain systemd[972]: A.service: Executing: /usr/bin/echo A2 - Oct 24 22:28:47 localhost.localdomain echo[972]: A2 - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Child 972 belongs to A.service. - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS - Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Changed start -> exited - -The issue occurs not only in reload command, i.e.: - - - reload - - try-restart - - reload-or-restart - - reload-or-try-restart commands - -The cause of this issue is that job_type_collapse() doesn't take care of the -activating state. - -Fixes: #10464 -(cherry picked from commit d1559793df555212271e490a4a72f55826caf5b4) -(cherry picked from commit cb084637ba1c8558f1538ce300c5520a6764dc76) -Resolves: #1781712 ---- - src/core/job.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/core/job.c b/src/core/job.c -index 8552ffb704..769ed6d603 100644 ---- a/src/core/job.c -+++ b/src/core/job.c -@@ -403,21 +403,21 @@ JobType job_type_collapse(JobType t, Unit *u) { - - case JOB_TRY_RESTART: - s = unit_active_state(u); -- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) -+ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) - return JOB_NOP; - - return JOB_RESTART; - - case JOB_TRY_RELOAD: - s = unit_active_state(u); -- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) -+ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) - return JOB_NOP; - - return JOB_RELOAD; - - case JOB_RELOAD_OR_START: - s = unit_active_state(u); -- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) -+ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) - return JOB_START; - - return JOB_RELOAD; diff --git a/SOURCES/0223-travis-don-t-run-slow-tests-under-ASan-UBSan.patch b/SOURCES/0223-travis-don-t-run-slow-tests-under-ASan-UBSan.patch new file mode 100644 index 0000000..d5df9f1 --- /dev/null +++ b/SOURCES/0223-travis-don-t-run-slow-tests-under-ASan-UBSan.patch @@ -0,0 +1,43 @@ +From 2f44943836b69455792a5422673f8a69bc9705ba Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 14 Oct 2019 17:14:35 +0200 +Subject: [PATCH] travis: don't run slow tests under ASan/UBSan + +Resolves: #1761519 +--- + ci/travis-centos-rhel8.sh | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/ci/travis-centos-rhel8.sh b/ci/travis-centos-rhel8.sh +index da131c726b..a1502e15ee 100755 +--- a/ci/travis-centos-rhel8.sh ++++ b/ci/travis-centos-rhel8.sh +@@ -65,10 +65,6 @@ CONFIGURE_OPTS=( + -Dnetworkd=false + -Dtimesyncd=false + -Ddefault-hierarchy=legacy +- # Custom options +- -Dslow-tests=true +- -Dtests=unsafe +- -Dinstall-tests=true + ) + + function info() { +@@ -104,7 +100,7 @@ for phase in "${PHASES[@]}"; do + RUN) + info "Run phase" + # Build systemd +- docker exec -it -e CFLAGS='-g -O0 -ftrapv' $CONT_NAME meson build "${CONFIGURE_OPTS[@]}" ++ docker exec -it -e CFLAGS='-g -O0 -ftrapv' $CONT_NAME meson build -Dtests=unsafe -Dslow-tests=true "${CONFIGURE_OPTS[@]}" + $DOCKER_EXEC ninja -v -C build + # Let's install the new systemd and "reboot" the container to avoid + # unexpected fails due to incompatibilities with older systemd +@@ -117,7 +113,7 @@ for phase in "${PHASES[@]}"; do + ENV_VARS="-e CC=clang -e CXX=clang++" + MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764 + fi +- docker exec $ENV_VARS -it $CONT_NAME meson build --werror -Dtests=unsafe -Db_sanitize=address,undefined $MESON_ARGS ${CONFIGURE_OPTS[@]} ++ docker exec $ENV_VARS -it $CONT_NAME meson build --werror -Dtests=unsafe -Db_sanitize=address,undefined $MESON_ARGS "${CONFIGURE_OPTS[@]}" + docker exec -it $CONT_NAME ninja -v -C build + + # Never remove halt_on_error from UBSAN_OPTIONS. See https://github.com/systemd/systemd/commit/2614d83aa06592aedb. diff --git a/SOURCES/0224-kernel-install-do-not-require-non-empty-kernel-cmdli.patch b/SOURCES/0224-kernel-install-do-not-require-non-empty-kernel-cmdli.patch new file mode 100644 index 0000000..b79434e --- /dev/null +++ b/SOURCES/0224-kernel-install-do-not-require-non-empty-kernel-cmdli.patch @@ -0,0 +1,67 @@ +From 6240d78097c6f828aa2ca3b50ac322b41dc41fd1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 23 Aug 2019 11:34:45 +0200 +Subject: [PATCH] kernel-install: do not require non-empty kernel cmdline + +When booting with Fedora-Server-dvd-x86_64-30-20190411.n.0.iso, +/proc/cmdline is empty (libvirt, qemu host with bios, not sure if that +matters), after installation to disk, anaconda would "crash" in kernel-core +%posttrans, after calling kernel-install, because dracut would fail +with + +> Could not determine the kernel command line parameters. +> Please specify the kernel command line in /etc/kernel/cmdline! + +I guess it's legitimate, even if unusual, to have no cmdline parameters. +Two changes are done in this patch: + +1. do not fail if the cmdline is empty. +2. if /usr/lib/kernel/cmdline or /etc/kernel/cmdline are present, but + empty, ignore /proc/cmdline. If there's explicit configuration to + have empty cmdline, don't ignore it. + +The same change was done in dracut: +https://github.com/dracutdevs/dracut/pull/561. + +(cherry picked from commit 88e1306af6380794842fb31108ba67895799fab4) + +Resolves: #1701454 +--- + src/kernel-install/90-loaderentry.install | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install +index a271cdb8a0..1619301536 100644 +--- a/src/kernel-install/90-loaderentry.install ++++ b/src/kernel-install/90-loaderentry.install +@@ -43,13 +43,13 @@ if ! [[ $PRETTY_NAME ]]; then + PRETTY_NAME="Linux $KERNEL_VERSION" + fi + +-declare -a BOOT_OPTIONS +- + if [[ -f /etc/kernel/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /etc/kernel/cmdline +-fi ++elif [[ -f /usr/lib/kernel/cmdline ]]; then ++ read -r -d '' -a BOOT_OPTIONS < /usr/lib/kernel/cmdline ++else ++ declare -a BOOT_OPTIONS + +-if ! [[ ${BOOT_OPTIONS[*]} ]]; then + read -r -d '' -a line < /proc/cmdline + for i in "${line[@]}"; do + [[ "${i#initrd=*}" != "$i" ]] && continue +@@ -57,12 +57,6 @@ if ! [[ ${BOOT_OPTIONS[*]} ]]; then + done + fi + +-if ! [[ ${BOOT_OPTIONS[*]} ]]; then +- echo "Could not determine the kernel command line parameters." >&2 +- echo "Please specify the kernel command line in /etc/kernel/cmdline!" >&2 +- exit 1 +-fi +- + cp "$KERNEL_IMAGE" "$BOOT_DIR_ABS/linux" && + chown root:root "$BOOT_DIR_ABS/linux" && + chmod 0644 "$BOOT_DIR_ABS/linux" || { diff --git a/SOURCES/0224-syslog-fix-segfault-in-syslog_parse_priority.patch b/SOURCES/0224-syslog-fix-segfault-in-syslog_parse_priority.patch deleted file mode 100644 index d243bc1..0000000 --- a/SOURCES/0224-syslog-fix-segfault-in-syslog_parse_priority.patch +++ /dev/null @@ -1,110 +0,0 @@ -From a9e1b3a33f65721e7f77f8d8253512dd16cbafdb Mon Sep 17 00:00:00 2001 -From: Yu Watanabe -Date: Wed, 8 Aug 2018 18:27:15 +0900 -Subject: [PATCH] syslog: fix segfault in syslog_parse_priority() - -(cherry picked from commit a5ee33b951cfa22db53d0274c9c6c0d9d4dae39d) -(cherry picked from commit 8bd791fb3a8e85063e297204bdef8004aacd22b1) -Related: #1781712 ---- - src/basic/syslog-util.c | 20 +++++++++++--------- - src/journal/test-journal-syslog.c | 20 ++++++++++++++++++++ - 2 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c -index 21461fa581..fe129482f3 100644 ---- a/src/basic/syslog-util.c -+++ b/src/basic/syslog-util.c -@@ -10,7 +10,8 @@ - - int syslog_parse_priority(const char **p, int *priority, bool with_facility) { - int a = 0, b = 0, c = 0; -- int k; -+ const char *end; -+ size_t k; - - assert(p); - assert(*p); -@@ -19,21 +20,22 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility) { - if ((*p)[0] != '<') - return 0; - -- if (!strchr(*p, '>')) -+ end = strchr(*p, '>'); -+ if (!end) - return 0; - -- if ((*p)[2] == '>') { -+ k = end - *p; -+ assert(k > 0); -+ -+ if (k == 2) - c = undecchar((*p)[1]); -- k = 3; -- } else if ((*p)[3] == '>') { -+ else if (k == 3) { - b = undecchar((*p)[1]); - c = undecchar((*p)[2]); -- k = 4; -- } else if ((*p)[4] == '>') { -+ } else if (k == 4) { - a = undecchar((*p)[1]); - b = undecchar((*p)[2]); - c = undecchar((*p)[3]); -- k = 5; - } else - return 0; - -@@ -46,7 +48,7 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility) { - else - *priority = (*priority & LOG_FACMASK) | c; - -- *p += k; -+ *p += k + 1; - return 1; - } - -diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c -index 7294cde032..120477cc9f 100644 ---- a/src/journal/test-journal-syslog.c -+++ b/src/journal/test-journal-syslog.c -@@ -4,6 +4,7 @@ - #include "journald-syslog.h" - #include "macro.h" - #include "string-util.h" -+#include "syslog-util.h" - - static void test_syslog_parse_identifier(const char *str, - const char *ident, const char *pid, const char *rest, int ret) { -@@ -19,6 +20,17 @@ static void test_syslog_parse_identifier(const char *str, - assert_se(streq(buf, rest)); - } - -+static void test_syslog_parse_priority(const char *str, int priority, int ret) { -+ const char *buf = str; -+ int priority2, ret2; -+ -+ ret2 = syslog_parse_priority(&buf, &priority2, false); -+ -+ assert_se(ret == ret2); -+ if (ret2 == 1) -+ assert_se(priority == priority2); -+} -+ - int main(void) { - test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", "xxx", 11); - test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, "xxx", 6); -@@ -33,5 +45,13 @@ int main(void) { - test_syslog_parse_identifier("pidu: ", "pidu", NULL, "", 6); - test_syslog_parse_identifier("pidu : ", NULL, NULL, "pidu : ", 0); - -+ test_syslog_parse_priority("<>", 0, 0); -+ test_syslog_parse_priority("<>aaa", 0, 0); -+ test_syslog_parse_priority("", 0, 0); -+ test_syslog_parse_priority("aaa", 0, 0); -+ test_syslog_parse_priority(" ", 0, 0); -+ test_syslog_parse_priority(" aaa", 0, 0); -+ /* TODO: add test cases of valid priorities */ -+ - return 0; - } diff --git a/SOURCES/0225-ask-password-prevent-buffer-overrow-when-reading-fro.patch b/SOURCES/0225-ask-password-prevent-buffer-overrow-when-reading-fro.patch new file mode 100644 index 0000000..1a3af20 --- /dev/null +++ b/SOURCES/0225-ask-password-prevent-buffer-overrow-when-reading-fro.patch @@ -0,0 +1,36 @@ +From c6c8e0d097d6ba12471c6112c3fd339ea40329d5 Mon Sep 17 00:00:00 2001 +From: Thadeu Lima de Souza Cascardo +Date: Mon, 13 May 2019 16:58:01 -0300 +Subject: [PATCH] ask-password: prevent buffer overrow when reading from + keyring + +When we read from keyring, a temporary buffer is allocated in order to +determine the size needed for the entire data. However, when zeroing that area, +we use the data size returned by the read instead of the lesser size allocate +for the buffer. + +That will cause memory corruption that causes systemd-cryptsetup to crash +either when a single large password is used or when multiple passwords have +already been pushed to the keyring. + +Signed-off-by: Thadeu Lima de Souza Cascardo +(cherry picked from commit 59c55e73eaee345e1ee67c23eace8895ed499693) + +Resolves: #1752050 +--- + src/shared/ask-password-api.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c +index 682dc754fc..764ebd08e1 100644 +--- a/src/shared/ask-password-api.c ++++ b/src/shared/ask-password-api.c +@@ -79,7 +79,7 @@ static int retrieve_key(key_serial_t serial, char ***ret) { + if (n < m) + break; + +- explicit_bzero(p, n); ++ explicit_bzero(p, m); + free(p); + m *= 2; + } diff --git a/SOURCES/0225-journald-fixed-assertion-failure-when-system-journal.patch b/SOURCES/0225-journald-fixed-assertion-failure-when-system-journal.patch deleted file mode 100644 index ff2e481..0000000 --- a/SOURCES/0225-journald-fixed-assertion-failure-when-system-journal.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 7fdcc0e9cc7f047a778a2f1776d2398f46c6ac86 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= - <1163635+rmetrich@users.noreply.github.com> -Date: Mon, 3 Sep 2018 05:42:39 +0200 -Subject: [PATCH] journald: fixed assertion failure when system journal - rotation fails (#9893) - -(cherry picked from commit fd790d6f09b10a87b007b71403cb018f18ff91c9) -(cherry picked from commit 33aa231f5bf3335cdacfb38ffba757865019ce4d) -Related: #1781712 ---- - src/journal/journald-server.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c -index 8de45552f6..f2d2856e03 100644 ---- a/src/journal/journald-server.c -+++ b/src/journal/journald-server.c -@@ -1041,7 +1041,8 @@ int server_flush_to_var(Server *s, bool require_flag_file) { - r = 0; - - finish: -- journal_file_post_change(s->system_journal); -+ if (s->system_journal) -+ journal_file_post_change(s->system_journal); - - s->runtime_journal = journal_file_close(s->runtime_journal); - diff --git a/SOURCES/0226-core-try-to-reopen-dev-kmsg-again-right-after-mounti.patch b/SOURCES/0226-core-try-to-reopen-dev-kmsg-again-right-after-mounti.patch new file mode 100644 index 0000000..d568e76 --- /dev/null +++ b/SOURCES/0226-core-try-to-reopen-dev-kmsg-again-right-after-mounti.patch @@ -0,0 +1,37 @@ +From 985837dab9c892858a92ae50043843307f5e0714 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 19 Jul 2019 18:29:11 +0200 +Subject: [PATCH] core: try to reopen /dev/kmsg again right after mounting /dev + +I was debugging stuff during early boot, and was confused that I never +found the logs for it in kmsg. The reason for that was that /proc is +generally not mounted the first time we do log_open() and hence +log_set_target(LOG_TARGET_KMSG) we do when running as PID 1 had not +effect. A lot later during start-up we call log_open() again where this +is fixed (after the point where we close all remaining fds still open), +but in the meantime no logs every got written to kmsg. This patch fixes +that. + +(cherry picked from commit 0a2eef1ee1fef74be9d12f7dc4d0006b645b579c) + +Resolves: #1749212 +--- + src/core/main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/core/main.c b/src/core/main.c +index 44dd8348be..af7b26d6f1 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -2215,6 +2215,11 @@ int main(int argc, char *argv[]) { + goto finish; + } + ++ /* Let's open the log backend a second time, in case the first time didn't ++ * work. Quite possibly we have mounted /dev just now, so /dev/kmsg became ++ * available, and it previously wasn't. */ ++ log_open(); ++ + r = initialize_security( + &loaded_policy, + &security_start_timestamp, diff --git a/SOURCES/0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch b/SOURCES/0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch deleted file mode 100644 index 57d7275..0000000 --- a/SOURCES/0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 9896fd236594fba4c2288ab33884f23a709565ab Mon Sep 17 00:00:00 2001 -From: Frantisek Sumsal -Date: Fri, 15 Mar 2019 10:05:33 +0100 -Subject: [PATCH] test: use PBKDF2 instead of Argon2 in cryptsetup... - -to reduce memory requirements for volume manipulation. Also, -to further improve the test performance, reduce number of PBKDF -iterations to 1000 (allowed minimum). - -(cherry picked from commit 5b69d297c153478f6f5e74ba66e1f4e5b6422baf) -(cherry picked from commit a7f18f9ef4abc7e0732d1710ead2a18a38c3ec6d) -Related: #1781712 ---- - test/TEST-02-CRYPTSETUP/test.sh | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh -index 545602e17a..c38e56f72e 100755 ---- a/test/TEST-02-CRYPTSETUP/test.sh -+++ b/test/TEST-02-CRYPTSETUP/test.sh -@@ -29,7 +29,7 @@ check_result_qemu() { - test_setup() { - create_empty_image - echo -n test >$TESTDIR/keyfile -- cryptsetup -q luksFormat ${LOOPDEV}p2 $TESTDIR/keyfile -+ cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 ${LOOPDEV}p2 $TESTDIR/keyfile - cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile - mkfs.ext4 -L var /dev/mapper/varcrypt - mkdir -p $TESTDIR/root diff --git a/SOURCES/0227-buildsys-don-t-garbage-collect-sections-while-linkin.patch b/SOURCES/0227-buildsys-don-t-garbage-collect-sections-while-linkin.patch new file mode 100644 index 0000000..d305484 --- /dev/null +++ b/SOURCES/0227-buildsys-don-t-garbage-collect-sections-while-linkin.patch @@ -0,0 +1,29 @@ +From 9f259b46b760b2aa08ac1fe76fe61df514e2768f Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Tue, 3 Sep 2019 10:05:42 +0200 +Subject: [PATCH] buildsys: don't garbage collect sections while linking + +gc-sections is actually very aggressive and garbage collects ELF +sections used by annobin gcc plugin and annocheck then reports gaps in +coverage. Let's drop that linker flag. + +RHEL-only + +Resolves: #1748258 +--- + meson.build | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/meson.build b/meson.build +index 04b461dcd4..613a5133b6 100644 +--- a/meson.build ++++ b/meson.build +@@ -357,8 +357,6 @@ if get_option('buildtype') != 'debug' + '-ffunction-sections', + '-fdata-sections', + ] +- +- possible_link_flags += '-Wl,--gc-sections' + endif + + add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c') diff --git a/SOURCES/0227-test-mask-several-unnecessary-services.patch b/SOURCES/0227-test-mask-several-unnecessary-services.patch deleted file mode 100644 index d1a4f13..0000000 --- a/SOURCES/0227-test-mask-several-unnecessary-services.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 0b16c6baa6b24c984a1b4bcd7026172f1627fe92 Mon Sep 17 00:00:00 2001 -From: Yu Watanabe -Date: Thu, 1 Nov 2018 17:26:36 +0900 -Subject: [PATCH] test: mask several unnecessary services - -This may make CIs run faster. - -(cherry picked from commit 056ae88152a722bdbea54ff33db815d585c8b9c6) -(cherry picked from commit c748b95f5a00b6d9c46026c3d251c40437e6b64a) -Related: #1781712 ---- - test/TEST-02-CRYPTSETUP/test.sh | 8 ++++++++ - test/TEST-03-JOBS/test.sh | 8 ++++++++ - test/TEST-04-JOURNAL/test.sh | 8 ++++++++ - test/TEST-05-RLIMITS/test.sh | 8 ++++++++ - test/TEST-07-ISSUE-1981/test.sh | 8 ++++++++ - test/TEST-11-ISSUE-3166/test.sh | 8 ++++++++ - test/TEST-12-ISSUE-3171/test.sh | 8 ++++++++ - test/TEST-13-NSPAWN-SMOKE/test.sh | 8 ++++++++ - test/TEST-18-FAILUREACTION/test.sh | 7 +++++++ - test/TEST-19-DELEGATE/test.sh | 8 ++++++++ - test/TEST-20-MAINPIDGAMES/test.sh | 8 ++++++++ - test/TEST-23-TYPE-EXEC/test.sh | 8 ++++++++ - 12 files changed, 95 insertions(+) - -diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh -index c38e56f72e..97eb2f409e 100755 ---- a/test/TEST-02-CRYPTSETUP/test.sh -+++ b/test/TEST-02-CRYPTSETUP/test.sh -@@ -45,6 +45,14 @@ test_setup() { - - setup_basic_environment - -+ # mask some services that we do not want to run in these tests -+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service -+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service -+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service -+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket -+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service -+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service -+ - # setup the testsuite service - cat >$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system.conf <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service < -Date: Mon, 21 Oct 2019 18:39:39 +0200 -Subject: [PATCH] test: bump the second partition's size to 50M - -The former size (10M) caused systemd-journald to crash with SIGABRT when -used on a LUKS2 partition, as the LUKS2 metadata consume a significant -part of the 10M partition, thus leaving no space for the journal file -itself (relevant for TEST-02-CRYPTSETUP). This change has been present -in upstream for a while anyway. - -rhel-only - -(cherry picked from commit 27d1acaa1d4c9299db461f0f1922c573be6a52c0) -Related: #1781712 ---- - test/test-functions | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/test/test-functions b/test/test-functions -index af9d16140f..fe25a501da 100644 ---- a/test/test-functions -+++ b/test/test-functions -@@ -433,7 +433,7 @@ create_empty_image() { - [ -b "$LOOPDEV" ] || return 1 - echo "LOOPDEV=$LOOPDEV" >> $STATEFILE - sfdisk "$LOOPDEV" < +Date: Thu, 17 Oct 2019 09:37:35 +0200 +Subject: [PATCH] udev: introduce CONST key name + +Currently, there is no way to match against system-wide constants, such +as architecture or virtualization type, without forking helper binaries. +That potentially results in a huge number of spawned processes which +output always the same answer. + +This patch introduces a special CONST keyword which takes a hard-coded +string as its key and returns a value assigned to that key. Currently +implemented are CONST{arch} and CONST{virt}, which can be used to match +against the system's architecture and virtualization type. + +(based on commit 4801d8afe2ff1c1c075c9f0bc5631612172e0bb7) + +Resolves: #1762679 +--- + man/udev.xml | 26 ++++++++++++++++++++++++++ + rules/40-redhat.rules | 6 +++--- + src/udev/udev-rules.c | 32 ++++++++++++++++++++++++++++++++ + test/rule-syntax-check.py | 2 +- + 4 files changed, 62 insertions(+), 4 deletions(-) + +diff --git a/man/udev.xml b/man/udev.xml +index bdf901a8f0..8c1eb41787 100644 +--- a/man/udev.xml ++++ b/man/udev.xml +@@ -236,6 +236,32 @@ + + + ++ ++ CONST{key} ++ ++ Match against a system-wide constant. Supported keys are: ++ ++ ++ arch ++ ++ System's architecture. See in ++ systemd.unit5 ++ for possible values. ++ ++ ++ ++ virt ++ ++ System's virtualization environment. See ++ systemd-detect-virt1 ++ for possible values. ++ ++ ++ ++ Unknown keys will never match. ++ ++ ++ + + TAG + +diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules +index fadc6e59f1..3c95cd2df0 100644 +--- a/rules/40-redhat.rules ++++ b/rules/40-redhat.rules +@@ -6,11 +6,11 @@ SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online} + # Memory hotadd request + SUBSYSTEM!="memory", GOTO="memory_hotplug_end" + ACTION!="add", GOTO="memory_hotplug_end" +-PROGRAM="/bin/uname -p", RESULT=="s390*", GOTO="memory_hotplug_end" +-PROGRAM="/bin/uname -p", RESULT=="ppc64*", GOTO="memory_hotplug_end" ++CONST{arch}=="s390*", GOTO="memory_hotplug_end" ++CONST{arch}=="ppc64*", GOTO="memory_hotplug_end" + + ENV{.state}="online" +-PROGRAM="/bin/systemd-detect-virt", RESULT=="none", ENV{.state}="online_movable" ++CONST{virt}=="none", ENV{.state}="online_movable" + ATTR{state}=="offline", ATTR{state}="$env{.state}" + + LABEL="memory_hotplug_end" +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index 58af863f3d..a246cbe67e 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -17,6 +17,7 @@ + #include + + #include "alloc-util.h" ++#include "architecture.h" + #include "conf-files.h" + #include "dirent-util.h" + #include "escape.h" +@@ -34,6 +35,7 @@ + #include "udev.h" + #include "user-util.h" + #include "util.h" ++#include "virt.h" + + #define PREALLOC_TOKEN 2048 + +@@ -123,6 +125,7 @@ enum token_type { + TK_M_DEVLINK, /* val */ + TK_M_NAME, /* val */ + TK_M_ENV, /* val, attr */ ++ TK_M_CONST, /* val, attr */ + TK_M_TAG, /* val */ + TK_M_SUBSYSTEM, /* val */ + TK_M_DRIVER, /* val */ +@@ -259,6 +262,7 @@ static const char *token_str(enum token_type type) { + [TK_M_DEVLINK] = "M DEVLINK", + [TK_M_NAME] = "M NAME", + [TK_M_ENV] = "M ENV", ++ [TK_M_CONST] = "M CONST", + [TK_M_TAG] = "M TAG", + [TK_M_SUBSYSTEM] = "M SUBSYSTEM", + [TK_M_DRIVER] = "M DRIVER", +@@ -370,6 +374,7 @@ static void dump_token(struct udev_rules *rules, struct token *token) { + case TK_M_SYSCTL: + case TK_M_ATTRS: + case TK_M_ENV: ++ case TK_M_CONST: + case TK_A_ATTR: + case TK_A_SYSCTL: + case TK_A_ENV: +@@ -903,6 +908,7 @@ static void rule_add_key(struct rule_tmp *rule_tmp, enum token_type type, + token->key.builtin_cmd = *(enum udev_builtin_cmd *)data; + break; + case TK_M_ENV: ++ case TK_M_CONST: + case TK_M_ATTR: + case TK_M_SYSCTL: + case TK_M_ATTRS: +@@ -1226,6 +1232,17 @@ static void add_rule(struct udev_rules *rules, char *line, + rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr); + } + ++ } else if (startswith(key, "CONST{")) { ++ attr = get_key_attribute(rules->udev, key + STRLEN("CONST")); ++ if (attr == NULL || !STR_IN_SET(attr, "arch", "virt")) ++ LOG_AND_RETURN("error parsing %s attribute", "CONST"); ++ ++ if (op == OP_REMOVE) ++ LOG_AND_RETURN("invalid %s operation", "CONST"); ++ ++ if (op < OP_MATCH_MAX) ++ rule_add_key(&rule_tmp, TK_M_CONST, op, value, attr); ++ + } else if (streq(key, "TAG")) { + if (op < OP_MATCH_MAX) + rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL); +@@ -1855,6 +1872,21 @@ void udev_rules_apply_to_event(struct udev_rules *rules, + goto nomatch; + break; + } ++ case TK_M_CONST: { ++ const char *key_name = rules_str(rules, cur->key.attr_off); ++ const char *value = NULL; ++ ++ if (streq(key_name, "arch")) { ++ value = architecture_to_string(uname_architecture()); ++ } else if (streq(key_name, "virt")) { ++ value = virtualization_to_string(detect_virtualization()); ++ } else ++ assert_not_reached("Invalid CONST key"); ++ ++ if (match_key(rules, cur, value)) ++ goto nomatch; ++ break; ++ } + case TK_M_TAG: { + struct udev_list_entry *list_entry; + bool match = false; +diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py +index c7c0a1a656..6e59f421f5 100755 +--- a/test/rule-syntax-check.py ++++ b/test/rule-syntax-check.py +@@ -19,7 +19,7 @@ quoted_string_re = r'"(?:[^\\"]|\\.)*"' + no_args_tests = re.compile(r'(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|PROGRAM|RESULT|TEST)\s*(?:=|!)=\s*' + quoted_string_re + '$') + # PROGRAM can also be specified as an assignment. + program_assign = re.compile(r'PROGRAM\s*=\s*' + quoted_string_re + '$') +-args_tests = re.compile(r'(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*' + quoted_string_re + '$') ++args_tests = re.compile(r'(ATTRS?|ENV|CONST|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*' + quoted_string_re + '$') + no_args_assign = re.compile(r'(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|RUN|LABEL|GOTO|WAIT_FOR|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*' + quoted_string_re + '$') + args_assign = re.compile(r'(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*' + quoted_string_re + '$') + # Find comma-separated groups, but allow commas that are inside quoted strings. diff --git a/SOURCES/0229-Call-getgroups-to-know-size-of-supplementary-groups-.patch b/SOURCES/0229-Call-getgroups-to-know-size-of-supplementary-groups-.patch new file mode 100644 index 0000000..655f32a --- /dev/null +++ b/SOURCES/0229-Call-getgroups-to-know-size-of-supplementary-groups-.patch @@ -0,0 +1,50 @@ +From e1bd03e75860fb349a6de589bbb1274acc454aef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Fri, 13 Sep 2019 11:18:18 +0200 +Subject: [PATCH] Call getgroups() to know size of supplementary groups array + to allocate + +Resolves RHBZ #1743230 - journalctl dumps core when stack limit is reduced to 256 KB + +(cherry picked from commit f5e0b942af1e86993c21f4e5c84342bb10403dac) + +Resolves: #1743235 +--- + src/basic/user-util.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/src/basic/user-util.c b/src/basic/user-util.c +index a562a397c7..c533f67025 100644 +--- a/src/basic/user-util.c ++++ b/src/basic/user-util.c +@@ -358,9 +358,8 @@ char* gid_to_name(gid_t gid) { + } + + int in_gid(gid_t gid) { +- long ngroups_max; + gid_t *gids; +- int r, i; ++ int ngroups, r, i; + + if (getgid() == gid) + return 1; +@@ -371,12 +370,15 @@ int in_gid(gid_t gid) { + if (!gid_is_valid(gid)) + return -EINVAL; + +- ngroups_max = sysconf(_SC_NGROUPS_MAX); +- assert(ngroups_max > 0); ++ ngroups = getgroups(0, NULL); ++ if (ngroups < 0) ++ return -errno; ++ if (ngroups == 0) ++ return 0; + +- gids = newa(gid_t, ngroups_max); ++ gids = newa(gid_t, ngroups); + +- r = getgroups(ngroups_max, gids); ++ r = getgroups(ngroups, gids); + if (r < 0) + return -errno; + diff --git a/SOURCES/0229-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch b/SOURCES/0229-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch deleted file mode 100644 index 86ad50c..0000000 --- a/SOURCES/0229-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch +++ /dev/null @@ -1,49 +0,0 @@ -From a115123d009dde9bcaf508eea066934459940348 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Jan 2019 18:13:03 +0100 -Subject: [PATCH] sd-bus: make rqueue/wqueue sizes of type size_t - -Let's do this like we usually do and size arrays with size_t. - -We already do this for the "allocated" counter correctly, and externally -we expose the queue sizes as uint64_t anyway, hence there's really no -point in usigned "unsigned" internally. - -(cherry picked from commit 143d4e045a798ccc87889b2a8a60d7fbe44be441) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/bus-internal.h | 4 ++-- - src/libsystemd/sd-bus/sd-bus.c | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h -index 90e6028983..2d21319df5 100644 ---- a/src/libsystemd/sd-bus/bus-internal.h -+++ b/src/libsystemd/sd-bus/bus-internal.h -@@ -221,11 +221,11 @@ struct sd_bus { - size_t rbuffer_size; - - sd_bus_message **rqueue; -- unsigned rqueue_size; -+ size_t rqueue_size; - size_t rqueue_allocated; - - sd_bus_message **wqueue; -- unsigned wqueue_size; -+ size_t wqueue_size; - size_t windex; - size_t wqueue_allocated; - -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index 1c9e967ae0..64026f7ee1 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -2080,7 +2080,7 @@ _public_ int sd_bus_call( - _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); - usec_t timeout; - uint64_t cookie; -- unsigned i; -+ size_t i; - int r; - - bus_assert_return(m, -EINVAL, error); diff --git a/SOURCES/0230-Consider-smb3-as-remote-filesystem.patch b/SOURCES/0230-Consider-smb3-as-remote-filesystem.patch new file mode 100644 index 0000000..691f180 --- /dev/null +++ b/SOURCES/0230-Consider-smb3-as-remote-filesystem.patch @@ -0,0 +1,30 @@ +From 1bf923686a6842f222b1ef5f5174511340c75685 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Tue, 1 Oct 2019 08:45:08 +0200 +Subject: [PATCH] Consider smb3 as remote filesystem + +Currently systemd will treat smb3 as local filesystem and cause +can't boot failures. Add smb3 to the list of remote filesystems +to fix this issue. + +Signed-off-by: Kenneth D'souza + +(cherry picked from commit ff7d6a740b0c6fa3be63d3908a0858730a0837c5) + +Resolves: #1757257 +--- + src/basic/mount-util.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c +index 3670b7f591..5b04e21f34 100644 +--- a/src/basic/mount-util.c ++++ b/src/basic/mount-util.c +@@ -603,6 +603,7 @@ bool fstype_is_network(const char *fstype) { + return STR_IN_SET(fstype, + "afs", + "cifs", ++ "smb3", + "smbfs", + "sshfs", + "ncpfs", diff --git a/SOURCES/0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch b/SOURCES/0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch deleted file mode 100644 index 0074f56..0000000 --- a/SOURCES/0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 90dedb47d2cb060a366d12bf467f03fa20c5ed24 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Jan 2019 18:14:17 +0100 -Subject: [PATCH] sd-bus: reorder bus ref and bus message ref handling - -Let's always place handling of these references together, so that all -reference counting during allocation is at a single place. - -(cherry picked from commit e593b6a87a335267e5f7238b14683b7f840a01a3) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/bus-message.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c -index 53cbd675b7..2ea3c5bba9 100644 ---- a/src/libsystemd/sd-bus/bus-message.c -+++ b/src/libsystemd/sd-bus/bus-message.c -@@ -461,7 +461,6 @@ int bus_message_from_header( - if (!m) - return -ENOMEM; - -- m->n_ref = 1; - m->sealed = true; - m->header = header; - m->header_accessible = header_accessible; -@@ -515,7 +514,9 @@ int bus_message_from_header( - m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; - } - -+ m->n_ref = 1; - m->bus = sd_bus_ref(bus); -+ - *ret = TAKE_PTR(m); - - return 0; -@@ -588,13 +589,13 @@ _public_ int sd_bus_message_new( - return -ENOMEM; - - t->n_ref = 1; -+ t->bus = sd_bus_ref(bus); - t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message))); - t->header->endian = BUS_NATIVE_ENDIAN; - t->header->type = type; - t->header->version = bus->message_version; - t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING); - t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t); -- t->bus = sd_bus_ref(bus); - - if (bus->allow_interactive_authorization) - t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; diff --git a/SOURCES/0231-process-util-introduce-pid_is_my_child-helper.patch b/SOURCES/0231-process-util-introduce-pid_is_my_child-helper.patch new file mode 100644 index 0000000..5d740cf --- /dev/null +++ b/SOURCES/0231-process-util-introduce-pid_is_my_child-helper.patch @@ -0,0 +1,114 @@ +From f057aa6bb604845fa10ad569bca306e5e1e8fe0d Mon Sep 17 00:00:00 2001 +From: Franck Bui +Date: Mon, 18 Mar 2019 11:48:34 +0100 +Subject: [PATCH] process-util: introduce pid_is_my_child() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +No functional changes. + +Thanks Renaud Métrich for backporting this to RHEL. +Resolves: #1744972 +--- + src/basic/process-util.c | 14 ++++++++++++++ + src/basic/process-util.h | 1 + + src/core/cgroup.c | 7 ++----- + src/core/service.c | 8 ++------ + 4 files changed, 19 insertions(+), 11 deletions(-) + +diff --git a/src/basic/process-util.c b/src/basic/process-util.c +index aa3eff779a..6dbeee9dda 100644 +--- a/src/basic/process-util.c ++++ b/src/basic/process-util.c +@@ -903,6 +903,20 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) { + return 0; + } + ++int pid_is_my_child(pid_t pid) { ++ pid_t ppid; ++ int r; ++ ++ if (pid <= 1) ++ return false; ++ ++ r = get_process_ppid(pid, &ppid); ++ if (r < 0) ++ return r; ++ ++ return ppid == getpid_cached(); ++} ++ + bool pid_is_unwaited(pid_t pid) { + /* Checks whether a PID is still valid at all, including a zombie */ + +diff --git a/src/basic/process-util.h b/src/basic/process-util.h +index a5bb072b25..a3bd2851b4 100644 +--- a/src/basic/process-util.h ++++ b/src/basic/process-util.h +@@ -68,6 +68,7 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value); + + bool pid_is_alive(pid_t pid); + bool pid_is_unwaited(pid_t pid); ++int pid_is_my_child(pid_t pid); + int pid_from_same_root_fs(pid_t pid); + + bool is_main_thread(void); +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 62ab41a288..b7ed07e65b 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -1876,7 +1876,7 @@ void unit_prune_cgroup(Unit *u) { + + int unit_search_main_pid(Unit *u, pid_t *ret) { + _cleanup_fclose_ FILE *f = NULL; +- pid_t pid = 0, npid, mypid; ++ pid_t pid = 0, npid; + int r; + + assert(u); +@@ -1889,15 +1889,12 @@ int unit_search_main_pid(Unit *u, pid_t *ret) { + if (r < 0) + return r; + +- mypid = getpid_cached(); + while (cg_read_pid(f, &npid) > 0) { +- pid_t ppid; + + if (npid == pid) + continue; + +- /* Ignore processes that aren't our kids */ +- if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid) ++ if (pid_is_my_child(npid) == 0) + continue; + + if (pid != 0) +diff --git a/src/core/service.c b/src/core/service.c +index 24f167572a..614ba05d89 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -139,8 +139,6 @@ static void service_unwatch_pid_file(Service *s) { + } + + static int service_set_main_pid(Service *s, pid_t pid) { +- pid_t ppid; +- + assert(s); + + if (pid <= 1) +@@ -159,12 +157,10 @@ static int service_set_main_pid(Service *s, pid_t pid) { + + s->main_pid = pid; + s->main_pid_known = true; ++ s->main_pid_alien = pid_is_my_child(pid) == 0; + +- if (get_process_ppid(pid, &ppid) >= 0 && ppid != getpid_cached()) { ++ if (s->main_pid_alien) + log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid); +- s->main_pid_alien = true; +- } else +- s->main_pid_alien = false; + + return 0; + } diff --git a/SOURCES/0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch b/SOURCES/0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch deleted file mode 100644 index fbd6a7f..0000000 --- a/SOURCES/0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch +++ /dev/null @@ -1,32 +0,0 @@ -From d2725078f0da567eb2bcae3bef53f013d7fa3ba5 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Jan 2019 18:15:37 +0100 -Subject: [PATCH] sd-bus: make sure dispatch_rqueue() initializes return - parameter on all types of success - -Let's make sure our own code follows coding style and initializes all -return values on all types of success (and leaves it uninitialized in -all types of failure). - -(cherry picked from commit c0bc4ec5cc17ac61773d1e9362b0ffa8382c1ff1) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/sd-bus.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index 64026f7ee1..55b008cc9f 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -1814,8 +1814,10 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd - r = bus_read_message(bus, hint_priority, priority); - if (r < 0) - return r; -- if (r == 0) -+ if (r == 0) { -+ *m = NULL; - return ret; -+ } - - ret = 1; - } diff --git a/SOURCES/0232-core-reduce-the-number-of-stalled-PIDs-from-the-watc.patch b/SOURCES/0232-core-reduce-the-number-of-stalled-PIDs-from-the-watc.patch new file mode 100644 index 0000000..46cf59e --- /dev/null +++ b/SOURCES/0232-core-reduce-the-number-of-stalled-PIDs-from-the-watc.patch @@ -0,0 +1,323 @@ +From 79e9566ec0a61d887ab63f17192dbd71aae36ee0 Mon Sep 17 00:00:00 2001 +From: Franck Bui +Date: Mon, 18 Mar 2019 20:59:36 +0100 +Subject: [PATCH] core: reduce the number of stalled PIDs from the watched + processes list when possible +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some PIDs can remain in the watched list even though their processes have +exited since a long time. It can easily happen if the main process of a forking +service manages to spawn a child before the control process exits for example. + +However when a pid is about to be mapped to a unit by calling unit_watch_pid(), +the caller usually knows if the pid should belong to this unit exclusively: if +we just forked() off a child, then we can be sure that its PID is otherwise +unused. In this case we take this opportunity to remove any stalled PIDs from +the watched process list. + +If we learnt about a PID in any other form (for example via PID file, via +searching, MAINPID= and so on), then we can't assume anything. + +Thanks Renaud Métrich for backporting this to RHEL. +Resolves: #1744972 +--- + src/core/cgroup.c | 2 +- + src/core/dbus-scope.c | 2 +- + src/core/manager.c | 10 ++++++++++ + src/core/manager.h | 2 ++ + src/core/mount.c | 5 ++--- + src/core/service.c | 16 ++++++++-------- + src/core/socket.c | 7 +++---- + src/core/swap.c | 5 ++--- + src/core/unit.c | 8 +++++++- + src/core/unit.h | 2 +- + src/test/test-watch-pid.c | 12 ++++++------ + 11 files changed, 43 insertions(+), 28 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index b7ed07e65b..76eafdc082 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -1926,7 +1926,7 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) { + pid_t pid; + + while ((r = cg_read_pid(f, &pid)) > 0) { +- r = unit_watch_pid(u, pid); ++ r = unit_watch_pid(u, pid, false); + if (r < 0 && ret >= 0) + ret = r; + } +diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c +index 6725f62794..0bbf64fff1 100644 +--- a/src/core/dbus-scope.c ++++ b/src/core/dbus-scope.c +@@ -106,7 +106,7 @@ static int bus_scope_set_transient_property( + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { +- r = unit_watch_pid(UNIT(s), pid); ++ r = unit_watch_pid(UNIT(s), pid, false); + if (r < 0 && r != -EEXIST) + return r; + } +diff --git a/src/core/manager.c b/src/core/manager.c +index c83e296cf3..0eae7d46fb 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -2044,6 +2044,16 @@ void manager_clear_jobs(Manager *m) { + job_finish_and_invalidate(j, JOB_CANCELED, false, false); + } + ++void manager_unwatch_pid(Manager *m, pid_t pid) { ++ assert(m); ++ ++ /* First let's drop the unit keyed as "pid". */ ++ (void) hashmap_remove(m->watch_pids, PID_TO_PTR(pid)); ++ ++ /* Then, let's also drop the array keyed by -pid. */ ++ free(hashmap_remove(m->watch_pids, PID_TO_PTR(-pid))); ++} ++ + static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) { + Manager *m = userdata; + Job *j; +diff --git a/src/core/manager.h b/src/core/manager.h +index c7f4d66ecd..fa47952d24 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -406,6 +406,8 @@ int manager_get_dump_string(Manager *m, char **ret); + + void manager_clear_jobs(Manager *m); + ++void manager_unwatch_pid(Manager *m, pid_t pid); ++ + unsigned manager_dispatch_load_queue(Manager *m); + + int manager_environment_add(Manager *m, char **minus, char **plus); +diff --git a/src/core/mount.c b/src/core/mount.c +index 2ac04e3874..5878814b1b 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -677,7 +677,7 @@ static int mount_coldplug(Unit *u) { + pid_is_unwaited(m->control_pid) && + MOUNT_STATE_WITH_PROCESS(new_state)) { + +- r = unit_watch_pid(UNIT(m), m->control_pid); ++ r = unit_watch_pid(UNIT(m), m->control_pid, false); + if (r < 0) + return r; + +@@ -781,9 +781,8 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { + if (r < 0) + return r; + +- r = unit_watch_pid(UNIT(m), pid); ++ r = unit_watch_pid(UNIT(m), pid, true); + if (r < 0) +- /* FIXME: we need to do something here */ + return r; + + *_pid = pid; +diff --git a/src/core/service.c b/src/core/service.c +index 614ba05d89..310838a5f6 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -974,7 +974,7 @@ static int service_load_pid_file(Service *s, bool may_warn) { + if (r < 0) + return r; + +- r = unit_watch_pid(UNIT(s), pid); ++ r = unit_watch_pid(UNIT(s), pid, false); + if (r < 0) /* FIXME: we need to do something here */ + return log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", pid); + +@@ -1004,7 +1004,7 @@ static void service_search_main_pid(Service *s) { + if (service_set_main_pid(s, pid) < 0) + return; + +- r = unit_watch_pid(UNIT(s), pid); ++ r = unit_watch_pid(UNIT(s), pid, false); + if (r < 0) + /* FIXME: we need to do something here */ + log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", pid); +@@ -1135,7 +1135,7 @@ static int service_coldplug(Unit *u) { + SERVICE_RUNNING, SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) { +- r = unit_watch_pid(UNIT(s), s->main_pid); ++ r = unit_watch_pid(UNIT(s), s->main_pid, false); + if (r < 0) + return r; + } +@@ -1147,7 +1147,7 @@ static int service_coldplug(Unit *u) { + SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { +- r = unit_watch_pid(UNIT(s), s->control_pid); ++ r = unit_watch_pid(UNIT(s), s->control_pid, false); + if (r < 0) + return r; + } +@@ -1545,8 +1545,8 @@ static int service_spawn( + s->exec_fd_event_source = TAKE_PTR(exec_fd_source); + s->exec_fd_hot = false; + +- r = unit_watch_pid(UNIT(s), pid); +- if (r < 0) /* FIXME: we need to do something here */ ++ r = unit_watch_pid(UNIT(s), pid, true); ++ if (r < 0) + return r; + + *_pid = pid; +@@ -3643,7 +3643,7 @@ static void service_notify_message( + } + if (r > 0) { + service_set_main_pid(s, new_main_pid); +- unit_watch_pid(UNIT(s), new_main_pid); ++ unit_watch_pid(UNIT(s), new_main_pid, false); + notify_dbus = true; + } + } +@@ -3858,7 +3858,7 @@ static void service_bus_name_owner_change( + log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, name, pid); + + service_set_main_pid(s, pid); +- unit_watch_pid(UNIT(s), pid); ++ unit_watch_pid(UNIT(s), pid, false); + } + } + } +diff --git a/src/core/socket.c b/src/core/socket.c +index d488c64e91..b034549634 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -1816,7 +1816,7 @@ static int socket_coldplug(Unit *u) { + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL)) { + +- r = unit_watch_pid(UNIT(s), s->control_pid); ++ r = unit_watch_pid(UNIT(s), s->control_pid, false); + if (r < 0) + return r; + +@@ -1902,9 +1902,8 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { + if (r < 0) + return r; + +- r = unit_watch_pid(UNIT(s), pid); ++ r = unit_watch_pid(UNIT(s), pid, true); + if (r < 0) +- /* FIXME: we need to do something here */ + return r; + + *_pid = pid; +@@ -1973,7 +1972,7 @@ static int socket_chown(Socket *s, pid_t *_pid) { + _exit(EXIT_SUCCESS); + } + +- r = unit_watch_pid(UNIT(s), pid); ++ r = unit_watch_pid(UNIT(s), pid, true); + if (r < 0) + goto fail; + +diff --git a/src/core/swap.c b/src/core/swap.c +index b644753a1c..e717dbb54a 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -531,7 +531,7 @@ static int swap_coldplug(Unit *u) { + pid_is_unwaited(s->control_pid) && + SWAP_STATE_WITH_PROCESS(new_state)) { + +- r = unit_watch_pid(UNIT(s), s->control_pid); ++ r = unit_watch_pid(UNIT(s), s->control_pid, false); + if (r < 0) + return r; + +@@ -636,9 +636,8 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { + if (r < 0) + goto fail; + +- r = unit_watch_pid(UNIT(s), pid); ++ r = unit_watch_pid(UNIT(s), pid, true); + if (r < 0) +- /* FIXME: we need to do something here */ + goto fail; + + *_pid = pid; +diff --git a/src/core/unit.c b/src/core/unit.c +index d298afb0d4..b0b1c77ef7 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -2500,7 +2500,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag + unit_add_to_gc_queue(u); + } + +-int unit_watch_pid(Unit *u, pid_t pid) { ++int unit_watch_pid(Unit *u, pid_t pid, bool exclusive) { + int r; + + assert(u); +@@ -2508,6 +2508,12 @@ int unit_watch_pid(Unit *u, pid_t pid) { + + /* Watch a specific PID */ + ++ /* Caller might be sure that this PID belongs to this unit only. Let's take this ++ * opportunity to remove any stalled references to this PID as they can be created ++ * easily (when watching a process which is not our direct child). */ ++ if (exclusive) ++ manager_unwatch_pid(u->manager, pid); ++ + r = set_ensure_allocated(&u->pids, NULL); + if (r < 0) + return r; +diff --git a/src/core/unit.h b/src/core/unit.h +index e1a60da244..68cc1869e4 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -655,7 +655,7 @@ typedef enum UnitNotifyFlags { + + void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags); + +-int unit_watch_pid(Unit *u, pid_t pid); ++int unit_watch_pid(Unit *u, pid_t pid, bool exclusive); + void unit_unwatch_pid(Unit *u, pid_t pid); + void unit_unwatch_all_pids(Unit *u); + +diff --git a/src/test/test-watch-pid.c b/src/test/test-watch-pid.c +index cb43b35bc5..8c70175aed 100644 +--- a/src/test/test-watch-pid.c ++++ b/src/test/test-watch-pid.c +@@ -49,25 +49,25 @@ int main(int argc, char *argv[]) { + assert_se(hashmap_isempty(m->watch_pids)); + assert_se(manager_get_unit_by_pid(m, 4711) == NULL); + +- assert_se(unit_watch_pid(a, 4711) >= 0); ++ assert_se(unit_watch_pid(a, 4711, false) >= 0); + assert_se(manager_get_unit_by_pid(m, 4711) == a); + +- assert_se(unit_watch_pid(a, 4711) >= 0); ++ assert_se(unit_watch_pid(a, 4711, false) >= 0); + assert_se(manager_get_unit_by_pid(m, 4711) == a); + +- assert_se(unit_watch_pid(b, 4711) >= 0); ++ assert_se(unit_watch_pid(b, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b); + +- assert_se(unit_watch_pid(b, 4711) >= 0); ++ assert_se(unit_watch_pid(b, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b); + +- assert_se(unit_watch_pid(c, 4711) >= 0); ++ assert_se(unit_watch_pid(c, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b || u == c); + +- assert_se(unit_watch_pid(c, 4711) >= 0); ++ assert_se(unit_watch_pid(c, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b || u == c); + diff --git a/SOURCES/0232-sd-bus-drop-two-inappropriate-empty-lines.patch b/SOURCES/0232-sd-bus-drop-two-inappropriate-empty-lines.patch deleted file mode 100644 index 335c018..0000000 --- a/SOURCES/0232-sd-bus-drop-two-inappropriate-empty-lines.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e81231e9a88ebc68c715010ce288c1d59c52e88f Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Jan 2019 18:18:18 +0100 -Subject: [PATCH] sd-bus: drop two inappropriate empty lines - -(cherry picked from commit 39feb2ce417e54cf9746e64b5dfd610cef6ac440) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/sd-bus.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index 55b008cc9f..01060d105c 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -2634,7 +2634,6 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) { - SD_BUS_ERROR_UNKNOWN_METHOD, - "Unknown method '%s' on interface '%s'.", m->member, m->interface); - } -- - if (r < 0) - return r; - -@@ -2758,7 +2757,6 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd - return r; - - *ret = TAKE_PTR(m); -- - return 1; - } - diff --git a/SOURCES/0233-core-only-watch-processes-when-it-s-really-necessary.patch b/SOURCES/0233-core-only-watch-processes-when-it-s-really-necessary.patch new file mode 100644 index 0000000..058ff69 --- /dev/null +++ b/SOURCES/0233-core-only-watch-processes-when-it-s-really-necessary.patch @@ -0,0 +1,55 @@ +From 25b93538eba0275d35ef4b0792c2cd63d63d5e8d Mon Sep 17 00:00:00 2001 +From: Franck Bui +Date: Tue, 19 Mar 2019 10:59:26 +0100 +Subject: [PATCH] core: only watch processes when it's really necessary +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If we know that main pid is our child then it's unnecessary to watch all +other processes of a unit since in this case we will get SIGCHLD when the main +process will exit and will act upon accordingly. + +So let's watch all processes only if the main process is not our child since in +this case we need to detect when the cgroup will become empty in order to +figure out when the service becomes dead. This is only needed by cgroupv1. + +Thanks Renaud Métrich for backporting this to RHEL. +Resolves: #1744972 +--- + src/core/service.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 310838a5f6..b1ec52d220 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -3410,8 +3410,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + if (main_pid_good(s) <= 0) + service_enter_stop_post(s, f); + +- /* If there is still a service +- * process around, wait until ++ /* If there is still a service process around, wait until + * that one quit, too */ + break; + +@@ -3433,10 +3432,14 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + if (notify_dbus) + unit_add_to_dbus_queue(u); + +- /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to watch, +- * under the assumption that we'll sooner or later get a SIGCHLD for them, as the original process we watched +- * was probably the parent of them, and they are hence now our children. */ +- (void) unit_enqueue_rewatch_pids(u); ++ /* We watch the main/control process otherwise we can't retrieve the unit they ++ * belong to with cgroupv1. But if they are not our direct child, we won't get a ++ * SIGCHLD for them. Therefore we need to look for others to watch so we can ++ * detect when the cgroup becomes empty. Note that the control process is always ++ * our child so it's pointless to watch all other processes. */ ++ if (!control_pid_good(s)) ++ if (!s->main_pid_known || s->main_pid_alien) ++ (void) unit_enqueue_rewatch_pids(u); + } + + static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { diff --git a/SOURCES/0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch b/SOURCES/0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch deleted file mode 100644 index 03ea861..0000000 --- a/SOURCES/0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch +++ /dev/null @@ -1,33 +0,0 @@ -From fb04f17617458d2d3d09e0bef29f1255d4d3500c Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Jan 2019 21:06:30 +0100 -Subject: [PATCH] sd-bus: initialize mutex after we allocated the wqueue - -That way the mutex doesn't have to be destroyed when we exit early due -to OOM. - -(cherry picked from commit 2fe9a10d7695c4c3a748969a0d1662c624e50e5e) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/sd-bus.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index 01060d105c..e49d58137d 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -248,12 +248,12 @@ _public_ int sd_bus_new(sd_bus **ret) { - b->original_pid = getpid_cached(); - b->n_groups = (size_t) -1; - -- assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0); -- - /* We guarantee that wqueue always has space for at least one entry */ - if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1)) - return -ENOMEM; - -+ assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0); -+ - *ret = TAKE_PTR(b); - return 0; - } diff --git a/SOURCES/0234-core-implement-per-unit-journal-rate-limiting.patch b/SOURCES/0234-core-implement-per-unit-journal-rate-limiting.patch new file mode 100644 index 0000000..a503b82 --- /dev/null +++ b/SOURCES/0234-core-implement-per-unit-journal-rate-limiting.patch @@ -0,0 +1,641 @@ +From a26f2b2732733aa361fec0a3a8f0ba377f48e75c Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Sun, 7 Oct 2018 20:28:36 -0700 +Subject: [PATCH] core: implement per unit journal rate limiting + +Add LogRateLimitIntervalSec= and LogRateLimitBurst= options for +services. If provided, these values get passed to the journald +client context, and those values are used in the rate limiting +function in the journal over the the journald.conf values. + +Part of #10230 + +(cherry picked from commit 90fc172e191f44979005a524521112f2bd1ff21b) + +Resolves: #1719577 +--- + catalog/systemd.catalog.in | 3 +- + doc/TRANSIENT-SETTINGS.md | 2 + + man/journald.conf.xml | 8 +- + man/systemd.exec.xml | 16 ++++ + src/core/dbus-execute.c | 8 ++ + src/core/execute.c | 14 ++++ + src/core/execute.h | 3 + + src/core/load-fragment-gperf.gperf.m4 | 2 + + src/core/unit.c | 92 +++++++++++++++++++++ + src/core/unit.h | 2 + + src/journal/journald-context.c | 50 ++++++++++- + src/journal/journald-context.h | 3 + + src/journal/journald-rate-limit.c | 38 ++++----- + src/journal/journald-rate-limit.h | 4 +- + src/journal/journald-server.c | 4 +- + src/shared/bus-unit-util.c | 8 ++ + test/fuzz/fuzz-unit-file/directives.service | 2 + + 17 files changed, 231 insertions(+), 28 deletions(-) + +diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in +index f1bddc6f7d..8234e387cf 100644 +--- a/catalog/systemd.catalog.in ++++ b/catalog/systemd.catalog.in +@@ -52,7 +52,8 @@ dropped, other services' messages are unaffected. + + The limits controlling when messages are dropped may be configured + with RateLimitIntervalSec= and RateLimitBurst= in +-/etc/systemd/journald.conf. See journald.conf(5) for details. ++/etc/systemd/journald.conf or LogRateLimitIntervalSec= and LogRateLimitBurst= ++in the unit file. See journald.conf(5) and systemd.exec(5) for details. + + -- e9bf28e6e834481bb6f48f548ad13606 + Subject: Journal messages have been missed +diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md +index ca9e8387b7..0ea444b133 100644 +--- a/doc/TRANSIENT-SETTINGS.md ++++ b/doc/TRANSIENT-SETTINGS.md +@@ -135,6 +135,8 @@ All execution-related settings are available for transient units. + ✓ SyslogLevelPrefix= + ✓ LogLevelMax= + ✓ LogExtraFields= ++✓ LogRateLimitIntervalSec= ++✓ LogRateLimitBurst= + ✓ SecureBits= + ✓ CapabilityBoundingSet= + ✓ AmbientCapabilities= +diff --git a/man/journald.conf.xml b/man/journald.conf.xml +index ee8e8b7faf..b57a244b22 100644 +--- a/man/journald.conf.xml ++++ b/man/journald.conf.xml +@@ -140,7 +140,13 @@ + following units: s, min, + h, ms, + us. To turn off any kind of rate limiting, +- set either value to 0. ++ set either value to 0. ++ ++ If a service provides rate limits for itself through ++ LogRateLimitIntervalSec= and/or LogRateLimitBurst= ++ in systemd.exec5, ++ those values will override the settings specified here. ++ + + + +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index 3bd790b485..737c52bcc4 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -1905,6 +1905,22 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy + matching. Assign an empty string to reset the list. + + ++ ++ LogRateLimitIntervalSec= ++ LogRateLimitBurst= ++ ++ Configures the rate limiting that is applied to messages generated by this unit. If, in the ++ time interval defined by LogRateLimitIntervalSec=, more messages than specified in ++ LogRateLimitBurst= are logged by a service, all further messages within the interval are ++ dropped until the interval is over. A message about the number of dropped messages is generated. The time ++ specification for LogRateLimitIntervalSec= may be specified in the following units: "s", ++ "min", "h", "ms", "us" (see ++ systemd.time7 for details). ++ The default settings are set by RateLimitIntervalSec= and RateLimitBurst= ++ configured in journald.conf5. ++ ++ ++ + + SyslogIdentifier= + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index c44970c10c..33a91c012e 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -718,6 +718,8 @@ const sd_bus_vtable bus_exec_vtable[] = { + SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("LogRateLimitIntervalUSec", "t", bus_property_get_usec, offsetof(ExecContext, log_rate_limit_interval_usec), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("LogRateLimitBurst", "u", bus_property_get_unsigned, offsetof(ExecContext, log_rate_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST), +@@ -1073,6 +1075,12 @@ int bus_exec_context_set_transient_property( + if (streq(name, "CPUSchedulingPriority")) + return bus_set_transient_sched_priority(u, name, &c->cpu_sched_priority, message, flags, error); + ++ if (streq(name, "LogRateLimitIntervalUSec")) ++ return bus_set_transient_usec(u, name, &c->log_rate_limit_interval_usec, message, flags, error); ++ ++ if (streq(name, "LogRateLimitBurst")) ++ return bus_set_transient_unsigned(u, name, &c->log_rate_limit_burst, message, flags, error); ++ + if (streq(name, "Personality")) + return bus_set_transient_personality(u, name, &c->personality, message, flags, error); + +diff --git a/src/core/execute.c b/src/core/execute.c +index c62f3cf849..8293c522bc 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -3693,6 +3693,9 @@ void exec_context_done(ExecContext *c) { + + exec_context_free_log_extra_fields(c); + ++ c->log_rate_limit_interval_usec = 0; ++ c->log_rate_limit_burst = 0; ++ + c->stdin_data = mfree(c->stdin_data); + c->stdin_data_size = 0; + } +@@ -4153,6 +4156,17 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { + fprintf(f, "%sLogLevelMax: %s\n", prefix, strna(t)); + } + ++ if (c->log_rate_limit_interval_usec > 0) { ++ char buf_timespan[FORMAT_TIMESPAN_MAX]; ++ ++ fprintf(f, ++ "%sLogRateLimitIntervalSec: %s\n", ++ prefix, format_timespan(buf_timespan, sizeof(buf_timespan), c->log_rate_limit_interval_usec, USEC_PER_SEC)); ++ } ++ ++ if (c->log_rate_limit_burst > 0) ++ fprintf(f, "%sLogRateLimitBurst: %u\n", prefix, c->log_rate_limit_burst); ++ + if (c->n_log_extra_fields > 0) { + size_t j; + +diff --git a/src/core/execute.h b/src/core/execute.h +index bff1634b88..8c91636adc 100644 +--- a/src/core/execute.h ++++ b/src/core/execute.h +@@ -216,6 +216,9 @@ struct ExecContext { + struct iovec* log_extra_fields; + size_t n_log_extra_fields; + ++ usec_t log_rate_limit_interval_usec; ++ unsigned log_rate_limit_burst; ++ + bool cpu_sched_reset_on_fork; + bool non_blocking; + bool private_tmp; +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index 15fb47838c..1066bcfb8f 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -57,6 +57,8 @@ $1.SyslogFacility, config_parse_log_facility, 0, + $1.SyslogLevel, config_parse_log_level, 0, offsetof($1, exec_context.syslog_priority) + $1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix) + $1.LogLevelMax, config_parse_log_level, 0, offsetof($1, exec_context.log_level_max) ++$1.LogRateLimitIntervalSec, config_parse_sec, 0, offsetof($1, exec_context.log_rate_limit_interval_usec) ++$1.LogRateLimitBurst, config_parse_unsigned, 0, offsetof($1, exec_context.log_rate_limit_burst) + $1.LogExtraFields, config_parse_log_extra_fields, 0, offsetof($1, exec_context) + $1.Capabilities, config_parse_warn_compat, DISABLED_LEGACY, offsetof($1, exec_context) + $1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context.secure_bits) +diff --git a/src/core/unit.c b/src/core/unit.c +index b0b1c77ef7..115739f4c6 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3245,6 +3245,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { + unit_serialize_item(u, f, "exported-invocation-id", yes_no(u->exported_invocation_id)); + unit_serialize_item(u, f, "exported-log-level-max", yes_no(u->exported_log_level_max)); + unit_serialize_item(u, f, "exported-log-extra-fields", yes_no(u->exported_log_extra_fields)); ++ unit_serialize_item(u, f, "exported-log-rate-limit-interval", yes_no(u->exported_log_rate_limit_interval)); ++ unit_serialize_item(u, f, "exported-log-rate-limit-burst", yes_no(u->exported_log_rate_limit_burst)); + + unit_serialize_item_format(u, f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base); + if (u->cpu_usage_last != NSEC_INFINITY) +@@ -3508,6 +3510,26 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { + + continue; + ++ } else if (streq(l, "exported-log-rate-limit-interval")) { ++ ++ r = parse_boolean(v); ++ if (r < 0) ++ log_unit_debug(u, "Failed to parse exported log rate limit interval %s, ignoring.", v); ++ else ++ u->exported_log_rate_limit_interval = r; ++ ++ continue; ++ ++ } else if (streq(l, "exported-log-rate-limit-burst")) { ++ ++ r = parse_boolean(v); ++ if (r < 0) ++ log_unit_debug(u, "Failed to parse exported log rate limit burst %s, ignoring.", v); ++ else ++ u->exported_log_rate_limit_burst = r; ++ ++ continue; ++ + } else if (STR_IN_SET(l, "cpu-usage-base", "cpuacct-usage-base")) { + + r = safe_atou64(v, &u->cpu_usage_base); +@@ -5241,6 +5263,60 @@ fail: + return r; + } + ++static int unit_export_log_rate_limit_interval(Unit *u, const ExecContext *c) { ++ _cleanup_free_ char *buf = NULL; ++ const char *p; ++ int r; ++ ++ assert(u); ++ assert(c); ++ ++ if (u->exported_log_rate_limit_interval) ++ return 0; ++ ++ if (c->log_rate_limit_interval_usec == 0) ++ return 0; ++ ++ p = strjoina("/run/systemd/units/log-rate-limit-interval:", u->id); ++ ++ if (asprintf(&buf, "%" PRIu64, c->log_rate_limit_interval_usec) < 0) ++ return log_oom(); ++ ++ r = symlink_atomic(buf, p); ++ if (r < 0) ++ return log_unit_debug_errno(u, r, "Failed to create log rate limit interval symlink %s: %m", p); ++ ++ u->exported_log_rate_limit_interval = true; ++ return 0; ++} ++ ++static int unit_export_log_rate_limit_burst(Unit *u, const ExecContext *c) { ++ _cleanup_free_ char *buf = NULL; ++ const char *p; ++ int r; ++ ++ assert(u); ++ assert(c); ++ ++ if (u->exported_log_rate_limit_burst) ++ return 0; ++ ++ if (c->log_rate_limit_burst == 0) ++ return 0; ++ ++ p = strjoina("/run/systemd/units/log-rate-limit-burst:", u->id); ++ ++ if (asprintf(&buf, "%u", c->log_rate_limit_burst) < 0) ++ return log_oom(); ++ ++ r = symlink_atomic(buf, p); ++ if (r < 0) ++ return log_unit_debug_errno(u, r, "Failed to create log rate limit burst symlink %s: %m", p); ++ ++ u->exported_log_rate_limit_burst = true; ++ return 0; ++} ++ + void unit_export_state_files(Unit *u) { + const ExecContext *c; + +@@ -5274,6 +5350,8 @@ void unit_export_state_files(Unit *u) { + if (c) { + (void) unit_export_log_level_max(u, c); + (void) unit_export_log_extra_fields(u, c); ++ (void) unit_export_log_rate_limit_interval(u, c); ++ (void) unit_export_log_rate_limit_burst(u, c); + } + } + +@@ -5310,6 +5388,20 @@ void unit_unlink_state_files(Unit *u) { + + u->exported_log_extra_fields = false; + } ++ ++ if (u->exported_log_rate_limit_interval) { ++ p = strjoina("/run/systemd/units/log-rate-limit-interval:", u->id); ++ (void) unlink(p); ++ ++ u->exported_log_rate_limit_interval = false; ++ } ++ ++ if (u->exported_log_rate_limit_burst) { ++ p = strjoina("/run/systemd/units/log-rate-limit-burst:", u->id); ++ (void) unlink(p); ++ ++ u->exported_log_rate_limit_burst = false; ++ } + } + + int unit_prepare_exec(Unit *u) { +diff --git a/src/core/unit.h b/src/core/unit.h +index 68cc1869e4..99755823eb 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -349,6 +349,8 @@ typedef struct Unit { + bool exported_invocation_id:1; + bool exported_log_level_max:1; + bool exported_log_extra_fields:1; ++ bool exported_log_rate_limit_interval:1; ++ bool exported_log_rate_limit_burst:1; + + /* When writing transient unit files, stores which section we stored last. If < 0, we didn't write any yet. If + * == 0 we are in the [Unit] section, if > 0 we are in the unit type-specific section. */ +diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c +index dba3525ed8..c8e97e16de 100644 +--- a/src/journal/journald-context.c ++++ b/src/journal/journald-context.c +@@ -140,6 +140,8 @@ static int client_context_new(Server *s, pid_t pid, ClientContext **ret) { + c->timestamp = USEC_INFINITY; + c->extra_fields_mtime = NSEC_INFINITY; + c->log_level_max = -1; ++ c->log_rate_limit_interval = s->rate_limit_interval; ++ c->log_rate_limit_burst = s->rate_limit_burst; + + r = hashmap_put(s->client_contexts, PID_TO_PTR(pid), c); + if (r < 0) { +@@ -151,7 +153,8 @@ static int client_context_new(Server *s, pid_t pid, ClientContext **ret) { + return 0; + } + +-static void client_context_reset(ClientContext *c) { ++static void client_context_reset(Server *s, ClientContext *c) { ++ assert(s); + assert(c); + + c->timestamp = USEC_INFINITY; +@@ -186,6 +189,9 @@ static void client_context_reset(ClientContext *c) { + c->extra_fields_mtime = NSEC_INFINITY; + + c->log_level_max = -1; ++ ++ c->log_rate_limit_interval = s->rate_limit_interval; ++ c->log_rate_limit_burst = s->rate_limit_burst; + } + + static ClientContext* client_context_free(Server *s, ClientContext *c) { +@@ -199,7 +205,7 @@ static ClientContext* client_context_free(Server *s, ClientContext *c) { + if (c->in_lru) + assert_se(prioq_remove(s->client_contexts_lru, c, &c->lru_index) >= 0); + +- client_context_reset(c); ++ client_context_reset(s, c); + + return mfree(c); + } +@@ -464,6 +470,42 @@ static int client_context_read_extra_fields( + return 0; + } + ++static int client_context_read_log_rate_limit_interval(ClientContext *c) { ++ _cleanup_free_ char *value = NULL; ++ const char *p; ++ int r; ++ ++ assert(c); ++ ++ if (!c->unit) ++ return 0; ++ ++ p = strjoina("/run/systemd/units/log-rate-limit-interval:", c->unit); ++ r = readlink_malloc(p, &value); ++ if (r < 0) ++ return r; ++ ++ return safe_atou64(value, &c->log_rate_limit_interval); ++} ++ ++static int client_context_read_log_rate_limit_burst(ClientContext *c) { ++ _cleanup_free_ char *value = NULL; ++ const char *p; ++ int r; ++ ++ assert(c); ++ ++ if (!c->unit) ++ return 0; ++ ++ p = strjoina("/run/systemd/units/log-rate-limit-burst:", c->unit); ++ r = readlink_malloc(p, &value); ++ if (r < 0) ++ return r; ++ ++ return safe_atou(value, &c->log_rate_limit_burst); ++} ++ + static void client_context_really_refresh( + Server *s, + ClientContext *c, +@@ -490,6 +532,8 @@ static void client_context_really_refresh( + (void) client_context_read_invocation_id(s, c); + (void) client_context_read_log_level_max(s, c); + (void) client_context_read_extra_fields(s, c); ++ (void) client_context_read_log_rate_limit_interval(c); ++ (void) client_context_read_log_rate_limit_burst(c); + + c->timestamp = timestamp; + +@@ -520,7 +564,7 @@ void client_context_maybe_refresh( + /* If the data isn't pinned and if the cashed data is older than the upper limit, we flush it out + * entirely. This follows the logic that as long as an entry is pinned the PID reuse is unlikely. */ + if (c->n_ref == 0 && c->timestamp + MAX_USEC < timestamp) { +- client_context_reset(c); ++ client_context_reset(s, c); + goto refresh; + } + +diff --git a/src/journal/journald-context.h b/src/journal/journald-context.h +index 9df3a38eff..5e19c71f14 100644 +--- a/src/journal/journald-context.h ++++ b/src/journal/journald-context.h +@@ -49,6 +49,9 @@ struct ClientContext { + size_t extra_fields_n_iovec; + void *extra_fields_data; + nsec_t extra_fields_mtime; ++ ++ usec_t log_rate_limit_interval; ++ unsigned log_rate_limit_burst; + }; + + int client_context_get( +diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c +index 6a8a36a736..539efb8669 100644 +--- a/src/journal/journald-rate-limit.c ++++ b/src/journal/journald-rate-limit.c +@@ -39,6 +39,10 @@ struct JournalRateLimitGroup { + JournalRateLimit *parent; + + char *id; ++ ++ /* Interval is stored to keep track of when the group expires */ ++ usec_t interval; ++ + JournalRateLimitPool pools[POOLS_MAX]; + uint64_t hash; + +@@ -47,8 +51,6 @@ struct JournalRateLimitGroup { + }; + + struct JournalRateLimit { +- usec_t interval; +- unsigned burst; + + JournalRateLimitGroup* buckets[BUCKETS_MAX]; + JournalRateLimitGroup *lru, *lru_tail; +@@ -58,18 +60,13 @@ struct JournalRateLimit { + uint8_t hash_key[16]; + }; + +-JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst) { ++JournalRateLimit *journal_rate_limit_new(void) { + JournalRateLimit *r; + +- assert(interval > 0 || burst == 0); +- + r = new0(JournalRateLimit, 1); + if (!r) + return NULL; + +- r->interval = interval; +- r->burst = burst; +- + random_bytes(r->hash_key, sizeof(r->hash_key)); + + return r; +@@ -109,7 +106,7 @@ _pure_ static bool journal_rate_limit_group_expired(JournalRateLimitGroup *g, us + assert(g); + + for (i = 0; i < POOLS_MAX; i++) +- if (g->pools[i].begin + g->parent->interval >= ts) ++ if (g->pools[i].begin + g->interval >= ts) + return false; + + return true; +@@ -126,7 +123,7 @@ static void journal_rate_limit_vacuum(JournalRateLimit *r, usec_t ts) { + journal_rate_limit_group_free(r->lru_tail); + } + +-static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r, const char *id, usec_t ts) { ++static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r, const char *id, usec_t interval, usec_t ts) { + JournalRateLimitGroup *g; + struct siphash state; + +@@ -145,6 +142,8 @@ static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r, + string_hash_func(g->id, &state); + g->hash = siphash24_finalize(&state); + ++ g->interval = interval; ++ + journal_rate_limit_vacuum(r, ts); + + LIST_PREPEND(bucket, r->buckets[g->hash % BUCKETS_MAX], g); +@@ -189,7 +188,7 @@ static unsigned burst_modulate(unsigned burst, uint64_t available) { + return burst; + } + +-int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available) { ++int journal_rate_limit_test(JournalRateLimit *r, const char *id, usec_t rl_interval, unsigned rl_burst, int priority, uint64_t available) { + uint64_t h; + JournalRateLimitGroup *g; + JournalRateLimitPool *p; +@@ -209,11 +208,6 @@ int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, u + if (!r) + return 1; + +- if (r->interval == 0 || r->burst == 0) +- return 1; +- +- burst = burst_modulate(r->burst, available); +- + ts = now(CLOCK_MONOTONIC); + + siphash24_init(&state, r->hash_key); +@@ -226,10 +220,16 @@ int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, u + break; + + if (!g) { +- g = journal_rate_limit_group_new(r, id, ts); ++ g = journal_rate_limit_group_new(r, id, rl_interval, ts); + if (!g) + return -ENOMEM; +- } ++ } else ++ g->interval = rl_interval; ++ ++ if (rl_interval == 0 || rl_burst == 0) ++ return 1; ++ ++ burst = burst_modulate(rl_burst, available); + + p = &g->pools[priority_map[priority]]; + +@@ -240,7 +240,7 @@ int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, u + return 1; + } + +- if (p->begin + r->interval < ts) { ++ if (p->begin + rl_interval < ts) { + unsigned s; + + s = p->suppressed; +diff --git a/src/journal/journald-rate-limit.h b/src/journal/journald-rate-limit.h +index 3a7f106de0..a2992800fe 100644 +--- a/src/journal/journald-rate-limit.h ++++ b/src/journal/journald-rate-limit.h +@@ -5,6 +5,6 @@ + + typedef struct JournalRateLimit JournalRateLimit; + +-JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst); ++JournalRateLimit *journal_rate_limit_new(void); + void journal_rate_limit_free(JournalRateLimit *r); +-int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available); ++int journal_rate_limit_test(JournalRateLimit *r, const char *id, usec_t rl_interval, unsigned rl_burst, int priority, uint64_t available); +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 8de45552f6..0c983e102a 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -943,7 +943,7 @@ void server_dispatch_message( + if (c && c->unit) { + (void) determine_space(s, &available, NULL); + +- rl = journal_rate_limit_test(s->rate_limit, c->unit, priority & LOG_PRIMASK, available); ++ rl = journal_rate_limit_test(s->rate_limit, c->unit, c->log_rate_limit_interval, c->log_rate_limit_burst, priority & LOG_PRIMASK, available); + if (rl == 0) + return; + +@@ -1852,7 +1852,7 @@ int server_init(Server *s) { + if (!s->udev) + return -ENOMEM; + +- s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, s->rate_limit_burst); ++ s->rate_limit = journal_rate_limit_new(); + if (!s->rate_limit) + return -ENOMEM; + +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 3238b442c0..271cc054da 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -755,6 +755,14 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con + + return bus_append_parse_nsec(m, field, eq); + ++ if (STR_IN_SET(field, "LogRateLimitIntervalSec")) ++ ++ return bus_append_parse_sec_rename(m, field, eq); ++ ++ if (streq(field, "LogRateLimitBurst")) ++ ++ return bus_append_safe_atou(m, field, eq); ++ + if (streq(field, "MountFlags")) + + return bus_append_mount_propagation_flags_from_string(m, field, eq); +diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service +index c2334d3b19..d8d1fc68b8 100644 +--- a/test/fuzz/fuzz-unit-file/directives.service ++++ b/test/fuzz/fuzz-unit-file/directives.service +@@ -792,6 +792,8 @@ LineMax= + LockPersonality= + LogExtraFields= + LogLevelMax= ++LogRateLimitIntervalSec= ++LogRateLimitBurst= + LogsDirectory= + LogsDirectoryMode= + MACVLAN= diff --git a/SOURCES/0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch b/SOURCES/0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch deleted file mode 100644 index 732ad35..0000000 --- a/SOURCES/0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 51c839c733ff53061807d92326830b5fe8499041 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Jan 2019 21:07:42 +0100 -Subject: [PATCH] sd-bus: always go through sd_bus_unref() to free messages - -Don't try to be smart, don't bypass the ref counting logic if there's no -real reason to. - -This matters if we want to tweak the ref counting logic later. - -(cherry picked from commit b41812d1e308de03c879cfca490105216d528c4b) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/bus-message.c | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c -index 2ea3c5bba9..ac19cc04bf 100644 ---- a/src/libsystemd/sd-bus/bus-message.c -+++ b/src/libsystemd/sd-bus/bus-message.c -@@ -138,8 +138,6 @@ static sd_bus_message* message_free(sd_bus_message *m) { - return mfree(m); - } - --DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free); -- - static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) { - void *op, *np; - size_t old_size, new_size, start; -@@ -531,7 +529,7 @@ int bus_message_from_malloc( - const char *label, - sd_bus_message **ret) { - -- _cleanup_(message_freep) sd_bus_message *m = NULL; -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - size_t sz; - int r; - -@@ -651,7 +649,7 @@ _public_ int sd_bus_message_new_method_call( - const char *interface, - const char *member) { - -- _cleanup_(message_freep) sd_bus_message *t = NULL; -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; - int r; - - assert_return(bus, -ENOTCONN); -@@ -696,7 +694,7 @@ static int message_new_reply( - uint8_t type, - sd_bus_message **m) { - -- _cleanup_(message_freep) sd_bus_message *t = NULL; -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; - uint64_t cookie; - int r; - -@@ -747,7 +745,7 @@ _public_ int sd_bus_message_new_method_error( - sd_bus_message **m, - const sd_bus_error *e) { - -- _cleanup_(message_freep) sd_bus_message *t = NULL; -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; - int r; - - assert_return(sd_bus_error_is_set(e), -EINVAL); -@@ -850,7 +848,7 @@ int bus_message_new_synthetic_error( - const sd_bus_error *e, - sd_bus_message **m) { - -- _cleanup_(message_freep) sd_bus_message *t = NULL; -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; - int r; - - assert(bus); diff --git a/SOURCES/0235-bus-message-introduce-two-kinds-of-references-to-bus.patch b/SOURCES/0235-bus-message-introduce-two-kinds-of-references-to-bus.patch deleted file mode 100644 index cf6db16..0000000 --- a/SOURCES/0235-bus-message-introduce-two-kinds-of-references-to-bus.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 02d55f8f5bfd38ed2958c7e55707cadb058071be Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Jan 2019 18:18:54 +0100 -Subject: [PATCH] bus-message: introduce two kinds of references to bus - messages - -Before this commit bus messages had a single reference count: when it -reached zero the message would be freed. This simple approach meant a -cyclic dependency was typically seen: a message that was enqueued in a -bus connection object would reference the bus connection object but also -itself be referenced by the bus connection object. So far out strategy -to avoid cases like this was: make sure to process the bus connection -regularly so that messages don#t stay queued, and at exit flush/close -the connection so that the message queued would be emptied, and thus the -cyclic dependencies resolved. Im many cases this isn't done properly -however. - -With this change, let's address the issue more systematically: let's -break the reference cycle. Specifically, there are now two types of -references to a bus message: - -1. A regular one, which keeps both the message and the bus object it is - associated with pinned. - -2. A "queue" reference, which is weaker: it pins the message, but not - the bus object it is associated with. - -The idea is then that regular user handling uses regular references, but -when a message is enqueued on its connection, then this takes a "queue" -reference instead. This then means that a queued message doesn't imply -the connection itself remains pinned, only regular references to the -connection or a message associated with it do. Thus, if we end up in the -situation where a user allocates a bus and a message and enqueues the -latter in the former and drops all refs to both, then this will detect -this case and free both. - -Note that this scheme isn't perfect, it only covers references between -messages and the busses they are associated with. If OTOH a bus message -is enqueued on a different bus than it is associated with cyclic deps -cannot be recognized with this simple algorithm, and thus if you enqueue -a message associated with a bus A on a bus B, and another message -associated with bus B on a bus A, a cyclic ref will be in effect and not -be discovered. However, given that this is an exotic case (though one -that happens, consider systemd-bus-stdio-bridge), it should be OK not to -cover with this, and people have to explicit flush all queues on exit in -that case. - -Note that this commit only establishes the separate reference counters -per message. A follow-up commit will start making use of this from the -bus connection object. - -(cherry picked from commit 1b3f9dd759ca0ea215e7b89f8ce66d1b724497b9) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/bus-message.c | 60 ++++++++++++++++++++++++++--- - src/libsystemd/sd-bus/bus-message.h | 14 ++++++- - 2 files changed, 68 insertions(+), 6 deletions(-) - -diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c -index ac19cc04bf..ce7e67ecf2 100644 ---- a/src/libsystemd/sd-bus/bus-message.c -+++ b/src/libsystemd/sd-bus/bus-message.c -@@ -120,7 +120,8 @@ static sd_bus_message* message_free(sd_bus_message *m) { - - message_reset_parts(m); - -- sd_bus_unref(m->bus); -+ /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user -+ * reference to the bus message also is considered a reference to the bus connection itself. */ - - if (m->free_fds) { - close_many(m->fds, m->n_fds); -@@ -893,27 +894,76 @@ int bus_message_new_synthetic_error( - } - - _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) { -- - if (!m) - return NULL; - -- assert(m->n_ref > 0); -+ /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at -+ * least one bus connection object. */ -+ assert(m->n_ref > 0 || m->n_queued > 0); -+ - m->n_ref++; - -+ /* Each user reference to a bus message shall also be considered a ref on the bus */ -+ sd_bus_ref(m->bus); - return m; - } - - _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) { -- - if (!m) - return NULL; - - assert(m->n_ref > 0); -+ -+ sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it -+ * here. Note we have to do this before decrementing our own n_ref here, since -+ * otherwise, if this message is currently queued sd_bus_unref() might call -+ * bus_message_unref_queued() for this which might then destroy the message -+ * while we are still processing it. */ - m->n_ref--; - -- if (m->n_ref > 0) -+ if (m->n_ref > 0 || m->n_queued > 0) - return NULL; - -+ /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful -+ * to reset the field only after the last reference to the bus is dropped, after all we might keep -+ * multiple references to the bus, once for each reference kept on outselves. */ -+ m->bus = NULL; -+ -+ return message_free(m); -+} -+ -+sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) { -+ if (!m) -+ return NULL; -+ -+ /* If this is a different bus than the message is associated with, then implicitly turn this into a -+ * regular reference. This means that you can create a memory leak by enqueuing a message generated -+ * on one bus onto another at the same time as enqueueing a message from the second one on the first, -+ * as we'll not detect the cyclic references there. */ -+ if (bus != m->bus) -+ return sd_bus_message_ref(m); -+ -+ assert(m->n_ref > 0 || m->n_queued > 0); -+ m->n_queued++; -+ -+ return m; -+} -+ -+sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) { -+ if (!m) -+ return NULL; -+ -+ if (bus != m->bus) -+ return sd_bus_message_unref(m); -+ -+ assert(m->n_queued > 0); -+ m->n_queued--; -+ -+ if (m->n_ref > 0 || m->n_queued > 0) -+ return NULL; -+ -+ m->bus = NULL; -+ - return message_free(m); - } - -diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h -index 97f6060e30..ded88005e2 100644 ---- a/src/libsystemd/sd-bus/bus-message.h -+++ b/src/libsystemd/sd-bus/bus-message.h -@@ -51,7 +51,16 @@ struct bus_body_part { - }; - - struct sd_bus_message { -- unsigned n_ref; -+ /* Caveat: a message can be referenced in two different ways: the main (user-facing) way will also -+ * pin the bus connection object the message is associated with. The secondary way ("queued") is used -+ * when a message is in the read or write queues of the bus connection object, which will not pin the -+ * bus connection object. This is necessary so that we don't have to have a pair of cyclic references -+ * between a message that is queued and its connection: as soon as a message is only referenced by -+ * the connection (by means of being queued) and the connection itself has no other references it -+ * will be freed. */ -+ -+ unsigned n_ref; /* Counter of references that pin the connection */ -+ unsigned n_queued; /* Counter of references that do not pin the connection */ - - sd_bus *bus; - -@@ -216,3 +225,6 @@ int bus_message_append_sender(sd_bus_message *m, const char *sender); - - void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m); - void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m); -+ -+sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus); -+sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus); diff --git a/SOURCES/0235-path-stop-watching-path-specs-once-we-triggered-the-.patch b/SOURCES/0235-path-stop-watching-path-specs-once-we-triggered-the-.patch new file mode 100644 index 0000000..c538f50 --- /dev/null +++ b/SOURCES/0235-path-stop-watching-path-specs-once-we-triggered-the-.patch @@ -0,0 +1,35 @@ +From 55d9d6dfb731d2f1c8c940fb8a7ea0af6c498c4c Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 9 Sep 2019 14:38:35 +0200 +Subject: [PATCH] path: stop watching path specs once we triggered the target + unit + +We start watching them again once we get a notification that triggered +unit entered inactive or failed state. + +Fixes: #10503 +(cherry picked from commit 8fca6944c2ee20c63d62154c8badddc77170b176) + +Resolves: #1763161 +--- + src/core/path.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/core/path.c b/src/core/path.c +index 68b13b610a..5ef178a46b 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -478,11 +478,9 @@ static void path_enter_running(Path *p) { + + p->inotify_triggered = false; + +- r = path_watch(p); +- if (r < 0) +- goto fail; +- + path_set_state(p, PATH_RUNNING); ++ path_unwatch(p); ++ + return; + + fail: diff --git a/SOURCES/0236-journald-fixed-assertion-failure-when-system-journal.patch b/SOURCES/0236-journald-fixed-assertion-failure-when-system-journal.patch new file mode 100644 index 0000000..25c91dd --- /dev/null +++ b/SOURCES/0236-journald-fixed-assertion-failure-when-system-journal.patch @@ -0,0 +1,28 @@ +From 33aa231f5bf3335cdacfb38ffba757865019ce4d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= + <1163635+rmetrich@users.noreply.github.com> +Date: Mon, 3 Sep 2018 05:42:39 +0200 +Subject: [PATCH] journald: fixed assertion failure when system journal + rotation fails (#9893) + +(cherry picked from commit fd790d6f09b10a87b007b71403cb018f18ff91c9) + +Resolves: #1763619 +--- + src/journal/journald-server.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 0c983e102a..6aecb67d6c 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1041,7 +1041,8 @@ int server_flush_to_var(Server *s, bool require_flag_file) { + r = 0; + + finish: +- journal_file_post_change(s->system_journal); ++ if (s->system_journal) ++ journal_file_post_change(s->system_journal); + + s->runtime_journal = journal_file_close(s->runtime_journal); + diff --git a/SOURCES/0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch b/SOURCES/0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch deleted file mode 100644 index 2ce2ef3..0000000 --- a/SOURCES/0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch +++ /dev/null @@ -1,74 +0,0 @@ -From f16b5124274f35c475cb70fa936567877a4b74f9 Mon Sep 17 00:00:00 2001 -From: Jan Synacek -Date: Fri, 31 Jan 2020 11:34:45 +0100 -Subject: [PATCH] sd-bus: introduce API for re-enqueuing incoming messages - -When authorizing via PolicyKit we want to process incoming method calls -twice: once to process and figure out that we need PK authentication, -and a second time after we aquired PK authentication to actually execute -the operation. With this new call sd_bus_enqueue_for_read() we have a -way to put an incoming message back into the read queue for this -purpose. - -This might have other uses too, for example debugging. -Related: CVE-2020-1712 ---- - src/libsystemd/libsystemd.sym | 1 + - src/libsystemd/sd-bus/sd-bus.c | 24 ++++++++++++++++++++++++ - src/systemd/sd-bus.h | 1 + - 3 files changed, 26 insertions(+) - -diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym -index 1eec17db50..e9972593a6 100644 ---- a/src/libsystemd/libsystemd.sym -+++ b/src/libsystemd/libsystemd.sym -@@ -569,4 +569,5 @@ global: - sd_event_source_get_inotify_mask; - sd_event_source_set_destroy_callback; - sd_event_source_get_destroy_callback; -+ sd_bus_enqueue_for_read; - } LIBSYSTEMD_238; -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index e49d58137d..68ad6cbe89 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -4120,3 +4120,27 @@ _public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) { - *ret = bus->wqueue_size; - return 0; - } -+ -+_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) { -+ int r; -+ -+ assert_return(bus, -EINVAL); -+ assert_return(bus = bus_resolve(bus), -ENOPKG); -+ assert_return(m, -EINVAL); -+ assert_return(m->sealed, -EINVAL); -+ assert_return(!bus_pid_changed(bus), -ECHILD); -+ -+ if (!BUS_IS_OPEN(bus->state)) -+ return -ENOTCONN; -+ -+ /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication, -+ * where we want accept a message, then determine we need to interactively authenticate the user, and -+ * when we have that process the message again. */ -+ -+ r = bus_rqueue_make_room(bus); -+ if (r < 0) -+ return r; -+ -+ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus); -+ return 0; -+} -diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h -index 54c4b1ca83..9ba757b13d 100644 ---- a/src/systemd/sd-bus.h -+++ b/src/systemd/sd-bus.h -@@ -193,6 +193,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r); - int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); - int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); - int sd_bus_flush(sd_bus *bus); -+int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m); - - sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); - sd_bus_message* sd_bus_get_current_message(sd_bus *bus); diff --git a/SOURCES/0237-sd-event-add-sd_event_source_disable_unref-helper.patch b/SOURCES/0237-sd-event-add-sd_event_source_disable_unref-helper.patch deleted file mode 100644 index 9ff72ce..0000000 --- a/SOURCES/0237-sd-event-add-sd_event_source_disable_unref-helper.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 8e155b3dad29a96cd2586185c63604c42bc5690e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Wed, 8 May 2019 14:39:57 +0200 -Subject: [PATCH] sd-event: add sd_event_source_disable_unref() helper - -(cherry picked from commit afd15bbb4b6414b9356799c63029e36642dae8e4) -Related: CVE-2020-1712 ---- - man/rules/meson.build | 4 +++- - man/sd_event_source_unref.xml | 30 +++++++++++++++++++----------- - src/libsystemd/libsystemd.sym | 1 + - src/libsystemd/sd-event/sd-event.c | 6 ++++++ - src/systemd/sd-event.h | 1 + - 5 files changed, 30 insertions(+), 12 deletions(-) - -diff --git a/man/rules/meson.build b/man/rules/meson.build -index 989d11c9b9..7ae94ea265 100644 ---- a/man/rules/meson.build -+++ b/man/rules/meson.build -@@ -340,7 +340,9 @@ manpages = [ - ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''], - ['sd_event_source_unref', - '3', -- ['sd_event_source_ref', 'sd_event_source_unrefp'], -+ ['sd_event_source_disable_unref', -+ 'sd_event_source_ref', -+ 'sd_event_source_unrefp'], - ''], - ['sd_event_wait', - '3', -diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml -index d1b83c57aa..af8fed33f2 100644 ---- a/man/sd_event_source_unref.xml -+++ b/man/sd_event_source_unref.xml -@@ -22,6 +22,7 @@ - sd_event_source_unref - sd_event_source_unrefp - sd_event_source_ref -+ sd_event_source_disable_unref - - Increase or decrease event source reference counters - -@@ -45,6 +46,10 @@ - sd_event_source *source - - -+ -+ sd_event_source* sd_event_source_disable_unref -+ sd_event_source *source -+ - - - -@@ -80,23 +85,26 @@ - the passed event source object is - NULL. - -- Note that event source objects stay alive and may be -- dispatched as long as they have a reference counter greater than -- zero. In order to drop a reference of an event source and make -- sure the associated event source handler function is not called -- anymore it is recommended to combine a call of -+ Note that event source objects stay alive and may be dispatched as long as they have a reference -+ counter greater than zero. In order to drop a reference of an event source and make sure the associated -+ event source handler function is not called anymore it is recommended to combine a call of - sd_event_source_unref() with a prior call to -- sd_event_source_set_enabled() with -- SD_EVENT_OFF. -+ sd_event_source_set_enabled() with SD_EVENT_OFF or call -+ sd_event_source_disable_unref(), see below. -+ -+ sd_event_source_disable_unref() combines a call to -+ sd_event_source_set_enabled() with SD_EVENT_OFF with -+ sd_event_source_unref(). This ensures that the source is disabled before the local -+ reference to it is lost. The source parameter is allowed to be -+ NULL. - - - - Return Value - -- sd_event_source_unref() always returns -- NULL. -- sd_event_source_ref() always returns the -- event source object passed in. -+ sd_event_source_unref() and -+ sd_event_source_disable_unref() always return NULL. -+ sd_event_source_ref() always returns the event source object passed in. - - - -diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym -index e9972593a6..778e88a16c 100644 ---- a/src/libsystemd/libsystemd.sym -+++ b/src/libsystemd/libsystemd.sym -@@ -570,4 +570,5 @@ global: - sd_event_source_set_destroy_callback; - sd_event_source_get_destroy_callback; - sd_bus_enqueue_for_read; -+ sd_event_source_disable_unref; - } LIBSYSTEMD_238; -diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c -index d53b9a7026..0d3bf5cbb6 100644 ---- a/src/libsystemd/sd-event/sd-event.c -+++ b/src/libsystemd/sd-event/sd-event.c -@@ -580,6 +580,12 @@ _public_ sd_event* sd_event_unref(sd_event *e) { - return NULL; - } - -+_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) { -+ if (s) -+ (void) sd_event_source_set_enabled(s, SD_EVENT_OFF); -+ return sd_event_source_unref(s); -+} -+ - static bool event_pid_changed(sd_event *e) { - assert(e); - -diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h -index 7fcae4ac49..9876be01c6 100644 ---- a/src/systemd/sd-event.h -+++ b/src/systemd/sd-event.h -@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret); - - sd_event_source* sd_event_source_ref(sd_event_source *s); - sd_event_source* sd_event_source_unref(sd_event_source *s); -+sd_event_source* sd_event_source_disable_unref(sd_event_source *s); - - sd_event *sd_event_source_get_event(sd_event_source *s); - void* sd_event_source_get_userdata(sd_event_source *s); diff --git a/SOURCES/0237-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch b/SOURCES/0237-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch new file mode 100644 index 0000000..4599b60 --- /dev/null +++ b/SOURCES/0237-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch @@ -0,0 +1,29 @@ +From a7f18f9ef4abc7e0732d1710ead2a18a38c3ec6d Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Fri, 15 Mar 2019 10:05:33 +0100 +Subject: [PATCH] test: use PBKDF2 instead of Argon2 in cryptsetup... + +to reduce memory requirements for volume manipulation. Also, +to further improve the test performance, reduce number of PBKDF +iterations to 1000 (allowed minimum). + +(cherry picked from commit 5b69d297c153478f6f5e74ba66e1f4e5b6422baf) + +Related: #1761519 +--- + test/TEST-02-CRYPTSETUP/test.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh +index 545602e17a..c38e56f72e 100755 +--- a/test/TEST-02-CRYPTSETUP/test.sh ++++ b/test/TEST-02-CRYPTSETUP/test.sh +@@ -29,7 +29,7 @@ check_result_qemu() { + test_setup() { + create_empty_image + echo -n test >$TESTDIR/keyfile +- cryptsetup -q luksFormat ${LOOPDEV}p2 $TESTDIR/keyfile ++ cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 ${LOOPDEV}p2 $TESTDIR/keyfile + cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile + mkfs.ext4 -L var /dev/mapper/varcrypt + mkdir -p $TESTDIR/root diff --git a/SOURCES/0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch b/SOURCES/0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch deleted file mode 100644 index 24c565a..0000000 --- a/SOURCES/0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch +++ /dev/null @@ -1,156 +0,0 @@ -From ae3cdcd5f8954d020a146c980ed064c21fd21239 Mon Sep 17 00:00:00 2001 -From: Jan Synacek -Date: Fri, 31 Jan 2020 15:17:25 +0100 -Subject: [PATCH] polkit: when authorizing via PK let's re-resolve - callback/userdata instead of caching it - -Previously, when doing an async PK query we'd store the original -callback/userdata pair and call it again after the PK request is -complete. This is problematic, since PK queries might be slow and in the -meantime the userdata might be released and re-acquired. Let's avoid -this by always traversing through the message handlers so that we always -re-resolve the callback and userdata pair and thus can be sure it's -up-to-date and properly valid. - -Resolves: CVE-2020-1712 ---- - src/shared/bus-util.c | 74 +++++++++++++++++++++++++++++-------------- - 1 file changed, 50 insertions(+), 24 deletions(-) - -diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c -index 2d908eb45c..5ed68429be 100644 ---- a/src/shared/bus-util.c -+++ b/src/shared/bus-util.c -@@ -319,10 +319,10 @@ int bus_test_polkit( - - typedef struct AsyncPolkitQuery { - sd_bus_message *request, *reply; -- sd_bus_message_handler_t callback; -- void *userdata; - sd_bus_slot *slot; -+ - Hashmap *registry; -+ sd_event_source *defer_event_source; - } AsyncPolkitQuery; - - static void async_polkit_query_free(AsyncPolkitQuery *q) { -@@ -338,9 +338,22 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { - sd_bus_message_unref(q->request); - sd_bus_message_unref(q->reply); - -+ sd_event_source_disable_unref(q->defer_event_source); - free(q); - } - -+static int async_polkit_defer(sd_event_source *s, void *userdata) { -+ AsyncPolkitQuery *q = userdata; -+ -+ assert(s); -+ -+ /* This is called as idle event source after we processed the async polkit reply, hopefully after the -+ * method call we re-enqueued has been properly processed. */ -+ -+ async_polkit_query_free(q); -+ return 0; -+} -+ - static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { - _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; - AsyncPolkitQuery *q = userdata; -@@ -349,19 +362,45 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e - assert(reply); - assert(q); - -+ assert(q->slot); - q->slot = sd_bus_slot_unref(q->slot); -+ -+ assert(!q->reply); - q->reply = sd_bus_message_ref(reply); - -+ /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the -+ * whole message processing again, and thus re-validating and re-retrieving the "userdata" field -+ * again. -+ * -+ * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again, -+ * i.e. after the second time the message is processed is complete. */ -+ -+ assert(!q->defer_event_source); -+ r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q); -+ if (r < 0) -+ goto fail; -+ -+ r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE); -+ if (r < 0) -+ goto fail; -+ -+ r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT); -+ if (r < 0) -+ goto fail; -+ - r = sd_bus_message_rewind(q->request, true); -- if (r < 0) { -- r = sd_bus_reply_method_errno(q->request, r, NULL); -- goto finish; -- } -+ if (r < 0) -+ goto fail; - -- r = q->callback(q->request, q->userdata, &error_buffer); -- r = bus_maybe_reply_error(q->request, r, &error_buffer); -+ r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request); -+ if (r < 0) -+ goto fail; - --finish: -+ return 1; -+ -+fail: -+ log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m"); -+ (void) sd_bus_reply_method_errno(q->request, r, NULL); - async_polkit_query_free(q); - - return r; -@@ -382,11 +421,9 @@ int bus_verify_polkit_async( - #if ENABLE_POLKIT - _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; - AsyncPolkitQuery *q; -- const char *sender, **k, **v; -- sd_bus_message_handler_t callback; -- void *userdata; - int c; - #endif -+ const char *sender, **k, **v; - int r; - - assert(call); -@@ -444,20 +481,11 @@ int bus_verify_polkit_async( - else if (r > 0) - return 1; - --#if ENABLE_POLKIT -- if (sd_bus_get_current_message(call->bus) != call) -- return -EINVAL; -- -- callback = sd_bus_get_current_handler(call->bus); -- if (!callback) -- return -EINVAL; -- -- userdata = sd_bus_get_current_userdata(call->bus); -- - sender = sd_bus_message_get_sender(call); - if (!sender) - return -EBADMSG; - -+#if ENABLE_POLKIT - c = sd_bus_message_get_allow_interactive_authorization(call); - if (c < 0) - return c; -@@ -509,8 +537,6 @@ int bus_verify_polkit_async( - return -ENOMEM; - - q->request = sd_bus_message_ref(call); -- q->callback = callback; -- q->userdata = userdata; - - r = hashmap_put(*registry, call, q); - if (r < 0) { diff --git a/SOURCES/0238-test-mask-several-unnecessary-services.patch b/SOURCES/0238-test-mask-several-unnecessary-services.patch new file mode 100644 index 0000000..6ff56e8 --- /dev/null +++ b/SOURCES/0238-test-mask-several-unnecessary-services.patch @@ -0,0 +1,252 @@ +From c748b95f5a00b6d9c46026c3d251c40437e6b64a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 1 Nov 2018 17:26:36 +0900 +Subject: [PATCH] test: mask several unnecessary services + +This may make CIs run faster. + +(cherry picked from commit 056ae88152a722bdbea54ff33db815d585c8b9c6) + +Related: #1761519 +--- + test/TEST-02-CRYPTSETUP/test.sh | 8 ++++++++ + test/TEST-03-JOBS/test.sh | 8 ++++++++ + test/TEST-04-JOURNAL/test.sh | 8 ++++++++ + test/TEST-05-RLIMITS/test.sh | 8 ++++++++ + test/TEST-07-ISSUE-1981/test.sh | 8 ++++++++ + test/TEST-11-ISSUE-3166/test.sh | 8 ++++++++ + test/TEST-12-ISSUE-3171/test.sh | 8 ++++++++ + test/TEST-13-NSPAWN-SMOKE/test.sh | 8 ++++++++ + test/TEST-18-FAILUREACTION/test.sh | 7 +++++++ + test/TEST-19-DELEGATE/test.sh | 8 ++++++++ + test/TEST-20-MAINPIDGAMES/test.sh | 8 ++++++++ + test/TEST-23-TYPE-EXEC/test.sh | 8 ++++++++ + 12 files changed, 95 insertions(+) + +diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh +index c38e56f72e..97eb2f409e 100755 +--- a/test/TEST-02-CRYPTSETUP/test.sh ++++ b/test/TEST-02-CRYPTSETUP/test.sh +@@ -45,6 +45,14 @@ test_setup() { + + setup_basic_environment + ++ # mask some services that we do not want to run in these tests ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service ++ + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system.conf <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service < -Date: Thu, 17 Jan 2019 18:31:59 +0100 -Subject: [PATCH] sd-bus: use "queue" message references for managing r/w - message queues in connection objects - -Let's make use of the new concept the previous commit added. - -See: #4846 -(cherry picked from commit c1757a70eac0382c4837a3833d683919f6a48ed7) -Related: CVE-2020-1712 ---- - src/libsystemd/sd-bus/bus-socket.c | 6 ++- - src/libsystemd/sd-bus/sd-bus.c | 60 ++++++++++++++---------------- - 2 files changed, 32 insertions(+), 34 deletions(-) - -diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c -index 17cfa8e1fd..4a72795d2b 100644 ---- a/src/libsystemd/sd-bus/bus-socket.c -+++ b/src/libsystemd/sd-bus/bus-socket.c -@@ -1116,8 +1116,10 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { - bus->fds = NULL; - bus->n_fds = 0; - -- if (t) -- bus->rqueue[bus->rqueue_size++] = t; -+ if (t) { -+ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus); -+ sd_bus_message_unref(t); -+ } - - return 1; - } -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index 68ad6cbe89..a3509f7e89 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -148,13 +148,13 @@ static void bus_reset_queues(sd_bus *b) { - assert(b); - - while (b->rqueue_size > 0) -- sd_bus_message_unref(b->rqueue[--b->rqueue_size]); -+ bus_message_unref_queued(b->rqueue[--b->rqueue_size], b); - - b->rqueue = mfree(b->rqueue); - b->rqueue_allocated = 0; - - while (b->wqueue_size > 0) -- sd_bus_message_unref(b->wqueue[--b->wqueue_size]); -+ bus_message_unref_queued(b->wqueue[--b->wqueue_size], b); - - b->wqueue = mfree(b->wqueue); - b->wqueue_allocated = 0; -@@ -493,7 +493,7 @@ static int synthesize_connected_signal(sd_bus *bus) { - - /* Insert at the very front */ - memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size); -- bus->rqueue[0] = TAKE_PTR(m); -+ bus->rqueue[0] = bus_message_ref_queued(m, bus); - bus->rqueue_size++; - - return 0; -@@ -1760,7 +1760,7 @@ static int dispatch_wqueue(sd_bus *bus) { - * anyway. */ - - bus->wqueue_size--; -- sd_bus_message_unref(bus->wqueue[0]); -+ bus_message_unref_queued(bus->wqueue[0], bus); - memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size); - bus->windex = 0; - -@@ -1789,6 +1789,15 @@ int bus_rqueue_make_room(sd_bus *bus) { - return 0; - } - -+static void rqueue_drop_one(sd_bus *bus, size_t i) { -+ assert(bus); -+ assert(i < bus->rqueue_size); -+ -+ bus_message_unref_queued(bus->rqueue[i], bus); -+ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); -+ bus->rqueue_size--; -+} -+ - static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) { - int r, ret = 0; - -@@ -1803,10 +1812,8 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd - for (;;) { - if (bus->rqueue_size > 0) { - /* Dispatch a queued message */ -- -- *m = bus->rqueue[0]; -- bus->rqueue_size--; -- memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size); -+ *m = sd_bus_message_ref(bus->rqueue[0]); -+ rqueue_drop_one(bus, 0); - return 1; - } - -@@ -1884,7 +1891,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { - * of the wqueue array is always allocated so - * that we always can remember how much was - * written. */ -- bus->wqueue[0] = sd_bus_message_ref(m); -+ bus->wqueue[0] = bus_message_ref_queued(m, bus); - bus->wqueue_size = 1; - bus->windex = idx; - } -@@ -1898,7 +1905,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { - if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1)) - return -ENOMEM; - -- bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m); -+ bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus); - } - - finish: -@@ -2124,37 +2131,30 @@ _public_ int sd_bus_call( - usec_t left; - - while (i < bus->rqueue_size) { -- sd_bus_message *incoming = NULL; -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL; - -- incoming = bus->rqueue[i]; -+ incoming = sd_bus_message_ref(bus->rqueue[i]); - - if (incoming->reply_cookie == cookie) { - /* Found a match! */ - -- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); -- bus->rqueue_size--; -+ rqueue_drop_one(bus, i); - log_debug_bus_message(incoming); - - if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) { - - if (incoming->n_fds <= 0 || bus->accept_fd) { - if (reply) -- *reply = incoming; -- else -- sd_bus_message_unref(incoming); -+ *reply = TAKE_PTR(incoming); - - return 1; - } - -- r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); -- sd_bus_message_unref(incoming); -- return r; -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); - -- } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) { -- r = sd_bus_error_copy(error, &incoming->error); -- sd_bus_message_unref(incoming); -- return r; -- } else { -+ } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) -+ return sd_bus_error_copy(error, &incoming->error); -+ else { - r = -EIO; - goto fail; - } -@@ -2164,15 +2164,11 @@ _public_ int sd_bus_call( - incoming->sender && - streq(bus->unique_name, incoming->sender)) { - -- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); -- bus->rqueue_size--; -+ rqueue_drop_one(bus, i); - -- /* Our own message? Somebody is trying -- * to send its own client a message, -- * let's not dead-lock, let's fail -- * immediately. */ -+ /* Our own message? Somebody is trying to send its own client a message, -+ * let's not dead-lock, let's fail immediately. */ - -- sd_bus_message_unref(incoming); - r = -ELOOP; - goto fail; - } diff --git a/SOURCES/0239-test-bump-the-second-partition-s-size-to-50M.patch b/SOURCES/0239-test-bump-the-second-partition-s-size-to-50M.patch new file mode 100644 index 0000000..ff68908 --- /dev/null +++ b/SOURCES/0239-test-bump-the-second-partition-s-size-to-50M.patch @@ -0,0 +1,30 @@ +From 27d1acaa1d4c9299db461f0f1922c573be6a52c0 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 21 Oct 2019 18:39:39 +0200 +Subject: [PATCH] test: bump the second partition's size to 50M + +The former size (10M) caused systemd-journald to crash with SIGABRT when +used on a LUKS2 partition, as the LUKS2 metadata consume a significant +part of the 10M partition, thus leaving no space for the journal file +itself (relevant for TEST-02-CRYPTSETUP). This change has been present +in upstream for a while anyway. + +Related: #1761519 +rhel-only +--- + test/test-functions | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/test-functions b/test/test-functions +index af9d16140f..fe25a501da 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -433,7 +433,7 @@ create_empty_image() { + [ -b "$LOOPDEV" ] || return 1 + echo "LOOPDEV=$LOOPDEV" >> $STATEFILE + sfdisk "$LOOPDEV" < -Date: Tue, 28 May 2019 12:40:17 +0900 -Subject: [PATCH] journal: do not trigger assertion when journal_file_close() - get NULL - -We generally expect destructors to not complain if a NULL argument is passed. - -Closes #12400. - -(cherry picked from commit c377a6f3ad3d9bed4ce7e873e8e9ec6b1650c57d) -(cherry picked from commit dc4c3a5aa35a5e88adcf210471d9460262c8c0d9) -Resolves: #1807350 ---- - src/journal/journal-file.c | 3 ++- - src/journal/journald-server.c | 7 ++----- - 2 files changed, 4 insertions(+), 6 deletions(-) - -diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c -index efc3ee052b..8249b11b23 100644 ---- a/src/journal/journal-file.c -+++ b/src/journal/journal-file.c -@@ -335,7 +335,8 @@ bool journal_file_is_offlining(JournalFile *f) { - } - - JournalFile* journal_file_close(JournalFile *f) { -- assert(f); -+ if (!f) -+ return NULL; - - #if HAVE_GCRYPT - /* Write the final tag */ -diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c -index f2d2856e03..31a7b5ff03 100644 ---- a/src/journal/journald-server.c -+++ b/src/journal/journald-server.c -@@ -1906,11 +1906,8 @@ void server_done(Server *s) { - - client_context_flush_all(s); - -- if (s->system_journal) -- (void) journal_file_close(s->system_journal); -- -- if (s->runtime_journal) -- (void) journal_file_close(s->runtime_journal); -+ (void) journal_file_close(s->system_journal); -+ (void) journal_file_close(s->runtime_journal); - - ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close); - diff --git a/SOURCES/0240-shared-sleep-config-exclude-zram-devices-from-hibern.patch b/SOURCES/0240-shared-sleep-config-exclude-zram-devices-from-hibern.patch new file mode 100644 index 0000000..667c909 --- /dev/null +++ b/SOURCES/0240-shared-sleep-config-exclude-zram-devices-from-hibern.patch @@ -0,0 +1,51 @@ +From 069cf14150b55e6580cf1d482709a0e48c36ee84 Mon Sep 17 00:00:00 2001 +From: Andrew Jorgensen +Date: Wed, 25 Jul 2018 08:06:57 -0700 +Subject: [PATCH] shared/sleep-config: exclude zram devices from hibernation + candidates + +On a host with sufficiently large zram but with no actual swap, logind will +respond to CanHibernate() with yes. With this patch, it will correctly respond +no, unless there are other swap devices to consider. + +(cherry picked from commit 411ae92b407bd7b4549b205ad754bcd0e3dfd81f) + +Resolves: #1763617 +--- + src/shared/sleep-config.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c +index 9e4ce183d3..a1523e3f21 100644 +--- a/src/shared/sleep-config.c ++++ b/src/shared/sleep-config.c +@@ -21,6 +21,7 @@ + #include "log.h" + #include "macro.h" + #include "parse-util.h" ++#include "path-util.h" + #include "sleep-config.h" + #include "string-util.h" + #include "strv.h" +@@ -201,9 +202,18 @@ int find_hibernate_location(char **device, char **type, size_t *size, size_t *us + continue; + } + +- if (streq(type_field, "partition") && endswith(dev_field, "\\040(deleted)")) { +- log_warning("Ignoring deleted swapfile '%s'.", dev_field); +- continue; ++ if (streq(type_field, "partition")) { ++ if (endswith(dev_field, "\\040(deleted)")) { ++ log_warning("Ignoring deleted swapfile '%s'.", dev_field); ++ continue; ++ } ++ ++ const char *fn; ++ fn = path_startswith(dev_field, "/dev/"); ++ if (fn && startswith(fn, "zram")) { ++ log_debug("Ignoring compressed ram swap device '%s'.", dev_field); ++ continue; ++ } + } + if (device) + *device = TAKE_PTR(dev_field); diff --git a/SOURCES/0241-journal-use-cleanup-attribute-at-one-more-place.patch b/SOURCES/0241-journal-use-cleanup-attribute-at-one-more-place.patch deleted file mode 100644 index c5ba94c..0000000 --- a/SOURCES/0241-journal-use-cleanup-attribute-at-one-more-place.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 8a9a0b62a58e1481b6a0f2e54b323b4eefadc4fd Mon Sep 17 00:00:00 2001 -From: Yu Watanabe -Date: Tue, 28 May 2019 18:07:01 +0900 -Subject: [PATCH] journal: use cleanup attribute at one more place - -(cherry picked from commit 627df1dc42b68a74b0882b06366d1185b1a34332) - -Conflicts: - src/journal/journald-server.c - -(cherry picked from commit ceacf935ac9f59bc08b5901f70f227958a2bcf52) -Related: #1807350 ---- - src/journal/journal-file.h | 1 + - src/journal/journald-server.c | 9 ++++----- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h -index cd8a48a364..6a44fd39d2 100644 ---- a/src/journal/journal-file.h -+++ b/src/journal/journal-file.h -@@ -144,6 +144,7 @@ int journal_file_open( - int journal_file_set_offline(JournalFile *f, bool wait); - bool journal_file_is_offlining(JournalFile *f); - JournalFile* journal_file_close(JournalFile *j); -+DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close); - - int journal_file_open_reliably( - const char *fname, -diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c -index 31a7b5ff03..90c146dc67 100644 ---- a/src/journal/journald-server.c -+++ b/src/journal/journald-server.c -@@ -253,8 +253,9 @@ static int open_journal( - bool seal, - JournalMetrics *metrics, - JournalFile **ret) { -+ -+ _cleanup_(journal_file_closep) JournalFile *f = NULL; - int r; -- JournalFile *f; - - assert(s); - assert(fname); -@@ -271,12 +272,10 @@ static int open_journal( - return r; - - r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC); -- if (r < 0) { -- (void) journal_file_close(f); -+ if (r < 0) - return r; -- } - -- *ret = f; -+ *ret = TAKE_PTR(f); - return r; - } - diff --git a/SOURCES/0241-selinux-don-t-log-SELINUX_INFO-and-SELINUX_WARNING-m.patch b/SOURCES/0241-selinux-don-t-log-SELINUX_INFO-and-SELINUX_WARNING-m.patch new file mode 100644 index 0000000..5845313 --- /dev/null +++ b/SOURCES/0241-selinux-don-t-log-SELINUX_INFO-and-SELINUX_WARNING-m.patch @@ -0,0 +1,45 @@ +From cc3c020a5f4fc577dbd2da769c22b77e37ae4e30 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Tue, 26 Feb 2019 17:33:27 +0100 +Subject: [PATCH] selinux: don't log SELINUX_INFO and SELINUX_WARNING messages + to audit + +Previously we logged even info message from libselinux as USER_AVC's to +audit. For example, setting SELinux to permissive mode generated +following audit message, + +time->Tue Feb 26 11:29:29 2019 +type=USER_AVC msg=audit(1551198569.423:334): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='avc: received setenforce notice (enforcing=0) exe="/usr/lib/systemd/systemd" sauid=0 hostname=? addr=? terminal=?' + +This is unnecessary and wrong at the same time. First, kernel already +records audit event that SELinux was switched to permissive mode, also +the type of the message really shouldn't be USER_AVC. + +Let's ignore SELINUX_WARNING and SELINUX_INFO and forward to audit only +USER_AVC's and errors as these two libselinux message types have clear +mapping to audit message types. + +(cherry picked from commit 6227fc14c48c4c17daed4b91f61cdd4aa375790a) + +Resolves: #1763612 +--- + src/core/selinux-access.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c +index 39e994afd7..ada4f8705c 100644 +--- a/src/core/selinux-access.c ++++ b/src/core/selinux-access.c +@@ -112,7 +112,11 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) { + va_end(ap); + + if (r >= 0) { +- audit_log_user_avc_message(fd, AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0); ++ if (type == SELINUX_AVC) ++ audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0); ++ else if (type == SELINUX_ERROR) ++ audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, 0); ++ + return 0; + } + } diff --git a/SOURCES/0242-sd-device-introduce-log_device_-macros.patch b/SOURCES/0242-sd-device-introduce-log_device_-macros.patch new file mode 100644 index 0000000..6b13e77 --- /dev/null +++ b/SOURCES/0242-sd-device-introduce-log_device_-macros.patch @@ -0,0 +1,47 @@ +From 0160499e86642f159a972be0196bf7c8a1d19ea8 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 22 Oct 2018 12:04:13 +0900 +Subject: [PATCH] sd-device: introduce log_device_*() macros + +(cherry picked from commit b0cba0ca526ed2d86e283a0fcfebdf0a4d4bea9b) + +Related: #1753369 +--- + src/libsystemd/sd-device/device-util.h | 27 ++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/src/libsystemd/sd-device/device-util.h b/src/libsystemd/sd-device/device-util.h +index 6dcd2645e6..448dfc63d7 100644 +--- a/src/libsystemd/sd-device/device-util.h ++++ b/src/libsystemd/sd-device/device-util.h +@@ -33,3 +33,30 @@ + for (device = sd_device_enumerator_get_subsystem_first(enumerator); \ + device; \ + device = sd_device_enumerator_get_subsystem_next(enumerator)) ++ ++#define log_device_full(device, level, error, ...) \ ++ ({ \ ++ const char *_sysname = NULL, *_subsystem = NULL; \ ++ sd_device *_d = (device); \ ++ int _level = (level), _error = (error); \ ++ \ ++ if (_d && _unlikely_(log_get_max_level() >= _level)) { \ ++ (void) sd_device_get_sysname(_d, &_sysname); \ ++ (void) sd_device_get_subsystem(_d, &_subsystem); \ ++ } \ ++ log_object_internal(_level, _error, __FILE__, __LINE__, __func__, \ ++ _sysname ? "DEVICE=" : NULL, _sysname, \ ++ _subsystem ? "SUBSYSTEM=" : NULL, _subsystem, ##__VA_ARGS__); \ ++ }) ++ ++#define log_device_debug(link, ...) log_device_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) ++#define log_device_info(link, ...) log_device_full(link, LOG_INFO, 0, ##__VA_ARGS__) ++#define log_device_notice(link, ...) log_device_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) ++#define log_device_warning(link, ...) log_device_full(link, LOG_WARNING, 0, ##__VA_ARGS__) ++#define log_device_error(link, ...) log_device_full(link, LOG_ERR, 0, ##__VA_ARGS__) ++ ++#define log_device_debug_errno(link, error, ...) log_device_full(link, LOG_DEBUG, error, ##__VA_ARGS__) ++#define log_device_info_errno(link, error, ...) log_device_full(link, LOG_INFO, error, ##__VA_ARGS__) ++#define log_device_notice_errno(link, error, ...) log_device_full(link, LOG_NOTICE, error, ##__VA_ARGS__) ++#define log_device_warning_errno(link, error, ...) log_device_full(link, LOG_WARNING, error, ##__VA_ARGS__) ++#define log_device_error_errno(link, error, ...) log_device_full(link, LOG_ERR, error, ##__VA_ARGS__) diff --git a/SOURCES/0243-udev-Add-id-program-and-rule-for-FIDO-security-token.patch b/SOURCES/0243-udev-Add-id-program-and-rule-for-FIDO-security-token.patch new file mode 100644 index 0000000..0d32c08 --- /dev/null +++ b/SOURCES/0243-udev-Add-id-program-and-rule-for-FIDO-security-token.patch @@ -0,0 +1,505 @@ +From 080d3b14470f6ac59f4cfb97a4200ed18df5c260 Mon Sep 17 00:00:00 2001 +From: Fabian Henneke +Date: Wed, 21 Aug 2019 11:17:59 +0200 +Subject: [PATCH] udev: Add id program and rule for FIDO security tokens + +Add a fido_id program meant to be run for devices in the hidraw +subsystem via an IMPORT directive. The program parses the HID report +descriptor and assigns the ID_SECURITY_TOKEN environment variable if a +declared usage matches the FIDO_CTAPHID_USAGE declared in the FIDO CTAP +specification. This replaces the previous approach of whitelisting all +known security token models manually. + +This commit is accompanied by a test suite and a fuzzer target for the +descriptor parsing routine. + +Fixes: #11996. +(cherry picked from commit d45ee2f31a8358db0accde2e7c81777cedadc3c2) + +Resolves: #1753369 +--- + rules/60-fido-id.rules | 7 ++ + rules/meson.build | 1 + + src/fuzz/fuzz-fido-id-desc.c | 23 +++++++ + src/fuzz/fuzz-fido-id-desc.dict | 6 ++ + src/fuzz/meson.build | 4 ++ + src/test/meson.build | 4 ++ + src/test/test-fido-id-desc.c | 85 +++++++++++++++++++++++ + src/udev/fido_id/fido_id.c | 103 ++++++++++++++++++++++++++++ + src/udev/fido_id/fido_id_desc.c | 92 +++++++++++++++++++++++++ + src/udev/fido_id/fido_id_desc.h | 8 +++ + src/udev/meson.build | 3 + + test/fuzz/fuzz-fido-id-desc/crash0 | 1 + + test/fuzz/fuzz-fido-id-desc/crash1 | 1 + + test/fuzz/fuzz-fido-id-desc/report0 | Bin 0 -> 71 bytes + test/fuzz/fuzz-fido-id-desc/report1 | Bin 0 -> 34 bytes + 15 files changed, 338 insertions(+) + create mode 100644 rules/60-fido-id.rules + create mode 100644 src/fuzz/fuzz-fido-id-desc.c + create mode 100644 src/fuzz/fuzz-fido-id-desc.dict + create mode 100644 src/test/test-fido-id-desc.c + create mode 100644 src/udev/fido_id/fido_id.c + create mode 100644 src/udev/fido_id/fido_id_desc.c + create mode 100644 src/udev/fido_id/fido_id_desc.h + create mode 100644 test/fuzz/fuzz-fido-id-desc/crash0 + create mode 100644 test/fuzz/fuzz-fido-id-desc/crash1 + create mode 100644 test/fuzz/fuzz-fido-id-desc/report0 + create mode 100644 test/fuzz/fuzz-fido-id-desc/report1 + +diff --git a/rules/60-fido-id.rules b/rules/60-fido-id.rules +new file mode 100644 +index 0000000000..fcf5079704 +--- /dev/null ++++ b/rules/60-fido-id.rules +@@ -0,0 +1,7 @@ ++# do not edit this file, it will be overwritten on update ++ ++ACTION=="remove", GOTO="fido_id_end" ++ ++SUBSYSTEM=="hidraw", IMPORT{program}="fido_id" ++ ++LABEL="fido_id_end" +diff --git a/rules/meson.build b/rules/meson.build +index b6aae596b6..6363f8bf2e 100644 +--- a/rules/meson.build ++++ b/rules/meson.build +@@ -7,6 +7,7 @@ rules = files(''' + 60-cdrom_id.rules + 60-drm.rules + 60-evdev.rules ++ 60-fido-id.rules + 60-input-id.rules + 60-persistent-alsa.rules + 60-persistent-input.rules +diff --git a/src/fuzz/fuzz-fido-id-desc.c b/src/fuzz/fuzz-fido-id-desc.c +new file mode 100644 +index 0000000000..cf98dee044 +--- /dev/null ++++ b/src/fuzz/fuzz-fido-id-desc.c +@@ -0,0 +1,23 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "fido_id/fido_id_desc.h" ++#include "fuzz.h" ++#include "log.h" ++ ++int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ++ /* We don't want to fill the logs with messages about parse errors. ++ * Disable most logging if not running standalone */ ++ if (!getenv("SYSTEMD_LOG_LEVEL")) ++ log_set_max_level(LOG_CRIT); ++ ++ if (size > HID_MAX_DESCRIPTOR_SIZE) ++ return 0; ++ (void) is_fido_security_token_desc(data, size); ++ ++ return 0; ++} +diff --git a/src/fuzz/fuzz-fido-id-desc.dict b/src/fuzz/fuzz-fido-id-desc.dict +new file mode 100644 +index 0000000000..d2d2679e18 +--- /dev/null ++++ b/src/fuzz/fuzz-fido-id-desc.dict +@@ -0,0 +1,6 @@ ++"\xfe" ++"\x00" ++"\x01" ++"\xf1" ++"\xd0" ++"\xf1\xd0\x00\x01" +diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build +index 1dbe28e57e..483a952421 100644 +--- a/src/fuzz/meson.build ++++ b/src/fuzz/meson.build +@@ -47,4 +47,8 @@ fuzzers += [ + [libsystemd_journal_remote, + libshared], + []], ++ [['src/fuzz/fuzz-fido-id-desc.c', ++ 'src/udev/fido_id/fido_id_desc.c'], ++ [], ++ []] + ] +diff --git a/src/test/meson.build b/src/test/meson.build +index 0998f59897..4259421f98 100644 +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -663,6 +663,10 @@ tests += [ + [['src/test/test-bus-util.c'], + [], + []], ++ [['src/test/test-fido-id-desc.c', ++ 'src/udev/fido_id/fido_id_desc.c'], ++ [], ++ []], + ] + + ############################################################ +diff --git a/src/test/test-fido-id-desc.c b/src/test/test-fido-id-desc.c +new file mode 100644 +index 0000000000..cf55dd3266 +--- /dev/null ++++ b/src/test/test-fido-id-desc.c +@@ -0,0 +1,85 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include ++#include ++ ++#include "fido_id/fido_id_desc.h" ++#include "macro.h" ++ ++static void test_is_fido_security_token_desc__fido(void) { ++ static const uint8_t FIDO_HID_DESC_1[] = { ++ 0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, ++ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, ++ 0x40, 0x91, 0x02, 0xc0, ++ }; ++ assert_se(is_fido_security_token_desc(FIDO_HID_DESC_1, sizeof(FIDO_HID_DESC_1)) > 0); ++ ++ static const uint8_t FIDO_HID_DESC_2[] = { ++ 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, ++ 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05, ++ 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91, ++ 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65, ++ 0x81, 0x00, 0x09, 0x03, 0x75, 0x08, 0x95, 0x08, 0xb1, 0x02, 0xc0, ++ 0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, ++ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, ++ 0x40, 0x91, 0x02, 0xc0, ++ }; ++ assert_se(is_fido_security_token_desc(FIDO_HID_DESC_2, sizeof(FIDO_HID_DESC_2)) > 0); ++} ++ ++static void test_is_fido_security_token_desc__non_fido(void) { ++ /* Wrong usage page */ ++ static const uint8_t NON_FIDO_HID_DESC_1[] = { ++ 0x06, 0xd0, 0xf0, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, ++ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, ++ 0x40, 0x91, 0x02, 0xc0, ++ }; ++ assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_1, sizeof(NON_FIDO_HID_DESC_1)) == 0); ++ ++ /* Wrong usage */ ++ static const uint8_t NON_FIDO_HID_DESC_2[] = { ++ 0x06, 0xd0, 0xf1, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, ++ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, ++ 0x40, 0x91, 0x02, 0xc0, ++ }; ++ assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_2, sizeof(NON_FIDO_HID_DESC_2)) == 0); ++ ++ static const uint8_t NON_FIDO_HID_DESC_3[] = { ++ 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, ++ 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05, ++ 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91, ++ 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65, ++ 0x81, 0x00, 0x09, 0x03, 0x75, 0x08, 0x95, 0x08, 0xb1, 0x02, 0xc0, ++ }; ++ assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_3, sizeof(NON_FIDO_HID_DESC_3)) == 0); ++} ++ ++static void test_is_fido_security_token_desc__invalid(void) { ++ /* Size coded on 1 byte, but no byte given */ ++ static const uint8_t INVALID_HID_DESC_1[] = { 0x01 }; ++ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_1, sizeof(INVALID_HID_DESC_1)) < 0); ++ ++ /* Size coded on 2 bytes, but only 1 byte given */ ++ static const uint8_t INVALID_HID_DESC_2[] = { 0x02, 0x01 }; ++ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_2, sizeof(INVALID_HID_DESC_2)) < 0); ++ ++ /* Size coded on 4 bytes, but only 3 bytes given */ ++ static const uint8_t INVALID_HID_DESC_3[] = { 0x03, 0x01, 0x02, 0x03 }; ++ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_3, sizeof(INVALID_HID_DESC_3)) < 0); ++ ++ /* Long item without a size byte */ ++ static const uint8_t INVALID_HID_DESC_4[] = { 0xfe }; ++ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_4, sizeof(INVALID_HID_DESC_4)) < 0); ++ ++ /* Usage pages are coded on at most 2 bytes */ ++ static const uint8_t INVALID_HID_DESC_5[] = { 0x07, 0x01, 0x02, 0x03, 0x04 }; ++ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_5, sizeof(INVALID_HID_DESC_5)) < 0); ++} ++ ++int main(int argc, char *argv[]) { ++ test_is_fido_security_token_desc__fido(); ++ test_is_fido_security_token_desc__non_fido(); ++ test_is_fido_security_token_desc__invalid(); ++ ++ return EXIT_SUCCESS; ++} +diff --git a/src/udev/fido_id/fido_id.c b/src/udev/fido_id/fido_id.c +new file mode 100644 +index 0000000000..7e1cc804f2 +--- /dev/null ++++ b/src/udev/fido_id/fido_id.c +@@ -0,0 +1,103 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++/* ++ * Identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on the usage declared in their report ++ * descriptor and outputs suitable environment variables. ++ * ++ * Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c' ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sd-device.h" ++ ++#include "device-internal.h" ++#include "device-private.h" ++#include "device-util.h" ++#include "fd-util.h" ++#include "fido_id_desc.h" ++#include "log.h" ++#include "macro.h" ++#include "path-util.h" ++#include "string-util.h" ++#include "udev-util.h" ++ ++static int run(int argc, char **argv) { ++ _cleanup_(sd_device_unrefp) struct sd_device *device = NULL; ++ _cleanup_free_ char *desc_path = NULL; ++ _cleanup_close_ int fd = -1; ++ ++ struct sd_device *hid_device; ++ const char *sys_path; ++ uint8_t desc[HID_MAX_DESCRIPTOR_SIZE]; ++ ssize_t desc_len; ++ ++ int r; ++ ++ log_set_target(LOG_TARGET_AUTO); ++ udev_parse_config(); ++ log_parse_environment(); ++ log_open(); ++ ++ if (argc > 2) ++ return log_error_errno(EINVAL, "Usage: %s [SYSFS_PATH]", program_invocation_short_name); ++ ++ if (argc == 1) { ++ r = device_new_from_strv(&device, environ); ++ if (r < 0) ++ return log_error_errno(r, "Failed to get current device from environment: %m"); ++ } else { ++ r = sd_device_new_from_syspath(&device, argv[1]); ++ if (r < 0) ++ return log_error_errno(r, "Failed to get device from syspath: %m"); ++ } ++ ++ r = sd_device_get_parent(device, &hid_device); ++ if (r < 0) ++ return log_device_error_errno(device, r, "Failed to get parent HID device: %m"); ++ ++ r = sd_device_get_syspath(hid_device, &sys_path); ++ if (r < 0) ++ return log_device_error_errno(hid_device, r, "Failed to get syspath for HID device: %m"); ++ ++ desc_path = path_join(NULL, sys_path, "report_descriptor"); ++ if (!desc_path) ++ return log_oom(); ++ ++ fd = open(desc_path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); ++ if (fd < 0) ++ return log_device_error_errno(hid_device, errno, ++ "Failed to open report descriptor at '%s': %m", desc_path); ++ ++ desc_len = read(fd, desc, sizeof(desc)); ++ if (desc_len < 0) ++ return log_device_error_errno(hid_device, errno, ++ "Failed to read report descriptor at '%s': %m", desc_path); ++ if (desc_len == 0) ++ return log_device_debug_errno(hid_device, EINVAL, ++ "Empty report descriptor at '%s'.", desc_path); ++ ++ r = is_fido_security_token_desc(desc, desc_len); ++ if (r < 0) ++ return log_device_debug_errno(hid_device, r, ++ "Failed to parse report descriptor at '%s'.", desc_path); ++ if (r > 0) { ++ printf("ID_FIDO_TOKEN=1\n"); ++ printf("ID_SECURITY_TOKEN=1\n"); ++ } ++ ++ return 0; ++} ++ ++int main(int argc, char *argv[]) { ++ int r; ++ ++ r = run(argc, argv); ++ ++ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; ++} +diff --git a/src/udev/fido_id/fido_id_desc.c b/src/udev/fido_id/fido_id_desc.c +new file mode 100644 +index 0000000000..bbfcf93709 +--- /dev/null ++++ b/src/udev/fido_id/fido_id_desc.c +@@ -0,0 +1,92 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++/* Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c' */ ++ ++#include ++#include ++#include ++#include ++ ++#include "fido_id_desc.h" ++ ++#define HID_RPTDESC_FIRST_BYTE_LONG_ITEM 0xfeu ++#define HID_RPTDESC_TYPE_GLOBAL 0x1u ++#define HID_RPTDESC_TYPE_LOCAL 0x2u ++#define HID_RPTDESC_TAG_USAGE_PAGE 0x0u ++#define HID_RPTDESC_TAG_USAGE 0x0u ++ ++/* ++ * HID usage for FIDO CTAP1 ("U2F") and CTAP2 security tokens. ++ * https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-u2f_hid.h-v1.0-ps-20141009.txt ++ * https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#usb-discovery ++ * https://www.usb.org/sites/default/files/hutrr48.pdf ++ */ ++#define FIDO_FULL_USAGE_CTAPHID 0xf1d00001u ++ ++/* ++ * Parses a HID report descriptor and identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on their ++ * declared usage. ++ * A positive return value indicates that the report descriptor belongs to a FIDO security token. ++ * https://www.usb.org/sites/default/files/documents/hid1_11.pdf (Section 6.2.2) ++ */ ++int is_fido_security_token_desc(const uint8_t *desc, size_t desc_len) { ++ uint32_t usage = 0; ++ ++ for (size_t pos = 0; pos < desc_len; ) { ++ uint8_t tag, type, size_code; ++ size_t size; ++ uint32_t value; ++ ++ /* Report descriptors consists of short items (1-5 bytes) and long items (3-258 bytes). */ ++ if (desc[pos] == HID_RPTDESC_FIRST_BYTE_LONG_ITEM) { ++ /* No long items are defined in the spec; skip them. ++ * The length of the data in a long item is contained in the byte after the long ++ * item tag. The header consists of three bytes: special long item tag, length, ++ * actual tag. */ ++ if (pos + 1 >= desc_len) ++ return -EINVAL; ++ pos += desc[pos + 1] + 3; ++ continue; ++ } ++ ++ /* The first byte of a short item encodes tag, type and size. */ ++ tag = desc[pos] >> 4; /* Bits 7 to 4 */ ++ type = (desc[pos] >> 2) & 0x3; /* Bits 3 and 2 */ ++ size_code = desc[pos] & 0x3; /* Bits 1 and 0 */ ++ /* Size is coded as follows: ++ * 0 -> 0 bytes, 1 -> 1 byte, 2 -> 2 bytes, 3 -> 4 bytes ++ */ ++ size = size_code < 3 ? size_code : 4; ++ /* Consume header byte. */ ++ pos++; ++ ++ /* Extract the item value coded on size bytes. */ ++ if (pos + size > desc_len) ++ return -EINVAL; ++ value = 0; ++ for (size_t i = 0; i < size; i++) ++ value |= (uint32_t) desc[pos + i] << (8 * i); ++ /* Consume value bytes. */ ++ pos += size; ++ ++ if (type == HID_RPTDESC_TYPE_GLOBAL && tag == HID_RPTDESC_TAG_USAGE_PAGE) { ++ /* A usage page is a 16 bit value coded on at most 16 bits. */ ++ if (size > 2) ++ return -EINVAL; ++ /* A usage page sets the upper 16 bits of a following usage. */ ++ usage = (value & 0x0000ffffu) << 16; ++ } ++ ++ if (type == HID_RPTDESC_TYPE_LOCAL && tag == HID_RPTDESC_TAG_USAGE) { ++ /* A usage is a 32 bit value, but is prepended with the current usage page if ++ * coded on less than 4 bytes (that is, at most 2 bytes). */ ++ if (size == 4) ++ usage = value; ++ else ++ usage = (usage & 0xffff0000u) | (value & 0x0000ffffu); ++ if (usage == FIDO_FULL_USAGE_CTAPHID) ++ return 1; ++ } ++ } ++ ++ return 0; ++} +diff --git a/src/udev/fido_id/fido_id_desc.h b/src/udev/fido_id/fido_id_desc.h +new file mode 100644 +index 0000000000..c813a3a454 +--- /dev/null ++++ b/src/udev/fido_id/fido_id_desc.h +@@ -0,0 +1,8 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#pragma once ++ ++#include ++#include ++ ++int is_fido_security_token_desc(const uint8_t *desc, size_t desc_len); +diff --git a/src/udev/meson.build b/src/udev/meson.build +index 3bcd2bd3d7..5931a6da7d 100644 +--- a/src/udev/meson.build ++++ b/src/udev/meson.build +@@ -160,6 +160,9 @@ libudev_core = static_library( + foreach prog : [['ata_id/ata_id.c'], + ['cdrom_id/cdrom_id.c'], + ['collect/collect.c'], ++ ['fido_id/fido_id.c', ++ 'fido_id/fido_id_desc.c', ++ 'fido_id/fido_id_desc.h'], + ['scsi_id/scsi_id.c', + 'scsi_id/scsi_id.h', + 'scsi_id/scsi_serial.c', +diff --git a/test/fuzz/fuzz-fido-id-desc/crash0 b/test/fuzz/fuzz-fido-id-desc/crash0 +new file mode 100644 +index 0000000000..e066656502 +--- /dev/null ++++ b/test/fuzz/fuzz-fido-id-desc/crash0 +@@ -0,0 +1 @@ ++� +\ No newline at end of file +diff --git a/test/fuzz/fuzz-fido-id-desc/crash1 b/test/fuzz/fuzz-fido-id-desc/crash1 +new file mode 100644 +index 0000000000..aef3e18335 +--- /dev/null ++++ b/test/fuzz/fuzz-fido-id-desc/crash1 +@@ -0,0 +1 @@ ++������ +\ No newline at end of file +diff --git a/test/fuzz/fuzz-fido-id-desc/report0 b/test/fuzz/fuzz-fido-id-desc/report0 +new file mode 100644 +index 0000000000000000000000000000000000000000..48757cba682ffddd5a1ddd8988bb8bcdc7db0a7a +GIT binary patch +literal 71 +zcmZQ& +Date: Tue, 27 Aug 2019 19:00:34 +0200 +Subject: [PATCH] shared/but-util: drop trusted annotation from + bus_open_system_watch_bind_with_description() + +https://bugzilla.redhat.com/show_bug.cgi?id=1746057 + +This only affects systemd-resolved. bus_open_system_watch_bind_with_description() +is also used in timesyncd, but it has no methods, only read-only properties, and +in networkd, but it annotates all methods with SD_BUS_VTABLE_UNPRIVILEGED and does +polkit checks. + +Resolves: #1746857 +--- + src/shared/bus-util.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index a4f2deba31..302dbb4c2e 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -1699,10 +1699,6 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri + if (r < 0) + return r; + +- r = sd_bus_set_trusted(bus, true); +- if (r < 0) +- return r; +- + r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS); + if (r < 0) + return r; diff --git a/SOURCES/0245-sd-bus-adjust-indentation-of-comments.patch b/SOURCES/0245-sd-bus-adjust-indentation-of-comments.patch new file mode 100644 index 0000000..bdb144e --- /dev/null +++ b/SOURCES/0245-sd-bus-adjust-indentation-of-comments.patch @@ -0,0 +1,50 @@ +From 7e0f9a0cd4053fcc713a99ada3d0d50793b83564 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 27 Aug 2019 19:00:50 +0200 +Subject: [PATCH] sd-bus: adjust indentation of comments + +Related: #1746857 +--- + src/libsystemd/sd-bus/sd-bus.c | 3 +-- + src/shared/bus-util.c | 7 ++++--- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 3583e24e64..1c9e967ae0 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -1341,8 +1341,7 @@ _public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *descrip + b->bus_client = true; + b->is_user = true; + +- /* We don't do any per-method access control on the user +- * bus. */ ++ /* We don't do any per-method access control on the user bus. */ + b->trusted = true; + b->is_local = true; + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 302dbb4c2e..2d908eb45c 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -1675,7 +1675,8 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri + + assert(ret); + +- /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */ ++ /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal ++ * turned on. */ + + r = sd_bus_new(&bus); + if (r < 0) +@@ -1890,8 +1891,8 @@ int bus_reply_pair_array(sd_bus_message *m, char **l) { + + assert(m); + +- /* Reply to the specified message with a message containing a dictionary put together from the specified +- * strv */ ++ /* Reply to the specified message with a message containing a dictionary put together from the ++ * specified strv */ + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) diff --git a/SOURCES/0246-resolved-do-not-run-loop-twice.patch b/SOURCES/0246-resolved-do-not-run-loop-twice.patch new file mode 100644 index 0000000..70fdf78 --- /dev/null +++ b/SOURCES/0246-resolved-do-not-run-loop-twice.patch @@ -0,0 +1,46 @@ +From d95afbca80cf52f0bc84b2e1b4af6aadda007138 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 27 Aug 2019 19:02:53 +0200 +Subject: [PATCH] resolved: do not run loop twice + +This doesn't matter much, but let's just do the loop once and allocate +the populate the result set on the fly. If we find an error, it'll get +cleaned up automatically. + +Related: #1746857 +--- + src/resolve/resolved-link-bus.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c +index b1581740d8..46d2b11636 100644 +--- a/src/resolve/resolved-link-bus.c ++++ b/src/resolve/resolved-link-bus.c +@@ -492,6 +492,10 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v + if (r < 0) + return r; + ++ ns = set_new(&dns_name_hash_ops); ++ if (!ns) ++ return -ENOMEM; ++ + r = sd_bus_message_read_strv(message, &ntas); + if (r < 0) + return r; +@@ -501,14 +505,9 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v + if (r < 0) + return r; + if (r == 0) +- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i); +- } ++ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, ++ "Invalid negative trust anchor domain: %s", *i); + +- ns = set_new(&dns_name_hash_ops); +- if (!ns) +- return -ENOMEM; +- +- STRV_FOREACH(i, ntas) { + r = set_put_strdup(ns, *i); + if (r < 0) + return r; diff --git a/SOURCES/0247-resolved-allow-access-to-Set-Link-and-Revert-methods.patch b/SOURCES/0247-resolved-allow-access-to-Set-Link-and-Revert-methods.patch new file mode 100644 index 0000000..5e2b359 --- /dev/null +++ b/SOURCES/0247-resolved-allow-access-to-Set-Link-and-Revert-methods.patch @@ -0,0 +1,347 @@ +From ddd08e75b1e7fa1f6dfef3d30a0c1ef8c63e4d07 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 27 Aug 2019 19:25:05 +0200 +Subject: [PATCH] resolved: allow access to Set*Link and Revert methods through + polkit + +This matches what is done in networkd very closely. In fact even the +policy descriptions are all identical (with s/network/resolve), except +for the last one: +resolved has org.freedesktop.resolve1.revert while +networkd has org.freedesktop.network1.revert-ntp and +org.freedesktop.network1.revert-dns so the description is a bit different. + +Conflicts: + src/resolve/resolved-bus.c + src/resolve/resolved-link-bus.c + +Related: #1746857 +--- + src/resolve/org.freedesktop.resolve1.policy | 99 +++++++++++++++++++++ + src/resolve/resolved-bus.c | 22 ++--- + src/resolve/resolved-link-bus.c | 97 +++++++++++++++++--- + 3 files changed, 197 insertions(+), 21 deletions(-) + +diff --git a/src/resolve/org.freedesktop.resolve1.policy b/src/resolve/org.freedesktop.resolve1.policy +index b65ba3e56a..592c4eb8b0 100644 +--- a/src/resolve/org.freedesktop.resolve1.policy ++++ b/src/resolve/org.freedesktop.resolve1.policy +@@ -40,4 +40,103 @@ + unix-user:systemd-resolve + + ++ ++ Set DNS servers ++ Authentication is required to set DNS servers. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Set domains ++ Authentication is required to set domains. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Set default route ++ Authentication is required to set default route. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Enable/disable LLMNR ++ Authentication is required to enable or disable LLMNR. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Enable/disable multicast DNS ++ Authentication is required to enable or disable multicast DNS. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Enable/disable DNS over TLS ++ Authentication is required to enable or disable DNS over TLS. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Enable/disable DNSSEC ++ Authentication is required to enable or disable DNSSEC. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Set DNSSEC Negative Trust Anchors ++ Authentication is required to set DNSSEC Negative Trust Anchros. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ ++ ++ Revert name resolution settings ++ Authentication is required to revert name resolution settings. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ unix-user:systemd-resolve ++ ++ + +diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c +index da0a909dd6..4d6cc4fd48 100644 +--- a/src/resolve/resolved-bus.c ++++ b/src/resolve/resolved-bus.c +@@ -1848,18 +1848,18 @@ static const sd_bus_vtable resolve_vtable[] = { + SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED), +- SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0), +- SD_BUS_METHOD("FlushCaches", NULL, NULL, bus_method_flush_caches, 0), +- SD_BUS_METHOD("ResetServerFeatures", NULL, NULL, bus_method_reset_server_features, 0), ++ SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("FlushCaches", NULL, NULL, bus_method_flush_caches, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("ResetServerFeatures", NULL, NULL, bus_method_reset_server_features, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED), +- SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0), +- SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, 0), +- SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0), +- SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0), +- SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, 0), +- SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0), +- SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, 0), +- SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, 0), ++ SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_METHOD("RegisterService", "sssqqqaa{say}", "o", bus_method_register_service, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnregisterService", "o", NULL, bus_method_unregister_service, SD_BUS_VTABLE_UNPRIVILEGED), +diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c +index 46d2b11636..bf3e42264e 100644 +--- a/src/resolve/resolved-link-bus.c ++++ b/src/resolve/resolved-link-bus.c +@@ -1,5 +1,9 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + ++#include ++#include ++#include ++ + #include "alloc-util.h" + #include "bus-common-errors.h" + #include "bus-util.h" +@@ -9,6 +13,7 @@ + #include "resolved-link-bus.h" + #include "resolved-resolv-conf.h" + #include "strv.h" ++#include "user-util.h" + + static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported); + static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string); +@@ -235,6 +240,15 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ + if (r < 0) + return r; + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.set-dns-servers", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + dns_server_mark_all(l->dns_servers); + + for (i = 0; i < n; i++) { +@@ -298,12 +312,21 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain"); + } + +- dns_search_domain_mark_all(l->search_domains); +- + r = sd_bus_message_rewind(message, false); + if (r < 0) + return r; + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.set-domains", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ ++ dns_search_domain_mark_all(l->search_domains); ++ + for (;;) { + DnsSearchDomain *d; + const char *name; +@@ -371,6 +394,15 @@ int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_er + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr); + } + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.set-llmnr", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + l->llmnr_support = mode; + link_allocate_scopes(l); + link_add_rrs(l, false); +@@ -405,6 +437,15 @@ int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_err + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns); + } + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.set-mdns", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + l->mdns_support = mode; + link_allocate_scopes(l); + link_add_rrs(l, false); +@@ -439,6 +480,15 @@ int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls); + } + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.set-dns-over-tls", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + link_set_dns_over_tls_mode(l, mode); + + (void) link_save_user(l); +@@ -471,6 +521,15 @@ int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_e + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec); + } + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.set-dnssec", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + link_set_dnssec_mode(l, mode); + + (void) link_save_user(l); +@@ -513,6 +572,15 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v + return r; + } + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.set-dnssec-negative-trust-anchors", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + set_free_free(l->dnssec_negative_trust_anchors); + l->dnssec_negative_trust_anchors = TAKE_PTR(ns); + +@@ -532,6 +600,15 @@ int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error + if (r < 0) + return r; + ++ r = bus_verify_polkit_async(message, CAP_NET_ADMIN, ++ "org.freedesktop.resolve1.revert", ++ NULL, true, UID_INVALID, ++ &l->manager->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + link_flush_settings(l); + link_allocate_scopes(l); + link_add_rrs(l, false); +@@ -556,14 +633,14 @@ const sd_bus_vtable link_vtable[] = { + SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0), + SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0), + +- SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0), +- SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, 0), +- SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0), +- SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0), +- SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, 0), +- SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0), +- SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, 0), +- SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, 0), ++ SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END + }; diff --git a/SOURCES/0248-resolved-query-polkit-only-after-parsing-the-data.patch b/SOURCES/0248-resolved-query-polkit-only-after-parsing-the-data.patch new file mode 100644 index 0000000..eac8530 --- /dev/null +++ b/SOURCES/0248-resolved-query-polkit-only-after-parsing-the-data.patch @@ -0,0 +1,48 @@ +From 7b00cae817e54ee3398ad3b42ec69a3b63676562 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 27 Aug 2019 19:28:19 +0200 +Subject: [PATCH] resolved: query polkit only after parsing the data + +That's what we do everywhere else because it leads to nicer user experience. + +Related: #1746857 +--- + src/resolve/resolved-bus.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c +index 4d6cc4fd48..3f6a6f9e12 100644 +--- a/src/resolve/resolved-bus.c ++++ b/src/resolve/resolved-bus.c +@@ -1632,15 +1632,6 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, + if (m->mdns_support != RESOLVE_SUPPORT_YES) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled"); + +- r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, +- "org.freedesktop.resolve1.register-service", +- NULL, false, UID_INVALID, +- &m->polkit_registry, error); +- if (r < 0) +- return r; +- if (r == 0) +- return 1; /* Polkit will call us back */ +- + service = new0(DnssdService, 1); + if (!service) + return log_oom(); +@@ -1765,6 +1756,15 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, + if (r < 0) + return r; + ++ r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, ++ "org.freedesktop.resolve1.register-service", ++ NULL, false, UID_INVALID, ++ &m->polkit_registry, error); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return 1; /* Polkit will call us back */ ++ + r = hashmap_ensure_allocated(&m->dnssd_services, &string_hash_ops); + if (r < 0) + return r; diff --git a/SOURCES/0249-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch b/SOURCES/0249-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch new file mode 100644 index 0000000..932a2fc --- /dev/null +++ b/SOURCES/0249-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch @@ -0,0 +1,48 @@ +From 4d2145e3edd6ba6ac2e52a232fa5059ecdacaead Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Mon, 24 Dec 2018 00:29:56 +0100 +Subject: [PATCH] journal: rely on _cleanup_free_ to free a temporary string + used in client_context_read_cgroup + +Closes https://github.com/systemd/systemd/issues/11253. + +(cherry picked from commit ef30f7cac18a810814ada7e6a68a31d48cc9fccd) + +Resolves: #1764560 +--- + src/journal/journald-context.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c +index c8e97e16de..3a768094d9 100644 +--- a/src/journal/journald-context.c ++++ b/src/journal/journald-context.c +@@ -282,7 +282,7 @@ static int client_context_read_label( + } + + static int client_context_read_cgroup(Server *s, ClientContext *c, const char *unit_id) { +- char *t = NULL; ++ _cleanup_free_ char *t = NULL; + int r; + + assert(c); +@@ -290,7 +290,6 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u + /* Try to acquire the current cgroup path */ + r = cg_pid_get_path_shifted(c->pid, s->cgroup_root, &t); + if (r < 0 || empty_or_root(t)) { +- + /* We use the unit ID passed in as fallback if we have nothing cached yet and cg_pid_get_path_shifted() + * failed or process is running in a root cgroup. Zombie processes are automatically migrated to root cgroup + * on cgroupsv1 and we want to be able to map log messages from them too. */ +@@ -304,10 +303,8 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u + } + + /* Let's shortcut this if the cgroup path didn't change */ +- if (streq_ptr(c->cgroup, t)) { +- free(t); ++ if (streq_ptr(c->cgroup, t)) + return 0; +- } + + free_and_replace(c->cgroup, t); + diff --git a/SOURCES/0250-basic-user-util-allow-dots-in-user-names.patch b/SOURCES/0250-basic-user-util-allow-dots-in-user-names.patch new file mode 100644 index 0000000..4b03b91 --- /dev/null +++ b/SOURCES/0250-basic-user-util-allow-dots-in-user-names.patch @@ -0,0 +1,90 @@ +From 76176de0889c3e8b9b3a176da24e4f8dbbd380a3 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Wed, 2 Oct 2019 11:59:41 +0200 +Subject: [PATCH] basic/user-util: allow dots in user names + +(based on commit 1a29610f5fa1bcb2eeb37d2c6b79d8d1a6dbb865) + +Resolves: #1717603 +--- + src/basic/user-util.c | 9 ++++++--- + src/test/test-user-util.c | 8 ++++---- + 2 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/src/basic/user-util.c b/src/basic/user-util.c +index c533f67025..d92969c966 100644 +--- a/src/basic/user-util.c ++++ b/src/basic/user-util.c +@@ -575,11 +575,14 @@ bool valid_user_group_name(const char *u) { + /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, + * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules: + * +- * - We don't allow any dots (this would break chown syntax which permits dots as user/group name separator) + * - We require that names fit into the appropriate utmp field + * - We don't allow empty user names + * + * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters. ++ * ++ * jsynacek: We now allow dots in user names. The checks are not exhaustive as user names like "..." are allowed ++ * and valid according to POSIX, but can't be created using useradd. However, ".user" can be created. Let's not ++ * complicate the code by adding additional checks for weird corner cases like these, as they don't really matter here. + */ + + if (isempty(u)) +@@ -587,14 +590,14 @@ bool valid_user_group_name(const char *u) { + + if (!(u[0] >= 'a' && u[0] <= 'z') && + !(u[0] >= 'A' && u[0] <= 'Z') && +- u[0] != '_') ++ u[0] != '_' && u[0] != '.') + return false; + + for (i = u+1; *i; i++) { + if (!(*i >= 'a' && *i <= 'z') && + !(*i >= 'A' && *i <= 'Z') && + !(*i >= '0' && *i <= '9') && +- !IN_SET(*i, '_', '-')) ++ !IN_SET(*i, '_', '-', '.')) + return false; + } + +diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c +index c1428fab02..9114d30b8c 100644 +--- a/src/test/test-user-util.c ++++ b/src/test/test-user-util.c +@@ -71,8 +71,6 @@ static void test_valid_user_group_name(void) { + assert_se(!valid_user_group_name("-1")); + assert_se(!valid_user_group_name("-kkk")); + assert_se(!valid_user_group_name("rööt")); +- assert_se(!valid_user_group_name(".")); +- assert_se(!valid_user_group_name("eff.eff")); + assert_se(!valid_user_group_name("foo\nbar")); + assert_se(!valid_user_group_name("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id("aaa:bbb")); +@@ -83,6 +81,8 @@ static void test_valid_user_group_name(void) { + assert_se(valid_user_group_name("_kkk")); + assert_se(valid_user_group_name("kkk-")); + assert_se(valid_user_group_name("kk-k")); ++ assert_se(valid_user_group_name(".moo")); ++ assert_se(valid_user_group_name("eff.eff")); + + assert_se(valid_user_group_name("some5")); + assert_se(!valid_user_group_name("5some")); +@@ -102,8 +102,6 @@ static void test_valid_user_group_name_or_id(void) { + assert_se(!valid_user_group_name_or_id("-1")); + assert_se(!valid_user_group_name_or_id("-kkk")); + assert_se(!valid_user_group_name_or_id("rööt")); +- assert_se(!valid_user_group_name_or_id(".")); +- assert_se(!valid_user_group_name_or_id("eff.eff")); + assert_se(!valid_user_group_name_or_id("foo\nbar")); + assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id("aaa:bbb")); +@@ -114,6 +112,8 @@ static void test_valid_user_group_name_or_id(void) { + assert_se(valid_user_group_name_or_id("_kkk")); + assert_se(valid_user_group_name_or_id("kkk-")); + assert_se(valid_user_group_name_or_id("kk-k")); ++ assert_se(valid_user_group_name_or_id(".moo")); ++ assert_se(valid_user_group_name_or_id("eff.eff")); + + assert_se(valid_user_group_name_or_id("some5")); + assert_se(!valid_user_group_name_or_id("5some")); diff --git a/SOURCES/0251-sd-bus-bump-message-queue-size-again.patch b/SOURCES/0251-sd-bus-bump-message-queue-size-again.patch new file mode 100644 index 0000000..5fd7ade --- /dev/null +++ b/SOURCES/0251-sd-bus-bump-message-queue-size-again.patch @@ -0,0 +1,29 @@ +From 62623bafd9ce4842122ddeda83f9527e43b9a21f Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 8 Nov 2019 14:54:30 +0100 +Subject: [PATCH] sd-bus: bump message queue size again + +Simliarly to issue #4068, the current limit turns out to be too small for a +big storage setup that uses many small disks. Let's bump it further. + +(cherry picked from commit 83a32ea7b03d6707b8e5bb90a0b3a6eb868ef633) +Resolves: #1770189 +--- + src/libsystemd/sd-bus/bus-internal.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h +index 90e6028983..5d773b14c4 100644 +--- a/src/libsystemd/sd-bus/bus-internal.h ++++ b/src/libsystemd/sd-bus/bus-internal.h +@@ -328,8 +328,8 @@ struct sd_bus { + * with enough entropy yet and might delay the boot */ + #define BUS_AUTH_TIMEOUT ((usec_t) DEFAULT_TIMEOUT_USEC) + +-#define BUS_WQUEUE_MAX (192*1024) +-#define BUS_RQUEUE_MAX (192*1024) ++#define BUS_WQUEUE_MAX (384*1024) ++#define BUS_RQUEUE_MAX (384*1024) + + #define BUS_MESSAGE_SIZE_MAX (128*1024*1024) + #define BUS_AUTH_SIZE_MAX (64*1024) diff --git a/SOURCES/0252-tests-put-fuzz_journald_processing_function-in-a-.c-.patch b/SOURCES/0252-tests-put-fuzz_journald_processing_function-in-a-.c-.patch new file mode 100644 index 0000000..532dd60 --- /dev/null +++ b/SOURCES/0252-tests-put-fuzz_journald_processing_function-in-a-.c-.patch @@ -0,0 +1,109 @@ +From 18a45cf91dbdd075fb55d752f959e84d36f3ab3b Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 7 Sep 2018 06:13:17 +0000 +Subject: [PATCH] tests: put fuzz_journald_processing_function in a .c file + +(cherry picked from commit 231dca5579cfba6175d19eee5347d693893fb5aa) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald.c | 30 ++++++++++++++++++++++++++++++ + src/fuzz/fuzz-journald.h | 24 ++---------------------- + src/fuzz/meson.build | 6 ++++-- + 3 files changed, 36 insertions(+), 24 deletions(-) + create mode 100644 src/fuzz/fuzz-journald.c + +diff --git a/src/fuzz/fuzz-journald.c b/src/fuzz/fuzz-journald.c +new file mode 100644 +index 0000000000..f271d7f2fe +--- /dev/null ++++ b/src/fuzz/fuzz-journald.c +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "alloc-util.h" ++#include "fuzz-journald.h" ++#include "journald-server.h" ++#include "sd-event.h" ++ ++void fuzz_journald_processing_function( ++ const uint8_t *data, ++ size_t size, ++ void (*f)(Server *s, const char *buf, size_t raw_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) ++ ) { ++ Server s = {}; ++ char *label = NULL; ++ size_t label_len = 0; ++ struct ucred *ucred = NULL; ++ struct timeval *tv = NULL; ++ ++ if (size == 0) ++ return; ++ ++ assert_se(sd_event_default(&s.event) >= 0); ++ s.syslog_fd = s.native_fd = s.stdout_fd = s.dev_kmsg_fd = s.audit_fd = s.hostname_fd = s.notify_fd = -1; ++ s.buffer = memdup_suffix0(data, size); ++ assert_se(s.buffer); ++ s.buffer_size = size + 1; ++ s.storage = STORAGE_NONE; ++ (*f)(&s, s.buffer, size, ucred, tv, label, label_len); ++ server_done(&s); ++} +diff --git a/src/fuzz/fuzz-journald.h b/src/fuzz/fuzz-journald.h +index e66ef54c9b..e9d32a74aa 100644 +--- a/src/fuzz/fuzz-journald.h ++++ b/src/fuzz/fuzz-journald.h +@@ -1,30 +1,10 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + #pragma once + +-#include "alloc-util.h" + #include "journald-server.h" +-#include "sd-event.h" + +-static void fuzz_journald_processing_function( ++void fuzz_journald_processing_function( + const uint8_t *data, + size_t size, + void (*f)(Server *s, const char *buf, size_t raw_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) +- ) { +- Server s = {}; +- char *label = NULL; +- size_t label_len = 0; +- struct ucred *ucred = NULL; +- struct timeval *tv = NULL; +- +- if (size == 0) +- return; +- +- assert_se(sd_event_default(&s.event) >= 0); +- s.syslog_fd = s.native_fd = s.stdout_fd = s.dev_kmsg_fd = s.audit_fd = s.hostname_fd = s.notify_fd = -1; +- s.buffer = memdup_suffix0(data, size); +- assert_se(s.buffer); +- s.buffer_size = size + 1; +- s.storage = STORAGE_NONE; +- (*f)(&s, s.buffer, size, ucred, tv, label, label_len); +- server_done(&s); +-} ++); +diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build +index 483a952421..1f8631bcc0 100644 +--- a/src/fuzz/meson.build ++++ b/src/fuzz/meson.build +@@ -33,12 +33,14 @@ fuzzers += [ + libshared], + [libmount]], + +- [['src/fuzz/fuzz-journald-native.c'], ++ [['src/fuzz/fuzz-journald-native.c', ++ 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + +- [['src/fuzz/fuzz-journald-syslog.c'], ++ [['src/fuzz/fuzz-journald-syslog.c', ++ 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], diff --git a/SOURCES/0253-tests-add-a-fuzzer-for-dev_kmsg_record.patch b/SOURCES/0253-tests-add-a-fuzzer-for-dev_kmsg_record.patch new file mode 100644 index 0000000..6e01bbf --- /dev/null +++ b/SOURCES/0253-tests-add-a-fuzzer-for-dev_kmsg_record.patch @@ -0,0 +1,129 @@ +From e7e70f575840cd021f6429f264911ae0cbff9741 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Thu, 15 Nov 2018 17:52:57 +0100 +Subject: [PATCH] tests: add a fuzzer for dev_kmsg_record + +(cherry picked from commit 8857fb9beb9dcb95a6ce1be14dc94c4dc4cd3ea3) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald-kmsg.c | 29 +++++++++++++++++++ + src/fuzz/meson.build | 5 ++++ + src/journal/journald-kmsg.c | 2 +- + src/journal/journald-kmsg.h | 2 ++ + test/fuzz/fuzz-journald-kmsg/basic | 1 + + test/fuzz/fuzz-journald-kmsg/dev-null | 2 ++ + test/fuzz/fuzz-journald-kmsg/loopback | 2 ++ + .../fuzz-journald-kmsg/subsystem-loopback | 2 ++ + 8 files changed, 44 insertions(+), 1 deletion(-) + create mode 100644 src/fuzz/fuzz-journald-kmsg.c + create mode 100644 test/fuzz/fuzz-journald-kmsg/basic + create mode 100644 test/fuzz/fuzz-journald-kmsg/dev-null + create mode 100644 test/fuzz/fuzz-journald-kmsg/loopback + create mode 100644 test/fuzz/fuzz-journald-kmsg/subsystem-loopback + +diff --git a/src/fuzz/fuzz-journald-kmsg.c b/src/fuzz/fuzz-journald-kmsg.c +new file mode 100644 +index 0000000000..5d99d244b5 +--- /dev/null ++++ b/src/fuzz/fuzz-journald-kmsg.c +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "fuzz.h" ++#include "journald-kmsg.h" ++ ++int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ++ Server s = {}; ++ _cleanup_free_ char *buffer = NULL; ++ ++ if (size == 0) ++ return 0; ++ ++ s = (Server) { ++ .native_fd = -1, ++ .stdout_fd = -1, ++ .dev_kmsg_fd = -1, ++ .audit_fd = -1, ++ .hostname_fd = -1, ++ .notify_fd = -1, ++ .storage = STORAGE_NONE, ++ }; ++ assert_se(sd_event_default(&s.event) >= 0); ++ buffer = memdup(data, size); ++ assert_se(buffer); ++ dev_kmsg_record(&s, buffer, size); ++ server_done(&s); ++ ++ return 0; ++} +diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build +index 1f8631bcc0..0520e448a9 100644 +--- a/src/fuzz/meson.build ++++ b/src/fuzz/meson.build +@@ -33,6 +33,11 @@ fuzzers += [ + libshared], + [libmount]], + ++ [['src/fuzz/fuzz-journald-kmsg.c'], ++ [libjournal_core, ++ libshared], ++ [libselinux]], ++ + [['src/fuzz/fuzz-journald-native.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, +diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c +index 7644bebfc8..0cdf1c4794 100644 +--- a/src/journal/journald-kmsg.c ++++ b/src/journal/journald-kmsg.c +@@ -93,7 +93,7 @@ static bool is_us(const char *identifier, const char *pid) { + streq(identifier, program_invocation_short_name); + } + +-static void dev_kmsg_record(Server *s, char *p, size_t l) { ++void dev_kmsg_record(Server *s, char *p, size_t l) { + + _cleanup_free_ char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL, *identifier = NULL, *pid = NULL; + struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS]; +diff --git a/src/journal/journald-kmsg.h b/src/journal/journald-kmsg.h +index bff24ac310..2326bc8c93 100644 +--- a/src/journal/journald-kmsg.h ++++ b/src/journal/journald-kmsg.h +@@ -9,3 +9,5 @@ int server_flush_dev_kmsg(Server *s); + void server_forward_kmsg(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); + + int server_open_kernel_seqnum(Server *s); ++ ++void dev_kmsg_record(Server *s, char *p, size_t l); +diff --git a/test/fuzz/fuzz-journald-kmsg/basic b/test/fuzz/fuzz-journald-kmsg/basic +new file mode 100644 +index 0000000000..1299cd0869 +--- /dev/null ++++ b/test/fuzz/fuzz-journald-kmsg/basic +@@ -0,0 +1 @@ ++29,456,292891883,-;systemd[1]: Reexecuting. +diff --git a/test/fuzz/fuzz-journald-kmsg/dev-null b/test/fuzz/fuzz-journald-kmsg/dev-null +new file mode 100644 +index 0000000000..de039588b5 +--- /dev/null ++++ b/test/fuzz/fuzz-journald-kmsg/dev-null +@@ -0,0 +1,2 @@ ++12,460,1322026586,-;hey ++ DEVICE=c1:3 +diff --git a/test/fuzz/fuzz-journald-kmsg/loopback b/test/fuzz/fuzz-journald-kmsg/loopback +new file mode 100644 +index 0000000000..ca320177b7 +--- /dev/null ++++ b/test/fuzz/fuzz-journald-kmsg/loopback +@@ -0,0 +1,2 @@ ++12,460,1322026586,-;hey ++ DEVICE=n1 +diff --git a/test/fuzz/fuzz-journald-kmsg/subsystem-loopback b/test/fuzz/fuzz-journald-kmsg/subsystem-loopback +new file mode 100644 +index 0000000000..af9c0d91e5 +--- /dev/null ++++ b/test/fuzz/fuzz-journald-kmsg/subsystem-loopback +@@ -0,0 +1,2 @@ ++12,460,1322026586,-;hey ++ DEVICE=+net:lo diff --git a/SOURCES/0254-basic-remove-an-assertion-from-cunescape_one.patch b/SOURCES/0254-basic-remove-an-assertion-from-cunescape_one.patch new file mode 100644 index 0000000..ec38ffc --- /dev/null +++ b/SOURCES/0254-basic-remove-an-assertion-from-cunescape_one.patch @@ -0,0 +1,30 @@ +From 43d72623fdfca8500c8c89a4b5023e35a3f0b259 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 16 Nov 2018 07:05:29 +0100 +Subject: [PATCH] basic: remove an assertion from cunescape_one + +The function takes a pointer to a random block of memory and +the length of that block. It shouldn't crash every time it sees +a zero byte at the beginning there. + +This should help the dev-kmsg fuzzer to keep going. + +(cherry picked from commit 8dc4de966ce6d32470aaff30ed054f6a2688d6d7) + +Resolves: #1764560 +--- + src/basic/escape.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/basic/escape.c b/src/basic/escape.c +index 5004763d97..5f715156fb 100644 +--- a/src/basic/escape.c ++++ b/src/basic/escape.c +@@ -106,7 +106,6 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) + int r = 1; + + assert(p); +- assert(*p); + assert(ret); + + /* Unescapes C style. Returns the unescaped character in ret. diff --git a/SOURCES/0255-journal-fix-an-off-by-one-error-in-dev_kmsg_record.patch b/SOURCES/0255-journal-fix-an-off-by-one-error-in-dev_kmsg_record.patch new file mode 100644 index 0000000..28a0b3e --- /dev/null +++ b/SOURCES/0255-journal-fix-an-off-by-one-error-in-dev_kmsg_record.patch @@ -0,0 +1,25 @@ +From f00d221d5dc92a530e260db5f44fa57653f03e8b Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 16 Nov 2018 07:11:06 +0100 +Subject: [PATCH] journal: fix an off-by-one error in dev_kmsg_record + +(cherry picked from commit 080d112caa0dc948555a69a008c1caf4d5d41ed6) + +Resolves: #1764560 +--- + src/journal/journald-kmsg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c +index 0cdf1c4794..726c006ce1 100644 +--- a/src/journal/journald-kmsg.c ++++ b/src/journal/journald-kmsg.c +@@ -239,7 +239,7 @@ void dev_kmsg_record(Server *s, char *p, size_t l) { + ll = udev_device_get_devlinks_list_entry(ud); + udev_list_entry_foreach(ll, ll) { + +- if (j > N_IOVEC_UDEV_FIELDS) ++ if (j >= N_IOVEC_UDEV_FIELDS) + break; + + g = udev_list_entry_get_name(ll); diff --git a/SOURCES/0256-tests-add-a-reproducer-for-a-memory-leak-fixed-in-30.patch b/SOURCES/0256-tests-add-a-reproducer-for-a-memory-leak-fixed-in-30.patch new file mode 100644 index 0000000..14c1223 --- /dev/null +++ b/SOURCES/0256-tests-add-a-reproducer-for-a-memory-leak-fixed-in-30.patch @@ -0,0 +1,25 @@ +From 4caa887ae8eabc087d6f9f2b233c96c220de8b02 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 16 Nov 2018 07:20:44 +0100 +Subject: [PATCH] tests: add a reproducer for a memory leak fixed in + 30eddcd51b8a472e05d3b8d1 in August + +(cherry picked from commit 1dd485b700fe9ad94d7a780f14fcf18a4738ace4) + +Resolves: #1764560 +--- + ...leak-ab161e601e82f1ec31d11e2cbae2747834ce9e43 | Bin 0 -> 1847 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 test/fuzz/fuzz-journald-kmsg/leak-ab161e601e82f1ec31d11e2cbae2747834ce9e43 + +diff --git a/test/fuzz/fuzz-journald-kmsg/leak-ab161e601e82f1ec31d11e2cbae2747834ce9e43 b/test/fuzz/fuzz-journald-kmsg/leak-ab161e601e82f1ec31d11e2cbae2747834ce9e43 +new file mode 100644 +index 0000000000000000000000000000000000000000..424ae5cb010aa519758e6af90cc981795b68d3fd +GIT binary patch +literal 1847 +zcmXps(lIeJ&@nVNGBPkSGqo_&(Y4MjX0aSiiycD2<{NiEaQE6vG)izFLb8I! +Date: Fri, 16 Nov 2018 07:33:02 +0100 +Subject: [PATCH] tests: add a reproducer for a heap-buffer-overflow fixed in + 937b1171378bc1000a + +(cherry picked from commit f7a6b40187a98751a9ab6867e8b52e4e6f1dad5c) + +Resolves: #1764560 +--- + ...crash-c6c04d83e73f3d1417bc0afce8fa81b99f955963 | Bin 0 -> 112 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 test/fuzz/fuzz-journald-kmsg/crash-c6c04d83e73f3d1417bc0afce8fa81b99f955963 + +diff --git a/test/fuzz/fuzz-journald-kmsg/crash-c6c04d83e73f3d1417bc0afce8fa81b99f955963 b/test/fuzz/fuzz-journald-kmsg/crash-c6c04d83e73f3d1417bc0afce8fa81b99f955963 +new file mode 100644 +index 0000000000000000000000000000000000000000..19887a1fec9fc29b1f7da8a2d1c5ea5054f2bc02 +GIT binary patch +literal 112 +zcmXpq)Zrxx80r}680lCOP-~&{)k?wIfGehgOM!tQroxI#0Z63Aa4DF?03ibx03hxS +A82|tP + +literal 0 +HcmV?d00001 + diff --git a/SOURCES/0258-test-initialize-syslog_fd-in-fuzz-journald-kmsg-too.patch b/SOURCES/0258-test-initialize-syslog_fd-in-fuzz-journald-kmsg-too.patch new file mode 100644 index 0000000..3ffa913 --- /dev/null +++ b/SOURCES/0258-test-initialize-syslog_fd-in-fuzz-journald-kmsg-too.patch @@ -0,0 +1,44 @@ +From af471e7402a70b670cd50e45c6139a0ac50a74bd Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 16 Nov 2018 09:23:53 +0100 +Subject: [PATCH] test: initialize syslog_fd in fuzz-journald-kmsg too + +This is a follow-up to 8857fb9beb9dcb that prevents the fuzzer from crashing with +``` +==220==ERROR: AddressSanitizer: ABRT on unknown address 0x0000000000dc (pc 0x7ff4953c8428 bp 0x7ffcf66ec290 sp 0x7ffcf66ec128 T0) +SCARINESS: 10 (signal) + #0 0x7ff4953c8427 in gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35427) + #1 0x7ff4953ca029 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x37029) + #2 0x7ff49666503a in log_assert_failed_realm /work/build/../../src/systemd/src/basic/log.c:805:9 + #3 0x7ff496614ecf in safe_close /work/build/../../src/systemd/src/basic/fd-util.c:66:17 + #4 0x548806 in server_done /work/build/../../src/systemd/src/journal/journald-server.c:2064:9 + #5 0x5349fa in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/fuzz/fuzz-journald-kmsg.c:26:9 + #6 0x592755 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:571:15 + #7 0x590627 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/libfuzzer/FuzzerLoop.cpp:480:3 + #8 0x594432 in fuzzer::Fuzzer::MutateAndTestOne() /src/libfuzzer/FuzzerLoop.cpp:708:19 + #9 0x5973c6 in fuzzer::Fuzzer::Loop(std::__1::vector, std::__1::allocator >, fuzzer::fuzzer_allocator, std::__1::allocator > > > const&) /src/libfuzzer/FuzzerLoop.cpp:839:5 + #10 0x574541 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:764:6 + #11 0x5675fc in main /src/libfuzzer/FuzzerMain.cpp:20:10 + #12 0x7ff4953b382f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) + #13 0x420f58 in _start (/out/fuzz-journald-kmsg+0x420f58) +``` + +(cherry picked from commit cc55ac0171a2493768c021faa356513642797e7f) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald-kmsg.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/fuzz/fuzz-journald-kmsg.c b/src/fuzz/fuzz-journald-kmsg.c +index 5d99d244b5..e2611c6d45 100644 +--- a/src/fuzz/fuzz-journald-kmsg.c ++++ b/src/fuzz/fuzz-journald-kmsg.c +@@ -11,6 +11,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + return 0; + + s = (Server) { ++ .syslog_fd = -1, + .native_fd = -1, + .stdout_fd = -1, + .dev_kmsg_fd = -1, diff --git a/SOURCES/0259-tests-add-a-fuzzer-for-process_audit_string.patch b/SOURCES/0259-tests-add-a-fuzzer-for-process_audit_string.patch new file mode 100644 index 0000000..d6ea02d --- /dev/null +++ b/SOURCES/0259-tests-add-a-fuzzer-for-process_audit_string.patch @@ -0,0 +1,99 @@ +From f991a9c7644f3fb5155ff823600ba5a6ea403dc4 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 16 Nov 2018 21:23:56 +0100 +Subject: [PATCH] tests: add a fuzzer for process_audit_string + +(cherry picked from commit 090a20cfaf3d5439fa39c5d8df473b0cfef181dd) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald-audit.c | 27 +++++++++++++++++++++++++++ + src/fuzz/meson.build | 5 +++++ + src/journal/journald-audit.c | 2 +- + src/journal/journald-audit.h | 2 ++ + test/fuzz/fuzz-journald-audit/basic | 1 + + 5 files changed, 36 insertions(+), 1 deletion(-) + create mode 100644 src/fuzz/fuzz-journald-audit.c + create mode 100644 test/fuzz/fuzz-journald-audit/basic + +diff --git a/src/fuzz/fuzz-journald-audit.c b/src/fuzz/fuzz-journald-audit.c +new file mode 100644 +index 0000000000..fe401c0d98 +--- /dev/null ++++ b/src/fuzz/fuzz-journald-audit.c +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "fuzz.h" ++#include "journald-audit.h" ++ ++int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ++ Server s; ++ _cleanup_free_ char *buffer = NULL; ++ ++ s = (Server) { ++ .syslog_fd = -1, ++ .native_fd = -1, ++ .stdout_fd = -1, ++ .dev_kmsg_fd = -1, ++ .audit_fd = -1, ++ .hostname_fd = -1, ++ .notify_fd = -1, ++ .storage = STORAGE_NONE, ++ }; ++ assert_se(sd_event_default(&s.event) >= 0); ++ buffer = memdup_suffix0(data, size); ++ assert_se(buffer); ++ process_audit_string(&s, 0, buffer, size); ++ server_done(&s); ++ ++ return 0; ++} +diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build +index 0520e448a9..5548da3822 100644 +--- a/src/fuzz/meson.build ++++ b/src/fuzz/meson.build +@@ -33,6 +33,11 @@ fuzzers += [ + libshared], + [libmount]], + ++ [['src/fuzz/fuzz-journald-audit.c'], ++ [libjournal_core, ++ libshared], ++ [libselinux]], ++ + [['src/fuzz/fuzz-journald-kmsg.c'], + [libjournal_core, + libshared], +diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c +index 87726684af..7810a0139a 100644 +--- a/src/journal/journald-audit.c ++++ b/src/journal/journald-audit.c +@@ -313,7 +313,7 @@ static int map_all_fields( + } + } + +-static void process_audit_string(Server *s, int type, const char *data, size_t size) { ++void process_audit_string(Server *s, int type, const char *data, size_t size) { + size_t n_iov_allocated = 0, n_iov = 0, z; + _cleanup_free_ struct iovec *iov = NULL; + uint64_t seconds, msec, id; +diff --git a/src/journal/journald-audit.h b/src/journal/journald-audit.h +index 57bb1711c9..7766618c98 100644 +--- a/src/journal/journald-audit.h ++++ b/src/journal/journald-audit.h +@@ -6,4 +6,6 @@ + + void server_process_audit_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const union sockaddr_union *sa, socklen_t salen); + ++void process_audit_string(Server *s, int type, const char *data, size_t size); ++ + int server_open_audit(Server*s); +diff --git a/test/fuzz/fuzz-journald-audit/basic b/test/fuzz/fuzz-journald-audit/basic +new file mode 100644 +index 0000000000..d1ce8cc5f0 +--- /dev/null ++++ b/test/fuzz/fuzz-journald-audit/basic +@@ -0,0 +1 @@ ++audit(1542398162.211:744): pid=7376 uid=1000 auid=1000 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="vagrant" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success' +\ No newline at end of file diff --git a/SOURCES/0260-journald-check-whether-sscanf-has-changed-the-value-.patch b/SOURCES/0260-journald-check-whether-sscanf-has-changed-the-value-.patch new file mode 100644 index 0000000..29ce46f --- /dev/null +++ b/SOURCES/0260-journald-check-whether-sscanf-has-changed-the-value-.patch @@ -0,0 +1,47 @@ +From bef599d1a0e41afe4b6f1d6dfb6fbc86896ab8c5 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 16 Nov 2018 23:32:31 +0100 +Subject: [PATCH] journald: check whether sscanf has changed the value + corresponding to %n + +It's possible for sscanf to receive strings containing all three fields +and not matching the template at the same time. When this happens the +value of k doesn't change, which basically means that process_audit_string +tries to access memory randomly. Sometimes it works and sometimes it doesn't :-) + +See also https://bugzilla.redhat.com/show_bug.cgi?id=1059314. + +(cherry picked from commit 1dab14aba749b9c5ab8176c5730107b70834240b) + +Resolves: #1764560 +--- + src/journal/journald-audit.c | 3 ++- + test/fuzz/fuzz-journald-audit/crash | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + create mode 100644 test/fuzz/fuzz-journald-audit/crash + +diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c +index 7810a0139a..0fd6ab2a84 100644 +--- a/src/journal/journald-audit.c ++++ b/src/journal/journald-audit.c +@@ -341,11 +341,12 @@ void process_audit_string(Server *s, int type, const char *data, size_t size) { + if (!p) + return; + ++ k = 0; + if (sscanf(p, "(%" PRIu64 ".%" PRIu64 ":%" PRIu64 "):%n", + &seconds, + &msec, + &id, +- &k) != 3) ++ &k) != 3 || k == 0) + return; + + p += k; +diff --git a/test/fuzz/fuzz-journald-audit/crash b/test/fuzz/fuzz-journald-audit/crash +new file mode 100644 +index 0000000000..91bd85ca6e +--- /dev/null ++++ b/test/fuzz/fuzz-journald-audit/crash +@@ -0,0 +1 @@ ++audit(1542398162.211:744) pid=7376 uid=1000 auid=1000 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="vagrant" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success' diff --git a/SOURCES/0261-tests-introduce-dummy_server_init-and-use-it-in-all-.patch b/SOURCES/0261-tests-introduce-dummy_server_init-and-use-it-in-all-.patch new file mode 100644 index 0000000..f4a5225 --- /dev/null +++ b/SOURCES/0261-tests-introduce-dummy_server_init-and-use-it-in-all-.patch @@ -0,0 +1,172 @@ +From b276c85200786add6c86b6c1fedc888c71ffe5db Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Sat, 17 Nov 2018 13:01:09 +0100 +Subject: [PATCH] tests: introduce dummy_server_init and use it in all journald + fuzzers + +(cherry picked from commit ed62712dc6fb236845c489a7f386c7aff0ec31d6) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald-audit.c | 18 +++--------------- + src/fuzz/fuzz-journald-kmsg.c | 20 ++++---------------- + src/fuzz/fuzz-journald.c | 26 +++++++++++++++++++------- + src/fuzz/fuzz-journald.h | 2 ++ + src/fuzz/meson.build | 6 ++++-- + 5 files changed, 32 insertions(+), 40 deletions(-) + +diff --git a/src/fuzz/fuzz-journald-audit.c b/src/fuzz/fuzz-journald-audit.c +index fe401c0d98..3f3ce7e8ee 100644 +--- a/src/fuzz/fuzz-journald-audit.c ++++ b/src/fuzz/fuzz-journald-audit.c +@@ -1,26 +1,14 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include "fuzz.h" ++#include "fuzz-journald.h" + #include "journald-audit.h" + + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + Server s; +- _cleanup_free_ char *buffer = NULL; + +- s = (Server) { +- .syslog_fd = -1, +- .native_fd = -1, +- .stdout_fd = -1, +- .dev_kmsg_fd = -1, +- .audit_fd = -1, +- .hostname_fd = -1, +- .notify_fd = -1, +- .storage = STORAGE_NONE, +- }; +- assert_se(sd_event_default(&s.event) >= 0); +- buffer = memdup_suffix0(data, size); +- assert_se(buffer); +- process_audit_string(&s, 0, buffer, size); ++ dummy_server_init(&s, data, size); ++ process_audit_string(&s, 0, s.buffer, size); + server_done(&s); + + return 0; +diff --git a/src/fuzz/fuzz-journald-kmsg.c b/src/fuzz/fuzz-journald-kmsg.c +index e2611c6d45..f7426c8400 100644 +--- a/src/fuzz/fuzz-journald-kmsg.c ++++ b/src/fuzz/fuzz-journald-kmsg.c +@@ -1,29 +1,17 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include "fuzz.h" ++#include "fuzz-journald.h" + #include "journald-kmsg.h" + + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { +- Server s = {}; +- _cleanup_free_ char *buffer = NULL; ++ Server s; + + if (size == 0) + return 0; + +- s = (Server) { +- .syslog_fd = -1, +- .native_fd = -1, +- .stdout_fd = -1, +- .dev_kmsg_fd = -1, +- .audit_fd = -1, +- .hostname_fd = -1, +- .notify_fd = -1, +- .storage = STORAGE_NONE, +- }; +- assert_se(sd_event_default(&s.event) >= 0); +- buffer = memdup(data, size); +- assert_se(buffer); +- dev_kmsg_record(&s, buffer, size); ++ dummy_server_init(&s, data, size); ++ dev_kmsg_record(&s, s.buffer, size); + server_done(&s); + + return 0; +diff --git a/src/fuzz/fuzz-journald.c b/src/fuzz/fuzz-journald.c +index f271d7f2fe..0659b92ba3 100644 +--- a/src/fuzz/fuzz-journald.c ++++ b/src/fuzz/fuzz-journald.c +@@ -5,12 +5,29 @@ + #include "journald-server.h" + #include "sd-event.h" + ++void dummy_server_init(Server *s, const uint8_t *buffer, size_t size) { ++ *s = (Server) { ++ .syslog_fd = -1, ++ .native_fd = -1, ++ .stdout_fd = -1, ++ .dev_kmsg_fd = -1, ++ .audit_fd = -1, ++ .hostname_fd = -1, ++ .notify_fd = -1, ++ .storage = STORAGE_NONE, ++ }; ++ assert_se(sd_event_default(&s->event) >= 0); ++ s->buffer = memdup_suffix0(buffer, size); ++ assert_se(s->buffer); ++ s->buffer_size = size + 1; ++} ++ + void fuzz_journald_processing_function( + const uint8_t *data, + size_t size, + void (*f)(Server *s, const char *buf, size_t raw_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) + ) { +- Server s = {}; ++ Server s; + char *label = NULL; + size_t label_len = 0; + struct ucred *ucred = NULL; +@@ -19,12 +36,7 @@ void fuzz_journald_processing_function( + if (size == 0) + return; + +- assert_se(sd_event_default(&s.event) >= 0); +- s.syslog_fd = s.native_fd = s.stdout_fd = s.dev_kmsg_fd = s.audit_fd = s.hostname_fd = s.notify_fd = -1; +- s.buffer = memdup_suffix0(data, size); +- assert_se(s.buffer); +- s.buffer_size = size + 1; +- s.storage = STORAGE_NONE; ++ dummy_server_init(&s, data, size); + (*f)(&s, s.buffer, size, ucred, tv, label, label_len); + server_done(&s); + } +diff --git a/src/fuzz/fuzz-journald.h b/src/fuzz/fuzz-journald.h +index e9d32a74aa..77e3b0c064 100644 +--- a/src/fuzz/fuzz-journald.h ++++ b/src/fuzz/fuzz-journald.h +@@ -3,6 +3,8 @@ + + #include "journald-server.h" + ++void dummy_server_init(Server *s, const uint8_t *buffer, size_t size); ++ + void fuzz_journald_processing_function( + const uint8_t *data, + size_t size, +diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build +index 5548da3822..897c02e4ae 100644 +--- a/src/fuzz/meson.build ++++ b/src/fuzz/meson.build +@@ -33,12 +33,14 @@ fuzzers += [ + libshared], + [libmount]], + +- [['src/fuzz/fuzz-journald-audit.c'], ++ [['src/fuzz/fuzz-journald-audit.c', ++ 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + +- [['src/fuzz/fuzz-journald-kmsg.c'], ++ [['src/fuzz/fuzz-journald-kmsg.c', ++ 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], diff --git a/SOURCES/0262-tests-add-a-fuzzer-for-journald-streams.patch b/SOURCES/0262-tests-add-a-fuzzer-for-journald-streams.patch new file mode 100644 index 0000000..03ff6e8 --- /dev/null +++ b/SOURCES/0262-tests-add-a-fuzzer-for-journald-streams.patch @@ -0,0 +1,148 @@ +From e7077e3a551a3faedfcc3d007de6a72fb5e1df62 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Tue, 20 Nov 2018 01:20:32 +0100 +Subject: [PATCH] tests: add a fuzzer for journald streams + +(cherry picked from commit 9541f5ff5c637bb1b3e3c69706cb73e68ff06813) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald-stream.c | 35 ++++++++++++++++++++++++++++ + src/fuzz/fuzz-journald.c | 10 +++++--- + src/fuzz/meson.build | 6 +++++ + src/journal/journald-stream.c | 4 ++-- + src/journal/journald-stream.h | 2 ++ + test/fuzz/fuzz-journald-stream/basic | 8 +++++++ + 6 files changed, 60 insertions(+), 5 deletions(-) + create mode 100644 src/fuzz/fuzz-journald-stream.c + create mode 100644 test/fuzz/fuzz-journald-stream/basic + +diff --git a/src/fuzz/fuzz-journald-stream.c b/src/fuzz/fuzz-journald-stream.c +new file mode 100644 +index 0000000000..247c0889bc +--- /dev/null ++++ b/src/fuzz/fuzz-journald-stream.c +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include ++ ++#include "fd-util.h" ++#include "fuzz.h" ++#include "fuzz-journald.h" ++#include "journald-stream.h" ++ ++static int stream_fds[2] = { -1, -1 }; ++ ++int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ++ Server s; ++ StdoutStream *stream; ++ int v; ++ ++ if (size == 0) ++ return 0; ++ ++ if (!getenv("SYSTEMD_LOG_LEVEL")) ++ log_set_max_level(LOG_CRIT); ++ ++ assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, stream_fds) >= 0); ++ dummy_server_init(&s, NULL, 0); ++ assert_se(stdout_stream_install(&s, stream_fds[0], &stream) >= 0); ++ assert_se(write(stream_fds[1], data, size) == (ssize_t) size); ++ while (ioctl(stream_fds[0], SIOCINQ, &v) == 0 && v) ++ sd_event_run(s.event, (uint64_t) -1); ++ if (s.n_stdout_streams) ++ stdout_stream_destroy(stream); ++ server_done(&s); ++ stream_fds[1] = safe_close(stream_fds[1]); ++ ++ return 0; ++} +diff --git a/src/fuzz/fuzz-journald.c b/src/fuzz/fuzz-journald.c +index 0659b92ba3..950e885cae 100644 +--- a/src/fuzz/fuzz-journald.c ++++ b/src/fuzz/fuzz-journald.c +@@ -15,11 +15,15 @@ void dummy_server_init(Server *s, const uint8_t *buffer, size_t size) { + .hostname_fd = -1, + .notify_fd = -1, + .storage = STORAGE_NONE, ++ .line_max = 64, + }; + assert_se(sd_event_default(&s->event) >= 0); +- s->buffer = memdup_suffix0(buffer, size); +- assert_se(s->buffer); +- s->buffer_size = size + 1; ++ ++ if (buffer) { ++ s->buffer = memdup_suffix0(buffer, size); ++ assert_se(s->buffer); ++ s->buffer_size = size + 1; ++ } + } + + void fuzz_journald_processing_function( +diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build +index 897c02e4ae..eea9117360 100644 +--- a/src/fuzz/meson.build ++++ b/src/fuzz/meson.build +@@ -51,6 +51,12 @@ fuzzers += [ + libshared], + [libselinux]], + ++ [['src/fuzz/fuzz-journald-stream.c', ++ 'src/fuzz/fuzz-journald.c'], ++ [libjournal_core, ++ libshared], ++ [libselinux]], ++ + [['src/fuzz/fuzz-journald-syslog.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index dbf3503a82..6f8a4011ff 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -125,7 +125,7 @@ void stdout_stream_free(StdoutStream *s) { + + DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free); + +-static void stdout_stream_destroy(StdoutStream *s) { ++void stdout_stream_destroy(StdoutStream *s) { + if (!s) + return; + +@@ -534,7 +534,7 @@ terminate: + return 0; + } + +-static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { ++int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { + _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL; + sd_id128_t id; + int r; +diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h +index bc5622ab3b..487376e763 100644 +--- a/src/journal/journald-stream.h ++++ b/src/journal/journald-stream.h +@@ -10,4 +10,6 @@ int server_open_stdout_socket(Server *s); + int server_restore_streams(Server *s, FDSet *fds); + + void stdout_stream_free(StdoutStream *s); ++int stdout_stream_install(Server *s, int fd, StdoutStream **ret); ++void stdout_stream_destroy(StdoutStream *s); + void stdout_stream_send_notify(StdoutStream *s); +diff --git a/test/fuzz/fuzz-journald-stream/basic b/test/fuzz/fuzz-journald-stream/basic +new file mode 100644 +index 0000000000..a088f1a539 +--- /dev/null ++++ b/test/fuzz/fuzz-journald-stream/basic +@@ -0,0 +1,8 @@ ++ ++ ++6 ++1 ++0 ++0 ++0 ++hey +\ No newline at end of file diff --git a/SOURCES/0263-tests-add-a-fuzzer-for-server_process_native_file.patch b/SOURCES/0263-tests-add-a-fuzzer-for-server_process_native_file.patch new file mode 100644 index 0000000..500af37 --- /dev/null +++ b/SOURCES/0263-tests-add-a-fuzzer-for-server_process_native_file.patch @@ -0,0 +1,96 @@ +From 76e2fa8ed4bbee7c625e3b790f2e38a59fffd93d Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 23 Nov 2018 00:27:19 +0100 +Subject: [PATCH] tests: add a fuzzer for server_process_native_file + +(cherry picked from commit a4aa59bae206eebb4703b291147144def5d4bb3e) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald-native-fd.c | 47 ++++++++++++++++++++++++ + src/fuzz/meson.build | 6 +++ + test/fuzz/fuzz-journald-native-fd/basic | Bin 0 -> 34 bytes + 3 files changed, 53 insertions(+) + create mode 100644 src/fuzz/fuzz-journald-native-fd.c + create mode 100644 test/fuzz/fuzz-journald-native-fd/basic + +diff --git a/src/fuzz/fuzz-journald-native-fd.c b/src/fuzz/fuzz-journald-native-fd.c +new file mode 100644 +index 0000000000..95415d9f85 +--- /dev/null ++++ b/src/fuzz/fuzz-journald-native-fd.c +@@ -0,0 +1,47 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "fd-util.h" ++#include "fileio.h" ++#include "fs-util.h" ++#include "fuzz.h" ++#include "fuzz-journald.h" ++#include "journald-native.h" ++#include "memfd-util.h" ++#include "process-util.h" ++ ++int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ++ Server s; ++ _cleanup_close_ int sealed_fd = -1, unsealed_fd = -1; ++ _cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-journald-native-fd.XXXXXX"; ++ char *label = NULL; ++ size_t label_len = 0; ++ struct ucred ucred; ++ struct timeval *tv = NULL; ++ ++ if (!getenv("SYSTEMD_LOG_LEVEL")) ++ log_set_max_level(LOG_CRIT); ++ ++ dummy_server_init(&s, NULL, 0); ++ ++ sealed_fd = memfd_new(NULL); ++ assert_se(sealed_fd >= 0); ++ assert_se(write(sealed_fd, data, size) == (ssize_t) size); ++ assert_se(memfd_set_sealed(sealed_fd) >= 0); ++ assert_se(lseek(sealed_fd, 0, SEEK_SET) == 0); ++ ucred = (struct ucred) { ++ .pid = getpid_cached(), ++ .uid = geteuid(), ++ .gid = getegid(), ++ }; ++ server_process_native_file(&s, sealed_fd, &ucred, tv, label, label_len); ++ ++ unsealed_fd = mkostemp_safe(name); ++ assert_se(unsealed_fd >= 0); ++ assert_se(write(unsealed_fd, data, size) == (ssize_t) size); ++ assert_se(lseek(unsealed_fd, 0, SEEK_SET) == 0); ++ server_process_native_file(&s, unsealed_fd, &ucred, tv, label, label_len); ++ ++ server_done(&s); ++ ++ return 0; ++} +diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build +index eea9117360..5315d2771c 100644 +--- a/src/fuzz/meson.build ++++ b/src/fuzz/meson.build +@@ -51,6 +51,12 @@ fuzzers += [ + libshared], + [libselinux]], + ++ [['src/fuzz/fuzz-journald-native-fd.c', ++ 'src/fuzz/fuzz-journald.c'], ++ [libjournal_core, ++ libshared], ++ [libselinux]], ++ + [['src/fuzz/fuzz-journald-stream.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, +diff --git a/test/fuzz/fuzz-journald-native-fd/basic b/test/fuzz/fuzz-journald-native-fd/basic +new file mode 100644 +index 0000000000000000000000000000000000000000..65f89705a655618851c0e446efaa5c633adf425f +GIT binary patch +literal 34 +kcmeZu4Gwm6cjaPXfB;7>M@KGyCofm$koW*k7h3}^0B8*cRR910 + +literal 0 +HcmV?d00001 + diff --git a/SOURCES/0264-fuzz-journal-stream-avoid-assertion-failure-on-sampl.patch b/SOURCES/0264-fuzz-journal-stream-avoid-assertion-failure-on-sampl.patch new file mode 100644 index 0000000..798aa6c --- /dev/null +++ b/SOURCES/0264-fuzz-journal-stream-avoid-assertion-failure-on-sampl.patch @@ -0,0 +1,47 @@ +From 2d197adc6d7109d5901401a90288530582f3f991 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 26 Feb 2019 13:00:35 +0100 +Subject: [PATCH] fuzz-journal-stream: avoid assertion failure on samples which + don't fit in pipe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11587. +We had a sample which was large enough that write(2) failed to push all the +data into the pipe, and an assert failed. The code could be changed to use +a loop, but then we'd need to interleave writes and sd_event_run (to process +the journal). I don't think the complexity is worth it — fuzzing works best +if the sample is not too huge anyway. So let's just reject samples above 64k, +and tell oss-fuzz about this limit. + +(cherry picked from commit eafadd069c4e30ed62173123326a7237448615d1) + +Resolves: #1764560 +--- + src/fuzz/fuzz-journald-stream.c | 2 +- + src/fuzz/fuzz-journald-stream.options | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + create mode 100644 src/fuzz/fuzz-journald-stream.options + +diff --git a/src/fuzz/fuzz-journald-stream.c b/src/fuzz/fuzz-journald-stream.c +index 247c0889bc..693b197d3a 100644 +--- a/src/fuzz/fuzz-journald-stream.c ++++ b/src/fuzz/fuzz-journald-stream.c +@@ -14,7 +14,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + StdoutStream *stream; + int v; + +- if (size == 0) ++ if (size == 0 || size > 65536) + return 0; + + if (!getenv("SYSTEMD_LOG_LEVEL")) +diff --git a/src/fuzz/fuzz-journald-stream.options b/src/fuzz/fuzz-journald-stream.options +new file mode 100644 +index 0000000000..678d526b1e +--- /dev/null ++++ b/src/fuzz/fuzz-journald-stream.options +@@ -0,0 +1,2 @@ ++[libfuzzer] ++max_len = 65536 diff --git a/SOURCES/0265-journald-take-leading-spaces-into-account-in-syslog_.patch b/SOURCES/0265-journald-take-leading-spaces-into-account-in-syslog_.patch new file mode 100644 index 0000000..25b1d95 --- /dev/null +++ b/SOURCES/0265-journald-take-leading-spaces-into-account-in-syslog_.patch @@ -0,0 +1,45 @@ +From 3521217c88b364e2c5b10a1e35d3c036b1ecba64 Mon Sep 17 00:00:00 2001 +From: Evgeny Vereshchagin +Date: Fri, 10 Aug 2018 12:55:09 +0000 +Subject: [PATCH] journald: take leading spaces into account in + syslog_parse_identifier + +This is a kind of follow-up to e88baee88fad8bc59d3 which should finally fix +the issue which that commit was supposed to fix. + +(cherry picked from commit 937b1171378bc1000a34fcdfe9534d898227e35f) + +Resolves: #1764560 +--- + src/journal/journald-syslog.c | 3 ++- + src/journal/test-journal-syslog.c | 2 ++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c +index e0b55cc566..ae966763a0 100644 +--- a/src/journal/journald-syslog.c ++++ b/src/journal/journald-syslog.c +@@ -223,8 +223,9 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) + if (p[e] != '\0' && strchr(WHITESPACE, p[e])) + e++; + ++ l = (p - *buf) + e; + *buf = p + e; +- return e; ++ return l; + } + + static void syslog_skip_date(char **buf) { +diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c +index 120477cc9f..415b9d23ca 100644 +--- a/src/journal/test-journal-syslog.c ++++ b/src/journal/test-journal-syslog.c +@@ -41,6 +41,8 @@ int main(void) { + test_syslog_parse_identifier(" ", NULL, NULL, " ", 0); + test_syslog_parse_identifier(":", "", NULL, "", 1); + test_syslog_parse_identifier(": ", "", NULL, " ", 2); ++ test_syslog_parse_identifier(" :", "", NULL, "", 2); ++ test_syslog_parse_identifier(" pidu:", "pidu", NULL, "", 8); + test_syslog_parse_identifier("pidu:", "pidu", NULL, "", 5); + test_syslog_parse_identifier("pidu: ", "pidu", NULL, "", 6); + test_syslog_parse_identifier("pidu : ", NULL, NULL, "pidu : ", 0); diff --git a/SOURCES/0266-Add-a-warning-about-the-difference-in-permissions-be.patch b/SOURCES/0266-Add-a-warning-about-the-difference-in-permissions-be.patch new file mode 100644 index 0000000..8b0bd5c --- /dev/null +++ b/SOURCES/0266-Add-a-warning-about-the-difference-in-permissions-be.patch @@ -0,0 +1,43 @@ +From 5df63c2ddf93bab5e7f13e09dfb1f97a011b3451 Mon Sep 17 00:00:00 2001 +From: Taro Yamada +Date: Sun, 27 Jan 2019 13:50:04 +0900 +Subject: [PATCH] Add a warning about the difference in permissions between + existing directories and unit settings. + +To follows the intent of 30c81ce, this change does not execute chmod() and just add warnings. + +(cherry picked from commit 6cff72eb0a18d8547f005a481cd0622d3bc78483) + +Related: #1778384 +--- + src/core/execute.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 8293c522bc..9ddba00421 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2099,8 +2099,21 @@ static int setup_exec_directory( + r = mkdir_label(p, context->directories[type].mode); + if (r < 0 && r != -EEXIST) + goto fail; +- if (r == -EEXIST && !context->dynamic_user) +- continue; ++ if (r == -EEXIST) { ++ struct stat st; ++ ++ if (stat(p, &st) < 0) { ++ r = -errno; ++ goto fail; ++ } ++ if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0) ++ log_warning("%s \'%s\' already exists but the mode is different. " ++ "(filesystem: %o %sMode: %o)", ++ exec_directory_type_to_string(type), *rt, ++ st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777); ++ if (!context->dynamic_user) ++ continue; ++ } + } + + /* Don't change the owner of the configuration directory, as in the common case it is not written to by diff --git a/SOURCES/0267-execute-remove-one-redundant-comparison-check.patch b/SOURCES/0267-execute-remove-one-redundant-comparison-check.patch new file mode 100644 index 0000000..8101159 --- /dev/null +++ b/SOURCES/0267-execute-remove-one-redundant-comparison-check.patch @@ -0,0 +1,32 @@ +From 81ca39b7b38ef1d44cc146efe75bef412e7c4c97 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 14 Mar 2019 17:01:46 +0100 +Subject: [PATCH] execute: remove one redundant comparison check + +(cherry picked from commit d484580ca6f0e79abe6f3f5c677323a22d9e22d7) + +Related: #1778384 +--- + src/core/execute.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 9ddba00421..46aa733937 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2097,11 +2097,12 @@ static int setup_exec_directory( + } + } else { + r = mkdir_label(p, context->directories[type].mode); +- if (r < 0 && r != -EEXIST) +- goto fail; +- if (r == -EEXIST) { ++ if (r < 0) { + struct stat st; + ++ if (r != -EEXIST) ++ goto fail; ++ + if (stat(p, &st) < 0) { + r = -errno; + goto fail; diff --git a/SOURCES/0268-core-change-ownership-mode-of-the-execution-director.patch b/SOURCES/0268-core-change-ownership-mode-of-the-execution-director.patch new file mode 100644 index 0000000..faaef74 --- /dev/null +++ b/SOURCES/0268-core-change-ownership-mode-of-the-execution-director.patch @@ -0,0 +1,88 @@ +From 789806ac06bb13d1b579fef47dbb85f224b6dbb1 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 14 Mar 2019 17:19:30 +0100 +Subject: [PATCH] core: change ownership/mode of the execution directories also + for static users + +It's probably unexpected if we do a recursive chown() when dynamic users +are used but not on static users. + +hence, let's tweak the logic slightly, and recursively chown in both +cases, except when operating on the configuration directory. + +Fixes: #11842 +(cherry picked from commit 206e9864de460dd79d9edd7bedb47dee168765e1) + +Resolves: #1778384 +--- + src/core/execute.c | 47 +++++++++++++++++++++++++--------------------- + 1 file changed, 26 insertions(+), 21 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 46aa733937..c42300a41e 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2090,37 +2090,42 @@ static int setup_exec_directory( + if (r < 0) + goto fail; + +- /* Lock down the access mode */ +- if (chmod(pp, context->directories[type].mode) < 0) { +- r = -errno; +- goto fail; +- } + } else { + r = mkdir_label(p, context->directories[type].mode); + if (r < 0) { +- struct stat st; +- + if (r != -EEXIST) + goto fail; + +- if (stat(p, &st) < 0) { +- r = -errno; +- goto fail; +- } +- if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0) +- log_warning("%s \'%s\' already exists but the mode is different. " +- "(filesystem: %o %sMode: %o)", +- exec_directory_type_to_string(type), *rt, +- st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777); +- if (!context->dynamic_user) ++ if (type == EXEC_DIRECTORY_CONFIGURATION) { ++ struct stat st; ++ ++ /* Don't change the owner/access mode of the configuration directory, ++ * as in the common case it is not written to by a service, and shall ++ * not be writable. */ ++ ++ if (stat(p, &st) < 0) { ++ r = -errno; ++ goto fail; ++ } ++ ++ /* Still complain if the access mode doesn't match */ ++ if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0) ++ log_warning("%s \'%s\' already exists but the mode is different. " ++ "(File system: %o %sMode: %o)", ++ exec_directory_type_to_string(type), *rt, ++ st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777); ++ + continue; ++ } + } + } + +- /* Don't change the owner of the configuration directory, as in the common case it is not written to by +- * a service, and shall not be writable. */ +- if (type == EXEC_DIRECTORY_CONFIGURATION) +- continue; ++ /* Lock down the access mode (we use chmod_and_chown() to make this idempotent. We don't ++ * specifiy UID/GID here, so that path_chown_recursive() can optimize things depending on the ++ * current UID/GID ownership.) */ ++ r = chmod_and_chown(pp ?: p, context->directories[type].mode, UID_INVALID, GID_INVALID); ++ if (r < 0) ++ goto fail; + + /* Then, change the ownership of the whole tree, if necessary */ + r = path_chown_recursive(pp ?: p, uid, gid); diff --git a/SOURCES/0269-core-dbus-execute-remove-unnecessary-initialization.patch b/SOURCES/0269-core-dbus-execute-remove-unnecessary-initialization.patch new file mode 100644 index 0000000..e46f256 --- /dev/null +++ b/SOURCES/0269-core-dbus-execute-remove-unnecessary-initialization.patch @@ -0,0 +1,25 @@ +From 5d7e8cb0e12e4642a760cf00cbb6caf4c07b9cd9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 19 May 2019 16:05:02 +0200 +Subject: [PATCH] core/dbus-execute: remove unnecessary initialization + +(cherry picked from commit bd0abfaea1514bdd7cb60228d7a3f94c17ba916d) + +Related: #1734787 +--- + src/core/dbus-execute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 33a91c012e..5379545d57 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1552,7 +1552,7 @@ int bus_exec_context_set_transient_property( + #endif + if (streq(name, "CPUAffinity")) { + const void *a; +- size_t n = 0; ++ size_t n; + + r = sd_bus_message_read_array(message, 'y', &a, &n); + if (r < 0) diff --git a/SOURCES/0270-shared-cpu-set-util-move-the-part-to-print-cpu-set-i.patch b/SOURCES/0270-shared-cpu-set-util-move-the-part-to-print-cpu-set-i.patch new file mode 100644 index 0000000..5babb33 --- /dev/null +++ b/SOURCES/0270-shared-cpu-set-util-move-the-part-to-print-cpu-set-i.patch @@ -0,0 +1,215 @@ +From 46b4d26c54a773f7da350e89562039ccc5157a8f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 19 May 2019 18:02:38 +0200 +Subject: [PATCH] shared/cpu-set-util: move the part to print cpu-set into a + separate function + +Also avoid unnecessary asprintf() when we can write to the output area +directly. + +(cherry picked from commit a832893f9c4f0a0329768e90f67e2fa24bb0008e) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 21 +++++++++++++++++++++ + src/basic/cpu-set-util.h | 1 + + src/core/dbus-execute.c | 29 +++++------------------------ + src/test/test-cpu-set-util.c | 29 +++++++++++++++++++++++++++++ + 4 files changed, 56 insertions(+), 24 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index b1c927bcb8..8f24a2601a 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + #include + + #include "alloc-util.h" +@@ -15,6 +16,26 @@ + #include "parse-util.h" + #include "string-util.h" + ++char* cpu_set_to_string(const cpu_set_t *set, size_t setsize) { ++ _cleanup_free_ char *str = NULL; ++ size_t allocated = 0, len = 0; ++ int i, r; ++ ++ for (i = 0; (size_t) i < setsize * 8; i++) { ++ if (!CPU_ISSET_S(i, setsize, set)) ++ continue; ++ ++ if (!GREEDY_REALLOC(str, allocated, len + 1 + DECIMAL_STR_MAX(int))) ++ return NULL; ++ ++ r = sprintf(str + len, len > 0 ? " %d" : "%d", i); ++ assert_se(r > 0); ++ len += r; ++ } ++ ++ return TAKE_PTR(str) ?: strdup(""); ++} ++ + cpu_set_t* cpu_set_malloc(unsigned *ncpus) { + cpu_set_t *c; + unsigned n = 1024; +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index 88470fe15a..3c546beb55 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -26,6 +26,7 @@ static inline cpu_set_t* cpu_set_mfree(cpu_set_t *p) { + + cpu_set_t* cpu_set_malloc(unsigned *ncpus); + ++char* cpu_set_to_string(const cpu_set_t *set, size_t setsize); + int parse_cpu_set_internal(const char *rvalue, cpu_set_t **cpu_set, bool warn, const char *unit, const char *filename, unsigned line, const char *lvalue); + + static inline int parse_cpu_set_and_warn(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue) { +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 5379545d57..d9f4445745 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1565,32 +1565,13 @@ int bus_exec_context_set_transient_property( + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *str = NULL; +- size_t allocated = 0, len = 0, i, ncpus; ++ size_t ncpus; + +- ncpus = CPU_SIZE_TO_NUM(n); +- +- for (i = 0; i < ncpus; i++) { +- _cleanup_free_ char *p = NULL; +- size_t add; +- +- if (!CPU_ISSET_S(i, n, (cpu_set_t*) a)) +- continue; +- +- r = asprintf(&p, "%zu", i); +- if (r < 0) +- return -ENOMEM; +- +- add = strlen(p); +- +- if (!GREEDY_REALLOC(str, allocated, len + add + 2)) +- return -ENOMEM; +- +- strcpy(mempcpy(str + len, p, add), " "); +- len += add + 1; +- } ++ str = cpu_set_to_string(a, n); ++ if (!str) ++ return -ENOMEM; + +- if (len != 0) +- str[len - 1] = '\0'; ++ ncpus = CPU_SIZE_TO_NUM(n); + + if (!c->cpuset || c->cpuset_ncpus < ncpus) { + cpu_set_t *cpuset; +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index c9272459b4..ff5edb2a69 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -6,6 +6,7 @@ + + static void test_parse_cpu_set(void) { + cpu_set_t *c = NULL; ++ _cleanup_free_ char *str = NULL; + int ncpus; + int cpu; + +@@ -15,6 +16,10 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c)); + assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c)); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2); ++ ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* A more interesting range */ +@@ -25,6 +30,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Quoted strings */ +@@ -33,6 +41,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Use commas as separators */ +@@ -43,6 +54,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Commas with spaces (and trailing comma, space) */ +@@ -51,6 +65,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); + for (cpu = 0; cpu < 8; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Ranges */ +@@ -61,6 +78,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Ranges with trailing comma, space */ +@@ -71,6 +91,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Negative range (returns empty cpu_set) */ +@@ -85,6 +108,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12); + for (cpu = 0; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Mix ranges and individual CPUs */ +@@ -95,6 +121,9 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 4; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); + c = cpu_set_mfree(c); + + /* Garbage */ diff --git a/SOURCES/0271-shared-cpu-set-util-remove-now-unused-CPU_SIZE_TO_NU.patch b/SOURCES/0271-shared-cpu-set-util-remove-now-unused-CPU_SIZE_TO_NU.patch new file mode 100644 index 0000000..8d393c5 --- /dev/null +++ b/SOURCES/0271-shared-cpu-set-util-remove-now-unused-CPU_SIZE_TO_NU.patch @@ -0,0 +1,29 @@ +From d6935e61de30967aa82b7722f36193ba782b75e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 19 May 2019 18:08:39 +0200 +Subject: [PATCH] shared/cpu-set-util: remove now-unused CPU_SIZE_TO_NUM() + +(cherry picked from commit b12ef7141648be40fd8c4b0209a742f2151736d9) + +Related: #1734787 +--- + src/basic/cpu-set-util.h | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index 3c546beb55..20612a8876 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -9,12 +9,6 @@ + + #include "macro.h" + +-#ifdef __NCPUBITS +-#define CPU_SIZE_TO_NUM(n) ((n) * __NCPUBITS) +-#else +-#define CPU_SIZE_TO_NUM(n) ((n) * sizeof(cpu_set_t) * 8) +-#endif +- + DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE); + #define _cleanup_cpu_free_ _cleanup_(CPU_FREEp) + diff --git a/SOURCES/0272-Rework-cpu-affinity-parsing.patch b/SOURCES/0272-Rework-cpu-affinity-parsing.patch new file mode 100644 index 0000000..f6001e5 --- /dev/null +++ b/SOURCES/0272-Rework-cpu-affinity-parsing.patch @@ -0,0 +1,932 @@ +From 61e5aed87f1b82a51c6ea8ccde96805cb63e5b15 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 21 May 2019 08:45:19 +0200 +Subject: [PATCH] Rework cpu affinity parsing + +The CPU_SET_S api is pretty bad. In particular, it has a parameter for the size +of the array, but operations which take two (CPU_EQUAL_S) or even three arrays +(CPU_{AND,OR,XOR}_S) still take just one size. This means that all arrays must +be of the same size, or buffer overruns will occur. This is exactly what our +code would do, if it received an array of unexpected size over the network. +("Unexpected" here means anything different from what cpu_set_malloc() detects +as the "right" size.) + +Let's rework this, and store the size in bytes of the allocated storage area. + +The code will now parse any number up to 8191, independently of what the current +kernel supports. This matches the kernel maximum setting for any architecture, +to make things more portable. + +Fixes #12605. + +(cherry picked from commit 0985c7c4e22c8dbbea4398cf3453da45ebf63800) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 133 +++++++++++++++++++++----- + src/basic/cpu-set-util.h | 47 ++++++--- + src/core/dbus-execute.c | 35 ++----- + src/core/execute.c | 12 +-- + src/core/execute.h | 4 +- + src/core/load-fragment.c | 31 +----- + src/core/main.c | 14 +-- + src/nspawn/nspawn-settings.c | 33 +------ + src/nspawn/nspawn-settings.h | 4 +- + src/nspawn/nspawn.c | 29 +++--- + src/shared/bus-unit-util.c | 4 +- + src/test/test-cpu-set-util.c | 179 +++++++++++++++++++---------------- + src/test/test-sizeof.c | 3 + + 13 files changed, 286 insertions(+), 242 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index 8f24a2601a..fe440f6381 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -15,14 +15,15 @@ + #include "macro.h" + #include "parse-util.h" + #include "string-util.h" ++#include "util.h" + +-char* cpu_set_to_string(const cpu_set_t *set, size_t setsize) { ++char* cpu_set_to_string(const CPUSet *a) { + _cleanup_free_ char *str = NULL; + size_t allocated = 0, len = 0; + int i, r; + +- for (i = 0; (size_t) i < setsize * 8; i++) { +- if (!CPU_ISSET_S(i, setsize, set)) ++ for (i = 0; (size_t) i < a->allocated * 8; i++) { ++ if (!CPU_ISSET_S(i, a->allocated, a->set)) + continue; + + if (!GREEDY_REALLOC(str, allocated, len + 1 + DECIMAL_STR_MAX(int))) +@@ -65,24 +66,74 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) { + } + } + +-int parse_cpu_set_internal( ++static int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { ++ size_t need; ++ ++ assert(cpu_set); ++ ++ need = CPU_ALLOC_SIZE(ncpus); ++ if (need > cpu_set->allocated) { ++ cpu_set_t *t; ++ ++ t = realloc(cpu_set->set, need); ++ if (!t) ++ return -ENOMEM; ++ ++ memzero((uint8_t*) t + cpu_set->allocated, need - cpu_set->allocated); ++ ++ cpu_set->set = t; ++ cpu_set->allocated = need; ++ } ++ ++ return 0; ++} ++ ++static int cpu_set_add(CPUSet *cpu_set, unsigned cpu) { ++ int r; ++ ++ if (cpu >= 8192) ++ /* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */ ++ return -ERANGE; ++ ++ r = cpu_set_realloc(cpu_set, cpu + 1); ++ if (r < 0) ++ return r; ++ ++ CPU_SET_S(cpu, cpu_set->allocated, cpu_set->set); ++ return 0; ++} ++ ++int cpu_set_add_all(CPUSet *a, const CPUSet *b) { ++ int r; ++ ++ /* Do this backwards, so if we fail, we fail before changing anything. */ ++ for (unsigned cpu_p1 = b->allocated * 8; cpu_p1 > 0; cpu_p1--) ++ if (CPU_ISSET_S(cpu_p1 - 1, b->allocated, b->set)) { ++ r = cpu_set_add(a, cpu_p1 - 1); ++ if (r < 0) ++ return r; ++ } ++ ++ return 0; ++} ++ ++int parse_cpu_set_full( + const char *rvalue, +- cpu_set_t **cpu_set, ++ CPUSet *cpu_set, + bool warn, + const char *unit, + const char *filename, + unsigned line, + const char *lvalue) { + +- _cleanup_cpu_free_ cpu_set_t *c = NULL; ++ _cleanup_(cpu_set_reset) CPUSet c = {}; + const char *p = rvalue; +- unsigned ncpus = 0; + +- assert(rvalue); ++ assert(p); + + for (;;) { + _cleanup_free_ char *word = NULL; +- unsigned cpu, cpu_lower, cpu_upper; ++ unsigned cpu_lower, cpu_upper; + int r; + + r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_QUOTES); +@@ -93,31 +144,63 @@ int parse_cpu_set_internal( + if (r == 0) + break; + +- if (!c) { +- c = cpu_set_malloc(&ncpus); +- if (!c) +- return warn ? log_oom() : -ENOMEM; +- } +- + r = parse_range(word, &cpu_lower, &cpu_upper); + if (r < 0) + return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word) : r; +- if (cpu_lower >= ncpus || cpu_upper >= ncpus) +- return warn ? log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus) : -EINVAL; + + if (cpu_lower > cpu_upper) { + if (warn) +- log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring", word, cpu_lower, cpu_upper); +- continue; ++ log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring.", ++ word, cpu_lower, cpu_upper); ++ ++ /* Make sure something is allocated, to distinguish this from the empty case */ ++ r = cpu_set_realloc(&c, 1); ++ if (r < 0) ++ return r; + } + +- for (cpu = cpu_lower; cpu <= cpu_upper; cpu++) +- CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c); ++ for (unsigned cpu_p1 = MIN(cpu_upper, UINT_MAX-1) + 1; cpu_p1 > cpu_lower; cpu_p1--) { ++ r = cpu_set_add(&c, cpu_p1 - 1); ++ if (r < 0) ++ return warn ? log_syntax(unit, LOG_ERR, filename, line, r, ++ "Cannot add CPU %u to set: %m", cpu_p1 - 1) : r; ++ } + } + +- /* On success, sets *cpu_set and returns ncpus for the system. */ +- if (c) +- *cpu_set = TAKE_PTR(c); ++ /* On success, transfer ownership to the output variable */ ++ *cpu_set = c; ++ c = (CPUSet) {}; ++ ++ return 0; ++} ++ ++int parse_cpu_set_extend( ++ const char *rvalue, ++ CPUSet *old, ++ bool warn, ++ const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *lvalue) { ++ ++ _cleanup_(cpu_set_reset) CPUSet cpuset = {}; ++ int r; ++ ++ r = parse_cpu_set_full(rvalue, &cpuset, true, unit, filename, line, lvalue); ++ if (r < 0) ++ return r; ++ ++ if (!cpuset.set) { ++ /* An empty assignment resets the CPU list */ ++ cpu_set_reset(old); ++ return 0; ++ } ++ ++ if (!old->set) { ++ *old = cpuset; ++ cpuset = (CPUSet) {}; ++ return 0; ++ } + +- return (int) ncpus; ++ return cpu_set_add_all(old, &cpuset); + } +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index 20612a8876..eb31b362fe 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -12,23 +12,40 @@ + DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE); + #define _cleanup_cpu_free_ _cleanup_(CPU_FREEp) + +-static inline cpu_set_t* cpu_set_mfree(cpu_set_t *p) { +- if (p) +- CPU_FREE(p); +- return NULL; +-} +- + cpu_set_t* cpu_set_malloc(unsigned *ncpus); + +-char* cpu_set_to_string(const cpu_set_t *set, size_t setsize); +-int parse_cpu_set_internal(const char *rvalue, cpu_set_t **cpu_set, bool warn, const char *unit, const char *filename, unsigned line, const char *lvalue); +- +-static inline int parse_cpu_set_and_warn(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue) { +- assert(lvalue); +- +- return parse_cpu_set_internal(rvalue, cpu_set, true, unit, filename, line, lvalue); ++/* This wraps the libc interface with a variable to keep the allocated size. */ ++typedef struct CPUSet { ++ cpu_set_t *set; ++ size_t allocated; /* in bytes */ ++} CPUSet; ++ ++static inline void cpu_set_reset(CPUSet *a) { ++ assert((a->allocated > 0) == !!a->set); ++ if (a->set) ++ CPU_FREE(a->set); ++ *a = (CPUSet) {}; + } + +-static inline int parse_cpu_set(const char *rvalue, cpu_set_t **cpu_set){ +- return parse_cpu_set_internal(rvalue, cpu_set, false, NULL, NULL, 0, NULL); ++int cpu_set_add_all(CPUSet *a, const CPUSet *b); ++ ++char* cpu_set_to_string(const CPUSet *a); ++int parse_cpu_set_full( ++ const char *rvalue, ++ CPUSet *cpu_set, ++ bool warn, ++ const char *unit, ++ const char *filename, unsigned line, ++ const char *lvalue); ++int parse_cpu_set_extend( ++ const char *rvalue, ++ CPUSet *old, ++ bool warn, ++ const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *lvalue); ++ ++static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){ ++ return parse_cpu_set_full(rvalue, cpu_set, false, NULL, NULL, 0, NULL); + } +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index d9f4445745..08946627e3 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -220,7 +220,7 @@ static int property_get_cpu_affinity( + assert(reply); + assert(c); + +- return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus)); ++ return sd_bus_message_append_array(reply, 'y', c->cpu_set.set, c->cpu_set.allocated); + } + + static int property_get_timer_slack_nsec( +@@ -1560,37 +1560,22 @@ int bus_exec_context_set_transient_property( + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (n == 0) { +- c->cpuset = cpu_set_mfree(c->cpuset); +- c->cpuset_ncpus = 0; ++ cpu_set_reset(&c->cpu_set); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *str = NULL; +- size_t ncpus; ++ const CPUSet set = {(cpu_set_t*) a, n}; + +- str = cpu_set_to_string(a, n); ++ str = cpu_set_to_string(&set); + if (!str) + return -ENOMEM; + +- ncpus = CPU_SIZE_TO_NUM(n); +- +- if (!c->cpuset || c->cpuset_ncpus < ncpus) { +- cpu_set_t *cpuset; +- +- cpuset = CPU_ALLOC(ncpus); +- if (!cpuset) +- return -ENOMEM; +- +- CPU_ZERO_S(n, cpuset); +- if (c->cpuset) { +- CPU_OR_S(CPU_ALLOC_SIZE(c->cpuset_ncpus), cpuset, c->cpuset, (cpu_set_t*) a); +- CPU_FREE(c->cpuset); +- } else +- CPU_OR_S(n, cpuset, cpuset, (cpu_set_t*) a); +- +- c->cpuset = cpuset; +- c->cpuset_ncpus = ncpus; +- } else +- CPU_OR_S(n, c->cpuset, c->cpuset, (cpu_set_t*) a); ++ /* We forego any optimizations here, and always create the structure using ++ * cpu_set_add_all(), because we don't want to care if the existing size we ++ * got over dbus is appropriate. */ ++ r = cpu_set_add_all(&c->cpu_set, &set); ++ if (r < 0) ++ return r; + + unit_write_settingf(u, flags, name, "%s=%s", name, str); + } +diff --git a/src/core/execute.c b/src/core/execute.c +index c42300a41e..22e5825905 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2991,8 +2991,8 @@ static int exec_child( + } + } + +- if (context->cpuset) +- if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) { ++ if (context->cpu_set.set) ++ if (sched_setaffinity(0, context->cpu_set.allocated, context->cpu_set.set) < 0) { + *exit_status = EXIT_CPUAFFINITY; + return log_unit_error_errno(unit, errno, "Failed to set up CPU affinity: %m"); + } +@@ -3694,7 +3694,7 @@ void exec_context_done(ExecContext *c) { + c->temporary_filesystems = NULL; + c->n_temporary_filesystems = 0; + +- c->cpuset = cpu_set_mfree(c->cpuset); ++ cpu_set_reset(&c->cpu_set); + + c->utmp_id = mfree(c->utmp_id); + c->selinux_context = mfree(c->selinux_context); +@@ -4097,10 +4097,10 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { + prefix, yes_no(c->cpu_sched_reset_on_fork)); + } + +- if (c->cpuset) { ++ if (c->cpu_set.set) { + fprintf(f, "%sCPUAffinity:", prefix); +- for (i = 0; i < c->cpuset_ncpus; i++) +- if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset)) ++ for (i = 0; i < c->cpu_set.allocated * 8; i++) ++ if (CPU_ISSET_S(i, c->cpu_set.allocated, c->cpu_set.set)) + fprintf(f, " %u", i); + fputs("\n", f); + } +diff --git a/src/core/execute.h b/src/core/execute.h +index 8c91636adc..e1e7a494cd 100644 +--- a/src/core/execute.h ++++ b/src/core/execute.h +@@ -14,6 +14,7 @@ typedef struct Manager Manager; + #include + + #include "cgroup-util.h" ++#include "cpu-set-util.h" + #include "fdset.h" + #include "list.h" + #include "missing.h" +@@ -148,8 +149,7 @@ struct ExecContext { + int cpu_sched_policy; + int cpu_sched_priority; + +- cpu_set_t *cpuset; +- unsigned cpuset_ncpus; ++ CPUSet cpu_set; + + ExecInput std_input; + ExecOutput std_output; +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index d9a5094aa0..34ae834188 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -1211,42 +1211,13 @@ int config_parse_exec_cpu_affinity(const char *unit, + void *userdata) { + + ExecContext *c = data; +- _cleanup_cpu_free_ cpu_set_t *cpuset = NULL; +- int ncpus; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + +- ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue); +- if (ncpus < 0) +- return ncpus; +- +- if (ncpus == 0) { +- /* An empty assignment resets the CPU list */ +- c->cpuset = cpu_set_mfree(c->cpuset); +- c->cpuset_ncpus = 0; +- return 0; +- } +- +- if (!c->cpuset) { +- c->cpuset = TAKE_PTR(cpuset); +- c->cpuset_ncpus = (unsigned) ncpus; +- return 0; +- } +- +- if (c->cpuset_ncpus < (unsigned) ncpus) { +- CPU_OR_S(CPU_ALLOC_SIZE(c->cpuset_ncpus), cpuset, c->cpuset, cpuset); +- CPU_FREE(c->cpuset); +- c->cpuset = TAKE_PTR(cpuset); +- c->cpuset_ncpus = (unsigned) ncpus; +- return 0; +- } +- +- CPU_OR_S(CPU_ALLOC_SIZE((unsigned) ncpus), c->cpuset, c->cpuset, cpuset); +- +- return 0; ++ return parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue); + } + + int config_parse_capability_set( +diff --git a/src/core/main.c b/src/core/main.c +index af7b26d6f1..e62b2756ee 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -537,16 +537,18 @@ static int config_parse_cpu_affinity2( + void *data, + void *userdata) { + +- _cleanup_cpu_free_ cpu_set_t *c = NULL; +- int ncpus; ++ _cleanup_(cpu_set_reset) CPUSet c = {}; ++ int r; + +- ncpus = parse_cpu_set_and_warn(rvalue, &c, unit, filename, line, lvalue); +- if (ncpus < 0) +- return ncpus; ++ r = parse_cpu_set_full(rvalue, &c, true, unit, filename, line, lvalue); ++ if (r < 0) ++ return r; + +- if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0) ++ if (sched_setaffinity(0, c.allocated, c.set) < 0) + log_warning_errno(errno, "Failed to set CPU affinity: %m"); + ++ // FIXME: parsing and execution should be seperated. ++ + return 0; + } + +diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c +index 62a3486952..21c24a1111 100644 +--- a/src/nspawn/nspawn-settings.c ++++ b/src/nspawn/nspawn-settings.c +@@ -85,7 +85,7 @@ Settings* settings_free(Settings *s) { + strv_free(s->syscall_blacklist); + rlimit_free_all(s->rlimit); + free(s->hostname); +- s->cpuset = cpu_set_mfree(s->cpuset); ++ cpu_set_reset(&s->cpu_set); + + strv_free(s->network_interfaces); + strv_free(s->network_macvlan); +@@ -687,41 +687,12 @@ int config_parse_cpu_affinity( + void *data, + void *userdata) { + +- _cleanup_cpu_free_ cpu_set_t *cpuset = NULL; + Settings *settings = data; +- int ncpus; + + assert(rvalue); + assert(settings); + +- ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue); +- if (ncpus < 0) +- return ncpus; +- +- if (ncpus == 0) { +- /* An empty assignment resets the CPU list */ +- settings->cpuset = cpu_set_mfree(settings->cpuset); +- settings->cpuset_ncpus = 0; +- return 0; +- } +- +- if (!settings->cpuset) { +- settings->cpuset = TAKE_PTR(cpuset); +- settings->cpuset_ncpus = (unsigned) ncpus; +- return 0; +- } +- +- if (settings->cpuset_ncpus < (unsigned) ncpus) { +- CPU_OR_S(CPU_ALLOC_SIZE(settings->cpuset_ncpus), cpuset, settings->cpuset, cpuset); +- CPU_FREE(settings->cpuset); +- settings->cpuset = TAKE_PTR(cpuset); +- settings->cpuset_ncpus = (unsigned) ncpus; +- return 0; +- } +- +- CPU_OR_S(CPU_ALLOC_SIZE((unsigned) ncpus), settings->cpuset, settings->cpuset, cpuset); +- +- return 0; ++ return parse_cpu_set_extend(rvalue, &settings->cpu_set, true, unit, filename, line, lvalue); + } + + DEFINE_CONFIG_PARSE_ENUM(config_parse_resolv_conf, resolv_conf_mode, ResolvConfMode, "Failed to parse resolv.conf mode"); +diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h +index d522f3cb36..da863ef11c 100644 +--- a/src/nspawn/nspawn-settings.h ++++ b/src/nspawn/nspawn-settings.h +@@ -7,6 +7,7 @@ + #include "sd-id128.h" + + #include "conf-parser.h" ++#include "cpu-set-util.h" + #include "macro.h" + #include "nspawn-expose-ports.h" + #include "nspawn-mount.h" +@@ -123,8 +124,7 @@ typedef struct Settings { + int no_new_privileges; + int oom_score_adjust; + bool oom_score_adjust_set; +- cpu_set_t *cpuset; +- unsigned cpuset_ncpus; ++ CPUSet cpu_set; + ResolvConfMode resolv_conf; + LinkJournal link_journal; + bool link_journal_try; +diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c +index b40411dcd0..08255b5724 100644 +--- a/src/nspawn/nspawn.c ++++ b/src/nspawn/nspawn.c +@@ -199,8 +199,7 @@ static struct rlimit *arg_rlimit[_RLIMIT_MAX] = {}; + static bool arg_no_new_privileges = false; + static int arg_oom_score_adjust = 0; + static bool arg_oom_score_adjust_set = false; +-static cpu_set_t *arg_cpuset = NULL; +-static unsigned arg_cpuset_ncpus = 0; ++static CPUSet arg_cpu_set = {}; + static ResolvConfMode arg_resolv_conf = RESOLV_CONF_AUTO; + static TimezoneMode arg_timezone = TIMEZONE_AUTO; + +@@ -1186,17 +1185,14 @@ static int parse_argv(int argc, char *argv[]) { + break; + + case ARG_CPU_AFFINITY: { +- _cleanup_cpu_free_ cpu_set_t *cpuset = NULL; ++ CPUSet cpuset; + + r = parse_cpu_set(optarg, &cpuset); + if (r < 0) +- return log_error_errno(r, "Failed to parse CPU affinity mask: %s", optarg); ++ return log_error_errno(r, "Failed to parse CPU affinity mask %s: %m", optarg); + +- if (arg_cpuset) +- CPU_FREE(arg_cpuset); +- +- arg_cpuset = TAKE_PTR(cpuset); +- arg_cpuset_ncpus = r; ++ cpu_set_reset(&arg_cpu_set); ++ arg_cpu_set = cpuset; + arg_settings_mask |= SETTING_CPU_AFFINITY; + break; + } +@@ -2631,8 +2627,8 @@ static int inner_child( + return log_error_errno(r, "Failed to adjust OOM score: %m"); + } + +- if (arg_cpuset) +- if (sched_setaffinity(0, CPU_ALLOC_SIZE(arg_cpuset_ncpus), arg_cpuset) < 0) ++ if (arg_cpu_set.set) ++ if (sched_setaffinity(0, arg_cpu_set.allocated, arg_cpu_set.set) < 0) + return log_error_errno(errno, "Failed to set CPU affinity: %m"); + + r = drop_capabilities(); +@@ -3494,15 +3490,14 @@ static int merge_settings(Settings *settings, const char *path) { + } + + if ((arg_settings_mask & SETTING_CPU_AFFINITY) == 0 && +- settings->cpuset) { ++ settings->cpu_set.set) { + + if (!arg_settings_trusted) + log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", path); + else { +- if (arg_cpuset) +- CPU_FREE(arg_cpuset); +- arg_cpuset = TAKE_PTR(settings->cpuset); +- arg_cpuset_ncpus = settings->cpuset_ncpus; ++ cpu_set_reset(&arg_cpu_set); ++ arg_cpu_set = settings->cpu_set; ++ settings->cpu_set = (CPUSet) {}; + } + } + +@@ -4600,7 +4595,7 @@ finish: + rlimit_free_all(arg_rlimit); + strv_free(arg_syscall_whitelist); + strv_free(arg_syscall_blacklist); +- arg_cpuset = cpu_set_mfree(arg_cpuset); ++ cpu_set_reset(&arg_cpu_set); + + return r < 0 ? EXIT_FAILURE : ret; + } +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 271cc054da..75b4aace84 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -932,13 +932,13 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con + } + + if (streq(field, "CPUAffinity")) { +- _cleanup_cpu_free_ cpu_set_t *cpuset = NULL; ++ _cleanup_(cpu_set_reset) CPUSet cpuset = {}; + + r = parse_cpu_set(eq, &cpuset); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value: %s", field, eq); + +- return bus_append_byte_array(m, field, cpuset, CPU_ALLOC_SIZE(r)); ++ return bus_append_byte_array(m, field, cpuset.set, cpuset.allocated); + } + + if (STR_IN_SET(field, "RestrictAddressFamilies", "SystemCallFilter")) { +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index ff5edb2a69..b9ec29af66 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -1,154 +1,171 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + ++#include ++ + #include "alloc-util.h" + #include "cpu-set-util.h" + #include "macro.h" + + static void test_parse_cpu_set(void) { +- cpu_set_t *c = NULL; ++ CPUSet c = {}; + _cleanup_free_ char *str = NULL; +- int ncpus; + int cpu; + + /* Simple range (from CPUAffinity example) */ +- ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2); +- +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(parse_cpu_set_full("1 2", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.set); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_ISSET_S(1, c.allocated, c.set)); ++ assert_se(CPU_ISSET_S(2, c.allocated, c.set)); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 2); ++ ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* A more interesting range */ +- ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); ++ assert_se(parse_cpu_set_full("0 1 2 3 8 9 10 11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Quoted strings */ +- ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4); ++ assert_se(parse_cpu_set_full("8 '9' 10 \"11\"", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 4); + for (cpu = 8; cpu < 12; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Use commas as separators */ +- ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); ++ assert_se(parse_cpu_set_full("0,1,2,3 8,9,10,11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Commas with spaces (and trailing comma, space) */ +- ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); ++ assert_se(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 8; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Ranges */ +- ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); ++ assert_se(parse_cpu_set_full("0-3,8-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Ranges with trailing comma, space */ +- ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); ++ assert_se(parse_cpu_set_full("0-3 8-11, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Negative range (returns empty cpu_set) */ +- ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0); +- c = cpu_set_mfree(c); ++ assert_se(parse_cpu_set_full("3-0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 0); ++ cpu_set_reset(&c); + + /* Overlapping ranges */ +- ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12); ++ assert_se(parse_cpu_set_full("0-7 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 12); + for (cpu = 0; cpu < 12; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Mix ranges and individual CPUs */ +- ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus >= 1024); +- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10); +- assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c)); ++ assert_se(parse_cpu_set_full("0,1 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 10); ++ assert_se(CPU_ISSET_S(0, c.allocated, c.set)); ++ assert_se(CPU_ISSET_S(1, c.allocated, c.set)); + for (cpu = 4; cpu < 12; cpu++) +- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); +- assert_se(str = cpu_set_to_string(c, CPU_ALLOC_SIZE(ncpus))); ++ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); +- c = cpu_set_mfree(c); ++ cpu_set_reset(&c); + + /* Garbage */ +- ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus < 0); +- assert_se(!c); ++ assert_se(parse_cpu_set_full("0 1 2 3 garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL); ++ assert_se(!c.set); ++ assert_se(c.allocated == 0); + + /* Range with garbage */ +- ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus < 0); +- assert_se(!c); ++ assert_se(parse_cpu_set_full("0-3 8-garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL); ++ assert_se(!c.set); ++ assert_se(c.allocated == 0); + + /* Empty string */ +- c = NULL; +- ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus == 0); /* empty string returns 0 */ +- assert_se(!c); ++ assert_se(parse_cpu_set_full("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); ++ assert_se(!c.set); /* empty string returns NULL */ ++ assert_se(c.allocated == 0); + + /* Runaway quoted string */ +- ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity"); +- assert_se(ncpus < 0); +- assert_se(!c); ++ assert_se(parse_cpu_set_full("0 1 2 3 \"4 5 6 7 ", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL); ++ assert_se(!c.set); ++ assert_se(c.allocated == 0); ++ ++ /* Maximum allocation */ ++ assert_se(parse_cpu_set_full("8000-8191", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 192); ++ assert_se(str = cpu_set_to_string(&c)); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); ++ cpu_set_reset(&c); + } + + int main(int argc, char *argv[]) { ++ log_info("CPU_ALLOC_SIZE(1) = %zu", CPU_ALLOC_SIZE(1)); ++ log_info("CPU_ALLOC_SIZE(9) = %zu", CPU_ALLOC_SIZE(9)); ++ log_info("CPU_ALLOC_SIZE(64) = %zu", CPU_ALLOC_SIZE(64)); ++ log_info("CPU_ALLOC_SIZE(65) = %zu", CPU_ALLOC_SIZE(65)); ++ log_info("CPU_ALLOC_SIZE(1024) = %zu", CPU_ALLOC_SIZE(1024)); ++ log_info("CPU_ALLOC_SIZE(1025) = %zu", CPU_ALLOC_SIZE(1025)); ++ log_info("CPU_ALLOC_SIZE(8191) = %zu", CPU_ALLOC_SIZE(8191)); ++ + test_parse_cpu_set(); + + return 0; +diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c +index 7a1e496ed2..396e68f35f 100644 +--- a/src/test/test-sizeof.c ++++ b/src/test/test-sizeof.c +@@ -1,5 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + ++#include + #include + #include + +@@ -64,6 +65,8 @@ int main(void) { + info(uid_t); + info(gid_t); + ++ info(__cpu_mask); ++ + info(enum Enum); + info(enum BigEnum); + info(enum BigEnum2); diff --git a/SOURCES/0273-Move-cpus_in_affinity_mask-to-cpu-set-util.-ch.patch b/SOURCES/0273-Move-cpus_in_affinity_mask-to-cpu-set-util.-ch.patch new file mode 100644 index 0000000..43f5d04 --- /dev/null +++ b/SOURCES/0273-Move-cpus_in_affinity_mask-to-cpu-set-util.-ch.patch @@ -0,0 +1,125 @@ +From 42032749e61076b3d9e5004432073c2a5ea737ce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 28 May 2019 21:28:31 +0200 +Subject: [PATCH] Move cpus_in_affinity_mask() to cpu-set-util.[ch] + +It just seems to fit better there and it's always better to have things +in shared/ rather than basic/. + +(cherry picked from commit f44b3035d4a698aa0ce08a552199b54d43de3d85) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 34 ++++++++++++++++++++++++++++++++++ + src/basic/cpu-set-util.h | 2 ++ + src/basic/process-util.c | 5 ++--- + src/shared/condition.c | 1 + + src/test/test-condition.c | 1 + + 5 files changed, 40 insertions(+), 3 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index fe440f6381..1803539ac6 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -204,3 +204,37 @@ int parse_cpu_set_extend( + + return cpu_set_add_all(old, &cpuset); + } ++ ++int cpus_in_affinity_mask(void) { ++ size_t n = 16; ++ int r; ++ ++ for (;;) { ++ cpu_set_t *c; ++ ++ c = CPU_ALLOC(n); ++ if (!c) ++ return -ENOMEM; ++ ++ if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) { ++ int k; ++ ++ k = CPU_COUNT_S(CPU_ALLOC_SIZE(n), c); ++ CPU_FREE(c); ++ ++ if (k <= 0) ++ return -EINVAL; ++ ++ return k; ++ } ++ ++ r = -errno; ++ CPU_FREE(c); ++ ++ if (r != -EINVAL) ++ return r; ++ if (n > SIZE_MAX/2) ++ return -ENOMEM; ++ n *= 2; ++ } ++} +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index eb31b362fe..9b026aca09 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -49,3 +49,5 @@ int parse_cpu_set_extend( + static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){ + return parse_cpu_set_full(rvalue, cpu_set, false, NULL, NULL, 0, NULL); + } ++ ++int cpus_in_affinity_mask(void); +diff --git a/src/basic/process-util.c b/src/basic/process-util.c +index 6dbeee9dda..0a4a747ba4 100644 +--- a/src/basic/process-util.c ++++ b/src/basic/process-util.c +@@ -4,7 +4,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -1474,7 +1473,7 @@ static const char *const ioprio_class_table[] = { + [IOPRIO_CLASS_NONE] = "none", + [IOPRIO_CLASS_RT] = "realtime", + [IOPRIO_CLASS_BE] = "best-effort", +- [IOPRIO_CLASS_IDLE] = "idle" ++ [IOPRIO_CLASS_IDLE] = "idle", + }; + + DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES); +@@ -1495,7 +1494,7 @@ static const char* const sched_policy_table[] = { + [SCHED_BATCH] = "batch", + [SCHED_IDLE] = "idle", + [SCHED_FIFO] = "fifo", +- [SCHED_RR] = "rr" ++ [SCHED_RR] = "rr", + }; + + DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX); +diff --git a/src/shared/condition.c b/src/shared/condition.c +index 2969a89b4e..b829f0528c 100644 +--- a/src/shared/condition.c ++++ b/src/shared/condition.c +@@ -21,6 +21,7 @@ + #include "cap-list.h" + #include "cgroup-util.h" + #include "condition.h" ++#include "cpu-set-util.h" + #include "efivars.h" + #include "extract-word.h" + #include "fd-util.h" +diff --git a/src/test/test-condition.c b/src/test/test-condition.c +index 7ce6ee80ea..24395dafc6 100644 +--- a/src/test/test-condition.c ++++ b/src/test/test-condition.c +@@ -13,6 +13,7 @@ + #include "audit-util.h" + #include "cgroup-util.h" + #include "condition.h" ++#include "cpu-set-util.h" + #include "efivars.h" + #include "hostname-util.h" + #include "id128-util.h" diff --git a/SOURCES/0274-test-cpu-set-util-add-simple-test-for-cpus_in_affini.patch b/SOURCES/0274-test-cpu-set-util-add-simple-test-for-cpus_in_affini.patch new file mode 100644 index 0000000..026cee1 --- /dev/null +++ b/SOURCES/0274-test-cpu-set-util-add-simple-test-for-cpus_in_affini.patch @@ -0,0 +1,40 @@ +From a1ed6bfc5a8c40377b9f1cab1acc3c67a9529427 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 21 May 2019 09:01:34 +0200 +Subject: [PATCH] test-cpu-set-util: add simple test for + cpus_in_affinity_mask() + +(cherry picked from commit 9d1345f0657c707df89b41b2738776efb40aec8e) + +Related: #1734787 +--- + src/test/test-cpu-set-util.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index b9ec29af66..e87e0ca6e6 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -157,6 +157,14 @@ static void test_parse_cpu_set(void) { + cpu_set_reset(&c); + } + ++static void test_cpus_in_affinity_mask(void) { ++ int r; ++ ++ r = cpus_in_affinity_mask(); ++ assert(r > 0); ++ log_info("cpus_in_affinity_mask: %d", r); ++} ++ + int main(int argc, char *argv[]) { + log_info("CPU_ALLOC_SIZE(1) = %zu", CPU_ALLOC_SIZE(1)); + log_info("CPU_ALLOC_SIZE(9) = %zu", CPU_ALLOC_SIZE(9)); +@@ -167,6 +175,7 @@ int main(int argc, char *argv[]) { + log_info("CPU_ALLOC_SIZE(8191) = %zu", CPU_ALLOC_SIZE(8191)); + + test_parse_cpu_set(); ++ test_cpus_in_affinity_mask(); + + return 0; + } diff --git a/SOURCES/0275-test-cpu-set-util-add-a-smoke-test-for-test_parse_cp.patch b/SOURCES/0275-test-cpu-set-util-add-a-smoke-test-for-test_parse_cp.patch new file mode 100644 index 0000000..cce5c67 --- /dev/null +++ b/SOURCES/0275-test-cpu-set-util-add-a-smoke-test-for-test_parse_cp.patch @@ -0,0 +1,63 @@ +From 69541e93c45efb7ee15d7584c3aa70c3ff0b2200 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 24 May 2019 08:50:41 +0200 +Subject: [PATCH] test-cpu-set-util: add a smoke test for + test_parse_cpu_set_extend() + +(cherry picked from commit b54d7241f25b859c6c008e516c2131c39902e6e4) + +Related: #1734787 +--- + src/test/test-cpu-set-util.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index e87e0ca6e6..81f67647e8 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -11,6 +11,8 @@ static void test_parse_cpu_set(void) { + _cleanup_free_ char *str = NULL; + int cpu; + ++ log_info("/* %s */", __func__); ++ + /* Simple range (from CPUAffinity example) */ + assert_se(parse_cpu_set_full("1 2", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.set); +@@ -157,6 +159,28 @@ static void test_parse_cpu_set(void) { + cpu_set_reset(&c); + } + ++static void test_parse_cpu_set_extend(void) { ++ CPUSet c = {}; ++ _cleanup_free_ char *s1 = NULL, *s2 = NULL; ++ ++ log_info("/* %s */", __func__); ++ ++ assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 2); ++ assert_se(s1 = cpu_set_to_string(&c)); ++ log_info("cpu_set_to_string: %s", s1); ++ ++ assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 3); ++ assert_se(s2 = cpu_set_to_string(&c)); ++ log_info("cpu_set_to_string: %s", s2); ++ ++ assert_se(parse_cpu_set_extend("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); ++ assert_se(!c.set); ++ assert_se(c.allocated == 0); ++ log_info("cpu_set_to_string: (null)"); ++} ++ + static void test_cpus_in_affinity_mask(void) { + int r; + +@@ -175,6 +199,7 @@ int main(int argc, char *argv[]) { + log_info("CPU_ALLOC_SIZE(8191) = %zu", CPU_ALLOC_SIZE(8191)); + + test_parse_cpu_set(); ++ test_parse_cpu_set_extend(); + test_cpus_in_affinity_mask(); + + return 0; diff --git a/SOURCES/0276-pid1-parse-CPUAffinity-in-incremental-fashion.patch b/SOURCES/0276-pid1-parse-CPUAffinity-in-incremental-fashion.patch new file mode 100644 index 0000000..948c139 --- /dev/null +++ b/SOURCES/0276-pid1-parse-CPUAffinity-in-incremental-fashion.patch @@ -0,0 +1,148 @@ +From 8bf8409c6e08f5aef35d1976e172b3f61b651c8d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 24 May 2019 08:35:51 +0200 +Subject: [PATCH] pid1: parse CPUAffinity= in incremental fashion + +This makes the handling of this option match what we do in unit files. I think +consistency is important here. (As it happens, it is the only option in +system.conf that is "non-atomic", i.e. where there's a list of things which can +be split over multiple assignments. All other options are single-valued, so +there's no issue of how to handle multiple assignments.) + +(cherry picked from commit 61fbbac1d517a0b3498a689c736c6ca918497904) + +Related: #1734787 +--- + man/systemd-system.conf.xml | 13 ++++++++----- + man/systemd.exec.xml | 2 +- + src/core/main.c | 36 ++++++++++++++++++++++++++---------- + 3 files changed, 35 insertions(+), 16 deletions(-) + +diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml +index 085086200a..ab23779ec0 100644 +--- a/man/systemd-system.conf.xml ++++ b/man/systemd-system.conf.xml +@@ -99,11 +99,14 @@ + + CPUAffinity= + +- Configures the initial CPU affinity for the +- init process. Takes a list of CPU indices or ranges separated +- by either whitespace or commas. CPU ranges are specified by +- the lower and upper CPU indices separated by a +- dash. ++ Configures the CPU affinity for the service manager as well as the default CPU ++ affinity for all forked off processes. Takes a list of CPU indices or ranges separated by either ++ whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a ++ dash. This option may be specified more than once, in which case the specified CPU affinity masks are ++ merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have ++ no effect. Individual services may override the CPU affinity for their processes with the ++ CPUAffinity= setting in unit files, see ++ systemd.exec5. + + + +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index 737c52bcc4..342b8385bc 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -703,7 +703,7 @@ CapabilityBoundingSet=~CAP_B CAP_C + + Controls the CPU affinity of the executed processes. Takes a list of CPU indices or ranges + separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated +- by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are ++ by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are + merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no + effect. See + sched_setaffinity2 for +diff --git a/src/core/main.c b/src/core/main.c +index e62b2756ee..bc1db2af7b 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -127,6 +127,7 @@ static bool arg_default_tasks_accounting = true; + static uint64_t arg_default_tasks_max = UINT64_MAX; + static sd_id128_t arg_machine_id = {}; + static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; ++static CPUSet arg_cpu_affinity = {}; + + _noreturn_ static void freeze_or_reboot(void) { + +@@ -537,17 +538,11 @@ static int config_parse_cpu_affinity2( + void *data, + void *userdata) { + +- _cleanup_(cpu_set_reset) CPUSet c = {}; +- int r; +- +- r = parse_cpu_set_full(rvalue, &c, true, unit, filename, line, lvalue); +- if (r < 0) +- return r; ++ CPUSet *affinity = data; + +- if (sched_setaffinity(0, c.allocated, c.set) < 0) +- log_warning_errno(errno, "Failed to set CPU affinity: %m"); ++ assert(affinity); + +- // FIXME: parsing and execution should be seperated. ++ (void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue); + + return 0; + } +@@ -655,7 +650,7 @@ static int parse_config_file(void) { + { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell }, + { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot }, + { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status }, +- { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL }, ++ { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity }, + { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, + { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, + { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog }, +@@ -1483,6 +1478,21 @@ static void initialize_coredump(bool skip_setup) { + #endif + } + ++static void update_cpu_affinity(bool skip_setup) { ++ _cleanup_free_ char *mask = NULL; ++ ++ if (skip_setup || !arg_cpu_affinity.set) ++ return; ++ ++ assert(arg_cpu_affinity.allocated > 0); ++ ++ mask = cpu_set_to_string(&arg_cpu_affinity); ++ log_debug("Setting CPU affinity to %s.", strnull(mask)); ++ ++ if (sched_setaffinity(0, arg_cpu_affinity.allocated, arg_cpu_affinity.set) < 0) ++ log_warning_errno(errno, "Failed to set CPU affinity: %m"); ++} ++ + static void do_reexecute( + int argc, + char *argv[], +@@ -1655,6 +1665,8 @@ static int invoke_main_loop( + + set_manager_defaults(m); + ++ update_cpu_affinity(false); ++ + if (saved_log_level >= 0) + manager_override_log_level(m, saved_log_level); + if (saved_log_target >= 0) +@@ -1813,6 +1825,8 @@ static int initialize_runtime( + if (arg_action != ACTION_RUN) + return 0; + ++ update_cpu_affinity(skip_setup); ++ + if (arg_system) { + /* Make sure we leave a core dump without panicing the kernel. */ + install_crash_handler(); +@@ -1947,6 +1961,8 @@ static void free_arguments(void) { + arg_join_controllers = strv_free_free(arg_join_controllers); + arg_default_environment = strv_free(arg_default_environment); + arg_syscall_archs = set_free(arg_syscall_archs); ++ ++ cpu_set_reset(&arg_cpu_affinity); + } + + static int load_configuration(int argc, char **argv, const char **ret_error_message) { diff --git a/SOURCES/0277-pid1-don-t-reset-setting-from-proc-cmdline-upon-rest.patch b/SOURCES/0277-pid1-don-t-reset-setting-from-proc-cmdline-upon-rest.patch new file mode 100644 index 0000000..bb8d822 --- /dev/null +++ b/SOURCES/0277-pid1-don-t-reset-setting-from-proc-cmdline-upon-rest.patch @@ -0,0 +1,86 @@ +From f71f3271fa149d2b5f022830d43071d97b022b38 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 24 May 2019 08:59:23 +0200 +Subject: [PATCH] pid1: don't reset setting from /proc/cmdline upon restart + +We have settings which may be set on the kernel command line, and also +in /proc/cmdline (for pid1). The settings in /proc/cmdline have higher priority +of course. When a reload was done, we'd reload just the configuration file, +losing the overrides. + +So read /proc/cmdline again during reload. + +Also, when initially reading the configuration file when program starts, +don't treat any errors as fatal. The configuration done in there doesn't +seem important enough to refuse boot. + +(cherry picked from commit 470a5e6dcec4637439ae953002127af214d396ac) + +Related: #1734787 +--- + src/core/main.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index bc1db2af7b..9a9f145080 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -129,6 +129,8 @@ static sd_id128_t arg_machine_id = {}; + static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; + static CPUSet arg_cpu_affinity = {}; + ++static int parse_configuration(void); ++ + _noreturn_ static void freeze_or_reboot(void) { + + if (arg_crash_reboot) { +@@ -1659,9 +1661,7 @@ static int invoke_main_loop( + saved_log_level = m->log_level_overridden ? log_get_max_level() : -1; + saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID; + +- r = parse_config_file(); +- if (r < 0) +- log_warning_errno(r, "Failed to parse config file, ignoring: %m"); ++ (void) parse_configuration(); + + set_manager_defaults(m); + +@@ -1965,18 +1965,14 @@ static void free_arguments(void) { + cpu_set_reset(&arg_cpu_affinity); + } + +-static int load_configuration(int argc, char **argv, const char **ret_error_message) { ++static int parse_configuration(void) { + int r; + +- assert(ret_error_message); +- + arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U); + + r = parse_config_file(); +- if (r < 0) { +- *ret_error_message = "Failed to parse config file"; +- return r; +- } ++ if (r < 0) ++ log_warning_errno(r, "Failed to parse config file, ignoring: %m"); + + if (arg_system) { + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); +@@ -1987,6 +1983,16 @@ static int load_configuration(int argc, char **argv, const char **ret_error_mess + /* Note that this also parses bits from the kernel command line, including "debug". */ + log_parse_environment(); + ++ return 0; ++} ++ ++static int load_configuration(int argc, char **argv, const char **ret_error_message) { ++ int r; ++ ++ assert(ret_error_message); ++ ++ (void) parse_configuration(); ++ + r = parse_argv(argc, argv); + if (r < 0) { + *ret_error_message = "Failed to parse commandline arguments"; diff --git a/SOURCES/0278-pid1-when-reloading-configuration-forget-old-setting.patch b/SOURCES/0278-pid1-when-reloading-configuration-forget-old-setting.patch new file mode 100644 index 0000000..1b941cc --- /dev/null +++ b/SOURCES/0278-pid1-when-reloading-configuration-forget-old-setting.patch @@ -0,0 +1,208 @@ +From 0387294ba41ceaf80c79621409aab9508732bda0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 24 May 2019 09:41:44 +0200 +Subject: [PATCH] pid1: when reloading configuration, forget old settings + +If we had a configuration setting from a configuration file, and it was +removed, we'd still remember the old value, because there's was no mechanism to +"reset" everything, just to assign new values. + +Note that the effect of this is limited. For settings that have an "ongoing" effect, +like systemd.confirm_spawn, the new value is simply used. But some settings can only +be set at start. + +In particular, CPUAffinity= will be updated if set to a new value, but if +CPUAffinity= is fully removed, it will not be reset, simply because we don't +know what to reset it to. We might have inherited a setting, or we might have +set it ourselves. In principle we could remember the "original" value that was +set when we were executed, but propagate this over reloads and reexecs, but +that would be a lot of work for little gain. So this corner case of removal of +CPUAffinity= is not handled fully, and a reboot is needed to execute the +change. As a work-around, a full mask of CPUAffinity=0-8191 can be specified. + +(cherry picked from commit fb39af4ce42d7ef9af63009f271f404038703704) + +Related: #1734787 +--- + src/core/main.c | 139 +++++++++++++++++++++++++++++++++--------------- + 1 file changed, 95 insertions(+), 44 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index 9a9f145080..c74dc641c1 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -88,46 +88,52 @@ static enum { + ACTION_DUMP_CONFIGURATION_ITEMS, + ACTION_DUMP_BUS_PROPERTIES, + } arg_action = ACTION_RUN; +-static char *arg_default_unit = NULL; +-static bool arg_system = false; +-static bool arg_dump_core = true; +-static int arg_crash_chvt = -1; +-static bool arg_crash_shell = false; +-static bool arg_crash_reboot = false; +-static char *arg_confirm_spawn = NULL; +-static ShowStatus arg_show_status = _SHOW_STATUS_UNSET; +-static bool arg_switched_root = false; +-static bool arg_no_pager = false; +-static bool arg_service_watchdogs = true; ++ ++/* Those variables are initalized to 0 automatically, so we avoid uninitialized memory access. ++ * Real defaults are assigned in reset_arguments() below. */ ++static char *arg_default_unit; ++static bool arg_system; ++static bool arg_dump_core; ++static int arg_crash_chvt; ++static bool arg_crash_shell; ++static bool arg_crash_reboot; ++static char *arg_confirm_spawn; ++static ShowStatus arg_show_status; ++static bool arg_switched_root; ++static bool arg_no_pager; ++static bool arg_service_watchdogs; + static char ***arg_join_controllers = NULL; +-static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; +-static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; +-static usec_t arg_default_restart_usec = DEFAULT_RESTART_USEC; +-static usec_t arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; +-static usec_t arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; +-static usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL; +-static unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST; +-static usec_t arg_runtime_watchdog = 0; +-static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; +-static char *arg_watchdog_device = NULL; +-static char **arg_default_environment = NULL; +-static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {}; +-static uint64_t arg_capability_bounding_set = CAP_ALL; +-static bool arg_no_new_privs = false; +-static nsec_t arg_timer_slack_nsec = NSEC_INFINITY; +-static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE; +-static Set* arg_syscall_archs = NULL; +-static FILE* arg_serialization = NULL; +-static bool arg_default_cpu_accounting = false; +-static bool arg_default_io_accounting = false; +-static bool arg_default_ip_accounting = false; +-static bool arg_default_blockio_accounting = false; +-static bool arg_default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT; +-static bool arg_default_tasks_accounting = true; +-static uint64_t arg_default_tasks_max = UINT64_MAX; +-static sd_id128_t arg_machine_id = {}; +-static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; +-static CPUSet arg_cpu_affinity = {}; ++static ExecOutput arg_default_std_output; ++static ExecOutput arg_default_std_error; ++static usec_t arg_default_restart_usec; ++static usec_t arg_default_timeout_start_usec; ++static usec_t arg_default_timeout_stop_usec; ++static usec_t arg_default_timeout_abort_usec; ++static bool arg_default_timeout_abort_set; ++static usec_t arg_default_start_limit_interval; ++static unsigned arg_default_start_limit_burst; ++static usec_t arg_runtime_watchdog; ++static usec_t arg_shutdown_watchdog; ++static char *arg_early_core_pattern; ++static char *arg_watchdog_device; ++static char **arg_default_environment; ++static struct rlimit *arg_default_rlimit[_RLIMIT_MAX]; ++static uint64_t arg_capability_bounding_set; ++static bool arg_no_new_privs; ++static nsec_t arg_timer_slack_nsec; ++static usec_t arg_default_timer_accuracy_usec; ++static Set* arg_syscall_archs; ++static FILE* arg_serialization; ++static int arg_default_cpu_accounting; ++static bool arg_default_io_accounting; ++static bool arg_default_ip_accounting; ++static bool arg_default_blockio_accounting; ++static bool arg_default_memory_accounting; ++static bool arg_default_tasks_accounting; ++static uint64_t arg_default_tasks_max; ++static sd_id128_t arg_machine_id; ++static EmergencyAction arg_cad_burst_action; ++static CPUSet arg_cpu_affinity; + + static int parse_configuration(void); + +@@ -1951,17 +1957,59 @@ static int do_queue_default_job( + return 0; + } + +-static void free_arguments(void) { +- +- /* Frees all arg_* variables, with the exception of arg_serialization */ +- rlimit_free_all(arg_default_rlimit); ++static void reset_arguments(void) { ++ /* Frees/resets arg_* variables, with a few exceptions commented below. */ + + arg_default_unit = mfree(arg_default_unit); ++ ++ /* arg_system — ignore */ ++ ++ arg_dump_core = true; ++ arg_crash_chvt = -1; ++ arg_crash_shell = false; ++ arg_crash_reboot = false; + arg_confirm_spawn = mfree(arg_confirm_spawn); + arg_join_controllers = strv_free_free(arg_join_controllers); ++ arg_show_status = _SHOW_STATUS_UNSET; ++ arg_switched_root = false; ++ arg_no_pager = false; ++ arg_service_watchdogs = true; ++ arg_default_std_output = EXEC_OUTPUT_JOURNAL; ++ arg_default_std_error = EXEC_OUTPUT_INHERIT; ++ arg_default_restart_usec = DEFAULT_RESTART_USEC; ++ arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; ++ arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; ++ arg_default_timeout_abort_usec = DEFAULT_TIMEOUT_USEC; ++ arg_default_timeout_abort_set = false; ++ arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL; ++ arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST; ++ arg_runtime_watchdog = 0; ++ arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; ++ arg_early_core_pattern = NULL; ++ arg_watchdog_device = NULL; ++ + arg_default_environment = strv_free(arg_default_environment); ++ rlimit_free_all(arg_default_rlimit); ++ ++ arg_capability_bounding_set = CAP_ALL; ++ arg_no_new_privs = false; ++ arg_timer_slack_nsec = NSEC_INFINITY; ++ arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE; ++ + arg_syscall_archs = set_free(arg_syscall_archs); + ++ /* arg_serialization — ignore */ ++ ++ arg_default_cpu_accounting = -1; ++ arg_default_io_accounting = false; ++ arg_default_ip_accounting = false; ++ arg_default_blockio_accounting = false; ++ arg_default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT; ++ arg_default_tasks_accounting = true; ++ arg_default_tasks_max = UINT64_MAX; ++ arg_machine_id = (sd_id128_t) {}; ++ arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; ++ + cpu_set_reset(&arg_cpu_affinity); + } + +@@ -1970,6 +2018,9 @@ static int parse_configuration(void) { + + arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U); + ++ /* Assign configuration defaults */ ++ reset_arguments(); ++ + r = parse_config_file(); + if (r < 0) + log_warning_errno(r, "Failed to parse config file, ignoring: %m"); +@@ -2460,7 +2511,7 @@ finish: + m = manager_free(m); + } + +- free_arguments(); ++ reset_arguments(); + mac_selinux_finish(); + + if (reexecute) diff --git a/SOURCES/0279-test-execute-use-CPUSet-too.patch b/SOURCES/0279-test-execute-use-CPUSet-too.patch new file mode 100644 index 0000000..2332226 --- /dev/null +++ b/SOURCES/0279-test-execute-use-CPUSet-too.patch @@ -0,0 +1,114 @@ +From 5e6b616ed2708391752ba8c45f183ceb38573d7d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 28 May 2019 21:38:41 +0200 +Subject: [PATCH] test-execute: use CPUSet too + +cpu_set_malloc() was the last user. It doesn't seem useful to keep +it just to save the allocation of a few hundred bytes in a test, so +it is dropped and a fixed maximum is allocated (1024 bytes). + +(cherry picked from commit 167a776dbe9d033523bd6881e5a695f2155dc321) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 31 +------------------------------ + src/basic/cpu-set-util.h | 3 +-- + src/test/test-execute.c | 13 ++++++------- + 3 files changed, 8 insertions(+), 39 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index 1803539ac6..c297eab032 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -37,36 +37,7 @@ char* cpu_set_to_string(const CPUSet *a) { + return TAKE_PTR(str) ?: strdup(""); + } + +-cpu_set_t* cpu_set_malloc(unsigned *ncpus) { +- cpu_set_t *c; +- unsigned n = 1024; +- +- /* Allocates the cpuset in the right size */ +- +- for (;;) { +- c = CPU_ALLOC(n); +- if (!c) +- return NULL; +- +- if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) { +- CPU_ZERO_S(CPU_ALLOC_SIZE(n), c); +- +- if (ncpus) +- *ncpus = n; +- +- return c; +- } +- +- CPU_FREE(c); +- +- if (errno != EINVAL) +- return NULL; +- +- n *= 2; +- } +-} +- +-static int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { ++int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { + size_t need; + + assert(cpu_set); +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index 9b026aca09..b54e737110 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -12,8 +12,6 @@ + DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE); + #define _cleanup_cpu_free_ _cleanup_(CPU_FREEp) + +-cpu_set_t* cpu_set_malloc(unsigned *ncpus); +- + /* This wraps the libc interface with a variable to keep the allocated size. */ + typedef struct CPUSet { + cpu_set_t *set; +@@ -30,6 +28,7 @@ static inline void cpu_set_reset(CPUSet *a) { + int cpu_set_add_all(CPUSet *a, const CPUSet *b); + + char* cpu_set_to_string(const CPUSet *a); ++int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus); + int parse_cpu_set_full( + const char *rvalue, + CPUSet *cpu_set, +diff --git a/src/test/test-execute.c b/src/test/test-execute.c +index fa8efdddd2..6c22995b1e 100644 +--- a/src/test/test-execute.c ++++ b/src/test/test-execute.c +@@ -144,13 +144,12 @@ static void test_exec_bindpaths(Manager *m) { + } + + static void test_exec_cpuaffinity(Manager *m) { +- _cleanup_cpu_free_ cpu_set_t *c = NULL; +- unsigned n; ++ _cleanup_(cpu_set_reset) CPUSet c = {}; + +- assert_se(c = cpu_set_malloc(&n)); +- assert_se(sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0); ++ assert_se(cpu_set_realloc(&c, 8192) >= 0); /* just allocate the maximum possible size */ ++ assert_se(sched_getaffinity(0, c.allocated, c.set) >= 0); + +- if (CPU_ISSET_S(0, CPU_ALLOC_SIZE(n), c) == 0) { ++ if (!CPU_ISSET_S(0, c.allocated, c.set)) { + log_notice("Cannot use CPU 0, skipping %s", __func__); + return; + } +@@ -158,8 +157,8 @@ static void test_exec_cpuaffinity(Manager *m) { + test(m, "exec-cpuaffinity1.service", 0, CLD_EXITED); + test(m, "exec-cpuaffinity2.service", 0, CLD_EXITED); + +- if (CPU_ISSET_S(1, CPU_ALLOC_SIZE(n), c) == 0 || +- CPU_ISSET_S(2, CPU_ALLOC_SIZE(n), c) == 0) { ++ if (!CPU_ISSET_S(1, c.allocated, c.set) || ++ !CPU_ISSET_S(2, c.allocated, c.set)) { + log_notice("Cannot use CPU 1 or 2, skipping remaining tests in %s", __func__); + return; + } diff --git a/SOURCES/0280-shared-cpu-set-util-drop-now-unused-cleanup-function.patch b/SOURCES/0280-shared-cpu-set-util-drop-now-unused-cleanup-function.patch new file mode 100644 index 0000000..21bf12e --- /dev/null +++ b/SOURCES/0280-shared-cpu-set-util-drop-now-unused-cleanup-function.patch @@ -0,0 +1,26 @@ +From 7aa32093c3dfc4bf7298f02be553e95c40d7c211 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 28 May 2019 21:40:10 +0200 +Subject: [PATCH] shared/cpu-set-util: drop now-unused cleanup function + +(cherry picked from commit cb0d3acf55ef335001cac5dd9c335ec5e75e9b56) + +Related: #1734787 +--- + src/basic/cpu-set-util.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index b54e737110..68a73bf9f7 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -9,9 +9,6 @@ + + #include "macro.h" + +-DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE); +-#define _cleanup_cpu_free_ _cleanup_(CPU_FREEp) +- + /* This wraps the libc interface with a variable to keep the allocated size. */ + typedef struct CPUSet { + cpu_set_t *set; diff --git a/SOURCES/0281-shared-cpu-set-util-make-transfer-of-cpu_set_t-over-.patch b/SOURCES/0281-shared-cpu-set-util-make-transfer-of-cpu_set_t-over-.patch new file mode 100644 index 0000000..d09f290 --- /dev/null +++ b/SOURCES/0281-shared-cpu-set-util-make-transfer-of-cpu_set_t-over-.patch @@ -0,0 +1,126 @@ +From daa0243fda679c8af723648b8b1e501fc55b0ada Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 22 May 2019 13:55:49 +0200 +Subject: [PATCH] shared/cpu-set-util: make transfer of cpu_set_t over bus + endian safe + +(cherry picked from commit c367f996f5f091a63f812f0140b304c649be77fc) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 38 ++++++++++++++++++++++++++++++++++++++ + src/basic/cpu-set-util.h | 3 +++ + src/core/dbus-execute.c | 6 +++++- + src/shared/bus-unit-util.c | 8 +++++++- + 4 files changed, 53 insertions(+), 2 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index c297eab032..74e35e57dd 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -209,3 +209,41 @@ int cpus_in_affinity_mask(void) { + n *= 2; + } + } ++ ++int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated) { ++ uint8_t *out; ++ ++ assert(set); ++ assert(ret); ++ ++ out = new0(uint8_t, set->allocated); ++ if (!out) ++ return -ENOMEM; ++ ++ for (unsigned cpu = 0; cpu < set->allocated * 8; cpu++) ++ if (CPU_ISSET_S(cpu, set->allocated, set->set)) ++ out[cpu / 8] |= 1u << (cpu % 8); ++ ++ *ret = out; ++ *allocated = set->allocated; ++ return 0; ++} ++ ++int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) { ++ _cleanup_(cpu_set_reset) CPUSet s = {}; ++ int r; ++ ++ assert(bits); ++ assert(set); ++ ++ for (unsigned cpu = size * 8; cpu > 0; cpu--) ++ if (bits[(cpu - 1) / 8] & (1u << ((cpu - 1) % 8))) { ++ r = cpu_set_add(&s, cpu - 1); ++ if (r < 0) ++ return r; ++ } ++ ++ *set = s; ++ s = (CPUSet) {}; ++ return 0; ++} +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index 68a73bf9f7..415c6ca295 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -46,4 +46,7 @@ static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){ + return parse_cpu_set_full(rvalue, cpu_set, false, NULL, NULL, 0, NULL); + } + ++int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated); ++int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set); ++ + int cpus_in_affinity_mask(void); +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 08946627e3..50ea71a281 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1553,18 +1553,22 @@ int bus_exec_context_set_transient_property( + if (streq(name, "CPUAffinity")) { + const void *a; + size_t n; ++ _cleanup_(cpu_set_reset) CPUSet set = {}; + + r = sd_bus_message_read_array(message, 'y', &a, &n); + if (r < 0) + return r; + ++ r = cpu_set_from_dbus(a, n, &set); ++ if (r < 0) ++ return r; ++ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (n == 0) { + cpu_set_reset(&c->cpu_set); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *str = NULL; +- const CPUSet set = {(cpu_set_t*) a, n}; + + str = cpu_set_to_string(&set); + if (!str) +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 75b4aace84..ec8732c226 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -933,12 +933,18 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con + + if (streq(field, "CPUAffinity")) { + _cleanup_(cpu_set_reset) CPUSet cpuset = {}; ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; + + r = parse_cpu_set(eq, &cpuset); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value: %s", field, eq); + +- return bus_append_byte_array(m, field, cpuset.set, cpuset.allocated); ++ r = cpu_set_to_dbus(&cpuset, &array, &allocated); ++ if (r < 0) ++ return log_error_errno(r, "Failed to serialize CPUAffinity: %m"); ++ ++ return bus_append_byte_array(m, field, array, allocated); + } + + if (STR_IN_SET(field, "RestrictAddressFamilies", "SystemCallFilter")) { diff --git a/SOURCES/0282-test-cpu-set-util-add-test-for-dbus-conversions.patch b/SOURCES/0282-test-cpu-set-util-add-test-for-dbus-conversions.patch new file mode 100644 index 0000000..f6e259a --- /dev/null +++ b/SOURCES/0282-test-cpu-set-util-add-test-for-dbus-conversions.patch @@ -0,0 +1,61 @@ +From fd65eadbbcc068171ee9164610fd1c2016b3bf59 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 29 May 2019 09:44:16 +0200 +Subject: [PATCH] test-cpu-set-util: add test for dbus conversions + +(cherry picked from commit 1bf0d6c28f8c884e187c7dacc1a969c0763ff4e3) + +Related: #1734787 +--- + src/test/test-cpu-set-util.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index 81f67647e8..cae51ad7d9 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -181,6 +181,36 @@ static void test_parse_cpu_set_extend(void) { + log_info("cpu_set_to_string: (null)"); + } + ++static void test_cpu_set_to_from_dbus(void) { ++ _cleanup_(cpu_set_reset) CPUSet c = {}, c2 = {}; ++ _cleanup_free_ char *s = NULL; ++ ++ log_info("/* %s */", __func__); ++ ++ assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); ++ assert_se(s = cpu_set_to_string(&c)); ++ log_info("cpu_set_to_string: %s", s); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 104); ++ ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; ++ static const char expected[32] = ++ "\x0A\x01\x00\x00\x00\x00\x00\x00\x00\x00" ++ "\x00\x00\xF0\xFF\xFF\xFF\xFF\xFF\xFF\xFF" ++ "\xFF\xFF\xFF\xFF\xFF\x01"; ++ ++ assert_se(cpu_set_to_dbus(&c, &array, &allocated) == 0); ++ assert_se(array); ++ assert_se(allocated == c.allocated); ++ ++ assert(memcmp(array, expected, sizeof expected) == 0); ++ ++ assert_se(cpu_set_from_dbus(array, allocated, &c2) == 0); ++ assert_se(c2.set); ++ assert_se(c2.allocated == c.allocated); ++ assert_se(memcmp(c.set, c2.set, c.allocated) == 0); ++} ++ + static void test_cpus_in_affinity_mask(void) { + int r; + +@@ -201,6 +231,7 @@ int main(int argc, char *argv[]) { + test_parse_cpu_set(); + test_parse_cpu_set_extend(); + test_cpus_in_affinity_mask(); ++ test_cpu_set_to_from_dbus(); + + return 0; + } diff --git a/SOURCES/0283-shared-cpu-set-util-introduce-cpu_set_to_range.patch b/SOURCES/0283-shared-cpu-set-util-introduce-cpu_set_to_range.patch new file mode 100644 index 0000000..d49553f --- /dev/null +++ b/SOURCES/0283-shared-cpu-set-util-introduce-cpu_set_to_range.patch @@ -0,0 +1,203 @@ +From 93777a6dd8c12d5cba094694bf7ed6e8c06c2d6d Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 23 May 2019 14:27:18 +0200 +Subject: [PATCH] shared/cpu-set-util: introduce cpu_set_to_range() + +(cherry picked from commit 71b28519b55b496237146f9bcb5a627455f15f7e) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 37 ++++++++++++++++++++++++++ + src/basic/cpu-set-util.h | 2 ++ + src/test/test-cpu-set-util.c | 50 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 89 insertions(+) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index 74e35e57dd..bff39ec143 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -37,6 +37,43 @@ char* cpu_set_to_string(const CPUSet *a) { + return TAKE_PTR(str) ?: strdup(""); + } + ++char *cpu_set_to_range_string(const CPUSet *set) { ++ unsigned range_start = 0, range_end; ++ _cleanup_free_ char *str = NULL; ++ size_t allocated = 0, len = 0; ++ bool in_range = false; ++ int r; ++ ++ for (unsigned i = 0; i < set->allocated * 8; i++) ++ if (CPU_ISSET_S(i, set->allocated, set->set)) { ++ if (in_range) ++ range_end++; ++ else { ++ range_start = range_end = i; ++ in_range = true; ++ } ++ } else if (in_range) { ++ in_range = false; ++ ++ if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned))) ++ return NULL; ++ ++ r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); ++ assert_se(r > 0); ++ len += r; ++ } ++ ++ if (in_range) { ++ if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int))) ++ return NULL; ++ ++ r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); ++ assert_se(r > 0); ++ } ++ ++ return TAKE_PTR(str) ?: strdup(""); ++} ++ + int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { + size_t need; + +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index 415c6ca295..ec640b2ec9 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -25,7 +25,9 @@ static inline void cpu_set_reset(CPUSet *a) { + int cpu_set_add_all(CPUSet *a, const CPUSet *b); + + char* cpu_set_to_string(const CPUSet *a); ++char *cpu_set_to_range_string(const CPUSet *a); + int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus); ++ + int parse_cpu_set_full( + const char *rvalue, + CPUSet *cpu_set, +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index cae51ad7d9..0d2741cd43 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -4,6 +4,7 @@ + + #include "alloc-util.h" + #include "cpu-set-util.h" ++#include "string-util.h" + #include "macro.h" + + static void test_parse_cpu_set(void) { +@@ -13,6 +14,22 @@ static void test_parse_cpu_set(void) { + + log_info("/* %s */", __func__); + ++ /* Single value */ ++ assert_se(parse_cpu_set_full("0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(c.set); ++ assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(CPU_ISSET_S(0, c.allocated, c.set)); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 1); ++ ++ assert_se(str = cpu_set_to_string(&c)); ++ log_info("cpu_set_to_string: %s", str); ++ str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "0-0")); ++ str = mfree(str); ++ cpu_set_reset(&c); ++ + /* Simple range (from CPUAffinity example) */ + assert_se(parse_cpu_set_full("1 2", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.set); +@@ -24,6 +41,10 @@ static void test_parse_cpu_set(void) { + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "1-2")); ++ str = mfree(str); + cpu_set_reset(&c); + + /* A more interesting range */ +@@ -34,9 +55,14 @@ static void test_parse_cpu_set(void) { + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "0-3 8-11")); ++ str = mfree(str); + cpu_set_reset(&c); + + /* Quoted strings */ +@@ -48,6 +74,10 @@ static void test_parse_cpu_set(void) { + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "8-11")); ++ str = mfree(str); + cpu_set_reset(&c); + + /* Use commas as separators */ +@@ -72,6 +102,10 @@ static void test_parse_cpu_set(void) { + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "0-7")); ++ str = mfree(str); + cpu_set_reset(&c); + + /* Ranges */ +@@ -98,6 +132,10 @@ static void test_parse_cpu_set(void) { + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "0-3 8-11")); ++ str = mfree(str); + cpu_set_reset(&c); + + /* Negative range (returns empty cpu_set) */ +@@ -115,6 +153,10 @@ static void test_parse_cpu_set(void) { + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "0-11")); ++ str = mfree(str); + cpu_set_reset(&c); + + /* Mix ranges and individual CPUs */ +@@ -128,6 +170,10 @@ static void test_parse_cpu_set(void) { + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "0-1 4-11")); ++ str = mfree(str); + cpu_set_reset(&c); + + /* Garbage */ +@@ -156,6 +202,10 @@ static void test_parse_cpu_set(void) { + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); ++ assert_se(str = cpu_set_to_range_string(&c)); ++ log_info("cpu_set_to_range_string: %s", str); ++ assert_se(streq(str, "8000-8191")); ++ str = mfree(str); + cpu_set_reset(&c); + } + diff --git a/SOURCES/0284-systemctl-present-CPUAffinity-mask-as-a-list-of-CPU-.patch b/SOURCES/0284-systemctl-present-CPUAffinity-mask-as-a-list-of-CPU-.patch new file mode 100644 index 0000000..44d35dd --- /dev/null +++ b/SOURCES/0284-systemctl-present-CPUAffinity-mask-as-a-list-of-CPU-.patch @@ -0,0 +1,53 @@ +From fb1244ef318e9f54628a7c13db9e2ffbc712dd38 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 22 May 2019 17:14:21 +0200 +Subject: [PATCH] systemctl: present CPUAffinity mask as a list of CPU index + ranges + +(cherry picked from commit a047f4f10ed2f922d6079c033d24a443b0e95f38) + +Related: #1734787 +--- + src/systemctl/systemctl.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index f072ad0c31..0154b300a3 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -30,6 +30,7 @@ + #include "cgroup-show.h" + #include "cgroup-util.h" + #include "copy.h" ++#include "cpu-set-util.h" + #include "dropin.h" + #include "efivars.h" + #include "env-util.h" +@@ -4876,6 +4877,27 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool + + print_prop(name, "%s", h); + ++ return 1; ++ } else if (contents[0] == SD_BUS_TYPE_BYTE && streq(name, "CPUAffinity")) { ++ _cleanup_free_ char *affinity = NULL; ++ _cleanup_(cpu_set_reset) CPUSet set = {}; ++ const void *a; ++ size_t n; ++ ++ r = sd_bus_message_read_array(m, 'y', &a, &n); ++ if (r < 0) ++ return bus_log_parse_error(r); ++ ++ r = cpu_set_from_dbus(a, n, &set); ++ if (r < 0) ++ return log_error_errno(r, "Failed to deserialize CPUAffinity: %m"); ++ ++ affinity = cpu_set_to_range_string(&set); ++ if (!affinity) ++ return log_oom(); ++ ++ print_prop(name, "%s", affinity); ++ + return 1; + } + diff --git a/SOURCES/0285-shared-cpu-set-util-only-force-range-printing-one-ti.patch b/SOURCES/0285-shared-cpu-set-util-only-force-range-printing-one-ti.patch new file mode 100644 index 0000000..5f34600 --- /dev/null +++ b/SOURCES/0285-shared-cpu-set-util-only-force-range-printing-one-ti.patch @@ -0,0 +1,77 @@ +From cabd9055d0d745f7de9625dec6c623d363dd3aa6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 29 May 2019 10:17:43 +0200 +Subject: [PATCH] shared/cpu-set-util: only force range printing one time +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The idea is to have at least one range to make the new format clearly +distinguishable from the old. But it is enough to just do it once. +In particular, in case the affinity would be specified like 0, 2, 4, 6…, +this gives much shorter output. + +(cherry picked from commit 1f57a176af5152d05719bf43740e87a47e37af50) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 10 ++++++++-- + src/test/test-cpu-set-util.c | 7 ++++--- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index bff39ec143..5024290557 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -58,7 +58,10 @@ char *cpu_set_to_range_string(const CPUSet *set) { + if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned))) + return NULL; + +- r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); ++ if (range_end > range_start || len == 0) ++ r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); ++ else ++ r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); + assert_se(r > 0); + len += r; + } +@@ -67,7 +70,10 @@ char *cpu_set_to_range_string(const CPUSet *set) { + if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int))) + return NULL; + +- r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); ++ if (range_end > range_start || len == 0) ++ r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); ++ else ++ r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); + assert_se(r > 0); + } + +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index 0d2741cd43..995b981d25 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -31,19 +31,20 @@ static void test_parse_cpu_set(void) { + cpu_set_reset(&c); + + /* Simple range (from CPUAffinity example) */ +- assert_se(parse_cpu_set_full("1 2", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(parse_cpu_set_full("1 2 4", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.set); + assert_se(c.allocated >= sizeof(__cpu_mask) / 8); + assert_se(CPU_ISSET_S(1, c.allocated, c.set)); + assert_se(CPU_ISSET_S(2, c.allocated, c.set)); +- assert_se(CPU_COUNT_S(c.allocated, c.set) == 2); ++ assert_se(CPU_ISSET_S(4, c.allocated, c.set)); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 3); + + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); +- assert_se(streq(str, "1-2")); ++ assert_se(streq(str, "1-2 4")); + str = mfree(str); + cpu_set_reset(&c); + diff --git a/SOURCES/0286-execute-dump-CPUAffinity-as-a-range-string-instead-o.patch b/SOURCES/0286-execute-dump-CPUAffinity-as-a-range-string-instead-o.patch new file mode 100644 index 0000000..050478a --- /dev/null +++ b/SOURCES/0286-execute-dump-CPUAffinity-as-a-range-string-instead-o.patch @@ -0,0 +1,36 @@ +From b90f935f8d2268522480a7c12f7e2213a7a5e19d Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 31 May 2019 18:02:20 +0200 +Subject: [PATCH] execute: dump CPUAffinity as a range string instead of a list + of CPUs + +We do this already when printing the property in systemctl so be +consistent and do the same for systemd-analyze dump. + +(cherry picked from commit e7fca352ba43988682a927de6b1f629b3f10a415) + +Related: #1734787 +--- + src/core/execute.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 22e5825905..bc26aa66e7 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -4098,11 +4098,10 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { + } + + if (c->cpu_set.set) { +- fprintf(f, "%sCPUAffinity:", prefix); +- for (i = 0; i < c->cpu_set.allocated * 8; i++) +- if (CPU_ISSET_S(i, c->cpu_set.allocated, c->cpu_set.set)) +- fprintf(f, " %u", i); +- fputs("\n", f); ++ _cleanup_free_ char *affinity = NULL; ++ ++ affinity = cpu_set_to_range_string(&c->cpu_set); ++ fprintf(f, "%sCPUAffinity: %s\n", prefix, affinity); + } + + if (c->timer_slack_nsec != NSEC_INFINITY) diff --git a/SOURCES/0287-cpu-set-util-use-d-d-format-in-cpu_set_to_range_stri.patch b/SOURCES/0287-cpu-set-util-use-d-d-format-in-cpu_set_to_range_stri.patch new file mode 100644 index 0000000..0b2bec0 --- /dev/null +++ b/SOURCES/0287-cpu-set-util-use-d-d-format-in-cpu_set_to_range_stri.patch @@ -0,0 +1,95 @@ +From 35894625624f0e8c7d3ca2c200861005c7ad4435 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 3 Jun 2019 10:12:35 +0200 +Subject: [PATCH] cpu-set-util: use %d-%d format in cpu_set_to_range_string() + only for actual ranges + +(cherry picked from commit 71923237b18df35401626993d8a285cd998be78d) + +Related: #1734787 +--- + src/basic/cpu-set-util.c | 4 ++-- + src/test/test-cpu-set-util.c | 16 +++++++++------- + 2 files changed, 11 insertions(+), 9 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index 5024290557..103b9703b3 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -58,7 +58,7 @@ char *cpu_set_to_range_string(const CPUSet *set) { + if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned))) + return NULL; + +- if (range_end > range_start || len == 0) ++ if (range_end > range_start) + r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); + else + r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); +@@ -70,7 +70,7 @@ char *cpu_set_to_range_string(const CPUSet *set) { + if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int))) + return NULL; + +- if (range_end > range_start || len == 0) ++ if (range_end > range_start) + r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); + else + r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index 995b981d25..9522582891 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -26,7 +26,7 @@ static void test_parse_cpu_set(void) { + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); +- assert_se(streq(str, "0-0")); ++ assert_se(streq(str, "0")); + str = mfree(str); + cpu_set_reset(&c); + +@@ -95,17 +95,19 @@ static void test_parse_cpu_set(void) { + cpu_set_reset(&c); + + /* Commas with spaces (and trailing comma, space) */ +- assert_se(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, 63, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= sizeof(__cpu_mask) / 8); +- assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); ++ assert_se(CPU_COUNT_S(c.allocated, c.set) == 9); + for (cpu = 0; cpu < 8; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); ++ ++ assert_se(CPU_ISSET_S(63, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); +- assert_se(streq(str, "0-7")); ++ assert_se(streq(str, "0-7 63")); + str = mfree(str); + cpu_set_reset(&c); + +@@ -161,11 +163,11 @@ static void test_parse_cpu_set(void) { + cpu_set_reset(&c); + + /* Mix ranges and individual CPUs */ +- assert_se(parse_cpu_set_full("0,1 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); ++ assert_se(parse_cpu_set_full("0,2 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= sizeof(__cpu_mask) / 8); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 10); + assert_se(CPU_ISSET_S(0, c.allocated, c.set)); +- assert_se(CPU_ISSET_S(1, c.allocated, c.set)); ++ assert_se(CPU_ISSET_S(2, c.allocated, c.set)); + for (cpu = 4; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); +@@ -173,7 +175,7 @@ static void test_parse_cpu_set(void) { + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); +- assert_se(streq(str, "0-1 4-11")); ++ assert_se(streq(str, "0 2 4-11")); + str = mfree(str); + cpu_set_reset(&c); + diff --git a/SOURCES/0288-core-introduce-NUMAPolicy-and-NUMAMask-options.patch b/SOURCES/0288-core-introduce-NUMAPolicy-and-NUMAMask-options.patch new file mode 100644 index 0000000..bcfd3a3 --- /dev/null +++ b/SOURCES/0288-core-introduce-NUMAPolicy-and-NUMAMask-options.patch @@ -0,0 +1,779 @@ +From a735699a8287c19e043b7d2fe9a387a3938e1e2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Mon, 18 Nov 2019 12:50:11 +0100 +Subject: [PATCH] core: introduce NUMAPolicy and NUMAMask options + +Make possible to set NUMA allocation policy for manager. Manager's +policy is by default inherited to all forked off processes. However, it +is possible to override the policy on per-service basis. Currently we +support, these policies: default, prefer, bind, interleave, local. +See man 2 set_mempolicy for details on each policy. + +Overall NUMA policy actually consists of two parts. Policy itself and +bitmask representing NUMA nodes where is policy effective. Node mask can +be specified using related option, NUMAMask. Default mask can be +overwritten on per-service level. + +(cherry-picked from commit fe9c54b2188e6cd23262a319f96b13215f2c5e9c) + +Resolves: #1734787 +--- + man/systemd-system.conf.xml | 19 ++++++ + man/systemd.exec.xml | 28 +++++++++ + meson.build | 4 ++ + src/basic/cpu-set-util.c | 91 +++++++++++++++++++++++++++ + src/basic/cpu-set-util.h | 28 +++++++++ + src/basic/exit-status.c | 3 + + src/basic/exit-status.h | 1 + + src/basic/missing_syscall.h | 43 +++++++++++++ + src/core/dbus-execute.c | 65 ++++++++++++++++++- + src/core/execute.c | 20 ++++++ + src/core/execute.h | 1 + + src/core/load-fragment-gperf.gperf.m4 | 2 + + src/core/load-fragment.c | 28 +++++++++ + src/core/load-fragment.h | 2 + + src/core/main.c | 27 ++++++++ + src/core/system.conf.in | 2 + + src/shared/bus-unit-util.c | 28 +++++++++ + src/systemctl/systemctl.c | 18 +++++- + 18 files changed, 405 insertions(+), 5 deletions(-) + +diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml +index ab23779ec0..988c4e7665 100644 +--- a/man/systemd-system.conf.xml ++++ b/man/systemd-system.conf.xml +@@ -132,6 +132,25 @@ + anymore. + + ++ ++ NUMAPolicy= ++ ++ Configures the NUMA memory policy for the service manager and the default NUMA memory policy ++ for all forked off processes. Individual services may override the default policy with the ++ NUMAPolicy= setting in unit files, see ++ systemd.exec5. ++ ++ ++ ++ NUMAMask= ++ ++ Configures the NUMA node mask that will be associated with the selected NUMA policy. Note that ++ and NUMA policies don't require explicit NUMA node mask and ++ value of the option can be empty. Similarly to NUMAPolicy=, value can be overriden ++ by individual services in unit files, see ++ systemd.exec5. ++ ++ + + RuntimeWatchdogSec= + ShutdownWatchdogSec= +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index 342b8385bc..87fb8b34f4 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -710,6 +710,28 @@ CapabilityBoundingSet=~CAP_B CAP_C + details. + + ++ ++ NUMAPolicy= ++ ++ Controls the NUMA memory policy of the executed processes. Takes a policy type, one of: ++ , , , and ++ . A list of NUMA nodes that should be associated with the policy must be specified ++ in NUMAMask=. For more details on each policy please see, ++ set_mempolicy2. For overall ++ overview of NUMA support in Linux see, ++ numa7 ++ ++ ++ ++ ++ NUMAMask= ++ ++ Controls the NUMA node list which will be applied alongside with selected NUMA policy. ++ Takes a list of NUMA nodes and has the same syntax as a list of CPUs for CPUAffinity= ++ option. Note that the list of NUMA nodes is not required for and ++ policies and for policy we expect a single NUMA node. ++ ++ + + IOSchedulingClass= + +@@ -2709,6 +2731,12 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy + EXIT_CONFIGURATION_DIRECTORY + Failed to set up unit's configuration directory. See ConfigurationDirectory= above. + ++ ++ 242 ++ EXIT_NUMA_POLICY ++ Failed to set up unit's NUMA memory policy. See NUMAPolicy= and NUMAMask=above. ++ ++ + + + +diff --git a/meson.build b/meson.build +index 613a5133b6..fe82ca4ac2 100644 +--- a/meson.build ++++ b/meson.build +@@ -501,6 +501,10 @@ foreach ident : [ + #include '''], + ['explicit_bzero' , '''#include '''], + ['reallocarray', '''#include '''], ++ ['set_mempolicy', '''#include ++ #include '''], ++ ['get_mempolicy', '''#include ++ #include '''], + ] + + have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE') +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index 103b9703b3..36cb017ae7 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -10,11 +10,17 @@ + + #include "alloc-util.h" + #include "cpu-set-util.h" ++#include "dirent-util.h" + #include "extract-word.h" ++#include "fd-util.h" + #include "log.h" + #include "macro.h" ++#include "missing.h" + #include "parse-util.h" ++#include "stat-util.h" + #include "string-util.h" ++#include "string-table.h" ++#include "strv.h" + #include "util.h" + + char* cpu_set_to_string(const CPUSet *a) { +@@ -290,3 +296,88 @@ int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) { + s = (CPUSet) {}; + return 0; + } ++ ++bool numa_policy_is_valid(const NUMAPolicy *policy) { ++ assert(policy); ++ ++ if (!mpol_is_valid(numa_policy_get_type(policy))) ++ return false; ++ ++ if (!policy->nodes.set && ++ !IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL, MPOL_PREFERRED)) ++ return false; ++ ++ if (policy->nodes.set && ++ numa_policy_get_type(policy) == MPOL_PREFERRED && ++ CPU_COUNT_S(policy->nodes.allocated, policy->nodes.set) != 1) ++ return false; ++ ++ return true; ++} ++ ++static int numa_policy_to_mempolicy(const NUMAPolicy *policy, unsigned long *ret_maxnode, unsigned long **ret_nodes) { ++ unsigned node, bits = 0, ulong_bits; ++ _cleanup_free_ unsigned long *out = NULL; ++ ++ assert(policy); ++ assert(ret_maxnode); ++ assert(ret_nodes); ++ ++ if (IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL) || ++ (numa_policy_get_type(policy) == MPOL_PREFERRED && !policy->nodes.set)) { ++ *ret_nodes = NULL; ++ *ret_maxnode = 0; ++ return 0; ++ } ++ ++ bits = policy->nodes.allocated * 8; ++ ulong_bits = sizeof(unsigned long) * 8; ++ ++ out = new0(unsigned long, DIV_ROUND_UP(policy->nodes.allocated, sizeof(unsigned long))); ++ if (!out) ++ return -ENOMEM; ++ ++ /* We don't make any assumptions about internal type libc is using to store NUMA node mask. ++ Hence we need to convert the node mask to the representation expected by set_mempolicy() */ ++ for (node = 0; node < bits; node++) ++ if (CPU_ISSET_S(node, policy->nodes.allocated, policy->nodes.set)) ++ out[node / ulong_bits] |= 1ul << (node % ulong_bits); ++ ++ *ret_nodes = TAKE_PTR(out); ++ *ret_maxnode = bits + 1; ++ return 0; ++} ++ ++int apply_numa_policy(const NUMAPolicy *policy) { ++ int r; ++ _cleanup_free_ unsigned long *nodes = NULL; ++ unsigned long maxnode; ++ ++ assert(policy); ++ ++ if (get_mempolicy(NULL, NULL, 0, 0, 0) < 0 && errno == ENOSYS) ++ return -EOPNOTSUPP; ++ ++ if (!numa_policy_is_valid(policy)) ++ return -EINVAL; ++ ++ r = numa_policy_to_mempolicy(policy, &maxnode, &nodes); ++ if (r < 0) ++ return r; ++ ++ r = set_mempolicy(numa_policy_get_type(policy), nodes, maxnode); ++ if (r < 0) ++ return -errno; ++ ++ return 0; ++} ++ ++static const char* const mpol_table[] = { ++ [MPOL_DEFAULT] = "default", ++ [MPOL_PREFERRED] = "preferred", ++ [MPOL_BIND] = "bind", ++ [MPOL_INTERLEAVE] = "interleave", ++ [MPOL_LOCAL] = "local", ++}; ++ ++DEFINE_STRING_TABLE_LOOKUP(mpol, int); +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index ec640b2ec9..295028cb54 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -8,6 +8,7 @@ + #include + + #include "macro.h" ++#include "missing.h" + + /* This wraps the libc interface with a variable to keep the allocated size. */ + typedef struct CPUSet { +@@ -52,3 +53,30 @@ int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated); + int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set); + + int cpus_in_affinity_mask(void); ++ ++static inline bool mpol_is_valid(int t) { ++ return t >= MPOL_DEFAULT && t <= MPOL_LOCAL; ++} ++ ++typedef struct NUMAPolicy { ++ /* Always use numa_policy_get_type() to read the value */ ++ int type; ++ CPUSet nodes; ++} NUMAPolicy; ++ ++bool numa_policy_is_valid(const NUMAPolicy *p); ++ ++static inline int numa_policy_get_type(const NUMAPolicy *p) { ++ return p->type < 0 ? (p->nodes.set ? MPOL_PREFERRED : -1) : p->type; ++} ++ ++static inline void numa_policy_reset(NUMAPolicy *p) { ++ assert(p); ++ cpu_set_reset(&p->nodes); ++ p->type = -1; ++} ++ ++int apply_numa_policy(const NUMAPolicy *policy); ++ ++const char* mpol_to_string(int i) _const_; ++int mpol_from_string(const char *s) _pure_; +diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c +index 21af8c4c71..0a7a53b73d 100644 +--- a/src/basic/exit-status.c ++++ b/src/basic/exit-status.c +@@ -155,6 +155,9 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) { + + case EXIT_CONFIGURATION_DIRECTORY: + return "CONFIGURATION_DIRECTORY"; ++ ++ case EXIT_NUMA_POLICY: ++ return "NUMA_POLICY"; + } + } + +diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h +index c41e8b82c3..dc284aacb1 100644 +--- a/src/basic/exit-status.h ++++ b/src/basic/exit-status.h +@@ -69,6 +69,7 @@ enum { + EXIT_CACHE_DIRECTORY, + EXIT_LOGS_DIRECTORY, /* 240 */ + EXIT_CONFIGURATION_DIRECTORY, ++ EXIT_NUMA_POLICY, + }; + + typedef enum ExitStatusLevel { +diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h +index 93c60458bf..014dd2b326 100644 +--- a/src/basic/missing_syscall.h ++++ b/src/basic/missing_syscall.h +@@ -428,3 +428,46 @@ static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flag + + # define statx missing_statx + #endif ++ ++#if !HAVE_SET_MEMPOLICY ++ ++enum { ++ MPOL_DEFAULT, ++ MPOL_PREFERRED, ++ MPOL_BIND, ++ MPOL_INTERLEAVE, ++ MPOL_LOCAL, ++}; ++ ++static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask, ++ unsigned long maxnode) { ++ long i; ++# ifdef __NR_set_mempolicy ++ i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode); ++# else ++ errno = ENOSYS; ++ i = -1; ++# endif ++ return i; ++} ++ ++# define set_mempolicy missing_set_mempolicy ++#endif ++ ++ ++#if !HAVE_GET_MEMPOLICY ++static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, ++ unsigned long maxnode, void *addr, ++ unsigned long flags) { ++ long i; ++# ifdef __NR_get_mempolicy ++ i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags); ++# else ++ errno = ENOSYS; ++ i = -1; ++# endif ++ return i; ++} ++ ++#define get_mempolicy missing_get_mempolicy ++#endif +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 50ea71a281..198f149210 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -223,6 +223,48 @@ static int property_get_cpu_affinity( + return sd_bus_message_append_array(reply, 'y', c->cpu_set.set, c->cpu_set.allocated); + } + ++static int property_get_numa_mask( ++ sd_bus *bus, ++ const char *path, ++ const char *interface, ++ const char *property, ++ sd_bus_message *reply, ++ void *userdata, ++ sd_bus_error *error) { ++ ++ ExecContext *c = userdata; ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; ++ ++ assert(bus); ++ assert(reply); ++ assert(c); ++ ++ (void) cpu_set_to_dbus(&c->numa_policy.nodes, &array, &allocated); ++ ++ return sd_bus_message_append_array(reply, 'y', array, allocated); ++} ++ ++static int property_get_numa_policy( ++ sd_bus *bus, ++ const char *path, ++ const char *interface, ++ const char *property, ++ sd_bus_message *reply, ++ void *userdata, ++ sd_bus_error *error) { ++ ExecContext *c = userdata; ++ int32_t policy; ++ ++ assert(bus); ++ assert(reply); ++ assert(c); ++ ++ policy = numa_policy_get_type(&c->numa_policy); ++ ++ return sd_bus_message_append_basic(reply, 'i', &policy); ++} ++ + static int property_get_timer_slack_nsec( + sd_bus *bus, + const char *path, +@@ -698,6 +740,8 @@ const sd_bus_vtable bus_exec_vtable[] = { + SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("NUMAPolicy", "i", property_get_numa_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("NUMAMask", "ay", property_get_numa_mask, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST), +@@ -1550,9 +1594,10 @@ int bus_exec_context_set_transient_property( + return 1; + } + #endif +- if (streq(name, "CPUAffinity")) { ++ if (STR_IN_SET(name, "CPUAffinity", "NUMAMask")) { + const void *a; + size_t n; ++ bool affinity = streq(name, "CPUAffinity"); + _cleanup_(cpu_set_reset) CPUSet set = {}; + + r = sd_bus_message_read_array(message, 'y', &a, &n); +@@ -1565,7 +1610,7 @@ int bus_exec_context_set_transient_property( + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (n == 0) { +- cpu_set_reset(&c->cpu_set); ++ cpu_set_reset(affinity ? &c->cpu_set : &c->numa_policy.nodes); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *str = NULL; +@@ -1577,7 +1622,7 @@ int bus_exec_context_set_transient_property( + /* We forego any optimizations here, and always create the structure using + * cpu_set_add_all(), because we don't want to care if the existing size we + * got over dbus is appropriate. */ +- r = cpu_set_add_all(&c->cpu_set, &set); ++ r = cpu_set_add_all(affinity ? &c->cpu_set : &c->numa_policy.nodes, &set); + if (r < 0) + return r; + +@@ -1587,6 +1632,20 @@ int bus_exec_context_set_transient_property( + + return 1; + ++ } else if (streq(name, "NUMAPolicy")) { ++ int32_t type; ++ ++ r = sd_bus_message_read(message, "i", &type); ++ if (r < 0) ++ return r; ++ ++ if (!mpol_is_valid(type)) ++ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NUMAPolicy value: %i", type); ++ ++ if (!UNIT_WRITE_FLAGS_NOOP(flags)) ++ c->numa_policy.type = type; ++ ++ return 1; + } else if (streq(name, "IOSchedulingClass")) { + int32_t q; + +diff --git a/src/core/execute.c b/src/core/execute.c +index bc26aa66e7..56aa89e1ec 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2997,6 +2997,16 @@ static int exec_child( + return log_unit_error_errno(unit, errno, "Failed to set up CPU affinity: %m"); + } + ++ if (mpol_is_valid(numa_policy_get_type(&context->numa_policy))) { ++ r = apply_numa_policy(&context->numa_policy); ++ if (r == -EOPNOTSUPP) ++ log_unit_debug_errno(unit, r, "NUMA support not available, ignoring."); ++ else if (r < 0) { ++ *exit_status = EXIT_NUMA_POLICY; ++ return log_unit_error_errno(unit, r, "Failed to set NUMA memory policy: %m"); ++ } ++ } ++ + if (context->ioprio_set) + if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) { + *exit_status = EXIT_IOPRIO; +@@ -3651,6 +3661,7 @@ void exec_context_init(ExecContext *c) { + assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL); + c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL; + c->log_level_max = -1; ++ numa_policy_reset(&c->numa_policy); + } + + void exec_context_done(ExecContext *c) { +@@ -3695,6 +3706,7 @@ void exec_context_done(ExecContext *c) { + c->n_temporary_filesystems = 0; + + cpu_set_reset(&c->cpu_set); ++ numa_policy_reset(&c->numa_policy); + + c->utmp_id = mfree(c->utmp_id); + c->selinux_context = mfree(c->selinux_context); +@@ -4104,6 +4116,14 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { + fprintf(f, "%sCPUAffinity: %s\n", prefix, affinity); + } + ++ if (mpol_is_valid(numa_policy_get_type(&c->numa_policy))) { ++ _cleanup_free_ char *nodes = NULL; ++ ++ nodes = cpu_set_to_range_string(&c->numa_policy.nodes); ++ fprintf(f, "%sNUMAPolicy: %s\n", prefix, mpol_to_string(numa_policy_get_type(&c->numa_policy))); ++ fprintf(f, "%sNUMAMask: %s\n", prefix, strnull(nodes)); ++ } ++ + if (c->timer_slack_nsec != NSEC_INFINITY) + fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec); + +diff --git a/src/core/execute.h b/src/core/execute.h +index e1e7a494cd..b2eb55f8f5 100644 +--- a/src/core/execute.h ++++ b/src/core/execute.h +@@ -150,6 +150,7 @@ struct ExecContext { + int cpu_sched_priority; + + CPUSet cpu_set; ++ NUMAPolicy numa_policy; + + ExecInput std_input; + ExecOutput std_output; +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index 1066bcfb8f..cdf4d14c4e 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -36,6 +36,8 @@ $1.CPUSchedulingPolicy, config_parse_exec_cpu_sched_policy, 0, + $1.CPUSchedulingPriority, config_parse_exec_cpu_sched_prio, 0, offsetof($1, exec_context) + $1.CPUSchedulingResetOnFork, config_parse_bool, 0, offsetof($1, exec_context.cpu_sched_reset_on_fork) + $1.CPUAffinity, config_parse_exec_cpu_affinity, 0, offsetof($1, exec_context) ++$1.NUMAPolicy, config_parse_numa_policy, 0, offsetof($1, exec_context.numa_policy.type) ++$1.NUMAMask, config_parse_numa_mask, 0, offsetof($1, exec_context.numa_policy) + $1.UMask, config_parse_mode, 0, offsetof($1, exec_context.umask) + $1.Environment, config_parse_environ, 0, offsetof($1, exec_context.environment) + $1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files) +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 34ae834188..35dd595098 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -93,6 +93,7 @@ DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint + DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight"); + DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares"); + DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag"); ++DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_numa_policy, mpol, int, -1, "Invalid NUMA policy type"); + + int config_parse_unit_deps( + const char *unit, +@@ -1159,6 +1160,33 @@ int config_parse_exec_cpu_sched_policy(const char *unit, + return 0; + } + ++int config_parse_numa_mask(const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ int r; ++ NUMAPolicy *p = data; ++ ++ assert(filename); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ r = parse_cpu_set_extend(rvalue, &p->nodes, true, unit, filename, line, lvalue); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse NUMA node mask, ignoring: %s", rvalue); ++ return 0; ++ } ++ ++ return r; ++} ++ + int config_parse_exec_cpu_sched_prio(const char *unit, + const char *filename, + unsigned line, +diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h +index dad281ef72..f2ca1b8ee7 100644 +--- a/src/core/load-fragment.h ++++ b/src/core/load-fragment.h +@@ -102,6 +102,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_job_timeout_sec); + CONFIG_PARSER_PROTOTYPE(config_parse_job_running_timeout_sec); + CONFIG_PARSER_PROTOTYPE(config_parse_log_extra_fields); + CONFIG_PARSER_PROTOTYPE(config_parse_collect_mode); ++CONFIG_PARSER_PROTOTYPE(config_parse_numa_policy); ++CONFIG_PARSER_PROTOTYPE(config_parse_numa_mask); + + /* gperf prototypes */ + const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); +diff --git a/src/core/main.c b/src/core/main.c +index c74dc641c1..83f9dd5878 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -134,6 +134,7 @@ static uint64_t arg_default_tasks_max; + static sd_id128_t arg_machine_id; + static EmergencyAction arg_cad_burst_action; + static CPUSet arg_cpu_affinity; ++static NUMAPolicy arg_numa_policy; + + static int parse_configuration(void); + +@@ -660,6 +661,8 @@ static int parse_config_file(void) { + { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status }, + { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity }, + { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, ++ { "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type }, ++ { "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy }, + { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, + { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog }, + { "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device }, +@@ -1501,6 +1504,27 @@ static void update_cpu_affinity(bool skip_setup) { + log_warning_errno(errno, "Failed to set CPU affinity: %m"); + } + ++static void update_numa_policy(bool skip_setup) { ++ int r; ++ _cleanup_free_ char *nodes = NULL; ++ const char * policy = NULL; ++ ++ if (skip_setup || !mpol_is_valid(numa_policy_get_type(&arg_numa_policy))) ++ return; ++ ++ if (DEBUG_LOGGING) { ++ policy = mpol_to_string(numa_policy_get_type(&arg_numa_policy)); ++ nodes = cpu_set_to_range_string(&arg_numa_policy.nodes); ++ log_debug("Setting NUMA policy to %s, with nodes %s.", strnull(policy), strnull(nodes)); ++ } ++ ++ r = apply_numa_policy(&arg_numa_policy); ++ if (r == -EOPNOTSUPP) ++ log_debug_errno(r, "NUMA support not available, ignoring."); ++ else if (r < 0) ++ log_warning_errno(r, "Failed to set NUMA memory policy: %m"); ++} ++ + static void do_reexecute( + int argc, + char *argv[], +@@ -1672,6 +1696,7 @@ static int invoke_main_loop( + set_manager_defaults(m); + + update_cpu_affinity(false); ++ update_numa_policy(false); + + if (saved_log_level >= 0) + manager_override_log_level(m, saved_log_level); +@@ -1832,6 +1857,7 @@ static int initialize_runtime( + return 0; + + update_cpu_affinity(skip_setup); ++ update_numa_policy(skip_setup); + + if (arg_system) { + /* Make sure we leave a core dump without panicing the kernel. */ +@@ -2011,6 +2037,7 @@ static void reset_arguments(void) { + arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; + + cpu_set_reset(&arg_cpu_affinity); ++ numa_policy_reset(&arg_numa_policy); + } + + static int parse_configuration(void) { +diff --git a/src/core/system.conf.in b/src/core/system.conf.in +index 653ec6b8c9..0d93fbf147 100644 +--- a/src/core/system.conf.in ++++ b/src/core/system.conf.in +@@ -24,6 +24,8 @@ + #CtrlAltDelBurstAction=reboot-force + #CPUAffinity=1 2 + #JoinControllers=cpu,cpuacct net_cls,net_prio ++#NUMAPolicy=default ++#NUMAMask= + #RuntimeWatchdogSec=0 + #ShutdownWatchdogSec=10min + #CapabilityBoundingSet= +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index ec8732c226..055edd6e22 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -947,6 +947,34 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con + return bus_append_byte_array(m, field, array, allocated); + } + ++ if (streq(field, "NUMAPolicy")) { ++ r = mpol_from_string(eq); ++ if (r < 0) ++ return log_error_errno(r, "Failed to parse %s value: %s", field, eq); ++ ++ r = sd_bus_message_append(m, "(sv)", field, "i", (int32_t) r); ++ if (r < 0) ++ return bus_log_create_error(r); ++ ++ return 1; ++ } ++ ++ if (streq(field, "NUMAMask")) { ++ _cleanup_(cpu_set_reset) CPUSet nodes = {}; ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; ++ ++ r = parse_cpu_set(eq, &nodes); ++ if (r < 0) ++ return log_error_errno(r, "Failed to parse %s value: %s", field, eq); ++ ++ r = cpu_set_to_dbus(&nodes, &array, &allocated); ++ if (r < 0) ++ return log_error_errno(r, "Failed to serialize NUMAMask: %m"); ++ ++ return bus_append_byte_array(m, field, array, allocated); ++ } ++ + if (STR_IN_SET(field, "RestrictAddressFamilies", "SystemCallFilter")) { + int whitelist = 1; + const char *p = eq; +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 0154b300a3..7274921e6d 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -4573,6 +4573,20 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool + + switch (bus_type) { + ++ case SD_BUS_TYPE_INT32: ++ if (streq(name, "NUMAPolicy")) { ++ int32_t i; ++ ++ r = sd_bus_message_read_basic(m, bus_type, &i); ++ if (r < 0) ++ return r; ++ ++ print_prop(name, "%s", strna(mpol_to_string(i))); ++ ++ return 1; ++ } ++ break; ++ + case SD_BUS_TYPE_STRUCT: + + if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) { +@@ -4878,7 +4892,7 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool + print_prop(name, "%s", h); + + return 1; +- } else if (contents[0] == SD_BUS_TYPE_BYTE && streq(name, "CPUAffinity")) { ++ } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask")) { + _cleanup_free_ char *affinity = NULL; + _cleanup_(cpu_set_reset) CPUSet set = {}; + const void *a; +@@ -4890,7 +4904,7 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool + + r = cpu_set_from_dbus(a, n, &set); + if (r < 0) +- return log_error_errno(r, "Failed to deserialize CPUAffinity: %m"); ++ return log_error_errno(r, "Failed to deserialize %s: %m", name); + + affinity = cpu_set_to_range_string(&set); + if (!affinity) diff --git a/SOURCES/0289-core-disable-CPUAccounting-by-default.patch b/SOURCES/0289-core-disable-CPUAccounting-by-default.patch new file mode 100644 index 0000000..d250c03 --- /dev/null +++ b/SOURCES/0289-core-disable-CPUAccounting-by-default.patch @@ -0,0 +1,25 @@ +From b47f26558e5234ec8cf2ecc3674c94a87f20ec69 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Thu, 28 Nov 2019 15:47:43 +0100 +Subject: [PATCH] core: disable CPUAccounting by default + +Related: #1734787 + +[RHEL-only] +--- + src/core/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/main.c b/src/core/main.c +index 83f9dd5878..c83249a8dc 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -2026,7 +2026,7 @@ static void reset_arguments(void) { + + /* arg_serialization — ignore */ + +- arg_default_cpu_accounting = -1; ++ arg_default_cpu_accounting = 0; + arg_default_io_accounting = false; + arg_default_ip_accounting = false; + arg_default_blockio_accounting = false; diff --git a/SOURCES/0290-set-kptr_restrict-1.patch b/SOURCES/0290-set-kptr_restrict-1.patch new file mode 100644 index 0000000..5005756 --- /dev/null +++ b/SOURCES/0290-set-kptr_restrict-1.patch @@ -0,0 +1,24 @@ +From cf1a9df1171273fc1ed3f977b5ec52aba27674bf Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Tue, 3 Dec 2019 14:04:00 +0100 +Subject: [PATCH] set kptr_restrict=1 + +Resolves: #1689346 +--- + sysctl.d/50-default.conf | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf +index e263cf0628..e0afc9c702 100644 +--- a/sysctl.d/50-default.conf ++++ b/sysctl.d/50-default.conf +@@ -21,6 +21,9 @@ kernel.sysrq = 16 + # Append the PID to the core filename + kernel.core_uses_pid = 1 + ++# https://bugzilla.redhat.com/show_bug.cgi?id=1689346 ++kernel.kptr_restrict = 1 ++ + # Source route verification + net.ipv4.conf.all.rp_filter = 1 + diff --git a/SOURCES/0291-cryptsetup-reduce-the-chance-that-we-will-be-OOM-kil.patch b/SOURCES/0291-cryptsetup-reduce-the-chance-that-we-will-be-OOM-kil.patch new file mode 100644 index 0000000..48f41cf --- /dev/null +++ b/SOURCES/0291-cryptsetup-reduce-the-chance-that-we-will-be-OOM-kil.patch @@ -0,0 +1,34 @@ +From 40612e4e7690c613cba7ac87b9d782724e623a39 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Wed, 27 Nov 2019 14:27:58 +0100 +Subject: [PATCH] cryptsetup: reduce the chance that we will be OOM killed + +cryptsetup introduced optional locking scheme that should serialize +unlocking keyslots which use memory hard key derivation +function (argon2). Using the serialization should prevent OOM situation +in early boot while unlocking encrypted volumes. + +(cherry picked from commit 408c81f62454684dfbff1c95ce3210d06f256e58) + +Resolves: #1696602 +--- + src/cryptsetup/cryptsetup.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 4e1b3eff19..9071126c2e 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -656,6 +656,12 @@ int main(int argc, char *argv[]) { + if (arg_discards) + flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; + ++#ifdef CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF ++ /* Try to decrease the risk of OOM event if memory hard key derivation function is in use */ ++ /* https://gitlab.com/cryptsetup/cryptsetup/issues/446/ */ ++ flags |= CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF; ++#endif ++ + if (arg_timeout == USEC_INFINITY) + until = 0; + else diff --git a/SOURCES/0292-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch b/SOURCES/0292-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch new file mode 100644 index 0000000..4bfb5ef --- /dev/null +++ b/SOURCES/0292-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch @@ -0,0 +1,136 @@ +From cb084637ba1c8558f1538ce300c5520a6764dc76 Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Mon, 28 Oct 2019 19:35:24 +0900 +Subject: [PATCH] core, job: fix breakage of ordering dependencies by systemctl + reload command + +Currently, systemctl reload command breaks ordering dependencies if it's +executed when its target service unit is in activating state. + +For example, prepare A.service, B.service and C.target as follows: + + # systemctl cat A.service B.service C.target + # /etc/systemd/system/A.service + [Unit] + Description=A + + [Service] + Type=oneshot + ExecStart=/usr/bin/echo A1 + ExecStart=/usr/bin/sleep 60 + ExecStart=/usr/bin/echo A2 + ExecReload=/usr/bin/echo A reloaded + RemainAfterExit=yes + + # /etc/systemd/system/B.service + [Unit] + Description=B + After=A.service + + [Service] + Type=oneshot + ExecStart=/usr/bin/echo B + RemainAfterExit=yes + + # /etc/systemd/system/C.target + [Unit] + Description=C + Wants=A.service B.service + +Start them. + + # systemctl daemon-reload + # systemctl start C.target + +Then, we have: + + # LANG=C journalctl --no-pager -u A.service -u B.service -u C.target -b + -- Logs begin at Mon 2019-09-09 00:25:06 EDT, end at Thu 2019-10-24 22:28:47 EDT. -- + Oct 24 22:27:47 localhost.localdomain systemd[1]: Starting A... + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Child 967 belongs to A.service. + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Running next main command for state start. + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Passing 0 fds to service + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: About to execute: /usr/bin/sleep 60 + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Forked /usr/bin/sleep as 968 + Oct 24 22:27:47 localhost.localdomain systemd[968]: A.service: Executing: /usr/bin/sleep 60 + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Trying to enqueue job A.service/reload/replace + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Merged into running job, re-running: A.service/reload as 1288 + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Enqueued job A.service/reload as 1288 + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Unit cannot be reloaded because it is inactive. + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Job 1288 A.service/reload finished, result=invalid + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Passing 0 fds to service + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: About to execute: /usr/bin/echo B + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Forked /usr/bin/echo as 970 + Oct 24 22:27:52 localhost.localdomain systemd[970]: B.service: Executing: /usr/bin/echo B + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Failed to send unit change signal for B.service: Connection reset by peer + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Changed dead -> start + Oct 24 22:27:52 localhost.localdomain systemd[1]: Starting B... + Oct 24 22:27:52 localhost.localdomain echo[970]: B + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Child 970 belongs to B.service. + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Changed start -> exited + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Job 1371 B.service/start finished, result=done + Oct 24 22:27:52 localhost.localdomain systemd[1]: Started B. + Oct 24 22:27:52 localhost.localdomain systemd[1]: C.target: Job 1287 C.target/start finished, result=done + Oct 24 22:27:52 localhost.localdomain systemd[1]: Reached target C. + Oct 24 22:27:52 localhost.localdomain systemd[1]: C.target: Failed to send unit change signal for C.target: Connection reset by peer + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Child 968 belongs to A.service. + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Running next main command for state start. + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Passing 0 fds to service + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: About to execute: /usr/bin/echo A2 + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Forked /usr/bin/echo as 972 + Oct 24 22:28:47 localhost.localdomain systemd[972]: A.service: Executing: /usr/bin/echo A2 + Oct 24 22:28:47 localhost.localdomain echo[972]: A2 + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Child 972 belongs to A.service. + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Changed start -> exited + +The issue occurs not only in reload command, i.e.: + + - reload + - try-restart + - reload-or-restart + - reload-or-try-restart commands + +The cause of this issue is that job_type_collapse() doesn't take care of the +activating state. + +Fixes: #10464 +(cherry picked from commit d1559793df555212271e490a4a72f55826caf5b4) + +Resolves: #1766417 +--- + src/core/job.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index 8552ffb704..769ed6d603 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -403,21 +403,21 @@ JobType job_type_collapse(JobType t, Unit *u) { + + case JOB_TRY_RESTART: + s = unit_active_state(u); +- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_NOP; + + return JOB_RESTART; + + case JOB_TRY_RELOAD: + s = unit_active_state(u); +- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_NOP; + + return JOB_RELOAD; + + case JOB_RELOAD_OR_START: + s = unit_active_state(u); +- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_START; + + return JOB_RELOAD; diff --git a/SOURCES/0293-debug-generator-enable-custom-systemd.debug_shell-tt.patch b/SOURCES/0293-debug-generator-enable-custom-systemd.debug_shell-tt.patch new file mode 100644 index 0000000..fb40563 --- /dev/null +++ b/SOURCES/0293-debug-generator-enable-custom-systemd.debug_shell-tt.patch @@ -0,0 +1,149 @@ +From 613a02b7d67864af1860e9137e2ee101d603463e Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Thu, 25 Apr 2019 12:19:16 +0200 +Subject: [PATCH] debug-generator: enable custom systemd.debug_shell tty + +(cherry picked from commit 93912e872fb14e9c372e090409e429084a6450f5) + +Resolves: #1723722 +--- + man/custom-entities.ent.in | 1 + + man/systemd-debug-generator.xml | 13 ++++++--- + meson.build | 1 + + src/debug-generator/debug-generator.c | 41 +++++++++++++++++++++------ + 4 files changed, 43 insertions(+), 13 deletions(-) + +diff --git a/man/custom-entities.ent.in b/man/custom-entities.ent.in +index e2bd44e5e7..85805777a0 100644 +--- a/man/custom-entities.ent.in ++++ b/man/custom-entities.ent.in +@@ -8,3 +8,4 @@ + + + ++ +diff --git a/man/systemd-debug-generator.xml b/man/systemd-debug-generator.xml +index fa88e8ac01..25d8b1a873 100644 +--- a/man/systemd-debug-generator.xml ++++ b/man/systemd-debug-generator.xml +@@ -1,6 +1,10 @@ + + +- ++ ++%entities; ++]> + +@@ -57,9 +61,10 @@ + option is + specified, the debug shell service + debug-shell.service is pulled into the boot +- transaction. It will spawn a debug shell on tty9 during early +- system startup. Note that the shell may also be turned on +- persistently by enabling it with ++ transaction and a debug shell will be spawned during early boot. ++ By default, &DEBUGTTY; is used, but a specific tty can also be set, ++ either with or without the /dev/ prefix. ++ Note that the shell may also be turned on persistently by enabling it with + systemctl1's + enable command. + is honored only by initial +diff --git a/meson.build b/meson.build +index fe82ca4ac2..70811c29cf 100644 +--- a/meson.build ++++ b/meson.build +@@ -768,6 +768,7 @@ conf.set_quoted('GETTEXT_PACKAGE', meson.project_name()) + + substs.set('SUSHELL', get_option('debug-shell')) + substs.set('DEBUGTTY', get_option('debug-tty')) ++conf.set_quoted('DEBUGTTY', get_option('debug-tty')) + + enable_debug_hashmap = false + enable_debug_mmap_cache = false +diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c +index 800d31cebe..ddef385833 100644 +--- a/src/debug-generator/debug-generator.c ++++ b/src/debug-generator/debug-generator.c +@@ -1,8 +1,11 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include "alloc-util.h" ++#include "dropin.h" ++#include "generator.h" + #include "mkdir.h" + #include "parse-util.h" ++#include "path-util.h" + #include "proc-cmdline.h" + #include "special.h" + #include "string-util.h" +@@ -14,7 +17,7 @@ static char *arg_default_unit = NULL; + static const char *arg_dest = "/tmp"; + static char **arg_mask = NULL; + static char **arg_wants = NULL; +-static bool arg_debug_shell = false; ++static char *arg_debug_shell = NULL; + + static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r; +@@ -50,15 +53,16 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.debug_shell")) { ++ const char *t = NULL; + +- if (value) { +- r = parse_boolean(value); +- if (r < 0) +- log_error("Failed to parse systemd.debug_shell= argument '%s', ignoring.", value); +- else +- arg_debug_shell = r; +- } else +- arg_debug_shell = true; ++ r = value ? parse_boolean(value) : 1; ++ if (r < 0) ++ t = skip_dev_prefix(value); ++ else if (r > 0) ++ t = skip_dev_prefix(DEBUGTTY); ++ ++ if (free_and_strdup(&arg_debug_shell, t) < 0) ++ return log_oom(); + + } else if (streq(key, "systemd.unit")) { + +@@ -136,6 +140,23 @@ static int generate_wants_symlinks(void) { + return r; + } + ++static void install_debug_shell_dropin(const char *dir) { ++ int r; ++ ++ if (streq(arg_debug_shell, skip_dev_prefix(DEBUGTTY))) ++ return; ++ ++ r = write_drop_in_format(dir, "debug-shell.service", 50, "tty", ++ "[Unit]\n" ++ "Description=Early root shell on /dev/%s FOR DEBUGGING ONLY\n" ++ "ConditionPathExists=\n" ++ "[Service]\n" ++ "TTYPath=/dev/%s", ++ arg_debug_shell, arg_debug_shell); ++ if (r < 0) ++ log_warning_errno(r, "Failed to write drop-in for debug-shell.service, ignoring: %m"); ++} ++ + int main(int argc, char *argv[]) { + int r, q; + +@@ -164,6 +185,8 @@ int main(int argc, char *argv[]) { + r = log_oom(); + goto finish; + } ++ ++ install_debug_shell_dropin(arg_dest); + } + + r = generate_mask_symlinks(); diff --git a/SOURCES/0294-test-cpu-set-util-fix-comparison-for-allocation-size.patch b/SOURCES/0294-test-cpu-set-util-fix-comparison-for-allocation-size.patch new file mode 100644 index 0000000..490a14f --- /dev/null +++ b/SOURCES/0294-test-cpu-set-util-fix-comparison-for-allocation-size.patch @@ -0,0 +1,118 @@ +From f4344bb4055cab8dc3bbe82a7f3d97fc6fabcb7e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 4 Jun 2019 09:19:04 +0200 +Subject: [PATCH] test-cpu-set-util: fix comparison for allocation size + +On i386, __cpu_mask is 4 bytes, so we'd check if c.allocated >= 0, and +gcc would warn about a bogus comparison. Let's round up. + +Fixes #12726. + +(cherry picked from commit a299ce058b41b21c87f36e77e2c563b0ddd1be0d) + +Related: #1734787 +--- + src/test/test-cpu-set-util.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index 9522582891..3456add989 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -17,7 +17,7 @@ static void test_parse_cpu_set(void) { + /* Single value */ + assert_se(parse_cpu_set_full("0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.set); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_ISSET_S(0, c.allocated, c.set)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 1); + +@@ -33,7 +33,7 @@ static void test_parse_cpu_set(void) { + /* Simple range (from CPUAffinity example) */ + assert_se(parse_cpu_set_full("1 2 4", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.set); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_ISSET_S(1, c.allocated, c.set)); + assert_se(CPU_ISSET_S(2, c.allocated, c.set)); + assert_se(CPU_ISSET_S(4, c.allocated, c.set)); +@@ -50,7 +50,7 @@ static void test_parse_cpu_set(void) { + + /* A more interesting range */ + assert_se(parse_cpu_set_full("0 1 2 3 8 9 10 11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); +@@ -68,7 +68,7 @@ static void test_parse_cpu_set(void) { + + /* Quoted strings */ + assert_se(parse_cpu_set_full("8 '9' 10 \"11\"", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 4); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); +@@ -83,7 +83,7 @@ static void test_parse_cpu_set(void) { + + /* Use commas as separators */ + assert_se(parse_cpu_set_full("0,1,2,3 8,9,10,11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); +@@ -96,7 +96,7 @@ static void test_parse_cpu_set(void) { + + /* Commas with spaces (and trailing comma, space) */ + assert_se(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, 63, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 9); + for (cpu = 0; cpu < 8; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); +@@ -113,7 +113,7 @@ static void test_parse_cpu_set(void) { + + /* Ranges */ + assert_se(parse_cpu_set_full("0-3,8-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); +@@ -126,7 +126,7 @@ static void test_parse_cpu_set(void) { + + /* Ranges with trailing comma, space */ + assert_se(parse_cpu_set_full("0-3 8-11, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); +@@ -143,13 +143,13 @@ static void test_parse_cpu_set(void) { + + /* Negative range (returns empty cpu_set) */ + assert_se(parse_cpu_set_full("3-0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 0); + cpu_set_reset(&c); + + /* Overlapping ranges */ + assert_se(parse_cpu_set_full("0-7 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 12); + for (cpu = 0; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); +@@ -164,7 +164,7 @@ static void test_parse_cpu_set(void) { + + /* Mix ranges and individual CPUs */ + assert_se(parse_cpu_set_full("0,2 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); +- assert_se(c.allocated >= sizeof(__cpu_mask) / 8); ++ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 10); + assert_se(CPU_ISSET_S(0, c.allocated, c.set)); + assert_se(CPU_ISSET_S(2, c.allocated, c.set)); diff --git a/SOURCES/0295-test-cpu-set-util-fix-allocation-size-check-on-i386.patch b/SOURCES/0295-test-cpu-set-util-fix-allocation-size-check-on-i386.patch new file mode 100644 index 0000000..cbb8483 --- /dev/null +++ b/SOURCES/0295-test-cpu-set-util-fix-allocation-size-check-on-i386.patch @@ -0,0 +1,30 @@ +From 3cf9361996b796eae0bda12aec8c92ddae1d5d48 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 4 Jun 2019 09:40:38 +0200 +Subject: [PATCH] test-cpu-set-util: fix allocation size check on i386 + +We get just 28 bytes not 32 as on 64-bit architectures (__cpu_set_t is 4 bytes, +we need at least 26, so 28 satisfies the constraints). + +(cherry picked from commit 64412970ac0d4b6f5c4bbd8816edc9bff9eab2de) + +Related: #1734787 +--- + src/test/test-cpu-set-util.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c +index 3456add989..136eaca82d 100644 +--- a/src/test/test-cpu-set-util.c ++++ b/src/test/test-cpu-set-util.c +@@ -256,7 +256,9 @@ static void test_cpu_set_to_from_dbus(void) { + assert_se(array); + assert_se(allocated == c.allocated); + +- assert(memcmp(array, expected, sizeof expected) == 0); ++ assert_se(allocated <= sizeof expected); ++ assert_se(allocated >= DIV_ROUND_UP(201u, 8u)); /* We need at least 201 bits for our mask */ ++ assert(memcmp(array, expected, allocated) == 0); + + assert_se(cpu_set_from_dbus(array, allocated, &c2) == 0); + assert_se(c2.set); diff --git a/SOURCES/0296-catalog-fix-name-of-variable.patch b/SOURCES/0296-catalog-fix-name-of-variable.patch new file mode 100644 index 0000000..1e752eb --- /dev/null +++ b/SOURCES/0296-catalog-fix-name-of-variable.patch @@ -0,0 +1,531 @@ +From c3513c7bcc27210c89edad1740e1190e693df86f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 15 Oct 2018 22:41:49 +0200 +Subject: [PATCH] catalog: fix name of variable + +All the messages would (literally) say "The start-up result is RESULT." +because @RESULT@ was not defined. + +Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1639482 +and the first part of #8005. + +Fixup for 646cc98dc81c4d0edbc1b57e7bca0f474b47e270. + +(cherry picked from commit 65d51875c2a7b27b61de090f1bd6311b0cef2016) + +Resolves: #1677768 +--- + catalog/systemd.be.catalog.in | 6 +++--- + catalog/systemd.be@latin.catalog.in | 6 +++--- + catalog/systemd.bg.catalog.in | 6 +++--- + catalog/systemd.catalog.in | 6 +++--- + catalog/systemd.da.catalog.in | 6 +++--- + catalog/systemd.fr.catalog.in | 6 +++--- + catalog/systemd.hr.catalog.in | 6 +++--- + catalog/systemd.hu.catalog.in | 6 +++--- + catalog/systemd.it.catalog.in | 6 +++--- + catalog/systemd.ko.catalog.in | 6 +++--- + catalog/systemd.pl.catalog.in | 6 +++--- + catalog/systemd.pt_BR.catalog.in | 6 +++--- + catalog/systemd.ru.catalog.in | 6 +++--- + catalog/systemd.sr.catalog.in | 6 +++--- + catalog/systemd.zh_CN.catalog.in | 6 +++--- + catalog/systemd.zh_TW.catalog.in | 6 +++--- + 16 files changed, 48 insertions(+), 48 deletions(-) + +diff --git a/catalog/systemd.be.catalog.in b/catalog/systemd.be.catalog.in +index 5011ea268d..2c59898683 100644 +--- a/catalog/systemd.be.catalog.in ++++ b/catalog/systemd.be.catalog.in +@@ -175,7 +175,7 @@ Support: %SUPPORT_URL% + + Працэс запуску юніта @UNIT@ завершаны. + +-Вынік: @RESULT@. ++Вынік: @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Юніт @UNIT@ спыняецца +@@ -198,7 +198,7 @@ Support: %SUPPORT_URL% + + Збой юніта @UNIT@. + +-Вынік: @RESULT@. ++Вынік: @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: Юніт @UNIT@ перачытвае сваю канфігурацыю +@@ -214,7 +214,7 @@ Support: %SUPPORT_URL% + + Юніт @UNIT@ перачытаў сваю канфігурацыю. + +-Вынік: @RESULT@. ++Вынік: @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Працэс @EXECUTABLE@ не можа быць выкананы +diff --git a/catalog/systemd.be@latin.catalog.in b/catalog/systemd.be@latin.catalog.in +index 6a8b092669..1d024fea12 100644 +--- a/catalog/systemd.be@latin.catalog.in ++++ b/catalog/systemd.be@latin.catalog.in +@@ -178,7 +178,7 @@ Support: %SUPPORT_URL% + + Praces zapusku junita @UNIT@ zavieršany. + +-Vynik: @RESULT@. ++Vynik: @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Junit @UNIT@ spyniajecca +@@ -201,7 +201,7 @@ Support: %SUPPORT_URL% + + Zboj junita @UNIT@. + +-Vynik: @RESULT@. ++Vynik: @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: Junit @UNIT@ pieračytvaje svaju kanfihuracyju +@@ -217,7 +217,7 @@ Support: %SUPPORT_URL% + + Junit @UNIT@ pieračytaŭ svaju kanfihuracyju. + +-Vynik: @RESULT@. ++Vynik: @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Praces @EXECUTABLE@ nie moža być vykanany +diff --git a/catalog/systemd.bg.catalog.in b/catalog/systemd.bg.catalog.in +index 64d616f381..41f7b21bce 100644 +--- a/catalog/systemd.bg.catalog.in ++++ b/catalog/systemd.bg.catalog.in +@@ -178,7 +178,7 @@ Support: %SUPPORT_URL% + + Стартирането на модул „@UNIT@“ завърши. + +-Резултатът е: @RESULT@ ++Резултатът е: @JOB_RESULT@ + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Модул „@UNIT@“ се спира +@@ -201,7 +201,7 @@ Support: %SUPPORT_URL% + + Модулът „@UNIT@“ не успя да стартира. + +-Резултатът е: @RESULT@ ++Резултатът е: @JOB_RESULT@ + + -- d34d037fff1847e6ae669a370e694725 + Subject: Модулът „@UNIT@“ започна презареждане на настройките си +@@ -217,7 +217,7 @@ Support: %SUPPORT_URL% + + Модулът „@UNIT@“ завърши презареждането на настройките си. + +-Резултатът e: @RESULT@ ++Резултатът e: @JOB_RESULT@ + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Програмата „@EXECUTABLE@“ не успя да се стартира +diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in +index 8234e387cf..49a45890f6 100644 +--- a/catalog/systemd.catalog.in ++++ b/catalog/systemd.catalog.in +@@ -202,7 +202,7 @@ Support: %SUPPORT_URL% + + Unit @UNIT@ has finished starting up. + +-The start-up result is @RESULT@. ++The start-up result is @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Unit @UNIT@ has begun shutting down +@@ -225,7 +225,7 @@ Support: %SUPPORT_URL% + + Unit @UNIT@ has failed. + +-The result is @RESULT@. ++The result is @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: Unit @UNIT@ has begun reloading its configuration +@@ -241,7 +241,7 @@ Support: %SUPPORT_URL% + + Unit @UNIT@ has finished reloading its configuration + +-The result is @RESULT@. ++The result is @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Process @EXECUTABLE@ could not be executed +diff --git a/catalog/systemd.da.catalog.in b/catalog/systemd.da.catalog.in +index 4e2bec8a0f..aecfafa05f 100644 +--- a/catalog/systemd.da.catalog.in ++++ b/catalog/systemd.da.catalog.in +@@ -159,7 +159,7 @@ Support: %SUPPORT_URL% + + Enhed @UNIT@ er færdig med at starte op. + +-Resultat for opstart er @RESULT@. ++Resultat for opstart er @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Enhed @UNIT@ har påbegyndt nedlukning +@@ -182,7 +182,7 @@ Support: %SUPPORT_URL% + + Enhed @UNIT@ har fejlet. + +-Resultatet er @RESULT@ ++Resultatet er @JOB_RESULT@ + + -- d34d037fff1847e6ae669a370e694725 + Subject: Enhed @UNIT@ har påbegyndt genindlæsning af sin konfiguration +@@ -198,7 +198,7 @@ Support: %SUPPORT_URL% + + Enhed @UNIT@ er færdig med at genindlæse sin konfiguration + +-Resultatet er: @RESULT@. ++Resultatet er: @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Process @EXECUTABLE@ kunne ikke eksekveres +diff --git a/catalog/systemd.fr.catalog.in b/catalog/systemd.fr.catalog.in +index 156b1a37dc..13edd083cb 100644 +--- a/catalog/systemd.fr.catalog.in ++++ b/catalog/systemd.fr.catalog.in +@@ -191,7 +191,7 @@ Subject: L'unité (unit) @UNIT@ a terminé son démarrage + Defined-By: systemd + Support: %SUPPORT_URL% + +-L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @RESULT@. ++L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: L'unité (unit) @UNIT@ a commencé à s'arrêter +@@ -212,7 +212,7 @@ Subject: L'unité (unit) @UNIT@ a échoué + Defined-By: systemd + Support: %SUPPORT_URL% + +-L'unité (unit) @UNIT@ a échoué, avec le résultat @RESULT@. ++L'unité (unit) @UNIT@ a échoué, avec le résultat @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: L'unité (unit) @UNIT@ a commencé à recharger sa configuration +@@ -227,7 +227,7 @@ Defined-By: systemd + Support: %SUPPORT_URL% + + L'unité (unit) @UNIT@ a terminé de recharger configuration, +-avec le résultat @RESULT@. ++avec le résultat @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Le processus @EXECUTABLE@ n'a pas pu être exécuté +diff --git a/catalog/systemd.hr.catalog.in b/catalog/systemd.hr.catalog.in +index c4808b4c7d..4526ae2a8c 100644 +--- a/catalog/systemd.hr.catalog.in ++++ b/catalog/systemd.hr.catalog.in +@@ -173,7 +173,7 @@ Support: %SUPPORT_URL% + + Jedinica @UNIT@ je završila pokretanje. + +-Rezultat pokretanja je @RESULT@. ++Rezultat pokretanja je @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Jedinica @UNIT@ je započela isključivanje +@@ -196,7 +196,7 @@ Support: %SUPPORT_URL% + + Jedinica @UNIT@ nije uspjela. + +-Rezultat je @RESULT@. ++Rezultat je @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: Jedinica @UNIT@ je započela ponovno učitavati podešavanja +@@ -212,7 +212,7 @@ Support: %SUPPORT_URL% + + Jedinica @UNIT@ je završila ponovno učitavati podešavanja + +-Rezultat je @RESULT@. ++Rezultat je @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Proces @EXECUTABLE@ se ne može pokrenuti +diff --git a/catalog/systemd.hu.catalog.in b/catalog/systemd.hu.catalog.in +index 6c6d7e7934..5565b80b2a 100644 +--- a/catalog/systemd.hu.catalog.in ++++ b/catalog/systemd.hu.catalog.in +@@ -161,7 +161,7 @@ Support: %SUPPORT_URL% + + A(z) @UNIT@ egység befejezte az indulást + +-Az indítás eredménye: @RESULT@. ++Az indítás eredménye: @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: A(z) @UNIT@ egység megkezdte a leállást +@@ -184,7 +184,7 @@ Support: %SUPPORT_URL% + + A(z) @UNIT@ egység hibát jelzett. + +-Az eredmény: @RESULT@. ++Az eredmény: @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: A(z) @UNIT@ egység megkezdte a beállításainak újratöltését +@@ -200,7 +200,7 @@ Support: %SUPPORT_URL% + + A(z) @UNIT@ egység befejezte a beállításainak újratöltését. + +-Az eredmény: @RESULT@. ++Az eredmény: @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: A folyamat végrehajtása sikertelen: @EXECUTABLE@ +diff --git a/catalog/systemd.it.catalog.in b/catalog/systemd.it.catalog.in +index 4fd1f2a933..8ce4fa5d92 100644 +--- a/catalog/systemd.it.catalog.in ++++ b/catalog/systemd.it.catalog.in +@@ -191,7 +191,7 @@ Support: %SUPPORT_URL% + + L'unità @UNIT@ ha terminato la fase di avvio. + +-La fase di avvio è @RESULT@. ++La fase di avvio è @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: L'unità @UNIT@ inizia la fase di spegnimento +@@ -214,7 +214,7 @@ Support: %SUPPORT_URL% + + L'unità @UNIT@ è fallita. + +-Il risultato è @RESULT@. ++Il risultato è @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: L'unità @UNIT@ inizia a caricare la propria configurazione +@@ -230,7 +230,7 @@ Support: %SUPPORT_URL% + + L'unità @UNIT@ è terminata ricaricando la propria configurazione + +-Il risultato è @RESULT@. ++Il risultato è @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Il processo @EXECUTABLE@ non può essere eseguito +diff --git a/catalog/systemd.ko.catalog.in b/catalog/systemd.ko.catalog.in +index fc0faad02c..59fbde8b62 100644 +--- a/catalog/systemd.ko.catalog.in ++++ b/catalog/systemd.ko.catalog.in +@@ -182,7 +182,7 @@ Support: %SUPPORT_URL% + + @UNIT@ 유닛 시동을 마쳤습니다. + +-시동 결과는 @RESULT@ 입니다. ++시동 결과는 @JOB_RESULT@ 입니다. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: @UNIT@ 유닛 끝내기 동작 시작 +@@ -205,7 +205,7 @@ Support: %SUPPORT_URL% + + @UNIT@ 유닛 동작에 실패했습니다. + +-결과는 @RESULT@ 입니다. ++결과는 @JOB_RESULT@ 입니다. + + -- d34d037fff1847e6ae669a370e694725 + Subject: @UNIT@ 유닛 설정 다시 읽기 시작 +@@ -221,7 +221,7 @@ Support: %SUPPORT_URL% + + @UNIT@ 유닛의 설정 다시 읽기 동작을 끝냈습니다. + +-결과는 @RESULT@ 입니다. ++결과는 @JOB_RESULT@ 입니다. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: @EXECUTABLE@ 프로세스 시작할 수 없음 +diff --git a/catalog/systemd.pl.catalog.in b/catalog/systemd.pl.catalog.in +index 998894bd0a..b73f56ca11 100644 +--- a/catalog/systemd.pl.catalog.in ++++ b/catalog/systemd.pl.catalog.in +@@ -201,7 +201,7 @@ Support: %SUPPORT_URL% + + Jednostka @UNIT@ ukończyła uruchamianie. + +-Wynik uruchamiania: @RESULT@. ++Wynik uruchamiania: @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Rozpoczęto wyłączanie jednostki @UNIT@ +@@ -224,7 +224,7 @@ Support: %SUPPORT_URL% + + Jednostka @UNIT@ się nie powiodła. + +-Wynik: @RESULT@. ++Wynik: @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: Rozpoczęto ponowne wczytywanie konfiguracji jednostki @UNIT@ +@@ -240,7 +240,7 @@ Support: %SUPPORT_URL% + + Jednostka @UNIT@ ukończyła ponowne wczytywanie swojej konfiguracji. + +-Wynik: @RESULT@. ++Wynik: @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Nie można wykonać procesu @EXECUTABLE@ +diff --git a/catalog/systemd.pt_BR.catalog.in b/catalog/systemd.pt_BR.catalog.in +index db1cb03198..edaefb7164 100644 +--- a/catalog/systemd.pt_BR.catalog.in ++++ b/catalog/systemd.pt_BR.catalog.in +@@ -162,7 +162,7 @@ Support: %SUPPORT_URL% + + A unidade @UNIT@ concluiu a inicialização. + +-The start-up result is @RESULT@. ++The start-up result is @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Unidade @UNIT@ sendo desligado +@@ -185,7 +185,7 @@ Support: %SUPPORT_URL% + + A unidade @UNIT@ falhou. + +-O resultado é @RESULT@. ++O resultado é @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: Unidade @UNIT@ iniciou recarregamento de sua configuração +@@ -201,7 +201,7 @@ Support: %SUPPORT_URL% + + A unidade @UNIT@ concluiu o recarregamento de sua configuração. + +-O resultado é @RESULT@. ++O resultado é @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Processo @EXECUTABLE@ não pôde ser executado +diff --git a/catalog/systemd.ru.catalog.in b/catalog/systemd.ru.catalog.in +index 645edaa922..ccdc685037 100644 +--- a/catalog/systemd.ru.catalog.in ++++ b/catalog/systemd.ru.catalog.in +@@ -227,7 +227,7 @@ Support: %SUPPORT_URL% + + Процесс запуска юнита @UNIT@ был завершен. + +-Результат: @RESULT@. ++Результат: @JOB_RESULT@. + + # Subject: Unit @UNIT@ has begun shutting down + -- de5b426a63be47a7b6ac3eaac82e2f6f +@@ -253,7 +253,7 @@ Support: %SUPPORT_URL% + + Произошел сбой юнита @UNIT@. + +-Результат: @RESULT@. ++Результат: @JOB_RESULT@. + + # Subject: Unit @UNIT@ has begun with reloading its configuration + -- d34d037fff1847e6ae669a370e694725 +@@ -271,7 +271,7 @@ Support: %SUPPORT_URL% + + Юнит @UNIT@ завершил процесс перечитывания своей конфигурации. + +-Результат: @RESULT@. ++Результат: @JOB_RESULT@. + + # Subject: Process @EXECUTABLE@ could not be executed + -- 641257651c1b4ec9a8624d7a40a9e1e7 +diff --git a/catalog/systemd.sr.catalog.in b/catalog/systemd.sr.catalog.in +index f5746715a4..7cb6546d43 100644 +--- a/catalog/systemd.sr.catalog.in ++++ b/catalog/systemd.sr.catalog.in +@@ -158,7 +158,7 @@ Support: %SUPPORT_URL% + + Јединица @UNIT@ је завршила са покретањем. + +-Исход покретања је @RESULT@. ++Исход покретања је @JOB_RESULT@. + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: Јединица @UNIT@ је почела са гашењем +@@ -181,7 +181,7 @@ Support: %SUPPORT_URL% + + Јединица @UNIT@ је пукла. + +-Исход је @RESULT@. ++Исход је @JOB_RESULT@. + + -- d34d037fff1847e6ae669a370e694725 + Subject: Јединица @UNIT@ је почела са поновним учитавањем свог подешавања +@@ -197,7 +197,7 @@ Support: %SUPPORT_URL% + + Јединица @UNIT@ је завршила са поновним учитавањем свог подешавања + +-Исход је @RESULT@. ++Исход је @JOB_RESULT@. + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: Процес @EXECUTABLE@ није могао бити извршен +diff --git a/catalog/systemd.zh_CN.catalog.in b/catalog/systemd.zh_CN.catalog.in +index fa58448acf..d6ac2592b8 100644 +--- a/catalog/systemd.zh_CN.catalog.in ++++ b/catalog/systemd.zh_CN.catalog.in +@@ -156,7 +156,7 @@ Support: %SUPPORT_URL% + + @UNIT@ 单元已结束启动。 + +-启动结果为“@RESULT@”。 ++启动结果为“@JOB_RESULT@”。 + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: @UNIT@ 单元已开始停止操作 +@@ -179,7 +179,7 @@ Support: %SUPPORT_URL% + + @UNIT@ 单元已失败。 + +-结果为“@RESULT@”。 ++结果为“@JOB_RESULT@”。 + + -- d34d037fff1847e6ae669a370e694725 + Subject: @UNIT@ 单元已开始重新载入其配置 +@@ -195,7 +195,7 @@ Support: %SUPPORT_URL% + + @UNIT@ 单元已结束配置重载入操作。 + +-结果为“@RESULT@”。 ++结果为“@JOB_RESULT@”。 + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: 进程 @EXECUTABLE@ 无法执行 +diff --git a/catalog/systemd.zh_TW.catalog.in b/catalog/systemd.zh_TW.catalog.in +index 17bd2bc9af..a468c2f6bf 100644 +--- a/catalog/systemd.zh_TW.catalog.in ++++ b/catalog/systemd.zh_TW.catalog.in +@@ -160,7 +160,7 @@ Support: %SUPPORT_URL% + + 單位 @UNIT@ 啟動已結束。 + +-啟動結果為 @RESULT@。 ++啟動結果為 @JOB_RESULT@。 + + -- de5b426a63be47a7b6ac3eaac82e2f6f + Subject: 單位 @UNIT@ 已開始關閉 +@@ -183,7 +183,7 @@ Support: %SUPPORT_URL% + + 單位 @UNIT@ 已失敗。 + +-結果為 @RESULT@。 ++結果為 @JOB_RESULT@。 + + -- d34d037fff1847e6ae669a370e694725 + Subject: 單位 @UNIT@ 已開始重新載入其設定 +@@ -199,7 +199,7 @@ Support: %SUPPORT_URL% + + 單位 @UNIT@ 已結束重新載入其設定 + +-結果為 @RESULT@。 ++結果為 @JOB_RESULT@。 + + -- 641257651c1b4ec9a8624d7a40a9e1e7 + Subject: 行程 @EXECUTABLE@ 無法執行 diff --git a/SOURCES/0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch b/SOURCES/0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch new file mode 100644 index 0000000..8e99e2f --- /dev/null +++ b/SOURCES/0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch @@ -0,0 +1,273 @@ +From 0f7a4f49a7ce95e87061afe03ac40662a1eb0e2d Mon Sep 17 00:00:00 2001 +From: shinygold <10763595+shinygold@users.noreply.github.com> +Date: Tue, 16 Jul 2019 13:06:16 +0200 +Subject: [PATCH] cryptsetup: add keyfile-timeout to allow a keydev timeout and + allow to fallback to a password if it fails. + +(cherry picked from commit 50d2eba27b9bfc77ef6b40e5721713846815418b) + +Resolves: #1763155 +--- + src/cryptsetup/cryptsetup-generator.c | 119 ++++++++++++++++++-------- + src/cryptsetup/cryptsetup.c | 5 +- + 2 files changed, 89 insertions(+), 35 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 52c1262728..1e8e3ba00d 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -40,10 +40,39 @@ static Hashmap *arg_disks = NULL; + static char *arg_default_options = NULL; + static char *arg_default_keyfile = NULL; + +-static int generate_keydev_mount(const char *name, const char *keydev, char **unit, char **mount) { +- _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL; ++static int split_keyspec(const char *keyspec, char **keyfile, char **keydev) { ++ _cleanup_free_ char *kfile = NULL, *kdev = NULL; ++ char *c; ++ ++ assert(keyspec); ++ assert(keyfile); ++ assert(keydev); ++ ++ c = strrchr(keyspec, ':'); ++ if (c) { ++ kfile = strndup(keyspec, c-keyspec); ++ kdev = strdup(c + 1); ++ if (!*kfile || !*kdev) ++ return log_oom(); ++ } else { ++ /* No keydev specified */ ++ kfile = strdup(keyspec); ++ kdev = NULL; ++ if (!*kfile) ++ return log_oom(); ++ } ++ ++ *keyfile = TAKE_PTR(kfile); ++ *keydev = TAKE_PTR(kdev); ++ ++ return 0; ++} ++ ++static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) { ++ _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; ++ usec_t timeout_us; + + assert(name); + assert(keydev); +@@ -88,7 +117,25 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un + "[Mount]\n" + "What=%s\n" + "Where=%s\n" +- "Options=ro\n", what, where); ++ "Options=ro%s\n", what, where, canfail ? ",nofail" : ""); ++ ++ if (keydev_timeout) { ++ r = parse_sec_fix_0(keydev_timeout, &timeout_us); ++ if (r >= 0) { ++ r = unit_name_from_path(what, ".device", &device_unit); ++ if (r < 0) ++ return log_error_errno(r, "Failed to generate unit name: %m"); ++ ++ r = write_drop_in_format(arg_dest, device_unit, 90, "device-timeout", ++ "# Automatically generated by systemd-cryptsetup-generator \n\n" ++ "[Unit]\nJobRunningTimeoutSec=%s", keydev_timeout); ++ if (r < 0) ++ return log_error_errno(r, "Failed to write device drop-in: %m"); ++ ++ } else ++ log_warning_errno(r, "Failed to parse %s, ignoring: %m", keydev_timeout); ++ ++ } + + r = fflush_and_check(f); + if (r < 0) +@@ -103,16 +150,17 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un + static int create_disk( + const char *name, + const char *device, +- const char *keydev, + const char *password, ++ const char *keydev, + const char *options) { + + _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL, +- *filtered = NULL, *u_escaped = NULL, *password_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL, *keydev_mount = NULL; ++ *keydev_mount = NULL, *keyfile_timeout_value = NULL, *password_escaped = NULL, ++ *filtered = NULL, *u_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *dmname; + bool noauto, nofail, tmp, swap, netdev; +- int r; ++ int r, keyfile_can_timeout; + + assert(name); + assert(device); +@@ -123,6 +171,10 @@ static int create_disk( + swap = fstab_test_option(options, "swap\0"); + netdev = fstab_test_option(options, "_netdev\0"); + ++ keyfile_can_timeout = fstab_filter_options(options, "keyfile-timeout\0", NULL, &keyfile_timeout_value, NULL); ++ if (keyfile_can_timeout < 0) ++ return log_error_errno(keyfile_can_timeout, "Failed to parse keyfile-timeout= option value: %m"); ++ + if (tmp && swap) { + log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name); + return -EINVAL; +@@ -152,12 +204,6 @@ static int create_disk( + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + +- if (password) { +- password_escaped = specifier_escape(password); +- if (!password_escaped) +- return log_oom(); +- } +- + if (keydev && !password) { + log_error("Key device is specified, but path to the password file is missing."); + return -EINVAL; +@@ -178,10 +224,16 @@ static int create_disk( + "After=%s\n", + netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target"); + ++ if (password) { ++ password_escaped = specifier_escape(password); ++ if (!password_escaped) ++ return log_oom(); ++ } ++ + if (keydev) { + _cleanup_free_ char *unit = NULL, *p = NULL; + +- r = generate_keydev_mount(name, keydev, &unit, &keydev_mount); ++ r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount); + if (r < 0) + return log_error_errno(r, "Failed to generate keydev mount unit: %m"); + +@@ -190,6 +242,12 @@ static int create_disk( + return log_oom(); + + free_and_replace(password_escaped, p); ++ ++ fprintf(f, "After=%s\n", unit); ++ if (keyfile_can_timeout > 0) ++ fprintf(f, "Wants=%s\n", unit); ++ else ++ fprintf(f, "Requires=%s\n", unit); + } + + if (!nofail) +@@ -197,7 +255,7 @@ static int create_disk( + "Before=%s\n", + netdev ? "remote-cryptsetup.target" : "cryptsetup.target"); + +- if (password) { ++ if (password && !keydev) { + if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random")) + fputs("After=systemd-random-seed.service\n", f); + else if (!STR_IN_SET(password, "-", "none")) { +@@ -271,7 +329,7 @@ static int create_disk( + + if (keydev) + fprintf(f, +- "ExecStartPost=" UMOUNT_PATH " %s\n\n", ++ "ExecStartPost=-" UMOUNT_PATH " %s\n\n", + keydev_mount); + + r = fflush_and_check(f); +@@ -394,7 +452,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat + } else if (streq(key, "luks.key")) { + size_t n; + _cleanup_free_ char *keyfile = NULL, *keydev = NULL; +- char *c; + const char *keyspec; + + if (proc_cmdline_value_missing(key, value)) +@@ -421,23 +478,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat + return log_oom(); + + keyspec = value + n + 1; +- c = strrchr(keyspec, ':'); +- if (c) { +- *c = '\0'; +- keyfile = strdup(keyspec); +- keydev = strdup(c + 1); +- +- if (!keyfile || !keydev) +- return log_oom(); +- } else { +- /* No keydev specified */ +- keyfile = strdup(keyspec); +- if (!keyfile) +- return log_oom(); +- } ++ r = split_keyspec(keyspec, &keyfile, &keydev); ++ if (r < 0) ++ return r; + + free_and_replace(d->keyfile, keyfile); + free_and_replace(d->keydev, keydev); ++ + } else if (streq(key, "luks.name")) { + + if (proc_cmdline_value_missing(key, value)) +@@ -485,7 +532,7 @@ static int add_crypttab_devices(void) { + int r, k; + char line[LINE_MAX], *l, *uuid; + crypto_device *d = NULL; +- _cleanup_free_ char *name = NULL, *device = NULL, *keyfile = NULL, *options = NULL; ++ _cleanup_free_ char *name = NULL, *device = NULL, *keydev = NULL, *keyfile = NULL, *keyspec = NULL, *options = NULL; + + if (!fgets(line, sizeof(line), f)) + break; +@@ -496,7 +543,7 @@ static int add_crypttab_devices(void) { + if (IN_SET(*l, 0, '#')) + continue; + +- k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyfile, &options); ++ k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyspec, &options); + if (k < 2 || k > 4) { + log_error("Failed to parse /etc/crypttab:%u, ignoring.", crypttab_line); + continue; +@@ -515,7 +562,11 @@ static int add_crypttab_devices(void) { + continue; + } + +- r = create_disk(name, device, NULL, keyfile, (d && d->options) ? d->options : options); ++ r = split_keyspec(keyspec, &keyfile, &keydev); ++ if (r < 0) ++ return r; ++ ++ r = create_disk(name, device, keyfile, keydev, (d && d->options) ? d->options : options); + if (r < 0) + return r; + +@@ -555,7 +606,7 @@ static int add_proc_cmdline_devices(void) { + else + options = "timeout=0"; + +- r = create_disk(d->name, device, d->keydev, d->keyfile ?: arg_default_keyfile, options); ++ r = create_disk(d->name, device, d->keyfile ?: arg_default_keyfile, d->keydev, options); + if (r < 0) + return r; + } +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 9071126c2e..0881aea915 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -69,7 +69,10 @@ static int parse_one_option(const char *option) { + assert(option); + + /* Handled outside of this tool */ +- if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail", "_netdev")) ++ if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail", "_netdev", "keyfile-timeout")) ++ return 0; ++ ++ if (startswith(option, "keyfile-timeout=")) + return 0; + + if ((val = startswith(option, "cipher="))) { diff --git a/SOURCES/0298-cryptsetup-add-documentation-for-keyfile-timeout.patch b/SOURCES/0298-cryptsetup-add-documentation-for-keyfile-timeout.patch new file mode 100644 index 0000000..c43658a --- /dev/null +++ b/SOURCES/0298-cryptsetup-add-documentation-for-keyfile-timeout.patch @@ -0,0 +1,44 @@ +From fdb86185b56619c59602c6546fd0710eec4a6e85 Mon Sep 17 00:00:00 2001 +From: shinygold <10763595+shinygold@users.noreply.github.com> +Date: Tue, 16 Jul 2019 13:05:34 +0200 +Subject: [PATCH] cryptsetup: add documentation for keyfile-timeout + +(cherry picked from commit 4e1334512debb27f4a0c4a6da237a4b8d59fea08) + +Related: #1763155 +--- + man/crypttab.xml | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/man/crypttab.xml b/man/crypttab.xml +index 3574ce00da..6074315980 100644 +--- a/man/crypttab.xml ++++ b/man/crypttab.xml +@@ -150,6 +150,17 @@ + sequential order. + + ++ ++ ++ ++ Specifies the timeout for the device on ++ which the key file resides and falls back to a password if ++ it could not be mounted. See ++ systemd-cryptsetup-generator8 ++ for key files on external devices. ++ ++ ++ + + + +@@ -417,7 +428,8 @@ + luks UUID=2505567a-9e27-4efe-a4d5-15ad146c258b + swap /dev/sda7 /dev/urandom swap + truecrypt /dev/sda2 /etc/container_password tcrypt +-hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile ++hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile ++external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s + + + diff --git a/SOURCES/0299-cryptsetup-use-unabbrieviated-variable-names.patch b/SOURCES/0299-cryptsetup-use-unabbrieviated-variable-names.patch new file mode 100644 index 0000000..be86edd --- /dev/null +++ b/SOURCES/0299-cryptsetup-use-unabbrieviated-variable-names.patch @@ -0,0 +1,63 @@ +From 0577d8378645c1ecd909b74403cefe31ed569398 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 1 Aug 2019 08:13:13 +0200 +Subject: [PATCH] cryptsetup: use unabbrieviated variable names + +Now that "ret_" has been added to the output variables, we can name +the internal variables without artificial abbrevs. + +(cherry picked from commit 5d2100dc4c32abbce4109e75cbfbbef6e1b2b7b1) + +Related: #1763155 +--- + src/cryptsetup/cryptsetup-generator.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 1e8e3ba00d..7b234e37be 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -40,30 +40,30 @@ static Hashmap *arg_disks = NULL; + static char *arg_default_options = NULL; + static char *arg_default_keyfile = NULL; + +-static int split_keyspec(const char *keyspec, char **keyfile, char **keydev) { +- _cleanup_free_ char *kfile = NULL, *kdev = NULL; +- char *c; ++static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_keydev) { ++ _cleanup_free_ char *keyfile = NULL, *keydev = NULL; ++ const char *c; + + assert(keyspec); +- assert(keyfile); +- assert(keydev); ++ assert(ret_keyfile); ++ assert(ret_keydev); + + c = strrchr(keyspec, ':'); + if (c) { +- kfile = strndup(keyspec, c-keyspec); +- kdev = strdup(c + 1); +- if (!*kfile || !*kdev) ++ keyfile = strndup(keyspec, c-keyspec); ++ keydev = strdup(c + 1); ++ if (!keyfile || !keydev) + return log_oom(); + } else { + /* No keydev specified */ +- kfile = strdup(keyspec); +- kdev = NULL; +- if (!*kfile) ++ keyfile = strdup(keyspec); ++ keydev = NULL; ++ if (!keyfile) + return log_oom(); + } + +- *keyfile = TAKE_PTR(kfile); +- *keydev = TAKE_PTR(kdev); ++ *ret_keyfile = TAKE_PTR(keyfile); ++ *ret_keydev = TAKE_PTR(keydev); + + return 0; + } diff --git a/SOURCES/0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch b/SOURCES/0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch new file mode 100644 index 0000000..7154dca --- /dev/null +++ b/SOURCES/0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch @@ -0,0 +1,37 @@ +From 5cdb2b0b2a0f8f89f97053b0633b8419506d4e28 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 1 Aug 2019 08:15:43 +0200 +Subject: [PATCH] cryptsetup: don't assert on variable which is optional + +https://github.com/systemd/systemd/commit/50d2eba27b9bfc77ef6b40e5721713846815418b#commitcomment-34519739 + +In add_crypttab_devices() split_keyspec is called on the keyfile argument, +which may be NULL. + +(cherry picked from commit fef716b28be6e866b8afe995805d5ebe2af6bbfa) + +Related: #1763155 +--- + src/cryptsetup/cryptsetup-generator.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 7b234e37be..a09983b576 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -44,10 +44,14 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key + _cleanup_free_ char *keyfile = NULL, *keydev = NULL; + const char *c; + +- assert(keyspec); + assert(ret_keyfile); + assert(ret_keydev); + ++ if (!keyspec) { ++ *ret_keyfile = *ret_keydev = NULL; ++ return 0; ++ } ++ + c = strrchr(keyspec, ':'); + if (c) { + keyfile = strndup(keyspec, c-keyspec); diff --git a/SOURCES/0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch b/SOURCES/0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch new file mode 100644 index 0000000..0f394ac --- /dev/null +++ b/SOURCES/0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch @@ -0,0 +1,100 @@ +From 9040e15cd3cba546b47aeae0ea133afa1a6ad292 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 13 Nov 2019 10:32:30 +0100 +Subject: [PATCH] cryptsetup-generator: guess whether the keyfile argument is + two items or one + +Fixes #13615. + +See the inline comment for documentation. + +(cherry picked from commit 32c6237a7c2e697d2fc4f3403319db16858fb8e3) + +Related: #1763155 +--- + src/cryptsetup/cryptsetup-generator.c | 45 ++++++++++++++++++--------- + 1 file changed, 30 insertions(+), 15 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index a09983b576..4117930925 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -54,17 +54,36 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key + + c = strrchr(keyspec, ':'); + if (c) { +- keyfile = strndup(keyspec, c-keyspec); +- keydev = strdup(c + 1); +- if (!keyfile || !keydev) ++ /* The keydev part has to be either an absolute path to device node (/dev/something, ++ * /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device ++ * specification starting with LABEL= or similar. The keyfile part has the same syntax. ++ * ++ * Let's try to guess if the second part looks like a keydev specification, or just part of a ++ * filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to ++ * an absolute path. If we didn't get an absolute path, assume that it is just part of the ++ * first keyfile argument. */ ++ ++ keydev = fstab_node_to_udev_node(c + 1); ++ if (!keydev) + return log_oom(); +- } else { ++ ++ if (path_is_absolute(keydev)) ++ keyfile = strndup(keyspec, c-keyspec); ++ else { ++ log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n" ++ "Assuming that \"%s\" is a single device specification.", ++ c + 1, keyspec); ++ keydev = mfree(keydev); ++ c = NULL; ++ } ++ } ++ ++ if (!c) + /* No keydev specified */ + keyfile = strdup(keyspec); +- keydev = NULL; +- if (!keyfile) +- return log_oom(); +- } ++ ++ if (!keyfile) ++ return log_oom(); + + *ret_keyfile = TAKE_PTR(keyfile); + *ret_keydev = TAKE_PTR(keydev); +@@ -73,7 +92,7 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key + } + + static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) { +- _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL; ++ _cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + usec_t timeout_us; +@@ -111,22 +130,18 @@ static int generate_keydev_mount(const char *name, const char *keydev, const cha + if (r < 0) + return r; + +- what = fstab_node_to_udev_node(keydev); +- if (!what) +- return -ENOMEM; +- + fprintf(f, + "[Unit]\n" + "DefaultDependencies=no\n\n" + "[Mount]\n" + "What=%s\n" + "Where=%s\n" +- "Options=ro%s\n", what, where, canfail ? ",nofail" : ""); ++ "Options=ro%s\n", keydev, where, canfail ? ",nofail" : ""); + + if (keydev_timeout) { + r = parse_sec_fix_0(keydev_timeout, &timeout_us); + if (r >= 0) { +- r = unit_name_from_path(what, ".device", &device_unit); ++ r = unit_name_from_path(keydev, ".device", &device_unit); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + diff --git a/SOURCES/0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch b/SOURCES/0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch new file mode 100644 index 0000000..f7c2454 --- /dev/null +++ b/SOURCES/0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch @@ -0,0 +1,46 @@ +From 05e184dea3f0182e5787812adfd52b68cff9418d Mon Sep 17 00:00:00 2001 +From: Jan Janssen +Date: Mon, 25 Jun 2018 20:33:31 +0200 +Subject: [PATCH] crypt-util: Translate libcryptsetup log level instead of + using log_debug() + +This makes sure that errors reported by libcryptsetup are shown to the +user instead of getting swallowed up by log_debug(). + +(cherry picked from commit aa2cc005d77890b07e8c579f25e1333ff8ba8dac) + +Resolves: #1776408 +--- + src/basic/crypt-util.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/src/basic/crypt-util.c b/src/basic/crypt-util.c +index b181ba3ba0..20bdc5489e 100644 +--- a/src/basic/crypt-util.c ++++ b/src/basic/crypt-util.c +@@ -5,6 +5,24 @@ + #include "log.h" + + void cryptsetup_log_glue(int level, const char *msg, void *usrptr) { +- log_debug("%s", msg); ++ switch (level) { ++ case CRYPT_LOG_NORMAL: ++ level = LOG_NOTICE; ++ break; ++ case CRYPT_LOG_ERROR: ++ level = LOG_ERR; ++ break; ++ case CRYPT_LOG_VERBOSE: ++ level = LOG_INFO; ++ break; ++ case CRYPT_LOG_DEBUG: ++ level = LOG_DEBUG; ++ break; ++ default: ++ log_error("Unknown libcryptsetup log level: %d", level); ++ level = LOG_ERR; ++ } ++ ++ log_full(level, "%s", msg); + } + #endif diff --git a/SOURCES/0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch b/SOURCES/0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch new file mode 100644 index 0000000..e8f6f83 --- /dev/null +++ b/SOURCES/0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch @@ -0,0 +1,25 @@ +From ea0c4c31f6dff7d01e585bd8d5f962b373844544 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 21 Jan 2019 20:13:11 +0100 +Subject: [PATCH] cryptsetup: add some commenting about EAGAIN generation + +(cherry picked from commit b7a0fead10959b03a1fa642a5ae7aca3a6a3dee9) + +Related: #1776408 +--- + src/cryptsetup/cryptsetup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 0881aea915..f2b2557497 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -455,7 +455,7 @@ static int attach_tcrypt( + r = read_one_line_file(key_file, &passphrase); + if (r < 0) { + log_error_errno(r, "Failed to read password file '%s': %m", key_file); +- return -EAGAIN; ++ return -EAGAIN; /* log with the actual error, but return EAGAIN */ + } + + params.passphrase = passphrase; diff --git a/SOURCES/0304-cryptsetup-downgrade-a-log-message-we-ignore.patch b/SOURCES/0304-cryptsetup-downgrade-a-log-message-we-ignore.patch new file mode 100644 index 0000000..cd853ee --- /dev/null +++ b/SOURCES/0304-cryptsetup-downgrade-a-log-message-we-ignore.patch @@ -0,0 +1,25 @@ +From 3bbacfb22a9266769a41dee6f8f594fbeb6287fc Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 21 Jan 2019 20:19:57 +0100 +Subject: [PATCH] cryptsetup: downgrade a log message we ignore + +(cherry picked from commit 44ce4255147ab308c1f13580147c693204c322e8) + +Related: #1776408 +--- + src/cryptsetup/cryptsetup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index f2b2557497..53fe04a73f 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -621,7 +621,7 @@ int main(int argc, char *argv[]) { + !streq(argv[4], "none")) { + + if (!path_is_absolute(argv[4])) +- log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]); ++ log_warning("Password file path '%s' is not absolute. Ignoring.", argv[4]); + else + key_file = argv[4]; + } diff --git a/SOURCES/0305-cryptsetup-rework-how-we-log-about-activation-failur.patch b/SOURCES/0305-cryptsetup-rework-how-we-log-about-activation-failur.patch new file mode 100644 index 0000000..5b357c3 --- /dev/null +++ b/SOURCES/0305-cryptsetup-rework-how-we-log-about-activation-failur.patch @@ -0,0 +1,102 @@ +From 966ecf0011a02c7823083a7868b8589fdf850be8 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 21 Jan 2019 20:20:35 +0100 +Subject: [PATCH] cryptsetup: rework how we log about activation failures + +First of all let's always log where the errors happen, and not in an +upper stackframe, in all cases. Previously we'd do this somethis one way +and sometimes another, which resulted in sometimes duplicate logging and +sometimes none. + +When we cannot activate something due to bad password the kernel gives +us EPERM. Let's uniformly return this EAGAIN, so tha the next password +is tried. (previously this was done in most cases but not in all) + +When we get EPERM let's also explicitly indicate that this probably +means the password is simply wrong. + +Fixes: #11498 +(cherry picked from commit 6f177c7dc092eb68762b4533d41b14244adb2a73) + +Related: #1776408 +--- + src/cryptsetup/cryptsetup.c | 36 ++++++++++++++++++++++-------------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 53fe04a73f..33c215eaa1 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -469,10 +469,15 @@ static int attach_tcrypt( + log_error("Failed to activate using password file '%s'.", key_file); + return -EAGAIN; + } +- return r; ++ ++ return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", crypt_get_device_name(cd)); + } + +- return crypt_activate_by_volume_key(cd, name, NULL, 0, flags); ++ r = crypt_activate_by_volume_key(cd, name, NULL, 0, flags); ++ if (r < 0) ++ return log_error_errno(r, "Failed to activate tcrypt device %s: %m", crypt_get_device_name(cd)); ++ ++ return 0; + } + + static int attach_luks_or_plain(struct crypt_device *cd, +@@ -549,22 +554,30 @@ static int attach_luks_or_plain(struct crypt_device *cd, + + if (key_file) { + r = crypt_activate_by_keyfile_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags); +- if (r < 0) { +- log_error_errno(r, "Failed to activate with key file '%s': %m", key_file); +- return -EAGAIN; ++ if (r == -EPERM) { ++ log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file); ++ return -EAGAIN; /* Log actual error, but return EAGAIN */ + } ++ if (r < 0) ++ return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file); + } else { + char **p; + ++ r = -EINVAL; + STRV_FOREACH(p, passwords) { + if (pass_volume_key) + r = crypt_activate_by_volume_key(cd, name, *p, arg_key_size, flags); + else + r = crypt_activate_by_passphrase(cd, name, arg_key_slot, *p, strlen(*p), flags); +- + if (r >= 0) + break; + } ++ if (r == -EPERM) { ++ log_error_errno(r, "Failed to activate with specified passphrase. (Passphrase incorrect?)"); ++ return -EAGAIN; /* log actual error, but return EAGAIN */ ++ } ++ if (r < 0) ++ return log_error_errno(r, "Failed to activate with specified passphrase: %m"); + } + + return r; +@@ -726,16 +739,11 @@ int main(int argc, char *argv[]) { + flags); + if (r >= 0) + break; +- if (r == -EAGAIN) { +- key_file = NULL; +- continue; +- } +- if (r != -EPERM) { +- log_error_errno(r, "Failed to activate: %m"); ++ if (r != -EAGAIN) + goto finish; +- } + +- log_warning("Invalid passphrase."); ++ /* Passphrase not correct? Let's try again! */ ++ key_file = NULL; + } + + if (arg_tries != 0 && tries >= arg_tries) { diff --git a/SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch b/SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch new file mode 100644 index 0000000..2451c00 --- /dev/null +++ b/SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch @@ -0,0 +1,41 @@ +From b7f9d757dd6f276203b8b04f0c0ba1c61bcf8937 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Wed, 18 Dec 2019 09:41:29 +0100 +Subject: [PATCH] rules: reintroduce 60-alias-kmsg.rules + +Resolves:#1739353 +rhel-only +--- + rules/60-alias-kmsg.rules | 10 ++++++++++ + rules/meson.build | 1 + + 2 files changed, 11 insertions(+) + create mode 100644 rules/60-alias-kmsg.rules + +diff --git a/rules/60-alias-kmsg.rules b/rules/60-alias-kmsg.rules +new file mode 100644 +index 0000000000..9c7236a730 +--- /dev/null ++++ b/rules/60-alias-kmsg.rules +@@ -0,0 +1,10 @@ ++SUBSYSTEM!="block", GOTO="log_end" ++KERNEL=="loop*|ram*", GOTO="log_end" ++ACTION=="remove", GOTO="log_end" ++ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="log_end" ++ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}=="1", GOTO="log_end" ++ ++IMPORT{cmdline}="udev.alias" ++ENV{udev.alias}=="1", RUN+="/bin/sh -c 'echo udev-alias: $name \($links\) > /dev/kmsg'" ++ ++LABEL="log_end" +diff --git a/rules/meson.build b/rules/meson.build +index 6363f8bf2e..7b5b2472de 100644 +--- a/rules/meson.build ++++ b/rules/meson.build +@@ -3,6 +3,7 @@ + rules = files(''' + 40-redhat.rules + 40-elevator.rules ++ 60-alias-kmsg.rules + 60-block.rules + 60-cdrom_id.rules + 60-drm.rules diff --git a/SOURCES/0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch b/SOURCES/0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch new file mode 100644 index 0000000..65374a7 --- /dev/null +++ b/SOURCES/0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch @@ -0,0 +1,49 @@ +From 1d8e642b0b67f07b0bf469c25126b878380bae6a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:13:03 +0100 +Subject: [PATCH] sd-bus: make rqueue/wqueue sizes of type size_t + +Let's do this like we usually do and size arrays with size_t. + +We already do this for the "allocated" counter correctly, and externally +we expose the queue sizes as uint64_t anyway, hence there's really no +point in usigned "unsigned" internally. + +(cherry picked from commit 143d4e045a798ccc87889b2a8a60d7fbe44be441) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-internal.h | 4 ++-- + src/libsystemd/sd-bus/sd-bus.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h +index 5d773b14c4..06bd7862cb 100644 +--- a/src/libsystemd/sd-bus/bus-internal.h ++++ b/src/libsystemd/sd-bus/bus-internal.h +@@ -221,11 +221,11 @@ struct sd_bus { + size_t rbuffer_size; + + sd_bus_message **rqueue; +- unsigned rqueue_size; ++ size_t rqueue_size; + size_t rqueue_allocated; + + sd_bus_message **wqueue; +- unsigned wqueue_size; ++ size_t wqueue_size; + size_t windex; + size_t wqueue_allocated; + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 1c9e967ae0..64026f7ee1 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -2080,7 +2080,7 @@ _public_ int sd_bus_call( + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); + usec_t timeout; + uint64_t cookie; +- unsigned i; ++ size_t i; + int r; + + bus_assert_return(m, -EINVAL, error); diff --git a/SOURCES/0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch b/SOURCES/0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch new file mode 100644 index 0000000..89004d8 --- /dev/null +++ b/SOURCES/0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch @@ -0,0 +1,51 @@ +From 9c23ceef0a08ffdf4aed7a96ec440e1b110568ac Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:14:17 +0100 +Subject: [PATCH] sd-bus: reorder bus ref and bus message ref handling + +Let's always place handling of these references together, so that all +reference counting during allocation is at a single place. + +(cherry picked from commit e593b6a87a335267e5f7238b14683b7f840a01a3) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-message.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index 19cb2b9a97..e9cdf46c91 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -461,7 +461,6 @@ int bus_message_from_header( + if (!m) + return -ENOMEM; + +- m->n_ref = 1; + m->sealed = true; + m->header = header; + m->header_accessible = header_accessible; +@@ -515,7 +514,9 @@ int bus_message_from_header( + m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + ++ m->n_ref = 1; + m->bus = sd_bus_ref(bus); ++ + *ret = TAKE_PTR(m); + + return 0; +@@ -588,13 +589,13 @@ _public_ int sd_bus_message_new( + return -ENOMEM; + + t->n_ref = 1; ++ t->bus = sd_bus_ref(bus); + t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message))); + t->header->endian = BUS_NATIVE_ENDIAN; + t->header->type = type; + t->header->version = bus->message_version; + t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING); + t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t); +- t->bus = sd_bus_ref(bus); + + if (bus->allow_interactive_authorization) + t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; diff --git a/SOURCES/0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch b/SOURCES/0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch new file mode 100644 index 0000000..9c7b804 --- /dev/null +++ b/SOURCES/0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch @@ -0,0 +1,32 @@ +From 19a9c67b79ebb9a65bc2aec8d8f2799262ef0cb2 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:15:37 +0100 +Subject: [PATCH] sd-bus: make sure dispatch_rqueue() initializes return + parameter on all types of success + +Let's make sure our own code follows coding style and initializes all +return values on all types of success (and leaves it uninitialized in +all types of failure). + +(cherry picked from commit c0bc4ec5cc17ac61773d1e9362b0ffa8382c1ff1) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/sd-bus.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 64026f7ee1..55b008cc9f 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -1814,8 +1814,10 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd + r = bus_read_message(bus, hint_priority, priority); + if (r < 0) + return r; +- if (r == 0) ++ if (r == 0) { ++ *m = NULL; + return ret; ++ } + + ret = 1; + } diff --git a/SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch b/SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch new file mode 100644 index 0000000..da2330b --- /dev/null +++ b/SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch @@ -0,0 +1,31 @@ +From 7e9944795e3f0046857379a5f878b365597ed373 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:18:18 +0100 +Subject: [PATCH] sd-bus: drop two inappropriate empty lines + +(cherry picked from commit 39feb2ce417e54cf9746e64b5dfd610cef6ac440) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/sd-bus.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 55b008cc9f..01060d105c 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -2634,7 +2634,6 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) { + SD_BUS_ERROR_UNKNOWN_METHOD, + "Unknown method '%s' on interface '%s'.", m->member, m->interface); + } +- + if (r < 0) + return r; + +@@ -2758,7 +2757,6 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd + return r; + + *ret = TAKE_PTR(m); +- + return 1; + } + diff --git a/SOURCES/0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch b/SOURCES/0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch new file mode 100644 index 0000000..d91eb20 --- /dev/null +++ b/SOURCES/0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch @@ -0,0 +1,33 @@ +From 247d4f826ab189c4dfc4706aaa94782342655218 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 21:06:30 +0100 +Subject: [PATCH] sd-bus: initialize mutex after we allocated the wqueue + +That way the mutex doesn't have to be destroyed when we exit early due +to OOM. + +(cherry picked from commit 2fe9a10d7695c4c3a748969a0d1662c624e50e5e) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/sd-bus.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 01060d105c..e49d58137d 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -248,12 +248,12 @@ _public_ int sd_bus_new(sd_bus **ret) { + b->original_pid = getpid_cached(); + b->n_groups = (size_t) -1; + +- assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0); +- + /* We guarantee that wqueue always has space for at least one entry */ + if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1)) + return -ENOMEM; + ++ assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0); ++ + *ret = TAKE_PTR(b); + return 0; + } diff --git a/SOURCES/0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch b/SOURCES/0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch new file mode 100644 index 0000000..4e2883a --- /dev/null +++ b/SOURCES/0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch @@ -0,0 +1,74 @@ +From 6180d5ee908c9c742f816c6922c229aefd533117 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 21:07:42 +0100 +Subject: [PATCH] sd-bus: always go through sd_bus_unref() to free messages + +Don't try to be smart, don't bypass the ref counting logic if there's no +real reason to. + +This matters if we want to tweak the ref counting logic later. + +(cherry picked from commit b41812d1e308de03c879cfca490105216d528c4b) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-message.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index e9cdf46c91..306b6d6816 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -138,8 +138,6 @@ static sd_bus_message* message_free(sd_bus_message *m) { + return mfree(m); + } + +-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free); +- + static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) { + void *op, *np; + size_t old_size, new_size, start; +@@ -531,7 +529,7 @@ int bus_message_from_malloc( + const char *label, + sd_bus_message **ret) { + +- _cleanup_(message_freep) sd_bus_message *m = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + size_t sz; + int r; + +@@ -651,7 +649,7 @@ _public_ int sd_bus_message_new_method_call( + const char *interface, + const char *member) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert_return(bus, -ENOTCONN); +@@ -696,7 +694,7 @@ static int message_new_reply( + uint8_t type, + sd_bus_message **m) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + uint64_t cookie; + int r; + +@@ -747,7 +745,7 @@ _public_ int sd_bus_message_new_method_error( + sd_bus_message **m, + const sd_bus_error *e) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert_return(sd_bus_error_is_set(e), -EINVAL); +@@ -850,7 +848,7 @@ int bus_message_new_synthetic_error( + const sd_bus_error *e, + sd_bus_message **m) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert(bus); diff --git a/SOURCES/0313-bus-message-introduce-two-kinds-of-references-to-bus.patch b/SOURCES/0313-bus-message-introduce-two-kinds-of-references-to-bus.patch new file mode 100644 index 0000000..7eb554d --- /dev/null +++ b/SOURCES/0313-bus-message-introduce-two-kinds-of-references-to-bus.patch @@ -0,0 +1,182 @@ +From bc2d7df4fc21e9e54413169d5aad21616314d65e Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:18:54 +0100 +Subject: [PATCH] bus-message: introduce two kinds of references to bus + messages + +Before this commit bus messages had a single reference count: when it +reached zero the message would be freed. This simple approach meant a +cyclic dependency was typically seen: a message that was enqueued in a +bus connection object would reference the bus connection object but also +itself be referenced by the bus connection object. So far out strategy +to avoid cases like this was: make sure to process the bus connection +regularly so that messages don#t stay queued, and at exit flush/close +the connection so that the message queued would be emptied, and thus the +cyclic dependencies resolved. Im many cases this isn't done properly +however. + +With this change, let's address the issue more systematically: let's +break the reference cycle. Specifically, there are now two types of +references to a bus message: + +1. A regular one, which keeps both the message and the bus object it is + associated with pinned. + +2. A "queue" reference, which is weaker: it pins the message, but not + the bus object it is associated with. + +The idea is then that regular user handling uses regular references, but +when a message is enqueued on its connection, then this takes a "queue" +reference instead. This then means that a queued message doesn't imply +the connection itself remains pinned, only regular references to the +connection or a message associated with it do. Thus, if we end up in the +situation where a user allocates a bus and a message and enqueues the +latter in the former and drops all refs to both, then this will detect +this case and free both. + +Note that this scheme isn't perfect, it only covers references between +messages and the busses they are associated with. If OTOH a bus message +is enqueued on a different bus than it is associated with cyclic deps +cannot be recognized with this simple algorithm, and thus if you enqueue +a message associated with a bus A on a bus B, and another message +associated with bus B on a bus A, a cyclic ref will be in effect and not +be discovered. However, given that this is an exotic case (though one +that happens, consider systemd-bus-stdio-bridge), it should be OK not to +cover with this, and people have to explicit flush all queues on exit in +that case. + +Note that this commit only establishes the separate reference counters +per message. A follow-up commit will start making use of this from the +bus connection object. + +(cherry picked from commit 1b3f9dd759ca0ea215e7b89f8ce66d1b724497b9) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-message.c | 60 ++++++++++++++++++++++++++--- + src/libsystemd/sd-bus/bus-message.h | 14 ++++++- + 2 files changed, 68 insertions(+), 6 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index 306b6d6816..7fe8929f82 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -120,7 +120,8 @@ static sd_bus_message* message_free(sd_bus_message *m) { + + message_reset_parts(m); + +- sd_bus_unref(m->bus); ++ /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user ++ * reference to the bus message also is considered a reference to the bus connection itself. */ + + if (m->free_fds) { + close_many(m->fds, m->n_fds); +@@ -893,27 +894,76 @@ int bus_message_new_synthetic_error( + } + + _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) { +- + if (!m) + return NULL; + +- assert(m->n_ref > 0); ++ /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at ++ * least one bus connection object. */ ++ assert(m->n_ref > 0 || m->n_queued > 0); ++ + m->n_ref++; + ++ /* Each user reference to a bus message shall also be considered a ref on the bus */ ++ sd_bus_ref(m->bus); + return m; + } + + _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) { +- + if (!m) + return NULL; + + assert(m->n_ref > 0); ++ ++ sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it ++ * here. Note we have to do this before decrementing our own n_ref here, since ++ * otherwise, if this message is currently queued sd_bus_unref() might call ++ * bus_message_unref_queued() for this which might then destroy the message ++ * while we are still processing it. */ + m->n_ref--; + +- if (m->n_ref > 0) ++ if (m->n_ref > 0 || m->n_queued > 0) + return NULL; + ++ /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful ++ * to reset the field only after the last reference to the bus is dropped, after all we might keep ++ * multiple references to the bus, once for each reference kept on outselves. */ ++ m->bus = NULL; ++ ++ return message_free(m); ++} ++ ++sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) { ++ if (!m) ++ return NULL; ++ ++ /* If this is a different bus than the message is associated with, then implicitly turn this into a ++ * regular reference. This means that you can create a memory leak by enqueuing a message generated ++ * on one bus onto another at the same time as enqueueing a message from the second one on the first, ++ * as we'll not detect the cyclic references there. */ ++ if (bus != m->bus) ++ return sd_bus_message_ref(m); ++ ++ assert(m->n_ref > 0 || m->n_queued > 0); ++ m->n_queued++; ++ ++ return m; ++} ++ ++sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) { ++ if (!m) ++ return NULL; ++ ++ if (bus != m->bus) ++ return sd_bus_message_unref(m); ++ ++ assert(m->n_queued > 0); ++ m->n_queued--; ++ ++ if (m->n_ref > 0 || m->n_queued > 0) ++ return NULL; ++ ++ m->bus = NULL; ++ + return message_free(m); + } + +diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h +index 97f6060e30..ded88005e2 100644 +--- a/src/libsystemd/sd-bus/bus-message.h ++++ b/src/libsystemd/sd-bus/bus-message.h +@@ -51,7 +51,16 @@ struct bus_body_part { + }; + + struct sd_bus_message { +- unsigned n_ref; ++ /* Caveat: a message can be referenced in two different ways: the main (user-facing) way will also ++ * pin the bus connection object the message is associated with. The secondary way ("queued") is used ++ * when a message is in the read or write queues of the bus connection object, which will not pin the ++ * bus connection object. This is necessary so that we don't have to have a pair of cyclic references ++ * between a message that is queued and its connection: as soon as a message is only referenced by ++ * the connection (by means of being queued) and the connection itself has no other references it ++ * will be freed. */ ++ ++ unsigned n_ref; /* Counter of references that pin the connection */ ++ unsigned n_queued; /* Counter of references that do not pin the connection */ + + sd_bus *bus; + +@@ -216,3 +225,6 @@ int bus_message_append_sender(sd_bus_message *m, const char *sender); + + void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m); + void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m); ++ ++sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus); ++sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus); diff --git a/SOURCES/0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch b/SOURCES/0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch new file mode 100644 index 0000000..fdafc3d --- /dev/null +++ b/SOURCES/0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch @@ -0,0 +1,74 @@ +From 8efdae75ddf035c8c04983820f8d8cf767cc17b1 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 31 Jan 2020 11:34:45 +0100 +Subject: [PATCH] sd-bus: introduce API for re-enqueuing incoming messages + +When authorizing via PolicyKit we want to process incoming method calls +twice: once to process and figure out that we need PK authentication, +and a second time after we aquired PK authentication to actually execute +the operation. With this new call sd_bus_enqueue_for_read() we have a +way to put an incoming message back into the read queue for this +purpose. + +This might have other uses too, for example debugging. +Related: CVE-2020-1712 +--- + src/libsystemd/libsystemd.sym | 1 + + src/libsystemd/sd-bus/sd-bus.c | 24 ++++++++++++++++++++++++ + src/systemd/sd-bus.h | 1 + + 3 files changed, 26 insertions(+) + +diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym +index 1eec17db50..e9972593a6 100644 +--- a/src/libsystemd/libsystemd.sym ++++ b/src/libsystemd/libsystemd.sym +@@ -569,4 +569,5 @@ global: + sd_event_source_get_inotify_mask; + sd_event_source_set_destroy_callback; + sd_event_source_get_destroy_callback; ++ sd_bus_enqueue_for_read; + } LIBSYSTEMD_238; +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index e49d58137d..68ad6cbe89 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -4120,3 +4120,27 @@ _public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) { + *ret = bus->wqueue_size; + return 0; + } ++ ++_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) { ++ int r; ++ ++ assert_return(bus, -EINVAL); ++ assert_return(bus = bus_resolve(bus), -ENOPKG); ++ assert_return(m, -EINVAL); ++ assert_return(m->sealed, -EINVAL); ++ assert_return(!bus_pid_changed(bus), -ECHILD); ++ ++ if (!BUS_IS_OPEN(bus->state)) ++ return -ENOTCONN; ++ ++ /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication, ++ * where we want accept a message, then determine we need to interactively authenticate the user, and ++ * when we have that process the message again. */ ++ ++ r = bus_rqueue_make_room(bus); ++ if (r < 0) ++ return r; ++ ++ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus); ++ return 0; ++} +diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h +index 54c4b1ca83..9ba757b13d 100644 +--- a/src/systemd/sd-bus.h ++++ b/src/systemd/sd-bus.h +@@ -193,6 +193,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r); + int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); + int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); + int sd_bus_flush(sd_bus *bus); ++int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m); + + sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); + sd_bus_message* sd_bus_get_current_message(sd_bus *bus); diff --git a/SOURCES/0315-sd-event-add-sd_event_source_disable_unref-helper.patch b/SOURCES/0315-sd-event-add-sd_event_source_disable_unref-helper.patch new file mode 100644 index 0000000..1748190 --- /dev/null +++ b/SOURCES/0315-sd-event-add-sd_event_source_disable_unref-helper.patch @@ -0,0 +1,130 @@ +From 73b87f8c73af714a32e7b56b217cd4e4f46a5ea7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 8 May 2019 14:39:57 +0200 +Subject: [PATCH] sd-event: add sd_event_source_disable_unref() helper + +(cherry picked from commit afd15bbb4b6414b9356799c63029e36642dae8e4) +Related: CVE-2020-1712 +--- + man/rules/meson.build | 4 +++- + man/sd_event_source_unref.xml | 30 +++++++++++++++++++----------- + src/libsystemd/libsystemd.sym | 1 + + src/libsystemd/sd-event/sd-event.c | 6 ++++++ + src/systemd/sd-event.h | 1 + + 5 files changed, 30 insertions(+), 12 deletions(-) + +diff --git a/man/rules/meson.build b/man/rules/meson.build +index 989d11c9b9..7ae94ea265 100644 +--- a/man/rules/meson.build ++++ b/man/rules/meson.build +@@ -340,7 +340,9 @@ manpages = [ + ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''], + ['sd_event_source_unref', + '3', +- ['sd_event_source_ref', 'sd_event_source_unrefp'], ++ ['sd_event_source_disable_unref', ++ 'sd_event_source_ref', ++ 'sd_event_source_unrefp'], + ''], + ['sd_event_wait', + '3', +diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml +index d1b83c57aa..af8fed33f2 100644 +--- a/man/sd_event_source_unref.xml ++++ b/man/sd_event_source_unref.xml +@@ -22,6 +22,7 @@ + sd_event_source_unref + sd_event_source_unrefp + sd_event_source_ref ++ sd_event_source_disable_unref + + Increase or decrease event source reference counters + +@@ -45,6 +46,10 @@ + sd_event_source *source + + ++ ++ sd_event_source* sd_event_source_disable_unref ++ sd_event_source *source ++ + + + +@@ -80,23 +85,26 @@ + the passed event source object is + NULL. + +- Note that event source objects stay alive and may be +- dispatched as long as they have a reference counter greater than +- zero. In order to drop a reference of an event source and make +- sure the associated event source handler function is not called +- anymore it is recommended to combine a call of ++ Note that event source objects stay alive and may be dispatched as long as they have a reference ++ counter greater than zero. In order to drop a reference of an event source and make sure the associated ++ event source handler function is not called anymore it is recommended to combine a call of + sd_event_source_unref() with a prior call to +- sd_event_source_set_enabled() with +- SD_EVENT_OFF. ++ sd_event_source_set_enabled() with SD_EVENT_OFF or call ++ sd_event_source_disable_unref(), see below. ++ ++ sd_event_source_disable_unref() combines a call to ++ sd_event_source_set_enabled() with SD_EVENT_OFF with ++ sd_event_source_unref(). This ensures that the source is disabled before the local ++ reference to it is lost. The source parameter is allowed to be ++ NULL. + + + + Return Value + +- sd_event_source_unref() always returns +- NULL. +- sd_event_source_ref() always returns the +- event source object passed in. ++ sd_event_source_unref() and ++ sd_event_source_disable_unref() always return NULL. ++ sd_event_source_ref() always returns the event source object passed in. + + + +diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym +index e9972593a6..778e88a16c 100644 +--- a/src/libsystemd/libsystemd.sym ++++ b/src/libsystemd/libsystemd.sym +@@ -570,4 +570,5 @@ global: + sd_event_source_set_destroy_callback; + sd_event_source_get_destroy_callback; + sd_bus_enqueue_for_read; ++ sd_event_source_disable_unref; + } LIBSYSTEMD_238; +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index d53b9a7026..0d3bf5cbb6 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -580,6 +580,12 @@ _public_ sd_event* sd_event_unref(sd_event *e) { + return NULL; + } + ++_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) { ++ if (s) ++ (void) sd_event_source_set_enabled(s, SD_EVENT_OFF); ++ return sd_event_source_unref(s); ++} ++ + static bool event_pid_changed(sd_event *e) { + assert(e); + +diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h +index 7fcae4ac49..9876be01c6 100644 +--- a/src/systemd/sd-event.h ++++ b/src/systemd/sd-event.h +@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret); + + sd_event_source* sd_event_source_ref(sd_event_source *s); + sd_event_source* sd_event_source_unref(sd_event_source *s); ++sd_event_source* sd_event_source_disable_unref(sd_event_source *s); + + sd_event *sd_event_source_get_event(sd_event_source *s); + void* sd_event_source_get_userdata(sd_event_source *s); diff --git a/SOURCES/0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch b/SOURCES/0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch new file mode 100644 index 0000000..da3d850 --- /dev/null +++ b/SOURCES/0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch @@ -0,0 +1,156 @@ +From 2ec3c78b1d1ba907cd888aac3cdc3a86c03cda90 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 31 Jan 2020 15:17:25 +0100 +Subject: [PATCH] polkit: when authorizing via PK let's re-resolve + callback/userdata instead of caching it + +Previously, when doing an async PK query we'd store the original +callback/userdata pair and call it again after the PK request is +complete. This is problematic, since PK queries might be slow and in the +meantime the userdata might be released and re-acquired. Let's avoid +this by always traversing through the message handlers so that we always +re-resolve the callback and userdata pair and thus can be sure it's +up-to-date and properly valid. + +Resolves: CVE-2020-1712 +--- + src/shared/bus-util.c | 74 +++++++++++++++++++++++++++++-------------- + 1 file changed, 50 insertions(+), 24 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 2d908eb45c..5ed68429be 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -319,10 +319,10 @@ int bus_test_polkit( + + typedef struct AsyncPolkitQuery { + sd_bus_message *request, *reply; +- sd_bus_message_handler_t callback; +- void *userdata; + sd_bus_slot *slot; ++ + Hashmap *registry; ++ sd_event_source *defer_event_source; + } AsyncPolkitQuery; + + static void async_polkit_query_free(AsyncPolkitQuery *q) { +@@ -338,9 +338,22 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { + sd_bus_message_unref(q->request); + sd_bus_message_unref(q->reply); + ++ sd_event_source_disable_unref(q->defer_event_source); + free(q); + } + ++static int async_polkit_defer(sd_event_source *s, void *userdata) { ++ AsyncPolkitQuery *q = userdata; ++ ++ assert(s); ++ ++ /* This is called as idle event source after we processed the async polkit reply, hopefully after the ++ * method call we re-enqueued has been properly processed. */ ++ ++ async_polkit_query_free(q); ++ return 0; ++} ++ + static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + AsyncPolkitQuery *q = userdata; +@@ -349,19 +362,45 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e + assert(reply); + assert(q); + ++ assert(q->slot); + q->slot = sd_bus_slot_unref(q->slot); ++ ++ assert(!q->reply); + q->reply = sd_bus_message_ref(reply); + ++ /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the ++ * whole message processing again, and thus re-validating and re-retrieving the "userdata" field ++ * again. ++ * ++ * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again, ++ * i.e. after the second time the message is processed is complete. */ ++ ++ assert(!q->defer_event_source); ++ r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT); ++ if (r < 0) ++ goto fail; ++ + r = sd_bus_message_rewind(q->request, true); +- if (r < 0) { +- r = sd_bus_reply_method_errno(q->request, r, NULL); +- goto finish; +- } ++ if (r < 0) ++ goto fail; + +- r = q->callback(q->request, q->userdata, &error_buffer); +- r = bus_maybe_reply_error(q->request, r, &error_buffer); ++ r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request); ++ if (r < 0) ++ goto fail; + +-finish: ++ return 1; ++ ++fail: ++ log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m"); ++ (void) sd_bus_reply_method_errno(q->request, r, NULL); + async_polkit_query_free(q); + + return r; +@@ -382,11 +421,9 @@ int bus_verify_polkit_async( + #if ENABLE_POLKIT + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; + AsyncPolkitQuery *q; +- const char *sender, **k, **v; +- sd_bus_message_handler_t callback; +- void *userdata; + int c; + #endif ++ const char *sender, **k, **v; + int r; + + assert(call); +@@ -444,20 +481,11 @@ int bus_verify_polkit_async( + else if (r > 0) + return 1; + +-#if ENABLE_POLKIT +- if (sd_bus_get_current_message(call->bus) != call) +- return -EINVAL; +- +- callback = sd_bus_get_current_handler(call->bus); +- if (!callback) +- return -EINVAL; +- +- userdata = sd_bus_get_current_userdata(call->bus); +- + sender = sd_bus_message_get_sender(call); + if (!sender) + return -EBADMSG; + ++#if ENABLE_POLKIT + c = sd_bus_message_get_allow_interactive_authorization(call); + if (c < 0) + return c; +@@ -509,8 +537,6 @@ int bus_verify_polkit_async( + return -ENOMEM; + + q->request = sd_bus_message_ref(call); +- q->callback = callback; +- q->userdata = userdata; + + r = hashmap_put(*registry, call, q); + if (r < 0) { diff --git a/SOURCES/0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch b/SOURCES/0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch new file mode 100644 index 0000000..d7523ce --- /dev/null +++ b/SOURCES/0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch @@ -0,0 +1,70 @@ +From b9be2c6b48227642ba85c5a741f121cc99655904 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Mon, 6 Jan 2020 12:30:58 +0100 +Subject: [PATCH] sysctl: let's by default increase the numeric PID range from + 2^16 to 2^22 + +This should PID collisions a tiny bit less likely, and thus improve +security and robustness. + +2^22 isn't particularly a lot either, but it's the current kernel +limitation. + +Bumping this limit was suggested by Linus himself: + +https://lwn.net/ml/linux-kernel/CAHk-=wiZ40LVjnXSi9iHLE_-ZBsWFGCgdmNiYZUXn1-V5YBg2g@mail.gmail.com/ + +Let's experiment with this in systemd upstream first. Downstreams and +users can after all still comment this easily. + +Besides compat concern the most often heard issue with such high PIDs is +usability, since they are potentially hard to type. I am not entirely sure though +whether 4194304 (as largest new PID) is that much worse to type or to +copy than 65563. + +This should also simplify management of per system tasks limits as by +this move the sysctl /proc/sys/kernel/threads-max becomes the primary +knob to control how many processes to have in parallel. + +Resolves: #1744214 +--- + sysctl.d/50-pid-max.conf | 17 +++++++++++++++++ + sysctl.d/meson.build | 1 + + 2 files changed, 18 insertions(+) + create mode 100644 sysctl.d/50-pid-max.conf + +diff --git a/sysctl.d/50-pid-max.conf b/sysctl.d/50-pid-max.conf +new file mode 100644 +index 0000000000..3a8393d185 +--- /dev/null ++++ b/sysctl.d/50-pid-max.conf +@@ -0,0 +1,17 @@ ++# This file is part of systemd. ++# ++# systemd is free software; you can redistribute it and/or modify it ++# under the terms of the GNU Lesser General Public License as published by ++# the Free Software Foundation; either version 2.1 of the License, or ++# (at your option) any later version. ++ ++# See sysctl.d(5) and core(5) for documentation. ++ ++# To override settings in this file, create a local file in /etc ++# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments ++# there. ++ ++# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default ++# of 2^16), to make PID collisions less likely. ++kernel.pid_max = 4194304 ++ +diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build +index 64f6ce942e..a95957ad7d 100644 +--- a/sysctl.d/meson.build ++++ b/sysctl.d/meson.build +@@ -2,6 +2,7 @@ + + install_data( + '50-default.conf', ++ '50-pid-max.conf', + install_dir : sysctldir) + + in_files = [] diff --git a/SOURCES/0318-journal-do-not-trigger-assertion-when-journal_file_c.patch b/SOURCES/0318-journal-do-not-trigger-assertion-when-journal_file_c.patch new file mode 100644 index 0000000..9ebc71d --- /dev/null +++ b/SOURCES/0318-journal-do-not-trigger-assertion-when-journal_file_c.patch @@ -0,0 +1,49 @@ +From dc4c3a5aa35a5e88adcf210471d9460262c8c0d9 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 28 May 2019 12:40:17 +0900 +Subject: [PATCH] journal: do not trigger assertion when journal_file_close() + get NULL + +We generally expect destructors to not complain if a NULL argument is passed. + +Closes #12400. + +(cherry picked from commit c377a6f3ad3d9bed4ce7e873e8e9ec6b1650c57d) +Resolves: #1788085 +--- + src/journal/journal-file.c | 3 ++- + src/journal/journald-server.c | 7 ++----- + 2 files changed, 4 insertions(+), 6 deletions(-) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index efc3ee052b..8249b11b23 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -335,7 +335,8 @@ bool journal_file_is_offlining(JournalFile *f) { + } + + JournalFile* journal_file_close(JournalFile *f) { +- assert(f); ++ if (!f) ++ return NULL; + + #if HAVE_GCRYPT + /* Write the final tag */ +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 6aecb67d6c..6250eab831 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1906,11 +1906,8 @@ void server_done(Server *s) { + + client_context_flush_all(s); + +- if (s->system_journal) +- (void) journal_file_close(s->system_journal); +- +- if (s->runtime_journal) +- (void) journal_file_close(s->runtime_journal); ++ (void) journal_file_close(s->system_journal); ++ (void) journal_file_close(s->runtime_journal); + + ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close); + diff --git a/SOURCES/0319-journal-use-cleanup-attribute-at-one-more-place.patch b/SOURCES/0319-journal-use-cleanup-attribute-at-one-more-place.patch new file mode 100644 index 0000000..9ca0d60 --- /dev/null +++ b/SOURCES/0319-journal-use-cleanup-attribute-at-one-more-place.patch @@ -0,0 +1,58 @@ +From ceacf935ac9f59bc08b5901f70f227958a2bcf52 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 28 May 2019 18:07:01 +0900 +Subject: [PATCH] journal: use cleanup attribute at one more place + +(cherry picked from commit 627df1dc42b68a74b0882b06366d1185b1a34332) + +Conflicts: + src/journal/journald-server.c + +Related: #1788085 +--- + src/journal/journal-file.h | 1 + + src/journal/journald-server.c | 9 ++++----- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h +index cd8a48a364..6a44fd39d2 100644 +--- a/src/journal/journal-file.h ++++ b/src/journal/journal-file.h +@@ -144,6 +144,7 @@ int journal_file_open( + int journal_file_set_offline(JournalFile *f, bool wait); + bool journal_file_is_offlining(JournalFile *f); + JournalFile* journal_file_close(JournalFile *j); ++DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close); + + int journal_file_open_reliably( + const char *fname, +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 6250eab831..7632e2d9d0 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -253,8 +253,9 @@ static int open_journal( + bool seal, + JournalMetrics *metrics, + JournalFile **ret) { ++ ++ _cleanup_(journal_file_closep) JournalFile *f = NULL; + int r; +- JournalFile *f; + + assert(s); + assert(fname); +@@ -271,12 +272,10 @@ static int open_journal( + return r; + + r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC); +- if (r < 0) { +- (void) journal_file_close(f); ++ if (r < 0) + return r; +- } + +- *ret = f; ++ *ret = TAKE_PTR(f); + return r; + } + diff --git a/SOURCES/0320-sd-bus-use-queue-message-references-for-managing-r-w.patch b/SOURCES/0320-sd-bus-use-queue-message-references-for-managing-r-w.patch new file mode 100644 index 0000000..f8ff1d5 --- /dev/null +++ b/SOURCES/0320-sd-bus-use-queue-message-references-for-managing-r-w.patch @@ -0,0 +1,183 @@ +From 781a055c17400e953bb7929434fe7a2e6517d5e8 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:31:59 +0100 +Subject: [PATCH] sd-bus: use "queue" message references for managing r/w + message queues in connection objects + +Let's make use of the new concept the previous commit added. + +See: #4846 +(cherry picked from commit c1757a70eac0382c4837a3833d683919f6a48ed7) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-socket.c | 6 ++- + src/libsystemd/sd-bus/sd-bus.c | 60 ++++++++++++++---------------- + 2 files changed, 32 insertions(+), 34 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c +index 17cfa8e1fd..4a72795d2b 100644 +--- a/src/libsystemd/sd-bus/bus-socket.c ++++ b/src/libsystemd/sd-bus/bus-socket.c +@@ -1116,8 +1116,10 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { + bus->fds = NULL; + bus->n_fds = 0; + +- if (t) +- bus->rqueue[bus->rqueue_size++] = t; ++ if (t) { ++ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus); ++ sd_bus_message_unref(t); ++ } + + return 1; + } +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 68ad6cbe89..a3509f7e89 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -148,13 +148,13 @@ static void bus_reset_queues(sd_bus *b) { + assert(b); + + while (b->rqueue_size > 0) +- sd_bus_message_unref(b->rqueue[--b->rqueue_size]); ++ bus_message_unref_queued(b->rqueue[--b->rqueue_size], b); + + b->rqueue = mfree(b->rqueue); + b->rqueue_allocated = 0; + + while (b->wqueue_size > 0) +- sd_bus_message_unref(b->wqueue[--b->wqueue_size]); ++ bus_message_unref_queued(b->wqueue[--b->wqueue_size], b); + + b->wqueue = mfree(b->wqueue); + b->wqueue_allocated = 0; +@@ -493,7 +493,7 @@ static int synthesize_connected_signal(sd_bus *bus) { + + /* Insert at the very front */ + memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size); +- bus->rqueue[0] = TAKE_PTR(m); ++ bus->rqueue[0] = bus_message_ref_queued(m, bus); + bus->rqueue_size++; + + return 0; +@@ -1760,7 +1760,7 @@ static int dispatch_wqueue(sd_bus *bus) { + * anyway. */ + + bus->wqueue_size--; +- sd_bus_message_unref(bus->wqueue[0]); ++ bus_message_unref_queued(bus->wqueue[0], bus); + memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size); + bus->windex = 0; + +@@ -1789,6 +1789,15 @@ int bus_rqueue_make_room(sd_bus *bus) { + return 0; + } + ++static void rqueue_drop_one(sd_bus *bus, size_t i) { ++ assert(bus); ++ assert(i < bus->rqueue_size); ++ ++ bus_message_unref_queued(bus->rqueue[i], bus); ++ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); ++ bus->rqueue_size--; ++} ++ + static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) { + int r, ret = 0; + +@@ -1803,10 +1812,8 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd + for (;;) { + if (bus->rqueue_size > 0) { + /* Dispatch a queued message */ +- +- *m = bus->rqueue[0]; +- bus->rqueue_size--; +- memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size); ++ *m = sd_bus_message_ref(bus->rqueue[0]); ++ rqueue_drop_one(bus, 0); + return 1; + } + +@@ -1884,7 +1891,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { + * of the wqueue array is always allocated so + * that we always can remember how much was + * written. */ +- bus->wqueue[0] = sd_bus_message_ref(m); ++ bus->wqueue[0] = bus_message_ref_queued(m, bus); + bus->wqueue_size = 1; + bus->windex = idx; + } +@@ -1898,7 +1905,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { + if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1)) + return -ENOMEM; + +- bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m); ++ bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus); + } + + finish: +@@ -2124,37 +2131,30 @@ _public_ int sd_bus_call( + usec_t left; + + while (i < bus->rqueue_size) { +- sd_bus_message *incoming = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL; + +- incoming = bus->rqueue[i]; ++ incoming = sd_bus_message_ref(bus->rqueue[i]); + + if (incoming->reply_cookie == cookie) { + /* Found a match! */ + +- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); +- bus->rqueue_size--; ++ rqueue_drop_one(bus, i); + log_debug_bus_message(incoming); + + if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) { + + if (incoming->n_fds <= 0 || bus->accept_fd) { + if (reply) +- *reply = incoming; +- else +- sd_bus_message_unref(incoming); ++ *reply = TAKE_PTR(incoming); + + return 1; + } + +- r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); +- sd_bus_message_unref(incoming); +- return r; ++ return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); + +- } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) { +- r = sd_bus_error_copy(error, &incoming->error); +- sd_bus_message_unref(incoming); +- return r; +- } else { ++ } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) ++ return sd_bus_error_copy(error, &incoming->error); ++ else { + r = -EIO; + goto fail; + } +@@ -2164,15 +2164,11 @@ _public_ int sd_bus_call( + incoming->sender && + streq(bus->unique_name, incoming->sender)) { + +- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); +- bus->rqueue_size--; ++ rqueue_drop_one(bus, i); + +- /* Our own message? Somebody is trying +- * to send its own client a message, +- * let's not dead-lock, let's fail +- * immediately. */ ++ /* Our own message? Somebody is trying to send its own client a message, ++ * let's not dead-lock, let's fail immediately. */ + +- sd_bus_message_unref(incoming); + r = -ELOOP; + goto fail; + } diff --git a/SOURCES/0321-pid1-make-sure-to-restore-correct-default-values-for.patch b/SOURCES/0321-pid1-make-sure-to-restore-correct-default-values-for.patch new file mode 100644 index 0000000..2ca5b14 --- /dev/null +++ b/SOURCES/0321-pid1-make-sure-to-restore-correct-default-values-for.patch @@ -0,0 +1,261 @@ +From 77a273e02c1c811485d13ddca0f844512aed2cff Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Wed, 12 Feb 2020 12:58:54 +0100 +Subject: [PATCH] pid1: make sure to restore correct default values for some + rlimits + +Commit fb39af4ce42d7ef9af63009f271f404038703704 forgot to restore the default +rlimit values (RLIMIT_NOFILE and RLIMIT_MEMLOCK) while PID1 is reloading. + +This patch extracts the code in charge of initializing the default values for +those rlimits in order to create dedicated functions, which take care of their +initialization. + +These functions are then called in parse_configuration() so we make sure that +the default values for these rlimits get restored every time PID1 is reloading +its configuration. + +(cherry picked from commit a9fd4cd1206832a61aaf61fff583bb133e6cb965) +Resolves: #1789930 +--- + src/core/main.c | 135 +++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 106 insertions(+), 29 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index c83249a8dc..b8c1e567ad 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -136,7 +136,8 @@ static EmergencyAction arg_cad_burst_action; + static CPUSet arg_cpu_affinity; + static NUMAPolicy arg_numa_policy; + +-static int parse_configuration(void); ++static int parse_configuration(const struct rlimit *saved_rlimit_nofile, ++ const struct rlimit *saved_rlimit_memlock); + + _noreturn_ static void freeze_or_reboot(void) { + +@@ -1149,25 +1150,6 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching + static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { + int r, nr; + +- assert(saved_rlimit); +- +- /* Save the original RLIMIT_NOFILE so that we can reset it +- * later when transitioning from the initrd to the main +- * systemd or suchlike. */ +- if (getrlimit(RLIMIT_NOFILE, saved_rlimit) < 0) +- return log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m"); +- +- /* Make sure forked processes get the default kernel setting */ +- if (!arg_default_rlimit[RLIMIT_NOFILE]) { +- struct rlimit *rl; +- +- rl = newdup(struct rlimit, saved_rlimit, 1); +- if (!rl) +- return log_oom(); +- +- arg_default_rlimit[RLIMIT_NOFILE] = rl; +- } +- + /* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */ + nr = read_nr_open(); + r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr)); +@@ -1180,16 +1162,12 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { + static int bump_rlimit_memlock(struct rlimit *saved_rlimit) { + int r; + +- assert(saved_rlimit); + assert(getuid() == 0); + + /* BPF_MAP_TYPE_LPM_TRIE bpf maps are charged against RLIMIT_MEMLOCK, even though we have CAP_IPC_LOCK which + * should normally disable such checks. We need them to implement IPAccessAllow= and IPAccessDeny=, hence let's + * bump the value high enough for the root user. */ + +- if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit) < 0) +- return log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m"); +- + r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(1024ULL*1024ULL*16ULL)); + if (r < 0) + return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m"); +@@ -1651,6 +1629,8 @@ static void do_reexecute( + + static int invoke_main_loop( + Manager *m, ++ const struct rlimit *saved_rlimit_nofile, ++ const struct rlimit *saved_rlimit_memlock, + bool *ret_reexecute, + int *ret_retval, /* Return parameters relevant for shutting down */ + const char **ret_shutdown_verb, /* … */ +@@ -1662,6 +1642,8 @@ static int invoke_main_loop( + int r; + + assert(m); ++ assert(saved_rlimit_nofile); ++ assert(saved_rlimit_memlock); + assert(ret_reexecute); + assert(ret_retval); + assert(ret_shutdown_verb); +@@ -1691,7 +1673,7 @@ static int invoke_main_loop( + saved_log_level = m->log_level_overridden ? log_get_max_level() : -1; + saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID; + +- (void) parse_configuration(); ++ (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock); + + set_manager_defaults(m); + +@@ -1983,6 +1965,80 @@ static int do_queue_default_job( + return 0; + } + ++static void save_rlimits(struct rlimit *saved_rlimit_nofile, ++ struct rlimit *saved_rlimit_memlock) { ++ ++ assert(saved_rlimit_nofile); ++ assert(saved_rlimit_memlock); ++ ++ if (getrlimit(RLIMIT_NOFILE, saved_rlimit_nofile) < 0) ++ log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m"); ++ ++ if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock) < 0) ++ log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m"); ++} ++ ++static void fallback_rlimit_nofile(const struct rlimit *saved_rlimit_nofile) { ++ struct rlimit *rl; ++ ++ if (arg_default_rlimit[RLIMIT_NOFILE]) ++ return; ++ ++ /* Make sure forked processes get limits based on the original kernel setting */ ++ ++ rl = newdup(struct rlimit, saved_rlimit_nofile, 1); ++ if (!rl) { ++ log_oom(); ++ return; ++ } ++ ++ /* Bump the hard limit for system services to a substantially higher value. The default ++ * hard limit current kernels set is pretty low (4K), mostly for historical ++ * reasons. According to kernel developers, the fd handling in recent kernels has been ++ * optimized substantially enough, so that we can bump the limit now, without paying too ++ * high a price in memory or performance. Note however that we only bump the hard limit, ++ * not the soft limit. That's because select() works the way it works, and chokes on fds ++ * >= 1024. If we'd bump the soft limit globally, it might accidentally happen to ++ * unexpecting programs that they get fds higher than what they can process using ++ * select(). By only bumping the hard limit but leaving the low limit as it is we avoid ++ * this pitfall: programs that are written by folks aware of the select() problem in mind ++ * (and thus use poll()/epoll instead of select(), the way everybody should) can ++ * explicitly opt into high fds by bumping their soft limit beyond 1024, to the hard limit ++ * we pass. */ ++ if (arg_system) { ++ int nr; ++ ++ /* Get the underlying absolute limit the kernel enforces */ ++ nr = read_nr_open(); ++ ++ rl->rlim_max = MIN((rlim_t) nr, MAX(rl->rlim_max, (rlim_t) HIGH_RLIMIT_NOFILE)); ++ } ++ ++ /* If for some reason we were invoked with a soft limit above 1024 (which should never ++ * happen!, but who knows what we get passed in from pam_limit when invoked as --user ++ * instance), then lower what we pass on to not confuse our children */ ++ rl->rlim_cur = MIN(rl->rlim_cur, (rlim_t) FD_SETSIZE); ++ ++ arg_default_rlimit[RLIMIT_NOFILE] = rl; ++} ++ ++static void fallback_rlimit_memlock(const struct rlimit *saved_rlimit_memlock) { ++ struct rlimit *rl; ++ ++ /* Pass the original value down to invoked processes */ ++ ++ if (arg_default_rlimit[RLIMIT_MEMLOCK]) ++ return; ++ ++ rl = newdup(struct rlimit, saved_rlimit_memlock, 1); ++ if (!rl) { ++ log_oom(); ++ return; ++ } ++ ++ arg_default_rlimit[RLIMIT_MEMLOCK] = rl; ++} ++ + static void reset_arguments(void) { + /* Frees/resets arg_* variables, with a few exceptions commented below. */ + +@@ -2040,9 +2096,13 @@ static void reset_arguments(void) { + numa_policy_reset(&arg_numa_policy); + } + +-static int parse_configuration(void) { ++static int parse_configuration(const struct rlimit *saved_rlimit_nofile, ++ const struct rlimit *saved_rlimit_memlock) { + int r; + ++ assert(saved_rlimit_nofile); ++ assert(saved_rlimit_memlock); ++ + arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U); + + /* Assign configuration defaults */ +@@ -2058,18 +2118,29 @@ static int parse_configuration(void) { + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + } + ++ /* Initialize some default rlimits for services if they haven't been configured */ ++ fallback_rlimit_nofile(saved_rlimit_nofile); ++ fallback_rlimit_memlock(saved_rlimit_memlock); ++ + /* Note that this also parses bits from the kernel command line, including "debug". */ + log_parse_environment(); + + return 0; + } + +-static int load_configuration(int argc, char **argv, const char **ret_error_message) { ++static int load_configuration( ++ int argc, ++ char **argv, ++ const struct rlimit *saved_rlimit_nofile, ++ const struct rlimit *saved_rlimit_memlock, ++ const char **ret_error_message) { + int r; + ++ assert(saved_rlimit_nofile); ++ assert(saved_rlimit_memlock); + assert(ret_error_message); + +- (void) parse_configuration(); ++ (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock); + + r = parse_argv(argc, argv); + if (r < 0) { +@@ -2403,11 +2474,15 @@ int main(int argc, char *argv[]) { + } + } + ++ /* Save the original RLIMIT_NOFILE/RLIMIT_MEMLOCK so that we can reset it later when ++ * transitioning from the initrd to the main systemd or suchlike. */ ++ save_rlimits(&saved_rlimit_nofile, &saved_rlimit_memlock); ++ + /* Reset all signal handlers. */ + (void) reset_all_signal_handlers(); + (void) ignore_signals(SIGNALS_IGNORE, -1); + +- r = load_configuration(argc, argv, &error_message); ++ r = load_configuration(argc, argv, &saved_rlimit_nofile, &saved_rlimit_memlock, &error_message); + if (r < 0) + goto finish; + +@@ -2522,6 +2597,8 @@ int main(int argc, char *argv[]) { + } + + (void) invoke_main_loop(m, ++ &saved_rlimit_nofile, ++ &saved_rlimit_memlock, + &reexecute, + &retval, + &shutdown_verb, diff --git a/SOURCES/0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch b/SOURCES/0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch new file mode 100644 index 0000000..72ec11c --- /dev/null +++ b/SOURCES/0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch @@ -0,0 +1,37 @@ +From 0528a880ddf797a42b2de274e5c7bd2d9896c991 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 11 Oct 2018 18:31:11 +0200 +Subject: [PATCH] main: introduce a define HIGH_RLIMIT_MEMLOCK similar to + HIGH_RLIMIT_NOFILE + +(cherry picked from commit c8884aceefc85245b9bdfb626e2daf27521259bd) +Related: #1789930 +--- + src/basic/def.h | 3 +++ + src/core/main.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/basic/def.h b/src/basic/def.h +index 4d515c11b6..65ad659999 100644 +--- a/src/basic/def.h ++++ b/src/basic/def.h +@@ -75,3 +75,6 @@ + _CONF_PATHS_SPLIT_USR(n)) + + #define LONG_LINE_MAX (1U*1024U*1024U) ++ ++#define HIGH_RLIMIT_NOFILE (256*1024) ++#define HIGH_RLIMIT_MEMLOCK (1024ULL*1024ULL*64ULL) +diff --git a/src/core/main.c b/src/core/main.c +index b8c1e567ad..d6550ea161 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -1168,7 +1168,7 @@ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) { + * should normally disable such checks. We need them to implement IPAccessAllow= and IPAccessDeny=, hence let's + * bump the value high enough for the root user. */ + +- r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(1024ULL*1024ULL*16ULL)); ++ r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(HIGH_RLIMIT_MEMLOCK)); + if (r < 0) + return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m"); + diff --git a/SOURCES/0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch b/SOURCES/0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch new file mode 100644 index 0000000..d63169b --- /dev/null +++ b/SOURCES/0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch @@ -0,0 +1,178 @@ +From 5a62c0daff82e8343d24f98e1761d27bf8015782 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Mar 2019 19:00:28 +0100 +Subject: [PATCH] seccomp: introduce seccomp_restrict_suid_sgid() for blocking + chmod() for suid/sgid files + +(cherry picked from commit 3c27973b13724ede05a06a5d346a569794cda433) +Related: #1687512 +--- + src/shared/seccomp-util.c | 132 ++++++++++++++++++++++++++++++++++++++ + src/shared/seccomp-util.h | 1 + + 2 files changed, 133 insertions(+) + +diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c +index 92910acf0e..fd46b9f88d 100644 +--- a/src/shared/seccomp-util.c ++++ b/src/shared/seccomp-util.c +@@ -1,12 +1,14 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include ++#include + #include + #include + #include + #include + #include + #include ++#include + + #include "af-list.h" + #include "alloc-util.h" +@@ -1747,3 +1749,133 @@ int seccomp_lock_personality(unsigned long personality) { + + return 0; + } ++ ++int seccomp_restrict_suid_sgid(void) { ++ uint32_t arch; ++ int r; ++ ++ SECCOMP_FOREACH_LOCAL_ARCH(arch) { ++ _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; ++ ++ r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); ++ if (r < 0) ++ return r; ++ ++ /* Checks the mode_t parameter of the following system calls: ++ * ++ * → chmod() + fchmod() + fchmodat() ++ * → open() + creat() + openat() ++ * → mkdir() + mkdirat() ++ * → mknod() + mknodat() ++ */ ++ ++ for (unsigned bit = 0; bit < 2; bit ++) { ++ /* Block S_ISUID in the first iteration, S_ISGID in the second */ ++ mode_t m = bit == 0 ? S_ISUID : S_ISGID; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(chmod), ++ 1, ++ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(fchmod), ++ 1, ++ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(fchmodat), ++ 1, ++ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(mkdir), ++ 1, ++ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(mkdirat), ++ 1, ++ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(mknod), ++ 1, ++ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(mknodat), ++ 1, ++ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(open), ++ 2, ++ SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT), ++ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(openat), ++ 2, ++ SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT), ++ SCMP_A3(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(creat), ++ 1, ++ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); ++ if (r < 0) ++ break; ++ } ++ if (r < 0) { ++ log_debug_errno(r, "Failed to add suid/sgid rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); ++ continue; ++ } ++ ++ r = seccomp_load(seccomp); ++ if (IN_SET(r, -EPERM, -EACCES)) ++ return r; ++ if (r < 0) ++ log_debug_errno(r, "Failed to apply suid/sgid restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); ++ } ++ ++ return 0; ++} +diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h +index d8a36c4e21..602f092255 100644 +--- a/src/shared/seccomp-util.h ++++ b/src/shared/seccomp-util.h +@@ -85,6 +85,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist); + int seccomp_restrict_realtime(void); + int seccomp_memory_deny_write_execute(void); + int seccomp_lock_personality(unsigned long personality); ++int seccomp_restrict_suid_sgid(void); + + extern const uint32_t seccomp_local_archs[]; + diff --git a/SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch b/SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch new file mode 100644 index 0000000..c04084f --- /dev/null +++ b/SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch @@ -0,0 +1,265 @@ +From b39697a80ad388e2063c54e56333882f4307c1a1 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Tue, 12 Nov 2019 13:27:49 +0100 +Subject: [PATCH] test: add test case for restrict_suid_sgid() + +(cherry picked from commit 167fc10cb352b04d442c9010dab4f8dc24219749) +Related: #1687512 +--- + src/test/test-seccomp.c | 226 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 226 insertions(+) + +diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c +index d177515ac7..4021a06e0e 100644 +--- a/src/test/test-seccomp.c ++++ b/src/test/test-seccomp.c +@@ -17,9 +17,11 @@ + #include "nsflags.h" + #include "process-util.h" + #include "raw-clone.h" ++#include "rm-rf.h" + #include "seccomp-util.h" + #include "set.h" + #include "string-util.h" ++#include "umask-util.h" + #include "util.h" + #include "virt.h" + +@@ -666,6 +668,229 @@ static void test_filter_sets_ordered(void) { + } + } + ++static int mkostemp_safe(char *pattern) { ++ _unused_ _cleanup_umask_ mode_t u = umask(0077); ++ int fd; ++ ++ assert(pattern); ++ ++ fd = mkostemp(pattern, O_CLOEXEC); ++ if (fd < 0) ++ return -errno; ++ ++ return fd; ++} ++ ++static int real_open(const char *path, int flags, mode_t mode) { ++ /* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for ++ * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On ++ * other architectures, let's just fall back to the glibc call. */ ++ ++#ifdef SYS_open ++ return (int) syscall(SYS_open, path, flags, mode); ++#else ++ return open(path, flags, mode); ++#endif ++} ++ ++static void test_restrict_suid_sgid(void) { ++ pid_t pid; ++ ++ log_info("/* %s */", __func__); ++ ++ if (!is_seccomp_available()) { ++ log_notice("Seccomp not available, skipping %s", __func__); ++ return; ++ } ++ if (geteuid() != 0) { ++ log_notice("Not root, skipping %s", __func__); ++ return; ++ } ++ ++ pid = fork(); ++ assert_se(pid >= 0); ++ ++ if (pid == 0) { ++ char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX"; ++ int fd = -1, k = -1; ++ const char *z; ++ ++ fd = mkostemp_safe(path); ++ assert_se(fd >= 0); ++ ++ assert_se(mkdtemp(dir)); ++ z = strjoina(dir, "/test"); ++ ++ assert_se(chmod(path, 0755 | S_ISUID) >= 0); ++ assert_se(chmod(path, 0755 | S_ISGID) >= 0); ++ assert_se(chmod(path, 0755 | S_ISGID | S_ISUID) >= 0); ++ assert_se(chmod(path, 0755) >= 0); ++ ++ assert_se(fchmod(fd, 0755 | S_ISUID) >= 0); ++ assert_se(fchmod(fd, 0755 | S_ISGID) >= 0); ++ assert_se(fchmod(fd, 0755 | S_ISGID | S_ISUID) >= 0); ++ assert_se(fchmod(fd, 0755) >= 0); ++ ++ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0); ++ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0); ++ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0); ++ assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0); ++ ++ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = creat(z, 0644 | S_ISUID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = creat(z, 0644 | S_ISGID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = creat(z, 0644 | S_ISUID | S_ISGID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = creat(z, 0644); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(mkdir(z, 0755 | S_ISUID) >= 0); ++ assert_se(rmdir(z) >= 0); ++ assert_se(mkdir(z, 0755 | S_ISGID) >= 0); ++ assert_se(rmdir(z) >= 0); ++ assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) >= 0); ++ assert_se(rmdir(z) >= 0); ++ assert_se(mkdir(z, 0755) >= 0); ++ assert_se(rmdir(z) >= 0); ++ ++ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) >= 0); ++ assert_se(rmdir(z) >= 0); ++ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) >= 0); ++ assert_se(rmdir(z) >= 0); ++ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) >= 0); ++ assert_se(rmdir(z) >= 0); ++ assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0); ++ assert_se(rmdir(z) >= 0); ++ ++ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ assert_se(mknod(z, S_IFREG | 0755, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(seccomp_restrict_suid_sgid() >= 0); ++ ++ assert_se(chmod(path, 0775 | S_ISUID) < 0 && errno == EPERM); ++ assert_se(chmod(path, 0775 | S_ISGID) < 0 && errno == EPERM); ++ assert_se(chmod(path, 0775 | S_ISGID | S_ISUID) < 0 && errno == EPERM); ++ assert_se(chmod(path, 0775) >= 0); ++ ++ assert_se(fchmod(fd, 0775 | S_ISUID) < 0 && errno == EPERM); ++ assert_se(fchmod(fd, 0775 | S_ISGID) < 0 && errno == EPERM); ++ assert_se(fchmod(fd, 0775 | S_ISGID | S_ISUID) < 0 && errno == EPERM); ++ assert_se(fchmod(fd, 0775) >= 0); ++ ++ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM); ++ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM); ++ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM); ++ assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0); ++ ++ assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM); ++ assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM); ++ assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM); ++ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(creat(z, 0644 | S_ISUID) < 0 && errno == EPERM); ++ assert_se(creat(z, 0644 | S_ISGID) < 0 && errno == EPERM); ++ assert_se(creat(z, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM); ++ k = creat(z, 0644); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM); ++ assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM); ++ assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM); ++ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); ++ k = safe_close(k); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(mkdir(z, 0755 | S_ISUID) < 0 && errno == EPERM); ++ assert_se(mkdir(z, 0755 | S_ISGID) < 0 && errno == EPERM); ++ assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM); ++ assert_se(mkdir(z, 0755) >= 0); ++ assert_se(rmdir(z) >= 0); ++ ++ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) < 0 && errno == EPERM); ++ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) < 0 && errno == EPERM); ++ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM); ++ assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0); ++ assert_se(rmdir(z) >= 0); ++ ++ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM); ++ assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM); ++ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM); ++ assert_se(mknod(z, S_IFREG | 0755, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM); ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM); ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM); ++ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0); ++ assert_se(unlink(z) >= 0); ++ ++ assert_se(unlink(path) >= 0); ++ assert_se(rm_rf(dir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); ++ ++ _exit(EXIT_SUCCESS); ++ } ++ ++ assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); ++} ++ + int main(int argc, char *argv[]) { + + log_set_max_level(LOG_DEBUG); +@@ -684,6 +909,7 @@ int main(int argc, char *argv[]) { + test_load_syscall_filter_set_raw(); + test_lock_personality(); + test_filter_sets_ordered(); ++ test_restrict_suid_sgid(); + + return 0; + } diff --git a/SOURCES/0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch b/SOURCES/0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch new file mode 100644 index 0000000..7d8d98a --- /dev/null +++ b/SOURCES/0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch @@ -0,0 +1,157 @@ +From f79283a86531e3bbf0854b5f126b7b291fadfb43 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Mar 2019 19:09:09 +0100 +Subject: [PATCH] core: expose SUID/SGID restriction as new unit setting + RestrictSUIDSGID= + +(cherry picked from commit f69567cbe26d09eac9d387c0be0fc32c65a83ada) +Related: #1687512 +--- + src/core/dbus-execute.c | 4 ++++ + src/core/execute.c | 22 +++++++++++++++++++++ + src/core/execute.h | 1 + + src/core/load-fragment-gperf.gperf.m4 | 2 ++ + src/shared/bus-unit-util.c | 2 +- + test/fuzz/fuzz-unit-file/directives.service | 1 + + 6 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 198f149210..e7c0b893d1 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -815,6 +815,7 @@ const sd_bus_vtable bus_exec_vtable[] = { + SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool, offsetof(ExecContext, restrict_suid_sgid), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), +@@ -1179,6 +1180,9 @@ int bus_exec_context_set_transient_property( + if (streq(name, "RestrictRealtime")) + return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error); + ++ if (streq(name, "RestrictSUIDSGID")) ++ return bus_set_transient_bool(u, name, &c->restrict_suid_sgid, message, flags, error); ++ + if (streq(name, "DynamicUser")) + return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error); + +diff --git a/src/core/execute.c b/src/core/execute.c +index 56aa89e1ec..f012023224 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -1366,6 +1366,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) { + return context_has_address_families(c) || + c->memory_deny_write_execute || + c->restrict_realtime || ++ c->restrict_suid_sgid || + exec_context_restrict_namespaces_set(c) || + c->protect_kernel_tunables || + c->protect_kernel_modules || +@@ -1470,6 +1471,19 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { + return seccomp_restrict_realtime(); + } + ++static int apply_restrict_suid_sgid(const Unit* u, const ExecContext *c) { ++ assert(u); ++ assert(c); ++ ++ if (!c->restrict_suid_sgid) ++ return 0; ++ ++ if (skip_seccomp_unavailable(u, "RestrictSUIDSGID=")) ++ return 0; ++ ++ return seccomp_restrict_suid_sgid(); ++} ++ + static int apply_protect_sysctl(const Unit *u, const ExecContext *c) { + assert(u); + assert(c); +@@ -3404,6 +3418,12 @@ static int exec_child( + return log_unit_error_errno(unit, r, "Failed to apply realtime restrictions: %m"); + } + ++ r = apply_restrict_suid_sgid(unit, context); ++ if (r < 0) { ++ *exit_status = EXIT_SECCOMP; ++ return log_unit_error_errno(unit, r, "Failed to apply SUID/SGID restrictions: %m"); ++ } ++ + r = apply_restrict_namespaces(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; +@@ -4023,6 +4043,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { + "%sIgnoreSIGPIPE: %s\n" + "%sMemoryDenyWriteExecute: %s\n" + "%sRestrictRealtime: %s\n" ++ "%sRestrictSUIDSGID: %s\n" + "%sKeyringMode: %s\n", + prefix, c->umask, + prefix, c->working_directory ? c->working_directory : "/", +@@ -4041,6 +4062,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { + prefix, yes_no(c->ignore_sigpipe), + prefix, yes_no(c->memory_deny_write_execute), + prefix, yes_no(c->restrict_realtime), ++ prefix, yes_no(c->restrict_suid_sgid), + prefix, exec_keyring_mode_to_string(c->keyring_mode)); + + if (c->root_image) +diff --git a/src/core/execute.h b/src/core/execute.h +index b2eb55f8f5..2266355962 100644 +--- a/src/core/execute.h ++++ b/src/core/execute.h +@@ -245,6 +245,7 @@ struct ExecContext { + * that the autofs logic detects that it belongs to us and we + * don't enter a trigger loop. */ + bool same_pgrp; ++ bool restrict_suid_sgid; + + unsigned long personality; + bool lock_personality; +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index cdf4d14c4e..49e938d0ce 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -76,6 +76,7 @@ $1.SystemCallErrorNumber, config_parse_syscall_errno, 0, + $1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute) + $1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context) + $1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime) ++$1.RestrictSUIDSGID, config_parse_bool, 0, offsetof($1, exec_context.restrict_suid_sgid) + $1.RestrictAddressFamilies, config_parse_address_families, 0, offsetof($1, exec_context) + $1.LockPersonality, config_parse_bool, 0, offsetof($1, exec_context.lock_personality)', + `$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +@@ -84,6 +85,7 @@ $1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CO + $1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 + $1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 + $1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 ++$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION 0 + $1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 + $1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') + $1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit) +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 055edd6e22..3c42e97b7a 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -697,7 +697,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con + "PrivateMounts", "NoNewPrivileges", "SyslogLevelPrefix", + "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC", + "ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups", +- "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality")) ++ "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality" "RestrictSUIDSGID")) + + return bus_append_parse_boolean(m, field, eq); + +diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service +index d8d1fc68b8..eab1820e20 100644 +--- a/test/fuzz/fuzz-unit-file/directives.service ++++ b/test/fuzz/fuzz-unit-file/directives.service +@@ -849,6 +849,7 @@ ReserveVT= + RestrictAddressFamilies= + RestrictNamespaces= + RestrictRealtime= ++RestrictSUIDSGID= + RuntimeDirectory= + RuntimeDirectoryMode= + RuntimeDirectoryPreserve= diff --git a/SOURCES/0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch b/SOURCES/0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch new file mode 100644 index 0000000..ffdc4bf --- /dev/null +++ b/SOURCES/0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch @@ -0,0 +1,52 @@ +From 3d338556760632b9c8b646a719d56e02e3ad2088 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Mar 2019 19:20:35 +0100 +Subject: [PATCH] analyze: check for RestrictSUIDSGID= in "systemd-analyze + security" + +And let's give it a heigh weight, since it pretty much can be used for +bad things only. + +(cherry picked from commit 9d880b70ba5c6ca83c82952f4c90e86e56c7b70c) +Related: #1687512 +--- + src/analyze/analyze-security.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c +index eec040d5c3..969101c57b 100644 +--- a/src/analyze/analyze-security.c ++++ b/src/analyze/analyze-security.c +@@ -69,6 +69,7 @@ struct security_info { + + uint64_t restrict_namespaces; + bool restrict_realtime; ++ bool restrict_suid_sgid; + + char *root_directory; + char *root_image; +@@ -1130,6 +1131,16 @@ static const struct security_assessor security_assessor_table[] = { + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_realtime), + }, ++ { ++ .id = "RestrictSUIDSGID=", ++ .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=", ++ .description_good = "SUID/SGID file creation by service is restricted", ++ .description_bad = "Service may create SUID/SGID files", ++ .weight = 1000, ++ .range = 1, ++ .assess = assess_bool, ++ .offset = offsetof(struct security_info, restrict_suid_sgid), ++ }, + { + .id = "RestrictNamespaces=~CLONE_NEWUSER", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", +@@ -1862,6 +1873,7 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_ + { "RestrictAddressFamilies", "(bas)", property_read_restrict_address_families, 0 }, + { "RestrictNamespaces", "t", NULL, offsetof(struct security_info, restrict_namespaces) }, + { "RestrictRealtime", "b", NULL, offsetof(struct security_info, restrict_realtime) }, ++ { "RestrictSUIDSGID", "b", NULL, offsetof(struct security_info, restrict_suid_sgid) }, + { "RootDirectory", "s", NULL, offsetof(struct security_info, root_directory) }, + { "RootImage", "s", NULL, offsetof(struct security_info, root_image) }, + { "SupplementaryGroups", "as", NULL, offsetof(struct security_info, supplementary_groups) }, diff --git a/SOURCES/0327-man-document-the-new-RestrictSUIDSGID-setting.patch b/SOURCES/0327-man-document-the-new-RestrictSUIDSGID-setting.patch new file mode 100644 index 0000000..f362587 --- /dev/null +++ b/SOURCES/0327-man-document-the-new-RestrictSUIDSGID-setting.patch @@ -0,0 +1,83 @@ +From 797ebaa8240aefc39de3d1713468b221c83ed3f5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Mar 2019 19:45:32 +0100 +Subject: [PATCH] man: document the new RestrictSUIDSGID= setting + +(cherry picked from commit 7445db6eb70e8d5989f481d0c5a08ace7047ae5b) +Related: #1687512 +--- + doc/TRANSIENT-SETTINGS.md | 1 + + man/systemd.exec.xml | 41 +++++++++++++++++++++++++++------------ + 2 files changed, 30 insertions(+), 12 deletions(-) + +diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md +index 0ea444b133..c2b5c0dcce 100644 +--- a/doc/TRANSIENT-SETTINGS.md ++++ b/doc/TRANSIENT-SETTINGS.md +@@ -149,6 +149,7 @@ All execution-related settings are available for transient units. + ✓ MemoryDenyWriteExecute= + ✓ RestrictNamespaces= + ✓ RestrictRealtime= ++✓ RestrictSUIDSGID= + ✓ RestrictAddressFamilies= + ✓ LockPersonality= + ✓ LimitCPU= +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index 87fb8b34f4..45ed1864f8 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -348,18 +348,19 @@ CapabilityBoundingSet=~CAP_B CAP_C + + NoNewPrivileges= + +- Takes a boolean argument. If true, ensures that the service process and all its children can +- never gain new privileges through execve() (e.g. via setuid or setgid bits, or filesystem +- capabilities). This is the simplest and most effective way to ensure that a process and its children can never +- elevate privileges again. Defaults to false, but certain settings override this and ignore the value of this +- setting. This is the case when SystemCallFilter=, +- SystemCallArchitectures=, RestrictAddressFamilies=, +- RestrictNamespaces=, PrivateDevices=, +- ProtectKernelTunables=, ProtectKernelModules=, +- MemoryDenyWriteExecute=, RestrictRealtime=, or +- LockPersonality= are specified. Note that even if this setting is overridden by them, +- systemctl show shows the original value of this setting. Also see +- No New Privileges ++ Takes a boolean argument. If true, ensures that the service process and all its ++ children can never gain new privileges through execve() (e.g. via setuid or ++ setgid bits, or filesystem capabilities). This is the simplest and most effective way to ensure that ++ a process and its children can never elevate privileges again. Defaults to false, but certain ++ settings override this and ignore the value of this setting. This is the case when ++ SystemCallFilter=, SystemCallArchitectures=, ++ RestrictAddressFamilies=, RestrictNamespaces=, ++ PrivateDevices=, ProtectKernelTunables=, ++ ProtectKernelModules=, MemoryDenyWriteExecute=, ++ RestrictRealtime=, RestrictSUIDSGID= or ++ LockPersonality= are specified. Note that even if this setting is overridden by ++ them, systemctl show shows the original value of this setting. Also see No New Privileges + Flag. + + +@@ -1274,6 +1275,22 @@ RestrictNamespaces=~cgroup net + that actually require them. Defaults to off. + + ++ ++ RestrictSUIDSGID= ++ ++ Takes a boolean argument. If set, any attempts to set the set-user-ID (SUID) or ++ set-group-ID (SGID) bits on files or directories will be denied (for details on these bits see ++ inode7). If ++ running in user mode, or in system mode, but without the CAP_SYS_ADMIN ++ capability (e.g. setting User=), NoNewPrivileges=yes is ++ implied. As the SUID/SGID bits are mechanisms to elevate privileges, and allows users to acquire the ++ identity of other users, it is recommended to restrict creation of SUID/SGID files to the few ++ programs that actually require them. Note that this restricts marking of any type of file system ++ object with these bits, including both regular files and directories (where the SGID is a different ++ meaning than for files, see documentation). Defaults to off. ++ ++ + + RemoveIPC= + diff --git a/SOURCES/0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch b/SOURCES/0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch new file mode 100644 index 0000000..8a9917f --- /dev/null +++ b/SOURCES/0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch @@ -0,0 +1,157 @@ +From b0573f1a6f8022aed4954d5ca19cc037d25cd5e7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Mar 2019 19:52:20 +0100 +Subject: [PATCH] units: turn on RestrictSUIDSGID= in most of our long-running + daemons + +(cherry picked from commit 62aa29247c3d74bcec0607c347f2be23cd90675d) +Related: #1687512 +--- + units/systemd-coredump@.service.in | 1 + + units/systemd-hostnamed.service.in | 1 + + units/systemd-journal-remote.service.in | 1 + + units/systemd-journald.service.in | 1 + + units/systemd-localed.service.in | 1 + + units/systemd-logind.service.in | 1 + + units/systemd-networkd.service.in | 1 + + units/systemd-resolved.service.in | 1 + + units/systemd-timedated.service.in | 1 + + units/systemd-timesyncd.service.in | 1 + + units/systemd-udevd.service.in | 3 ++- + 11 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in +index 68a68a5055..d69ebd8b24 100644 +--- a/units/systemd-coredump@.service.in ++++ b/units/systemd-coredump@.service.in +@@ -33,6 +33,7 @@ MemoryDenyWriteExecute=yes + RestrictRealtime=yes + RestrictNamespaces=yes + RestrictAddressFamilies=AF_UNIX ++RestrictSUIDSGID=yes + SystemCallFilter=@system-service + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native +diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in +index 4e5470dd29..97d4e142bc 100644 +--- a/units/systemd-hostnamed.service.in ++++ b/units/systemd-hostnamed.service.in +@@ -29,6 +29,7 @@ MemoryDenyWriteExecute=yes + RestrictRealtime=yes + RestrictNamespaces=yes + RestrictAddressFamilies=AF_UNIX ++RestrictSUIDSGID=yes + SystemCallFilter=@system-service sethostname + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native +diff --git a/units/systemd-journal-remote.service.in b/units/systemd-journal-remote.service.in +index a94265f215..3c914f5a40 100644 +--- a/units/systemd-journal-remote.service.in ++++ b/units/systemd-journal-remote.service.in +@@ -28,6 +28,7 @@ MemoryDenyWriteExecute=yes + RestrictRealtime=yes + RestrictNamespaces=yes + RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 ++RestrictSUIDSGID=yes + SystemCallArchitectures=native + LockPersonality=yes + LogsDirectory=journal/remote +diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in +index e109b25792..ab9ec35ff8 100644 +--- a/units/systemd-journald.service.in ++++ b/units/systemd-journald.service.in +@@ -21,6 +21,7 @@ Sockets=systemd-journald.socket systemd-journald-dev-log.socket + ExecStart=@rootlibexecdir@/systemd-journald + Restart=always + RestartSec=0 ++RestrictSUIDSGID=yes + StandardOutput=null + WatchdogSec=3min + FileDescriptorStoreMax=4224 +diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in +index ce043db154..b87d60e9eb 100644 +--- a/units/systemd-localed.service.in ++++ b/units/systemd-localed.service.in +@@ -29,6 +29,7 @@ MemoryDenyWriteExecute=yes + RestrictRealtime=yes + RestrictNamespaces=yes + RestrictAddressFamilies=AF_UNIX ++RestrictSUIDSGID=yes + SystemCallFilter=@system-service + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native +diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in +index 6953fac55b..086338e03b 100644 +--- a/units/systemd-logind.service.in ++++ b/units/systemd-logind.service.in +@@ -30,6 +30,7 @@ MemoryDenyWriteExecute=yes + RestrictRealtime=yes + RestrictNamespaces=yes + RestrictAddressFamilies=AF_UNIX AF_NETLINK ++RestrictSUIDSGID=yes + SystemCallFilter=@system-service + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native +diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in +index 371ab3a9cf..a0f34ac738 100644 +--- a/units/systemd-networkd.service.in ++++ b/units/systemd-networkd.service.in +@@ -39,6 +39,7 @@ SystemCallFilter=@system-service + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native + LockPersonality=yes ++RestrictSUIDSGID=yes + RuntimeDirectory=systemd/netif + RuntimeDirectoryPreserve=yes + +diff --git a/units/systemd-resolved.service.in b/units/systemd-resolved.service.in +index aaed406ab2..6c2ad5ca86 100644 +--- a/units/systemd-resolved.service.in ++++ b/units/systemd-resolved.service.in +@@ -41,6 +41,7 @@ SystemCallFilter=@system-service + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native + LockPersonality=yes ++RestrictSUIDSGID=yes + RuntimeDirectory=systemd/resolve + RuntimeDirectoryPreserve=yes + +diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in +index 662b39557a..1da2bc4bb0 100644 +--- a/units/systemd-timedated.service.in ++++ b/units/systemd-timedated.service.in +@@ -27,6 +27,7 @@ MemoryDenyWriteExecute=yes + RestrictRealtime=yes + RestrictNamespaces=yes + RestrictAddressFamilies=AF_UNIX ++RestrictSUIDSGID=yes + SystemCallFilter=@system-service @clock + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native +diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in +index 4a490b6e16..c2b9551726 100644 +--- a/units/systemd-timesyncd.service.in ++++ b/units/systemd-timesyncd.service.in +@@ -37,6 +37,7 @@ MemoryDenyWriteExecute=yes + RestrictRealtime=yes + RestrictNamespaces=yes + RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 ++RestrictSUIDSGID=yes + RuntimeDirectory=systemd/timesync + SystemCallFilter=@system-service @clock + SystemCallErrorNumber=EPERM +diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in +index fd9ead3bb8..970cf0f290 100644 +--- a/units/systemd-udevd.service.in ++++ b/units/systemd-udevd.service.in +@@ -27,8 +27,9 @@ WatchdogSec=3min + TasksMax=infinity + PrivateMounts=yes + MemoryDenyWriteExecute=yes +-RestrictRealtime=yes + RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 ++RestrictRealtime=yes ++RestrictSUIDSGID=yes + SystemCallFilter=@system-service @module @raw-io + SystemCallErrorNumber=EPERM + SystemCallArchitectures=native diff --git a/SOURCES/0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch b/SOURCES/0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch new file mode 100644 index 0000000..df4279c --- /dev/null +++ b/SOURCES/0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch @@ -0,0 +1,89 @@ +From 11f5677752f9b78239214b3064e5a2c3712d71b1 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Mar 2019 20:19:38 +0100 +Subject: [PATCH] core: imply NNP and SUID/SGID restriction for DynamicUser=yes + service + +Let's be safe, rather than sorry. This way DynamicUser=yes services can +neither take benefit of, nor create SUID/SGID binaries. + +Given that DynamicUser= is a recent addition only we should be able to +get away with turning this on, even though this is strictly speaking a +binary compatibility breakage. + +(cherry picked from commit bf65b7e0c9fc215897b676ab9a7c9d1c688143ba) +Resolves: #1687512 +--- + man/systemd.exec.xml | 16 ++++++++++------ + src/core/unit.c | 10 ++++++++-- + 2 files changed, 18 insertions(+), 8 deletions(-) + +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index 45ed1864f8..bdaed68162 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -229,7 +229,9 @@ + created by the executed processes is bound to the runtime of the service, and hence the lifetime of the dynamic + user/group. Since /tmp and /var/tmp are usually the only + world-writable directories on a system this ensures that a unit making use of dynamic user/group allocation +- cannot leave files around after unit termination. Moreover ProtectSystem=strict and ++ cannot leave files around after unit termination. Furthermore NoNewPrivileges= and ++ RestrictSUIDSGID= are implicitly enabled to ensure that processes invoked cannot take benefit ++ or create SUID/SGID files or directories. Moreover ProtectSystem=strict and + ProtectHome=read-only are implied, thus prohibiting the service to write to arbitrary file + system locations. In order to allow the service to write to certain directories, they have to be whitelisted + using ReadWritePaths=, but care must be taken so that UID/GID recycling doesn't create +@@ -357,11 +359,12 @@ CapabilityBoundingSet=~CAP_B CAP_C + RestrictAddressFamilies=, RestrictNamespaces=, + PrivateDevices=, ProtectKernelTunables=, + ProtectKernelModules=, MemoryDenyWriteExecute=, +- RestrictRealtime=, RestrictSUIDSGID= or +- LockPersonality= are specified. Note that even if this setting is overridden by +- them, systemctl show shows the original value of this setting. Also see RestrictRealtime=, RestrictSUIDSGID=, ++ DynamicUser= or LockPersonality= are specified. Note that even ++ if this setting is overridden by them, systemctl show shows the original value of ++ this setting. Also see No New Privileges +- Flag. ++ Flag. + + + +@@ -1288,7 +1291,8 @@ RestrictNamespaces=~cgroup net + identity of other users, it is recommended to restrict creation of SUID/SGID files to the few + programs that actually require them. Note that this restricts marking of any type of file system + object with these bits, including both regular files and directories (where the SGID is a different +- meaning than for files, see documentation). Defaults to off. ++ meaning than for files, see documentation). This option is implied if DynamicUser= ++ is enabled. Defaults to off. + + + +diff --git a/src/core/unit.c b/src/core/unit.c +index 115739f4c6..e1f5e6f7bd 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -4161,14 +4161,20 @@ int unit_patch_contexts(Unit *u) { + return -ENOMEM; + } + +- /* If the dynamic user option is on, let's make sure that the unit can't leave its UID/GID +- * around in the file system or on IPC objects. Hence enforce a strict sandbox. */ ++ /* If the dynamic user option is on, let's make sure that the unit can't leave its ++ * UID/GID around in the file system or on IPC objects. Hence enforce a strict ++ * sandbox. */ + + ec->private_tmp = true; + ec->remove_ipc = true; + ec->protect_system = PROTECT_SYSTEM_STRICT; + if (ec->protect_home == PROTECT_HOME_NO) + ec->protect_home = PROTECT_HOME_READ_ONLY; ++ ++ /* Make sure this service can neither benefit from SUID/SGID binaries nor create ++ * them. */ ++ ec->no_new_privileges = true; ++ ec->restrict_suid_sgid = true; + } + } + diff --git a/SOURCES/0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch b/SOURCES/0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch new file mode 100644 index 0000000..d8d2f87 --- /dev/null +++ b/SOURCES/0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch @@ -0,0 +1,555 @@ +From b55c9b8e717d1967e6aa16c1e2646fc81d899ab7 Mon Sep 17 00:00:00 2001 +From: Pavel Hrdina +Date: Mon, 29 Jul 2019 17:50:05 +0200 +Subject: [PATCH] cgroup: introduce support for cgroup v2 CPUSET controller + +Introduce support for configuring cpus and mems for processes using +cgroup v2 CPUSET controller. This allows users to limit which cpus +and memory NUMA nodes can be used by processes to better utilize +system resources. + +The cgroup v2 interfaces to control it are cpuset.cpus and cpuset.mems +where the requested configuration is written. However, it doesn't mean +that the requested configuration will be actually used as parent cgroup +may limit the cpus or mems as well. In order to reflect the real +configuration cgroup v2 provides read-only files cpuset.cpus.effective +and cpuset.mems.effective which are exported to users as well. + +(cherry picked from commit 047f5d63d7a1ab75073f8485e2f9b550d25b0772) + +Related: #1724617 +--- + doc/TRANSIENT-SETTINGS.md | 2 + + man/systemd.resource-control.xml | 30 +++++++++++++ + src/basic/cgroup-util.c | 1 + + src/basic/cgroup-util.h | 2 + + src/core/cgroup.c | 63 +++++++++++++++++++++++++++ + src/core/cgroup.h | 5 +++ + src/core/dbus-cgroup.c | 59 +++++++++++++++++++++++++ + src/core/dbus-unit.c | 48 ++++++++++++++++++++ + src/core/load-fragment-gperf.gperf.m4 | 2 + + src/core/load-fragment.c | 38 ++++++++++++++++ + src/core/load-fragment.h | 2 + + src/shared/bus-unit-util.c | 16 +++++++ + src/systemctl/systemctl.c | 2 +- + src/test/test-cgroup-mask.c | 3 +- + 14 files changed, 271 insertions(+), 2 deletions(-) + +diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md +index c2b5c0dcce..0b2ad66dcb 100644 +--- a/doc/TRANSIENT-SETTINGS.md ++++ b/doc/TRANSIENT-SETTINGS.md +@@ -218,6 +218,8 @@ All cgroup/resource control settings are available for transient units + ✓ CPUShares= + ✓ StartupCPUShares= + ✓ CPUQuota= ++✓ AllowedCPUs= ++✓ AllowedMemoryNodes= + ✓ MemoryAccounting= + ✓ MemoryLow= + ✓ MemoryHigh= +diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml +index 370c110592..4329742e94 100644 +--- a/man/systemd.resource-control.xml ++++ b/man/systemd.resource-control.xml +@@ -201,6 +201,36 @@ + + + ++ ++ AllowedCPUs= ++ ++ ++ Restrict processes to be executed on specific CPUs. Takes a list of CPU indices or ranges separated by either ++ whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a dash. ++ ++ Setting AllowedCPUs= doesn't guarantee that all of the CPUs will be used by the processes ++ as it may be limited by parent units. The effective configuration is reported as EffectiveCPUs=. ++ ++ This setting is supported only with the unified control group hierarchy. ++ ++ ++ ++ ++ AllowedMemoryNodes= ++ ++ ++ Restrict processes to be executed on specific memory NUMA nodes. Takes a list of memory NUMA nodes indices ++ or ranges separated by either whitespace or commas. Memory NUMA nodes ranges are specified by the lower and upper ++ CPU indices separated by a dash. ++ ++ Setting AllowedMemoryNodes= doesn't guarantee that all of the memory NUMA nodes will ++ be used by the processes as it may be limited by parent units. The effective configuration is reported as ++ EffectiveMemoryNodes=. ++ ++ This setting is supported only with the unified control group hierarchy. ++ ++ ++ + + MemoryAccounting= + +diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c +index 038ece4b06..6f47c3aacb 100644 +--- a/src/basic/cgroup-util.c ++++ b/src/basic/cgroup-util.c +@@ -2763,6 +2763,7 @@ bool fd_is_cgroup_fs(int fd) { + static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = { + [CGROUP_CONTROLLER_CPU] = "cpu", + [CGROUP_CONTROLLER_CPUACCT] = "cpuacct", ++ [CGROUP_CONTROLLER_CPUSET] = "cpuset", + [CGROUP_CONTROLLER_IO] = "io", + [CGROUP_CONTROLLER_BLKIO] = "blkio", + [CGROUP_CONTROLLER_MEMORY] = "memory", +diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h +index 26e3ae0404..b414600dca 100644 +--- a/src/basic/cgroup-util.h ++++ b/src/basic/cgroup-util.h +@@ -21,6 +21,7 @@ + typedef enum CGroupController { + CGROUP_CONTROLLER_CPU, + CGROUP_CONTROLLER_CPUACCT, /* v1 only */ ++ CGROUP_CONTROLLER_CPUSET, /* v2 only */ + CGROUP_CONTROLLER_IO, /* v2 only */ + CGROUP_CONTROLLER_BLKIO, /* v1 only */ + CGROUP_CONTROLLER_MEMORY, +@@ -36,6 +37,7 @@ typedef enum CGroupController { + typedef enum CGroupMask { + CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU), + CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT), ++ CGROUP_MASK_CPUSET = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUSET), + CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO), + CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO), + CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY), +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 76eafdc082..664d269483 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -161,9 +161,14 @@ void cgroup_context_done(CGroupContext *c) { + + c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow); + c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny); ++ ++ cpu_set_reset(&c->cpuset_cpus); ++ cpu_set_reset(&c->cpuset_mems); + } + + void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { ++ _cleanup_free_ char *cpuset_cpus = NULL; ++ _cleanup_free_ char *cpuset_mems = NULL; + CGroupIODeviceLimit *il; + CGroupIODeviceWeight *iw; + CGroupBlockIODeviceBandwidth *b; +@@ -177,6 +182,9 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { + + prefix = strempty(prefix); + ++ cpuset_cpus = cpu_set_to_range_string(&c->cpuset_cpus); ++ cpuset_mems = cpu_set_to_range_string(&c->cpuset_mems); ++ + fprintf(f, + "%sCPUAccounting=%s\n" + "%sIOAccounting=%s\n" +@@ -189,6 +197,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { + "%sCPUShares=%" PRIu64 "\n" + "%sStartupCPUShares=%" PRIu64 "\n" + "%sCPUQuotaPerSecSec=%s\n" ++ "%sAllowedCPUs=%s\n" ++ "%sAllowedMemoryNodes=%s\n" + "%sIOWeight=%" PRIu64 "\n" + "%sStartupIOWeight=%" PRIu64 "\n" + "%sBlockIOWeight=%" PRIu64 "\n" +@@ -212,6 +222,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { + prefix, c->cpu_shares, + prefix, c->startup_cpu_shares, + prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1), ++ prefix, cpuset_cpus, ++ prefix, cpuset_mems, + prefix, c->io_weight, + prefix, c->startup_io_weight, + prefix, c->blockio_weight, +@@ -541,6 +553,21 @@ static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) { + CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX); + } + ++static void cgroup_apply_unified_cpuset(Unit *u, CPUSet cpus, const char *name) { ++ _cleanup_free_ char *buf = NULL; ++ int r; ++ ++ buf = cpu_set_to_range_string(&cpus); ++ if (!buf) ++ return; ++ ++ r = cg_set_attribute("cpuset", u->cgroup_path, name, buf); ++ if (r < 0) ++ log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, ++ "Failed to set %s: %m", name); ++ ++} ++ + static bool cgroup_context_has_io_config(CGroupContext *c) { + return c->io_accounting || + c->io_weight != CGROUP_WEIGHT_INVALID || +@@ -766,6 +793,11 @@ static void cgroup_context_apply( + } + } + ++ if ((apply_mask & CGROUP_MASK_CPUSET) && !is_root) { ++ cgroup_apply_unified_cpuset(u, c->cpuset_cpus, "cpuset.cpus"); ++ cgroup_apply_unified_cpuset(u, c->cpuset_mems, "cpuset.mems"); ++ } ++ + if (apply_mask & CGROUP_MASK_IO) { + bool has_io = cgroup_context_has_io_config(c); + bool has_blockio = cgroup_context_has_blockio_config(c); +@@ -1068,6 +1100,9 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) { + c->cpu_quota_per_sec_usec != USEC_INFINITY) + mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU; + ++ if (c->cpuset_cpus.set || c->cpuset_mems.set) ++ mask |= CGROUP_MASK_CPUSET; ++ + if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c)) + mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO; + +@@ -2697,4 +2732,32 @@ static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = + [CGROUP_STRICT] = "strict", + }; + ++int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) { ++ _cleanup_free_ char *v = NULL; ++ int r; ++ ++ assert(u); ++ assert(cpus); ++ ++ if (!u->cgroup_path) ++ return -ENODATA; ++ ++ if ((u->cgroup_realized_mask & CGROUP_MASK_CPUSET) == 0) ++ return -ENODATA; ++ ++ r = cg_all_unified(); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return -ENODATA; ++ if (r > 0) ++ r = cg_get_attribute("cpuset", u->cgroup_path, name, &v); ++ if (r == -ENOENT) ++ return -ENODATA; ++ if (r < 0) ++ return r; ++ ++ return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL); ++} ++ + DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy); +diff --git a/src/core/cgroup.h b/src/core/cgroup.h +index 2d2ff6fc3c..da10575394 100644 +--- a/src/core/cgroup.h ++++ b/src/core/cgroup.h +@@ -4,6 +4,7 @@ + #include + + #include "cgroup-util.h" ++#include "cpu-set-util.h" + #include "ip-address-access.h" + #include "list.h" + #include "time-util.h" +@@ -77,6 +78,9 @@ struct CGroupContext { + uint64_t startup_cpu_weight; + usec_t cpu_quota_per_sec_usec; + ++ CPUSet cpuset_cpus; ++ CPUSet cpuset_mems; ++ + uint64_t io_weight; + uint64_t startup_io_weight; + LIST_HEAD(CGroupIODeviceWeight, io_device_weights); +@@ -205,3 +209,4 @@ const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_; + CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_; + + bool unit_cgroup_delegate(Unit *u); ++int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name); +diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c +index 540bc77aed..30d4e83932 100644 +--- a/src/core/dbus-cgroup.c ++++ b/src/core/dbus-cgroup.c +@@ -53,6 +53,27 @@ static int property_get_delegate_controllers( + return sd_bus_message_close_container(reply); + } + ++static int property_get_cpuset( ++ sd_bus *bus, ++ const char *path, ++ const char *interface, ++ const char *property, ++ sd_bus_message *reply, ++ void *userdata, ++ sd_bus_error *error) { ++ ++ CPUSet *cpus = userdata; ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; ++ ++ assert(bus); ++ assert(reply); ++ assert(cpus); ++ ++ (void) cpu_set_to_dbus(cpus, &array, &allocated); ++ return sd_bus_message_append_array(reply, 'y', array, allocated); ++} ++ + static int property_get_io_device_weight( + sd_bus *bus, + const char *path, +@@ -283,6 +304,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = { + SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0), + SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0), + SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0), ++ SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0), ++ SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0), + SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0), + SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0), + SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0), +@@ -671,6 +694,42 @@ int bus_cgroup_set_property( + + return 1; + ++ } else if (STR_IN_SET(name, "AllowedCPUs", "AllowedMemoryNodes")) { ++ const void *a; ++ size_t n; ++ _cleanup_(cpu_set_reset) CPUSet new_set = {}; ++ ++ r = sd_bus_message_read_array(message, 'y', &a, &n); ++ if (r < 0) ++ return r; ++ ++ r = cpu_set_from_dbus(a, n, &new_set); ++ if (r < 0) ++ return r; ++ ++ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { ++ _cleanup_free_ char *setstr = NULL; ++ _cleanup_free_ char *data = NULL; ++ CPUSet *set; ++ ++ setstr = cpu_set_to_range_string(&new_set); ++ ++ if (streq(name, "AllowedCPUs")) ++ set = &c->cpuset_cpus; ++ else ++ set = &c->cpuset_mems; ++ ++ if (asprintf(&data, "%s=%s", name, setstr) < 0) ++ return -ENOMEM; ++ ++ cpu_set_reset(set); ++ cpu_set_add_all(set, &new_set); ++ unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET); ++ unit_write_setting(u, flags, name, data); ++ } ++ ++ return 1; ++ + } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) { + const char *path; + unsigned n = 0; +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index c5bca10979..aa15e47754 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -752,6 +752,52 @@ static int property_get_cpu_usage( + return sd_bus_message_append(reply, "t", ns); + } + ++static int property_get_cpuset_cpus( ++ sd_bus *bus, ++ const char *path, ++ const char *interface, ++ const char *property, ++ sd_bus_message *reply, ++ void *userdata, ++ sd_bus_error *error) { ++ ++ Unit *u = userdata; ++ _cleanup_(cpu_set_reset) CPUSet cpus = {}; ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; ++ ++ assert(bus); ++ assert(reply); ++ assert(u); ++ ++ (void) unit_get_cpuset(u, &cpus, "cpuset.cpus.effective"); ++ (void) cpu_set_to_dbus(&cpus, &array, &allocated); ++ return sd_bus_message_append_array(reply, 'y', array, allocated); ++} ++ ++static int property_get_cpuset_mems( ++ sd_bus *bus, ++ const char *path, ++ const char *interface, ++ const char *property, ++ sd_bus_message *reply, ++ void *userdata, ++ sd_bus_error *error) { ++ ++ Unit *u = userdata; ++ _cleanup_(cpu_set_reset) CPUSet mems = {}; ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; ++ ++ assert(bus); ++ assert(reply); ++ assert(u); ++ ++ (void) unit_get_cpuset(u, &mems, "cpuset.mems.effective"); ++ (void) cpu_set_to_dbus(&mems, &array, &allocated); ++ return sd_bus_message_append_array(reply, 'y', array, allocated); ++} ++ + static int property_get_cgroup( + sd_bus *bus, + const char *path, +@@ -1074,6 +1120,8 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = { + SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0), + SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0), + SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0), ++ SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0), ++ SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0), + SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0), + SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0), + SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0), +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index 49e938d0ce..ebb44df487 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -167,6 +167,8 @@ $1.StartupCPUWeight, config_parse_cg_weight, 0, + $1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares) + $1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares) + $1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context) ++$1.CPUSetCpus, config_parse_cpuset_cpus, 0, offsetof($1, cgroup_context) ++$1.CPUSetMems, config_parse_cpuset_mems, 0, offsetof($1, cgroup_context) + $1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting) + $1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context) + $1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 35dd595098..6debf82401 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -3011,6 +3011,44 @@ int config_parse_cpu_quota( + return 0; + } + ++int config_parse_cpuset_cpus( ++ const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ ++ CGroupContext *c = data; ++ ++ (void) parse_cpu_set_extend(rvalue, &c->cpuset_cpus, true, unit, filename, line, lvalue); ++ ++ return 0; ++} ++ ++int config_parse_cpuset_mems( ++ const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ ++ CGroupContext *c = data; ++ ++ (void) parse_cpu_set_extend(rvalue, &c->cpuset_mems, true, unit, filename, line, lvalue); ++ ++ return 0; ++} ++ + int config_parse_memory_limit( + const char *unit, + const char *filename, +diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h +index f2ca1b8ee7..6612e1fb32 100644 +--- a/src/core/load-fragment.h ++++ b/src/core/load-fragment.h +@@ -86,6 +86,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_set_status); + CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv); + CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems); + CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota); ++CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_cpus); ++CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_mems); + CONFIG_PARSER_PROTOTYPE(config_parse_protect_home); + CONFIG_PARSER_PROTOTYPE(config_parse_protect_system); + CONFIG_PARSER_PROTOTYPE(config_parse_bus_name); +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 3c42e97b7a..8f3b463c6b 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -396,6 +396,22 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons + + return bus_append_cg_cpu_shares_parse(m, field, eq); + ++ if (STR_IN_SET(field, "AllowedCPUs", "AllowedMemoryNodes")) { ++ _cleanup_(cpu_set_reset) CPUSet cpuset = {}; ++ _cleanup_free_ uint8_t *array = NULL; ++ size_t allocated; ++ ++ r = parse_cpu_set(eq, &cpuset); ++ if (r < 0) ++ return log_error_errno(r, "Failed to parse %s value: %s", field, eq); ++ ++ r = cpu_set_to_dbus(&cpuset, &array, &allocated); ++ if (r < 0) ++ return log_error_errno(r, "Failed to serialize CPUSet: %m"); ++ ++ return bus_append_byte_array(m, field, array, allocated); ++ } ++ + if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) + + return bus_append_cg_blkio_weight_parse(m, field, eq); +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 7274921e6d..a3074bc5e3 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -4892,7 +4892,7 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool + print_prop(name, "%s", h); + + return 1; +- } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask")) { ++ } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes", "EffectiveCPUs", "EffectiveMemoryNodes")) { + _cleanup_free_ char *affinity = NULL; + _cleanup_(cpu_set_reset) CPUSet set = {}; + const void *a; +diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c +index d65959edf1..93c3f5d856 100644 +--- a/src/test/test-cgroup-mask.c ++++ b/src/test/test-cgroup-mask.c +@@ -104,9 +104,10 @@ static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) { + + static void test_cg_mask_to_string(void) { + test_cg_mask_to_string_one(0, NULL); +- test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct io blkio memory devices pids"); ++ test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids"); + test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu"); + test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT, "cpuacct"); ++ test_cg_mask_to_string_one(CGROUP_MASK_CPUSET, "cpuset"); + test_cg_mask_to_string_one(CGROUP_MASK_IO, "io"); + test_cg_mask_to_string_one(CGROUP_MASK_BLKIO, "blkio"); + test_cg_mask_to_string_one(CGROUP_MASK_MEMORY, "memory"); diff --git a/SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch b/SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch new file mode 100644 index 0000000..9c89a62 --- /dev/null +++ b/SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch @@ -0,0 +1,41 @@ +From e809564cfa5af01a26075682d49f81a987c41dd8 Mon Sep 17 00:00:00 2001 +From: Franck Bui +Date: Wed, 2 Oct 2019 11:58:16 +0200 +Subject: [PATCH 331/341] pid1: fix DefaultTasksMax initialization + +Otherwise DefaultTasksMax is always set to "inifinity". + +This was broken by fb39af4ce42. + +(cherry picked from commit c0000de87d2c7934cb1f4ba66a533a85277600ff) + +Resolves: #1809037 +--- + src/core/main.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index d6550ea161..45d09b1e11 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -2088,7 +2088,7 @@ static void reset_arguments(void) { + arg_default_blockio_accounting = false; + arg_default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT; + arg_default_tasks_accounting = true; +- arg_default_tasks_max = UINT64_MAX; ++ arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U); + arg_machine_id = (sd_id128_t) {}; + arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; + +@@ -2103,8 +2103,6 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile, + assert(saved_rlimit_nofile); + assert(saved_rlimit_memlock); + +- arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U); +- + /* Assign configuration defaults */ + reset_arguments(); + +-- +2.21.1 + diff --git a/SOURCES/0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch b/SOURCES/0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch new file mode 100644 index 0000000..2596a8e --- /dev/null +++ b/SOURCES/0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch @@ -0,0 +1,43 @@ +From 5fc2d94fbf8271bb340e834f832af5d890c267bf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Tue, 3 Mar 2020 11:45:00 +0100 +Subject: [PATCH 332/341] cgroup: make sure that cpuset is supported on cgroup + v2 and disabled with v1 + +Resolves: #1808940 + +(rhel-only) +--- + src/basic/cgroup-util.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c +index 6f47c3aacb..92bc1f2543 100644 +--- a/src/basic/cgroup-util.c ++++ b/src/basic/cgroup-util.c +@@ -2353,10 +2353,10 @@ int cg_mask_supported(CGroupMask *ret) { + if (r < 0) + return r; + +- /* Currently, we support the cpu, memory, io and pids ++ /* Currently, we support the cpu, memory, io, pids and cpuset + * controller in the unified hierarchy, mask + * everything else off. */ +- mask &= CGROUP_MASK_CPU | CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS; ++ mask &= CGROUP_MASK_CPU | CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS | CGROUP_MASK_CPUSET; + + } else { + CGroupController c; +@@ -2367,6 +2367,9 @@ int cg_mask_supported(CGroupMask *ret) { + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + const char *n; + ++ if (c == CGROUP_CONTROLLER_CPUSET) ++ continue; ++ + n = cgroup_controller_to_string(c); + if (controller_is_accessible(n) >= 0) + mask |= CGROUP_CONTROLLER_TO_MASK(c); +-- +2.21.1 + diff --git a/SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch b/SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch new file mode 100644 index 0000000..2e1b42a --- /dev/null +++ b/SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch @@ -0,0 +1,383 @@ +From 90dda340e4adeb1126639a849d4f31ae327fdc4b Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 25 Jun 2019 23:01:40 +0200 +Subject: [PATCH 333/341] test: introduce TEST-36-NUMAPOLICY + +(cherry picked from commit 8f65e26508969610ac934d1aadbade8223bfcaac) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/Makefile | 1 + + test/TEST-36-NUMAPOLICY/test.sh | 51 +++++ + test/TEST-36-NUMAPOLICY/testsuite.sh | 292 +++++++++++++++++++++++++++ + 3 files changed, 344 insertions(+) + create mode 120000 test/TEST-36-NUMAPOLICY/Makefile + create mode 100755 test/TEST-36-NUMAPOLICY/test.sh + create mode 100755 test/TEST-36-NUMAPOLICY/testsuite.sh + +diff --git a/test/TEST-36-NUMAPOLICY/Makefile b/test/TEST-36-NUMAPOLICY/Makefile +new file mode 120000 +index 0000000000..e9f93b1104 +--- /dev/null ++++ b/test/TEST-36-NUMAPOLICY/Makefile +@@ -0,0 +1 @@ ++../TEST-01-BASIC/Makefile +\ No newline at end of file +diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh +new file mode 100755 +index 0000000000..a0d8623e8e +--- /dev/null ++++ b/test/TEST-36-NUMAPOLICY/test.sh +@@ -0,0 +1,51 @@ ++#!/bin/bash ++set -e ++TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options" ++TEST_NO_NSPAWN=1 ++QEMU_OPTIONS="-numa node,nodeid=0" ++ ++. $TEST_BASE_DIR/test-functions ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ setup_basic_environment ++ inst_binary mktemp ++ ++ # mask some services that we do not want to run in these tests ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service ++ ++ # setup the testsuite service ++ cat >$initdir/etc/systemd/system/testsuite.service < $journalLog ++} ++ ++stopJournalctl() { ++ # Wait a few seconds until the messages get properly queued... ++ sleep $journalSleep ++ # ...and then force journald to write them to the backing storage ++ # Also, using journalctl --sync should be better than using SIGRTMIN+1, as ++ # the --sync wait until the synchronization is complete ++ echo "Force journald to write all queued messages" ++ journalctl --sync ++ kill -s TERM $COPROC_PID ++} ++ ++checkNUMA() { ++ # NUMA enabled system should have at least NUMA node0 ++ test -e /sys/devices/system/node/node0 ++} ++ ++writePID1NUMAPolicy() { ++ echo [Manager] > $confDir/numa.conf ++ echo NUMAPolicy=$1 >> $confDir/numa.conf ++ echo NUMAMask=$2>> $confDir/numa.conf ++} ++ ++writeTestUnit() { ++ echo [Service] > $testUnitFile ++ echo ExecStart=/bin/sleep 3600 >> $testUnitFile ++ mkdir -p $testUnitFile.d/ ++} ++ ++writeTestUnitNUMAPolicy() { ++ echo [Service] > $testUnitNUMAConf ++ echo NUMAPolicy=$1 >> $testUnitNUMAConf ++ echo NUMAMask=$2>> $testUnitNUMAConf ++ systemctl daemon-reload ++} ++ ++pid1ReloadWithStrace() { ++ startStrace ++ systemctl daemon-reload ++ stopStrace ++} ++ ++pid1ReloadWithJournal() { ++ startJournalctl ++ systemctl daemon-reload ++ stopJournalctl ++} ++ ++pid1StartUnitWithStrace() { ++ startStrace '-f' ++ systemctl start $1 ++ sleep $sleepAfterStart ++ stopStrace ++} ++ ++pid1StartUnitWithJournal() { ++ startJournalctl ++ systemctl start $1 ++ sleep $sleepAfterStart ++ stopJournalctl ++} ++ ++pid1StopUnit() { ++ systemctl stop $1 ++} ++ ++systemctlCheckNUMAProperties() { ++ local LOGFILE="$(mktemp)" ++ systemctl show -p NUMAPolicy $1 > "$LOGFILE" ++ grep "NUMAPolicy=$2" "$LOGFILE" ++ ++ > "$LOGFILE" ++ ++ if [ -n $3 ]; then ++ systemctl show -p NUMAMask $1 > "$LOGFILE" ++ grep "NUMAMask=$3" "$LOGFILE" ++ fi ++} ++ ++checkNUMA ++writeTestUnit ++ ++# Create systemd config drop-in directory ++confDir="/etc/systemd/system.conf.d/" ++mkdir -p "$confDir" ++ ++echo "PID1 NUMAPolicy support - Default policy w/o mask" ++writePID1NUMAPolicy "default" ++pid1ReloadWithStrace ++# Kernel requires that nodemask argument is set to NULL when setting default policy ++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++echo "PID1 NUMAPolicy support - Default policy w/ mask" ++writePID1NUMAPolicy "default" "0" ++pid1ReloadWithStrace ++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++echo "PID1 NUMAPolicy support - Bind policy w/o mask" ++writePID1NUMAPolicy "bind" ++pid1ReloadWithJournal ++grep "Failed to set NUMA memory policy: Invalid argument" $journalLog ++ ++echo "PID1 NUMAPolicy support - Bind policy w/ mask" ++writePID1NUMAPolicy "bind" "0" ++pid1ReloadWithStrace ++grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog ++ ++echo "PID1 NUMAPolicy support - Interleave policy w/o mask" ++writePID1NUMAPolicy "interleave" ++pid1ReloadWithJournal ++grep "Failed to set NUMA memory policy: Invalid argument" $journalLog ++ ++echo "PID1 NUMAPolicy support - Interleave policy w/ mask" ++writePID1NUMAPolicy "interleave" "0" ++pid1ReloadWithStrace ++grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog ++ ++echo "PID1 NUMAPolicy support - Preferred policy w/o mask" ++writePID1NUMAPolicy "preferred" ++pid1ReloadWithJournal ++# Preferred policy with empty node mask is actually allowed and should reset allocation policy to default ++! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog ++ ++echo "PID1 NUMAPolicy support - Preferred policy w/ mask" ++writePID1NUMAPolicy "preferred" "0" ++pid1ReloadWithStrace ++grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog ++ ++echo "PID1 NUMAPolicy support - Local policy w/o mask" ++writePID1NUMAPolicy "local" ++pid1ReloadWithStrace ++# Kernel requires that nodemask argument is set to NULL when setting default policy ++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++ ++echo "PID1 NUMAPolicy support - Local policy w/ mask" ++writePID1NUMAPolicy "local" "0" ++pid1ReloadWithStrace ++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++ ++echo "Unit file NUMAPolicy support - Default policy w/o mask" ++writeTestUnitNUMAPolicy "default" ++pid1StartUnitWithStrace $testUnit ++systemctlCheckNUMAProperties $testUnit "default" ++pid1StopUnit $testUnit ++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++echo "Unit file NUMAPolicy support - Default policy w/ mask" ++writeTestUnitNUMAPolicy "default" "0" ++pid1StartUnitWithStrace $testUnit ++systemctlCheckNUMAProperties $testUnit "default" "0" ++pid1StopUnit $testUnit ++# Maks must be ignored ++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++echo "Unit file NUMAPolicy support - Bind policy w/o mask" ++writeTestUnitNUMAPolicy "bind" ++pid1StartUnitWithJournal $testUnit ++pid1StopUnit $testUnit ++grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog ++ ++echo "Unit file NUMAPolicy support - Bind policy w/ mask" ++writeTestUnitNUMAPolicy "bind" "0" ++pid1StartUnitWithStrace $testUnit ++systemctlCheckNUMAProperties $testUnit "bind" "0" ++pid1StopUnit $testUnit ++grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog ++ ++echo "Unit file NUMAPolicy support - Interleave policy w/o mask" ++writeTestUnitNUMAPolicy "interleave" ++pid1StartUnitWithStrace $testUnit ++pid1StopUnit $testUnit ++grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog ++ ++echo "Unit file NUMAPolicy support - Interleave policy w/ mask" ++writeTestUnitNUMAPolicy "interleave" "0" ++pid1StartUnitWithStrace $testUnit ++systemctlCheckNUMAProperties $testUnit "interleave" "0" ++pid1StopUnit $testUnit ++grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog ++ ++echo "Unit file NUMAPolicy support - Preferred policy w/o mask" ++writeTestUnitNUMAPolicy "preferred" ++pid1StartUnitWithJournal $testUnit ++systemctlCheckNUMAProperties $testUnit "preferred" ++pid1StopUnit $testUnit ++! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog ++ ++echo "Unit file NUMAPolicy support - Preferred policy w/ mask" ++writeTestUnitNUMAPolicy "preferred" "0" ++pid1StartUnitWithStrace $testUnit ++systemctlCheckNUMAProperties $testUnit "preferred" "0" ++pid1StopUnit $testUnit ++grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog ++ ++echo "Unit file NUMAPolicy support - Local policy w/o mask" ++writeTestUnitNUMAPolicy "local" ++pid1StartUnitWithStrace $testUnit ++systemctlCheckNUMAProperties $testUnit "local" ++pid1StopUnit $testUnit ++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++ ++echo "Unit file NUMAPolicy support - Local policy w/ mask" ++writeTestUnitNUMAPolicy "local" "0" ++pid1StartUnitWithStrace $testUnit ++systemctlCheckNUMAProperties $testUnit "local" "0" ++pid1StopUnit $testUnit ++# Maks must be ignored ++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++ ++echo "systemd-run NUMAPolicy support" ++runUnit='numa-systemd-run-test.service' ++ ++systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000 ++systemctlCheckNUMAProperties $runUnit "default" ++pid1StopUnit $runUnit ++ ++systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000 ++systemctlCheckNUMAProperties $runUnit "default" "" ++pid1StopUnit $runUnit ++ ++systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000 ++systemctlCheckNUMAProperties $runUnit "bind" "0" ++pid1StopUnit $runUnit ++ ++systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000 ++systemctlCheckNUMAProperties $runUnit "interleave" "0" ++pid1StopUnit $runUnit ++ ++systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000 ++systemctlCheckNUMAProperties $runUnit "preferred" "0" ++pid1StopUnit $runUnit ++ ++systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000 ++systemctlCheckNUMAProperties $runUnit "local" ++pid1StopUnit $runUnit ++ ++systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000 ++systemctlCheckNUMAProperties $runUnit "local" "" ++pid1StopUnit $runUnit ++ ++# Cleanup ++rm -rf $testDir ++rm -rf $confDir ++systemctl daemon-reload ++ ++systemd-analyze log-level info ++ ++echo OK > /testok ++ ++exit 0 +-- +2.21.1 + diff --git a/SOURCES/0334-test-replace-tail-f-with-journal-cursor-which-should.patch b/SOURCES/0334-test-replace-tail-f-with-journal-cursor-which-should.patch new file mode 100644 index 0000000..8254d16 --- /dev/null +++ b/SOURCES/0334-test-replace-tail-f-with-journal-cursor-which-should.patch @@ -0,0 +1,55 @@ +From b93a2617d49d9636801130d974995cabe6335b71 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 1 Jul 2019 09:27:59 +0200 +Subject: [PATCH 334/341] test: replace `tail -f` with journal cursor which + should be... + +more reliable + +(cherry picked from commit d0b2178f3e79f302702bd7140766eee03643f734) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/testsuite.sh | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh +index e15087b137..306a96b517 100755 +--- a/test/TEST-36-NUMAPOLICY/testsuite.sh ++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh +@@ -29,6 +29,9 @@ testUnitNUMAConf="$testUnitFile.d/numa.conf" + journalSleep=5 + sleepAfterStart=1 + ++# Journal cursor for easier navigation ++journalCursorFile="jounalCursorFile" ++ + startStrace() { + coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1 + } +@@ -38,18 +41,16 @@ stopStrace() { + } + + startJournalctl() { +- coproc journalctl -u init.scope -f > $journalLog ++ # Save journal's cursor for later navigation ++ journalctl --no-pager --cursor-file="$journalCursorFile" -n0 -ocat + } + + stopJournalctl() { +- # Wait a few seconds until the messages get properly queued... +- sleep $journalSleep +- # ...and then force journald to write them to the backing storage +- # Also, using journalctl --sync should be better than using SIGRTMIN+1, as ++ # Using journalctl --sync should be better than using SIGRTMIN+1, as + # the --sync wait until the synchronization is complete + echo "Force journald to write all queued messages" + journalctl --sync +- kill -s TERM $COPROC_PID ++ journalctl -u init.scope --cursor-file="$journalCursorFile" > "$journalLog" + } + + checkNUMA() { +-- +2.21.1 + diff --git a/SOURCES/0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch b/SOURCES/0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch new file mode 100644 index 0000000..8d293d9 --- /dev/null +++ b/SOURCES/0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch @@ -0,0 +1,61 @@ +From d6d43b81df76d571d57f83ceb050c8b4ac4701b8 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 1 Jul 2019 13:08:26 +0200 +Subject: [PATCH 335/341] test: support MPOL_LOCAL matching in unpatched strace + versions + +The MPOL_LOCAL constant is not recognized in current strace versions. +Let's match at least the numerical value of this constant until the +strace patch is approved & merged. + +(cherry picked from commit ac14396d027023e1be910327989cb422cb2f6724) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/testsuite.sh | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh +index 306a96b517..a4134bdeca 100755 +--- a/test/TEST-36-NUMAPOLICY/testsuite.sh ++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh +@@ -173,12 +173,16 @@ echo "PID1 NUMAPolicy support - Local policy w/o mask" + writePID1NUMAPolicy "local" + pid1ReloadWithStrace + # Kernel requires that nodemask argument is set to NULL when setting default policy +-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++# The unpatched versions of strace don't recognize the MPOL_LOCAL constant and ++# return a numerical constant instead (with a comment): ++# set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0 ++# Let's cover this scenario as well ++grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "PID1 NUMAPolicy support - Local policy w/ mask" + writePID1NUMAPolicy "local" "0" + pid1ReloadWithStrace +-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "Unit file NUMAPolicy support - Default policy w/o mask" + writeTestUnitNUMAPolicy "default" +@@ -240,7 +244,7 @@ writeTestUnitNUMAPolicy "local" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "local" + pid1StopUnit $testUnit +-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "Unit file NUMAPolicy support - Local policy w/ mask" + writeTestUnitNUMAPolicy "local" "0" +@@ -248,7 +252,7 @@ pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "local" "0" + pid1StopUnit $testUnit + # Maks must be ignored +-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog ++grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "systemd-run NUMAPolicy support" + runUnit='numa-systemd-run-test.service' +-- +2.21.1 + diff --git a/SOURCES/0336-test-make-sure-the-strace-process-is-indeed-dead.patch b/SOURCES/0336-test-make-sure-the-strace-process-is-indeed-dead.patch new file mode 100644 index 0000000..55d9b4f --- /dev/null +++ b/SOURCES/0336-test-make-sure-the-strace-process-is-indeed-dead.patch @@ -0,0 +1,53 @@ +From 60813b55f9b5b44b14f38bbc1b8c0d2b30e3f6c7 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 1 Jul 2019 19:53:45 +0200 +Subject: [PATCH 336/341] test: make sure the strace process is indeed dead + +It may take a few moments for the strace process to properly terminate +and write all logs to the backing storage + +(cherry picked from commit 56425e54a2140f47b4560b51c5db08aa2de199a6) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/test.sh | 2 +- + test/TEST-36-NUMAPOLICY/testsuite.sh | 3 +++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh +index a0d8623e8e..f0a321e7a1 100755 +--- a/test/TEST-36-NUMAPOLICY/test.sh ++++ b/test/TEST-36-NUMAPOLICY/test.sh +@@ -16,7 +16,7 @@ test_setup() { + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment +- inst_binary mktemp ++ dracut_install mktemp + + # mask some services that we do not want to run in these tests + ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service +diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh +index a4134bdeca..daed8fcc1c 100755 +--- a/test/TEST-36-NUMAPOLICY/testsuite.sh ++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh +@@ -38,6 +38,8 @@ startStrace() { + + stopStrace() { + kill -s TERM $COPROC_PID ++ # Make sure the strace process is indeed dead ++ while kill -0 $COPROC_PID 2>/dev/null; do sleep 0.1; done + } + + startJournalctl() { +@@ -80,6 +82,7 @@ writeTestUnitNUMAPolicy() { + pid1ReloadWithStrace() { + startStrace + systemctl daemon-reload ++ sleep $sleepAfterStart + stopStrace + } + +-- +2.21.1 + diff --git a/SOURCES/0337-test-skip-the-test-on-systems-without-NUMA-support.patch b/SOURCES/0337-test-skip-the-test-on-systems-without-NUMA-support.patch new file mode 100644 index 0000000..2680709 --- /dev/null +++ b/SOURCES/0337-test-skip-the-test-on-systems-without-NUMA-support.patch @@ -0,0 +1,39 @@ +From ad3e4a0f010c9497b01d89de54213af982f8afd2 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 2 Jul 2019 09:52:45 +0200 +Subject: [PATCH 337/341] test: skip the test on systems without NUMA support + +(cherry picked from commit b030847163e9bd63d3dd6eec6ac7f336411faba6) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/testsuite.sh | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh +index daed8fcc1c..4b715d305a 100755 +--- a/test/TEST-36-NUMAPOLICY/testsuite.sh ++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh +@@ -123,7 +123,18 @@ systemctlCheckNUMAProperties() { + fi + } + +-checkNUMA ++if ! checkNUMA; then ++ echo >&2 "NUMA is not supported on this machine, skipping the test" ++ ++ # FIXME: add some sanity checks to verify systemd behaves correctly with ++ # NUMA disabled together with NUMAPolicy= and NUMAMask= ++ ++ systemd-analyze log-level info ++ echo OK > /testok ++ ++ exit 0 ++fi ++ + writeTestUnit + + # Create systemd config drop-in directory +-- +2.21.1 + diff --git a/SOURCES/0338-test-give-strace-some-time-to-initialize.patch b/SOURCES/0338-test-give-strace-some-time-to-initialize.patch new file mode 100644 index 0000000..5d68666 --- /dev/null +++ b/SOURCES/0338-test-give-strace-some-time-to-initialize.patch @@ -0,0 +1,33 @@ +From 66f6f6304d87b2fe0c4f91373c7d1b836de1b054 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 23 Jul 2019 00:56:04 +0200 +Subject: [PATCH 338/341] test: give strace some time to initialize + +The `coproc` implementation seems to be a little bit different in older +bash versions, so the `strace` is sometimes started AFTER `systemctl +daemon-reload`, which causes unexpected fails. Let's help it a little by +sleeping for a bit. + +(cherry picked from commit c7367d7cfdfdcec98f8659f0ed3f1d7b77123903) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/testsuite.sh | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh +index 4b715d305a..1c8cf7e6b6 100755 +--- a/test/TEST-36-NUMAPOLICY/testsuite.sh ++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh +@@ -34,6 +34,8 @@ journalCursorFile="jounalCursorFile" + + startStrace() { + coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1 ++ # Wait for strace to properly "initialize" ++ sleep $sleepAfterStart + } + + stopStrace() { +-- +2.21.1 + diff --git a/SOURCES/0339-test-add-a-simple-sanity-check-for-systems-without-N.patch b/SOURCES/0339-test-add-a-simple-sanity-check-for-systems-without-N.patch new file mode 100644 index 0000000..10d52aa --- /dev/null +++ b/SOURCES/0339-test-add-a-simple-sanity-check-for-systems-without-N.patch @@ -0,0 +1,394 @@ +From 8239ecf0b4b8bbe5b3c17964d230d13cee4d900a Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 5 Aug 2019 14:38:45 +0200 +Subject: [PATCH 339/341] test: add a simple sanity check for systems without + NUMA support + +(cherry picked from commit 92f8e978923f962a57d744c5f358520ac06f7892) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/testsuite.sh | 350 ++++++++++++++------------- + 1 file changed, 180 insertions(+), 170 deletions(-) + +diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh +index 1c8cf7e6b6..a5ac788178 100755 +--- a/test/TEST-36-NUMAPOLICY/testsuite.sh ++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh +@@ -50,11 +50,12 @@ startJournalctl() { + } + + stopJournalctl() { ++ local unit="${1:-init.scope}" + # Using journalctl --sync should be better than using SIGRTMIN+1, as + # the --sync wait until the synchronization is complete + echo "Force journald to write all queued messages" + journalctl --sync +- journalctl -u init.scope --cursor-file="$journalCursorFile" > "$journalLog" ++ journalctl -u $unit --cursor-file="$journalCursorFile" > "$journalLog" + } + + checkNUMA() { +@@ -125,181 +126,190 @@ systemctlCheckNUMAProperties() { + fi + } + +-if ! checkNUMA; then +- echo >&2 "NUMA is not supported on this machine, skipping the test" +- +- # FIXME: add some sanity checks to verify systemd behaves correctly with +- # NUMA disabled together with NUMAPolicy= and NUMAMask= +- +- systemd-analyze log-level info +- echo OK > /testok +- +- exit 0 +-fi +- + writeTestUnit + + # Create systemd config drop-in directory + confDir="/etc/systemd/system.conf.d/" + mkdir -p "$confDir" + +-echo "PID1 NUMAPolicy support - Default policy w/o mask" +-writePID1NUMAPolicy "default" +-pid1ReloadWithStrace +-# Kernel requires that nodemask argument is set to NULL when setting default policy +-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog +- +-echo "PID1 NUMAPolicy support - Default policy w/ mask" +-writePID1NUMAPolicy "default" "0" +-pid1ReloadWithStrace +-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog +- +-echo "PID1 NUMAPolicy support - Bind policy w/o mask" +-writePID1NUMAPolicy "bind" +-pid1ReloadWithJournal +-grep "Failed to set NUMA memory policy: Invalid argument" $journalLog +- +-echo "PID1 NUMAPolicy support - Bind policy w/ mask" +-writePID1NUMAPolicy "bind" "0" +-pid1ReloadWithStrace +-grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog +- +-echo "PID1 NUMAPolicy support - Interleave policy w/o mask" +-writePID1NUMAPolicy "interleave" +-pid1ReloadWithJournal +-grep "Failed to set NUMA memory policy: Invalid argument" $journalLog +- +-echo "PID1 NUMAPolicy support - Interleave policy w/ mask" +-writePID1NUMAPolicy "interleave" "0" +-pid1ReloadWithStrace +-grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog +- +-echo "PID1 NUMAPolicy support - Preferred policy w/o mask" +-writePID1NUMAPolicy "preferred" +-pid1ReloadWithJournal +-# Preferred policy with empty node mask is actually allowed and should reset allocation policy to default +-! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog +- +-echo "PID1 NUMAPolicy support - Preferred policy w/ mask" +-writePID1NUMAPolicy "preferred" "0" +-pid1ReloadWithStrace +-grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog +- +-echo "PID1 NUMAPolicy support - Local policy w/o mask" +-writePID1NUMAPolicy "local" +-pid1ReloadWithStrace +-# Kernel requires that nodemask argument is set to NULL when setting default policy +-# The unpatched versions of strace don't recognize the MPOL_LOCAL constant and +-# return a numerical constant instead (with a comment): +-# set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0 +-# Let's cover this scenario as well +-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog +- +-echo "PID1 NUMAPolicy support - Local policy w/ mask" +-writePID1NUMAPolicy "local" "0" +-pid1ReloadWithStrace +-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog +- +-echo "Unit file NUMAPolicy support - Default policy w/o mask" +-writeTestUnitNUMAPolicy "default" +-pid1StartUnitWithStrace $testUnit +-systemctlCheckNUMAProperties $testUnit "default" +-pid1StopUnit $testUnit +-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog +- +-echo "Unit file NUMAPolicy support - Default policy w/ mask" +-writeTestUnitNUMAPolicy "default" "0" +-pid1StartUnitWithStrace $testUnit +-systemctlCheckNUMAProperties $testUnit "default" "0" +-pid1StopUnit $testUnit +-# Maks must be ignored +-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog +- +-echo "Unit file NUMAPolicy support - Bind policy w/o mask" +-writeTestUnitNUMAPolicy "bind" +-pid1StartUnitWithJournal $testUnit +-pid1StopUnit $testUnit +-grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog +- +-echo "Unit file NUMAPolicy support - Bind policy w/ mask" +-writeTestUnitNUMAPolicy "bind" "0" +-pid1StartUnitWithStrace $testUnit +-systemctlCheckNUMAProperties $testUnit "bind" "0" +-pid1StopUnit $testUnit +-grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog +- +-echo "Unit file NUMAPolicy support - Interleave policy w/o mask" +-writeTestUnitNUMAPolicy "interleave" +-pid1StartUnitWithStrace $testUnit +-pid1StopUnit $testUnit +-grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog +- +-echo "Unit file NUMAPolicy support - Interleave policy w/ mask" +-writeTestUnitNUMAPolicy "interleave" "0" +-pid1StartUnitWithStrace $testUnit +-systemctlCheckNUMAProperties $testUnit "interleave" "0" +-pid1StopUnit $testUnit +-grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog +- +-echo "Unit file NUMAPolicy support - Preferred policy w/o mask" +-writeTestUnitNUMAPolicy "preferred" +-pid1StartUnitWithJournal $testUnit +-systemctlCheckNUMAProperties $testUnit "preferred" +-pid1StopUnit $testUnit +-! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog +- +-echo "Unit file NUMAPolicy support - Preferred policy w/ mask" +-writeTestUnitNUMAPolicy "preferred" "0" +-pid1StartUnitWithStrace $testUnit +-systemctlCheckNUMAProperties $testUnit "preferred" "0" +-pid1StopUnit $testUnit +-grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog +- +-echo "Unit file NUMAPolicy support - Local policy w/o mask" +-writeTestUnitNUMAPolicy "local" +-pid1StartUnitWithStrace $testUnit +-systemctlCheckNUMAProperties $testUnit "local" +-pid1StopUnit $testUnit +-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog +- +-echo "Unit file NUMAPolicy support - Local policy w/ mask" +-writeTestUnitNUMAPolicy "local" "0" +-pid1StartUnitWithStrace $testUnit +-systemctlCheckNUMAProperties $testUnit "local" "0" +-pid1StopUnit $testUnit +-# Maks must be ignored +-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog +- +-echo "systemd-run NUMAPolicy support" +-runUnit='numa-systemd-run-test.service' +- +-systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000 +-systemctlCheckNUMAProperties $runUnit "default" +-pid1StopUnit $runUnit +- +-systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000 +-systemctlCheckNUMAProperties $runUnit "default" "" +-pid1StopUnit $runUnit +- +-systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000 +-systemctlCheckNUMAProperties $runUnit "bind" "0" +-pid1StopUnit $runUnit +- +-systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000 +-systemctlCheckNUMAProperties $runUnit "interleave" "0" +-pid1StopUnit $runUnit +- +-systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000 +-systemctlCheckNUMAProperties $runUnit "preferred" "0" +-pid1StopUnit $runUnit +- +-systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000 +-systemctlCheckNUMAProperties $runUnit "local" +-pid1StopUnit $runUnit +- +-systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000 +-systemctlCheckNUMAProperties $runUnit "local" "" +-pid1StopUnit $runUnit ++if ! checkNUMA; then ++ echo >&2 "NUMA is not supported on this machine, switching to a simple sanity check" ++ ++ echo "PID1 NUMAPolicy=default && NUMAMask=0 check without NUMA support" ++ writePID1NUMAPolicy "default" "0" ++ startJournalctl ++ systemctl daemon-reload ++ stopJournalctl ++ grep "NUMA support not available, ignoring" "$journalLog" ++ ++ echo "systemd-run NUMAPolicy=default && NUMAMask=0 check without NUMA support" ++ runUnit='numa-systemd-run-test.service' ++ startJournalctl ++ systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000 ++ sleep $sleepAfterStart ++ pid1StopUnit $runUnit ++ stopJournalctl $runUnit ++ grep "NUMA support not available, ignoring" "$journalLog" ++ ++else ++ echo "PID1 NUMAPolicy support - Default policy w/o mask" ++ writePID1NUMAPolicy "default" ++ pid1ReloadWithStrace ++ # Kernel requires that nodemask argument is set to NULL when setting default policy ++ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++ echo "PID1 NUMAPolicy support - Default policy w/ mask" ++ writePID1NUMAPolicy "default" "0" ++ pid1ReloadWithStrace ++ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++ echo "PID1 NUMAPolicy support - Bind policy w/o mask" ++ writePID1NUMAPolicy "bind" ++ pid1ReloadWithJournal ++ grep "Failed to set NUMA memory policy: Invalid argument" $journalLog ++ ++ echo "PID1 NUMAPolicy support - Bind policy w/ mask" ++ writePID1NUMAPolicy "bind" "0" ++ pid1ReloadWithStrace ++ grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog ++ ++ echo "PID1 NUMAPolicy support - Interleave policy w/o mask" ++ writePID1NUMAPolicy "interleave" ++ pid1ReloadWithJournal ++ grep "Failed to set NUMA memory policy: Invalid argument" $journalLog ++ ++ echo "PID1 NUMAPolicy support - Interleave policy w/ mask" ++ writePID1NUMAPolicy "interleave" "0" ++ pid1ReloadWithStrace ++ grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog ++ ++ echo "PID1 NUMAPolicy support - Preferred policy w/o mask" ++ writePID1NUMAPolicy "preferred" ++ pid1ReloadWithJournal ++ # Preferred policy with empty node mask is actually allowed and should reset allocation policy to default ++ ! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog ++ ++ echo "PID1 NUMAPolicy support - Preferred policy w/ mask" ++ writePID1NUMAPolicy "preferred" "0" ++ pid1ReloadWithStrace ++ grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog ++ ++ echo "PID1 NUMAPolicy support - Local policy w/o mask" ++ writePID1NUMAPolicy "local" ++ pid1ReloadWithStrace ++ # Kernel requires that nodemask argument is set to NULL when setting default policy ++ # The unpatched versions of strace don't recognize the MPOL_LOCAL constant and ++ # return a numerical constant instead (with a comment): ++ # set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0 ++ # Let's cover this scenario as well ++ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog ++ ++ echo "PID1 NUMAPolicy support - Local policy w/ mask" ++ writePID1NUMAPolicy "local" "0" ++ pid1ReloadWithStrace ++ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog ++ ++ echo "Unit file NUMAPolicy support - Default policy w/o mask" ++ writeTestUnitNUMAPolicy "default" ++ pid1StartUnitWithStrace $testUnit ++ systemctlCheckNUMAProperties $testUnit "default" ++ pid1StopUnit $testUnit ++ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++ echo "Unit file NUMAPolicy support - Default policy w/ mask" ++ writeTestUnitNUMAPolicy "default" "0" ++ pid1StartUnitWithStrace $testUnit ++ systemctlCheckNUMAProperties $testUnit "default" "0" ++ pid1StopUnit $testUnit ++ # Maks must be ignored ++ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog ++ ++ echo "Unit file NUMAPolicy support - Bind policy w/o mask" ++ writeTestUnitNUMAPolicy "bind" ++ pid1StartUnitWithJournal $testUnit ++ pid1StopUnit $testUnit ++ grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog ++ ++ echo "Unit file NUMAPolicy support - Bind policy w/ mask" ++ writeTestUnitNUMAPolicy "bind" "0" ++ pid1StartUnitWithStrace $testUnit ++ systemctlCheckNUMAProperties $testUnit "bind" "0" ++ pid1StopUnit $testUnit ++ grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog ++ ++ echo "Unit file NUMAPolicy support - Interleave policy w/o mask" ++ writeTestUnitNUMAPolicy "interleave" ++ pid1StartUnitWithStrace $testUnit ++ pid1StopUnit $testUnit ++ grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog ++ ++ echo "Unit file NUMAPolicy support - Interleave policy w/ mask" ++ writeTestUnitNUMAPolicy "interleave" "0" ++ pid1StartUnitWithStrace $testUnit ++ systemctlCheckNUMAProperties $testUnit "interleave" "0" ++ pid1StopUnit $testUnit ++ grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog ++ ++ echo "Unit file NUMAPolicy support - Preferred policy w/o mask" ++ writeTestUnitNUMAPolicy "preferred" ++ pid1StartUnitWithJournal $testUnit ++ systemctlCheckNUMAProperties $testUnit "preferred" ++ pid1StopUnit $testUnit ++ ! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog ++ ++ echo "Unit file NUMAPolicy support - Preferred policy w/ mask" ++ writeTestUnitNUMAPolicy "preferred" "0" ++ pid1StartUnitWithStrace $testUnit ++ systemctlCheckNUMAProperties $testUnit "preferred" "0" ++ pid1StopUnit $testUnit ++ grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog ++ ++ echo "Unit file NUMAPolicy support - Local policy w/o mask" ++ writeTestUnitNUMAPolicy "local" ++ pid1StartUnitWithStrace $testUnit ++ systemctlCheckNUMAProperties $testUnit "local" ++ pid1StopUnit $testUnit ++ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog ++ ++ echo "Unit file NUMAPolicy support - Local policy w/ mask" ++ writeTestUnitNUMAPolicy "local" "0" ++ pid1StartUnitWithStrace $testUnit ++ systemctlCheckNUMAProperties $testUnit "local" "0" ++ pid1StopUnit $testUnit ++ # Maks must be ignored ++ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog ++ ++ echo "systemd-run NUMAPolicy support" ++ runUnit='numa-systemd-run-test.service' ++ ++ systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000 ++ systemctlCheckNUMAProperties $runUnit "default" ++ pid1StopUnit $runUnit ++ ++ systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000 ++ systemctlCheckNUMAProperties $runUnit "default" "" ++ pid1StopUnit $runUnit ++ ++ systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000 ++ systemctlCheckNUMAProperties $runUnit "bind" "0" ++ pid1StopUnit $runUnit ++ ++ systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000 ++ systemctlCheckNUMAProperties $runUnit "interleave" "0" ++ pid1StopUnit $runUnit ++ ++ systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000 ++ systemctlCheckNUMAProperties $runUnit "preferred" "0" ++ pid1StopUnit $runUnit ++ ++ systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000 ++ systemctlCheckNUMAProperties $runUnit "local" ++ pid1StopUnit $runUnit ++ ++ systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000 ++ systemctlCheckNUMAProperties $runUnit "local" "" ++ pid1StopUnit $runUnit ++fi + + # Cleanup + rm -rf $testDir +-- +2.21.1 + diff --git a/SOURCES/0340-test-drop-the-missed-exit-1-expression.patch b/SOURCES/0340-test-drop-the-missed-exit-1-expression.patch new file mode 100644 index 0000000..d0df520 --- /dev/null +++ b/SOURCES/0340-test-drop-the-missed-exit-1-expression.patch @@ -0,0 +1,38 @@ +From 772f08f8255d7ab921c344ab4243249cbd1c37fc Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Sat, 10 Aug 2019 16:05:07 +0200 +Subject: [PATCH 340/341] test: drop the missed || exit 1 expression + +...as we've already done in the rest of the testsuite, see +cc469c3dfc398210f38f819d367e68646c71d8da + +(cherry picked from commit 67c434b03f8a24f5350f017dfb4b2464406046db) + +Related: #1808940 +--- + test/TEST-36-NUMAPOLICY/test.sh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh +index f0a321e7a1..3b3b120423 100755 +--- a/test/TEST-36-NUMAPOLICY/test.sh ++++ b/test/TEST-36-NUMAPOLICY/test.sh +@@ -1,5 +1,6 @@ + #!/bin/bash + set -e ++ + TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options" + TEST_NO_NSPAWN=1 + QEMU_OPTIONS="-numa node,nodeid=0" +@@ -41,7 +42,7 @@ EOF + cp testsuite.sh $initdir/ + + setup_testsuite +- ) || return 1 ++ ) + setup_nspawn_root + + ddebug "umount $TESTDIR/root" +-- +2.21.1 + diff --git a/SOURCES/0341-test-replace-cursor-file-with-a-plain-cursor.patch b/SOURCES/0341-test-replace-cursor-file-with-a-plain-cursor.patch new file mode 100644 index 0000000..f3b1f25 --- /dev/null +++ b/SOURCES/0341-test-replace-cursor-file-with-a-plain-cursor.patch @@ -0,0 +1,62 @@ +From 0bef8805c81eecfe3960bf00b6022837e4979198 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 3 Mar 2020 15:54:29 +0100 +Subject: [PATCH 341/341] test: replace cursor file with a plain cursor + +systemd in RHEL 8 doesn't support the --cursor-file option, so let's +fall back to a plain cursor string + +Related: #1808940 +rhel-only +--- + test/TEST-36-NUMAPOLICY/test.sh | 2 +- + test/TEST-36-NUMAPOLICY/testsuite.sh | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh +index 3b3b120423..7cc909765b 100755 +--- a/test/TEST-36-NUMAPOLICY/test.sh ++++ b/test/TEST-36-NUMAPOLICY/test.sh +@@ -17,7 +17,7 @@ test_setup() { + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment +- dracut_install mktemp ++ dracut_install mktemp awk + + # mask some services that we do not want to run in these tests + ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service +diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh +index a5ac788178..bffac4ffe6 100755 +--- a/test/TEST-36-NUMAPOLICY/testsuite.sh ++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh +@@ -30,7 +30,7 @@ journalSleep=5 + sleepAfterStart=1 + + # Journal cursor for easier navigation +-journalCursorFile="jounalCursorFile" ++journalCursor="" + + startStrace() { + coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1 +@@ -46,7 +46,7 @@ stopStrace() { + + startJournalctl() { + # Save journal's cursor for later navigation +- journalctl --no-pager --cursor-file="$journalCursorFile" -n0 -ocat ++ journalCursor="$(journalctl --no-pager --show-cursor -n0 -ocat | awk '{print $3}')" + } + + stopJournalctl() { +@@ -55,7 +55,7 @@ stopJournalctl() { + # the --sync wait until the synchronization is complete + echo "Force journald to write all queued messages" + journalctl --sync +- journalctl -u $unit --cursor-file="$journalCursorFile" > "$journalLog" ++ journalctl -u $unit --after-cursor="$journalCursor" > "$journalLog" + } + + checkNUMA() { +-- +2.21.1 + diff --git a/SOURCES/0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch b/SOURCES/0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch new file mode 100644 index 0000000..4fee429 --- /dev/null +++ b/SOURCES/0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch @@ -0,0 +1,32 @@ +From ed282d8d84fa32aaef21994d92d1d3dbfa281094 Mon Sep 17 00:00:00 2001 +From: Ryan Gonzalez +Date: Fri, 22 Feb 2019 23:45:03 -0600 +Subject: [PATCH] cryptsetup: Treat key file errors as a failed password + attempt + +6f177c7dc092eb68762b4533d41b14244adb2a73 caused key file errors to immediately fail, which would make it hard to correct an issue due to e.g. a crypttab typo or a damaged key file. + +Closes #11723. + +(cherry picked from commit c20db3887569e0c0d9c0e2845c5286e7edf0133a) + +Related: #1763155 +--- + src/cryptsetup/cryptsetup.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 33c215eaa1..11162eb722 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -558,6 +558,10 @@ static int attach_luks_or_plain(struct crypt_device *cd, + log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file); + return -EAGAIN; /* Log actual error, but return EAGAIN */ + } ++ if (r == -EINVAL) { ++ log_error_errno(r, "Failed to activate with key file '%s'. (Key file missing?)", key_file); ++ return -EAGAIN; /* Log actual error, but return EAGAIN */ ++ } + if (r < 0) + return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file); + } else { diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index 9f79b7c..1c03e7a 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -13,7 +13,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 18%{?dist}.5 +Release: 29%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -265,32 +265,133 @@ Patch0212: 0212-mount-simplify-proc-self-mountinfo-handler.patch Patch0213: 0213-mount-rescan-proc-self-mountinfo-before-processing-w.patch Patch0214: 0214-swap-scan-proc-swaps-before-processing-waitid-result.patch Patch0215: 0215-analyze-security-fix-potential-division-by-zero.patch -Patch0216: 0216-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch -Patch0217: 0217-shared-but-util-drop-trusted-annotation-from-bus_ope.patch -Patch0218: 0218-sd-bus-adjust-indentation-of-comments.patch -Patch0219: 0219-resolved-do-not-run-loop-twice.patch -Patch0220: 0220-resolved-allow-access-to-Set-Link-and-Revert-methods.patch -Patch0221: 0221-resolved-query-polkit-only-after-parsing-the-data.patch -Patch0222: 0222-ask-password-prevent-buffer-overrow-when-reading-fro.patch -Patch0223: 0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch -Patch0224: 0224-syslog-fix-segfault-in-syslog_parse_priority.patch -Patch0225: 0225-journald-fixed-assertion-failure-when-system-journal.patch -Patch0226: 0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch -Patch0227: 0227-test-mask-several-unnecessary-services.patch -Patch0228: 0228-test-bump-the-second-partition-s-size-to-50M.patch -Patch0229: 0229-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch -Patch0230: 0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch -Patch0231: 0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch -Patch0232: 0232-sd-bus-drop-two-inappropriate-empty-lines.patch -Patch0233: 0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch -Patch0234: 0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch -Patch0235: 0235-bus-message-introduce-two-kinds-of-references-to-bus.patch -Patch0236: 0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch -Patch0237: 0237-sd-event-add-sd_event_source_disable_unref-helper.patch -Patch0238: 0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch -Patch0239: 0239-sd-bus-use-queue-message-references-for-managing-r-w.patch -Patch0240: 0240-journal-do-not-trigger-assertion-when-journal_file_c.patch -Patch0241: 0241-journal-use-cleanup-attribute-at-one-more-place.patch +Patch0216: 0216-core-never-propagate-reload-failure-to-service-resul.patch +Patch0217: 0217-man-document-systemd-analyze-security.patch +Patch0218: 0218-man-reorder-and-add-examples-to-systemd-analyze-1.patch +Patch0219: 0219-travis-move-to-CentOS-8-docker-images.patch +Patch0220: 0220-travis-drop-SCL-remains.patch +Patch0221: 0221-syslog-fix-segfault-in-syslog_parse_priority.patch +Patch0222: 0222-sd-bus-make-strict-asan-shut-up.patch +Patch0223: 0223-travis-don-t-run-slow-tests-under-ASan-UBSan.patch +Patch0224: 0224-kernel-install-do-not-require-non-empty-kernel-cmdli.patch +Patch0225: 0225-ask-password-prevent-buffer-overrow-when-reading-fro.patch +Patch0226: 0226-core-try-to-reopen-dev-kmsg-again-right-after-mounti.patch +Patch0227: 0227-buildsys-don-t-garbage-collect-sections-while-linkin.patch +Patch0228: 0228-udev-introduce-CONST-key-name.patch +Patch0229: 0229-Call-getgroups-to-know-size-of-supplementary-groups-.patch +Patch0230: 0230-Consider-smb3-as-remote-filesystem.patch +Patch0231: 0231-process-util-introduce-pid_is_my_child-helper.patch +Patch0232: 0232-core-reduce-the-number-of-stalled-PIDs-from-the-watc.patch +Patch0233: 0233-core-only-watch-processes-when-it-s-really-necessary.patch +Patch0234: 0234-core-implement-per-unit-journal-rate-limiting.patch +Patch0235: 0235-path-stop-watching-path-specs-once-we-triggered-the-.patch +Patch0236: 0236-journald-fixed-assertion-failure-when-system-journal.patch +Patch0237: 0237-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch +Patch0238: 0238-test-mask-several-unnecessary-services.patch +Patch0239: 0239-test-bump-the-second-partition-s-size-to-50M.patch +Patch0240: 0240-shared-sleep-config-exclude-zram-devices-from-hibern.patch +Patch0241: 0241-selinux-don-t-log-SELINUX_INFO-and-SELINUX_WARNING-m.patch +Patch0242: 0242-sd-device-introduce-log_device_-macros.patch +Patch0243: 0243-udev-Add-id-program-and-rule-for-FIDO-security-token.patch +Patch0244: 0244-shared-but-util-drop-trusted-annotation-from-bus_ope.patch +Patch0245: 0245-sd-bus-adjust-indentation-of-comments.patch +Patch0246: 0246-resolved-do-not-run-loop-twice.patch +Patch0247: 0247-resolved-allow-access-to-Set-Link-and-Revert-methods.patch +Patch0248: 0248-resolved-query-polkit-only-after-parsing-the-data.patch +Patch0249: 0249-journal-rely-on-_cleanup_free_-to-free-a-temporary-s.patch +Patch0250: 0250-basic-user-util-allow-dots-in-user-names.patch +Patch0251: 0251-sd-bus-bump-message-queue-size-again.patch +Patch0252: 0252-tests-put-fuzz_journald_processing_function-in-a-.c-.patch +Patch0253: 0253-tests-add-a-fuzzer-for-dev_kmsg_record.patch +Patch0254: 0254-basic-remove-an-assertion-from-cunescape_one.patch +Patch0255: 0255-journal-fix-an-off-by-one-error-in-dev_kmsg_record.patch +Patch0256: 0256-tests-add-a-reproducer-for-a-memory-leak-fixed-in-30.patch +Patch0257: 0257-tests-add-a-reproducer-for-a-heap-buffer-overflow-fi.patch +Patch0258: 0258-test-initialize-syslog_fd-in-fuzz-journald-kmsg-too.patch +Patch0259: 0259-tests-add-a-fuzzer-for-process_audit_string.patch +Patch0260: 0260-journald-check-whether-sscanf-has-changed-the-value-.patch +Patch0261: 0261-tests-introduce-dummy_server_init-and-use-it-in-all-.patch +Patch0262: 0262-tests-add-a-fuzzer-for-journald-streams.patch +Patch0263: 0263-tests-add-a-fuzzer-for-server_process_native_file.patch +Patch0264: 0264-fuzz-journal-stream-avoid-assertion-failure-on-sampl.patch +Patch0265: 0265-journald-take-leading-spaces-into-account-in-syslog_.patch +Patch0266: 0266-Add-a-warning-about-the-difference-in-permissions-be.patch +Patch0267: 0267-execute-remove-one-redundant-comparison-check.patch +Patch0268: 0268-core-change-ownership-mode-of-the-execution-director.patch +Patch0269: 0269-core-dbus-execute-remove-unnecessary-initialization.patch +Patch0270: 0270-shared-cpu-set-util-move-the-part-to-print-cpu-set-i.patch +Patch0271: 0271-shared-cpu-set-util-remove-now-unused-CPU_SIZE_TO_NU.patch +Patch0272: 0272-Rework-cpu-affinity-parsing.patch +Patch0273: 0273-Move-cpus_in_affinity_mask-to-cpu-set-util.-ch.patch +Patch0274: 0274-test-cpu-set-util-add-simple-test-for-cpus_in_affini.patch +Patch0275: 0275-test-cpu-set-util-add-a-smoke-test-for-test_parse_cp.patch +Patch0276: 0276-pid1-parse-CPUAffinity-in-incremental-fashion.patch +Patch0277: 0277-pid1-don-t-reset-setting-from-proc-cmdline-upon-rest.patch +Patch0278: 0278-pid1-when-reloading-configuration-forget-old-setting.patch +Patch0279: 0279-test-execute-use-CPUSet-too.patch +Patch0280: 0280-shared-cpu-set-util-drop-now-unused-cleanup-function.patch +Patch0281: 0281-shared-cpu-set-util-make-transfer-of-cpu_set_t-over-.patch +Patch0282: 0282-test-cpu-set-util-add-test-for-dbus-conversions.patch +Patch0283: 0283-shared-cpu-set-util-introduce-cpu_set_to_range.patch +Patch0284: 0284-systemctl-present-CPUAffinity-mask-as-a-list-of-CPU-.patch +Patch0285: 0285-shared-cpu-set-util-only-force-range-printing-one-ti.patch +Patch0286: 0286-execute-dump-CPUAffinity-as-a-range-string-instead-o.patch +Patch0287: 0287-cpu-set-util-use-d-d-format-in-cpu_set_to_range_stri.patch +Patch0288: 0288-core-introduce-NUMAPolicy-and-NUMAMask-options.patch +Patch0289: 0289-core-disable-CPUAccounting-by-default.patch +Patch0290: 0290-set-kptr_restrict-1.patch +Patch0291: 0291-cryptsetup-reduce-the-chance-that-we-will-be-OOM-kil.patch +Patch0292: 0292-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch +Patch0293: 0293-debug-generator-enable-custom-systemd.debug_shell-tt.patch +Patch0294: 0294-test-cpu-set-util-fix-comparison-for-allocation-size.patch +Patch0295: 0295-test-cpu-set-util-fix-allocation-size-check-on-i386.patch +Patch0296: 0296-catalog-fix-name-of-variable.patch +Patch0297: 0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch +Patch0298: 0298-cryptsetup-add-documentation-for-keyfile-timeout.patch +Patch0299: 0299-cryptsetup-use-unabbrieviated-variable-names.patch +Patch0300: 0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch +Patch0301: 0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch +Patch0302: 0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch +Patch0303: 0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch +Patch0304: 0304-cryptsetup-downgrade-a-log-message-we-ignore.patch +Patch0305: 0305-cryptsetup-rework-how-we-log-about-activation-failur.patch +Patch0306: 0306-rules-reintroduce-60-alias-kmsg.rules.patch +Patch0307: 0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch +Patch0308: 0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch +Patch0309: 0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch +Patch0310: 0310-sd-bus-drop-two-inappropriate-empty-lines.patch +Patch0311: 0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch +Patch0312: 0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch +Patch0313: 0313-bus-message-introduce-two-kinds-of-references-to-bus.patch +Patch0314: 0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch +Patch0315: 0315-sd-event-add-sd_event_source_disable_unref-helper.patch +Patch0316: 0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch +Patch0317: 0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch +Patch0318: 0318-journal-do-not-trigger-assertion-when-journal_file_c.patch +Patch0319: 0319-journal-use-cleanup-attribute-at-one-more-place.patch +Patch0320: 0320-sd-bus-use-queue-message-references-for-managing-r-w.patch +Patch0321: 0321-pid1-make-sure-to-restore-correct-default-values-for.patch +Patch0322: 0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch +Patch0323: 0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch +Patch0324: 0324-test-add-test-case-for-restrict_suid_sgid.patch +Patch0325: 0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch +Patch0326: 0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch +Patch0327: 0327-man-document-the-new-RestrictSUIDSGID-setting.patch +Patch0328: 0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch +Patch0329: 0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch +Patch0330: 0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch +Patch0331: 0331-pid1-fix-DefaultTasksMax-initialization.patch +Patch0332: 0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch +Patch0333: 0333-test-introduce-TEST-36-NUMAPOLICY.patch +Patch0334: 0334-test-replace-tail-f-with-journal-cursor-which-should.patch +Patch0335: 0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch +Patch0336: 0336-test-make-sure-the-strace-process-is-indeed-dead.patch +Patch0337: 0337-test-skip-the-test-on-systems-without-NUMA-support.patch +Patch0338: 0338-test-give-strace-some-time-to-initialize.patch +Patch0339: 0339-test-add-a-simple-sanity-check-for-systems-without-N.patch +Patch0340: 0340-test-drop-the-missed-exit-1-expression.patch +Patch0341: 0341-test-replace-cursor-file-with-a-plain-cursor.patch +Patch0342: 0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch %ifarch %{ix86} x86_64 aarch64 @@ -358,6 +459,7 @@ Provides: /bin/systemctl Provides: /sbin/shutdown Provides: syslog Provides: systemd-units = %{version}-%{release} +Provides: systemd-rpm-macros = %{version}-%{release} Obsoletes: system-setup-keyboard < 0.9 Provides: system-setup-keyboard = 0.9 # systemd-sysv-convert was removed in f20: https://fedorahosted.org/fpc/ticket/308 @@ -552,6 +654,10 @@ CONFIGURE_OPTS=( -Ddefault-hierarchy=legacy ) +# Don't ship /var/log/README. The relationship between journal and syslog should be documented +# in the official documentation. +sed -ie "/subdir('doc\/var-log')/d" meson.build + %meson "${CONFIGURE_OPTS[@]}" %meson_build @@ -910,36 +1016,157 @@ fi %files tests -f .file-list-tests %changelog -* Thu Feb 27 2020 systemd maintenance team - 239-18.5 -- journal: do not trigger assertion when journal_file_close() get NULL (#1807350) -- journal: use cleanup attribute at one more place (#1807350) - -* Thu Feb 13 2020 systemd maintenance team - 239-18.4 +* Mon Mar 23 2020 systemd maintenance team - 239-29 +- cryptsetup: Treat key file errors as a failed password attempt (#1763155) + +* Wed Mar 11 2020 systemd maintenance team - 239-28 +- pid1: fix DefaultTasksMax initialization (#1809037) +- cgroup: make sure that cpuset is supported on cgroup v2 and disabled with v1 (#1808940) +- test: introduce TEST-36-NUMAPOLICY (#1808940) +- test: replace `tail -f` with journal cursor which should be more reliable (#1808940) +- test: support MPOL_LOCAL matching in unpatched strace versions (#1808940) +- test: make sure the strace process is indeed dead (#1808940) +- test: skip the test on systems without NUMA support (#1808940) +- test: give strace some time to initialize (#1808940) +- test: add a simple sanity check for systems without NUMA support (#1808940) +- test: drop the missed || exit 1 expression (#1808940) +- test: replace cursor file with a plain cursor (#1808940) + +* Fri Feb 21 2020 systemd maintenance team - 239-27 +- cgroup: introduce support for cgroup v2 CPUSET controller (#1724617) + +* Wed Feb 19 2020 systemd maintenance team - 239-26 +- seccomp: introduce seccomp_restrict_suid_sgid() for blocking chmod() for suid/sgid files (#1687512) +- test: add test case for restrict_suid_sgid() (#1687512) +- core: expose SUID/SGID restriction as new unit setting RestrictSUIDSGID= (#1687512) +- analyze: check for RestrictSUIDSGID= in "systemd-analyze security" (#1687512) +- man: document the new RestrictSUIDSGID= setting (#1687512) +- units: turn on RestrictSUIDSGID= in most of our long-running daemons (#1687512) +- core: imply NNP and SUID/SGID restriction for DynamicUser=yes service (#1687512) + +* Mon Feb 17 2020 systemd maintenance team - 239-25 - sd-bus: use "queue" message references for managing r/w message queues in connection objects (CVE-2020-1712) - -* Mon Feb 03 2020 systemd maintenance team - 239-18.3 -- core, job: fix breakage of ordering dependencies by systemctl reload command (#1781712) -- syslog: fix segfault in syslog_parse_priority() (#1781712) -- journald: fixed assertion failure when system journal rotation fails (#9893) (#1781712) -- test: use PBKDF2 instead of Argon2 in cryptsetup... (#1781712) -- test: mask several unnecessary services (#1781712) -- test: bump the second partition's size to 50M (#1781712) -- sd-bus: make rqueue/wqueue sizes of type size_t (#20201712) -- sd-bus: reorder bus ref and bus message ref handling (#20201712) -- sd-bus: make sure dispatch_rqueue() initializes return parameter on all types of success (#20201712) -- sd-bus: drop two inappropriate empty lines (#20201712) -- sd-bus: initialize mutex after we allocated the wqueue (#20201712) -- sd-bus: always go through sd_bus_unref() to free messages (#20201712) -- bus-message: introduce two kinds of references to bus messages (#20201712) -- sd-bus: introduce API for re-enqueuing incoming messages (#20201712) -- sd-event: add sd_event_source_disable_unref() helper (#20201712) -- polkit: when authorizing via PK let's re-resolve callback/userdata instead of caching it (#20201712) - -* Fri Nov 29 2019 systemd maintenance team - 239-18.2 -- ask-password: prevent buffer overrow when reading from keyring (#1777037) - -* Tue Nov 05 2019 Lukas Nykryn - 239-18.1 -- journal: rely on _cleanup_free_ to free a temporary string used in client_context_read_cgroup (#1767716) +- pid1: make sure to restore correct default values for some rlimits (#1789930) +- main: introduce a define HIGH_RLIMIT_MEMLOCK similar to HIGH_RLIMIT_NOFILE (#1789930) + +* Thu Feb 13 2020 systemd maintenance team - 239-24 +- rules: reintroduce 60-alias-kmsg.rules (#1739353) +- sd-bus: make rqueue/wqueue sizes of type size_t (CVE-2020-1712) +- sd-bus: reorder bus ref and bus message ref handling (CVE-2020-1712) +- sd-bus: make sure dispatch_rqueue() initializes return parameter on all types of success (CVE-2020-1712) +- sd-bus: drop two inappropriate empty lines (CVE-2020-1712) +- sd-bus: initialize mutex after we allocated the wqueue (CVE-2020-1712) +- sd-bus: always go through sd_bus_unref() to free messages (CVE-2020-1712) +- bus-message: introduce two kinds of references to bus messages (CVE-2020-1712) +- sd-bus: introduce API for re-enqueuing incoming messages (CVE-2020-1712) +- sd-event: add sd_event_source_disable_unref() helper (CVE-2020-1712) +- polkit: when authorizing via PK let's re-resolve callback/userdata instead of caching it (CVE-2020-1712) +- sysctl: let's by default increase the numeric PID range from 2^16 to 2^22 (#1744214) +- journal: do not trigger assertion when journal_file_close() get NULL (#1788085) +- journal: use cleanup attribute at one more place (#1788085) + +* Mon Jan 13 2020 systemd maintenance team - 239-23 +- catalog: fix name of variable (#1677768) +- cryptsetup: add keyfile-timeout to allow a keydev timeout and allow to fallback to a password if it fails. (#1763155) +- cryptsetup: add documentation for keyfile-timeout (#1763155) +- cryptsetup: use unabbrieviated variable names (#1763155) +- cryptsetup: don't assert on variable which is optional (#1763155) +- cryptsetup-generator: guess whether the keyfile argument is two items or one (#1763155) +- crypt-util: Translate libcryptsetup log level instead of using log_debug() (#1776408) +- cryptsetup: add some commenting about EAGAIN generation (#1776408) +- cryptsetup: downgrade a log message we ignore (#1776408) +- cryptsetup: rework how we log about activation failures (#1776408) + +* Tue Dec 17 2019 systemd maintenance team - 239-22 +- spec: don't ship /var/log/README +- spec: provide systemd-rpm-macros + +* Mon Dec 09 2019 systemd maintenance team - 239-21 +- test-cpu-set-util: fix comparison for allocation size (#1734787) +- test-cpu-set-util: fix allocation size check on i386 (#1734787) + +* Mon Dec 09 2019 systemd maintenance team - 239-20 +- journal: rely on _cleanup_free_ to free a temporary string used in client_context_read_cgroup (#1764560) +- basic/user-util: allow dots in user names (#1717603) +- sd-bus: bump message queue size again (#1770189) +- tests: put fuzz_journald_processing_function in a .c file (#1764560) +- tests: add a fuzzer for dev_kmsg_record (#1764560) +- basic: remove an assertion from cunescape_one (#1764560) +- journal: fix an off-by-one error in dev_kmsg_record (#1764560) +- tests: add a reproducer for a memory leak fixed in 30eddcd51b8a472e05d3b8d1 in August (#1764560) +- tests: add a reproducer for a heap-buffer-overflow fixed in 937b1171378bc1000a (#1764560) +- test: initialize syslog_fd in fuzz-journald-kmsg too (#1764560) +- tests: add a fuzzer for process_audit_string (#1764560) +- journald: check whether sscanf has changed the value corresponding to %n (#1764560) +- tests: introduce dummy_server_init and use it in all journald fuzzers (#1764560) +- tests: add a fuzzer for journald streams (#1764560) +- tests: add a fuzzer for server_process_native_file (#1764560) +- fuzz-journal-stream: avoid assertion failure on samples which don't fit in pipe (#1764560) +- journald: take leading spaces into account in syslog_parse_identifier (#1764560) +- Add a warning about the difference in permissions between existing directories and unit settings. (#1778384) +- execute: remove one redundant comparison check (#1778384) +- core: change ownership/mode of the execution directories also for static users (#1778384) +- core/dbus-execute: remove unnecessary initialization (#1734787) +- shared/cpu-set-util: move the part to print cpu-set into a separate function (#1734787) +- shared/cpu-set-util: remove now-unused CPU_SIZE_TO_NUM() (#1734787) +- Rework cpu affinity parsing (#1734787) +- Move cpus_in_affinity_mask() to cpu-set-util.[ch] (#1734787) +- test-cpu-set-util: add simple test for cpus_in_affinity_mask() (#1734787) +- test-cpu-set-util: add a smoke test for test_parse_cpu_set_extend() (#1734787) +- pid1: parse CPUAffinity= in incremental fashion (#1734787) +- pid1: don't reset setting from /proc/cmdline upon restart (#1734787) +- pid1: when reloading configuration, forget old settings (#1734787) +- test-execute: use CPUSet too (#1734787) +- shared/cpu-set-util: drop now-unused cleanup function (#1734787) +- shared/cpu-set-util: make transfer of cpu_set_t over bus endian safe (#1734787) +- test-cpu-set-util: add test for dbus conversions (#1734787) +- shared/cpu-set-util: introduce cpu_set_to_range() (#1734787) +- systemctl: present CPUAffinity mask as a list of CPU index ranges (#1734787) +- shared/cpu-set-util: only force range printing one time (#1734787) +- execute: dump CPUAffinity as a range string instead of a list of CPUs (#1734787) +- cpu-set-util: use %d-%d format in cpu_set_to_range_string() only for actual ranges (#1734787) +- core: introduce NUMAPolicy and NUMAMask options (#1734787) +- core: disable CPUAccounting by default (#1734787) +- set kptr_restrict=1 (#1689346) +- cryptsetup: reduce the chance that we will be OOM killed (#1696602) +- core, job: fix breakage of ordering dependencies by systemctl reload command (#1766417) +- debug-generator: enable custom systemd.debug_shell tty (#1723722) + +* Thu Oct 24 2019 Lukas Nykryn - 239-19 +- core: never propagate reload failure to service result (#1735787) +- man: document systemd-analyze security (#1750343) +- man: reorder and add examples to systemd-analyze(1) (#1750343) +- travis: move to CentOS 8 docker images (#1761519) +- travis: drop SCL remains (#1761519) +- syslog: fix segfault in syslog_parse_priority() (#1761519) +- sd-bus: make strict asan shut up (#1761519) +- travis: don't run slow tests under ASan/UBSan (#1761519) +- kernel-install: do not require non-empty kernel cmdline (#1701454) +- ask-password: prevent buffer overrow when reading from keyring (#1752050) +- core: try to reopen /dev/kmsg again right after mounting /dev (#1749212) +- buildsys: don't garbage collect sections while linking (#1748258) +- udev: introduce CONST key name (#1762679) +- Call getgroups() to know size of supplementary groups array to allocate (#1743230256 KB +#1743235) +- Consider smb3 as remote filesystem (#1757257) +- process-util: introduce pid_is_my_child() helper (#1744972) +- core: reduce the number of stalled PIDs from the watched processes list when possible (#1744972) +- core: only watch processes when it's really necessary (#1744972) +- core: implement per unit journal rate limiting (#1719577) +- path: stop watching path specs once we triggered the target unit (#1763161) +- journald: fixed assertion failure when system journal rotation fails (#9893) (#1763619) +- test: use PBKDF2 instead of Argon2 in cryptsetup... (#1761519) +- test: mask several unnecessary services (#1761519) +- test: bump the second partition's size to 50M (#1761519) +- shared/sleep-config: exclude zram devices from hibernation candidates (#1763617) +- selinux: don't log SELINUX_INFO and SELINUX_WARNING messages to audit (#1763612) +- sd-device: introduce log_device_*() macros (#1753369) +- udev: Add id program and rule for FIDO security tokens (#1753369) +- shared/but-util: drop trusted annotation from bus_open_system_watch_bind_with_description() (#1746857) +- sd-bus: adjust indentation of comments (#1746857) +- resolved: do not run loop twice (#1746857) +- resolved: allow access to Set*Link and Revert methods through polkit (#1746857) +- resolved: query polkit only after parsing the data (#1746857) * Fri Aug 30 2019 Lukas Nykryn - 239-18 - shared/but-util: drop trusted annotation from bus_open_system_watch_bind_with_description() (#1746857)