import systemd-239-74.el8_8
This commit is contained in:
		
							parent
							
								
									d8ae20ffcd
								
							
						
					
					
						commit
						020374c810
					
				| @ -0,0 +1,59 @@ | |||||||
|  | From 5f69ba3919d32ed93c68bb6b8b70a516f2bb56a8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Macku <jamacku@redhat.com> | ||||||
|  | Date: Tue, 16 Aug 2022 14:34:49 +0200 | ||||||
|  | Subject: [PATCH] ci(lint): add shell linter - Differential ShellCheck | ||||||
|  | 
 | ||||||
|  | It performs differential ShellCheck scans and report results directly in | ||||||
|  | pull request. | ||||||
|  | 
 | ||||||
|  | documentation: | ||||||
|  | https://github.com/redhat-plumbers-in-action/differential-shellcheck | ||||||
|  | 
 | ||||||
|  | (inspired by commit | ||||||
|  |  https://github.com/systemd/systemd/commit/3f3c718e79abdac698ae90de5cd4c0560a0a75d4) | ||||||
|  | 
 | ||||||
|  | RHEL-only | ||||||
|  | 
 | ||||||
|  | Related: #2122499 | ||||||
|  | ---
 | ||||||
|  |  .github/workflows/differential-shellcheck.yml | 31 +++++++++++++++++++ | ||||||
|  |  1 file changed, 31 insertions(+) | ||||||
|  |  create mode 100644 .github/workflows/differential-shellcheck.yml | ||||||
|  | 
 | ||||||
|  | diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..fa94679b51
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/.github/workflows/differential-shellcheck.yml
 | ||||||
|  | @@ -0,0 +1,31 @@
 | ||||||
|  | +---
 | ||||||
|  | +# https://github.com/redhat-plumbers-in-action/differential-shellcheck#readme
 | ||||||
|  | +
 | ||||||
|  | +name: Differential ShellCheck
 | ||||||
|  | +on:
 | ||||||
|  | +  pull_request:
 | ||||||
|  | +    branches:
 | ||||||
|  | +      - master
 | ||||||
|  | +      - rhel-8.*.0
 | ||||||
|  | +
 | ||||||
|  | +permissions:
 | ||||||
|  | +  contents: read
 | ||||||
|  | +
 | ||||||
|  | +jobs:
 | ||||||
|  | +  lint:
 | ||||||
|  | +    runs-on: ubuntu-latest
 | ||||||
|  | +
 | ||||||
|  | +    permissions:
 | ||||||
|  | +      security-events: write
 | ||||||
|  | +      pull-requests: write
 | ||||||
|  | +
 | ||||||
|  | +    steps:
 | ||||||
|  | +      - name: Repository checkout
 | ||||||
|  | +        uses: actions/checkout@v3
 | ||||||
|  | +        with:
 | ||||||
|  | +          fetch-depth: 0
 | ||||||
|  | +
 | ||||||
|  | +      - name: Differential ShellCheck
 | ||||||
|  | +        uses: redhat-plumbers-in-action/differential-shellcheck@v3
 | ||||||
|  | +        with:
 | ||||||
|  | +          token: ${{ secrets.GITHUB_TOKEN }}
 | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | From deb09b3bd826571149f6b018f3a3ff8a33cd104b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Thu, 28 Jun 2018 16:09:04 +0900 | ||||||
|  | Subject: [PATCH] meson: do not compare objects of different types | ||||||
|  | 
 | ||||||
|  | This fixes the following warning: | ||||||
|  | ``` | ||||||
|  | meson.build:1140: WARNING: Trying to compare values of different types (DependencyHolder, list) using !=. | ||||||
|  | The result of this is undefined and will become a hard error in a future Meson release. | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Follow-up for f02582f69fe1e7663a87ba80bd4f90d5d23ee75f(#9410). | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 48f5da19b6e8f0d05f5217bc9856093d354ce5d0) | ||||||
|  | 
 | ||||||
|  | Related: #2122499 | ||||||
|  | ---
 | ||||||
|  |  meson.build | 3 ++- | ||||||
|  |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/meson.build b/meson.build
 | ||||||
|  | index 6729a9ea5e..af4cf331da 100644
 | ||||||
|  | --- a/meson.build
 | ||||||
|  | +++ b/meson.build
 | ||||||
|  | @@ -1165,7 +1165,8 @@ substs.set('DEFAULT_DNSSEC_MODE', default_dnssec)
 | ||||||
|  |   | ||||||
|  |  dns_over_tls = get_option('dns-over-tls') | ||||||
|  |  if dns_over_tls != 'false' | ||||||
|  | -        have = libgnutls != [] and libgnutls.version().version_compare('>=3.5.3')
 | ||||||
|  | +        have = (conf.get('HAVE_GNUTLS') == 1 and
 | ||||||
|  | +                libgnutls.version().version_compare('>=3.5.3'))
 | ||||||
|  |          if dns_over_tls == 'true' and not have | ||||||
|  |                  error('DNS-over-TLS support was requested, but dependencies are not available') | ||||||
|  |          endif | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | From ea9b3a664f5e67d0ee6b0bf6ca362835ae11fedc Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Mon, 20 Dec 2021 20:48:32 +0900 | ||||||
|  | Subject: [PATCH] journal-remote: use MHD_HTTP_CONTENT_TOO_LARGE as | ||||||
|  |  MHD_HTTP_PAYLOAD_TOO_LARGE is deprecated since 0.9.74 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 30df858f43b14a55c6650b43bea12cbf2cc0bc67) | ||||||
|  | 
 | ||||||
|  | Related: #2122499 | ||||||
|  | ---
 | ||||||
|  |  src/journal-remote/journal-remote-main.c |  2 +- | ||||||
|  |  src/journal-remote/microhttpd-util.h     | 10 +++++++--- | ||||||
|  |  2 files changed, 8 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
 | ||||||
|  | index 47fe9d7433..bcaa370099 100644
 | ||||||
|  | --- a/src/journal-remote/journal-remote-main.c
 | ||||||
|  | +++ b/src/journal-remote/journal-remote-main.c
 | ||||||
|  | @@ -304,7 +304,7 @@ static int request_handler(
 | ||||||
|  |                          /* When serialized, an entry of maximum size might be slightly larger, | ||||||
|  |                           * so this does not correspond exactly to the limit in journald. Oh well. | ||||||
|  |                           */ | ||||||
|  | -                        return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE,
 | ||||||
|  | +                        return mhd_respondf(connection, 0, MHD_HTTP_CONTENT_TOO_LARGE,
 | ||||||
|  |                                              "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX); | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h
 | ||||||
|  | index 26909082a1..dd0ca1d9bd 100644
 | ||||||
|  | --- a/src/journal-remote/microhttpd-util.h
 | ||||||
|  | +++ b/src/journal-remote/microhttpd-util.h
 | ||||||
|  | @@ -38,9 +38,13 @@
 | ||||||
|  |  #  define MHD_HTTP_NOT_ACCEPTABLE MHD_HTTP_METHOD_NOT_ACCEPTABLE | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | -/* Renamed in µhttpd 0.9.53 */
 | ||||||
|  | -#ifndef MHD_HTTP_PAYLOAD_TOO_LARGE
 | ||||||
|  | -#  define MHD_HTTP_PAYLOAD_TOO_LARGE MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
 | ||||||
|  | +/* Renamed in µhttpd 0.9.74 (8c644fc1f4d498ea489add8d40a68f5d3e5899fa) */
 | ||||||
|  | +#ifndef MHD_HTTP_CONTENT_TOO_LARGE
 | ||||||
|  | +#  ifdef MHD_HTTP_PAYLOAD_TOO_LARGE
 | ||||||
|  | +#    define MHD_HTTP_CONTENT_TOO_LARGE MHD_HTTP_PAYLOAD_TOO_LARGE /* 0.9.53 or newer */
 | ||||||
|  | +#  else
 | ||||||
|  | +#    define MHD_HTTP_CONTENT_TOO_LARGE MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
 | ||||||
|  | +#  endif
 | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  |  #if MHD_VERSION < 0x00094203 | ||||||
							
								
								
									
										71
									
								
								SOURCES/0835-Fix-build-with-httpd-0.9.71.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								SOURCES/0835-Fix-build-with-httpd-0.9.71.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | From ca86de228e19cea268ec3eeabc9097d7c28fbf24 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Tue, 30 Jun 2020 09:56:10 +0200 | ||||||
|  | Subject: [PATCH] =?UTF-8?q?Fix=20build=20with=20=C2=B5httpd=200.9.71?= | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | The return type of callbacks was changed from int to an enum. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit d17eabb1052e7c8c432331a7a782845e36164f01) | ||||||
|  | 
 | ||||||
|  | Related: #2122499 | ||||||
|  | ---
 | ||||||
|  |  src/journal-remote/journal-gatewayd.c    | 4 ++-- | ||||||
|  |  src/journal-remote/journal-remote-main.c | 2 +- | ||||||
|  |  src/journal-remote/microhttpd-util.h     | 6 ++++++ | ||||||
|  |  3 files changed, 9 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
 | ||||||
|  | index 54446ff7b5..3ff05a4d72 100644
 | ||||||
|  | --- a/src/journal-remote/journal-gatewayd.c
 | ||||||
|  | +++ b/src/journal-remote/journal-gatewayd.c
 | ||||||
|  | @@ -338,7 +338,7 @@ static int request_parse_range(
 | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int request_parse_arguments_iterator(
 | ||||||
|  | +static mhd_result request_parse_arguments_iterator(
 | ||||||
|  |                  void *cls, | ||||||
|  |                  enum MHD_ValueKind kind, | ||||||
|  |                  const char *key, | ||||||
|  | @@ -795,7 +795,7 @@ static int request_handler_machine(
 | ||||||
|  |          return MHD_queue_response(connection, MHD_HTTP_OK, response); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int request_handler(
 | ||||||
|  | +static mhd_result request_handler(
 | ||||||
|  |                  void *cls, | ||||||
|  |                  struct MHD_Connection *connection, | ||||||
|  |                  const char *url, | ||||||
|  | diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
 | ||||||
|  | index bcaa370099..a1008db6eb 100644
 | ||||||
|  | --- a/src/journal-remote/journal-remote-main.c
 | ||||||
|  | +++ b/src/journal-remote/journal-remote-main.c
 | ||||||
|  | @@ -241,7 +241,7 @@ static int process_http_upload(
 | ||||||
|  |          return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK."); | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | -static int request_handler(
 | ||||||
|  | +static mhd_result request_handler(
 | ||||||
|  |                  void *cls, | ||||||
|  |                  struct MHD_Connection *connection, | ||||||
|  |                  const char *url, | ||||||
|  | diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h
 | ||||||
|  | index dd0ca1d9bd..792c07ac20 100644
 | ||||||
|  | --- a/src/journal-remote/microhttpd-util.h
 | ||||||
|  | +++ b/src/journal-remote/microhttpd-util.h
 | ||||||
|  | @@ -51,6 +51,12 @@
 | ||||||
|  |  #  define MHD_create_response_from_fd_at_offset64 MHD_create_response_from_fd_at_offset | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | +#if MHD_VERSION >= 0x00097002
 | ||||||
|  | +#  define mhd_result enum MHD_Result
 | ||||||
|  | +#else
 | ||||||
|  | +#  define mhd_result int
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0); | ||||||
|  |   | ||||||
|  |  /* respond_oom() must be usable with return, hence this form. */ | ||||||
							
								
								
									
										303
									
								
								SOURCES/0836-ci-replace-LGTM-with-CodeQL.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								SOURCES/0836-ci-replace-LGTM-with-CodeQL.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,303 @@ | |||||||
|  | From 2b1dbcab1af1a22f3a46fa23aa551a7394673938 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Frantisek Sumsal <frantisek@sumsal.cz> | ||||||
|  | Date: Thu, 15 Sep 2022 15:29:23 +0200 | ||||||
|  | Subject: [PATCH] ci: replace LGTM with CodeQL | ||||||
|  | 
 | ||||||
|  | As LGTM is going to be shut down by EOY, let's use CodeQL instead. | ||||||
|  | 
 | ||||||
|  | This is loosely based on upstream's CodeQL configs with some minor | ||||||
|  | tweaks to avoid backporting tons of unrelated commits. | ||||||
|  | 
 | ||||||
|  | rhel-only | ||||||
|  | Related: #2122499 | ||||||
|  | ---
 | ||||||
|  |  .github/codeql-config.yml                     | 12 ++++ | ||||||
|  |  .github/codeql-custom.qls                     | 44 ++++++++++++ | ||||||
|  |  .../PotentiallyDangerousFunction.ql           |  3 + | ||||||
|  |  .../UninitializedVariableWithCleanup.ql       | 16 ++--- | ||||||
|  |  .github/codeql-queries/qlpack.yml             | 11 +++ | ||||||
|  |  .github/workflows/codeql.yml                  | 68 +++++++++++++++++++ | ||||||
|  |  .lgtm.yml                                     | 37 ---------- | ||||||
|  |  7 files changed, 146 insertions(+), 45 deletions(-) | ||||||
|  |  create mode 100644 .github/codeql-config.yml | ||||||
|  |  create mode 100644 .github/codeql-custom.qls | ||||||
|  |  rename {.lgtm/cpp-queries => .github/codeql-queries}/PotentiallyDangerousFunction.ql (93%) | ||||||
|  |  rename {.lgtm/cpp-queries => .github/codeql-queries}/UninitializedVariableWithCleanup.ql (86%) | ||||||
|  |  create mode 100644 .github/codeql-queries/qlpack.yml | ||||||
|  |  create mode 100644 .github/workflows/codeql.yml | ||||||
|  |  delete mode 100644 .lgtm.yml | ||||||
|  | 
 | ||||||
|  | diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..7c01d32caa
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/.github/codeql-config.yml
 | ||||||
|  | @@ -0,0 +1,12 @@
 | ||||||
|  | +---
 | ||||||
|  | +# vi: ts=2 sw=2 et:
 | ||||||
|  | +# SPDX-License-Identifier: LGPL-2.1-or-later
 | ||||||
|  | +name: "CodeQL config"
 | ||||||
|  | +
 | ||||||
|  | +disable-default-queries: false
 | ||||||
|  | +
 | ||||||
|  | +queries:
 | ||||||
|  | +  - name: Enable possibly useful queries which are disabled by default
 | ||||||
|  | +    uses: ./.github/codeql-custom.qls
 | ||||||
|  | +  - name: systemd-specific CodeQL queries
 | ||||||
|  | +    uses: ./.github/codeql-queries/
 | ||||||
|  | diff --git a/.github/codeql-custom.qls b/.github/codeql-custom.qls
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..d35fbe3114
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/.github/codeql-custom.qls
 | ||||||
|  | @@ -0,0 +1,44 @@
 | ||||||
|  | +---
 | ||||||
|  | +# vi: ts=2 sw=2 et syntax=yaml:
 | ||||||
|  | +# SPDX-License-Identifier: LGPL-2.1-or-later
 | ||||||
|  | +#
 | ||||||
|  | +# Note: it is not recommended to directly reference the respective queries from
 | ||||||
|  | +#       the github/codeql repository, so we have to "dance" around it using
 | ||||||
|  | +#       a custom QL suite
 | ||||||
|  | +# See:
 | ||||||
|  | +#   - https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#running-additional-queries
 | ||||||
|  | +#   - https://github.com/github/codeql-action/issues/430#issuecomment-806092120
 | ||||||
|  | +#   - https://codeql.github.com/docs/codeql-cli/creating-codeql-query-suites/
 | ||||||
|  | +
 | ||||||
|  | +# Note: the codeql/<lang>-queries pack name can be found in the CodeQL repo[0]
 | ||||||
|  | +#       in <lang>/ql/src/qlpack.yml. The respective codeql-suites are then
 | ||||||
|  | +#       under <lang>/ql/src/codeql-suites/.
 | ||||||
|  | +#
 | ||||||
|  | +# [0] https://github.com/github/codeql
 | ||||||
|  | +- import: codeql-suites/cpp-lgtm.qls
 | ||||||
|  | +  from: codeql/cpp-queries
 | ||||||
|  | +- import: codeql-suites/python-lgtm.qls
 | ||||||
|  | +  from: codeql/python-queries
 | ||||||
|  | +- include:
 | ||||||
|  | +    id:
 | ||||||
|  | +      - cpp/bad-strncpy-size
 | ||||||
|  | +      - cpp/declaration-hides-variable
 | ||||||
|  | +      - cpp/include-non-header
 | ||||||
|  | +      - cpp/inconsistent-null-check
 | ||||||
|  | +      - cpp/mistyped-function-arguments
 | ||||||
|  | +      - cpp/nested-loops-with-same-variable
 | ||||||
|  | +      - cpp/sizeof-side-effect
 | ||||||
|  | +      - cpp/suspicious-pointer-scaling
 | ||||||
|  | +      - cpp/suspicious-pointer-scaling-void
 | ||||||
|  | +      - cpp/suspicious-sizeof
 | ||||||
|  | +      - cpp/unsafe-strcat
 | ||||||
|  | +      - cpp/unsafe-strncat
 | ||||||
|  | +      - cpp/unsigned-difference-expression-compared-zero
 | ||||||
|  | +      - cpp/unused-local-variable
 | ||||||
|  | +    tags:
 | ||||||
|  | +      - "security"
 | ||||||
|  | +      - "correctness"
 | ||||||
|  | +    severity: "error"
 | ||||||
|  | +- exclude:
 | ||||||
|  | +    id:
 | ||||||
|  | +      - cpp/fixme-comment
 | ||||||
|  | diff --git a/.lgtm/cpp-queries/PotentiallyDangerousFunction.ql b/.github/codeql-queries/PotentiallyDangerousFunction.ql
 | ||||||
|  | similarity index 93% | ||||||
|  | rename from .lgtm/cpp-queries/PotentiallyDangerousFunction.ql | ||||||
|  | rename to .github/codeql-queries/PotentiallyDangerousFunction.ql | ||||||
|  | index 39e8dddd13..63fd14e75f 100644
 | ||||||
|  | --- a/.lgtm/cpp-queries/PotentiallyDangerousFunction.ql
 | ||||||
|  | +++ b/.github/codeql-queries/PotentiallyDangerousFunction.ql
 | ||||||
|  | @@ -46,6 +46,9 @@ predicate potentiallyDangerousFunction(Function f, string message) {
 | ||||||
|  |    ) or ( | ||||||
|  |      f.getQualifiedName() = "accept" and | ||||||
|  |      message = "Call to accept() is not O_CLOEXEC-safe. Use accept4() instead." | ||||||
|  | +  ) or (
 | ||||||
|  | +    f.getQualifiedName() = "dirname" and
 | ||||||
|  | +    message = "Call dirname() is icky. Use path_extract_directory() instead."
 | ||||||
|  |    ) | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/.lgtm/cpp-queries/UninitializedVariableWithCleanup.ql b/.github/codeql-queries/UninitializedVariableWithCleanup.ql
 | ||||||
|  | similarity index 86% | ||||||
|  | rename from .lgtm/cpp-queries/UninitializedVariableWithCleanup.ql | ||||||
|  | rename to .github/codeql-queries/UninitializedVariableWithCleanup.ql | ||||||
|  | index 6b3b62f8bc..e514111f28 100644
 | ||||||
|  | --- a/.lgtm/cpp-queries/UninitializedVariableWithCleanup.ql
 | ||||||
|  | +++ b/.github/codeql-queries/UninitializedVariableWithCleanup.ql
 | ||||||
|  | @@ -50,16 +50,16 @@ class UninitialisedLocalReachability extends StackVariableReachability {
 | ||||||
|  |     * fun(&x); | ||||||
|  |     * puts(x); | ||||||
|  |     * | ||||||
|  | -   * `useOfVarActual()` won't treat this an an uninitialized read even if the callee
 | ||||||
|  | +   * `useOfVarActual()` won't treat this as an uninitialized read even if the callee
 | ||||||
|  |     * doesn't modify the argument, however, `useOfVar()` will | ||||||
|  |     */ | ||||||
|  |    override predicate isSink(ControlFlowNode node, StackVariable v) { useOfVar(v, node) } | ||||||
|  |   | ||||||
|  |    override predicate isBarrier(ControlFlowNode node, StackVariable v) { | ||||||
|  | -    // only report the _first_ possibly uninitialized use
 | ||||||
|  | +    /* only report the _first_ possibly uninitialized use */
 | ||||||
|  |      useOfVar(v, node) or | ||||||
|  |      ( | ||||||
|  | -      /* If there's an return statement somewhere between the variable declaration
 | ||||||
|  | +      /* If there's a return statement somewhere between the variable declaration
 | ||||||
|  |         * and a possible definition, don't accept is as a valid initialization. | ||||||
|  |         * | ||||||
|  |         * E.g.: | ||||||
|  | @@ -71,7 +71,7 @@ class UninitialisedLocalReachability extends StackVariableReachability {
 | ||||||
|  |         * x = malloc(...); | ||||||
|  |         * | ||||||
|  |         * is not a valid initialization, since we might return from the function | ||||||
|  | -       * _before_ the actual iniitialization (emphasis on _might_, since we
 | ||||||
|  | +       * _before_ the actual initialization (emphasis on _might_, since we
 | ||||||
|  |         * don't know if the return statement might ever evaluate to true). | ||||||
|  |         */ | ||||||
|  |        definitionBarrier(v, node) and | ||||||
|  | @@ -92,14 +92,14 @@ predicate containsInlineAssembly(Function f) { exists(AsmStmt s | s.getEnclosing
 | ||||||
|  |   * for this check to exclude them. | ||||||
|  |   */ | ||||||
|  |  VariableAccess commonException() { | ||||||
|  | -  // If the uninitialized use we've found is in a macro expansion, it's
 | ||||||
|  | -  // typically something like va_start(), and we don't want to complain.
 | ||||||
|  | +  /* If the uninitialized use we've found is in a macro expansion, it's
 | ||||||
|  | +   * typically something like va_start(), and we don't want to complain. */
 | ||||||
|  |    result.getParent().isInMacroExpansion() | ||||||
|  |    or | ||||||
|  |    result.getParent() instanceof BuiltInOperation | ||||||
|  |    or | ||||||
|  | -  // Finally, exclude functions that contain assembly blocks. It's
 | ||||||
|  | -  // anyone's guess what happens in those.
 | ||||||
|  | +  /* Finally, exclude functions that contain assembly blocks. It's
 | ||||||
|  | +   * anyone's guess what happens in those. */
 | ||||||
|  |    containsInlineAssembly(result.getEnclosingFunction()) | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/.github/codeql-queries/qlpack.yml b/.github/codeql-queries/qlpack.yml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..a1a2dec6d6
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/.github/codeql-queries/qlpack.yml
 | ||||||
|  | @@ -0,0 +1,11 @@
 | ||||||
|  | +---
 | ||||||
|  | +# vi: ts=2 sw=2 et syntax=yaml:
 | ||||||
|  | +# SPDX-License-Identifier: LGPL-2.1-or-later
 | ||||||
|  | +
 | ||||||
|  | +library: false
 | ||||||
|  | +name: systemd/cpp-queries
 | ||||||
|  | +version: 0.0.1
 | ||||||
|  | +dependencies:
 | ||||||
|  | +  codeql/cpp-all: "*"
 | ||||||
|  | +  codeql/suite-helpers: "*"
 | ||||||
|  | +extractor: cpp
 | ||||||
|  | diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..c5426d5686
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/.github/workflows/codeql.yml
 | ||||||
|  | @@ -0,0 +1,68 @@
 | ||||||
|  | +---
 | ||||||
|  | +# vi: ts=2 sw=2 et:
 | ||||||
|  | +# SPDX-License-Identifier: LGPL-2.1-or-later
 | ||||||
|  | +#
 | ||||||
|  | +name: "CodeQL"
 | ||||||
|  | +
 | ||||||
|  | +on:
 | ||||||
|  | +  pull_request:
 | ||||||
|  | +    branches:
 | ||||||
|  | +      - master
 | ||||||
|  | +      - rhel-*
 | ||||||
|  | +    paths:
 | ||||||
|  | +      - '**/meson.build'
 | ||||||
|  | +      - '.github/**/codeql*'
 | ||||||
|  | +      - 'src/**'
 | ||||||
|  | +      - 'test/**'
 | ||||||
|  | +      - 'tools/**'
 | ||||||
|  | +  push:
 | ||||||
|  | +    branches:
 | ||||||
|  | +      - master
 | ||||||
|  | +      - rhel-*
 | ||||||
|  | +
 | ||||||
|  | +permissions:
 | ||||||
|  | +  contents: read
 | ||||||
|  | +
 | ||||||
|  | +jobs:
 | ||||||
|  | +  analyze:
 | ||||||
|  | +    name: Analyze
 | ||||||
|  | +    runs-on: ubuntu-22.04
 | ||||||
|  | +    concurrency:
 | ||||||
|  | +      group: ${{ github.workflow }}-${{ matrix.language }}-${{ github.ref }}
 | ||||||
|  | +      cancel-in-progress: true
 | ||||||
|  | +    permissions:
 | ||||||
|  | +      actions: read
 | ||||||
|  | +      security-events: write
 | ||||||
|  | +
 | ||||||
|  | +    strategy:
 | ||||||
|  | +      fail-fast: false
 | ||||||
|  | +      matrix:
 | ||||||
|  | +        language: ['cpp', 'python']
 | ||||||
|  | +
 | ||||||
|  | +    steps:
 | ||||||
|  | +    - name: Checkout repository
 | ||||||
|  | +      uses: actions/checkout@v3
 | ||||||
|  | +
 | ||||||
|  | +    - name: Initialize CodeQL
 | ||||||
|  | +      uses: github/codeql-action/init@v2
 | ||||||
|  | +      with:
 | ||||||
|  | +        languages: ${{ matrix.language }}
 | ||||||
|  | +        config-file: ./.github/codeql-config.yml
 | ||||||
|  | +
 | ||||||
|  | +    - name: Install dependencies
 | ||||||
|  | +      if: matrix.language == 'cpp'
 | ||||||
|  | +      run: |
 | ||||||
|  | +        echo "deb-src http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
 | ||||||
|  | +        sudo apt-get -y update
 | ||||||
|  | +        sudo apt-get -y build-dep systemd
 | ||||||
|  | +        sudo apt-get -y install libfdisk-dev libpwquality-dev libqrencode-dev libssl-dev libxkbcommon-dev libzstd-dev
 | ||||||
|  | +
 | ||||||
|  | +    - name: Build
 | ||||||
|  | +      if: matrix.language == 'cpp'
 | ||||||
|  | +      run: |
 | ||||||
|  | +        # EL 8 systemd fails to build with newer gnu-efi (3.0.13 on Ubuntu Jammy ATTOW)
 | ||||||
|  | +        meson build -Dlibiptc=false -Dgnu-efi=false
 | ||||||
|  | +        ninja -C build -v
 | ||||||
|  | +
 | ||||||
|  | +    - name: Perform CodeQL Analysis
 | ||||||
|  | +      uses: github/codeql-action/analyze@v2
 | ||||||
|  | diff --git a/.lgtm.yml b/.lgtm.yml
 | ||||||
|  | deleted file mode 100644 | ||||||
|  | index fe93957b67..0000000000
 | ||||||
|  | --- a/.lgtm.yml
 | ||||||
|  | +++ /dev/null
 | ||||||
|  | @@ -1,37 +0,0 @@
 | ||||||
|  | ----
 | ||||||
|  | -# vi: ts=2 sw=2 et:
 | ||||||
|  | -
 | ||||||
|  | -# Explicitly enable certain checks which are hidden by default
 | ||||||
|  | -queries:
 | ||||||
|  | -  - include: cpp/bad-strncpy-size
 | ||||||
|  | -  - include: cpp/declaration-hides-variable
 | ||||||
|  | -  - include: cpp/inconsistent-null-check
 | ||||||
|  | -  - include: cpp/mistyped-function-arguments
 | ||||||
|  | -  - include: cpp/nested-loops-with-same-variable
 | ||||||
|  | -  - include: cpp/sizeof-side-effect
 | ||||||
|  | -  - include: cpp/suspicious-pointer-scaling
 | ||||||
|  | -  - include: cpp/suspicious-pointer-scaling-void
 | ||||||
|  | -  - include: cpp/suspicious-sizeof
 | ||||||
|  | -  - include: cpp/unsafe-strcat
 | ||||||
|  | -  - include: cpp/unsafe-strncat
 | ||||||
|  | -  - include: cpp/unsigned-difference-expression-compared-zero
 | ||||||
|  | -  - include: cpp/unused-local-variable
 | ||||||
|  | -  - include:
 | ||||||
|  | -      tags:
 | ||||||
|  | -        - "security"
 | ||||||
|  | -        - "correctness"
 | ||||||
|  | -      severity: "error"
 | ||||||
|  | -
 | ||||||
|  | -extraction:
 | ||||||
|  | -  cpp:
 | ||||||
|  | -    prepare:
 | ||||||
|  | -      packages:
 | ||||||
|  | -        - python3-pip
 | ||||||
|  | -        - python3-setuptools
 | ||||||
|  | -        - python3-wheel
 | ||||||
|  | -    after_prepare:
 | ||||||
|  | -      - pip3 install meson
 | ||||||
|  | -      - export PATH="$HOME/.local/bin/:$PATH"
 | ||||||
|  | -  python:
 | ||||||
|  | -    python_setup:
 | ||||||
|  | -      version: 3
 | ||||||
							
								
								
									
										71
									
								
								SOURCES/0837-ci-mergify-Update-policy-Drop-LGTM-checks.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								SOURCES/0837-ci-mergify-Update-policy-Drop-LGTM-checks.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | From 4c241b812ea79f3faa02c45f95834842c7847b76 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Macku <jamacku@redhat.com> | ||||||
|  | Date: Wed, 21 Sep 2022 15:14:26 +0200 | ||||||
|  | Subject: [PATCH] ci(mergify): Update policy - Drop LGTM checks | ||||||
|  | 
 | ||||||
|  | rhel-only | ||||||
|  | 
 | ||||||
|  | Related: #2122499 | ||||||
|  | ---
 | ||||||
|  |  .github/workflows/differential-shellcheck.yml |  1 + | ||||||
|  |  .mergify.yml                                  | 28 ++++++------------- | ||||||
|  |  2 files changed, 9 insertions(+), 20 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml
 | ||||||
|  | index fa94679b51..4399f0bc64 100644
 | ||||||
|  | --- a/.github/workflows/differential-shellcheck.yml
 | ||||||
|  | +++ b/.github/workflows/differential-shellcheck.yml
 | ||||||
|  | @@ -13,6 +13,7 @@ permissions:
 | ||||||
|  |   | ||||||
|  |  jobs: | ||||||
|  |    lint: | ||||||
|  | +    name: Differential ShellCheck
 | ||||||
|  |      runs-on: ubuntu-latest | ||||||
|  |   | ||||||
|  |      permissions: | ||||||
|  | diff --git a/.mergify.yml b/.mergify.yml
 | ||||||
|  | index 3afd04f18e..a5eed6a82a 100644
 | ||||||
|  | --- a/.mergify.yml
 | ||||||
|  | +++ b/.mergify.yml
 | ||||||
|  | @@ -11,16 +11,10 @@ pull_request_rules:
 | ||||||
|  |          - -check-success=build (stream8, GCC_ASAN) | ||||||
|  |          # CentOS Stream CI | ||||||
|  |          - -check-success=CentOS CI (CentOS Stream 8) | ||||||
|  | -        # LGTM
 | ||||||
|  | -        - and:
 | ||||||
|  | -          - "-check-success=LGTM analysis: JavaScript"
 | ||||||
|  | -          - "-check-neutral=LGTM analysis: JavaScript"
 | ||||||
|  | -        - and:
 | ||||||
|  | -          - "-check-success=LGTM analysis: Python"
 | ||||||
|  | -          - "-check-neutral=LGTM analysis: Python"
 | ||||||
|  | -        - and:    
 | ||||||
|  | -          - "-check-success=LGTM analysis: C/C++"
 | ||||||
|  | -          - "-check-neutral=LGTM analysis: C/C++"
 | ||||||
|  | +        # CodeQL
 | ||||||
|  | +        - -check-success=CodeQL
 | ||||||
|  | +        # Other
 | ||||||
|  | +        - -check-success=Differential ShellCheck
 | ||||||
|  |      actions: | ||||||
|  |        label: | ||||||
|  |          add: | ||||||
|  | @@ -36,16 +30,10 @@ pull_request_rules:
 | ||||||
|  |            - check-success=build (stream8, GCC_ASAN) | ||||||
|  |            # CentOS Stream CI | ||||||
|  |            - check-success=CentOS CI (CentOS Stream 8) | ||||||
|  | -          # LGTM
 | ||||||
|  | -          - or:
 | ||||||
|  | -            - "check-success=LGTM analysis: JavaScript"
 | ||||||
|  | -            - "check-neutral=LGTM analysis: JavaScript"
 | ||||||
|  | -          - or:
 | ||||||
|  | -            - "check-success=LGTM analysis: Python"
 | ||||||
|  | -            - "check-neutral=LGTM analysis: Python"
 | ||||||
|  | -          - or:    
 | ||||||
|  | -            - "check-success=LGTM analysis: C/C++"
 | ||||||
|  | -            - "check-neutral=LGTM analysis: C/C++"
 | ||||||
|  | +          # CodeQL
 | ||||||
|  | +          - check-success=CodeQL
 | ||||||
|  | +          # Other
 | ||||||
|  | +          - check-success=Differential ShellCheck
 | ||||||
|  |      actions: | ||||||
|  |        label: | ||||||
|  |          remove: | ||||||
| @ -1,4 +1,4 @@ | |||||||
| From 3ec7e3ece5474475b9123a67636f1ba3eec1e3c4 Mon Sep 17 00:00:00 2001 | From a521f942d5c304bca7c61bacb3c79e565853718e Mon Sep 17 00:00:00 2001 | ||||||
| From: Yu Watanabe <watanabe.yu+github@gmail.com> | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
| Date: Thu, 7 Jul 2022 18:27:02 +0900 | Date: Thu, 7 Jul 2022 18:27:02 +0900 | ||||||
| Subject: [PATCH] time-util: fix buffer-over-run | Subject: [PATCH] time-util: fix buffer-over-run | ||||||
| @ -7,7 +7,7 @@ Fixes #23928. | |||||||
| 
 | 
 | ||||||
| (cherry picked from commit 9102c625a673a3246d7e73d8737f3494446bad4e) | (cherry picked from commit 9102c625a673a3246d7e73d8737f3494446bad4e) | ||||||
| 
 | 
 | ||||||
| Resolves: #2139390 | Resolves: #2139391 | ||||||
| ---
 | ---
 | ||||||
|  src/basic/time-util.c     | 2 +- |  src/basic/time-util.c     | 2 +- | ||||||
|  src/test/test-time-util.c | 5 +++++ |  src/test/test-time-util.c | 5 +++++ | ||||||
| @ -1,4 +1,4 @@ | |||||||
| From 9274a3bec0d3b259a006574f6bfb559888b04533 Mon Sep 17 00:00:00 2001 | From 2fe9fb3e844d7991105c40d4363eed9069a6837d Mon Sep 17 00:00:00 2001 | ||||||
| From: Michal Sekletar <msekleta@redhat.com> | From: Michal Sekletar <msekleta@redhat.com> | ||||||
| Date: Fri, 18 Nov 2022 16:16:36 +0100 | Date: Fri, 18 Nov 2022 16:16:36 +0100 | ||||||
| Subject: [PATCH] basic: recognize pdfs filesystem as a network filesystem | Subject: [PATCH] basic: recognize pdfs filesystem as a network filesystem | ||||||
| @ -11,7 +11,7 @@ https://software.fujitsu.com/jp/manual/manualfiles/m130027/j2ul1563/02enz200/j15 | |||||||
| 
 | 
 | ||||||
| RHEL-only | RHEL-only | ||||||
| 
 | 
 | ||||||
| Resolves: #2143100 | Resolves: #2094661 | ||||||
| ---
 | ---
 | ||||||
|  src/basic/mount-util.c | 3 ++- |  src/basic/mount-util.c | 3 ++- | ||||||
|  1 file changed, 2 insertions(+), 1 deletion(-) |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
| @ -1,4 +1,4 @@ | |||||||
| From 944596e66a9cd947545c714c4682681fdbefc09f Mon Sep 17 00:00:00 2001 | From 4bb425eea9f3037a583a23d99f15aa71562f2481 Mon Sep 17 00:00:00 2001 | ||||||
| From: Anita Zhang <the.anitazha@gmail.com> | From: Anita Zhang <the.anitazha@gmail.com> | ||||||
| Date: Thu, 17 Sep 2020 01:49:17 -0700 | Date: Thu, 17 Sep 2020 01:49:17 -0700 | ||||||
| Subject: [PATCH] core: move reset_arguments() to the end of main's finish | Subject: [PATCH] core: move reset_arguments() to the end of main's finish | ||||||
| @ -15,7 +15,7 @@ right before the return, when nothing else will be using the arg_* variables. | |||||||
| 
 | 
 | ||||||
| (cherry picked from commit 7d9eea2bd3d4f83668c7a78754d201b226acbf1e) | (cherry picked from commit 7d9eea2bd3d4f83668c7a78754d201b226acbf1e) | ||||||
| 
 | 
 | ||||||
| Resolves: #2127170 | Resolves: #2127131 | ||||||
| ---
 | ---
 | ||||||
|  src/core/main.c | 3 ++- |  src/core/main.c | 3 ++- | ||||||
|  1 file changed, 2 insertions(+), 1 deletion(-) |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
| @ -0,0 +1,91 @@ | |||||||
|  | From 708c394b7ca35fe2328fa0760696ff95caab8ff8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Tardon <dtardon@redhat.com> | ||||||
|  | Date: Tue, 29 Nov 2022 16:15:47 +0100 | ||||||
|  | Subject: [PATCH] manager: move inc. of n_reloading into a function | ||||||
|  | 
 | ||||||
|  | [dtardon: This is inspired by commit d147e2b66b4d6b71db1bc59b62286b2eb9c3d29f , | ||||||
|  | but it does just the minimal change needed for the next commit.] | ||||||
|  | 
 | ||||||
|  | Related: #2136869 | ||||||
|  | ---
 | ||||||
|  |  src/core/main.c    |  2 +- | ||||||
|  |  src/core/manager.c | 12 ++++++++---- | ||||||
|  |  src/core/manager.h |  1 + | ||||||
|  |  3 files changed, 10 insertions(+), 5 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/main.c b/src/core/main.c
 | ||||||
|  | index cfa6fec930..c3e2ce8956 100644
 | ||||||
|  | --- a/src/core/main.c
 | ||||||
|  | +++ b/src/core/main.c
 | ||||||
|  | @@ -1131,7 +1131,7 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
 | ||||||
|  |                  return log_error_errno(r, "Failed to create serialization file: %m"); | ||||||
|  |   | ||||||
|  |          /* Make sure nothing is really destructed when we shut down */ | ||||||
|  | -        m->n_reloading++;
 | ||||||
|  | +        manager_reloading_start(m);
 | ||||||
|  |          bus_manager_send_reloading(m, true); | ||||||
|  |   | ||||||
|  |          fds = fdset_new(); | ||||||
|  | diff --git a/src/core/manager.c b/src/core/manager.c
 | ||||||
|  | index f4611e6f8f..f923cbce37 100644
 | ||||||
|  | --- a/src/core/manager.c
 | ||||||
|  | +++ b/src/core/manager.c
 | ||||||
|  | @@ -1578,6 +1578,10 @@ static void manager_preset_all(Manager *m) {
 | ||||||
|  |                  log_info("Populated /etc with preset unit settings."); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void manager_reloading_start(Manager *m) {
 | ||||||
|  | +        m->n_reloading++;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  | @@ -1609,7 +1613,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
 | ||||||
|  |           * this is already known, so we increase the counter here | ||||||
|  |           * already */ | ||||||
|  |          if (serialization) | ||||||
|  | -                m->n_reloading++;
 | ||||||
|  | +                manager_reloading_start(m);
 | ||||||
|  |   | ||||||
|  |          /* First, enumerate what we can from all config files */ | ||||||
|  |          dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_UNITS_LOAD_START); | ||||||
|  | @@ -3093,7 +3097,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
 | ||||||
|  |          assert(f); | ||||||
|  |          assert(fds); | ||||||
|  |   | ||||||
|  | -        m->n_reloading++;
 | ||||||
|  | +        manager_reloading_start(m);
 | ||||||
|  |   | ||||||
|  |          fprintf(f, "current-job-id=%"PRIu32"\n", m->current_job_id); | ||||||
|  |          fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs); | ||||||
|  | @@ -3211,7 +3215,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
 | ||||||
|  |   | ||||||
|  |          log_debug("Deserializing state..."); | ||||||
|  |   | ||||||
|  | -        m->n_reloading++;
 | ||||||
|  | +        manager_reloading_start(m);
 | ||||||
|  |   | ||||||
|  |          for (;;) { | ||||||
|  |                  _cleanup_free_ char *line = NULL; | ||||||
|  | @@ -3455,7 +3459,7 @@ int manager_reload(Manager *m) {
 | ||||||
|  |          if (r < 0) | ||||||
|  |                  return r; | ||||||
|  |   | ||||||
|  | -        m->n_reloading++;
 | ||||||
|  | +        manager_reloading_start(m);
 | ||||||
|  |          bus_manager_send_reloading(m, true); | ||||||
|  |   | ||||||
|  |          fds = fdset_new(); | ||||||
|  | diff --git a/src/core/manager.h b/src/core/manager.h
 | ||||||
|  | index 3f2cfc5e2e..adbbb518cb 100644
 | ||||||
|  | --- a/src/core/manager.h
 | ||||||
|  | +++ b/src/core/manager.h
 | ||||||
|  | @@ -386,6 +386,7 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **m);
 | ||||||
|  |  Manager* manager_free(Manager *m); | ||||||
|  |  DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); | ||||||
|  |   | ||||||
|  | +void manager_reloading_start(Manager *m);
 | ||||||
|  |  int manager_startup(Manager *m, FILE *serialization, FDSet *fds); | ||||||
|  |   | ||||||
|  |  Job *manager_get_job(Manager *m, uint32_t id); | ||||||
| @ -0,0 +1,59 @@ | |||||||
|  | From 22eb8fbdab14e5b1b11a4d84c83bef97317e1d2a Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Macku <jamacku@redhat.com> | ||||||
|  | Date: Thu, 2 Sep 2021 16:37:13 +0200 | ||||||
|  | Subject: [PATCH] core: Add new DBUS properties UnitsReloadStartTimestamp and | ||||||
|  |  UnitsLoadTimestampMontonic | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 49fbe940a429c3d8807bacdfce03af834275257c) | ||||||
|  | 
 | ||||||
|  | Related: #2136869 | ||||||
|  | ---
 | ||||||
|  |  src/core/dbus-manager.c | 1 + | ||||||
|  |  src/core/manager.c      | 2 ++ | ||||||
|  |  src/core/manager.h      | 1 + | ||||||
|  |  3 files changed, 4 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
 | ||||||
|  | index 5b1ed3646e..8a41eda4a6 100644
 | ||||||
|  | --- a/src/core/dbus-manager.c
 | ||||||
|  | +++ b/src/core/dbus-manager.c
 | ||||||
|  | @@ -2486,6 +2486,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
 | ||||||
|  |          BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_GENERATORS_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), | ||||||
|  |          BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_START]), SD_BUS_VTABLE_PROPERTY_CONST), | ||||||
|  |          BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), | ||||||
|  | +        BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD]), SD_BUS_VTABLE_PROPERTY_CONST),
 | ||||||
|  |          SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0), | ||||||
|  |          SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0), | ||||||
|  |          SD_BUS_PROPERTY("NNames", "u", property_get_hashmap_size, offsetof(Manager, units), 0), | ||||||
|  | diff --git a/src/core/manager.c b/src/core/manager.c
 | ||||||
|  | index f923cbce37..8aa398cac8 100644
 | ||||||
|  | --- a/src/core/manager.c
 | ||||||
|  | +++ b/src/core/manager.c
 | ||||||
|  | @@ -1580,6 +1580,7 @@ static void manager_preset_all(Manager *m) {
 | ||||||
|  |   | ||||||
|  |  void manager_reloading_start(Manager *m) { | ||||||
|  |          m->n_reloading++; | ||||||
|  | +        dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_UNITS_LOAD);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { | ||||||
|  | @@ -4622,6 +4623,7 @@ static const char *const manager_timestamp_table[_MANAGER_TIMESTAMP_MAX] = {
 | ||||||
|  |          [MANAGER_TIMESTAMP_GENERATORS_FINISH] = "generators-finish", | ||||||
|  |          [MANAGER_TIMESTAMP_UNITS_LOAD_START] = "units-load-start", | ||||||
|  |          [MANAGER_TIMESTAMP_UNITS_LOAD_FINISH] = "units-load-finish", | ||||||
|  | +        [MANAGER_TIMESTAMP_UNITS_LOAD]               = "units-load",
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  DEFINE_STRING_TABLE_LOOKUP(manager_timestamp, ManagerTimestamp); | ||||||
|  | diff --git a/src/core/manager.h b/src/core/manager.h
 | ||||||
|  | index adbbb518cb..98d381bc5b 100644
 | ||||||
|  | --- a/src/core/manager.h
 | ||||||
|  | +++ b/src/core/manager.h
 | ||||||
|  | @@ -67,6 +67,7 @@ typedef enum ManagerTimestamp {
 | ||||||
|  |          MANAGER_TIMESTAMP_GENERATORS_FINISH, | ||||||
|  |          MANAGER_TIMESTAMP_UNITS_LOAD_START, | ||||||
|  |          MANAGER_TIMESTAMP_UNITS_LOAD_FINISH, | ||||||
|  | +        MANAGER_TIMESTAMP_UNITS_LOAD,
 | ||||||
|  |          _MANAGER_TIMESTAMP_MAX, | ||||||
|  |          _MANAGER_TIMESTAMP_INVALID = -1, | ||||||
|  |  } ManagerTimestamp; | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | From f2de5398b0a1ebb3e6390506368c11329b843524 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Macku <jamacku@redhat.com> | ||||||
|  | Date: Thu, 2 Sep 2021 16:50:50 +0200 | ||||||
|  | Subject: [PATCH] core: Indicate the time when the manager started loading | ||||||
|  |  units the last time | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 15b9243c0d7f6d1531fa65dbc01bd11e8e6c12ca) | ||||||
|  | 
 | ||||||
|  | Resolves: #2136869 | ||||||
|  | ---
 | ||||||
|  |  src/core/manager.c | 5 +++++ | ||||||
|  |  1 file changed, 5 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/manager.c b/src/core/manager.c
 | ||||||
|  | index 8aa398cac8..a9cd51b624 100644
 | ||||||
|  | --- a/src/core/manager.c
 | ||||||
|  | +++ b/src/core/manager.c
 | ||||||
|  | @@ -3554,6 +3554,11 @@ int manager_reload(Manager *m) {
 | ||||||
|  |          /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ | ||||||
|  |          manager_catchup(m); | ||||||
|  |   | ||||||
|  | +        /* Create a file which will indicate when the manager started loading units the last time. */
 | ||||||
|  | +        (void) touch_file("/run/systemd/systemd-units-load", false,
 | ||||||
|  | +                m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD].realtime ?: now(CLOCK_REALTIME),
 | ||||||
|  | +                UID_INVALID, GID_INVALID, 0444);
 | ||||||
|  | +
 | ||||||
|  |          /* Sync current state of bus names with our set of listening units */ | ||||||
|  |          q = manager_enqueue_sync_bus_names(m); | ||||||
|  |          if (q < 0 && r >= 0) | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | From 3c2d2345814935cea8525e802e764fb2949eb3df Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Luca Boccassi <luca.boccassi@microsoft.com> | ||||||
|  | Date: Mon, 27 Dec 2021 18:22:43 +0000 | ||||||
|  | Subject: [PATCH] core: do not touch /run/systemd/systemd-units-load from user | ||||||
|  |  session instances | ||||||
|  | 
 | ||||||
|  | Follow-up for: https://github.com/systemd/systemd/commit/15b9243c0d7f6d1531fa65dbc01bd11e8e6c12ca | ||||||
|  | Fixes: https://github.com/systemd/systemd/issues/21911 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 4b3ad81bfafcd97acb06db463495e348d159d8e6) | ||||||
|  | 
 | ||||||
|  | Related: #2136869 | ||||||
|  | ---
 | ||||||
|  |  src/core/manager.c | 7 ++++--- | ||||||
|  |  1 file changed, 4 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/manager.c b/src/core/manager.c
 | ||||||
|  | index a9cd51b624..e083596e58 100644
 | ||||||
|  | --- a/src/core/manager.c
 | ||||||
|  | +++ b/src/core/manager.c
 | ||||||
|  | @@ -3555,9 +3555,10 @@ int manager_reload(Manager *m) {
 | ||||||
|  |          manager_catchup(m); | ||||||
|  |   | ||||||
|  |          /* Create a file which will indicate when the manager started loading units the last time. */ | ||||||
|  | -        (void) touch_file("/run/systemd/systemd-units-load", false,
 | ||||||
|  | -                m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD].realtime ?: now(CLOCK_REALTIME),
 | ||||||
|  | -                UID_INVALID, GID_INVALID, 0444);
 | ||||||
|  | +        if (MANAGER_IS_SYSTEM(m))
 | ||||||
|  | +                (void) touch_file("/run/systemd/systemd-units-load", false,
 | ||||||
|  | +                        m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD].realtime ?: now(CLOCK_REALTIME),
 | ||||||
|  | +                        UID_INVALID, GID_INVALID, 0444);
 | ||||||
|  |   | ||||||
|  |          /* Sync current state of bus names with our set of listening units */ | ||||||
|  |          q = manager_enqueue_sync_bus_names(m); | ||||||
| @ -0,0 +1,49 @@ | |||||||
|  | From ffe4233155085b479c69abe844a34de212b8e5e1 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Thu, 16 Jan 2020 14:45:28 +0100 | ||||||
|  | Subject: [PATCH] sysctl: downgrade message when we have no permission | ||||||
|  | 
 | ||||||
|  | We need to run sysctl also in containers, because the network | ||||||
|  | subtree is namespaces and may legitimately be writable. But logging | ||||||
|  | all "errors" at notice level creates unwanted noise. | ||||||
|  | 
 | ||||||
|  | Also downgrade message about missing sysctls to log_info. This might also be | ||||||
|  | relatively common when configuration is targeted at different kernel | ||||||
|  | versions. With log_debug it'll still end up in the logs, but isn't really worth | ||||||
|  | of "notice" most of the time. | ||||||
|  | 
 | ||||||
|  | https://bugzilla.redhat.com/show_bug.cgi?id=1609806 | ||||||
|  | (cherry picked from commit 32458cc9687c1b60ff0f22c0e71da93ce78b1534) | ||||||
|  | 
 | ||||||
|  | Resolves: #2158160 | ||||||
|  | ---
 | ||||||
|  |  src/sysctl/sysctl.c | 16 +++++++++------- | ||||||
|  |  1 file changed, 9 insertions(+), 7 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
 | ||||||
|  | index 4c85d6887f..dc14e1aaf1 100644
 | ||||||
|  | --- a/src/sysctl/sysctl.c
 | ||||||
|  | +++ b/src/sysctl/sysctl.c
 | ||||||
|  | @@ -82,13 +82,15 @@ static int apply_all(OrderedHashmap *sysctl_options) {
 | ||||||
|  |                  k = sysctl_write(option->key, option->value); | ||||||
|  |                  if (k < 0) { | ||||||
|  |                          /* If the sysctl is not available in the kernel or we are running with reduced | ||||||
|  | -                         * privileges and cannot write it, then log about the issue at LOG_NOTICE level, and
 | ||||||
|  | -                         * proceed without failing. (EROFS is treated as a permission problem here, since
 | ||||||
|  | -                         * that's how container managers usually protected their sysctls.) In all other cases
 | ||||||
|  | -                         * log an error and make the tool fail. */
 | ||||||
|  | -
 | ||||||
|  | -                        if (IN_SET(k, -EPERM, -EACCES, -EROFS, -ENOENT) || option->ignore_failure)
 | ||||||
|  | -                                log_notice_errno(k, "Couldn't write '%s' to '%s', ignoring: %m", option->value, option->key);
 | ||||||
|  | +                         * privileges and cannot write it, then log about the issue, and proceed without
 | ||||||
|  | +                         * failing. (EROFS is treated as a permission problem here, since that's how
 | ||||||
|  | +                         * container managers usually protected their sysctls.) In all other cases log an
 | ||||||
|  | +                         * error and make the tool fail. */
 | ||||||
|  | +
 | ||||||
|  | +                        if (option->ignore_failure || k == -EROFS || ERRNO_IS_PRIVILEGE(k))
 | ||||||
|  | +                                log_debug_errno(k, "Couldn't write '%s' to '%s', ignoring: %m", option->value, option->key);
 | ||||||
|  | +                        else if (k == -ENOENT)
 | ||||||
|  | +                                log_info_errno(k, "Couldn't write '%s' to '%s', ignoring: %m", option->value, option->key);
 | ||||||
|  |                          else { | ||||||
|  |                                  log_error_errno(k, "Couldn't write '%s' to '%s': %m", option->value, option->key); | ||||||
|  |                                  if (r == 0) | ||||||
| @ -0,0 +1,53 @@ | |||||||
|  | From 1f408c8d9739b1038012eeec7bf0f918c8095bc4 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com> | ||||||
|  | Date: Fri, 23 Sep 2022 19:00:22 +0200 | ||||||
|  | Subject: [PATCH] core: respect SELinuxContext= for socket creation | ||||||
|  | 
 | ||||||
|  | On socket creation respect the SELinuxContext= setting of the associated | ||||||
|  | service, such that the initial created socket has the same label as the | ||||||
|  | future process accepting the connection (since w.r.t SELinux sockets | ||||||
|  | normally have the same label as the owning process). | ||||||
|  | 
 | ||||||
|  | Triggered by #24702 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 599b384924bbef9f8f7fa5700c6fa35a404d9a98) | ||||||
|  | 
 | ||||||
|  | Related: #2136738 | ||||||
|  | ---
 | ||||||
|  |  src/core/socket.c | 15 ++++++++++++++- | ||||||
|  |  1 file changed, 14 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/socket.c b/src/core/socket.c
 | ||||||
|  | index 9d47ca2616..d1ca0a07c5 100644
 | ||||||
|  | --- a/src/core/socket.c
 | ||||||
|  | +++ b/src/core/socket.c
 | ||||||
|  | @@ -1427,6 +1427,7 @@ fail:
 | ||||||
|  |  static int socket_determine_selinux_label(Socket *s, char **ret) { | ||||||
|  |          Service *service; | ||||||
|  |          ExecCommand *c; | ||||||
|  | +        const char *exec_context;
 | ||||||
|  |          _cleanup_free_ char *path = NULL; | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  | @@ -1448,8 +1449,20 @@ static int socket_determine_selinux_label(Socket *s, char **ret) {
 | ||||||
|  |   | ||||||
|  |                  if (!UNIT_ISSET(s->service)) | ||||||
|  |                          goto no_label; | ||||||
|  | -
 | ||||||
|  |                  service = SERVICE(UNIT_DEREF(s->service)); | ||||||
|  | +
 | ||||||
|  | +                exec_context = service->exec_context.selinux_context;
 | ||||||
|  | +                if (exec_context) {
 | ||||||
|  | +                        char *con;
 | ||||||
|  | +
 | ||||||
|  | +                        con = strdup(exec_context);
 | ||||||
|  | +                        if (!con)
 | ||||||
|  | +                                return -ENOMEM;
 | ||||||
|  | +
 | ||||||
|  | +                        *ret = TAKE_PTR(con);
 | ||||||
|  | +                        return 0;
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  |                  c = service->exec_command[SERVICE_EXEC_START]; | ||||||
|  |                  if (!c) | ||||||
|  |                          goto no_label; | ||||||
| @ -0,0 +1,128 @@ | |||||||
|  | From 3f90090e70a5fa81bced17792fe08d9c46324da9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Ted X. Toth" <txtoth@flycast.org> | ||||||
|  | Date: Thu, 13 Oct 2022 12:58:26 -0700 | ||||||
|  | Subject: [PATCH] manager: use target process context to set socket context | ||||||
|  | 
 | ||||||
|  | Use target process context to set socket context when using SELinuxContextFromNet | ||||||
|  | not systemd's context. Currently when using the SELinuxContextFromNet option for | ||||||
|  | a socket activated services, systemd calls getcon_raw which returns init_t and | ||||||
|  | uses the resulting context to compute the context to be passed to the | ||||||
|  | setsockcreatecon call. A socket of type init_t is created and listened on and | ||||||
|  | this means that SELinux policy cannot be written to control which processes | ||||||
|  | (SELinux types) can connect to the socket since the ref policy allows all | ||||||
|  | 'types' to connect to sockets of the type init_t. When security accessors see | ||||||
|  | that any process can connect to a socket this raises serious concerns. I have | ||||||
|  | spoken with SELinux contributors in person and on the mailing list and the | ||||||
|  | consensus is that the best solution is to use the target executables context | ||||||
|  | when computing the sockets context in all cases. | ||||||
|  | 
 | ||||||
|  | [zjs review/comment: | ||||||
|  | 
 | ||||||
|  | This removes the branch that was added in 16115b0a7b7cdf08fb38084d857d572d8a9088dc. | ||||||
|  | 16115b0a7b7cdf08fb38084d857d572d8a9088dc did two things: it had the branch here | ||||||
|  | in 'socket_determine_selinux_label()' and a code in 'exec_child()' to call | ||||||
|  | 'label_get_child_mls_label(socket_fd, command->path, &label)'. | ||||||
|  | 
 | ||||||
|  | Before this patch, the flow was: | ||||||
|  | ''' | ||||||
|  | mac_selinux_get_child_mls_label: | ||||||
|  |   peercon = getpeercon_raw(socket_fd); | ||||||
|  |   if (!exec_label) | ||||||
|  |      exec_label = getfilecon_raw(exe); | ||||||
|  | 
 | ||||||
|  | socket_open_fds: | ||||||
|  |   if (params->selinux_context_net)                 # | ||||||
|  |      label = mac_selinux_get_our_label();          #  this part is removed | ||||||
|  |   else                                             # | ||||||
|  |      label = mac_selinux_get_create_label_from_exe(path); | ||||||
|  |   socket_address_listen_in_cgroup(s, &p->address, label); | ||||||
|  | 
 | ||||||
|  | exec_child(): | ||||||
|  |    exec_context = mac_selinux_get_child_mls_label(fd, executable, context->selinux_context); | ||||||
|  |    setexeccon(exec_context); | ||||||
|  | ''' | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 29dbc62d74f7b7881dc3136e68e03a03ea055b36) | ||||||
|  | 
 | ||||||
|  | Resolves: #2136738 | ||||||
|  | ---
 | ||||||
|  |  src/core/socket.c | 58 ++++++++++++++++++++--------------------------- | ||||||
|  |  1 file changed, 24 insertions(+), 34 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/socket.c b/src/core/socket.c
 | ||||||
|  | index d1ca0a07c5..8aa5463b25 100644
 | ||||||
|  | --- a/src/core/socket.c
 | ||||||
|  | +++ b/src/core/socket.c
 | ||||||
|  | @@ -1434,47 +1434,37 @@ static int socket_determine_selinux_label(Socket *s, char **ret) {
 | ||||||
|  |          assert(s); | ||||||
|  |          assert(ret); | ||||||
|  |   | ||||||
|  | -        if (s->selinux_context_from_net) {
 | ||||||
|  | -                /* If this is requested, get label from the network label */
 | ||||||
|  | -
 | ||||||
|  | -                r = mac_selinux_get_our_label(ret);
 | ||||||
|  | -                if (r == -EOPNOTSUPP)
 | ||||||
|  | -                        goto no_label;
 | ||||||
|  | -
 | ||||||
|  | -        } else {
 | ||||||
|  | -                /* Otherwise, get it from the executable we are about to start */
 | ||||||
|  | -                r = socket_instantiate_service(s);
 | ||||||
|  | -                if (r < 0)
 | ||||||
|  | -                        return r;
 | ||||||
|  | +        r = socket_instantiate_service(s);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                return r;
 | ||||||
|  |   | ||||||
|  | -                if (!UNIT_ISSET(s->service))
 | ||||||
|  | -                        goto no_label;
 | ||||||
|  | -                service = SERVICE(UNIT_DEREF(s->service));
 | ||||||
|  | +        if (!UNIT_ISSET(s->service))
 | ||||||
|  | +                goto no_label;
 | ||||||
|  | +        service = SERVICE(UNIT_DEREF(s->service));
 | ||||||
|  |   | ||||||
|  | -                exec_context = service->exec_context.selinux_context;
 | ||||||
|  | -                if (exec_context) {
 | ||||||
|  | -                        char *con;
 | ||||||
|  | +        exec_context = service->exec_context.selinux_context;
 | ||||||
|  | +        if (exec_context) {
 | ||||||
|  | +                char *con;
 | ||||||
|  |   | ||||||
|  | -                        con = strdup(exec_context);
 | ||||||
|  | -                        if (!con)
 | ||||||
|  | -                                return -ENOMEM;
 | ||||||
|  | +                con = strdup(exec_context);
 | ||||||
|  | +                if (!con)
 | ||||||
|  | +                        return -ENOMEM;
 | ||||||
|  |   | ||||||
|  | -                        *ret = TAKE_PTR(con);
 | ||||||
|  | -                        return 0;
 | ||||||
|  | -                }
 | ||||||
|  | +                *ret = TAKE_PTR(con);
 | ||||||
|  | +                return 0;
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  | -                c = service->exec_command[SERVICE_EXEC_START];
 | ||||||
|  | -                if (!c)
 | ||||||
|  | -                        goto no_label;
 | ||||||
|  | +        c = service->exec_command[SERVICE_EXEC_START];
 | ||||||
|  | +        if (!c)
 | ||||||
|  | +                goto no_label;
 | ||||||
|  |   | ||||||
|  | -                r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path);
 | ||||||
|  | -                if (r < 0)
 | ||||||
|  | -                        goto no_label;
 | ||||||
|  | +        r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                goto no_label;
 | ||||||
|  |   | ||||||
|  | -                r = mac_selinux_get_create_label_from_exe(path, ret);
 | ||||||
|  | -                if (IN_SET(r, -EPERM, -EOPNOTSUPP))
 | ||||||
|  | -                        goto no_label;
 | ||||||
|  | -        }
 | ||||||
|  | +        r = mac_selinux_get_create_label_from_exe(path, ret);
 | ||||||
|  | +        if (IN_SET(r, -EPERM, -EOPNOTSUPP))
 | ||||||
|  | +                goto no_label;
 | ||||||
|  |   | ||||||
|  |          return r; | ||||||
|  |   | ||||||
							
								
								
									
										142
									
								
								SOURCES/0848-virt-detect-Amazon-EC2-Nitro-instance.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								SOURCES/0848-virt-detect-Amazon-EC2-Nitro-instance.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,142 @@ | |||||||
|  | From 6ffd3de2ccc5901974f292c9694829e25441060d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Bertrand Jacquin <bertrand@jacquin.bzh> | ||||||
|  | Date: Sun, 11 Oct 2020 21:25:00 +0100 | ||||||
|  | Subject: [PATCH] virt: detect Amazon EC2 Nitro instance | ||||||
|  | 
 | ||||||
|  | Amazon EC2 Nitro hypervisor is technically based on KVM[1], which | ||||||
|  | systemd-detect-virt identify propely from CPUID. However the lack of | ||||||
|  | CPUID on aarch64 (A1, T4 instance type) prevents a correct | ||||||
|  | identification, impacting hostnamectl and systemd-random-seed. Instead | ||||||
|  | it's possible to identify virtualization from DMI vendor ID. | ||||||
|  | 
 | ||||||
|  | Prior to this commit: | ||||||
|  |   # hostnamectl | ||||||
|  |      Static hostname: n/a | ||||||
|  |   Transient hostname: ip-10-97-8-12 | ||||||
|  |            Icon name: computer | ||||||
|  |           Machine ID: 8e3772fbcfa3dd6f330a12ff5df5a63b | ||||||
|  |              Boot ID: b7b7e2fe0079448db664839df59f9817 | ||||||
|  |     Operating System: Gentoo/Linux | ||||||
|  |               Kernel: Linux 5.4.69-longterm | ||||||
|  |         Architecture: arm64 | ||||||
|  | 
 | ||||||
|  | After this commit: | ||||||
|  |   # hostnamectl | ||||||
|  |      Static hostname: n/a | ||||||
|  |   Transient hostname: ip-10-97-8-12 | ||||||
|  |            Icon name: computer-vm | ||||||
|  |              Chassis: vm | ||||||
|  |           Machine ID: 8e3772fbcfa3dd6f330a12ff5df5a63b | ||||||
|  |              Boot ID: bd04da57084e41078f20541101867113 | ||||||
|  |       Virtualization: amazon | ||||||
|  |     Operating System: Gentoo/Linux | ||||||
|  |               Kernel: Linux 5.4.69-longterm | ||||||
|  |         Architecture: arm64 | ||||||
|  | 
 | ||||||
|  | [1] https://aws.amazon.com/ec2/faqs/ | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit b6eca3731dd92b009b182f188936e1c2544574da) | ||||||
|  | 
 | ||||||
|  | Resolves: #2117948 | ||||||
|  | ---
 | ||||||
|  |  man/systemd-detect-virt.xml | 7 ++++++- | ||||||
|  |  man/systemd.unit.xml        | 1 + | ||||||
|  |  src/basic/virt.c            | 8 +++++--- | ||||||
|  |  src/basic/virt.h            | 1 + | ||||||
|  |  src/test/test-condition.c   | 1 + | ||||||
|  |  5 files changed, 14 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml
 | ||||||
|  | index 6beb2c2aa1..61c210e24d 100644
 | ||||||
|  | --- a/man/systemd-detect-virt.xml
 | ||||||
|  | +++ b/man/systemd-detect-virt.xml
 | ||||||
|  | @@ -72,7 +72,12 @@
 | ||||||
|  |   | ||||||
|  |            <row> | ||||||
|  |              <entry><varname>kvm</varname></entry> | ||||||
|  | -            <entry>Linux KVM kernel virtual machine, with whatever software, except Oracle Virtualbox</entry>
 | ||||||
|  | +            <entry>Linux KVM kernel virtual machine, in combination with QEMU. Not used for other virtualizers using the KVM interfaces, such as Oracle VirtualBox or Amazon EC2 Nitro, see below.</entry>
 | ||||||
|  | +          </row>
 | ||||||
|  | +
 | ||||||
|  | +          <row>
 | ||||||
|  | +            <entry><varname>amazon</varname></entry>
 | ||||||
|  | +            <entry>Amazon EC2 Nitro using Linux KVM</entry>
 | ||||||
|  |            </row> | ||||||
|  |   | ||||||
|  |            <row> | ||||||
|  | diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
 | ||||||
|  | index 6f213ccd56..5207a5bb3c 100644
 | ||||||
|  | --- a/man/systemd.unit.xml
 | ||||||
|  | +++ b/man/systemd.unit.xml
 | ||||||
|  | @@ -1068,6 +1068,7 @@
 | ||||||
|  |          virtualization solution, or one of | ||||||
|  |          <varname>qemu</varname>, | ||||||
|  |          <varname>kvm</varname>, | ||||||
|  | +        <literal>amazon</literal>,
 | ||||||
|  |          <varname>zvm</varname>, | ||||||
|  |          <varname>vmware</varname>, | ||||||
|  |          <varname>microsoft</varname>, | ||||||
|  | diff --git a/src/basic/virt.c b/src/basic/virt.c
 | ||||||
|  | index 8d862b6d67..78c68d66e0 100644
 | ||||||
|  | --- a/src/basic/virt.c
 | ||||||
|  | +++ b/src/basic/virt.c
 | ||||||
|  | @@ -147,6 +147,7 @@ static int detect_vm_dmi(void) {
 | ||||||
|  |                  int id; | ||||||
|  |          } dmi_vendor_table[] = { | ||||||
|  |                  { "KVM",           VIRTUALIZATION_KVM       }, | ||||||
|  | +                { "Amazon EC2",          VIRTUALIZATION_AMAZON    },
 | ||||||
|  |                  { "QEMU",          VIRTUALIZATION_QEMU      }, | ||||||
|  |                  /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ | ||||||
|  |                  { "VMware",        VIRTUALIZATION_VMWARE    }, | ||||||
|  | @@ -339,8 +340,8 @@ int detect_vm(void) {
 | ||||||
|  |   | ||||||
|  |          /* We have to use the correct order here: | ||||||
|  |           * | ||||||
|  | -         * → First, try to detect Oracle Virtualbox, even if it uses KVM, as well as Xen even if it cloaks as Microsoft
 | ||||||
|  | -         *   Hyper-V.
 | ||||||
|  | +         * → First, try to detect Oracle Virtualbox and Amazon EC2 Nitro, even if they use KVM, as well as Xen even if
 | ||||||
|  | +         *   it cloaks as Microsoft Hyper-V.
 | ||||||
|  |           * | ||||||
|  |           * → Second, try to detect from CPUID, this will report KVM for whatever software is used even if info in DMI is | ||||||
|  |           *   overwritten. | ||||||
|  | @@ -348,7 +349,7 @@ int detect_vm(void) {
 | ||||||
|  |           * → Third, try to detect from DMI. */ | ||||||
|  |   | ||||||
|  |          dmi = detect_vm_dmi(); | ||||||
|  | -        if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN)) {
 | ||||||
|  | +        if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN, VIRTUALIZATION_AMAZON)) {
 | ||||||
|  |                  r = dmi; | ||||||
|  |                  goto finish; | ||||||
|  |          } | ||||||
|  | @@ -631,6 +632,7 @@ int running_in_chroot(void) {
 | ||||||
|  |  static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { | ||||||
|  |          [VIRTUALIZATION_NONE] = "none", | ||||||
|  |          [VIRTUALIZATION_KVM] = "kvm", | ||||||
|  | +        [VIRTUALIZATION_AMAZON] = "amazon",
 | ||||||
|  |          [VIRTUALIZATION_QEMU] = "qemu", | ||||||
|  |          [VIRTUALIZATION_BOCHS] = "bochs", | ||||||
|  |          [VIRTUALIZATION_XEN] = "xen", | ||||||
|  | diff --git a/src/basic/virt.h b/src/basic/virt.h
 | ||||||
|  | index 640b3ed779..ed4ff063e0 100644
 | ||||||
|  | --- a/src/basic/virt.h
 | ||||||
|  | +++ b/src/basic/virt.h
 | ||||||
|  | @@ -10,6 +10,7 @@ enum {
 | ||||||
|  |   | ||||||
|  |          VIRTUALIZATION_VM_FIRST, | ||||||
|  |          VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST, | ||||||
|  | +        VIRTUALIZATION_AMAZON,
 | ||||||
|  |          VIRTUALIZATION_QEMU, | ||||||
|  |          VIRTUALIZATION_BOCHS, | ||||||
|  |          VIRTUALIZATION_XEN, | ||||||
|  | diff --git a/src/test/test-condition.c b/src/test/test-condition.c
 | ||||||
|  | index 24395dafc6..29ea63c4ff 100644
 | ||||||
|  | --- a/src/test/test-condition.c
 | ||||||
|  | +++ b/src/test/test-condition.c
 | ||||||
|  | @@ -510,6 +510,7 @@ static void test_condition_test_virtualization(void) {
 | ||||||
|  |   | ||||||
|  |          NULSTR_FOREACH(virt, | ||||||
|  |                         "kvm\0" | ||||||
|  | +                       "amazon\0"
 | ||||||
|  |                         "qemu\0" | ||||||
|  |                         "bochs\0" | ||||||
|  |                         "xen\0" | ||||||
| @ -0,0 +1,37 @@ | |||||||
|  | From e320f72150829228f10ec24f3fba34d5377c5120 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Bertrand Jacquin <bertrand@jacquin.bzh> | ||||||
|  | Date: Sun, 11 Oct 2020 22:25:56 +0100 | ||||||
|  | Subject: [PATCH] machine-id-setup: generate machine-id from DMI product ID on | ||||||
|  |  Amazon EC2 | ||||||
|  | 
 | ||||||
|  | Amazon EC2 Nitro hypervisor is technically based on KVM[1]. | ||||||
|  | 
 | ||||||
|  | [1] https://aws.amazon.com/ec2/faqs/ | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 382a46d129899ca9027b07c325102cab173dd563) | ||||||
|  | 
 | ||||||
|  | Related: #2117948 | ||||||
|  | ---
 | ||||||
|  |  src/core/machine-id-setup.c | 8 ++++---- | ||||||
|  |  1 file changed, 4 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
 | ||||||
|  | index 11528f83c4..fe2abc4e68 100644
 | ||||||
|  | --- a/src/core/machine-id-setup.c
 | ||||||
|  | +++ b/src/core/machine-id-setup.c
 | ||||||
|  | @@ -57,11 +57,11 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) {
 | ||||||
|  |                                  return 0; | ||||||
|  |                          } | ||||||
|  |   | ||||||
|  | -                } else if (detect_vm() == VIRTUALIZATION_KVM) {
 | ||||||
|  | +                } else if (IN_SET(detect_vm(), VIRTUALIZATION_KVM, VIRTUALIZATION_AMAZON, VIRTUALIZATION_QEMU)) {
 | ||||||
|  |   | ||||||
|  | -                        /* If we are not running in a container, see if we are
 | ||||||
|  | -                         * running in qemu/kvm and a machine ID was passed in
 | ||||||
|  | -                         * via -uuid on the qemu/kvm command line */
 | ||||||
|  | +                        /* If we are not running in a container, see if we are running in a VM that provides
 | ||||||
|  | +                         * a system UUID via the SMBIOS/DMI interfaces.  Such environments include QEMU/KVM
 | ||||||
|  | +                         * with the -uuid on the qemu command line or the Amazon EC2 Nitro hypervisor. */
 | ||||||
|  |   | ||||||
|  |                          if (id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, ret) >= 0) { | ||||||
|  |                                  log_info("Initializing machine ID from KVM UUID."); | ||||||
| @ -0,0 +1,134 @@ | |||||||
|  | From efa2cdb699df3e5d5d7180e50f3ebfff74788c5c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Tue, 7 Jan 2020 11:49:39 +0900 | ||||||
|  | Subject: [PATCH] virt: use string table to detect VM or container | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 735ea55f5cd87a82757a8911edd80fba799b46ee) | ||||||
|  | 
 | ||||||
|  | Related: #2117948 | ||||||
|  | ---
 | ||||||
|  |  src/basic/virt.c | 73 ++++++++++++++++++++++-------------------------- | ||||||
|  |  1 file changed, 33 insertions(+), 40 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/basic/virt.c b/src/basic/virt.c
 | ||||||
|  | index 78c68d66e0..6e4c702051 100644
 | ||||||
|  | --- a/src/basic/virt.c
 | ||||||
|  | +++ b/src/basic/virt.c
 | ||||||
|  | @@ -22,27 +22,26 @@
 | ||||||
|  |  #include "string-util.h" | ||||||
|  |  #include "virt.h" | ||||||
|  |   | ||||||
|  | +static const char *const vm_table[_VIRTUALIZATION_MAX] = {
 | ||||||
|  | +        [VIRTUALIZATION_XEN]       = "XenVMMXenVMM",
 | ||||||
|  | +        [VIRTUALIZATION_KVM]       = "KVMKVMKVM",
 | ||||||
|  | +        [VIRTUALIZATION_QEMU]      = "TCGTCGTCGTCG",
 | ||||||
|  | +        /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
 | ||||||
|  | +        [VIRTUALIZATION_VMWARE]    = "VMwareVMware",
 | ||||||
|  | +        /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
 | ||||||
|  | +        [VIRTUALIZATION_MICROSOFT] = "Microsoft Hv",
 | ||||||
|  | +        /* https://wiki.freebsd.org/bhyve */
 | ||||||
|  | +        [VIRTUALIZATION_BHYVE]     = "bhyve bhyve ",
 | ||||||
|  | +        [VIRTUALIZATION_QNX]       = "QNXQVMBSQG",
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  | +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(vm, int);
 | ||||||
|  | +
 | ||||||
|  |  static int detect_vm_cpuid(void) { | ||||||
|  |   | ||||||
|  |          /* CPUID is an x86 specific interface. */ | ||||||
|  |  #if defined(__i386__) || defined(__x86_64__) | ||||||
|  |   | ||||||
|  | -        static const struct {
 | ||||||
|  | -                const char *cpuid;
 | ||||||
|  | -                int id;
 | ||||||
|  | -        } cpuid_vendor_table[] = {
 | ||||||
|  | -                { "XenVMMXenVMM", VIRTUALIZATION_XEN       },
 | ||||||
|  | -                { "KVMKVMKVM",    VIRTUALIZATION_KVM       },
 | ||||||
|  | -                { "TCGTCGTCGTCG", VIRTUALIZATION_QEMU      },
 | ||||||
|  | -                /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
 | ||||||
|  | -                { "VMwareVMware", VIRTUALIZATION_VMWARE    },
 | ||||||
|  | -                /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
 | ||||||
|  | -                { "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
 | ||||||
|  | -                /* https://wiki.freebsd.org/bhyve */
 | ||||||
|  | -                { "bhyve bhyve ", VIRTUALIZATION_BHYVE     },
 | ||||||
|  | -                { "QNXQVMBSQG",   VIRTUALIZATION_QNX       },
 | ||||||
|  | -        };
 | ||||||
|  | -
 | ||||||
|  |          uint32_t eax, ebx, ecx, edx; | ||||||
|  |          bool hypervisor; | ||||||
|  |   | ||||||
|  | @@ -59,7 +58,7 @@ static int detect_vm_cpuid(void) {
 | ||||||
|  |                          uint32_t sig32[3]; | ||||||
|  |                          char text[13]; | ||||||
|  |                  } sig = {}; | ||||||
|  | -                unsigned j;
 | ||||||
|  | +                int v;
 | ||||||
|  |   | ||||||
|  |                  /* There is a hypervisor, see what it is */ | ||||||
|  |                  __cpuid(0x40000000U, eax, ebx, ecx, edx); | ||||||
|  | @@ -70,11 +69,11 @@ static int detect_vm_cpuid(void) {
 | ||||||
|  |   | ||||||
|  |                  log_debug("Virtualization found, CPUID=%s", sig.text); | ||||||
|  |   | ||||||
|  | -                for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
 | ||||||
|  | -                        if (streq(sig.text, cpuid_vendor_table[j].cpuid))
 | ||||||
|  | -                                return cpuid_vendor_table[j].id;
 | ||||||
|  | +                v = vm_from_string(sig.text);
 | ||||||
|  | +                if (v < 0)
 | ||||||
|  | +                        return VIRTUALIZATION_VM_OTHER;
 | ||||||
|  |   | ||||||
|  | -                return VIRTUALIZATION_VM_OTHER;
 | ||||||
|  | +                return v;
 | ||||||
|  |          } | ||||||
|  |  #endif | ||||||
|  |          log_debug("No virtualization found in CPUID"); | ||||||
|  | @@ -434,22 +433,20 @@ finish:
 | ||||||
|  |          return r; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -int detect_container(void) {
 | ||||||
|  | -        static const struct {
 | ||||||
|  | -                const char *value;
 | ||||||
|  | -                int id;
 | ||||||
|  | -        } value_table[] = {
 | ||||||
|  | -                { "lxc",            VIRTUALIZATION_LXC            },
 | ||||||
|  | -                { "lxc-libvirt",    VIRTUALIZATION_LXC_LIBVIRT    },
 | ||||||
|  | -                { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN },
 | ||||||
|  | -                { "docker",         VIRTUALIZATION_DOCKER         },
 | ||||||
|  | -                { "rkt",            VIRTUALIZATION_RKT            },
 | ||||||
|  | -        };
 | ||||||
|  | +static const char *const container_table[_VIRTUALIZATION_MAX] = {
 | ||||||
|  | +        [VIRTUALIZATION_LXC]            = "lxc",
 | ||||||
|  | +        [VIRTUALIZATION_LXC_LIBVIRT]    = "lxc-libvirt",
 | ||||||
|  | +        [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
 | ||||||
|  | +        [VIRTUALIZATION_DOCKER]         = "docker",
 | ||||||
|  | +        [VIRTUALIZATION_RKT]            = "rkt",
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  | +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
 | ||||||
|  |   | ||||||
|  | +int detect_container(void) {
 | ||||||
|  |          static thread_local int cached_found = _VIRTUALIZATION_INVALID; | ||||||
|  |          _cleanup_free_ char *m = NULL; | ||||||
|  |          const char *e = NULL; | ||||||
|  | -        unsigned j;
 | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  |          if (cached_found >= 0) | ||||||
|  | @@ -522,13 +519,9 @@ int detect_container(void) {
 | ||||||
|  |          goto finish; | ||||||
|  |   | ||||||
|  |  translate_name: | ||||||
|  | -        for (j = 0; j < ELEMENTSOF(value_table); j++)
 | ||||||
|  | -                if (streq(e, value_table[j].value)) {
 | ||||||
|  | -                        r = value_table[j].id;
 | ||||||
|  | -                        goto finish;
 | ||||||
|  | -                }
 | ||||||
|  | -
 | ||||||
|  | -        r = VIRTUALIZATION_CONTAINER_OTHER;
 | ||||||
|  | +        r = container_from_string(e);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                r = VIRTUALIZATION_CONTAINER_OTHER;
 | ||||||
|  |   | ||||||
|  |  finish: | ||||||
|  |          log_debug("Found container virtualization %s.", virtualization_to_string(r)); | ||||||
| @ -0,0 +1,194 @@ | |||||||
|  | From 7a3843972ea290daf1bec5e1133db654749b8c02 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Franck Bui <fbui@suse.com> | ||||||
|  | Date: Tue, 22 Oct 2019 16:09:21 +0200 | ||||||
|  | Subject: [PATCH] fileio: introduce read_full_virtual_file() for reading | ||||||
|  |  virtual files in sysfs, procfs | ||||||
|  | 
 | ||||||
|  | Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work | ||||||
|  | with two sorts of virtual files. | ||||||
|  | 
 | ||||||
|  | One sort uses "seq_file", and the results of the first read are buffered for | ||||||
|  | the second read. The other sort uses "raw" reads which always go direct to the | ||||||
|  | device. | ||||||
|  | 
 | ||||||
|  | In the later case, the content of the virtual file must be retrieved with a | ||||||
|  | single read otherwise subsequent read might get the new value instead of | ||||||
|  | finding EOF immediately. That's the reason why the usage of fread(3) is | ||||||
|  | prohibited in this case as it always performs a second call to read(2) looking | ||||||
|  | for EOF which is subject to the race described previously. | ||||||
|  | 
 | ||||||
|  | Fixes: #13585. | ||||||
|  | (cherry picked from commit 21b40f16622f171a9969dc334d74fb5eb2f575c2) | ||||||
|  | 
 | ||||||
|  | Related: #2117948 | ||||||
|  | ---
 | ||||||
|  |  src/basic/fileio.c                   | 115 ++++++++++++++++++++++++++- | ||||||
|  |  src/basic/fileio.h                   |   1 + | ||||||
|  |  src/libsystemd/sd-device/sd-device.c |   2 +- | ||||||
|  |  3 files changed, 113 insertions(+), 5 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/basic/fileio.c b/src/basic/fileio.c
 | ||||||
|  | index 6b0bad5b71..733fb42463 100644
 | ||||||
|  | --- a/src/basic/fileio.c
 | ||||||
|  | +++ b/src/basic/fileio.c
 | ||||||
|  | @@ -276,6 +276,113 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
 | ||||||
|  |          return 1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) {
 | ||||||
|  | +        _cleanup_free_ char *buf = NULL;
 | ||||||
|  | +        _cleanup_close_ int fd = -1;
 | ||||||
|  | +        struct stat st;
 | ||||||
|  | +        size_t n, size;
 | ||||||
|  | +        int n_retries;
 | ||||||
|  | +        char *p;
 | ||||||
|  | +
 | ||||||
|  | +        assert(ret_contents);
 | ||||||
|  | +
 | ||||||
|  | +        /* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work
 | ||||||
|  | +         * with two sorts of virtual files. One sort uses "seq_file", and the results of
 | ||||||
|  | +         * the first read are buffered for the second read. The other sort uses "raw"
 | ||||||
|  | +         * reads which always go direct to the device. In the latter case, the content of
 | ||||||
|  | +         * the virtual file must be retrieved with a single read otherwise a second read
 | ||||||
|  | +         * might get the new value instead of finding EOF immediately. That's the reason
 | ||||||
|  | +         * why the usage of fread(3) is prohibited in this case as it always performs a
 | ||||||
|  | +         * second call to read(2) looking for EOF. See issue 13585. */
 | ||||||
|  | +
 | ||||||
|  | +        fd = open(filename, O_RDONLY|O_CLOEXEC);
 | ||||||
|  | +        if (fd < 0)
 | ||||||
|  | +                return -errno;
 | ||||||
|  | +
 | ||||||
|  | +        /* Start size for files in /proc which usually report a file size of 0. */
 | ||||||
|  | +        size = LINE_MAX / 2;
 | ||||||
|  | +
 | ||||||
|  | +        /* Limit the number of attempts to read the number of bytes returned by fstat(). */
 | ||||||
|  | +        n_retries = 3;
 | ||||||
|  | +
 | ||||||
|  | +        for (;;) {
 | ||||||
|  | +                if (n_retries <= 0)
 | ||||||
|  | +                        return -EIO;
 | ||||||
|  | +
 | ||||||
|  | +                if (fstat(fd, &st) < 0)
 | ||||||
|  | +                        return -errno;
 | ||||||
|  | +
 | ||||||
|  | +                if (!S_ISREG(st.st_mode))
 | ||||||
|  | +                        return -EBADF;
 | ||||||
|  | +
 | ||||||
|  | +                /* Be prepared for files from /proc which generally report a file size of 0. */
 | ||||||
|  | +                if (st.st_size > 0) {
 | ||||||
|  | +                        size = st.st_size;
 | ||||||
|  | +                        n_retries--;
 | ||||||
|  | +                } else
 | ||||||
|  | +                        size = size * 2;
 | ||||||
|  | +
 | ||||||
|  | +                if (size > READ_FULL_BYTES_MAX)
 | ||||||
|  | +                        return -E2BIG;
 | ||||||
|  | +
 | ||||||
|  | +                p = realloc(buf, size + 1);
 | ||||||
|  | +                if (!p)
 | ||||||
|  | +                        return -ENOMEM;
 | ||||||
|  | +                buf = TAKE_PTR(p);
 | ||||||
|  | +
 | ||||||
|  | +                for (;;) {
 | ||||||
|  | +                        ssize_t k;
 | ||||||
|  | +
 | ||||||
|  | +                        /* Read one more byte so we can detect whether the content of the
 | ||||||
|  | +                         * file has already changed or the guessed size for files from /proc
 | ||||||
|  | +                         * wasn't large enough . */
 | ||||||
|  | +                        k = read(fd, buf, size + 1);
 | ||||||
|  | +                        if (k >= 0) {
 | ||||||
|  | +                                n = k;
 | ||||||
|  | +                                break;
 | ||||||
|  | +                        }
 | ||||||
|  | +
 | ||||||
|  | +                        if (errno != -EINTR)
 | ||||||
|  | +                                return -errno;
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                /* Consider a short read as EOF */
 | ||||||
|  | +                if (n <= size)
 | ||||||
|  | +                        break;
 | ||||||
|  | +
 | ||||||
|  | +                /* Hmm... either we read too few bytes from /proc or less likely the content
 | ||||||
|  | +                 * of the file might have been changed (and is now bigger) while we were
 | ||||||
|  | +                 * processing, let's try again either with a bigger guessed size or the new
 | ||||||
|  | +                 * file size. */
 | ||||||
|  | +
 | ||||||
|  | +                if (lseek(fd, 0, SEEK_SET) < 0)
 | ||||||
|  | +                        return -errno;
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        if (n < size) {
 | ||||||
|  | +                p = realloc(buf, n + 1);
 | ||||||
|  | +                if (!p)
 | ||||||
|  | +                        return -ENOMEM;
 | ||||||
|  | +                buf = TAKE_PTR(p);
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        if (!ret_size) {
 | ||||||
|  | +                /* Safety check: if the caller doesn't want to know the size of what we
 | ||||||
|  | +                 * just read it will rely on the trailing NUL byte. But if there's an
 | ||||||
|  | +                 * embedded NUL byte, then we should refuse operation as otherwise
 | ||||||
|  | +                 * there'd be ambiguity about what we just read. */
 | ||||||
|  | +
 | ||||||
|  | +                if (memchr(buf, 0, n))
 | ||||||
|  | +                        return -EBADMSG;
 | ||||||
|  | +        } else
 | ||||||
|  | +                *ret_size = n;
 | ||||||
|  | +
 | ||||||
|  | +        buf[n] = 0;
 | ||||||
|  | +        *ret_contents = TAKE_PTR(buf);
 | ||||||
|  | +
 | ||||||
|  | +        return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int read_full_stream(FILE *f, char **contents, size_t *size) { | ||||||
|  |          _cleanup_free_ char *buf = NULL; | ||||||
|  |          struct stat st; | ||||||
|  | @@ -300,9 +407,9 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
 | ||||||
|  |                          if (st.st_size > READ_FULL_BYTES_MAX) | ||||||
|  |                                  return -E2BIG; | ||||||
|  |   | ||||||
|  | -                        /* Start with the right file size, but be prepared for files from /proc which generally report a file
 | ||||||
|  | -                         * size of 0. Note that we increase the size to read here by one, so that the first read attempt
 | ||||||
|  | -                         * already makes us notice the EOF. */
 | ||||||
|  | +                        /* Start with the right file size. Note that we increase the size
 | ||||||
|  | +                         * to read here by one, so that the first read attempt already
 | ||||||
|  | +                         * makes us notice the EOF. */
 | ||||||
|  |                          if (st.st_size > 0) | ||||||
|  |                                  n = st.st_size + 1; | ||||||
|  |                  } | ||||||
|  | @@ -986,7 +1093,7 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
 | ||||||
|  |          assert(pattern); | ||||||
|  |          assert(field); | ||||||
|  |   | ||||||
|  | -        r = read_full_file(filename, &status, NULL);
 | ||||||
|  | +        r = read_full_virtual_file(filename, &status, NULL);
 | ||||||
|  |          if (r < 0) | ||||||
|  |                  return r; | ||||||
|  |   | ||||||
|  | diff --git a/src/basic/fileio.h b/src/basic/fileio.h
 | ||||||
|  | index 77e6206e95..c6ad375b8d 100644
 | ||||||
|  | --- a/src/basic/fileio.h
 | ||||||
|  | +++ b/src/basic/fileio.h
 | ||||||
|  | @@ -38,6 +38,7 @@ int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *f
 | ||||||
|  |  int read_one_line_file(const char *fn, char **line); | ||||||
|  |  int read_full_file(const char *fn, char **contents, size_t *size); | ||||||
|  |  int read_full_stream(FILE *f, char **contents, size_t *size); | ||||||
|  | +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size);
 | ||||||
|  |   | ||||||
|  |  int verify_file(const char *fn, const char *blob, bool accept_extra_nl); | ||||||
|  |   | ||||||
|  | diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
 | ||||||
|  | index be29053f8c..49750ba9d7 100644
 | ||||||
|  | --- a/src/libsystemd/sd-device/sd-device.c
 | ||||||
|  | +++ b/src/libsystemd/sd-device/sd-device.c
 | ||||||
|  | @@ -1798,7 +1798,7 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
 | ||||||
|  |                  size_t size; | ||||||
|  |   | ||||||
|  |                  /* read attribute value */ | ||||||
|  | -                r = read_full_file(path, &value, &size);
 | ||||||
|  | +                r = read_full_virtual_file(path, &value, &size);
 | ||||||
|  |                  if (r < 0) | ||||||
|  |                          return r; | ||||||
|  |   | ||||||
| @ -0,0 +1,118 @@ | |||||||
|  | From 44cbd79562ed55a8b0f2e5b5dc708265568ed9f8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Noah Meyerhans <nmeyerha@amazon.com> | ||||||
|  | Date: Fri, 30 Apr 2021 09:30:52 -0700 | ||||||
|  | Subject: [PATCH] Use BIOS characteristics to distinguish EC2 bare-metal from | ||||||
|  |  VMs | ||||||
|  | 
 | ||||||
|  | DMI vendor information fields do not provide enough information for us to | ||||||
|  | distinguish between Amazon EC2 virtual machines and bare-metal instances. | ||||||
|  | SMBIOS provides a BIOS Information | ||||||
|  | table (https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf | ||||||
|  | Ch. 7) that provides a field to indicate that the current machine is a virtual | ||||||
|  | machine.  On EC2 virtual machine instances, this field is set, while bare-metal | ||||||
|  | instances leave this unset, so we inspect the field via the kernel's | ||||||
|  | /sys/firemware/dmi/entries interface. | ||||||
|  | 
 | ||||||
|  | Fixes #18929 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit ce35037928f4c4c931088256853f07804ec7d235) | ||||||
|  | 
 | ||||||
|  | Related: #2117948 | ||||||
|  | ---
 | ||||||
|  |  src/basic/virt.c | 65 +++++++++++++++++++++++++++++++++++++++++++++--- | ||||||
|  |  1 file changed, 61 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/basic/virt.c b/src/basic/virt.c
 | ||||||
|  | index 6e4c702051..00d1c894e6 100644
 | ||||||
|  | --- a/src/basic/virt.c
 | ||||||
|  | +++ b/src/basic/virt.c
 | ||||||
|  | @@ -22,6 +22,12 @@
 | ||||||
|  |  #include "string-util.h" | ||||||
|  |  #include "virt.h" | ||||||
|  |   | ||||||
|  | +enum {
 | ||||||
|  | +      SMBIOS_VM_BIT_SET,
 | ||||||
|  | +      SMBIOS_VM_BIT_UNSET,
 | ||||||
|  | +      SMBIOS_VM_BIT_UNKNOWN,
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  |  static const char *const vm_table[_VIRTUALIZATION_MAX] = { | ||||||
|  |          [VIRTUALIZATION_XEN]       = "XenVMMXenVMM", | ||||||
|  |          [VIRTUALIZATION_KVM]       = "KVMKVMKVM", | ||||||
|  | @@ -131,9 +137,8 @@ static int detect_vm_device_tree(void) {
 | ||||||
|  |  #endif | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int detect_vm_dmi(void) {
 | ||||||
|  |  #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) | ||||||
|  | -
 | ||||||
|  | +static int detect_vm_dmi_vendor(void) {
 | ||||||
|  |          static const char *const dmi_vendors[] = { | ||||||
|  |                  "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */ | ||||||
|  |                  "/sys/class/dmi/id/sys_vendor", | ||||||
|  | @@ -179,11 +184,63 @@ static int detect_vm_dmi(void) {
 | ||||||
|  |                                  return dmi_vendor_table[j].id; | ||||||
|  |                          } | ||||||
|  |          } | ||||||
|  | -#endif
 | ||||||
|  | +        return VIRTUALIZATION_NONE;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int detect_vm_smbios(void) {
 | ||||||
|  | +        /* The SMBIOS BIOS Charateristics Extension Byte 2 (Section 2.1.2.2 of
 | ||||||
|  | +         * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf), specifies that
 | ||||||
|  | +         * the 4th bit being set indicates a VM. The BIOS Characteristics table is exposed via the kernel in
 | ||||||
|  | +         * /sys/firmware/dmi/entries/0-0. Note that in the general case, this bit being unset should not
 | ||||||
|  | +         * imply that the system is running on bare-metal.  For example, QEMU 3.1.0 (with or without KVM)
 | ||||||
|  | +         * with SeaBIOS does not set this bit. */
 | ||||||
|  | +        _cleanup_free_ char *s = NULL;
 | ||||||
|  | +        size_t readsize;
 | ||||||
|  | +        int r;
 | ||||||
|  | +
 | ||||||
|  | +        r = read_full_virtual_file("/sys/firmware/dmi/entries/0-0/raw", &s, &readsize);
 | ||||||
|  | +        if (r < 0) {
 | ||||||
|  | +                log_debug_errno(r, "Unable to read /sys/firmware/dmi/entries/0-0/raw, ignoring: %m");
 | ||||||
|  | +                return SMBIOS_VM_BIT_UNKNOWN;
 | ||||||
|  | +        }
 | ||||||
|  | +        if (readsize < 20 || s[1] < 20) {
 | ||||||
|  | +                /* The spec indicates that byte 1 contains the size of the table, 0x12 + the number of
 | ||||||
|  | +                 * extension bytes. The data we're interested in is in extension byte 2, which would be at
 | ||||||
|  | +                 * 0x13. If we didn't read that much data, or if the BIOS indicates that we don't have that
 | ||||||
|  | +                 * much data, we don't infer anything from the SMBIOS. */
 | ||||||
|  | +                log_debug("Only read %zu bytes from /sys/firmware/dmi/entries/0-0/raw (expected 20)", readsize);
 | ||||||
|  | +                return SMBIOS_VM_BIT_UNKNOWN;
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  | -        log_debug("No virtualization found in DMI");
 | ||||||
|  | +        uint8_t byte = (uint8_t) s[19];
 | ||||||
|  | +        if (byte & (1U<<4)) {
 | ||||||
|  | +                log_debug("DMI BIOS Extension table indicates virtualization");
 | ||||||
|  | +                return SMBIOS_VM_BIT_SET;
 | ||||||
|  | +        }
 | ||||||
|  | +        log_debug("DMI BIOS Extension table does not indicate virtualization");
 | ||||||
|  | +        return SMBIOS_VM_BIT_UNSET;
 | ||||||
|  | +}
 | ||||||
|  | +#endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) */
 | ||||||
|  | +
 | ||||||
|  | +static int detect_vm_dmi(void) {
 | ||||||
|  | +#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
 | ||||||
|  | +
 | ||||||
|  | +        int r;
 | ||||||
|  | +        r = detect_vm_dmi_vendor();
 | ||||||
|  |   | ||||||
|  | +        /* The DMI vendor tables in /sys/class/dmi/id don't help us distinguish between Amazon EC2
 | ||||||
|  | +         * virtual machines and bare-metal instances, so we need to look at SMBIOS. */
 | ||||||
|  | +        if (r == VIRTUALIZATION_AMAZON && detect_vm_smbios() == SMBIOS_VM_BIT_UNSET)
 | ||||||
|  | +                return VIRTUALIZATION_NONE;
 | ||||||
|  | +
 | ||||||
|  | +        /* If we haven't identified a VM, but the firmware indicates that there is one, indicate as much. We
 | ||||||
|  | +         * have no further information about what it is. */
 | ||||||
|  | +        if (r == VIRTUALIZATION_NONE && detect_vm_smbios() == SMBIOS_VM_BIT_SET)
 | ||||||
|  | +                return VIRTUALIZATION_VM_OTHER;
 | ||||||
|  | +        return r;
 | ||||||
|  | +#else
 | ||||||
|  |          return VIRTUALIZATION_NONE; | ||||||
|  | +#endif
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int detect_vm_xen(void) { | ||||||
							
								
								
									
										37
									
								
								SOURCES/0853-device-drop-refuse_after.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								SOURCES/0853-device-drop-refuse_after.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | From bb9d00035c00b8590c389e66b5d94334bbb7379d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Franck Bui <fbui@suse.com> | ||||||
|  | Date: Mon, 30 Mar 2020 10:49:29 +0200 | ||||||
|  | Subject: [PATCH] device: drop refuse_after | ||||||
|  | 
 | ||||||
|  | Scheduling devices after a given unit can be useful to start device *jobs* at a | ||||||
|  | specific time in the transaction, see commit 4195077ab4c823c. | ||||||
|  | 
 | ||||||
|  | This (hidden) change was introduced by commit eef85c4a3f8054d2. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit b862c25716520d9381d5a841dba0f0c14e9c970a) | ||||||
|  | 
 | ||||||
|  | [dtardon: This picks just the minimal relevant change from | ||||||
|  | c80a9a33d04fb4381327a69ce929c94a9f1d0e6c and | ||||||
|  | b862c25716520d9381d5a841dba0f0c14e9c970a] | ||||||
|  | 
 | ||||||
|  | Resolves: #2043524 | ||||||
|  | ---
 | ||||||
|  |  src/core/unit.c | 5 +++-- | ||||||
|  |  1 file changed, 3 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/unit.c b/src/core/unit.c
 | ||||||
|  | index dfe0c243ef..9be2a0c326 100644
 | ||||||
|  | --- a/src/core/unit.c
 | ||||||
|  | +++ b/src/core/unit.c
 | ||||||
|  | @@ -2841,8 +2841,9 @@ int unit_add_dependency(
 | ||||||
|  |                  return 0; | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | -        if ((d == UNIT_BEFORE && other->type == UNIT_DEVICE) ||
 | ||||||
|  | -            (d == UNIT_AFTER && u->type == UNIT_DEVICE)) {
 | ||||||
|  | +        /* Note that ordering a device unit after a unit is permitted since it
 | ||||||
|  | +         * allows to start its job running timeout at a specific time. */
 | ||||||
|  | +        if (d == UNIT_BEFORE && other->type == UNIT_DEVICE) {
 | ||||||
|  |                  log_unit_warning(u, "Dependency Before=%s ignored (.device units cannot be delayed)", other->id); | ||||||
|  |                  return 0; | ||||||
|  |          } | ||||||
| @ -0,0 +1,44 @@ | |||||||
|  | From 004130ae74688eb321aadc05192bab69fe5cbcbf Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Fri, 22 Jul 2022 11:45:12 +0200 | ||||||
|  | Subject: [PATCH] manager: limit access to private dbus socket | ||||||
|  | 
 | ||||||
|  | For the system manager, /run/systemd/private is publicly accessible, because | ||||||
|  | /run/systemd is 0755, and /run/systemd/private is 0777. For the user manager, | ||||||
|  | /run/user/<uid> is 0700, and /run/user/<uid>/systemd/private is 0777. This | ||||||
|  | does not directly cause any security issue because we check the sender in | ||||||
|  | bus_check_peercred (ucred.uid != 0 && ucred.uid != geteuid()). | ||||||
|  | 
 | ||||||
|  | But it makes sense to limit access to the socket to avoid wasting time in PID1. | ||||||
|  | Somebody could send messages there that'd we'd reject anyway. It also makes | ||||||
|  | things more explicit. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit df1cbd1adf26071aab41d96e054452a3d66103a4) | ||||||
|  | 
 | ||||||
|  | Resolves: #2119405 | ||||||
|  | ---
 | ||||||
|  |  src/core/dbus.c | 4 +++- | ||||||
|  |  1 file changed, 3 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/core/dbus.c b/src/core/dbus.c
 | ||||||
|  | index 66d838cdb4..ec6c52cb85 100644
 | ||||||
|  | --- a/src/core/dbus.c
 | ||||||
|  | +++ b/src/core/dbus.c
 | ||||||
|  | @@ -42,6 +42,7 @@
 | ||||||
|  |  #include "string-util.h" | ||||||
|  |  #include "strv.h" | ||||||
|  |  #include "strxcpyx.h" | ||||||
|  | +#include "umask-util.h"
 | ||||||
|  |  #include "user-util.h" | ||||||
|  |   | ||||||
|  |  #define CONNECTIONS_MAX 4096 | ||||||
|  | @@ -1019,7 +1020,8 @@ int bus_init_private(Manager *m) {
 | ||||||
|  |          if (fd < 0) | ||||||
|  |                  return log_error_errno(errno, "Failed to allocate private socket: %m"); | ||||||
|  |   | ||||||
|  | -        r = bind(fd, &sa.sa, salen);
 | ||||||
|  | +        RUN_WITH_UMASK(0077)
 | ||||||
|  | +                r = bind(fd, &sa.sa, salen);
 | ||||||
|  |          if (r < 0) | ||||||
|  |                  return log_error_errno(errno, "Failed to bind private socket: %m"); | ||||||
|  |   | ||||||
| @ -0,0 +1,35 @@ | |||||||
|  | From b0574acc0bddceb0af47f6cce327a87041ab4b52 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Sun, 11 Nov 2018 12:33:06 +0100 | ||||||
|  | Subject: [PATCH] journalctl: do not treat EINTR as an error when waiting for | ||||||
|  |  events | ||||||
|  | 
 | ||||||
|  | Fixup for 2a1e0f2228bbdfbc18635e959f47df7da50b62fe. Fixes #10724. | ||||||
|  | 
 | ||||||
|  | Reproducer: start 'journalctl -f' in a terminal window, change window size. | ||||||
|  | (cherry picked from commit 8e143a123276a9636987b08f555603927ca9e186) | ||||||
|  | 
 | ||||||
|  | Resolves: #2161683 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journalctl.c | 7 ++++++- | ||||||
|  |  1 file changed, 6 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
 | ||||||
|  | index fa83dce562..228cfe7e49 100644
 | ||||||
|  | --- a/src/journal/journalctl.c
 | ||||||
|  | +++ b/src/journal/journalctl.c
 | ||||||
|  | @@ -2084,8 +2084,13 @@ static int wait_for_change(sd_journal *j, int poll_fd) {
 | ||||||
|  |          if (r < 0) | ||||||
|  |                  return log_error_errno(r, "Failed to determine journal waiting time: %m"); | ||||||
|  |   | ||||||
|  | -        if (ppoll(pollfds, ELEMENTSOF(pollfds), timeout == USEC_INFINITY ? NULL : timespec_store(&ts, timeout), NULL) < 0)
 | ||||||
|  | +        if (ppoll(pollfds, ELEMENTSOF(pollfds),
 | ||||||
|  | +                  timeout == USEC_INFINITY ? NULL : timespec_store(&ts, timeout), NULL) < 0) {
 | ||||||
|  | +                if (errno == EINTR)
 | ||||||
|  | +                        return 0;
 | ||||||
|  | +
 | ||||||
|  |                  return log_error_errno(errno, "Couldn't wait for journal event: %m"); | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  |          if (pollfds[1].revents & (POLLHUP|POLLERR)) { /* STDOUT has been closed? */ | ||||||
|  |                  log_debug("Standard output has been closed."); | ||||||
| @ -1,4 +1,4 @@ | |||||||
| From 2385f40cc80d723b105add1496de292c3241595c Mon Sep 17 00:00:00 2001 | From b9dd7ee5f4d0f6d51899d7e14ac7ef2fd2840b8f Mon Sep 17 00:00:00 2001 | ||||||
| From: Lennart Poettering <lennart@poettering.net> | From: Lennart Poettering <lennart@poettering.net> | ||||||
| Date: Tue, 9 Oct 2018 17:37:57 +0200 | Date: Tue, 9 Oct 2018 17:37:57 +0200 | ||||||
| Subject: [PATCH] core: bring manager_startup() and manager_reload() more | Subject: [PATCH] core: bring manager_startup() and manager_reload() more | ||||||
| @ -26,16 +26,16 @@ This makes a number of changes: | |||||||
| 
 | 
 | ||||||
| (cherry picked from commit 3ad2afb6a204513c7834c64ab864e40169874390) | (cherry picked from commit 3ad2afb6a204513c7834c64ab864e40169874390) | ||||||
| 
 | 
 | ||||||
| Resolves: #2164049 | Resolves: #2059633 | ||||||
| ---
 | ---
 | ||||||
|  src/core/manager.c | 14 +++++++++++--- |  src/core/manager.c | 14 +++++++++++--- | ||||||
|  1 file changed, 11 insertions(+), 3 deletions(-) |  1 file changed, 11 insertions(+), 3 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/src/core/manager.c b/src/core/manager.c
 | diff --git a/src/core/manager.c b/src/core/manager.c
 | ||||||
| index f4611e6f8f..49d6d250ef 100644
 | index e083596e58..4a9f9bfcf9 100644
 | ||||||
| --- a/src/core/manager.c
 | --- a/src/core/manager.c
 | ||||||
| +++ b/src/core/manager.c
 | +++ b/src/core/manager.c
 | ||||||
| @@ -1660,12 +1660,12 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
 | @@ -1665,12 +1665,12 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
 | ||||||
|          /* Release any dynamic users no longer referenced */ |          /* Release any dynamic users no longer referenced */ | ||||||
|          dynamic_user_vacuum(m, true); |          dynamic_user_vacuum(m, true); | ||||||
|   |   | ||||||
| @ -50,7 +50,7 @@ index f4611e6f8f..49d6d250ef 100644 | |||||||
|          if (serialization) { |          if (serialization) { | ||||||
|                  assert(m->n_reloading > 0); |                  assert(m->n_reloading > 0); | ||||||
|                  m->n_reloading--; |                  m->n_reloading--; | ||||||
| @@ -1676,6 +1676,13 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
 | @@ -1681,6 +1681,13 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
 | ||||||
|                  m->send_reloading_done = true; |                  m->send_reloading_done = true; | ||||||
|          } |          } | ||||||
|   |   | ||||||
| @ -64,7 +64,7 @@ index f4611e6f8f..49d6d250ef 100644 | |||||||
|          /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ |          /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ | ||||||
|          manager_catchup(m); |          manager_catchup(m); | ||||||
|   |   | ||||||
| @@ -3500,7 +3507,8 @@ int manager_reload(Manager *m) {
 | @@ -3505,7 +3512,8 @@ int manager_reload(Manager *m) {
 | ||||||
|          lookup_paths_reduce(&m->lookup_paths); |          lookup_paths_reduce(&m->lookup_paths); | ||||||
|          manager_build_unit_path_cache(m); |          manager_build_unit_path_cache(m); | ||||||
|   |   | ||||||
							
								
								
									
										35
									
								
								SOURCES/0857-pam-add-a-call-to-pam_namespace.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								SOURCES/0857-pam-add-a-call-to-pam_namespace.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | From b1b7aaf83414c5b0bed6e61d38aefe29a21fdbcf Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Wed, 23 Nov 2022 16:09:56 +0100 | ||||||
|  | Subject: [PATCH] pam: add a call to pam_namespace | ||||||
|  | 
 | ||||||
|  | A call to pam_namespace is required so that children of user@.service end up in | ||||||
|  | a namespace as expected. pam_namespace gets called as part of the stack that | ||||||
|  | creates a session (login, sshd, gdm, etc.) and those processes end up in a | ||||||
|  | namespace, but it also needs to be called from our stack which is parallel and | ||||||
|  | descends from pid1 itself. | ||||||
|  | 
 | ||||||
|  | The call to pam_namespace is similar to the call to pam_keyinit that was added | ||||||
|  | in ab79099d1684457d040ee7c28b2012e8c1ea9a4f. The pam stack for user@.service | ||||||
|  | creates a new session which is disconnected from the parent environment. Both | ||||||
|  | calls are not suitable for inclusion in the shared part of the stack (e.g. | ||||||
|  | @system-auth on Fedora/RHEL systems), because for example su/sudo/runuser
 | ||||||
|  | should not include them. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 0ef48896d9f23b9fd547a532a4e6e6b8f8b12901) | ||||||
|  | 
 | ||||||
|  | Resolves: #1861836 | ||||||
|  | ---
 | ||||||
|  |  src/login/systemd-user.m4 | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/login/systemd-user.m4 b/src/login/systemd-user.m4
 | ||||||
|  | index 20c8999331..eb291beaed 100644
 | ||||||
|  | --- a/src/login/systemd-user.m4
 | ||||||
|  | +++ b/src/login/systemd-user.m4
 | ||||||
|  | @@ -9,4 +9,5 @@ session required pam_selinux.so nottys open
 | ||||||
|  |  )m4_dnl | ||||||
|  |  session required pam_loginuid.so | ||||||
|  |  session optional pam_keyinit.so force revoke | ||||||
|  | +session required pam_namespace.so
 | ||||||
|  |  session optional pam_systemd.so | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | From 4b573adbcc040fa50f1130cb8cf1bdb9559565cf Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Boqun Feng <boqun.feng@gmail.com> | ||||||
|  | Date: Wed, 13 Oct 2021 11:32:09 +0800 | ||||||
|  | Subject: [PATCH] virt: Support detection for ARM64 Hyper-V guests | ||||||
|  | 
 | ||||||
|  | The detection of Microsoft Hyper-V VMs is done by cpuid currently, | ||||||
|  | however there is no cpuid on ARM64. And since ARM64 is now a supported | ||||||
|  | architecture for Microsoft Hyper-V guests[1], then use DMI tables to | ||||||
|  | detect a Hyper-V guest, which is more generic and works for ARM64. | ||||||
|  | 
 | ||||||
|  | [1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7aff79e297ee1aa0126924921fd87a4ae59d2467 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 506bbc8569014253ea8614b680ccbc4fc2513a87) | ||||||
|  | 
 | ||||||
|  | Resolves: #2158307 | ||||||
|  | ---
 | ||||||
|  |  src/basic/virt.c | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/basic/virt.c b/src/basic/virt.c
 | ||||||
|  | index 00d1c894e6..cc95097101 100644
 | ||||||
|  | --- a/src/basic/virt.c
 | ||||||
|  | +++ b/src/basic/virt.c
 | ||||||
|  | @@ -162,6 +162,7 @@ static int detect_vm_dmi_vendor(void) {
 | ||||||
|  |                  { "Parallels",     VIRTUALIZATION_PARALLELS }, | ||||||
|  |                  /* https://wiki.freebsd.org/bhyve */ | ||||||
|  |                  { "BHYVE",         VIRTUALIZATION_BHYVE     }, | ||||||
|  | +                { "Microsoft",           VIRTUALIZATION_MICROSOFT },
 | ||||||
|  |          }; | ||||||
|  |          unsigned i; | ||||||
|  |          int r; | ||||||
							
								
								
									
										41
									
								
								SOURCES/0859-virt-Fix-the-detection-for-Hyper-V-VMs.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								SOURCES/0859-virt-Fix-the-detection-for-Hyper-V-VMs.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | From e732bc987f2f779e89f30193bf694e0456ab7ce0 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Boqun Feng <boqun.feng@gmail.com> | ||||||
|  | Date: Tue, 23 Nov 2021 15:09:26 +0800 | ||||||
|  | Subject: [PATCH] virt: Fix the detection for Hyper-V VMs | ||||||
|  | 
 | ||||||
|  | Use product_version instead of product_name in DMI table and the string | ||||||
|  | "Hyper-V" to avoid misdetection. | ||||||
|  | 
 | ||||||
|  | Fixes: #21468 | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Boqun Feng <boqun.feng@gmail.com> | ||||||
|  | (cherry picked from commit 76eec0649936d9ae2f9087769f463feaf0cf5cb4) | ||||||
|  | 
 | ||||||
|  | Related: #2158307 | ||||||
|  | ---
 | ||||||
|  |  src/basic/virt.c | 5 +++-- | ||||||
|  |  1 file changed, 3 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/basic/virt.c b/src/basic/virt.c
 | ||||||
|  | index cc95097101..f750a0463f 100644
 | ||||||
|  | --- a/src/basic/virt.c
 | ||||||
|  | +++ b/src/basic/virt.c
 | ||||||
|  | @@ -143,7 +143,8 @@ static int detect_vm_dmi_vendor(void) {
 | ||||||
|  |                  "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */ | ||||||
|  |                  "/sys/class/dmi/id/sys_vendor", | ||||||
|  |                  "/sys/class/dmi/id/board_vendor", | ||||||
|  | -                "/sys/class/dmi/id/bios_vendor"
 | ||||||
|  | +                "/sys/class/dmi/id/bios_vendor",
 | ||||||
|  | +                "/sys/class/dmi/id/product_version" /* For Hyper-V VMs test */
 | ||||||
|  |          }; | ||||||
|  |   | ||||||
|  |          static const struct { | ||||||
|  | @@ -162,7 +163,7 @@ static int detect_vm_dmi_vendor(void) {
 | ||||||
|  |                  { "Parallels",     VIRTUALIZATION_PARALLELS }, | ||||||
|  |                  /* https://wiki.freebsd.org/bhyve */ | ||||||
|  |                  { "BHYVE",         VIRTUALIZATION_BHYVE     }, | ||||||
|  | -                { "Microsoft",           VIRTUALIZATION_MICROSOFT },
 | ||||||
|  | +                { "Hyper-V",             VIRTUALIZATION_MICROSOFT },
 | ||||||
|  |          }; | ||||||
|  |          unsigned i; | ||||||
|  |          int r; | ||||||
| @ -1,11 +1,11 @@ | |||||||
| From 84a8245cf58fa7edea61eab5f1ebd86a3944c388 Mon Sep 17 00:00:00 2001 | From 9c95d8dda42de288a57638a44dd5ea967469063d Mon Sep 17 00:00:00 2001 | ||||||
| From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
| Date: Fri, 7 Oct 2022 12:28:31 +0200 | Date: Fri, 7 Oct 2022 12:28:31 +0200 | ||||||
| Subject: [PATCH] basic: add STRERROR() wrapper for strerror_r() | Subject: [PATCH] basic: add STRERROR() wrapper for strerror_r() | ||||||
| 
 | 
 | ||||||
| (cherry picked from commit 2c5d05b3cd986568105d67891e4010b868dea24f) | (cherry picked from commit 2c5d05b3cd986568105d67891e4010b868dea24f) | ||||||
| 
 | 
 | ||||||
| Related: #2155519 | Related: #2155520 | ||||||
| ---
 | ---
 | ||||||
|  src/basic/util.h     | 10 ++++++++++ |  src/basic/util.h     | 10 ++++++++++ | ||||||
|  src/test/test-util.c | 40 ++++++++++++++++++++++++++++++++++++++++ |  src/test/test-util.c | 40 ++++++++++++++++++++++++++++++++++++++++ | ||||||
| @ -1,4 +1,4 @@ | |||||||
| From e256e03710abfd96e74d0b278c2b7186e3c8888b Mon Sep 17 00:00:00 2001 | From f53c6620c55488e2a3bd92957b21b6b95a7a3d35 Mon Sep 17 00:00:00 2001 | ||||||
| From: David Tardon <dtardon@redhat.com> | From: David Tardon <dtardon@redhat.com> | ||||||
| Date: Thu, 12 Jan 2023 15:47:09 +0100 | Date: Thu, 12 Jan 2023 15:47:09 +0100 | ||||||
| Subject: [PATCH] coredump: put context array into a struct | Subject: [PATCH] coredump: put context array into a struct | ||||||
| @ -7,7 +7,7 @@ Subject: [PATCH] coredump: put context array into a struct | |||||||
| but does just the minimal change to introduce the Context struct that is | but does just the minimal change to introduce the Context struct that is | ||||||
| needed by the following commit.] | needed by the following commit.] | ||||||
| 
 | 
 | ||||||
| Related: #2155519 | Related: #2155520 | ||||||
| ---
 | ---
 | ||||||
|  src/coredump/coredump.c | 208 +++++++++++++++++++++------------------- |  src/coredump/coredump.c | 208 +++++++++++++++++++++------------------- | ||||||
|  1 file changed, 108 insertions(+), 100 deletions(-) |  1 file changed, 108 insertions(+), 100 deletions(-) | ||||||
| @ -1,4 +1,4 @@ | |||||||
| From 9fa7f77c5a3d92fe03d6eec8384043555ea16dc6 Mon Sep 17 00:00:00 2001 | From d178865d3d9940423f4d99360e3dc2fcaf0b2c96 Mon Sep 17 00:00:00 2001 | ||||||
| From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
| Date: Mon, 28 Nov 2022 12:12:55 +0100 | Date: Mon, 28 Nov 2022 12:12:55 +0100 | ||||||
| Subject: [PATCH] coredump: do not allow user to access coredumps with changed | Subject: [PATCH] coredump: do not allow user to access coredumps with changed | ||||||
| @ -36,7 +36,7 @@ ppc64el, but not the whole coredump handling. | |||||||
| 
 | 
 | ||||||
| (cherry picked from commit 3e4d0f6cf99f8677edd6a237382a65bfe758de03) | (cherry picked from commit 3e4d0f6cf99f8677edd6a237382a65bfe758de03) | ||||||
| 
 | 
 | ||||||
| Resolves: #2155519 | Resolves: #2155520 | ||||||
| ---
 | ---
 | ||||||
|  src/coredump/coredump.c | 190 ++++++++++++++++++++++++++++++++++++++-- |  src/coredump/coredump.c | 190 ++++++++++++++++++++++++++++++++++++++-- | ||||||
|  1 file changed, 182 insertions(+), 8 deletions(-) |  1 file changed, 182 insertions(+), 8 deletions(-) | ||||||
| @ -0,0 +1,70 @@ | |||||||
|  | From a55bdb007ca24900a704f72359305b04125d9e05 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Michal Sekletar <msekleta@redhat.com> | ||||||
|  | Date: Wed, 20 Apr 2022 10:13:43 +0200 | ||||||
|  | Subject: [PATCH] logind: remember our idle state and use it to detect idle | ||||||
|  |  level transitions | ||||||
|  | 
 | ||||||
|  | Fixes #16391 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 4e2cfb778b9ed7f22ee98f48f28cf8678d25ad32) | ||||||
|  | 
 | ||||||
|  | Resolved: #1866955 | ||||||
|  | ---
 | ||||||
|  |  src/login/logind.c | 23 +++++++++++++++++++---- | ||||||
|  |  src/login/logind.h |  1 + | ||||||
|  |  2 files changed, 20 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/login/logind.c b/src/login/logind.c
 | ||||||
|  | index 6b576dad0d..bb1d3f3523 100644
 | ||||||
|  | --- a/src/login/logind.c
 | ||||||
|  | +++ b/src/login/logind.c
 | ||||||
|  | @@ -1027,18 +1027,33 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
 | ||||||
|  |          n = now(CLOCK_MONOTONIC); | ||||||
|  |   | ||||||
|  |          r = manager_get_idle_hint(m, &since); | ||||||
|  | -        if (r <= 0)
 | ||||||
|  | +        if (r <= 0) {
 | ||||||
|  |                  /* Not idle. Let's check if after a timeout it might be idle then. */ | ||||||
|  |                  elapse = n + m->idle_action_usec; | ||||||
|  | -        else {
 | ||||||
|  | +                m->was_idle = false;
 | ||||||
|  | +        } else {
 | ||||||
|  | +
 | ||||||
|  |                  /* Idle! Let's see if it's time to do something, or if | ||||||
|  |                   * we shall sleep for longer. */ | ||||||
|  |   | ||||||
|  |                  if (n >= since.monotonic + m->idle_action_usec && | ||||||
|  |                      (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) { | ||||||
|  | -                        log_info("System idle. Taking action.");
 | ||||||
|  | +                        bool is_edge = false;
 | ||||||
|  | +
 | ||||||
|  | +                        /* We weren't idle previously or some activity happened while we were sleeping, and now we are
 | ||||||
|  | +                         * idle. Let's remember that for the next time and make this an edge transition. */
 | ||||||
|  | +                        if (!m->was_idle || since.monotonic >= m->idle_action_not_before_usec) {
 | ||||||
|  | +                                is_edge = true;
 | ||||||
|  | +                                m->was_idle = true;
 | ||||||
|  | +                        }
 | ||||||
|  | +
 | ||||||
|  | +                        if (m->idle_action == HANDLE_LOCK && !is_edge)
 | ||||||
|  | +                                /* We are idle and we were before so we are actually not taking any action. */
 | ||||||
|  | +                                log_debug("System idle.");
 | ||||||
|  | +                        else
 | ||||||
|  | +                                log_info("System idle. Doing %s operation.", handle_action_to_string(m->idle_action));
 | ||||||
|  |   | ||||||
|  | -                        manager_handle_action(m, 0, m->idle_action, false, false);
 | ||||||
|  | +                        manager_handle_action(m, 0, m->idle_action, false, is_edge);
 | ||||||
|  |                          m->idle_action_not_before_usec = n; | ||||||
|  |                  } | ||||||
|  |   | ||||||
|  | diff --git a/src/login/logind.h b/src/login/logind.h
 | ||||||
|  | index 606adf4fe6..b9b4a5113f 100644
 | ||||||
|  | --- a/src/login/logind.h
 | ||||||
|  | +++ b/src/login/logind.h
 | ||||||
|  | @@ -101,6 +101,7 @@ struct Manager {
 | ||||||
|  |          usec_t idle_action_usec; | ||||||
|  |          usec_t idle_action_not_before_usec; | ||||||
|  |          HandleAction idle_action; | ||||||
|  | +        bool was_idle;
 | ||||||
|  |   | ||||||
|  |          usec_t stop_idle_session_usec; | ||||||
|  |   | ||||||
| @ -0,0 +1,103 @@ | |||||||
|  | From 1925845dc10330e4b48fec68333fac6ef2b7bf5c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Wed, 1 Jun 2022 08:56:08 +0900 | ||||||
|  | Subject: [PATCH] test: import logind test from debian/ubuntu test suite | ||||||
|  | 
 | ||||||
|  | [dtardon: Picked just the scaffolding, not the tests themselves.] | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 9c94ab0f6ff22da4278a6e9a93ddc480607c55ac) | ||||||
|  | 
 | ||||||
|  | Related: #1866955 | ||||||
|  | ---
 | ||||||
|  |  test/TEST-35-LOGIN/Makefile     |  1 + | ||||||
|  |  test/TEST-35-LOGIN/test.sh      | 55 +++++++++++++++++++++++++++++++++ | ||||||
|  |  test/TEST-35-LOGIN/testsuite.sh |  9 ++++++ | ||||||
|  |  3 files changed, 65 insertions(+) | ||||||
|  |  create mode 120000 test/TEST-35-LOGIN/Makefile | ||||||
|  |  create mode 100755 test/TEST-35-LOGIN/test.sh | ||||||
|  |  create mode 100755 test/TEST-35-LOGIN/testsuite.sh | ||||||
|  | 
 | ||||||
|  | diff --git a/test/TEST-35-LOGIN/Makefile b/test/TEST-35-LOGIN/Makefile
 | ||||||
|  | new file mode 120000 | ||||||
|  | index 0000000000..e9f93b1104
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/TEST-35-LOGIN/Makefile
 | ||||||
|  | @@ -0,0 +1 @@
 | ||||||
|  | +../TEST-01-BASIC/Makefile
 | ||||||
|  | \ No newline at end of file | ||||||
|  | diff --git a/test/TEST-35-LOGIN/test.sh b/test/TEST-35-LOGIN/test.sh
 | ||||||
|  | new file mode 100755 | ||||||
|  | index 0000000000..32410c8149
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/TEST-35-LOGIN/test.sh
 | ||||||
|  | @@ -0,0 +1,55 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +# SPDX-License-Identifier: LGPL-2.1-or-later
 | ||||||
|  | +set -e
 | ||||||
|  | +
 | ||||||
|  | +TEST_DESCRIPTION="LOGIN"
 | ||||||
|  | +
 | ||||||
|  | +# shellcheck source=test/test-functions
 | ||||||
|  | +. "${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 pkill
 | ||||||
|  | +        inst_binary useradd
 | ||||||
|  | +        inst_binary userdel
 | ||||||
|  | +
 | ||||||
|  | +        # 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 <<EOF
 | ||||||
|  | +[Unit]
 | ||||||
|  | +Description=Testsuite service
 | ||||||
|  | +
 | ||||||
|  | +[Service]
 | ||||||
|  | +ExecStart=/bin/bash -x /testsuite.sh
 | ||||||
|  | +Type=oneshot
 | ||||||
|  | +StandardOutput=tty
 | ||||||
|  | +StandardError=tty
 | ||||||
|  | +NotifyAccess=all
 | ||||||
|  | +EOF
 | ||||||
|  | +        cp testsuite.sh "$initdir"/
 | ||||||
|  | +
 | ||||||
|  | +        setup_testsuite
 | ||||||
|  | +    ) || return 1
 | ||||||
|  | +    setup_nspawn_root
 | ||||||
|  | +
 | ||||||
|  | +    ddebug "umount $TESTDIR/root"
 | ||||||
|  | +    umount "$TESTDIR"/root
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +do_test "$@"
 | ||||||
|  | diff --git a/test/TEST-35-LOGIN/testsuite.sh b/test/TEST-35-LOGIN/testsuite.sh
 | ||||||
|  | new file mode 100755 | ||||||
|  | index 0000000000..9855b4bc80
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/TEST-35-LOGIN/testsuite.sh
 | ||||||
|  | @@ -0,0 +1,9 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +# SPDX-License-Identifier: LGPL-2.1-or-later
 | ||||||
|  | +set -eux
 | ||||||
|  | +set -o pipefail
 | ||||||
|  | +
 | ||||||
|  | +: >/failed
 | ||||||
|  | +
 | ||||||
|  | +touch /testok
 | ||||||
|  | +rm /failed
 | ||||||
| @ -0,0 +1,37 @@ | |||||||
|  | From 21c281585983fe2efc2b74d712d98ff7e6c013b1 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Tue, 14 Jun 2022 09:11:00 +0900 | ||||||
|  | Subject: [PATCH] test: introduce inst_recursive() helper function | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit da0465dc95388afc15598357452afef85035c639) | ||||||
|  | 
 | ||||||
|  | Related: #1866955 | ||||||
|  | ---
 | ||||||
|  |  test/test-functions | 14 ++++++++++++++ | ||||||
|  |  1 file changed, 14 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/test-functions b/test/test-functions
 | ||||||
|  | index 19363be858..9606a1b085 100644
 | ||||||
|  | --- a/test/test-functions
 | ||||||
|  | +++ b/test/test-functions
 | ||||||
|  | @@ -1224,6 +1224,20 @@ inst_any() {
 | ||||||
|  |      return 1 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +inst_recursive() {
 | ||||||
|  | +    local p item
 | ||||||
|  | +
 | ||||||
|  | +    for p in "$@"; do
 | ||||||
|  | +        while read -r item; do
 | ||||||
|  | +            if [[ -d "$item" ]]; then
 | ||||||
|  | +                inst_dir "$item"
 | ||||||
|  | +            elif [[ -f "$item" ]]; then
 | ||||||
|  | +                inst_simple "$item"
 | ||||||
|  | +            fi
 | ||||||
|  | +        done < <(find "$p" 2>/dev/null)
 | ||||||
|  | +    done
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  # dracut_install [-o ] <file> [<file> ... ] | ||||||
|  |  # Install <file> to the initramfs image | ||||||
|  |  # -o optionally install the <file> and don't fail, if it is not there | ||||||
| @ -0,0 +1,148 @@ | |||||||
|  | From 638c2418e705410344e07e77f944530df0f4608f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Michal Sekletar <msekleta@redhat.com> | ||||||
|  | Date: Fri, 1 Jul 2022 12:59:57 +0200 | ||||||
|  | Subject: [PATCH] tests: verify that Lock D-Bus signal is sent when | ||||||
|  |  IdleAction=lock | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 181656fc0faa885d69bc34822b8e9b5de3fdf6bf) | ||||||
|  | 
 | ||||||
|  | Related: #1866955 | ||||||
|  | ---
 | ||||||
|  |  test/TEST-35-LOGIN/test.sh      | 11 +++- | ||||||
|  |  test/TEST-35-LOGIN/testsuite.sh | 93 +++++++++++++++++++++++++++++++++ | ||||||
|  |  2 files changed, 103 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/TEST-35-LOGIN/test.sh b/test/TEST-35-LOGIN/test.sh
 | ||||||
|  | index 32410c8149..f83afcff49 100755
 | ||||||
|  | --- a/test/TEST-35-LOGIN/test.sh
 | ||||||
|  | +++ b/test/TEST-35-LOGIN/test.sh
 | ||||||
|  | @@ -14,14 +14,23 @@ test_setup() {
 | ||||||
|  |   | ||||||
|  |      ( | ||||||
|  |          LOG_LEVEL=5 | ||||||
|  | -        eval $(udevadm info --export --query=env --name="${LOOPDEV}p2")
 | ||||||
|  | +        eval "$(udevadm info --export --query=env --name="${LOOPDEV}p2")"
 | ||||||
|  |   | ||||||
|  |          setup_basic_environment | ||||||
|  |   | ||||||
|  | +        inst_binary awk
 | ||||||
|  |          inst_binary pkill | ||||||
|  |          inst_binary useradd | ||||||
|  |          inst_binary userdel | ||||||
|  |   | ||||||
|  | +        if command -v expect >/dev/null && command -v tclsh >/dev/null ; then
 | ||||||
|  | +                # shellcheck disable=SC2016
 | ||||||
|  | +                version="$(tclsh <<< 'puts $tcl_version')"
 | ||||||
|  | +
 | ||||||
|  | +                dracut_install expect
 | ||||||
|  | +                inst_recursive /usr/lib64/tcl"$version" /usr/share/tcl"$version"
 | ||||||
|  | +        fi
 | ||||||
|  | +
 | ||||||
|  |          # 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 | ||||||
|  | diff --git a/test/TEST-35-LOGIN/testsuite.sh b/test/TEST-35-LOGIN/testsuite.sh
 | ||||||
|  | index 9855b4bc80..e4d72beb74 100755
 | ||||||
|  | --- a/test/TEST-35-LOGIN/testsuite.sh
 | ||||||
|  | +++ b/test/TEST-35-LOGIN/testsuite.sh
 | ||||||
|  | @@ -3,7 +3,100 @@
 | ||||||
|  |  set -eux | ||||||
|  |  set -o pipefail | ||||||
|  |   | ||||||
|  | +setup_idle_action_lock() {
 | ||||||
|  | +    useradd testuser ||:
 | ||||||
|  | +
 | ||||||
|  | +    mkdir -p /run/systemd/logind.conf.d/
 | ||||||
|  | +    cat >/run/systemd/logind.conf.d/idle-action-lock.conf <<EOF
 | ||||||
|  | +[Login]
 | ||||||
|  | +IdleAction=lock
 | ||||||
|  | +IdleActionSec=1s
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +    mkdir -p /run/systemd/systemd-logind.service.d/
 | ||||||
|  | +    cat >/run/systemd/systemd-logind.service.d/debug.conf <<EOF
 | ||||||
|  | +[Service]
 | ||||||
|  | +Environment=SYSTEMD_LOG_LEVEL=debug
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +    systemctl restart systemd-logind.service
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +teardown_idle_action_lock() {(
 | ||||||
|  | +    set +ex
 | ||||||
|  | +    rm -f /run/systemd/logind.conf.d/idle-action-lock.conf
 | ||||||
|  | +    rm -f /run/systemd/systemd-logind.service.d/debug.conf
 | ||||||
|  | +    pkill -9 -u "$(id -u testuser)"
 | ||||||
|  | +    userdel -r testuser
 | ||||||
|  | +    systemctl restart systemd-logind.service
 | ||||||
|  | +)}
 | ||||||
|  | +
 | ||||||
|  | +test_lock_idle_action() {
 | ||||||
|  | +    if ! command -v expect >/dev/null ; then
 | ||||||
|  | +        echo >&2 "expect not installed, skiping test ${FUNCNAME[0]}"
 | ||||||
|  | +        return 0
 | ||||||
|  | +    fi
 | ||||||
|  | +
 | ||||||
|  | +    setup_idle_action_lock
 | ||||||
|  | +    trap teardown_idle_action_lock RETURN
 | ||||||
|  | +
 | ||||||
|  | +    if loginctl --no-legend | awk '{ print $3; }' | sort -u | grep -q testuser ; then
 | ||||||
|  | +        echo >&2 "Session of the \'testuser\' is already present."
 | ||||||
|  | +        return 1
 | ||||||
|  | +    fi
 | ||||||
|  | +
 | ||||||
|  | +    # IdleActionSec is set 1s but the accuracy of associated timer is 30s so we
 | ||||||
|  | +    # need to sleep in worst case for 31s to make sure timer elapsed. We sleep
 | ||||||
|  | +    # here for 35s to accomodate for any possible scheudling delays.
 | ||||||
|  | +    cat > /tmp/test.exp <<EOF
 | ||||||
|  | +spawn systemd-run -G -t -p PAMName=login -p User=testuser bash
 | ||||||
|  | +send "sleep 35\r"
 | ||||||
|  | +send "echo foobar\r"
 | ||||||
|  | +send "sleep 35\r"
 | ||||||
|  | +send "exit\r"
 | ||||||
|  | +interact
 | ||||||
|  | +wait
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +    ts="$(date '+%H:%M:%S')"
 | ||||||
|  | +    busctl --match "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='Lock'" monitor  > dbus.log &
 | ||||||
|  | +
 | ||||||
|  | +    expect /tmp/test.exp &
 | ||||||
|  | +
 | ||||||
|  | +    # Sleep a bit to give expect time to spawn systemd-run before we check for
 | ||||||
|  | +    # the presence of resulting session.
 | ||||||
|  | +    sleep 2
 | ||||||
|  | +    if [ "$(loginctl --no-legend | awk '{ print $3; }' | sort -u | grep -c testuser)" != 1 ] ; then
 | ||||||
|  | +        echo >&2 "\'testuser\' is expected to have exactly one session running."
 | ||||||
|  | +        return 1
 | ||||||
|  | +    fi
 | ||||||
|  | +
 | ||||||
|  | +    wait %2
 | ||||||
|  | +    sleep 20
 | ||||||
|  | +    kill %1
 | ||||||
|  | +
 | ||||||
|  | +    # We slept for 35s , in that interval all sessions should have become idle
 | ||||||
|  | +    # and "Lock" signal should have been sent out. Then we wrote to tty to make
 | ||||||
|  | +    # session active again and next we slept for another 35s so sessions have
 | ||||||
|  | +    # become idle again. 'Lock' signal is sent out for each session, we have at
 | ||||||
|  | +    # least one session, so minimum of 2 "Lock" signals must have been sent.
 | ||||||
|  | +    if [ "$(grep -c Member=Lock dbus.log)" -lt 2 ]; then
 | ||||||
|  | +        echo >&2 "Too few 'Lock' D-Bus signal sent, expected at least 2."
 | ||||||
|  | +        return 1
 | ||||||
|  | +    fi
 | ||||||
|  | +
 | ||||||
|  | +    journalctl -b -u systemd-logind.service --since="$ts" > logind.log
 | ||||||
|  | +    if [ "$(grep -c 'System idle. Doing lock operation.' logind.log)" -lt 2 ]; then
 | ||||||
|  | +        echo >&2 "System haven't entered idle state at least 2 times."
 | ||||||
|  | +        return 1
 | ||||||
|  | +    fi
 | ||||||
|  | +
 | ||||||
|  | +    rm -f dbus.log logind.log
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  : >/failed | ||||||
|  |   | ||||||
|  | +test_lock_idle_action
 | ||||||
|  | +
 | ||||||
|  |  touch /testok | ||||||
|  |  rm /failed | ||||||
							
								
								
									
										86
									
								
								SOURCES/0867-systemctl-simplify-halt_main.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								SOURCES/0867-systemctl-simplify-halt_main.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  | From 797b00e6a6f33d2b74beba02f678bf4d12e2146b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ludwig Nussel <ludwig.nussel@suse.de> | ||||||
|  | Date: Tue, 14 Dec 2021 17:27:05 +0100 | ||||||
|  | Subject: [PATCH] systemctl: simplify halt_main() | ||||||
|  | 
 | ||||||
|  | The code at this point is not able to tell whether it was called as | ||||||
|  | halt/poweroff/reboot or shutdown with time "now". | ||||||
|  | The code also takes a shortcut to skip logind if called as root. | ||||||
|  | That however means asking shutdown for immediate action won't trigger a | ||||||
|  | wall message. | ||||||
|  | As per https://github.com/systemd/systemd/issues/8424#issuecomment-374677315 | ||||||
|  | all commands should trigger a wall message. | ||||||
|  | That simplifies the code as we can try logind first always. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit adefc8789b63225662e50ceaa282f9553b5c64eb) | ||||||
|  | 
 | ||||||
|  | Resolves: #2053273 | ||||||
|  | ---
 | ||||||
|  |  src/systemctl/systemctl.c | 44 ++++++++++++++++----------------------- | ||||||
|  |  1 file changed, 18 insertions(+), 26 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
 | ||||||
|  | index b967550b97..4bedb52f2a 100644
 | ||||||
|  | --- a/src/systemctl/systemctl.c
 | ||||||
|  | +++ b/src/systemctl/systemctl.c
 | ||||||
|  | @@ -8658,34 +8658,23 @@ static int logind_schedule_shutdown(void) {
 | ||||||
|  |  static int halt_main(void) { | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  | -        r = logind_check_inhibitors(arg_action);
 | ||||||
|  | -        if (r < 0)
 | ||||||
|  | -                return r;
 | ||||||
|  | -
 | ||||||
|  | +        /* always try logind first */
 | ||||||
|  |          if (arg_when > 0) | ||||||
|  | -                return logind_schedule_shutdown();
 | ||||||
|  | -
 | ||||||
|  | -        if (geteuid() != 0) {
 | ||||||
|  | -                if (arg_dry_run || arg_force > 0) {
 | ||||||
|  | -                        (void) must_be_root();
 | ||||||
|  | -                        return -EPERM;
 | ||||||
|  | -                }
 | ||||||
|  | +                r = logind_schedule_shutdown();
 | ||||||
|  | +        else {
 | ||||||
|  | +                r = logind_check_inhibitors(arg_action);
 | ||||||
|  | +                if (r < 0)
 | ||||||
|  | +                        return r;
 | ||||||
|  |   | ||||||
|  | -                /* Try logind if we are a normal user and no special
 | ||||||
|  | -                 * mode applies. Maybe PolicyKit allows us to shutdown
 | ||||||
|  | -                 * the machine. */
 | ||||||
|  | -                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
 | ||||||
|  | -                        r = logind_reboot(arg_action);
 | ||||||
|  | -                        if (r >= 0)
 | ||||||
|  | -                                return r;
 | ||||||
|  | -                        if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
 | ||||||
|  | -                                /* requested operation is not
 | ||||||
|  | -                                 * supported on the local system or
 | ||||||
|  | -                                 * already in progress */
 | ||||||
|  | -                                return r;
 | ||||||
|  | -                        /* on all other errors, try low-level operation */
 | ||||||
|  | -                }
 | ||||||
|  | +                r = logind_reboot(arg_action);
 | ||||||
|  |          } | ||||||
|  | +        if (r >= 0)
 | ||||||
|  | +                return r;
 | ||||||
|  | +        if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
 | ||||||
|  | +                /* Requested operation is not supported on the local system or already in
 | ||||||
|  | +                 * progress */
 | ||||||
|  | +                return r;
 | ||||||
|  | +        /* on all other errors, try low-level operation */
 | ||||||
|  |   | ||||||
|  |          /* In order to minimize the difference between operation with and | ||||||
|  |           * without logind, we explicitly enable non-blocking mode for this, | ||||||
|  | @@ -8695,7 +8684,10 @@ static int halt_main(void) {
 | ||||||
|  |          if (!arg_dry_run && !arg_force) | ||||||
|  |                  return start_with_fallback(); | ||||||
|  |   | ||||||
|  | -        assert(geteuid() == 0);
 | ||||||
|  | +        if (geteuid() != 0) {
 | ||||||
|  | +                (void) must_be_root();
 | ||||||
|  | +                return -EPERM;
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  |          if (!arg_no_wtmp) { | ||||||
|  |                  if (sd_booted() > 0) | ||||||
| @ -0,0 +1,51 @@ | |||||||
|  | From 1d63577410cde215c04921d62f435259a6b258d7 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ludwig Nussel <ludwig.nussel@suse.de> | ||||||
|  | Date: Mon, 20 Dec 2021 18:05:50 +0100 | ||||||
|  | Subject: [PATCH] systemctl: shutdown don't fallback on auth fail | ||||||
|  | 
 | ||||||
|  | For shutdowns don't fall back to starting the target directly if talking | ||||||
|  | to logind failed with auth failure. That would just lead to another | ||||||
|  | polkit auth attempt. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 38d55bf2641f345445cb4e6a5e5e808555591db2) | ||||||
|  | 
 | ||||||
|  | Related: #2053273 | ||||||
|  | ---
 | ||||||
|  |  src/systemctl/systemctl.c | 10 +++++----- | ||||||
|  |  1 file changed, 5 insertions(+), 5 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
 | ||||||
|  | index 4bedb52f2a..199f736f7f 100644
 | ||||||
|  | --- a/src/systemctl/systemctl.c
 | ||||||
|  | +++ b/src/systemctl/systemctl.c
 | ||||||
|  | @@ -3675,8 +3675,8 @@ static int start_special(int argc, char *argv[], void *userdata) {
 | ||||||
|  |                          r = logind_reboot(a); | ||||||
|  |                          if (r >= 0) | ||||||
|  |                                  return r; | ||||||
|  | -                        if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
 | ||||||
|  | -                                /* requested operation is not supported or already in progress */
 | ||||||
|  | +                        if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
 | ||||||
|  | +                                /* Requested operation requires auth, is not supported or already in progress */
 | ||||||
|  |                                  return r; | ||||||
|  |   | ||||||
|  |                          /* On all other errors, try low-level operation. In order to minimize the difference between | ||||||
|  | @@ -8644,7 +8644,7 @@ static int logind_schedule_shutdown(void) {
 | ||||||
|  |                          action, | ||||||
|  |                          arg_when); | ||||||
|  |          if (r < 0) | ||||||
|  | -                return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
 | ||||||
|  | +                return log_warning_errno(r, "Failed to schedule shutdown: %s", bus_error_message(&error, r));
 | ||||||
|  |   | ||||||
|  |          if (!arg_quiet) | ||||||
|  |                  log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when)); | ||||||
|  | @@ -8670,8 +8670,8 @@ static int halt_main(void) {
 | ||||||
|  |          } | ||||||
|  |          if (r >= 0) | ||||||
|  |                  return r; | ||||||
|  | -        if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
 | ||||||
|  | -                /* Requested operation is not supported on the local system or already in
 | ||||||
|  | +        if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
 | ||||||
|  | +                /* Requested operation requires auth, is not supported on the local system or already in
 | ||||||
|  |                   * progress */ | ||||||
|  |                  return r; | ||||||
|  |          /* on all other errors, try low-level operation */ | ||||||
| @ -0,0 +1,82 @@ | |||||||
|  | From d36295d7c1b110d150b7af6e3354c28af4c4884d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Tardon <dtardon@redhat.com> | ||||||
|  | Date: Mon, 30 Jan 2023 14:27:24 +0100 | ||||||
|  | Subject: [PATCH] systemctl: reintroduce the original halt_main() | ||||||
|  | 
 | ||||||
|  | RHEL-only | ||||||
|  | 
 | ||||||
|  | Related: #2053273 | ||||||
|  | ---
 | ||||||
|  |  src/systemctl/systemctl.c | 59 +++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 59 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
 | ||||||
|  | index 199f736f7f..a26e4a913a 100644
 | ||||||
|  | --- a/src/systemctl/systemctl.c
 | ||||||
|  | +++ b/src/systemctl/systemctl.c
 | ||||||
|  | @@ -8655,6 +8655,65 @@ static int logind_schedule_shutdown(void) {
 | ||||||
|  |  #endif | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int halt_main_old(void) {
 | ||||||
|  | +        int r;
 | ||||||
|  | +
 | ||||||
|  | +        r = logind_check_inhibitors(arg_action);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                return r;
 | ||||||
|  | +
 | ||||||
|  | +        if (arg_when > 0)
 | ||||||
|  | +                return logind_schedule_shutdown();
 | ||||||
|  | +
 | ||||||
|  | +        if (geteuid() != 0) {
 | ||||||
|  | +                if (arg_dry_run || arg_force > 0) {
 | ||||||
|  | +                        (void) must_be_root();
 | ||||||
|  | +                        return -EPERM;
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                /* Try logind if we are a normal user and no special
 | ||||||
|  | +                 * mode applies. Maybe PolicyKit allows us to shutdown
 | ||||||
|  | +                 * the machine. */
 | ||||||
|  | +                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
 | ||||||
|  | +                        r = logind_reboot(arg_action);
 | ||||||
|  | +                        if (r >= 0)
 | ||||||
|  | +                                return r;
 | ||||||
|  | +                        if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
 | ||||||
|  | +                                /* requested operation is not
 | ||||||
|  | +                                 * supported on the local system or
 | ||||||
|  | +                                 * already in progress */
 | ||||||
|  | +                                return r;
 | ||||||
|  | +                        /* on all other errors, try low-level operation */
 | ||||||
|  | +                }
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        /* In order to minimize the difference between operation with and
 | ||||||
|  | +         * without logind, we explicitly enable non-blocking mode for this,
 | ||||||
|  | +         * as logind's shutdown operations are always non-blocking. */
 | ||||||
|  | +        arg_no_block = true;
 | ||||||
|  | +
 | ||||||
|  | +        if (!arg_dry_run && !arg_force)
 | ||||||
|  | +                return start_with_fallback();
 | ||||||
|  | +
 | ||||||
|  | +        assert(geteuid() == 0);
 | ||||||
|  | +
 | ||||||
|  | +        if (!arg_no_wtmp) {
 | ||||||
|  | +                if (sd_booted() > 0)
 | ||||||
|  | +                        log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
 | ||||||
|  | +                else {
 | ||||||
|  | +                        r = utmp_put_shutdown();
 | ||||||
|  | +                        if (r < 0)
 | ||||||
|  | +                                log_warning_errno(r, "Failed to write utmp record: %m");
 | ||||||
|  | +                }
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        if (arg_dry_run)
 | ||||||
|  | +                return 0;
 | ||||||
|  | +
 | ||||||
|  | +        r = halt_now(arg_action);
 | ||||||
|  | +        return log_error_errno(r, "Failed to reboot: %m");
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int halt_main(void) { | ||||||
|  |          int r; | ||||||
|  |   | ||||||
| @ -0,0 +1,44 @@ | |||||||
|  | From 74632586b46c7e88b09c57eec50f9c4aed254b98 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Tardon <dtardon@redhat.com> | ||||||
|  | Date: Mon, 30 Jan 2023 14:31:23 +0100 | ||||||
|  | Subject: [PATCH] systemctl: preserve old behavior unless requested | ||||||
|  | 
 | ||||||
|  | Currently, the legacy shutdown commands ignore inhibitors and reboot | ||||||
|  | immediately if run by root. Let's preserve that behavior in RHEL-8 by | ||||||
|  | default. The new behavior can be turned on by those who want it by | ||||||
|  | exporting SYSTEMD_NEW_SHUTDOWN=1 . | ||||||
|  | 
 | ||||||
|  | RHEL-only | ||||||
|  | 
 | ||||||
|  | Related: #2053273 | ||||||
|  | ---
 | ||||||
|  |  src/systemctl/systemctl.c | 9 ++++++++- | ||||||
|  |  1 file changed, 8 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
 | ||||||
|  | index a26e4a913a..1546119ce5 100644
 | ||||||
|  | --- a/src/systemctl/systemctl.c
 | ||||||
|  | +++ b/src/systemctl/systemctl.c
 | ||||||
|  | @@ -8714,7 +8714,7 @@ static int halt_main_old(void) {
 | ||||||
|  |          return log_error_errno(r, "Failed to reboot: %m"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int halt_main(void) {
 | ||||||
|  | +static int halt_main_new(void) {
 | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  |          /* always try logind first */ | ||||||
|  | @@ -8765,6 +8765,13 @@ static int halt_main(void) {
 | ||||||
|  |          return log_error_errno(r, "Failed to reboot: %m"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int halt_main(void) {
 | ||||||
|  | +        if (getenv_bool("SYSTEMD_NEW_SHUTDOWN") > 0)
 | ||||||
|  | +                return halt_main_new();
 | ||||||
|  | +        else
 | ||||||
|  | +                return halt_main_old();
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int runlevel_main(void) { | ||||||
|  |          int r, runlevel, previous; | ||||||
|  |   | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | From ea3910e561f043f5a131a846862955c77169da1b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Mon, 19 Nov 2018 11:39:45 +0100 | ||||||
|  | Subject: [PATCH] pam_systemd: suppress LOG_DEBUG log messages if debugging is | ||||||
|  |  off | ||||||
|  | 
 | ||||||
|  | In the PAM module we need to suppress LOG_DEBUG messages manually, if | ||||||
|  | debug logging is not on, as PAM won't do this for us. We did this | ||||||
|  | correctly for most log messages already, but two were missing. Let's fix | ||||||
|  | those too. | ||||||
|  | 
 | ||||||
|  | Fixes: #10822 | ||||||
|  | (cherry picked from commit 2675747f3cdd6f1e6236bbb2f79abfa53fb307f1) | ||||||
|  | 
 | ||||||
|  | Resolves: #2170084 | ||||||
|  | ---
 | ||||||
|  |  src/login/pam_systemd.c | 6 ++++-- | ||||||
|  |  1 file changed, 4 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
 | ||||||
|  | index 64e1b4d1bf..c87e980b18 100644
 | ||||||
|  | --- a/src/login/pam_systemd.c
 | ||||||
|  | +++ b/src/login/pam_systemd.c
 | ||||||
|  | @@ -476,7 +476,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 | ||||||
|  |          } | ||||||
|  |   | ||||||
|  |          if (seat && !streq(seat, "seat0") && vtnr != 0) { | ||||||
|  | -                pam_syslog(handle, LOG_DEBUG, "Ignoring vtnr %"PRIu32" for %s which is not seat0", vtnr, seat);
 | ||||||
|  | +                if (debug)
 | ||||||
|  | +                        pam_syslog(handle, LOG_DEBUG, "Ignoring vtnr %"PRIu32" for %s which is not seat0", vtnr, seat);
 | ||||||
|  |                  vtnr = 0; | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | @@ -577,7 +578,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 | ||||||
|  |          r = sd_bus_call(bus, m, 0, &error, &reply); | ||||||
|  |          if (r < 0) { | ||||||
|  |                  if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) { | ||||||
|  | -                        pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
 | ||||||
|  | +                        if (debug)
 | ||||||
|  | +                                pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
 | ||||||
|  |                          return PAM_SUCCESS; | ||||||
|  |                  } else { | ||||||
|  |                          pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r)); | ||||||
| @ -0,0 +1,50 @@ | |||||||
|  | From 33351e103734188a4a30b88e7f2ea0613d628599 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Macku <jamacku@redhat.com> | ||||||
|  | Date: Thu, 16 Feb 2023 15:56:52 +0100 | ||||||
|  | Subject: [PATCH] udev/net_id: introduce naming scheme for RHEL-8.8 | ||||||
|  | 
 | ||||||
|  | RHEL-only | ||||||
|  | 
 | ||||||
|  | Resolves: #2170499 | ||||||
|  | ---
 | ||||||
|  |  man/systemd.net-naming-scheme.xml | 6 ++++++ | ||||||
|  |  src/udev/udev-builtin-net_id.c    | 2 ++ | ||||||
|  |  2 files changed, 8 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
 | ||||||
|  | index a567483995..3cc7719e99 100644
 | ||||||
|  | --- a/man/systemd.net-naming-scheme.xml
 | ||||||
|  | +++ b/man/systemd.net-naming-scheme.xml
 | ||||||
|  | @@ -328,6 +328,12 @@
 | ||||||
|  |            for that, the limit is increased to now 65535.</para></listitem> | ||||||
|  |          </varlistentry> | ||||||
|  |   | ||||||
|  | +        <varlistentry>
 | ||||||
|  | +          <term><constant>rhel-8.8</constant></term>
 | ||||||
|  | +
 | ||||||
|  | +          <para>Same as naming scheme <constant>rhel-8.7</constant>.</para>
 | ||||||
|  | +        </varlistentry>
 | ||||||
|  | +
 | ||||||
|  |          <para>Note that <constant>latest</constant> may be used to denote the latest scheme known to this | ||||||
|  |          particular version of systemd.</para> | ||||||
|  |      </variablelist> | ||||||
|  | diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
 | ||||||
|  | index df84acf27c..ef2bb1b08e 100644
 | ||||||
|  | --- a/src/udev/udev-builtin-net_id.c
 | ||||||
|  | +++ b/src/udev/udev-builtin-net_id.c
 | ||||||
|  | @@ -141,6 +141,7 @@ typedef enum NamingSchemeFlags {
 | ||||||
|  |          NAMING_RHEL_8_5 = NAMING_RHEL_8_4, | ||||||
|  |          NAMING_RHEL_8_6 = NAMING_RHEL_8_4, | ||||||
|  |          NAMING_RHEL_8_7 = NAMING_RHEL_8_4|NAMING_SLOT_FUNCTION_ID|NAMING_16BIT_INDEX, | ||||||
|  | +        NAMING_RHEL_8_8 = NAMING_RHEL_8_7,
 | ||||||
|  |   | ||||||
|  |          _NAMING_SCHEME_FLAGS_INVALID = -1, | ||||||
|  |  } NamingSchemeFlags; | ||||||
|  | @@ -161,6 +162,7 @@ static const NamingScheme naming_schemes[] = {
 | ||||||
|  |          { "rhel-8.5", NAMING_RHEL_8_5 }, | ||||||
|  |          { "rhel-8.6", NAMING_RHEL_8_6 }, | ||||||
|  |          { "rhel-8.7", NAMING_RHEL_8_7 }, | ||||||
|  | +        { "rhel-8.8", NAMING_RHEL_8_8 },
 | ||||||
|  |          /* … add more schemes here, as the logic to name devices is updated … */ | ||||||
|  |  }; | ||||||
|  |   | ||||||
| @ -0,0 +1,176 @@ | |||||||
|  | From 8f0a91b5192b72eb8b0f06e04ef3515d0397fcb8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Fri, 5 Apr 2019 18:20:25 +0200 | ||||||
|  | Subject: [PATCH] journald: add API to move logging from /var to /run again | ||||||
|  | 
 | ||||||
|  | We now have this nice little Varlink API, let's beef it up a bit. | ||||||
|  | 
 | ||||||
|  | [dtardon: This diverges from the upstream commit in two ways: One is | ||||||
|  | that the new action is bound to a signal, as varlink is not available. | ||||||
|  | The other is that this introduces a new "flag" file | ||||||
|  | /run/systemd/journal/relinquished, which is essentially the opposite of | ||||||
|  | /run/systemd/journal/flushed (hence at most one of them may exist at any | ||||||
|  | time).] | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit b4e26d1d8e582d78e67ed766177f10e8e194404c) | ||||||
|  | 
 | ||||||
|  | Related: #1873540 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-server.c | 64 ++++++++++++++++++++++++++++------- | ||||||
|  |  1 file changed, 51 insertions(+), 13 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
 | ||||||
|  | index 7632e2d9d0..279a32768c 100644
 | ||||||
|  | --- a/src/journal/journald-server.c
 | ||||||
|  | +++ b/src/journal/journald-server.c
 | ||||||
|  | @@ -283,13 +283,14 @@ static bool flushed_flag_is_set(void) {
 | ||||||
|  |          return access("/run/systemd/journal/flushed", F_OK) >= 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int system_journal_open(Server *s, bool flush_requested) {
 | ||||||
|  | +static int system_journal_open(Server *s, bool flush_requested, bool relinquish_requested) {
 | ||||||
|  |          const char *fn; | ||||||
|  |          int r = 0; | ||||||
|  |   | ||||||
|  |          if (!s->system_journal && | ||||||
|  |              IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) && | ||||||
|  | -            (flush_requested || flushed_flag_is_set())) {
 | ||||||
|  | +            (flush_requested || flushed_flag_is_set()) &&
 | ||||||
|  | +            !relinquish_requested) {
 | ||||||
|  |   | ||||||
|  |                  /* If in auto mode: first try to create the machine | ||||||
|  |                   * path, but not the prefix. | ||||||
|  | @@ -331,7 +332,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
 | ||||||
|  |   | ||||||
|  |                  fn = strjoina(s->runtime_storage.path, "/system.journal"); | ||||||
|  |   | ||||||
|  | -                if (s->system_journal) {
 | ||||||
|  | +                if (s->system_journal && !relinquish_requested) {
 | ||||||
|  |   | ||||||
|  |                          /* Try to open the runtime journal, but only | ||||||
|  |                           * if it already exists, so that we can flush | ||||||
|  | @@ -386,7 +387,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
 | ||||||
|  |           * else that's left the journals as NULL). | ||||||
|  |           * | ||||||
|  |           * Fixes https://github.com/systemd/systemd/issues/3968 */ | ||||||
|  | -        (void) system_journal_open(s, false);
 | ||||||
|  | +        (void) system_journal_open(s, false, false);
 | ||||||
|  |   | ||||||
|  |          /* We split up user logs only on /var, not on /run. If the | ||||||
|  |           * runtime file is open, we write to it exclusively, in order | ||||||
|  | @@ -964,7 +965,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
 | ||||||
|  |          char ts[FORMAT_TIMESPAN_MAX]; | ||||||
|  |          usec_t start; | ||||||
|  |          unsigned n = 0; | ||||||
|  | -        int r;
 | ||||||
|  | +        int r, k;
 | ||||||
|  |   | ||||||
|  |          assert(s); | ||||||
|  |   | ||||||
|  | @@ -977,7 +978,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
 | ||||||
|  |          if (require_flag_file && !flushed_flag_is_set()) | ||||||
|  |                  return 0; | ||||||
|  |   | ||||||
|  | -        (void) system_journal_open(s, true);
 | ||||||
|  | +        (void) system_journal_open(s, true, false);
 | ||||||
|  |   | ||||||
|  |          if (!s->system_journal) | ||||||
|  |                  return 0; | ||||||
|  | @@ -1056,6 +1057,13 @@ finish:
 | ||||||
|  |                                            n), | ||||||
|  |                                NULL); | ||||||
|  |   | ||||||
|  | +        if (unlink("/run/systemd/journal/relinquished") < 0 && errno != ENOENT)
 | ||||||
|  | +                log_warning_errno(errno, "Failed to unlink /run/systemd/journal/relinquished, ignoring: %m");
 | ||||||
|  | +
 | ||||||
|  | +        k = touch("/run/systemd/journal/flushed");
 | ||||||
|  | +        if (k < 0)
 | ||||||
|  | +                log_warning_errno(k, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
 | ||||||
|  | +
 | ||||||
|  |          return r; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -1180,7 +1188,6 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
 | ||||||
|  |   | ||||||
|  |  static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { | ||||||
|  |          Server *s = userdata; | ||||||
|  | -        int r;
 | ||||||
|  |   | ||||||
|  |          assert(s); | ||||||
|  |   | ||||||
|  | @@ -1190,10 +1197,6 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *
 | ||||||
|  |          server_sync(s); | ||||||
|  |          server_vacuum(s, false); | ||||||
|  |   | ||||||
|  | -        r = touch("/run/systemd/journal/flushed");
 | ||||||
|  | -        if (r < 0)
 | ||||||
|  | -                log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
 | ||||||
|  | -
 | ||||||
|  |          server_space_usage_message(s, NULL); | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  | @@ -1250,12 +1253,43 @@ static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo
 | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +
 | ||||||
|  | +static int dispatch_sigrtmin2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
 | ||||||
|  | +        Server *s = userdata;
 | ||||||
|  | +        int r;
 | ||||||
|  | +
 | ||||||
|  | +        assert(s);
 | ||||||
|  | +
 | ||||||
|  | +        if (s->storage == STORAGE_NONE)
 | ||||||
|  | +                return 0;
 | ||||||
|  | +
 | ||||||
|  | +        if (s->runtime_journal && !s->system_journal)
 | ||||||
|  | +                return 0;
 | ||||||
|  | +
 | ||||||
|  | +        log_debug("Received request to relinquish /var from PID " PID_FMT, si->ssi_pid);
 | ||||||
|  | +
 | ||||||
|  | +        (void) system_journal_open(s, false, true);
 | ||||||
|  | +
 | ||||||
|  | +        s->system_journal = journal_file_close(s->system_journal);
 | ||||||
|  | +        ordered_hashmap_clear_with_destructor(s->user_journals, journal_file_close);
 | ||||||
|  | +        set_clear_with_destructor(s->deferred_closes, journal_file_close);
 | ||||||
|  | +
 | ||||||
|  | +        if (unlink("/run/systemd/journal/flushed") < 0 && errno != ENOENT)
 | ||||||
|  | +                log_warning_errno(errno, "Failed to unlink /run/systemd/journal/flushed, ignoring: %m")  ;
 | ||||||
|  | +
 | ||||||
|  | +        r = write_timestamp_file_atomic("/run/systemd/journal/relinquished", now(CLOCK_MONOTONIC));
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                log_warning_errno(r, "Failed to write /run/systemd/journal/relinquished, ignoring: %m");
 | ||||||
|  | +
 | ||||||
|  | +        return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int setup_signals(Server *s) { | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  |          assert(s); | ||||||
|  |   | ||||||
|  | -        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);
 | ||||||
|  | +        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+2, -1) >= 0);
 | ||||||
|  |   | ||||||
|  |          r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s); | ||||||
|  |          if (r < 0) | ||||||
|  | @@ -1294,6 +1328,10 @@ static int setup_signals(Server *s) {
 | ||||||
|  |          if (r < 0) | ||||||
|  |                  return r; | ||||||
|  |   | ||||||
|  | +        r = sd_event_add_signal(s->event, &s->sigrtmin1_event_source, SIGRTMIN+2, dispatch_sigrtmin2, s);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                return r;
 | ||||||
|  | +
 | ||||||
|  |          r = sd_event_source_set_priority(s->sigrtmin1_event_source, SD_EVENT_PRIORITY_NORMAL+15); | ||||||
|  |          if (r < 0) | ||||||
|  |                  return r; | ||||||
|  | @@ -1876,7 +1914,7 @@ int server_init(Server *s) {
 | ||||||
|  |   | ||||||
|  |          (void) client_context_acquire_default(s); | ||||||
|  |   | ||||||
|  | -        return system_journal_open(s, false);
 | ||||||
|  | +        return system_journal_open(s, false, false);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  void server_maybe_append_tags(Server *s) { | ||||||
| @ -0,0 +1,242 @@ | |||||||
|  | From fa93a97bdf18906d9517f4183802456986490c89 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Fri, 5 Apr 2019 18:21:02 +0200 | ||||||
|  | Subject: [PATCH] journalctl: add new --relinquish and --smart-relinquish | ||||||
|  |  options | ||||||
|  | 
 | ||||||
|  | The latter is identical to the former, but becomes a NOP if | ||||||
|  | /var/log/journal is on the same mount as /, and thus during shutdown | ||||||
|  | unmounting /var is not necessary and hence we can keep logging until the | ||||||
|  | very end. | ||||||
|  | 
 | ||||||
|  | [dtardon: The only divergence from the upstream commit is the impl. of | ||||||
|  | relinquish_var().] | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit c0dfcb318c28d87e1176a8ad87ac7cc4ecc50305) | ||||||
|  | 
 | ||||||
|  | Related: #1873540 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journalctl.c | 161 +++++++++++++++++++++++++-------------- | ||||||
|  |  1 file changed, 103 insertions(+), 58 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
 | ||||||
|  | index 228cfe7e49..6928c79a06 100644
 | ||||||
|  | --- a/src/journal/journalctl.c
 | ||||||
|  | +++ b/src/journal/journalctl.c
 | ||||||
|  | @@ -47,6 +47,7 @@
 | ||||||
|  |  #include "log.h" | ||||||
|  |  #include "logs-show.h" | ||||||
|  |  #include "mkdir.h" | ||||||
|  | +#include "mount-util.h"
 | ||||||
|  |  #include "pager.h" | ||||||
|  |  #include "parse-util.h" | ||||||
|  |  #include "path-util.h" | ||||||
|  | @@ -162,6 +163,7 @@ static enum {
 | ||||||
|  |          ACTION_UPDATE_CATALOG, | ||||||
|  |          ACTION_LIST_BOOTS, | ||||||
|  |          ACTION_FLUSH, | ||||||
|  | +        ACTION_RELINQUISH_VAR,
 | ||||||
|  |          ACTION_SYNC, | ||||||
|  |          ACTION_ROTATE, | ||||||
|  |          ACTION_VACUUM, | ||||||
|  | @@ -358,6 +360,8 @@ static void help(void) {
 | ||||||
|  |                 "     --vacuum-time=TIME      Remove journal files older than specified time\n" | ||||||
|  |                 "     --verify                Verify journal file consistency\n" | ||||||
|  |                 "     --sync                  Synchronize unwritten journal messages to disk\n" | ||||||
|  | +               "     --relinquish-var        Stop logging to disk, log to temporary file system\n"
 | ||||||
|  | +               "     --smart-relinquish-var  Similar, but NOP if log directory is on root mount\n"
 | ||||||
|  |                 "     --flush                 Flush all journal data from /run into /var\n" | ||||||
|  |                 "     --rotate                Request immediate rotation of the journal files\n" | ||||||
|  |                 "     --header                Show journal header information\n" | ||||||
|  | @@ -402,6 +406,8 @@ static int parse_argv(int argc, char *argv[]) {
 | ||||||
|  |                  ARG_UTC, | ||||||
|  |                  ARG_SYNC, | ||||||
|  |                  ARG_FLUSH, | ||||||
|  | +                ARG_RELINQUISH_VAR,
 | ||||||
|  | +                ARG_SMART_RELINQUISH_VAR,
 | ||||||
|  |                  ARG_ROTATE, | ||||||
|  |                  ARG_VACUUM_SIZE, | ||||||
|  |                  ARG_VACUUM_FILES, | ||||||
|  | @@ -411,64 +417,66 @@ static int parse_argv(int argc, char *argv[]) {
 | ||||||
|  |          }; | ||||||
|  |   | ||||||
|  |          static const struct option options[] = { | ||||||
|  | -                { "help",           no_argument,       NULL, 'h'                },
 | ||||||
|  | -                { "version" ,       no_argument,       NULL, ARG_VERSION        },
 | ||||||
|  | -                { "no-pager",       no_argument,       NULL, ARG_NO_PAGER       },
 | ||||||
|  | -                { "pager-end",      no_argument,       NULL, 'e'                },
 | ||||||
|  | -                { "follow",         no_argument,       NULL, 'f'                },
 | ||||||
|  | -                { "force",          no_argument,       NULL, ARG_FORCE          },
 | ||||||
|  | -                { "output",         required_argument, NULL, 'o'                },
 | ||||||
|  | -                { "all",            no_argument,       NULL, 'a'                },
 | ||||||
|  | -                { "full",           no_argument,       NULL, 'l'                },
 | ||||||
|  | -                { "no-full",        no_argument,       NULL, ARG_NO_FULL        },
 | ||||||
|  | -                { "lines",          optional_argument, NULL, 'n'                },
 | ||||||
|  | -                { "no-tail",        no_argument,       NULL, ARG_NO_TAIL        },
 | ||||||
|  | -                { "new-id128",      no_argument,       NULL, ARG_NEW_ID128      },
 | ||||||
|  | -                { "quiet",          no_argument,       NULL, 'q'                },
 | ||||||
|  | -                { "merge",          no_argument,       NULL, 'm'                },
 | ||||||
|  | -                { "this-boot",      no_argument,       NULL, ARG_THIS_BOOT      }, /* deprecated */
 | ||||||
|  | -                { "boot",           optional_argument, NULL, 'b'                },
 | ||||||
|  | -                { "list-boots",     no_argument,       NULL, ARG_LIST_BOOTS     },
 | ||||||
|  | -                { "dmesg",          no_argument,       NULL, 'k'                },
 | ||||||
|  | -                { "system",         no_argument,       NULL, ARG_SYSTEM         },
 | ||||||
|  | -                { "user",           no_argument,       NULL, ARG_USER           },
 | ||||||
|  | -                { "directory",      required_argument, NULL, 'D'                },
 | ||||||
|  | -                { "file",           required_argument, NULL, ARG_FILE           },
 | ||||||
|  | -                { "root",           required_argument, NULL, ARG_ROOT           },
 | ||||||
|  | -                { "header",         no_argument,       NULL, ARG_HEADER         },
 | ||||||
|  | -                { "identifier",     required_argument, NULL, 't'                },
 | ||||||
|  | -                { "priority",       required_argument, NULL, 'p'                },
 | ||||||
|  | -                { "grep",           required_argument, NULL, 'g'                },
 | ||||||
|  | -                { "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE },
 | ||||||
|  | -                { "setup-keys",     no_argument,       NULL, ARG_SETUP_KEYS     },
 | ||||||
|  | -                { "interval",       required_argument, NULL, ARG_INTERVAL       },
 | ||||||
|  | -                { "verify",         no_argument,       NULL, ARG_VERIFY         },
 | ||||||
|  | -                { "verify-key",     required_argument, NULL, ARG_VERIFY_KEY     },
 | ||||||
|  | -                { "disk-usage",     no_argument,       NULL, ARG_DISK_USAGE     },
 | ||||||
|  | -                { "cursor",         required_argument, NULL, 'c'                },
 | ||||||
|  | -                { "after-cursor",   required_argument, NULL, ARG_AFTER_CURSOR   },
 | ||||||
|  | -                { "show-cursor",    no_argument,       NULL, ARG_SHOW_CURSOR    },
 | ||||||
|  | -                { "since",          required_argument, NULL, 'S'                },
 | ||||||
|  | -                { "until",          required_argument, NULL, 'U'                },
 | ||||||
|  | -                { "unit",           required_argument, NULL, 'u'                },
 | ||||||
|  | -                { "user-unit",      required_argument, NULL, ARG_USER_UNIT      },
 | ||||||
|  | -                { "field",          required_argument, NULL, 'F'                },
 | ||||||
|  | -                { "fields",         no_argument,       NULL, 'N'                },
 | ||||||
|  | -                { "catalog",        no_argument,       NULL, 'x'                },
 | ||||||
|  | -                { "list-catalog",   no_argument,       NULL, ARG_LIST_CATALOG   },
 | ||||||
|  | -                { "dump-catalog",   no_argument,       NULL, ARG_DUMP_CATALOG   },
 | ||||||
|  | -                { "update-catalog", no_argument,       NULL, ARG_UPDATE_CATALOG },
 | ||||||
|  | -                { "reverse",        no_argument,       NULL, 'r'                },
 | ||||||
|  | -                { "machine",        required_argument, NULL, 'M'                },
 | ||||||
|  | -                { "utc",            no_argument,       NULL, ARG_UTC            },
 | ||||||
|  | -                { "flush",          no_argument,       NULL, ARG_FLUSH          },
 | ||||||
|  | -                { "sync",           no_argument,       NULL, ARG_SYNC           },
 | ||||||
|  | -                { "rotate",         no_argument,       NULL, ARG_ROTATE         },
 | ||||||
|  | -                { "vacuum-size",    required_argument, NULL, ARG_VACUUM_SIZE    },
 | ||||||
|  | -                { "vacuum-files",   required_argument, NULL, ARG_VACUUM_FILES   },
 | ||||||
|  | -                { "vacuum-time",    required_argument, NULL, ARG_VACUUM_TIME    },
 | ||||||
|  | -                { "no-hostname",    no_argument,       NULL, ARG_NO_HOSTNAME    },
 | ||||||
|  | -                { "output-fields",  required_argument, NULL, ARG_OUTPUT_FIELDS  },
 | ||||||
|  | +                { "help",                 no_argument,       NULL, 'h'                      },
 | ||||||
|  | +                { "version" ,             no_argument,       NULL, ARG_VERSION              },
 | ||||||
|  | +                { "no-pager",             no_argument,       NULL, ARG_NO_PAGER             },
 | ||||||
|  | +                { "pager-end",            no_argument,       NULL, 'e'                      },
 | ||||||
|  | +                { "follow",               no_argument,       NULL, 'f'                      },
 | ||||||
|  | +                { "force",                no_argument,       NULL, ARG_FORCE                },
 | ||||||
|  | +                { "output",               required_argument, NULL, 'o'                      },
 | ||||||
|  | +                { "all",                  no_argument,       NULL, 'a'                      },
 | ||||||
|  | +                { "full",                 no_argument,       NULL, 'l'                      },
 | ||||||
|  | +                { "no-full",              no_argument,       NULL, ARG_NO_FULL              },
 | ||||||
|  | +                { "lines",                optional_argument, NULL, 'n'                      },
 | ||||||
|  | +                { "no-tail",              no_argument,       NULL, ARG_NO_TAIL              },
 | ||||||
|  | +                { "new-id128",            no_argument,       NULL, ARG_NEW_ID128            }, /* deprecated */
 | ||||||
|  | +                { "quiet",                no_argument,       NULL, 'q'                      },
 | ||||||
|  | +                { "merge",                no_argument,       NULL, 'm'                      },
 | ||||||
|  | +                { "this-boot",            no_argument,       NULL, ARG_THIS_BOOT            }, /* deprecated */
 | ||||||
|  | +                { "boot",                 optional_argument, NULL, 'b'                      },
 | ||||||
|  | +                { "list-boots",           no_argument,       NULL, ARG_LIST_BOOTS           },
 | ||||||
|  | +                { "dmesg",                no_argument,       NULL, 'k'                      },
 | ||||||
|  | +                { "system",               no_argument,       NULL, ARG_SYSTEM               },
 | ||||||
|  | +                { "user",                 no_argument,       NULL, ARG_USER                 },
 | ||||||
|  | +                { "directory",            required_argument, NULL, 'D'                      },
 | ||||||
|  | +                { "file",                 required_argument, NULL, ARG_FILE                 },
 | ||||||
|  | +                { "root",                 required_argument, NULL, ARG_ROOT                 },
 | ||||||
|  | +                { "header",               no_argument,       NULL, ARG_HEADER               },
 | ||||||
|  | +                { "identifier",           required_argument, NULL, 't'                      },
 | ||||||
|  | +                { "priority",             required_argument, NULL, 'p'                      },
 | ||||||
|  | +                { "grep",                 required_argument, NULL, 'g'                      },
 | ||||||
|  | +                { "case-sensitive",       optional_argument, NULL, ARG_CASE_SENSITIVE       },
 | ||||||
|  | +                { "setup-keys",           no_argument,       NULL, ARG_SETUP_KEYS           },
 | ||||||
|  | +                { "interval",             required_argument, NULL, ARG_INTERVAL             },
 | ||||||
|  | +                { "verify",               no_argument,       NULL, ARG_VERIFY               },
 | ||||||
|  | +                { "verify-key",           required_argument, NULL, ARG_VERIFY_KEY           },
 | ||||||
|  | +                { "disk-usage",           no_argument,       NULL, ARG_DISK_USAGE           },
 | ||||||
|  | +                { "cursor",               required_argument, NULL, 'c'                      },
 | ||||||
|  | +                { "after-cursor",         required_argument, NULL, ARG_AFTER_CURSOR         },
 | ||||||
|  | +                { "show-cursor",          no_argument,       NULL, ARG_SHOW_CURSOR          },
 | ||||||
|  | +                { "since",                required_argument, NULL, 'S'                      },
 | ||||||
|  | +                { "until",                required_argument, NULL, 'U'                      },
 | ||||||
|  | +                { "unit",                 required_argument, NULL, 'u'                      },
 | ||||||
|  | +                { "user-unit",            required_argument, NULL, ARG_USER_UNIT            },
 | ||||||
|  | +                { "field",                required_argument, NULL, 'F'                      },
 | ||||||
|  | +                { "fields",               no_argument,       NULL, 'N'                      },
 | ||||||
|  | +                { "catalog",              no_argument,       NULL, 'x'                      },
 | ||||||
|  | +                { "list-catalog",         no_argument,       NULL, ARG_LIST_CATALOG         },
 | ||||||
|  | +                { "dump-catalog",         no_argument,       NULL, ARG_DUMP_CATALOG         },
 | ||||||
|  | +                { "update-catalog",       no_argument,       NULL, ARG_UPDATE_CATALOG       },
 | ||||||
|  | +                { "reverse",              no_argument,       NULL, 'r'                      },
 | ||||||
|  | +                { "machine",              required_argument, NULL, 'M'                      },
 | ||||||
|  | +                { "utc",                  no_argument,       NULL, ARG_UTC                  },
 | ||||||
|  | +                { "flush",                no_argument,       NULL, ARG_FLUSH                },
 | ||||||
|  | +                { "relinquish-var",       no_argument,       NULL, ARG_RELINQUISH_VAR       },
 | ||||||
|  | +                { "smart-relinquish-var", no_argument,       NULL, ARG_SMART_RELINQUISH_VAR },
 | ||||||
|  | +                { "sync",                 no_argument,       NULL, ARG_SYNC                 },
 | ||||||
|  | +                { "rotate",               no_argument,       NULL, ARG_ROTATE               },
 | ||||||
|  | +                { "vacuum-size",          required_argument, NULL, ARG_VACUUM_SIZE          },
 | ||||||
|  | +                { "vacuum-files",         required_argument, NULL, ARG_VACUUM_FILES         },
 | ||||||
|  | +                { "vacuum-time",          required_argument, NULL, ARG_VACUUM_TIME          },
 | ||||||
|  | +                { "no-hostname",          no_argument,       NULL, ARG_NO_HOSTNAME          },
 | ||||||
|  | +                { "output-fields",        required_argument, NULL, ARG_OUTPUT_FIELDS        },
 | ||||||
|  |                  {} | ||||||
|  |          }; | ||||||
|  |   | ||||||
|  | @@ -893,6 +901,35 @@ static int parse_argv(int argc, char *argv[]) {
 | ||||||
|  |                          arg_action = ACTION_FLUSH; | ||||||
|  |                          break; | ||||||
|  |   | ||||||
|  | +                case ARG_SMART_RELINQUISH_VAR: {
 | ||||||
|  | +                        int root_mnt_id, log_mnt_id;
 | ||||||
|  | +
 | ||||||
|  | +                        /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
 | ||||||
|  | +                         * if it's on the same mount as the root file system there's no point in
 | ||||||
|  | +                         * relinquishing access and we can leave journald write to it until the very last
 | ||||||
|  | +                         * moment. */
 | ||||||
|  | +
 | ||||||
|  | +                        r = path_get_mnt_id("/", &root_mnt_id);
 | ||||||
|  | +                        if (r < 0)
 | ||||||
|  | +                                log_debug_errno(r, "Failed to get root mount ID, ignoring: %m");
 | ||||||
|  | +                        else {
 | ||||||
|  | +                                r = path_get_mnt_id("/var/log/journal/", &log_mnt_id);
 | ||||||
|  | +                                if (r < 0)
 | ||||||
|  | +                                        log_debug_errno(r, "Failed to get journal directory mount ID, ignoring: %m");
 | ||||||
|  | +                                else if (root_mnt_id == log_mnt_id) {
 | ||||||
|  | +                                        log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
 | ||||||
|  | +                                        return 0;
 | ||||||
|  | +                                } else
 | ||||||
|  | +                                        log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
 | ||||||
|  | +                        }
 | ||||||
|  | +
 | ||||||
|  | +                        _fallthrough_;
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                case ARG_RELINQUISH_VAR:
 | ||||||
|  | +                        arg_action = ACTION_RELINQUISH_VAR;
 | ||||||
|  | +                        break;
 | ||||||
|  | +
 | ||||||
|  |                  case ARG_ROTATE: | ||||||
|  |                          arg_action = ACTION_ROTATE; | ||||||
|  |                          break; | ||||||
|  | @@ -2056,6 +2093,10 @@ static int send_signal_and_wait(int sig, const char *watch_path) {
 | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int relinquish_var(void) {
 | ||||||
|  | +        return send_signal_and_wait(SIGRTMIN+2, "/run/systemd/journal/relinquished");
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int rotate(void) { | ||||||
|  |          return send_signal_and_wait(SIGUSR2, "/run/systemd/journal/rotated"); | ||||||
|  |  } | ||||||
|  | @@ -2171,6 +2212,10 @@ int main(int argc, char *argv[]) {
 | ||||||
|  |                  r = flush_to_var(); | ||||||
|  |                  goto finish; | ||||||
|  |   | ||||||
|  | +        case ACTION_RELINQUISH_VAR:
 | ||||||
|  | +                r = relinquish_var();
 | ||||||
|  | +                goto finish;
 | ||||||
|  | +
 | ||||||
|  |          case ACTION_SYNC: | ||||||
|  |                  r = sync_journal(); | ||||||
|  |                  goto finish; | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | From ce6531045b337c3f793d1d74f1e5641e658805bb Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Fri, 5 Apr 2019 18:22:31 +0200 | ||||||
|  | Subject: [PATCH] units: automatically revert to /run logging on shutdown if | ||||||
|  |  necessary | ||||||
|  | 
 | ||||||
|  | Fixes: #867 | ||||||
|  | (cherry picked from commit 1e187d2dd52cbb4f0bb30e4d96acf7f72a145b91) | ||||||
|  | 
 | ||||||
|  | Resolves: #1873540 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-journal-flush.service.in | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-journal-flush.service.in b/units/systemd-journal-flush.service.in
 | ||||||
|  | index 439f5f3f76..653dcebe0e 100644
 | ||||||
|  | --- a/units/systemd-journal-flush.service.in
 | ||||||
|  | +++ b/units/systemd-journal-flush.service.in
 | ||||||
|  | @@ -19,6 +19,7 @@ RequiresMountsFor=/var/log/journal
 | ||||||
|  |   | ||||||
|  |  [Service] | ||||||
|  |  ExecStart=@rootbindir@/journalctl --flush | ||||||
|  | +ExecStop=@rootbindir@/journalctl --smart-relinquish-var
 | ||||||
|  |  Type=oneshot | ||||||
|  |  RemainAfterExit=yes | ||||||
|  |  TimeoutSec=90s | ||||||
							
								
								
									
										929
									
								
								SOURCES/0876-pstore-Tool-to-archive-contents-of-pstore.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										929
									
								
								SOURCES/0876-pstore-Tool-to-archive-contents-of-pstore.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,929 @@ | |||||||
|  | From 2f75df5cd6dcd56775fec9e89fc79672e702d826 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric DeVolder <eric.devolder@oracle.com> | ||||||
|  | Date: Thu, 16 May 2019 08:59:01 -0500 | ||||||
|  | Subject: [PATCH] pstore: Tool to archive contents of pstore | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | This patch introduces the systemd pstore service which will archive the | ||||||
|  | contents of the Linux persistent storage filesystem, pstore, to other storage, | ||||||
|  | thus preserving the existing information contained in the pstore, and clearing | ||||||
|  | pstore storage for future error events. | ||||||
|  | 
 | ||||||
|  | Linux provides a persistent storage file system, pstore[1], that can store | ||||||
|  | error records when the kernel dies (or reboots or powers-off). These records in | ||||||
|  | turn can be referenced to debug kernel problems (currently the kernel stuffs | ||||||
|  | the tail of the dmesg, which also contains a stack backtrace, into pstore). | ||||||
|  | 
 | ||||||
|  | The pstore file system supports a variety of backends that map onto persistent | ||||||
|  | storage, such as the ACPI ERST[2, Section 18.5 Error Serialization] and UEFI | ||||||
|  | variables[3 Appendix N Common Platform Error Record]. The pstore backends | ||||||
|  | typically offer a relatively small amount of persistent storage, e.g. 64KiB, | ||||||
|  | which can quickly fill up and thus prevent subsequent kernel crashes from | ||||||
|  | recording errors. Thus there is a need to monitor and extract the pstore | ||||||
|  | contents so that future kernel problems can also record information in the | ||||||
|  | pstore. | ||||||
|  | 
 | ||||||
|  | The pstore service is independent of the kdump service. In cloud environments | ||||||
|  | specifically, host and guest filesystems are on remote filesystems (eg. iSCSI | ||||||
|  | or NFS), thus kdump relies [implicitly and/or explicitly] upon proper operation | ||||||
|  | of networking software *and* hardware *and* infrastructure.  Thus it may not be | ||||||
|  | possible to capture a kernel coredump to a file since writes over the network | ||||||
|  | may not be possible. | ||||||
|  | 
 | ||||||
|  | The pstore backend, on the other hand, is completely local and provides a path | ||||||
|  | to store error records which will survive a reboot and aid in post-mortem | ||||||
|  | debugging. | ||||||
|  | 
 | ||||||
|  | Usage Notes: | ||||||
|  | This tool moves files from /sys/fs/pstore into /var/lib/systemd/pstore. | ||||||
|  | 
 | ||||||
|  | To enable kernel recording of error records into pstore, one must either pass | ||||||
|  | crash_kexec_post_notifiers[4] to the kernel command line or enable via 'echo Y | ||||||
|  |  > /sys/module/kernel/parameters/crash_kexec_post_notifiers'. This option | ||||||
|  | invokes the recording of errors into pstore *before* an attempt to kexec/kdump | ||||||
|  | on a kernel crash. | ||||||
|  | 
 | ||||||
|  | Optionally, to record reboots and shutdowns in the pstore, one can either pass | ||||||
|  | the printk.always_kmsg_dump[4] to the kernel command line or enable via 'echo Y > | ||||||
|  | /sys/module/printk/parameters/always_kmsg_dump'. This option enables code on the | ||||||
|  | shutdown path to record information via pstore. | ||||||
|  | 
 | ||||||
|  | This pstore service is a oneshot service. When run, the service invokes | ||||||
|  | systemd-pstore which is a tool that performs the following: | ||||||
|  |  - reads the pstore.conf configuration file | ||||||
|  |  - collects the lists of files in the pstore (eg. /sys/fs/pstore) | ||||||
|  |  - for certain file types (eg. dmesg) a handler is invoked | ||||||
|  |  - for all other files, the file is moved from pstore | ||||||
|  | 
 | ||||||
|  |  - In the case of dmesg handler, final processing occurs as such: | ||||||
|  |    - files processed in reverse lexigraphical order to faciliate | ||||||
|  |      reconstruction of original dmesg | ||||||
|  |    - the filename is examined to determine which dmesg it is a part | ||||||
|  |    - the file is appended to the reconstructed dmesg | ||||||
|  | 
 | ||||||
|  | For example, the following pstore contents: | ||||||
|  | 
 | ||||||
|  |  root@vm356:~# ls -al /sys/fs/pstore | ||||||
|  |  total 0 | ||||||
|  |  drwxr-x--- 2 root root    0 May  9 09:50 . | ||||||
|  |  drwxr-xr-x 7 root root    0 May  9 09:50 .. | ||||||
|  |  -r--r--r-- 1 root root 1610 May  9 09:49 dmesg-efi-155741337601001 | ||||||
|  |  -r--r--r-- 1 root root 1778 May  9 09:49 dmesg-efi-155741337602001 | ||||||
|  |  -r--r--r-- 1 root root 1726 May  9 09:49 dmesg-efi-155741337603001 | ||||||
|  |  -r--r--r-- 1 root root 1746 May  9 09:49 dmesg-efi-155741337604001 | ||||||
|  |  -r--r--r-- 1 root root 1686 May  9 09:49 dmesg-efi-155741337605001 | ||||||
|  |  -r--r--r-- 1 root root 1690 May  9 09:49 dmesg-efi-155741337606001 | ||||||
|  |  -r--r--r-- 1 root root 1775 May  9 09:49 dmesg-efi-155741337607001 | ||||||
|  |  -r--r--r-- 1 root root 1811 May  9 09:49 dmesg-efi-155741337608001 | ||||||
|  |  -r--r--r-- 1 root root 1817 May  9 09:49 dmesg-efi-155741337609001 | ||||||
|  |  -r--r--r-- 1 root root 1795 May  9 09:49 dmesg-efi-155741337710001 | ||||||
|  |  -r--r--r-- 1 root root 1770 May  9 09:49 dmesg-efi-155741337711001 | ||||||
|  |  -r--r--r-- 1 root root 1796 May  9 09:49 dmesg-efi-155741337712001 | ||||||
|  |  -r--r--r-- 1 root root 1787 May  9 09:49 dmesg-efi-155741337713001 | ||||||
|  |  -r--r--r-- 1 root root 1808 May  9 09:49 dmesg-efi-155741337714001 | ||||||
|  |  -r--r--r-- 1 root root 1754 May  9 09:49 dmesg-efi-155741337715001 | ||||||
|  | 
 | ||||||
|  | results in the following: | ||||||
|  | 
 | ||||||
|  |  root@vm356:~# ls -al /var/lib/systemd/pstore/155741337/ | ||||||
|  |  total 92 | ||||||
|  |  drwxr-xr-x 2 root root  4096 May  9 09:50 . | ||||||
|  |  drwxr-xr-x 4 root root    40 May  9 09:50 .. | ||||||
|  |  -rw-r--r-- 1 root root  1610 May  9 09:50 dmesg-efi-155741337601001 | ||||||
|  |  -rw-r--r-- 1 root root  1778 May  9 09:50 dmesg-efi-155741337602001 | ||||||
|  |  -rw-r--r-- 1 root root  1726 May  9 09:50 dmesg-efi-155741337603001 | ||||||
|  |  -rw-r--r-- 1 root root  1746 May  9 09:50 dmesg-efi-155741337604001 | ||||||
|  |  -rw-r--r-- 1 root root  1686 May  9 09:50 dmesg-efi-155741337605001 | ||||||
|  |  -rw-r--r-- 1 root root  1690 May  9 09:50 dmesg-efi-155741337606001 | ||||||
|  |  -rw-r--r-- 1 root root  1775 May  9 09:50 dmesg-efi-155741337607001 | ||||||
|  |  -rw-r--r-- 1 root root  1811 May  9 09:50 dmesg-efi-155741337608001 | ||||||
|  |  -rw-r--r-- 1 root root  1817 May  9 09:50 dmesg-efi-155741337609001 | ||||||
|  |  -rw-r--r-- 1 root root  1795 May  9 09:50 dmesg-efi-155741337710001 | ||||||
|  |  -rw-r--r-- 1 root root  1770 May  9 09:50 dmesg-efi-155741337711001 | ||||||
|  |  -rw-r--r-- 1 root root  1796 May  9 09:50 dmesg-efi-155741337712001 | ||||||
|  |  -rw-r--r-- 1 root root  1787 May  9 09:50 dmesg-efi-155741337713001 | ||||||
|  |  -rw-r--r-- 1 root root  1808 May  9 09:50 dmesg-efi-155741337714001 | ||||||
|  |  -rw-r--r-- 1 root root  1754 May  9 09:50 dmesg-efi-155741337715001 | ||||||
|  |  -rw-r--r-- 1 root root 26754 May  9 09:50 dmesg.txt | ||||||
|  | 
 | ||||||
|  | where dmesg.txt is reconstructed from the group of related | ||||||
|  | dmesg-efi-155741337* files. | ||||||
|  | 
 | ||||||
|  | Configuration file: | ||||||
|  | The pstore.conf configuration file has four settings, described below. | ||||||
|  |  - Storage : one of "none", "external", or "journal". With "none", this | ||||||
|  |    tool leaves the contents of pstore untouched. With "external", the | ||||||
|  |    contents of the pstore are moved into the /var/lib/systemd/pstore, | ||||||
|  |    as well as logged into the journal.  With "journal", the contents of | ||||||
|  |    the pstore are recorded only in the systemd journal. The default is | ||||||
|  |    "external". | ||||||
|  |  - Unlink : is a boolean. When "true", the default, then files in the | ||||||
|  |    pstore are removed once processed. When "false", processing of the | ||||||
|  |    pstore occurs normally, but the pstore files remain. | ||||||
|  | 
 | ||||||
|  | References: | ||||||
|  | [1] "Persistent storage for a kernel's dying breath", | ||||||
|  |     March 23, 2011. | ||||||
|  |     https://lwn.net/Articles/434821/ | ||||||
|  | 
 | ||||||
|  | [2] "Advanced Configuration and Power Interface Specification", | ||||||
|  |     version 6.2, May 2017. | ||||||
|  |     https://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf | ||||||
|  | 
 | ||||||
|  | [3] "Unified Extensible Firmware Interface Specification", | ||||||
|  |     version 2.8, March 2019. | ||||||
|  |     https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf | ||||||
|  | 
 | ||||||
|  | [4] "The kernel’s command-line parameters", | ||||||
|  |     https://static.lwn.net/kerneldoc/admin-guide/kernel-parameters.html | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 9b4abc69b201e5d7295e1b0762883659f053e747) | ||||||
|  | 
 | ||||||
|  | Resolves: #2158832 | ||||||
|  | ---
 | ||||||
|  |  man/pstore.conf.xml             |  89 +++++++ | ||||||
|  |  man/rules/meson.build           |   2 + | ||||||
|  |  man/systemd-pstore.xml          |  99 ++++++++ | ||||||
|  |  meson.build                     |  20 ++ | ||||||
|  |  meson_options.txt               |   2 + | ||||||
|  |  src/pstore/meson.build          |  10 + | ||||||
|  |  src/pstore/pstore.c             | 395 ++++++++++++++++++++++++++++++++ | ||||||
|  |  src/pstore/pstore.conf          |  16 ++ | ||||||
|  |  units/meson.build               |   1 + | ||||||
|  |  units/systemd-pstore.service.in |  24 ++ | ||||||
|  |  10 files changed, 658 insertions(+) | ||||||
|  |  create mode 100644 man/pstore.conf.xml | ||||||
|  |  create mode 100644 man/systemd-pstore.xml | ||||||
|  |  create mode 100644 src/pstore/meson.build | ||||||
|  |  create mode 100644 src/pstore/pstore.c | ||||||
|  |  create mode 100644 src/pstore/pstore.conf | ||||||
|  |  create mode 100644 units/systemd-pstore.service.in | ||||||
|  | 
 | ||||||
|  | diff --git a/man/pstore.conf.xml b/man/pstore.conf.xml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..b5cda47d02
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/man/pstore.conf.xml
 | ||||||
|  | @@ -0,0 +1,89 @@
 | ||||||
|  | +<?xml version='1.0'?>
 | ||||||
|  | +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
 | ||||||
|  | +  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 | ||||||
|  | +<!-- SPDX-License-Identifier: LGPL-2.1+ -->
 | ||||||
|  | +
 | ||||||
|  | +<refentry id="pstore.conf" conditional="ENABLE_PSTORE"
 | ||||||
|  | +          xmlns:xi="http://www.w3.org/2001/XInclude">
 | ||||||
|  | +  <refentryinfo>
 | ||||||
|  | +    <title>pstore.conf</title>
 | ||||||
|  | +    <productname>systemd</productname>
 | ||||||
|  | +  </refentryinfo>
 | ||||||
|  | +
 | ||||||
|  | +  <refmeta>
 | ||||||
|  | +    <refentrytitle>pstore.conf</refentrytitle>
 | ||||||
|  | +    <manvolnum>5</manvolnum>
 | ||||||
|  | +  </refmeta>
 | ||||||
|  | +
 | ||||||
|  | +  <refnamediv>
 | ||||||
|  | +    <refname>pstore.conf</refname>
 | ||||||
|  | +    <refname>pstore.conf.d</refname>
 | ||||||
|  | +    <refpurpose>PStore configuration file</refpurpose>
 | ||||||
|  | +  </refnamediv>
 | ||||||
|  | +
 | ||||||
|  | +  <refsynopsisdiv>
 | ||||||
|  | +    <para>
 | ||||||
|  | +    <filename>/etc/systemd/pstore.conf</filename>
 | ||||||
|  | +    <filename>/etc/systemd/pstore.conf.d/*</filename>
 | ||||||
|  | +    </para>
 | ||||||
|  | +  </refsynopsisdiv>
 | ||||||
|  | +
 | ||||||
|  | +  <refsect1>
 | ||||||
|  | +    <title>Description</title>
 | ||||||
|  | +
 | ||||||
|  | +    <para>This file configures the behavior of
 | ||||||
|  | +    <citerefentry><refentrytitle>systemd-pstore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
 | ||||||
|  | +    a tool for archiving the contents of the persistent storage filesystem,
 | ||||||
|  | +    <ulink url="https://www.kernel.org/doc/Documentation/ABI/testing/pstore">pstore</ulink>.
 | ||||||
|  | +    </para>
 | ||||||
|  | +  </refsect1>
 | ||||||
|  | +
 | ||||||
|  | +  <xi:include href="standard-conf.xml" xpointer="main-conf" />
 | ||||||
|  | +
 | ||||||
|  | +  <refsect1>
 | ||||||
|  | +    <title>Options</title>
 | ||||||
|  | +
 | ||||||
|  | +    <para>All options are configured in the
 | ||||||
|  | +    <literal>[PStore]</literal> section:</para>
 | ||||||
|  | +
 | ||||||
|  | +    <variablelist>
 | ||||||
|  | +
 | ||||||
|  | +      <varlistentry>
 | ||||||
|  | +        <term><varname>Storage=</varname></term>
 | ||||||
|  | +
 | ||||||
|  | +        <listitem><para>Controls where to archive (i.e. copy) files from the pstore filesystem. One of <literal>none</literal>,
 | ||||||
|  | +        <literal>external</literal>, and <literal>journal</literal>. When
 | ||||||
|  | +        <literal>none</literal>, the tool exits without processing files in the pstore filesystem.
 | ||||||
|  | +        When <literal>external</literal> (the default), files are archived into <filename>/var/lib/systemd/pstore/</filename>,
 | ||||||
|  | +        and logged into the journal.
 | ||||||
|  | +        When <literal>journal</literal>, pstore file contents are logged only in the journal.</para>
 | ||||||
|  | +        </listitem>
 | ||||||
|  | +
 | ||||||
|  | +      </varlistentry>
 | ||||||
|  | +
 | ||||||
|  | +      <varlistentry>
 | ||||||
|  | +        <term><varname>Unlink=</varname></term>
 | ||||||
|  | +
 | ||||||
|  | +        <listitem><para>Controls whether or not files are removed from pstore after processing.
 | ||||||
|  | +        Takes a boolean value. When true, a pstore file is removed from the pstore once it has been
 | ||||||
|  | +        archived (either to disk or into the journal). When false, processing of pstore files occurs
 | ||||||
|  | +        normally, but the files remain in the pstore.
 | ||||||
|  | +        The default is true in order to maintain the pstore in a nearly empty state, so that the pstore
 | ||||||
|  | +        has storage available for the next kernel error event.
 | ||||||
|  | +        </para></listitem>
 | ||||||
|  | +      </varlistentry>
 | ||||||
|  | +    </variablelist>
 | ||||||
|  | +
 | ||||||
|  | +    <para>The defaults for all values are listed as comments in the
 | ||||||
|  | +    template <filename>/etc/systemd/pstore.conf</filename> file that
 | ||||||
|  | +    is installed by default.</para>
 | ||||||
|  | +  </refsect1>
 | ||||||
|  | +
 | ||||||
|  | +  <refsect1>
 | ||||||
|  | +    <title>See Also</title>
 | ||||||
|  | +    <para>
 | ||||||
|  | +      <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
 | ||||||
|  | +    </para>
 | ||||||
|  | +  </refsect1>
 | ||||||
|  | +
 | ||||||
|  | +</refentry>
 | ||||||
|  | diff --git a/man/rules/meson.build b/man/rules/meson.build
 | ||||||
|  | index e6c0a99bbd..6295330c5e 100644
 | ||||||
|  | --- a/man/rules/meson.build
 | ||||||
|  | +++ b/man/rules/meson.build
 | ||||||
|  | @@ -44,6 +44,7 @@ manpages = [
 | ||||||
|  |   ['os-release', '5', [], ''], | ||||||
|  |   ['pam_systemd', '8', [], 'HAVE_PAM'], | ||||||
|  |   ['portablectl', '1', [], 'ENABLE_PORTABLED'], | ||||||
|  | + ['pstore.conf', '5', ['pstore.conf.d'], 'ENABLE_PSTORE'],
 | ||||||
|  |   ['resolvectl', '1', ['resolvconf'], 'ENABLE_RESOLVE'], | ||||||
|  |   ['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'], | ||||||
|  |   ['runlevel', '8', [], 'ENABLE_UTMP'], | ||||||
|  | @@ -633,6 +634,7 @@ manpages = [
 | ||||||
|  |   ['systemd-nspawn', '1', [], ''], | ||||||
|  |   ['systemd-path', '1', [], ''], | ||||||
|  |   ['systemd-portabled.service', '8', ['systemd-portabled'], 'ENABLE_PORTABLED'], | ||||||
|  | + ['systemd-pstore', '8', ['systemd-pstore.service'], 'ENABLE_PSTORE'],
 | ||||||
|  |   ['systemd-quotacheck.service', | ||||||
|  |    '8', | ||||||
|  |    ['systemd-quotacheck'], | ||||||
|  | diff --git a/man/systemd-pstore.xml b/man/systemd-pstore.xml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..dd1aa5e83b
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/man/systemd-pstore.xml
 | ||||||
|  | @@ -0,0 +1,99 @@
 | ||||||
|  | +<?xml version='1.0'?>
 | ||||||
|  | +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
 | ||||||
|  | +  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 | ||||||
|  | +<!-- SPDX-License-Identifier: LGPL-2.1+ -->
 | ||||||
|  | +
 | ||||||
|  | +<refentry id="systemd-pstore" conditional='ENABLE_PSTORE'
 | ||||||
|  | +          xmlns:xi="http://www.w3.org/2001/XInclude">
 | ||||||
|  | +
 | ||||||
|  | +  <refentryinfo>
 | ||||||
|  | +    <title>systemd-pstore</title>
 | ||||||
|  | +    <productname>systemd</productname>
 | ||||||
|  | +  </refentryinfo>
 | ||||||
|  | +
 | ||||||
|  | +  <refmeta>
 | ||||||
|  | +    <refentrytitle>systemd-pstore</refentrytitle>
 | ||||||
|  | +    <manvolnum>8</manvolnum>
 | ||||||
|  | +  </refmeta>
 | ||||||
|  | +
 | ||||||
|  | +  <refnamediv>
 | ||||||
|  | +    <refname>systemd-pstore</refname>
 | ||||||
|  | +    <refname>systemd-pstore.service</refname>
 | ||||||
|  | +    <refpurpose>Tool to archive contents of the persistent storage filesytem</refpurpose>
 | ||||||
|  | +  </refnamediv>
 | ||||||
|  | +
 | ||||||
|  | +  <refsynopsisdiv>
 | ||||||
|  | +    <para><filename>/usr/lib/systemd/systemd-pstore</filename></para>
 | ||||||
|  | +    <para><filename>systemd-pstore.service</filename></para>
 | ||||||
|  | +  </refsynopsisdiv>
 | ||||||
|  | +
 | ||||||
|  | +  <refsect1>
 | ||||||
|  | +    <title>Description</title>
 | ||||||
|  | +    <para><filename>systemd-pstore.service</filename> is a system service that archives the
 | ||||||
|  | +    contents of the Linux persistent storage filesystem, pstore, to other storage,
 | ||||||
|  | +    thus preserving the existing information contained in the pstore, and clearing
 | ||||||
|  | +    pstore storage for future error events.</para>
 | ||||||
|  | +
 | ||||||
|  | +    <para>Linux provides a persistent storage file system, pstore, that can store
 | ||||||
|  | +    error records when the kernel dies (or reboots or powers-off). These records in
 | ||||||
|  | +    turn can be referenced to debug kernel problems (currently the kernel stuffs
 | ||||||
|  | +    the tail of the dmesg, which also contains a stack backtrace, into pstore).</para>
 | ||||||
|  | +
 | ||||||
|  | +    <para>The pstore file system supports a variety of backends that map onto persistent
 | ||||||
|  | +    storage, such as the ACPI ERST and UEFI variables. The pstore backends
 | ||||||
|  | +    typically offer a relatively small amount of persistent storage, e.g. 64KiB,
 | ||||||
|  | +    which can quickly fill up and thus prevent subsequent kernel crashes from
 | ||||||
|  | +    recording errors. Thus there is a need to monitor and extract the pstore
 | ||||||
|  | +    contents so that future kernel problems can also record information in the
 | ||||||
|  | +    pstore.</para>
 | ||||||
|  | +
 | ||||||
|  | +    <para>The pstore service is independent of the kdump service. In cloud environments
 | ||||||
|  | +    specifically, host and guest filesystems are on remote filesystems (eg. iSCSI
 | ||||||
|  | +    or NFS), thus kdump relies [implicitly and/or explicitly] upon proper operation
 | ||||||
|  | +    of networking software *and* hardware *and* infrastructure.  Thus it may not be
 | ||||||
|  | +    possible to capture a kernel coredump to a file since writes over the network
 | ||||||
|  | +    may not be possible.</para>
 | ||||||
|  | +
 | ||||||
|  | +    <para>The pstore backend, on the other hand, is completely local and provides a path
 | ||||||
|  | +    to store error records which will survive a reboot and aid in post-mortem
 | ||||||
|  | +    debugging.</para>
 | ||||||
|  | +
 | ||||||
|  | +    <para>The <command>systemd-pstore</command> executable does the actual work. Upon starting,
 | ||||||
|  | +    the <filename>pstore.conf</filename> is read to obtain options, then the /sys/fs/pstore
 | ||||||
|  | +    directory contents are processed according to the options. Pstore files are written to the
 | ||||||
|  | +    journal, and optionally saved into /var/lib/systemd/pstore.</para>
 | ||||||
|  | +  </refsect1>
 | ||||||
|  | +
 | ||||||
|  | +  <refsect1>
 | ||||||
|  | +    <title>Configuration</title>
 | ||||||
|  | +
 | ||||||
|  | +    <para>The behavior of <command>systemd-pstore</command> is configured through the configuration file
 | ||||||
|  | +    <filename>/etc/systemd/pstore.conf</filename> and corresponding snippets
 | ||||||
|  | +    <filename>/etc/systemd/pstore.conf.d/*.conf</filename>, see
 | ||||||
|  | +    <citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
 | ||||||
|  | +    </para>
 | ||||||
|  | +
 | ||||||
|  | +    <refsect2>
 | ||||||
|  | +      <title>Disabling pstore processing</title>
 | ||||||
|  | +
 | ||||||
|  | +      <para>To disable pstore processing by <command>systemd-pstore</command>,
 | ||||||
|  | +      set <programlisting>Storage=none</programlisting> in
 | ||||||
|  | +      <citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
 | ||||||
|  | +      </para>
 | ||||||
|  | +    </refsect2>
 | ||||||
|  | +  </refsect1>
 | ||||||
|  | +
 | ||||||
|  | +  <refsect1>
 | ||||||
|  | +    <title>Usage</title>
 | ||||||
|  | +    <para>Data stored in the journal can be viewed with
 | ||||||
|  | +    <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
 | ||||||
|  | +    as usual.</para>
 | ||||||
|  | +  </refsect1>
 | ||||||
|  | +
 | ||||||
|  | +  <refsect1>
 | ||||||
|  | +    <title>See Also</title>
 | ||||||
|  | +    <para>
 | ||||||
|  | +      <citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
 | ||||||
|  | +    </para>
 | ||||||
|  | +  </refsect1>
 | ||||||
|  | +</refentry>
 | ||||||
|  | diff --git a/meson.build b/meson.build
 | ||||||
|  | index af4cf331da..972a8fb6f7 100644
 | ||||||
|  | --- a/meson.build
 | ||||||
|  | +++ b/meson.build
 | ||||||
|  | @@ -1224,6 +1224,7 @@ foreach term : ['utmp',
 | ||||||
|  |                  'environment-d', | ||||||
|  |                  'binfmt', | ||||||
|  |                  'coredump', | ||||||
|  | +                'pstore',
 | ||||||
|  |                  'resolve', | ||||||
|  |                  'logind', | ||||||
|  |                  'hostnamed', | ||||||
|  | @@ -1439,6 +1440,7 @@ subdir('src/network')
 | ||||||
|  |  subdir('src/analyze') | ||||||
|  |  subdir('src/journal-remote') | ||||||
|  |  subdir('src/coredump') | ||||||
|  | +subdir('src/pstore')
 | ||||||
|  |  subdir('src/hostname') | ||||||
|  |  subdir('src/import') | ||||||
|  |  subdir('src/kernel-install') | ||||||
|  | @@ -2151,6 +2153,23 @@ if conf.get('ENABLE_COREDUMP') == 1
 | ||||||
|  |          public_programs += [exe] | ||||||
|  |  endif | ||||||
|  |   | ||||||
|  | +if conf.get('ENABLE_PSTORE') == 1
 | ||||||
|  | +        executable('systemd-pstore',
 | ||||||
|  | +                   systemd_pstore_sources,
 | ||||||
|  | +                   include_directories : includes,
 | ||||||
|  | +                   link_with : [libshared],
 | ||||||
|  | +                   dependencies : [threads,
 | ||||||
|  | +                                   libacl,
 | ||||||
|  | +                                   libdw,
 | ||||||
|  | +                                   libxz,
 | ||||||
|  | +                                   liblz4],
 | ||||||
|  | +                   install_rpath : rootlibexecdir,
 | ||||||
|  | +                   install : true,
 | ||||||
|  | +                   install_dir : rootlibexecdir)
 | ||||||
|  | +
 | ||||||
|  | +        public_programs += exe
 | ||||||
|  | +endif
 | ||||||
|  | +
 | ||||||
|  |  if conf.get('ENABLE_BINFMT') == 1 | ||||||
|  |          exe = executable('systemd-binfmt', | ||||||
|  |                           'src/binfmt/binfmt.c', | ||||||
|  | @@ -3014,6 +3033,7 @@ foreach tuple : [
 | ||||||
|  |          ['resolve'], | ||||||
|  |          ['DNS-over-TLS'], | ||||||
|  |          ['coredump'], | ||||||
|  | +        ['pstore'],
 | ||||||
|  |          ['polkit'], | ||||||
|  |          ['legacy pkla',      install_polkit_pkla], | ||||||
|  |          ['efi'], | ||||||
|  | diff --git a/meson_options.txt b/meson_options.txt
 | ||||||
|  | index 213079ac15..5624304bf4 100644
 | ||||||
|  | --- a/meson_options.txt
 | ||||||
|  | +++ b/meson_options.txt
 | ||||||
|  | @@ -76,6 +76,8 @@ option('binfmt', type : 'boolean',
 | ||||||
|  |         description : 'support for custom binary formats') | ||||||
|  |  option('coredump', type : 'boolean', | ||||||
|  |         description : 'install the coredump handler') | ||||||
|  | +option('pstore', type : 'boolean',
 | ||||||
|  | +       description : 'install the pstore archival tool')
 | ||||||
|  |  option('logind', type : 'boolean', | ||||||
|  |         description : 'install the systemd-logind stack') | ||||||
|  |  option('hostnamed', type : 'boolean', | ||||||
|  | diff --git a/src/pstore/meson.build b/src/pstore/meson.build
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..adbac24b54
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/src/pstore/meson.build
 | ||||||
|  | @@ -0,0 +1,10 @@
 | ||||||
|  | +# SPDX-License-Identifier: LGPL-2.1+
 | ||||||
|  | +
 | ||||||
|  | +systemd_pstore_sources = files('''
 | ||||||
|  | +        pstore.c
 | ||||||
|  | +'''.split())
 | ||||||
|  | +
 | ||||||
|  | +if conf.get('ENABLE_PSTORE') == 1
 | ||||||
|  | +        install_data('pstore.conf',
 | ||||||
|  | +                     install_dir : pkgsysconfdir)
 | ||||||
|  | +endif
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..f95e016eb6
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -0,0 +1,395 @@
 | ||||||
|  | +/* SPDX-License-Identifier: LGPL-2.1+ */
 | ||||||
|  | +
 | ||||||
|  | +/* Copyright © 2019 Oracle and/or its affiliates. */
 | ||||||
|  | +
 | ||||||
|  | +/* Generally speaking, the pstore contains a small number of files
 | ||||||
|  | + * that in turn contain a small amount of data.  */
 | ||||||
|  | +#include <errno.h>
 | ||||||
|  | +#include <stdio.h>
 | ||||||
|  | +#include <stdio_ext.h>
 | ||||||
|  | +#include <sys/prctl.h>
 | ||||||
|  | +#include <sys/xattr.h>
 | ||||||
|  | +#include <unistd.h>
 | ||||||
|  | +
 | ||||||
|  | +#include "sd-daemon.h"
 | ||||||
|  | +#include "sd-journal.h"
 | ||||||
|  | +#include "sd-login.h"
 | ||||||
|  | +#include "sd-messages.h"
 | ||||||
|  | +
 | ||||||
|  | +#include "acl-util.h"
 | ||||||
|  | +#include "alloc-util.h"
 | ||||||
|  | +#include "capability-util.h"
 | ||||||
|  | +#include "cgroup-util.h"
 | ||||||
|  | +#include "compress.h"
 | ||||||
|  | +#include "conf-parser.h"
 | ||||||
|  | +#include "copy.h"
 | ||||||
|  | +#include "dirent-util.h"
 | ||||||
|  | +#include "escape.h"
 | ||||||
|  | +#include "fd-util.h"
 | ||||||
|  | +#include "fileio.h"
 | ||||||
|  | +#include "fs-util.h"
 | ||||||
|  | +#include "io-util.h"
 | ||||||
|  | +#include "journal-importer.h"
 | ||||||
|  | +#include "log.h"
 | ||||||
|  | +#include "macro.h"
 | ||||||
|  | +#include "missing.h"
 | ||||||
|  | +#include "mkdir.h"
 | ||||||
|  | +#include "parse-util.h"
 | ||||||
|  | +#include "process-util.h"
 | ||||||
|  | +#include "signal-util.h"
 | ||||||
|  | +#include "socket-util.h"
 | ||||||
|  | +#include "special.h"
 | ||||||
|  | +#include "string-table.h"
 | ||||||
|  | +#include "string-util.h"
 | ||||||
|  | +#include "strv.h"
 | ||||||
|  | +#include "user-util.h"
 | ||||||
|  | +#include "util.h"
 | ||||||
|  | +
 | ||||||
|  | +/* Command line argument handling */
 | ||||||
|  | +typedef enum PStoreStorage {
 | ||||||
|  | +        PSTORE_STORAGE_NONE,
 | ||||||
|  | +        PSTORE_STORAGE_EXTERNAL,
 | ||||||
|  | +        PSTORE_STORAGE_JOURNAL,
 | ||||||
|  | +        _PSTORE_STORAGE_MAX,
 | ||||||
|  | +        _PSTORE_STORAGE_INVALID = -1
 | ||||||
|  | +} PStoreStorage;
 | ||||||
|  | +
 | ||||||
|  | +static const char* const pstore_storage_table[_PSTORE_STORAGE_MAX] = {
 | ||||||
|  | +        [PSTORE_STORAGE_NONE] = "none",
 | ||||||
|  | +        [PSTORE_STORAGE_EXTERNAL] = "external",
 | ||||||
|  | +        [PSTORE_STORAGE_JOURNAL] = "journal",
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  | +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(pstore_storage, PStoreStorage);
 | ||||||
|  | +static DEFINE_CONFIG_PARSE_ENUM(config_parse_pstore_storage, pstore_storage, PStoreStorage, "Failed to parse storage setting");
 | ||||||
|  | +
 | ||||||
|  | +static PStoreStorage arg_storage = PSTORE_STORAGE_EXTERNAL;
 | ||||||
|  | +
 | ||||||
|  | +static bool arg_unlink = true;
 | ||||||
|  | +static const char *arg_sourcedir = "/sys/fs/pstore";
 | ||||||
|  | +static const char *arg_archivedir = "/var/lib/systemd/pstore";
 | ||||||
|  | +
 | ||||||
|  | +static int parse_config(void) {
 | ||||||
|  | +        static const ConfigTableItem items[] = {
 | ||||||
|  | +                { "PStore", "Unlink",  config_parse_bool,           0, &arg_unlink },
 | ||||||
|  | +                { "PStore", "Storage", config_parse_pstore_storage, 0, &arg_storage },
 | ||||||
|  | +                {}
 | ||||||
|  | +        };
 | ||||||
|  | +
 | ||||||
|  | +        return config_parse_many_nulstr(PKGSYSCONFDIR "/pstore.conf",
 | ||||||
|  | +                                        CONF_PATHS_NULSTR("systemd/pstore.conf.d"),
 | ||||||
|  | +                                        "PStore\0",
 | ||||||
|  | +                                        config_item_table_lookup, items,
 | ||||||
|  | +                                        CONFIG_PARSE_WARN, NULL);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +/* File list handling - PStoreEntry is the struct and
 | ||||||
|  | + * and PStoreEntry is the type that contains all info
 | ||||||
|  | + * about a pstore entry.  */
 | ||||||
|  | +typedef struct PStoreEntry {
 | ||||||
|  | +        struct dirent dirent;
 | ||||||
|  | +        bool is_binary;
 | ||||||
|  | +        bool handled;
 | ||||||
|  | +        char *content;
 | ||||||
|  | +        size_t content_size;
 | ||||||
|  | +} PStoreEntry;
 | ||||||
|  | +
 | ||||||
|  | +typedef struct PStoreList {
 | ||||||
|  | +        PStoreEntry *entries;
 | ||||||
|  | +        size_t n_entries;
 | ||||||
|  | +        size_t n_entries_allocated;
 | ||||||
|  | +} PStoreList;
 | ||||||
|  | +
 | ||||||
|  | +static void pstore_entries_reset(PStoreList *list) {
 | ||||||
|  | +        for (size_t i = 0; i < list->n_entries; i++)
 | ||||||
|  | +                free(list->entries[i].content);
 | ||||||
|  | +        free(list->entries);
 | ||||||
|  | +        list->n_entries = 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int compare_pstore_entries(const void *_a, const void *_b) {
 | ||||||
|  | +        PStoreEntry *a = (PStoreEntry *)_a, *b = (PStoreEntry *)_b;
 | ||||||
|  | +        return strcmp(a->dirent.d_name, b->dirent.d_name);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int move_file(PStoreEntry *pe, const char *subdir) {
 | ||||||
|  | +        _cleanup_free_ char *ifd_path = NULL;
 | ||||||
|  | +        _cleanup_free_ char *ofd_path = NULL;
 | ||||||
|  | +        int r = 0;
 | ||||||
|  | +        struct iovec iovec[2] = {};
 | ||||||
|  | +        int n_iovec = 0;
 | ||||||
|  | +        _cleanup_free_ void *field = NULL;
 | ||||||
|  | +        const char *suffix = NULL;
 | ||||||
|  | +        size_t field_size;
 | ||||||
|  | +
 | ||||||
|  | +        if (pe->handled)
 | ||||||
|  | +                return 0;
 | ||||||
|  | +
 | ||||||
|  | +        ifd_path = path_join(NULL, arg_sourcedir, pe->dirent.d_name);
 | ||||||
|  | +        if (!ifd_path)
 | ||||||
|  | +                return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +        ofd_path = path_join(arg_archivedir, subdir, pe->dirent.d_name);
 | ||||||
|  | +        if (!ofd_path)
 | ||||||
|  | +                return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +        /* Always log to the journal */
 | ||||||
|  | +        suffix = arg_storage == PSTORE_STORAGE_EXTERNAL ? strjoina(" moved to ", ofd_path) : (char *)".";
 | ||||||
|  | +        field = strjoina("MESSAGE=PStore ", pe->dirent.d_name, suffix);
 | ||||||
|  | +        iovec[n_iovec++] = IOVEC_MAKE_STRING(field);
 | ||||||
|  | +
 | ||||||
|  | +        field_size = strlen("FILE=") + pe->content_size;
 | ||||||
|  | +        field = malloc(field_size);
 | ||||||
|  | +        if (!field)
 | ||||||
|  | +                return log_oom();
 | ||||||
|  | +        memcpy(stpcpy(field, "FILE="), pe->content, pe->content_size);
 | ||||||
|  | +        iovec[n_iovec++] = IOVEC_MAKE(field, field_size);
 | ||||||
|  | +
 | ||||||
|  | +        r = sd_journal_sendv(iovec, n_iovec);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                return log_error_errno(r, "Failed to log pstore entry: %m");
 | ||||||
|  | +
 | ||||||
|  | +        if (arg_storage == PSTORE_STORAGE_EXTERNAL) {
 | ||||||
|  | +                /* Move file from pstore to external storage */
 | ||||||
|  | +                r = mkdir_parents(ofd_path, 0755);
 | ||||||
|  | +                if (r < 0)
 | ||||||
|  | +                        return log_error_errno(r, "Failed to create directoy %s: %m", ofd_path);
 | ||||||
|  | +                r = copy_file_atomic(ifd_path, ofd_path, 0600, 0, COPY_REPLACE);
 | ||||||
|  | +                if (r < 0)
 | ||||||
|  | +                        return log_error_errno(r, "Failed to copy_file_atomic: %s to %s", ifd_path, ofd_path);
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        /* If file copied properly, remove it from pstore */
 | ||||||
|  | +        if (arg_unlink)
 | ||||||
|  | +                (void) unlink(ifd_path);
 | ||||||
|  | +
 | ||||||
|  | +        pe->handled = true;
 | ||||||
|  | +
 | ||||||
|  | +        return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int write_dmesg(const char *dmesg, size_t size, const char *id) {
 | ||||||
|  | +        _cleanup_(unlink_and_freep) char *ofd_path = NULL;
 | ||||||
|  | +        _cleanup_free_ char *tmp_path = NULL;
 | ||||||
|  | +        _cleanup_close_ int ofd = -1;
 | ||||||
|  | +        ssize_t wr;
 | ||||||
|  | +        int r;
 | ||||||
|  | +
 | ||||||
|  | +        if (isempty(dmesg) || size == 0)
 | ||||||
|  | +                return 0;
 | ||||||
|  | +
 | ||||||
|  | +        /* log_info("Record ID %s", id); */
 | ||||||
|  | +
 | ||||||
|  | +        ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
 | ||||||
|  | +        if (!ofd_path)
 | ||||||
|  | +                return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +        ofd = open_tmpfile_linkable(ofd_path, O_CLOEXEC|O_CREAT|O_TRUNC|O_WRONLY, &tmp_path);
 | ||||||
|  | +        if (ofd < 0)
 | ||||||
|  | +                return log_error_errno(ofd, "Failed to open temporary file %s: %m", ofd_path);
 | ||||||
|  | +        wr = write(ofd, dmesg, size);
 | ||||||
|  | +        if (wr < 0)
 | ||||||
|  | +                return log_error_errno(errno, "Failed to store dmesg to %s: %m", ofd_path);
 | ||||||
|  | +        if (wr != (ssize_t)size)
 | ||||||
|  | +                return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, size - wr);
 | ||||||
|  | +        r = link_tmpfile(ofd, tmp_path, ofd_path);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path);
 | ||||||
|  | +        ofd_path = mfree(ofd_path);
 | ||||||
|  | +
 | ||||||
|  | +        return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static void process_dmesg_files(PStoreList *list) {
 | ||||||
|  | +        /* Move files, reconstruct dmesg.txt */
 | ||||||
|  | +        PStoreEntry *pe;
 | ||||||
|  | +        _cleanup_free_ char *dmesg = NULL;
 | ||||||
|  | +        size_t dmesg_size = 0;
 | ||||||
|  | +        _cleanup_free_ char *dmesg_id = NULL;
 | ||||||
|  | +
 | ||||||
|  | +        /* Handle each dmesg file: files processed in reverse
 | ||||||
|  | +         * order so as to properly reconstruct original dmesg */
 | ||||||
|  | +        for (size_t n = list->n_entries; n > 0; n--) {
 | ||||||
|  | +                bool move_file_and_continue = false;
 | ||||||
|  | +                _cleanup_free_ char *pe_id = NULL;
 | ||||||
|  | +                char *p;
 | ||||||
|  | +                size_t plen;
 | ||||||
|  | +
 | ||||||
|  | +                pe = &list->entries[n-1];
 | ||||||
|  | +
 | ||||||
|  | +                if (pe->handled)
 | ||||||
|  | +                        continue;
 | ||||||
|  | +                if (!startswith(pe->dirent.d_name, "dmesg-"))
 | ||||||
|  | +                        continue;
 | ||||||
|  | +
 | ||||||
|  | +                if (endswith(pe->dirent.d_name, ".enc.z")) /* indicates a problem */
 | ||||||
|  | +                        move_file_and_continue = true;
 | ||||||
|  | +                p = strrchr(pe->dirent.d_name, '-');
 | ||||||
|  | +                if (!p)
 | ||||||
|  | +                        move_file_and_continue = true;
 | ||||||
|  | +
 | ||||||
|  | +                if (move_file_and_continue) {
 | ||||||
|  | +                        /* A dmesg file on which we do NO additional processing */
 | ||||||
|  | +                        (void) move_file(pe, NULL);
 | ||||||
|  | +                        continue;
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                /* See if this file is one of a related group of files
 | ||||||
|  | +                 * in order to reconstruct dmesg */
 | ||||||
|  | +
 | ||||||
|  | +                /* When dmesg is written into pstore, it is done so in
 | ||||||
|  | +                 * small chunks, whatever the exchange buffer size is
 | ||||||
|  | +                 * with the underlying pstore backend (ie. EFI may be
 | ||||||
|  | +                 * ~2KiB), which means an example pstore with approximately
 | ||||||
|  | +                 * 64KB of storage may have up to roughly 32 dmesg files
 | ||||||
|  | +                 * that could be related, depending upon the size of the
 | ||||||
|  | +                 * original dmesg.
 | ||||||
|  | +                 *
 | ||||||
|  | +                 * Here we look at the dmesg filename and try to discern
 | ||||||
|  | +                 * if files are part of a related group, meaning the same
 | ||||||
|  | +                 * original dmesg.
 | ||||||
|  | +                 *
 | ||||||
|  | +                 * The two known pstore backends are EFI and ERST. These
 | ||||||
|  | +                 * backends store data in the Common Platform Error
 | ||||||
|  | +                 * Record, CPER, format. The dmesg- filename contains the
 | ||||||
|  | +                 * CPER record id, a 64bit number (in decimal notation).
 | ||||||
|  | +                 * In Linux, the record id is encoded with two digits for
 | ||||||
|  | +                 * the dmesg part (chunk) number and 3 digits for the
 | ||||||
|  | +                 * count number. So allowing an additional digit to
 | ||||||
|  | +                 * compensate for advancing time, this code ignores the
 | ||||||
|  | +                 * last six digits of the filename in determining the
 | ||||||
|  | +                 * record id.
 | ||||||
|  | +                 *
 | ||||||
|  | +                 * For the EFI backend, the record id encodes an id in the
 | ||||||
|  | +                 * upper 32 bits, and a timestamp in the lower 32-bits.
 | ||||||
|  | +                 * So ignoring the least significant 6 digits has proven
 | ||||||
|  | +                 * to generally identify related dmesg entries.  */
 | ||||||
|  | +#define PSTORE_FILENAME_IGNORE 6
 | ||||||
|  | +
 | ||||||
|  | +                /* determine common portion of record id */
 | ||||||
|  | +                ++p; /* move beyond dmesg- */
 | ||||||
|  | +                plen = strlen(p);
 | ||||||
|  | +                if (plen > PSTORE_FILENAME_IGNORE) {
 | ||||||
|  | +                        pe_id = memdup_suffix0(p, plen - PSTORE_FILENAME_IGNORE);
 | ||||||
|  | +                        if (!pe_id) {
 | ||||||
|  | +                                log_oom();
 | ||||||
|  | +                                return;
 | ||||||
|  | +                        }
 | ||||||
|  | +                } else
 | ||||||
|  | +                        pe_id = mfree(pe_id);
 | ||||||
|  | +
 | ||||||
|  | +                /* Now move file from pstore to archive storage */
 | ||||||
|  | +                move_file(pe, pe_id);
 | ||||||
|  | +
 | ||||||
|  | +                /* If the current record id is NOT the same as the
 | ||||||
|  | +                 * previous record id, then start a new dmesg.txt file */
 | ||||||
|  | +                if (!pe_id || !dmesg_id || !streq(pe_id, dmesg_id)) {
 | ||||||
|  | +                        /* Encountered a new dmesg group, close out old one, open new one */
 | ||||||
|  | +                        if (dmesg) {
 | ||||||
|  | +                                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
 | ||||||
|  | +                                dmesg = mfree(dmesg);
 | ||||||
|  | +                                dmesg_size = 0;
 | ||||||
|  | +                        }
 | ||||||
|  | +
 | ||||||
|  | +                        /* now point dmesg_id to storage of pe_id */
 | ||||||
|  | +                        free_and_replace(dmesg_id, pe_id);
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                /* Reconstruction of dmesg is done as a useful courtesy, do not log errors */
 | ||||||
|  | +                dmesg = realloc(dmesg, dmesg_size + strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1);
 | ||||||
|  | +                if (dmesg) {
 | ||||||
|  | +                        dmesg_size += sprintf(&dmesg[dmesg_size], "%s:\n", pe->dirent.d_name);
 | ||||||
|  | +                        if (pe->content) {
 | ||||||
|  | +                                memcpy(&dmesg[dmesg_size], pe->content, pe->content_size);
 | ||||||
|  | +                                dmesg_size += pe->content_size;
 | ||||||
|  | +                        }
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                pe_id = mfree(pe_id);
 | ||||||
|  | +        }
 | ||||||
|  | +        if (dmesg)
 | ||||||
|  | +                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int list_files(PStoreList *list, const char *sourcepath) {
 | ||||||
|  | +        _cleanup_(closedirp) DIR *dirp = NULL;
 | ||||||
|  | +        struct dirent *de;
 | ||||||
|  | +        int r = 0;
 | ||||||
|  | +
 | ||||||
|  | +        dirp = opendir(sourcepath);
 | ||||||
|  | +        if (!dirp)
 | ||||||
|  | +                return log_error_errno(errno, "Failed to opendir %s: %m", sourcepath);
 | ||||||
|  | +
 | ||||||
|  | +        FOREACH_DIRENT(de, dirp, return log_error_errno(errno, "Failed to iterate through %s: %m", sourcepath)) {
 | ||||||
|  | +                _cleanup_free_ char *ifd_path = NULL;
 | ||||||
|  | +
 | ||||||
|  | +                ifd_path = path_join(NULL, sourcepath, de->d_name);
 | ||||||
|  | +                if (!ifd_path)
 | ||||||
|  | +                        return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +                _cleanup_free_ char *buf = NULL;
 | ||||||
|  | +                size_t buf_size;
 | ||||||
|  | +
 | ||||||
|  | +                /* Now read contents of pstore file */
 | ||||||
|  | +                r = read_full_file(ifd_path, &buf, &buf_size);
 | ||||||
|  | +                if (r < 0) {
 | ||||||
|  | +                        log_warning_errno(r, "Failed to read file %s: %m", ifd_path);
 | ||||||
|  | +                        continue;
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                if (!GREEDY_REALLOC(list->entries, list->n_entries_allocated, list->n_entries + 1))
 | ||||||
|  | +                        return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +                list->entries[list->n_entries++] = (PStoreEntry) {
 | ||||||
|  | +                        .dirent = *de,
 | ||||||
|  | +                        .content = TAKE_PTR(buf),
 | ||||||
|  | +                        .content_size = buf_size,
 | ||||||
|  | +                        .is_binary = true,
 | ||||||
|  | +                        .handled = false,
 | ||||||
|  | +                };
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        return r;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int run(int argc, char *argv[]) {
 | ||||||
|  | +        _cleanup_(pstore_entries_reset) PStoreList list = {};
 | ||||||
|  | +        int r;
 | ||||||
|  | +
 | ||||||
|  | +        log_open();
 | ||||||
|  | +
 | ||||||
|  | +        /* Ignore all parse errors */
 | ||||||
|  | +        (void) parse_config();
 | ||||||
|  | +
 | ||||||
|  | +        log_debug("Selected storage '%s'.", pstore_storage_to_string(arg_storage));
 | ||||||
|  | +        log_debug("Selected Unlink '%d'.", arg_unlink);
 | ||||||
|  | +
 | ||||||
|  | +        if (arg_storage == PSTORE_STORAGE_NONE)
 | ||||||
|  | +                /* Do nothing, intentionally, leaving pstore untouched */
 | ||||||
|  | +                return 0;
 | ||||||
|  | +
 | ||||||
|  | +        /* Obtain list of files in pstore */
 | ||||||
|  | +        r = list_files(&list, arg_sourcedir);
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                return r;
 | ||||||
|  | +
 | ||||||
|  | +        /* Handle each pstore file */
 | ||||||
|  | +        /* Sort files lexigraphically ascending, generally needed by all */
 | ||||||
|  | +        qsort_safe(list.entries, list.n_entries, sizeof(PStoreEntry), compare_pstore_entries);
 | ||||||
|  | +
 | ||||||
|  | +        /* Process known file types */
 | ||||||
|  | +        process_dmesg_files(&list);
 | ||||||
|  | +
 | ||||||
|  | +        /* Move left over files out of pstore */
 | ||||||
|  | +        for (size_t n = 0; n < list.n_entries; n++)
 | ||||||
|  | +                move_file(&list.entries[n], NULL);
 | ||||||
|  | +
 | ||||||
|  | +        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/pstore/pstore.conf b/src/pstore/pstore.conf
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..93a8b6707c
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/src/pstore/pstore.conf
 | ||||||
|  | @@ -0,0 +1,16 @@
 | ||||||
|  | +#  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.
 | ||||||
|  | +#
 | ||||||
|  | +# Entries in this file show the compile time defaults.
 | ||||||
|  | +# You can change settings by editing this file.
 | ||||||
|  | +# Defaults can be restored by simply deleting this file.
 | ||||||
|  | +#
 | ||||||
|  | +# See pstore.conf(5) for details.
 | ||||||
|  | +
 | ||||||
|  | +[PStore]
 | ||||||
|  | +#Storage=external
 | ||||||
|  | +#Unlink=yes
 | ||||||
|  | diff --git a/units/meson.build b/units/meson.build
 | ||||||
|  | index a74fa95195..e8e64eb30a 100644
 | ||||||
|  | --- a/units/meson.build
 | ||||||
|  | +++ b/units/meson.build
 | ||||||
|  | @@ -136,6 +136,7 @@ in_units = [
 | ||||||
|  |          ['systemd-binfmt.service',               'ENABLE_BINFMT', | ||||||
|  |           'sysinit.target.wants/'], | ||||||
|  |          ['systemd-coredump@.service',            'ENABLE_COREDUMP'], | ||||||
|  | +        ['systemd-pstore.service',               'ENABLE_PSTORE'],
 | ||||||
|  |          ['systemd-firstboot.service',            'ENABLE_FIRSTBOOT', | ||||||
|  |           'sysinit.target.wants/'], | ||||||
|  |          ['systemd-fsck-root.service',            ''], | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..fec2b1aebf
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -0,0 +1,24 @@
 | ||||||
|  | +#  SPDX-License-Identifier: LGPL-2.1+
 | ||||||
|  | +#
 | ||||||
|  | +#  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.
 | ||||||
|  | +
 | ||||||
|  | +[Unit]
 | ||||||
|  | +Description=Platform Persistent Storage Archival
 | ||||||
|  | +Documentation=man:systemd-pstore(8)
 | ||||||
|  | +DefaultDependencies=no
 | ||||||
|  | +Wants=systemd-remount-fs.service
 | ||||||
|  | +After=systemd-remount-fs.service
 | ||||||
|  | +
 | ||||||
|  | +[Service]
 | ||||||
|  | +Type=oneshot
 | ||||||
|  | +ExecStart=@rootlibexecdir@/systemd-pstore
 | ||||||
|  | +RemainAfterExit=yes
 | ||||||
|  | +StateDirectory=systemd/pstore
 | ||||||
|  | +
 | ||||||
|  | +[Install]
 | ||||||
|  | +WantedBy=systemd-remount-fs.service
 | ||||||
							
								
								
									
										27
									
								
								SOURCES/0877-meson-drop-redundant-line.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								SOURCES/0877-meson-drop-redundant-line.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | From c95ba53ab720dfbd7f692e0a87d7f5d4f89ea36b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Mon, 22 Jul 2019 10:46:53 +0900 | ||||||
|  | Subject: [PATCH] meson: drop redundant line | ||||||
|  | 
 | ||||||
|  | Found by @mattiasb. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 3f708e7f6909faad307bdb60ed0f8d68e84f6584) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  meson.build | 2 -- | ||||||
|  |  1 file changed, 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/meson.build b/meson.build
 | ||||||
|  | index 972a8fb6f7..673800a1a7 100644
 | ||||||
|  | --- a/meson.build
 | ||||||
|  | +++ b/meson.build
 | ||||||
|  | @@ -2166,8 +2166,6 @@ if conf.get('ENABLE_PSTORE') == 1
 | ||||||
|  |                     install_rpath : rootlibexecdir, | ||||||
|  |                     install : true, | ||||||
|  |                     install_dir : rootlibexecdir) | ||||||
|  | -
 | ||||||
|  | -        public_programs += exe
 | ||||||
|  |  endif | ||||||
|  |   | ||||||
|  |  if conf.get('ENABLE_BINFMT') == 1 | ||||||
							
								
								
									
										48
									
								
								SOURCES/0878-pstore-drop-unnecessary-initializations.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								SOURCES/0878-pstore-drop-unnecessary-initializations.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | From 7e4b7cc35af0e3b3afbf32fa0fd9961cd01ad9a9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Mon, 22 Jul 2019 10:52:12 +0900 | ||||||
|  | Subject: [PATCH] pstore: drop unnecessary initializations | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 2e4effd129343d22bfed34e94810d3f87c8f0e85) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 15 ++++++--------- | ||||||
|  |  1 file changed, 6 insertions(+), 9 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index f95e016eb6..e6a342fc50 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -113,14 +113,12 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int move_file(PStoreEntry *pe, const char *subdir) { | ||||||
|  | -        _cleanup_free_ char *ifd_path = NULL;
 | ||||||
|  | -        _cleanup_free_ char *ofd_path = NULL;
 | ||||||
|  | -        int r = 0;
 | ||||||
|  | -        struct iovec iovec[2] = {};
 | ||||||
|  | -        int n_iovec = 0;
 | ||||||
|  | +        _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
 | ||||||
|  |          _cleanup_free_ void *field = NULL; | ||||||
|  | -        const char *suffix = NULL;
 | ||||||
|  | +        struct iovec iovec[2];
 | ||||||
|  | +        const char *suffix;
 | ||||||
|  |          size_t field_size; | ||||||
|  | +        int n_iovec = 0, r;
 | ||||||
|  |   | ||||||
|  |          if (pe->handled) | ||||||
|  |                  return 0; | ||||||
|  | @@ -202,10 +200,9 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
 | ||||||
|  |   | ||||||
|  |  static void process_dmesg_files(PStoreList *list) { | ||||||
|  |          /* Move files, reconstruct dmesg.txt */ | ||||||
|  | -        PStoreEntry *pe;
 | ||||||
|  | -        _cleanup_free_ char *dmesg = NULL;
 | ||||||
|  | +        _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
 | ||||||
|  |          size_t dmesg_size = 0; | ||||||
|  | -        _cleanup_free_ char *dmesg_id = NULL;
 | ||||||
|  | +        PStoreEntry *pe;
 | ||||||
|  |   | ||||||
|  |          /* Handle each dmesg file: files processed in reverse | ||||||
|  |           * order so as to properly reconstruct original dmesg */ | ||||||
							
								
								
									
										46
									
								
								SOURCES/0879-pstopre-fix-return-value-of-list_files.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								SOURCES/0879-pstopre-fix-return-value-of-list_files.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | From a0485b96118d3d2ac439f510e404ffb3db03e23f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Mon, 22 Jul 2019 10:55:10 +0900 | ||||||
|  | Subject: [PATCH] pstopre: fix return value of list_files() | ||||||
|  | 
 | ||||||
|  | Previously, the return value of the last read_full_file() is returned. | ||||||
|  | This makes the error in read_full_file() is always ignored. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 337874a45fff46a80e4974c681a5e651f3a0fac9) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 6 +++--- | ||||||
|  |  1 file changed, 3 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index e6a342fc50..2fbef48543 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -311,7 +311,7 @@ static void process_dmesg_files(PStoreList *list) {
 | ||||||
|  |  static int list_files(PStoreList *list, const char *sourcepath) { | ||||||
|  |          _cleanup_(closedirp) DIR *dirp = NULL; | ||||||
|  |          struct dirent *de; | ||||||
|  | -        int r = 0;
 | ||||||
|  | +        int r;
 | ||||||
|  |   | ||||||
|  |          dirp = opendir(sourcepath); | ||||||
|  |          if (!dirp) | ||||||
|  | @@ -330,7 +330,7 @@ static int list_files(PStoreList *list, const char *sourcepath) {
 | ||||||
|  |                  /* Now read contents of pstore file */ | ||||||
|  |                  r = read_full_file(ifd_path, &buf, &buf_size); | ||||||
|  |                  if (r < 0) { | ||||||
|  | -                        log_warning_errno(r, "Failed to read file %s: %m", ifd_path);
 | ||||||
|  | +                        log_warning_errno(r, "Failed to read file %s, skipping: %m", ifd_path);
 | ||||||
|  |                          continue; | ||||||
|  |                  } | ||||||
|  |   | ||||||
|  | @@ -346,7 +346,7 @@ static int list_files(PStoreList *list, const char *sourcepath) {
 | ||||||
|  |                  }; | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | -        return r;
 | ||||||
|  | +        return 0;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int run(int argc, char *argv[]) { | ||||||
							
								
								
									
										36
									
								
								SOURCES/0880-pstore-remove-temporary-file-on-failure.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								SOURCES/0880-pstore-remove-temporary-file-on-failure.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | From 58000dc7dd93ff6e8357de64154b0849d3c17c5d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Mon, 22 Jul 2019 11:01:43 +0900 | ||||||
|  | Subject: [PATCH] pstore: remove temporary file on failure | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 03c5f6cc02648eeff3179b2b762d46b9e1889bb1) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 6 +++--- | ||||||
|  |  1 file changed, 3 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index 2fbef48543..ce8080ceed 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -167,8 +167,8 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int write_dmesg(const char *dmesg, size_t size, const char *id) { | ||||||
|  | -        _cleanup_(unlink_and_freep) char *ofd_path = NULL;
 | ||||||
|  | -        _cleanup_free_ char *tmp_path = NULL;
 | ||||||
|  | +        _cleanup_(unlink_and_freep) char *tmp_path = NULL;
 | ||||||
|  | +        _cleanup_free_ char *ofd_path = NULL;
 | ||||||
|  |          _cleanup_close_ int ofd = -1; | ||||||
|  |          ssize_t wr; | ||||||
|  |          int r; | ||||||
|  | @@ -193,7 +193,7 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
 | ||||||
|  |          r = link_tmpfile(ofd, tmp_path, ofd_path); | ||||||
|  |          if (r < 0) | ||||||
|  |                  return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path); | ||||||
|  | -        ofd_path = mfree(ofd_path);
 | ||||||
|  | +        tmp_path = mfree(tmp_path);
 | ||||||
|  |   | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
| @ -0,0 +1,57 @@ | |||||||
|  | From 5006e4bd9aecea40ca3d907adc692c4c8001a6c1 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Mon, 22 Jul 2019 11:08:06 +0900 | ||||||
|  | Subject: [PATCH] pstore: do not add FILE= journal entry if content_size == 0 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 6bf18debddbe1b231f783617e054cc194bb36d1e) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 25 ++++++++++++++----------- | ||||||
|  |  1 file changed, 14 insertions(+), 11 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index ce8080ceed..eb251d61c8 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -114,10 +114,8 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
 | ||||||
|  |   | ||||||
|  |  static int move_file(PStoreEntry *pe, const char *subdir) { | ||||||
|  |          _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL; | ||||||
|  | -        _cleanup_free_ void *field = NULL;
 | ||||||
|  | +        const char *suffix, *message;
 | ||||||
|  |          struct iovec iovec[2]; | ||||||
|  | -        const char *suffix;
 | ||||||
|  | -        size_t field_size;
 | ||||||
|  |          int n_iovec = 0, r; | ||||||
|  |   | ||||||
|  |          if (pe->handled) | ||||||
|  | @@ -133,15 +131,20 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
 | ||||||
|  |   | ||||||
|  |          /* Always log to the journal */ | ||||||
|  |          suffix = arg_storage == PSTORE_STORAGE_EXTERNAL ? strjoina(" moved to ", ofd_path) : (char *)"."; | ||||||
|  | -        field = strjoina("MESSAGE=PStore ", pe->dirent.d_name, suffix);
 | ||||||
|  | -        iovec[n_iovec++] = IOVEC_MAKE_STRING(field);
 | ||||||
|  | +        message = strjoina("MESSAGE=PStore ", pe->dirent.d_name, suffix);
 | ||||||
|  | +        iovec[n_iovec++] = IOVEC_MAKE_STRING(message);
 | ||||||
|  |   | ||||||
|  | -        field_size = strlen("FILE=") + pe->content_size;
 | ||||||
|  | -        field = malloc(field_size);
 | ||||||
|  | -        if (!field)
 | ||||||
|  | -                return log_oom();
 | ||||||
|  | -        memcpy(stpcpy(field, "FILE="), pe->content, pe->content_size);
 | ||||||
|  | -        iovec[n_iovec++] = IOVEC_MAKE(field, field_size);
 | ||||||
|  | +        if (pe->content_size > 0) {
 | ||||||
|  | +                _cleanup_free_ void *field = NULL;
 | ||||||
|  | +                size_t field_size;
 | ||||||
|  | +
 | ||||||
|  | +                field_size = strlen("FILE=") + pe->content_size;
 | ||||||
|  | +                field = malloc(field_size);
 | ||||||
|  | +                if (!field)
 | ||||||
|  | +                        return log_oom();
 | ||||||
|  | +                memcpy(stpcpy(field, "FILE="), pe->content, pe->content_size);
 | ||||||
|  | +                iovec[n_iovec++] = IOVEC_MAKE(field, field_size);
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  |          r = sd_journal_sendv(iovec, n_iovec); | ||||||
|  |          if (r < 0) | ||||||
| @ -0,0 +1,24 @@ | |||||||
|  | From a7247899f156761934bcb4b380861b3d3ec5449f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||||||
|  | Date: Mon, 22 Jul 2019 14:09:12 +0900 | ||||||
|  | Subject: [PATCH] pstore: run only when /sys/fs/pstore is not empty | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 6d4f213b1f6afb2901f0d97cec0e28e20809b713) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-pstore.service.in | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | index fec2b1aebf..dde21bc33e 100644
 | ||||||
|  | --- a/units/systemd-pstore.service.in
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -10,6 +10,7 @@
 | ||||||
|  |  [Unit] | ||||||
|  |  Description=Platform Persistent Storage Archival | ||||||
|  |  Documentation=man:systemd-pstore(8) | ||||||
|  | +ConditionDirectoryNotEmpty=/sys/fs/pstore
 | ||||||
|  |  DefaultDependencies=no | ||||||
|  |  Wants=systemd-remount-fs.service | ||||||
|  |  After=systemd-remount-fs.service | ||||||
							
								
								
									
										34
									
								
								SOURCES/0883-pstore-fix-use-after-free.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								SOURCES/0883-pstore-fix-use-after-free.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | From 7f5bfbd5485e1cb779d7568cabb5783651fd9da3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Michael Olbrich <m.olbrich@pengutronix.de> | ||||||
|  | Date: Fri, 6 Sep 2019 15:04:01 +0200 | ||||||
|  | Subject: [PATCH] pstore: fix use after free | ||||||
|  | 
 | ||||||
|  | The memory is still needed in the sd_journal_sendv() after the 'if' block. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 1e19f5ac0d680a63eccae7ef1fc6ce225dca0bbf) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index eb251d61c8..cafb1804c6 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -114,6 +114,7 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
 | ||||||
|  |   | ||||||
|  |  static int move_file(PStoreEntry *pe, const char *subdir) { | ||||||
|  |          _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL; | ||||||
|  | +        _cleanup_free_ void *field = NULL;
 | ||||||
|  |          const char *suffix, *message; | ||||||
|  |          struct iovec iovec[2]; | ||||||
|  |          int n_iovec = 0, r; | ||||||
|  | @@ -135,7 +136,6 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
 | ||||||
|  |          iovec[n_iovec++] = IOVEC_MAKE_STRING(message); | ||||||
|  |   | ||||||
|  |          if (pe->content_size > 0) { | ||||||
|  | -                _cleanup_free_ void *field = NULL;
 | ||||||
|  |                  size_t field_size; | ||||||
|  |   | ||||||
|  |                  field_size = strlen("FILE=") + pe->content_size; | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | From a35a90322f8587f650aeb72bfbe1ebcc93e503aa Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Mon, 22 Jul 2019 10:43:19 +0200 | ||||||
|  | Subject: [PATCH] pstore: refuse to run if arguments are specified | ||||||
|  | 
 | ||||||
|  | (This is why the --help chech passed.) | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 22d6bea8820612e6a1483d8b6cfd820f1417ae6b) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 4 ++++ | ||||||
|  |  1 file changed, 4 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index cafb1804c6..b0b21dedd4 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -358,6 +358,10 @@ static int run(int argc, char *argv[]) {
 | ||||||
|  |   | ||||||
|  |          log_open(); | ||||||
|  |   | ||||||
|  | +        if (argc > 1)
 | ||||||
|  | +                return log_error_errno(-EINVAL,
 | ||||||
|  | +                                       "This program takes no arguments.");
 | ||||||
|  | +
 | ||||||
|  |          /* Ignore all parse errors */ | ||||||
|  |          (void) parse_config(); | ||||||
|  |   | ||||||
| @ -0,0 +1,44 @@ | |||||||
|  | From 76fe0974f62f0a2beb2d3d8e224e80a57c0ebd09 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Fri, 4 Oct 2019 16:14:47 +0200 | ||||||
|  | Subject: [PATCH] pstore: allow specifying src and dst dirs are arguments | ||||||
|  | 
 | ||||||
|  | This makes it much easier to debug the program as a normal user, since we | ||||||
|  | don't need to set up fake input under /sys/fs/pstore/. | ||||||
|  | 
 | ||||||
|  | Also, let's make the debug output a bit nicer. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit e05a72d7587ff916a983588f8393af624d330dd0) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 11 +++++++---- | ||||||
|  |  1 file changed, 7 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index b0b21dedd4..7353e83a81 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -358,15 +358,18 @@ static int run(int argc, char *argv[]) {
 | ||||||
|  |   | ||||||
|  |          log_open(); | ||||||
|  |   | ||||||
|  | -        if (argc > 1)
 | ||||||
|  | +        if (argc == 3) {
 | ||||||
|  | +                arg_sourcedir = argv[1];
 | ||||||
|  | +                arg_archivedir = argv[2];
 | ||||||
|  | +        } else if (argc > 1)
 | ||||||
|  |                  return log_error_errno(-EINVAL, | ||||||
|  | -                                       "This program takes no arguments.");
 | ||||||
|  | +                                       "This program takes zero or two arguments.");
 | ||||||
|  |   | ||||||
|  |          /* Ignore all parse errors */ | ||||||
|  |          (void) parse_config(); | ||||||
|  |   | ||||||
|  | -        log_debug("Selected storage '%s'.", pstore_storage_to_string(arg_storage));
 | ||||||
|  | -        log_debug("Selected Unlink '%d'.", arg_unlink);
 | ||||||
|  | +        log_debug("Selected storage: %s.", pstore_storage_to_string(arg_storage));
 | ||||||
|  | +        log_debug("Selected unlink: %s.", yes_no(arg_unlink));
 | ||||||
|  |   | ||||||
|  |          if (arg_storage == PSTORE_STORAGE_NONE) | ||||||
|  |                  /* Do nothing, intentionally, leaving pstore untouched */ | ||||||
							
								
								
									
										133
									
								
								SOURCES/0886-pstore-rework-memory-handling-for-dmesg.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								SOURCES/0886-pstore-rework-memory-handling-for-dmesg.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,133 @@ | |||||||
|  | From a2ba34a79de3748f51d57541c54dbe22e1d03a9e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||||||
|  | Date: Fri, 4 Oct 2019 16:17:27 +0200 | ||||||
|  | Subject: [PATCH] pstore: rework memory handling for dmesg | ||||||
|  | 
 | ||||||
|  | Semmle Security Reports report: | ||||||
|  | > The problem occurs on the way realloc is being used. When a size
 | ||||||
|  | > bigger than the chunk that wants to be reallocated is passed, realloc
 | ||||||
|  | > try to malloc a  bigger size, however in the case that malloc fails
 | ||||||
|  | > (for example, by forcing a big allocation)  realloc will return NULL.
 | ||||||
|  | > | ||||||
|  | > According to the man page:
 | ||||||
|  | > "The realloc() function returns a pointer to the newly allocated
 | ||||||
|  | > memory, which is suitably aligned for any built-in type and may be
 | ||||||
|  | > different from ptr,  or  NULL  if  the  request fails.   If size was
 | ||||||
|  | > equal to 0, either NULL or a pointer suitable to be passed to free()
 | ||||||
|  | > is returned.  If realloc() fails, the original block is left
 | ||||||
|  | > untouched; it is  not  freed or moved."
 | ||||||
|  | > | ||||||
|  | > The problem occurs when the memory ptr passed to the first argument of
 | ||||||
|  | > realloc is the same as the one used for the result, for example in
 | ||||||
|  | > this case:
 | ||||||
|  | > | ||||||
|  | > dmesg = realloc(dmesg, dmesg_size + strlen(pe->dirent.d_name) +
 | ||||||
|  | > strlen(":\n") + pe->content_size + 1);
 | ||||||
|  | > | ||||||
|  | > https://lgtm.com/projects/g/systemd/systemd/snapshot/f8bcb81955f9e93a4787627e28f43fffb2a84836/files/src/pstore/pstore.c?sort=name&dir=A
 | ||||||
|  | > SC&mode=heatmap#L300
 | ||||||
|  | > | ||||||
|  | > If the malloc inside that realloc fails, then the original memory
 | ||||||
|  | > chunk will never be free but since realloc will return NULL, the
 | ||||||
|  | > pointer to that memory chunk will be lost and a memory leak will
 | ||||||
|  | > occur.
 | ||||||
|  | > | ||||||
|  | > In case you are curious, this is the query we used to find this problem:
 | ||||||
|  | > https://lgtm.com/query/8650323308193591473/
 | ||||||
|  | 
 | ||||||
|  | Let's use a more standard pattern: allocate memory using greedy_realloc, and | ||||||
|  | instead of freeing it when we wrote out a chunk, let's just move the cursor | ||||||
|  | back to the beginning and reuse the memory we allocated previously. | ||||||
|  | 
 | ||||||
|  | If we fail to allocate the memory for dmesg contents, don't write the dmesg | ||||||
|  | entry, but let's still process the files to move them out of pstore. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 8198c3e42b0614b6bd1db6f38813b842c8577304) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 43 ++++++++++++++++++++++++++----------------- | ||||||
|  |  1 file changed, 26 insertions(+), 17 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index 7353e83a81..d70e142b4d 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -176,9 +176,11 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
 | ||||||
|  |          ssize_t wr; | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  | -        if (isempty(dmesg) || size == 0)
 | ||||||
|  | +        if (size == 0)
 | ||||||
|  |                  return 0; | ||||||
|  |   | ||||||
|  | +        assert(dmesg);
 | ||||||
|  | +
 | ||||||
|  |          /* log_info("Record ID %s", id); */ | ||||||
|  |   | ||||||
|  |          ofd_path = path_join(arg_archivedir, id, "dmesg.txt"); | ||||||
|  | @@ -204,7 +206,8 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
 | ||||||
|  |  static void process_dmesg_files(PStoreList *list) { | ||||||
|  |          /* Move files, reconstruct dmesg.txt */ | ||||||
|  |          _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL; | ||||||
|  | -        size_t dmesg_size = 0;
 | ||||||
|  | +        size_t dmesg_size = 0, dmesg_allocated = 0;
 | ||||||
|  | +        bool dmesg_bad = false;
 | ||||||
|  |          PStoreEntry *pe; | ||||||
|  |   | ||||||
|  |          /* Handle each dmesg file: files processed in reverse | ||||||
|  | @@ -281,33 +284,39 @@ static void process_dmesg_files(PStoreList *list) {
 | ||||||
|  |                  /* Now move file from pstore to archive storage */ | ||||||
|  |                  move_file(pe, pe_id); | ||||||
|  |   | ||||||
|  | +                if (dmesg_bad)
 | ||||||
|  | +                        continue;
 | ||||||
|  | +
 | ||||||
|  |                  /* If the current record id is NOT the same as the | ||||||
|  |                   * previous record id, then start a new dmesg.txt file */ | ||||||
|  | -                if (!pe_id || !dmesg_id || !streq(pe_id, dmesg_id)) {
 | ||||||
|  | +                if (!streq_ptr(pe_id, dmesg_id)) {
 | ||||||
|  |                          /* Encountered a new dmesg group, close out old one, open new one */ | ||||||
|  | -                        if (dmesg) {
 | ||||||
|  | -                                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
 | ||||||
|  | -                                dmesg = mfree(dmesg);
 | ||||||
|  | -                                dmesg_size = 0;
 | ||||||
|  | -                        }
 | ||||||
|  | +                        (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
 | ||||||
|  | +                        dmesg_size = 0;
 | ||||||
|  |   | ||||||
|  |                          /* now point dmesg_id to storage of pe_id */ | ||||||
|  |                          free_and_replace(dmesg_id, pe_id); | ||||||
|  |                  } | ||||||
|  |   | ||||||
|  | -                /* Reconstruction of dmesg is done as a useful courtesy, do not log errors */
 | ||||||
|  | -                dmesg = realloc(dmesg, dmesg_size + strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1);
 | ||||||
|  | -                if (dmesg) {
 | ||||||
|  | -                        dmesg_size += sprintf(&dmesg[dmesg_size], "%s:\n", pe->dirent.d_name);
 | ||||||
|  | -                        if (pe->content) {
 | ||||||
|  | -                                memcpy(&dmesg[dmesg_size], pe->content, pe->content_size);
 | ||||||
|  | -                                dmesg_size += pe->content_size;
 | ||||||
|  | -                        }
 | ||||||
|  | +                /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled
 | ||||||
|  | +                 * output either. */
 | ||||||
|  | +                size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1;
 | ||||||
|  | +                if (!GREEDY_REALLOC(dmesg, dmesg_allocated, dmesg_size + needed)) {
 | ||||||
|  | +                        log_warning_errno(ENOMEM, "Failed to write dmesg file: %m");
 | ||||||
|  | +                        dmesg_bad = true;
 | ||||||
|  | +                        continue;
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  | +                dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name);
 | ||||||
|  | +                if (pe->content) {
 | ||||||
|  | +                        memcpy(dmesg + dmesg_size, pe->content, pe->content_size);
 | ||||||
|  | +                        dmesg_size += pe->content_size;
 | ||||||
|  |                  } | ||||||
|  |   | ||||||
|  |                  pe_id = mfree(pe_id); | ||||||
|  |          } | ||||||
|  | -        if (dmesg)
 | ||||||
|  | +
 | ||||||
|  | +        if (!dmesg_bad)
 | ||||||
|  |                  (void) write_dmesg(dmesg, dmesg_size, dmesg_id); | ||||||
|  |  } | ||||||
|  |   | ||||||
							
								
								
									
										504
									
								
								SOURCES/0887-pstore-fixes-for-dmesg.txt-reconstruction.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										504
									
								
								SOURCES/0887-pstore-fixes-for-dmesg.txt-reconstruction.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,504 @@ | |||||||
|  | From 5ac15c7dc49476e7cd7cc3a4b507282c9f78d528 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric DeVolder <eric.devolder@oracle.com> | ||||||
|  | Date: Mon, 21 Nov 2022 11:27:27 -0500 | ||||||
|  | Subject: [PATCH] pstore: fixes for dmesg.txt reconstruction | ||||||
|  | 
 | ||||||
|  | This patch fixes problems with the re-assembly of the dmesg | ||||||
|  | from the records stored in pstore. | ||||||
|  | 
 | ||||||
|  | The current code simply ignores the last 6 characters of the | ||||||
|  | file name to form a base record id, which then groups any | ||||||
|  | pstore files with this base id into the reconstructed dmesg.txt. | ||||||
|  | This approach fails when the following oops generated the | ||||||
|  | following in pstore: | ||||||
|  | 
 | ||||||
|  |  -rw-------.  1 root root  1808 Oct 27 22:07 dmesg-efi-166692286101001 | ||||||
|  |  -rw-------.  1 root root  1341 Oct 27 22:07 dmesg-efi-166692286101002 | ||||||
|  |  -rw-------.  1 root root  1812 Oct 27 22:07 dmesg-efi-166692286102001 | ||||||
|  |  -rw-------.  1 root root  1820 Oct 27 22:07 dmesg-efi-166692286102002 | ||||||
|  |  -rw-------.  1 root root  1807 Oct 27 22:07 dmesg-efi-166692286103001 | ||||||
|  |  -rw-------.  1 root root  1791 Oct 27 22:07 dmesg-efi-166692286103002 | ||||||
|  |  -rw-------.  1 root root  1773 Oct 27 22:07 dmesg-efi-166692286104001 | ||||||
|  |  -rw-------.  1 root root  1801 Oct 27 22:07 dmesg-efi-166692286104002 | ||||||
|  |  -rw-------.  1 root root  1821 Oct 27 22:07 dmesg-efi-166692286105001 | ||||||
|  |  -rw-------.  1 root root  1809 Oct 27 22:07 dmesg-efi-166692286105002 | ||||||
|  |  -rw-------.  1 root root  1804 Oct 27 22:07 dmesg-efi-166692286106001 | ||||||
|  |  -rw-------.  1 root root  1817 Oct 27 22:07 dmesg-efi-166692286106002 | ||||||
|  |  -rw-------.  1 root root  1792 Oct 27 22:07 dmesg-efi-166692286107001 | ||||||
|  |  -rw-------.  1 root root  1810 Oct 27 22:07 dmesg-efi-166692286107002 | ||||||
|  |  -rw-------.  1 root root  1717 Oct 27 22:07 dmesg-efi-166692286108001 | ||||||
|  |  -rw-------.  1 root root  1808 Oct 27 22:07 dmesg-efi-166692286108002 | ||||||
|  |  -rw-------.  1 root root  1764 Oct 27 22:07 dmesg-efi-166692286109001 | ||||||
|  |  -rw-------.  1 root root  1765 Oct 27 22:07 dmesg-efi-166692286109002 | ||||||
|  |  -rw-------.  1 root root  1796 Oct 27 22:07 dmesg-efi-166692286110001 | ||||||
|  |  -rw-------.  1 root root  1816 Oct 27 22:07 dmesg-efi-166692286110002 | ||||||
|  |  -rw-------.  1 root root  1793 Oct 27 22:07 dmesg-efi-166692286111001 | ||||||
|  |  -rw-------.  1 root root  1751 Oct 27 22:07 dmesg-efi-166692286111002 | ||||||
|  |  -rw-------.  1 root root  1813 Oct 27 22:07 dmesg-efi-166692286112001 | ||||||
|  |  -rw-------.  1 root root  1786 Oct 27 22:07 dmesg-efi-166692286112002 | ||||||
|  |  -rw-------.  1 root root  1754 Oct 27 22:07 dmesg-efi-166692286113001 | ||||||
|  |  -rw-------.  1 root root  1752 Oct 27 22:07 dmesg-efi-166692286113002 | ||||||
|  |  -rw-------.  1 root root  1803 Oct 27 22:07 dmesg-efi-166692286114001 | ||||||
|  |  -rw-------.  1 root root  1759 Oct 27 22:07 dmesg-efi-166692286114002 | ||||||
|  |  -rw-------.  1 root root  1805 Oct 27 22:07 dmesg-efi-166692286115001 | ||||||
|  |  -rw-------.  1 root root  1787 Oct 27 22:07 dmesg-efi-166692286115002 | ||||||
|  |  -rw-------.  1 root root  1815 Oct 27 22:07 dmesg-efi-166692286116001 | ||||||
|  |  -rw-------.  1 root root  1771 Oct 27 22:07 dmesg-efi-166692286116002 | ||||||
|  |  -rw-------.  1 root root  1816 Oct 27 22:07 dmesg-efi-166692286117002 | ||||||
|  |  -rw-------.  1 root root  1388 Oct 27 22:07 dmesg-efi-166692286701003 | ||||||
|  |  -rw-------.  1 root root  1824 Oct 27 22:07 dmesg-efi-166692286702003 | ||||||
|  |  -rw-------.  1 root root  1795 Oct 27 22:07 dmesg-efi-166692286703003 | ||||||
|  |  -rw-------.  1 root root  1805 Oct 27 22:07 dmesg-efi-166692286704003 | ||||||
|  |  -rw-------.  1 root root  1813 Oct 27 22:07 dmesg-efi-166692286705003 | ||||||
|  |  -rw-------.  1 root root  1821 Oct 27 22:07 dmesg-efi-166692286706003 | ||||||
|  |  -rw-------.  1 root root  1814 Oct 27 22:07 dmesg-efi-166692286707003 | ||||||
|  |  -rw-------.  1 root root  1812 Oct 27 22:07 dmesg-efi-166692286708003 | ||||||
|  |  -rw-------.  1 root root  1769 Oct 27 22:07 dmesg-efi-166692286709003 | ||||||
|  |  -rw-------.  1 root root  1820 Oct 27 22:07 dmesg-efi-166692286710003 | ||||||
|  |  -rw-------.  1 root root  1755 Oct 27 22:07 dmesg-efi-166692286711003 | ||||||
|  |  -rw-------.  1 root root  1790 Oct 27 22:07 dmesg-efi-166692286712003 | ||||||
|  |  -rw-------.  1 root root  1756 Oct 27 22:07 dmesg-efi-166692286713003 | ||||||
|  |  -rw-------.  1 root root  1763 Oct 27 22:07 dmesg-efi-166692286714003 | ||||||
|  |  -rw-------.  1 root root  1791 Oct 27 22:07 dmesg-efi-166692286715003 | ||||||
|  |  -rw-------.  1 root root  1775 Oct 27 22:07 dmesg-efi-166692286716003 | ||||||
|  |  -rw-------.  1 root root  1820 Oct 27 22:07 dmesg-efi-166692286717003 | ||||||
|  | 
 | ||||||
|  | The "reconstructed" dmesg.txt that resulted from the above contained | ||||||
|  | the following (ignoring actual contents, just providing the Part info): | ||||||
|  | 
 | ||||||
|  |  Emergency#3 Part17 | ||||||
|  |  Emergency#3 Part16 | ||||||
|  |  Emergency#3 Part15 | ||||||
|  |  Emergency#3 Part14 | ||||||
|  |  Emergency#3 Part13 | ||||||
|  |  Emergency#3 Part12 | ||||||
|  |  Emergency#3 Part11 | ||||||
|  |  Emergency#3 Part10 | ||||||
|  |  Emergency#3 Part9 | ||||||
|  |  Emergency#3 Part8 | ||||||
|  |  Emergency#3 Part7 | ||||||
|  |  Emergency#3 Part6 | ||||||
|  |  Emergency#3 Part5 | ||||||
|  |  Emergency#3 Part4 | ||||||
|  |  Emergency#3 Part3 | ||||||
|  |  Emergency#3 Part2 | ||||||
|  |  Emergency#3 Part1 | ||||||
|  |  Panic#2 Part17 | ||||||
|  |  Panic#2 Part16 | ||||||
|  |  Oops#1 Part16 | ||||||
|  |  Panic#2 Part15 | ||||||
|  |  Oops#1 Part15 | ||||||
|  |  Panic#2 Part14 | ||||||
|  |  Oops#1 Part14 | ||||||
|  |  Panic#2 Part13 | ||||||
|  |  Oops#1 Part13 | ||||||
|  |  Panic#2 Part12 | ||||||
|  |  Oops#1 Part12 | ||||||
|  |  Panic#2 Part11 | ||||||
|  |  Oops#1 Part11 | ||||||
|  |  Panic#2 Part10 | ||||||
|  |  Oops#1 Part10 | ||||||
|  |  Panic#2 Part9 | ||||||
|  |  Oops#1 Part9 | ||||||
|  |  Panic#2 Part8 | ||||||
|  |  Oops#1 Part8 | ||||||
|  |  Panic#2 Part7 | ||||||
|  |  Oops#1 Part7 | ||||||
|  |  Panic#2 Part6 | ||||||
|  |  Oops#1 Part6 | ||||||
|  |  Panic#2 Part5 | ||||||
|  |  Oops#1 Part5 | ||||||
|  |  Panic#2 Part4 | ||||||
|  |  Oops#1 Part4 | ||||||
|  |  Panic#2 Part3 | ||||||
|  |  Oops#1 Part3 | ||||||
|  |  Panic#2 Part2 | ||||||
|  |  Oops#1 Part2 | ||||||
|  |  Panic#2 Part1 | ||||||
|  |  Oops#1 Part1 | ||||||
|  | 
 | ||||||
|  | The above is a interleaved mess of three dmesg dumps. | ||||||
|  | 
 | ||||||
|  | This patch fixes the above problems, and simplifies the dmesg | ||||||
|  | reconstruction process. The code now distinguishes between | ||||||
|  | records on EFI vs ERST, which have differently formatted | ||||||
|  | record identifiers. Using knowledge of the format of the | ||||||
|  | record ids allows vastly improved reconstruction process. | ||||||
|  | 
 | ||||||
|  | With this change in place, the above pstore records now | ||||||
|  | result in the following: | ||||||
|  | 
 | ||||||
|  |  # ls -alR /var/lib/systemd/pstore | ||||||
|  |  1666922861: | ||||||
|  |  total 8 | ||||||
|  |  drwxr-xr-x. 4 root root   28 Nov 18 14:58 . | ||||||
|  |  drwxr-xr-x. 7 root root  144 Nov 18 14:58 .. | ||||||
|  |  drwxr-xr-x. 2 root root 4096 Nov 18 14:58 001 | ||||||
|  |  drwxr-xr-x. 2 root root 4096 Nov 18 14:58 002 | ||||||
|  | 
 | ||||||
|  |  1666922861/001: | ||||||
|  |  total 100 | ||||||
|  |  drwxr-xr-x. 2 root root  4096 Nov 18 14:58 . | ||||||
|  |  drwxr-xr-x. 4 root root    28 Nov 18 14:58 .. | ||||||
|  |  -rw-------. 1 root root  1808 Oct 27 22:07 dmesg-efi-166692286101001 | ||||||
|  |  -rw-------. 1 root root  1812 Oct 27 22:07 dmesg-efi-166692286102001 | ||||||
|  |  -rw-------. 1 root root  1807 Oct 27 22:07 dmesg-efi-166692286103001 | ||||||
|  |  -rw-------. 1 root root  1773 Oct 27 22:07 dmesg-efi-166692286104001 | ||||||
|  |  -rw-------. 1 root root  1821 Oct 27 22:07 dmesg-efi-166692286105001 | ||||||
|  |  -rw-------. 1 root root  1804 Oct 27 22:07 dmesg-efi-166692286106001 | ||||||
|  |  -rw-------. 1 root root  1792 Oct 27 22:07 dmesg-efi-166692286107001 | ||||||
|  |  -rw-------. 1 root root  1717 Oct 27 22:07 dmesg-efi-166692286108001 | ||||||
|  |  -rw-------. 1 root root  1764 Oct 27 22:07 dmesg-efi-166692286109001 | ||||||
|  |  -rw-------. 1 root root  1796 Oct 27 22:07 dmesg-efi-166692286110001 | ||||||
|  |  -rw-------. 1 root root  1793 Oct 27 22:07 dmesg-efi-166692286111001 | ||||||
|  |  -rw-------. 1 root root  1813 Oct 27 22:07 dmesg-efi-166692286112001 | ||||||
|  |  -rw-------. 1 root root  1754 Oct 27 22:07 dmesg-efi-166692286113001 | ||||||
|  |  -rw-------. 1 root root  1803 Oct 27 22:07 dmesg-efi-166692286114001 | ||||||
|  |  -rw-------. 1 root root  1805 Oct 27 22:07 dmesg-efi-166692286115001 | ||||||
|  |  -rw-------. 1 root root  1815 Oct 27 22:07 dmesg-efi-166692286116001 | ||||||
|  |  -rw-r-----. 1 root root 28677 Nov 18 14:58 dmesg.txt | ||||||
|  | 
 | ||||||
|  |  1666922861/002: | ||||||
|  |  total 104 | ||||||
|  |  drwxr-xr-x. 2 root root  4096 Nov 18 14:58 . | ||||||
|  |  drwxr-xr-x. 4 root root    28 Nov 18 14:58 .. | ||||||
|  |  -rw-------. 1 root root  1341 Oct 27 22:07 dmesg-efi-166692286101002 | ||||||
|  |  -rw-------. 1 root root  1820 Oct 27 22:07 dmesg-efi-166692286102002 | ||||||
|  |  -rw-------. 1 root root  1791 Oct 27 22:07 dmesg-efi-166692286103002 | ||||||
|  |  -rw-------. 1 root root  1801 Oct 27 22:07 dmesg-efi-166692286104002 | ||||||
|  |  -rw-------. 1 root root  1809 Oct 27 22:07 dmesg-efi-166692286105002 | ||||||
|  |  -rw-------. 1 root root  1817 Oct 27 22:07 dmesg-efi-166692286106002 | ||||||
|  |  -rw-------. 1 root root  1810 Oct 27 22:07 dmesg-efi-166692286107002 | ||||||
|  |  -rw-------. 1 root root  1808 Oct 27 22:07 dmesg-efi-166692286108002 | ||||||
|  |  -rw-------. 1 root root  1765 Oct 27 22:07 dmesg-efi-166692286109002 | ||||||
|  |  -rw-------. 1 root root  1816 Oct 27 22:07 dmesg-efi-166692286110002 | ||||||
|  |  -rw-------. 1 root root  1751 Oct 27 22:07 dmesg-efi-166692286111002 | ||||||
|  |  -rw-------. 1 root root  1786 Oct 27 22:07 dmesg-efi-166692286112002 | ||||||
|  |  -rw-------. 1 root root  1752 Oct 27 22:07 dmesg-efi-166692286113002 | ||||||
|  |  -rw-------. 1 root root  1759 Oct 27 22:07 dmesg-efi-166692286114002 | ||||||
|  |  -rw-------. 1 root root  1787 Oct 27 22:07 dmesg-efi-166692286115002 | ||||||
|  |  -rw-------. 1 root root  1771 Oct 27 22:07 dmesg-efi-166692286116002 | ||||||
|  |  -rw-------. 1 root root  1816 Oct 27 22:07 dmesg-efi-166692286117002 | ||||||
|  |  -rw-r-----. 1 root root 30000 Nov 18 14:58 dmesg.txt | ||||||
|  | 
 | ||||||
|  |  1666922867: | ||||||
|  |  total 4 | ||||||
|  |  drwxr-xr-x. 3 root root   17 Nov 18 14:58 . | ||||||
|  |  drwxr-xr-x. 7 root root  144 Nov 18 14:58 .. | ||||||
|  |  drwxr-xr-x. 2 root root 4096 Nov 18 14:58 003 | ||||||
|  | 
 | ||||||
|  |  1666922867/003: | ||||||
|  |  total 104 | ||||||
|  |  drwxr-xr-x. 2 root root  4096 Nov 18 14:58 . | ||||||
|  |  drwxr-xr-x. 3 root root    17 Nov 18 14:58 .. | ||||||
|  |  -rw-------. 1 root root  1388 Oct 27 22:07 dmesg-efi-166692286701003 | ||||||
|  |  -rw-------. 1 root root  1824 Oct 27 22:07 dmesg-efi-166692286702003 | ||||||
|  |  -rw-------. 1 root root  1795 Oct 27 22:07 dmesg-efi-166692286703003 | ||||||
|  |  -rw-------. 1 root root  1805 Oct 27 22:07 dmesg-efi-166692286704003 | ||||||
|  |  -rw-------. 1 root root  1813 Oct 27 22:07 dmesg-efi-166692286705003 | ||||||
|  |  -rw-------. 1 root root  1821 Oct 27 22:07 dmesg-efi-166692286706003 | ||||||
|  |  -rw-------. 1 root root  1814 Oct 27 22:07 dmesg-efi-166692286707003 | ||||||
|  |  -rw-------. 1 root root  1812 Oct 27 22:07 dmesg-efi-166692286708003 | ||||||
|  |  -rw-------. 1 root root  1769 Oct 27 22:07 dmesg-efi-166692286709003 | ||||||
|  |  -rw-------. 1 root root  1820 Oct 27 22:07 dmesg-efi-166692286710003 | ||||||
|  |  -rw-------. 1 root root  1755 Oct 27 22:07 dmesg-efi-166692286711003 | ||||||
|  |  -rw-------. 1 root root  1790 Oct 27 22:07 dmesg-efi-166692286712003 | ||||||
|  |  -rw-------. 1 root root  1756 Oct 27 22:07 dmesg-efi-166692286713003 | ||||||
|  |  -rw-------. 1 root root  1763 Oct 27 22:07 dmesg-efi-166692286714003 | ||||||
|  |  -rw-------. 1 root root  1791 Oct 27 22:07 dmesg-efi-166692286715003 | ||||||
|  |  -rw-------. 1 root root  1775 Oct 27 22:07 dmesg-efi-166692286716003 | ||||||
|  |  -rw-------. 1 root root  1820 Oct 27 22:07 dmesg-efi-166692286717003 | ||||||
|  |  -rw-r-----. 1 root root 30111 Nov 18 14:58 dmesg.txt | ||||||
|  | 
 | ||||||
|  | Furthemore, pstore records on ERST are now able to accurately | ||||||
|  | identify the change in timestamp sequence in order to start a | ||||||
|  | new dmesg.txt, as needed. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 5fbaa757077bde2db8d33b1c358518c41b990339) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  src/pstore/pstore.c | 216 +++++++++++++++++++------------------------- | ||||||
|  |  1 file changed, 92 insertions(+), 124 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
 | ||||||
|  | index d70e142b4d..9f61e8f7f8 100644
 | ||||||
|  | --- a/src/pstore/pstore.c
 | ||||||
|  | +++ b/src/pstore/pstore.c
 | ||||||
|  | @@ -112,8 +112,8 @@ static int compare_pstore_entries(const void *_a, const void *_b) {
 | ||||||
|  |          return strcmp(a->dirent.d_name, b->dirent.d_name); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int move_file(PStoreEntry *pe, const char *subdir) {
 | ||||||
|  | -        _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
 | ||||||
|  | +static int move_file(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
 | ||||||
|  | +        _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL, *ofd_path_base = NULL;
 | ||||||
|  |          _cleanup_free_ void *field = NULL; | ||||||
|  |          const char *suffix, *message; | ||||||
|  |          struct iovec iovec[2]; | ||||||
|  | @@ -126,7 +126,11 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
 | ||||||
|  |          if (!ifd_path) | ||||||
|  |                  return log_oom(); | ||||||
|  |   | ||||||
|  | -        ofd_path = path_join(arg_archivedir, subdir, pe->dirent.d_name);
 | ||||||
|  | +        ofd_path_base = path_join(arg_archivedir, subdir1, subdir2);
 | ||||||
|  | +        if (!ofd_path_base)
 | ||||||
|  | +                return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +        ofd_path = path_join(NULL, ofd_path_base, pe->dirent.d_name);
 | ||||||
|  |          if (!ofd_path) | ||||||
|  |                  return log_oom(); | ||||||
|  |   | ||||||
|  | @@ -169,155 +173,119 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
 | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int write_dmesg(const char *dmesg, size_t size, const char *id) {
 | ||||||
|  | -        _cleanup_(unlink_and_freep) char *tmp_path = NULL;
 | ||||||
|  | -        _cleanup_free_ char *ofd_path = NULL;
 | ||||||
|  | +static int append_dmesg(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
 | ||||||
|  | +        /* Append dmesg chunk to end, create if needed */
 | ||||||
|  | +        _cleanup_free_ char *ofd_path = NULL, *ofd_path_base = NULL;
 | ||||||
|  |          _cleanup_close_ int ofd = -1; | ||||||
|  |          ssize_t wr; | ||||||
|  | -        int r;
 | ||||||
|  |   | ||||||
|  | -        if (size == 0)
 | ||||||
|  | -                return 0;
 | ||||||
|  | +        assert(pe);
 | ||||||
|  |   | ||||||
|  | -        assert(dmesg);
 | ||||||
|  | +        if (pe->content_size == 0)
 | ||||||
|  | +                return 0;
 | ||||||
|  |   | ||||||
|  | -        /* log_info("Record ID %s", id); */
 | ||||||
|  | +        ofd_path_base = path_join(arg_archivedir, subdir1, subdir2);
 | ||||||
|  | +        if (!ofd_path_base)
 | ||||||
|  | +                return log_oom();
 | ||||||
|  |   | ||||||
|  | -        ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
 | ||||||
|  | +        ofd_path = path_join(NULL, ofd_path_base, "dmesg.txt");
 | ||||||
|  |          if (!ofd_path) | ||||||
|  |                  return log_oom(); | ||||||
|  |   | ||||||
|  | -        ofd = open_tmpfile_linkable(ofd_path, O_CLOEXEC|O_CREAT|O_TRUNC|O_WRONLY, &tmp_path);
 | ||||||
|  | +        ofd = open(ofd_path, O_CREAT|O_NOFOLLOW|O_NOCTTY|O_CLOEXEC|O_APPEND|O_WRONLY, 0640);
 | ||||||
|  |          if (ofd < 0) | ||||||
|  | -                return log_error_errno(ofd, "Failed to open temporary file %s: %m", ofd_path);
 | ||||||
|  | -        wr = write(ofd, dmesg, size);
 | ||||||
|  | +                return log_error_errno(ofd, "Failed to open file %s: %m", ofd_path);
 | ||||||
|  | +        wr = write(ofd, pe->content, pe->content_size);
 | ||||||
|  |          if (wr < 0) | ||||||
|  |                  return log_error_errno(errno, "Failed to store dmesg to %s: %m", ofd_path); | ||||||
|  | -        if (wr != (ssize_t)size)
 | ||||||
|  | -                return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, size - wr);
 | ||||||
|  | -        r = link_tmpfile(ofd, tmp_path, ofd_path);
 | ||||||
|  | -        if (r < 0)
 | ||||||
|  | -                return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path);
 | ||||||
|  | -        tmp_path = mfree(tmp_path);
 | ||||||
|  | +        if ((size_t)wr != pe->content_size)
 | ||||||
|  | +                return log_error_errno(-EIO, "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, pe->content_size - wr);
 | ||||||
|  |   | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void process_dmesg_files(PStoreList *list) {
 | ||||||
|  | +static int process_dmesg_files(PStoreList *list) {
 | ||||||
|  |          /* Move files, reconstruct dmesg.txt */ | ||||||
|  | -        _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
 | ||||||
|  | -        size_t dmesg_size = 0, dmesg_allocated = 0;
 | ||||||
|  | -        bool dmesg_bad = false;
 | ||||||
|  | -        PStoreEntry *pe;
 | ||||||
|  | +        _cleanup_free_ char *erst_subdir = NULL;
 | ||||||
|  | +        uint64_t last_record_id = 0;
 | ||||||
|  | +
 | ||||||
|  | +        /* When dmesg is written into pstore, it is done so in small chunks, whatever the exchange buffer
 | ||||||
|  | +         * size is with the underlying pstore backend (ie. EFI may be ~2KiB), which means an example
 | ||||||
|  | +         * pstore with approximately 64KB of storage may have up to roughly 32 dmesg files, some likely
 | ||||||
|  | +         * related.
 | ||||||
|  | +         *
 | ||||||
|  | +         * Here we look at the dmesg filename and try to discern if files are part of a related group,
 | ||||||
|  | +         * meaning the same original dmesg.
 | ||||||
|  | +         *
 | ||||||
|  | +         * The dmesg- filename contains the backend-type and the Common Platform Error Record, CPER,
 | ||||||
|  | +         * record id, a 64-bit number.
 | ||||||
|  | +         *
 | ||||||
|  | +         * Files are processed in reverse lexigraphical order so as to properly reconstruct original dmesg.*/
 | ||||||
|  |   | ||||||
|  | -        /* Handle each dmesg file: files processed in reverse
 | ||||||
|  | -         * order so as to properly reconstruct original dmesg */
 | ||||||
|  |          for (size_t n = list->n_entries; n > 0; n--) { | ||||||
|  | -                bool move_file_and_continue = false;
 | ||||||
|  | -                _cleanup_free_ char *pe_id = NULL;
 | ||||||
|  | +                PStoreEntry *pe;
 | ||||||
|  |                  char *p; | ||||||
|  | -                size_t plen;
 | ||||||
|  |   | ||||||
|  |                  pe = &list->entries[n-1]; | ||||||
|  |   | ||||||
|  |                  if (pe->handled) | ||||||
|  |                          continue; | ||||||
|  | -                if (!startswith(pe->dirent.d_name, "dmesg-"))
 | ||||||
|  | -                        continue;
 | ||||||
|  | -
 | ||||||
|  |                  if (endswith(pe->dirent.d_name, ".enc.z")) /* indicates a problem */ | ||||||
|  | -                        move_file_and_continue = true;
 | ||||||
|  | -                p = strrchr(pe->dirent.d_name, '-');
 | ||||||
|  | -                if (!p)
 | ||||||
|  | -                        move_file_and_continue = true;
 | ||||||
|  | -
 | ||||||
|  | -                if (move_file_and_continue) {
 | ||||||
|  | -                        /* A dmesg file on which we do NO additional processing */
 | ||||||
|  | -                        (void) move_file(pe, NULL);
 | ||||||
|  |                          continue; | ||||||
|  | -                }
 | ||||||
|  | -
 | ||||||
|  | -                /* See if this file is one of a related group of files
 | ||||||
|  | -                 * in order to reconstruct dmesg */
 | ||||||
|  | -
 | ||||||
|  | -                /* When dmesg is written into pstore, it is done so in
 | ||||||
|  | -                 * small chunks, whatever the exchange buffer size is
 | ||||||
|  | -                 * with the underlying pstore backend (ie. EFI may be
 | ||||||
|  | -                 * ~2KiB), which means an example pstore with approximately
 | ||||||
|  | -                 * 64KB of storage may have up to roughly 32 dmesg files
 | ||||||
|  | -                 * that could be related, depending upon the size of the
 | ||||||
|  | -                 * original dmesg.
 | ||||||
|  | -                 *
 | ||||||
|  | -                 * Here we look at the dmesg filename and try to discern
 | ||||||
|  | -                 * if files are part of a related group, meaning the same
 | ||||||
|  | -                 * original dmesg.
 | ||||||
|  | -                 *
 | ||||||
|  | -                 * The two known pstore backends are EFI and ERST. These
 | ||||||
|  | -                 * backends store data in the Common Platform Error
 | ||||||
|  | -                 * Record, CPER, format. The dmesg- filename contains the
 | ||||||
|  | -                 * CPER record id, a 64bit number (in decimal notation).
 | ||||||
|  | -                 * In Linux, the record id is encoded with two digits for
 | ||||||
|  | -                 * the dmesg part (chunk) number and 3 digits for the
 | ||||||
|  | -                 * count number. So allowing an additional digit to
 | ||||||
|  | -                 * compensate for advancing time, this code ignores the
 | ||||||
|  | -                 * last six digits of the filename in determining the
 | ||||||
|  | -                 * record id.
 | ||||||
|  | -                 *
 | ||||||
|  | -                 * For the EFI backend, the record id encodes an id in the
 | ||||||
|  | -                 * upper 32 bits, and a timestamp in the lower 32-bits.
 | ||||||
|  | -                 * So ignoring the least significant 6 digits has proven
 | ||||||
|  | -                 * to generally identify related dmesg entries.  */
 | ||||||
|  | -#define PSTORE_FILENAME_IGNORE 6
 | ||||||
|  | -
 | ||||||
|  | -                /* determine common portion of record id */
 | ||||||
|  | -                ++p; /* move beyond dmesg- */
 | ||||||
|  | -                plen = strlen(p);
 | ||||||
|  | -                if (plen > PSTORE_FILENAME_IGNORE) {
 | ||||||
|  | -                        pe_id = memdup_suffix0(p, plen - PSTORE_FILENAME_IGNORE);
 | ||||||
|  | -                        if (!pe_id) {
 | ||||||
|  | -                                log_oom();
 | ||||||
|  | -                                return;
 | ||||||
|  | -                        }
 | ||||||
|  | -                } else
 | ||||||
|  | -                        pe_id = mfree(pe_id);
 | ||||||
|  | -
 | ||||||
|  | -                /* Now move file from pstore to archive storage */
 | ||||||
|  | -                move_file(pe, pe_id);
 | ||||||
|  | -
 | ||||||
|  | -                if (dmesg_bad)
 | ||||||
|  | +                if (!startswith(pe->dirent.d_name, "dmesg-"))
 | ||||||
|  |                          continue; | ||||||
|  |   | ||||||
|  | -                /* If the current record id is NOT the same as the
 | ||||||
|  | -                 * previous record id, then start a new dmesg.txt file */
 | ||||||
|  | -                if (!streq_ptr(pe_id, dmesg_id)) {
 | ||||||
|  | -                        /* Encountered a new dmesg group, close out old one, open new one */
 | ||||||
|  | -                        (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
 | ||||||
|  | -                        dmesg_size = 0;
 | ||||||
|  | -
 | ||||||
|  | -                        /* now point dmesg_id to storage of pe_id */
 | ||||||
|  | -                        free_and_replace(dmesg_id, pe_id);
 | ||||||
|  | -                }
 | ||||||
|  | -
 | ||||||
|  | -                /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled
 | ||||||
|  | -                 * output either. */
 | ||||||
|  | -                size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1;
 | ||||||
|  | -                if (!GREEDY_REALLOC(dmesg, dmesg_allocated, dmesg_size + needed)) {
 | ||||||
|  | -                        log_warning_errno(ENOMEM, "Failed to write dmesg file: %m");
 | ||||||
|  | -                        dmesg_bad = true;
 | ||||||
|  | -                        continue;
 | ||||||
|  | -                }
 | ||||||
|  | -
 | ||||||
|  | -                dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name);
 | ||||||
|  | -                if (pe->content) {
 | ||||||
|  | -                        memcpy(dmesg + dmesg_size, pe->content, pe->content_size);
 | ||||||
|  | -                        dmesg_size += pe->content_size;
 | ||||||
|  | -                }
 | ||||||
|  | -
 | ||||||
|  | -                pe_id = mfree(pe_id);
 | ||||||
|  | +                if ((p = startswith(pe->dirent.d_name, "dmesg-efi-"))) {
 | ||||||
|  | +                        /* For the EFI backend, the 3 least significant digits of record id encodes a
 | ||||||
|  | +                         * "count" number, the next 2 least significant digits for the dmesg part
 | ||||||
|  | +                         * (chunk) number, and the remaining digits as the timestamp.  See
 | ||||||
|  | +                         * linux/drivers/firmware/efi/efi-pstore.c in efi_pstore_write(). */
 | ||||||
|  | +                        _cleanup_free_ char *subdir1 = NULL, *subdir2 = NULL;
 | ||||||
|  | +                        size_t plen = strlen(p);
 | ||||||
|  | +
 | ||||||
|  | +                        if (plen < 6)
 | ||||||
|  | +                                continue;
 | ||||||
|  | +
 | ||||||
|  | +                        /* Extract base record id */
 | ||||||
|  | +                        subdir1 = strndup(p, plen - 5);
 | ||||||
|  | +                        if (!subdir1)
 | ||||||
|  | +                                return log_oom();
 | ||||||
|  | +                        /* Extract "count" field */
 | ||||||
|  | +                        subdir2 = strndup(p + plen - 3, 3);
 | ||||||
|  | +                        if (!subdir2)
 | ||||||
|  | +                                return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +                        /* Now move file from pstore to archive storage */
 | ||||||
|  | +                        (void) move_file(pe, subdir1, subdir2);
 | ||||||
|  | +
 | ||||||
|  | +                        /* Append to the dmesg */
 | ||||||
|  | +                        (void) append_dmesg(pe, subdir1, subdir2);
 | ||||||
|  | +                } else if ((p = startswith(pe->dirent.d_name, "dmesg-erst-"))) {
 | ||||||
|  | +                        /* For the ERST backend, the record is a monotonically increasing number, seeded as
 | ||||||
|  | +                         * a timestamp. See linux/drivers/acpi/apei/erst.c in erst_writer(). */
 | ||||||
|  | +                        uint64_t record_id;
 | ||||||
|  | +
 | ||||||
|  | +                        if (safe_atou64(p, &record_id) < 0)
 | ||||||
|  | +                                continue;
 | ||||||
|  | +                        if (last_record_id - 1 != record_id)
 | ||||||
|  | +                                /* A discontinuity in the number has been detected, this current record id
 | ||||||
|  | +                                 * will become the directory name for all pieces of the dmesg in this
 | ||||||
|  | +                                 * series. */
 | ||||||
|  | +                                if (free_and_strdup(&erst_subdir, p) < 0)
 | ||||||
|  | +                                        return log_oom();
 | ||||||
|  | +
 | ||||||
|  | +                        /* Now move file from pstore to archive storage */
 | ||||||
|  | +                        (void) move_file(pe, erst_subdir, NULL);
 | ||||||
|  | +
 | ||||||
|  | +                        /* Append to the dmesg */
 | ||||||
|  | +                        (void) append_dmesg(pe, erst_subdir, NULL);
 | ||||||
|  | +
 | ||||||
|  | +                        /* Update, but keep erst_subdir for next file */
 | ||||||
|  | +                        last_record_id = record_id;
 | ||||||
|  | +                } else
 | ||||||
|  | +                        log_debug("Unknown backend, ignoring \"%s\".", pe->dirent.d_name);
 | ||||||
|  |          } | ||||||
|  | -
 | ||||||
|  | -        if (!dmesg_bad)
 | ||||||
|  | -                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
 | ||||||
|  | +        return 0;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int list_files(PStoreList *list, const char *sourcepath) { | ||||||
|  | @@ -394,11 +362,11 @@ static int run(int argc, char *argv[]) {
 | ||||||
|  |          qsort_safe(list.entries, list.n_entries, sizeof(PStoreEntry), compare_pstore_entries); | ||||||
|  |   | ||||||
|  |          /* Process known file types */ | ||||||
|  | -        process_dmesg_files(&list);
 | ||||||
|  | +        (void) process_dmesg_files(&list);
 | ||||||
|  |   | ||||||
|  |          /* Move left over files out of pstore */ | ||||||
|  |          for (size_t n = 0; n < list.n_entries; n++) | ||||||
|  | -                move_file(&list.entries[n], NULL);
 | ||||||
|  | +                (void) move_file(&list.entries[n], NULL, NULL);
 | ||||||
|  |   | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
| @ -0,0 +1,27 @@ | |||||||
|  | From 653a635086cfeaf0af12da3a722b0ebe2029b927 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Balint Reczey <balint.reczey@canonical.com> | ||||||
|  | Date: Mon, 16 Dec 2019 19:03:19 +0100 | ||||||
|  | Subject: [PATCH] pstore: Don't start systemd-pstore.service in containers | ||||||
|  | 
 | ||||||
|  | Usually it is not useful and can also fail making | ||||||
|  | boot-and-services autopkgtest fail. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 287f506c32f3f4a48ba020408f964cb0f964d752) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-pstore.service.in | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | index dde21bc33e..89f34afe34 100644
 | ||||||
|  | --- a/units/systemd-pstore.service.in
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -11,6 +11,7 @@
 | ||||||
|  |  Description=Platform Persistent Storage Archival | ||||||
|  |  Documentation=man:systemd-pstore(8) | ||||||
|  |  ConditionDirectoryNotEmpty=/sys/fs/pstore | ||||||
|  | +ConditionVirtualization=!container
 | ||||||
|  |  DefaultDependencies=no | ||||||
|  |  Wants=systemd-remount-fs.service | ||||||
|  |  After=systemd-remount-fs.service | ||||||
| @ -0,0 +1,36 @@ | |||||||
|  | From c7e65774a4ccc8a431f63c5a12ab776b24ee1190 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Wed, 8 Apr 2020 16:12:00 +0200 | ||||||
|  | Subject: [PATCH] units: pull in systemd-pstore.service from sysinit.target | ||||||
|  | 
 | ||||||
|  | sysinit.target is the target our early boot services are generally | ||||||
|  | pulled in from, make systemd-pstore.service not an exception of that. | ||||||
|  | 
 | ||||||
|  | Effectively this doesn't mean much, either way our unit is part of the | ||||||
|  | initial transaction. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 167241912f51fbc0d7d0869b9af34c15b5ecc4b6) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-pstore.service.in | 3 ++- | ||||||
|  |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | index 89f34afe34..37fcf878f0 100644
 | ||||||
|  | --- a/units/systemd-pstore.service.in
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -15,6 +15,7 @@ ConditionVirtualization=!container
 | ||||||
|  |  DefaultDependencies=no | ||||||
|  |  Wants=systemd-remount-fs.service | ||||||
|  |  After=systemd-remount-fs.service | ||||||
|  | +Before=sysinit.target
 | ||||||
|  |   | ||||||
|  |  [Service] | ||||||
|  |  Type=oneshot | ||||||
|  | @@ -23,4 +24,4 @@ RemainAfterExit=yes
 | ||||||
|  |  StateDirectory=systemd/pstore | ||||||
|  |   | ||||||
|  |  [Install] | ||||||
|  | -WantedBy=systemd-remount-fs.service
 | ||||||
|  | +WantedBy=sysinit.target
 | ||||||
| @ -0,0 +1,36 @@ | |||||||
|  | From bc6f273a0475a1fa7ab56bc1e498ee62c96aa660 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Wed, 8 Apr 2020 16:10:38 +0200 | ||||||
|  | Subject: [PATCH] units: drop dependency on systemd-remount-fs.service from | ||||||
|  |  systemd-pstore.service | ||||||
|  | 
 | ||||||
|  | This dependency is now generated automatically given we use | ||||||
|  | StateDirectory=. Moreover the combination of Wants= and After= was too | ||||||
|  | strong anway, as whether remount-fs is pulled in or not should not be up | ||||||
|  | to systemd-pstore.service, and in fact is part of the initial | ||||||
|  | transaction anyway. | ||||||
|  | 
 | ||||||
|  | [dtardon: This only removes Wants=, not After=, because I haven't | ||||||
|  | backported the auto-generation code the description talks about. The | ||||||
|  | code is simple, but it's just an optimisation allowing for slightly | ||||||
|  | shorter unit files, hence I don't think we really need it.] | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 0c978faa16fa9ecf92f0bbb5c7cc709dc472d115) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-pstore.service.in | 1 - | ||||||
|  |  1 file changed, 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | index 37fcf878f0..9a86f3145c 100644
 | ||||||
|  | --- a/units/systemd-pstore.service.in
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -13,7 +13,6 @@ Documentation=man:systemd-pstore(8)
 | ||||||
|  |  ConditionDirectoryNotEmpty=/sys/fs/pstore | ||||||
|  |  ConditionVirtualization=!container | ||||||
|  |  DefaultDependencies=no | ||||||
|  | -Wants=systemd-remount-fs.service
 | ||||||
|  |  After=systemd-remount-fs.service | ||||||
|  |  Before=sysinit.target | ||||||
|  |   | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | From 818ddd1efd751ef50f9960920284465befe9d704 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Wed, 8 Apr 2020 16:25:03 +0200 | ||||||
|  | Subject: [PATCH] units: make sure systemd-pstore stops at shutdown | ||||||
|  | 
 | ||||||
|  | This doesn't matter too much given that the service doesn't do anything | ||||||
|  | on shutdown, but let's still stop it to make things cleaner. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit b0c1a07654c80d3cbbbcc52f860d4206707c0b08) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-pstore.service.in | 3 ++- | ||||||
|  |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | index 9a86f3145c..8cbf264a99 100644
 | ||||||
|  | --- a/units/systemd-pstore.service.in
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -14,7 +14,8 @@ ConditionDirectoryNotEmpty=/sys/fs/pstore
 | ||||||
|  |  ConditionVirtualization=!container | ||||||
|  |  DefaultDependencies=no | ||||||
|  |  After=systemd-remount-fs.service | ||||||
|  | -Before=sysinit.target
 | ||||||
|  | +Conflicts=shutdown.target
 | ||||||
|  | +Before=sysinit.target shutdown.target
 | ||||||
|  |   | ||||||
|  |  [Service] | ||||||
|  |  Type=oneshot | ||||||
							
								
								
									
										45
									
								
								SOURCES/0892-pstore-Run-after-modules-are-loaded.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								SOURCES/0892-pstore-Run-after-modules-are-loaded.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | From 9cc6ee46e0083bc36b53d19e14fb637f7a1542dd Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Alexander Graf <graf@amazon.com> | ||||||
|  | Date: Thu, 9 Jun 2022 16:20:43 +0200 | ||||||
|  | Subject: [PATCH] pstore: Run after modules are loaded | ||||||
|  | 
 | ||||||
|  | The systemd-pstore service takes pstore files on boot and transfers them | ||||||
|  | to disk. It only does it once on boot and only if it finds any. The typical | ||||||
|  | location of the pstore on modern systems is the UEFI variable store. | ||||||
|  | 
 | ||||||
|  | Most distributions ship with CONFIG_EFI_VARS_PSTORE=m. That means, the | ||||||
|  | UEFI variable store is only available on boot after the respective module | ||||||
|  | is loaded. | ||||||
|  | 
 | ||||||
|  | In most situations, the pstore service gets loaded before the UEFI pstore, | ||||||
|  | so we don't get to transfer logs. Instead, they accumulate, filling up the | ||||||
|  | pstore over time, potentially breaking the UEFI variable store. | ||||||
|  | 
 | ||||||
|  | Let's add a service dependency on any kernel module that can provide a | ||||||
|  | pstore to ensure we only scan for pstate after we can actually see pstate. | ||||||
|  | 
 | ||||||
|  | I have seen live occurences of systems breaking because we did not erase | ||||||
|  | the pstates and ran out of UEFI nvram space. | ||||||
|  | 
 | ||||||
|  | Fixes https://github.com/systemd/systemd/issues/18540 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 70e74a5997ae2ce7ba72a74ac949c3b2dad1a1d6) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-pstore.service.in | 2 ++ | ||||||
|  |  1 file changed, 2 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | index 8cbf264a99..1983a9738f 100644
 | ||||||
|  | --- a/units/systemd-pstore.service.in
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -16,6 +16,8 @@ DefaultDependencies=no
 | ||||||
|  |  After=systemd-remount-fs.service | ||||||
|  |  Conflicts=shutdown.target | ||||||
|  |  Before=sysinit.target shutdown.target | ||||||
|  | +After=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
 | ||||||
|  | +Wants=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
 | ||||||
|  |   | ||||||
|  |  [Service] | ||||||
|  |  Type=oneshot | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | From 6a6f108b59e47581d93cbc6bdc604ee84f1bb791 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Nick Rosbrook <nick.rosbrook@canonical.com> | ||||||
|  | Date: Wed, 7 Sep 2022 13:25:13 -0400 | ||||||
|  | Subject: [PATCH] pstore: do not try to load all known pstore modules | ||||||
|  | 
 | ||||||
|  | Commit 70e74a5997 ("pstore: Run after modules are loaded") added After= | ||||||
|  | and Wants= entries for all known kernel modules providing a pstore. | ||||||
|  | 
 | ||||||
|  | While adding these dependencies on systems where one of the modules is | ||||||
|  | not present, or not configured, should not have a real affect on the | ||||||
|  | system, it can produce annoying error messages in the kernel log. E.g. | ||||||
|  | "mtd device must be supplied (device name is empty)" when the mtdpstore | ||||||
|  | module is not configured correctly. | ||||||
|  | 
 | ||||||
|  | Since dependencies cannot be removed with drop-ins, if a distro wants to | ||||||
|  | remove some of these modules from systemd-pstore.service, they need to | ||||||
|  | patch units/systemd-pstore.service.in. On the other hand, if they want | ||||||
|  | to append to the dependencies this can be done by shipping a drop-in. | ||||||
|  | 
 | ||||||
|  | Since the original intent of the previous commit was to fix [1], which | ||||||
|  | only requires the efi_pstore module, remove all other kernel module | ||||||
|  | dependencies from systemd-pstore.service, and let distros ship drop-ins | ||||||
|  | to add dependencies if needed. | ||||||
|  | 
 | ||||||
|  | [1] https://github.com/systemd/systemd/issues/18540 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 8b8bd621e1d16808678fc3afed257df1fa03a281) | ||||||
|  | 
 | ||||||
|  | Related: #2158832 | ||||||
|  | ---
 | ||||||
|  |  units/systemd-pstore.service.in | 4 ++-- | ||||||
|  |  1 file changed, 2 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/units/systemd-pstore.service.in b/units/systemd-pstore.service.in
 | ||||||
|  | index 1983a9738f..19ffa8d4e8 100644
 | ||||||
|  | --- a/units/systemd-pstore.service.in
 | ||||||
|  | +++ b/units/systemd-pstore.service.in
 | ||||||
|  | @@ -16,8 +16,8 @@ DefaultDependencies=no
 | ||||||
|  |  After=systemd-remount-fs.service | ||||||
|  |  Conflicts=shutdown.target | ||||||
|  |  Before=sysinit.target shutdown.target | ||||||
|  | -After=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
 | ||||||
|  | -Wants=modprobe@efi_pstore.service modprobe@mtdpstore.service modprobe@chromeos_pstore.service modprobe@ramoops.service modprobe@pstore_zone.service modprobe@pstore_blk.service
 | ||||||
|  | +After=modprobe@efi_pstore.service
 | ||||||
|  | +Wants=modprobe@efi_pstore.service
 | ||||||
|  |   | ||||||
|  |  [Service] | ||||||
|  |  Type=oneshot | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | From b18e19f2262e7ed95c25d53268d12427fe77102d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Tardon <dtardon@redhat.com> | ||||||
|  | Date: Tue, 21 Feb 2023 10:41:47 +0100 | ||||||
|  | Subject: [PATCH] logind-session: make stopping of idle session visible to | ||||||
|  |  admins | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 6269ffe7ee8a659df7336a2582054ecd9eecf4b1) | ||||||
|  | 
 | ||||||
|  | Resolves: #2156780 | ||||||
|  | ---
 | ||||||
|  |  src/login/logind-session.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/login/logind-session.c b/src/login/logind-session.c
 | ||||||
|  | index 18a07efcdb..916202a65a 100644
 | ||||||
|  | --- a/src/login/logind-session.c
 | ||||||
|  | +++ b/src/login/logind-session.c
 | ||||||
|  | @@ -673,7 +673,7 @@ static int session_dispatch_stop_on_idle(sd_event_source *source, uint64_t t, vo
 | ||||||
|  |   | ||||||
|  |          idle = session_get_idle_hint(s, &ts); | ||||||
|  |          if (idle) { | ||||||
|  | -                log_debug("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->name);
 | ||||||
|  | +                log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->name);
 | ||||||
|  |   | ||||||
|  |                  return session_stop(s, /* force */ true); | ||||||
|  |          } | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | From a0b52398692f3e4bda18520db9e2397f7b2c80dd Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Benjamin Robin <dev@benjarobin.fr> | ||||||
|  | Date: Sun, 3 May 2020 18:37:21 +0200 | ||||||
|  | Subject: [PATCH] journald: Increase stdout buffer size sooner, when almost | ||||||
|  |  full | ||||||
|  | 
 | ||||||
|  | If the previous received buffer length is almost equal to the allocated | ||||||
|  | buffer size, before this change the next read can only receive a couple | ||||||
|  | of bytes (in the worst case only 1 byte), which is not efficient. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 034e9719ac1ba88a36b05da38c7aa98761d42c77) | ||||||
|  | 
 | ||||||
|  | Related: #2029426 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-stream.c | 4 ++-- | ||||||
|  |  1 file changed, 2 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
 | ||||||
|  | index 302a82d3d7..c8de984335 100644
 | ||||||
|  | --- a/src/journal/journald-stream.c
 | ||||||
|  | +++ b/src/journal/journald-stream.c
 | ||||||
|  | @@ -507,8 +507,8 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
 | ||||||
|  |                  goto terminate; | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | -        /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */
 | ||||||
|  | -        if (s->length + 1 >= s->allocated) {
 | ||||||
|  | +        /* If the buffer is almost full, add room for another 1K */
 | ||||||
|  | +        if (s->length + 512 >= s->allocated) {
 | ||||||
|  |                  if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) { | ||||||
|  |                          log_oom(); | ||||||
|  |                          goto terminate; | ||||||
| @ -0,0 +1,77 @@ | |||||||
|  | From d8fabe7a6839eeb0d5d0504471f2d18b07545238 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Tue, 12 May 2020 18:53:35 +0200 | ||||||
|  | Subject: [PATCH] journald: rework end of line marker handling to use a field | ||||||
|  |  table | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 549b7379ba404c33fd448d2bca46a57f6529b00b) | ||||||
|  | 
 | ||||||
|  | Related: #2029426 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-stream.c | 29 ++++++++++++++++++++--------- | ||||||
|  |  1 file changed, 20 insertions(+), 9 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
 | ||||||
|  | index c8de984335..58752a5a24 100644
 | ||||||
|  | --- a/src/journal/journald-stream.c
 | ||||||
|  | +++ b/src/journal/journald-stream.c
 | ||||||
|  | @@ -54,6 +54,8 @@ typedef enum LineBreak {
 | ||||||
|  |          LINE_BREAK_NUL, | ||||||
|  |          LINE_BREAK_LINE_MAX, | ||||||
|  |          LINE_BREAK_EOF, | ||||||
|  | +        _LINE_BREAK_MAX,
 | ||||||
|  | +        _LINE_BREAK_INVALID = -1,
 | ||||||
|  |  } LineBreak; | ||||||
|  |   | ||||||
|  |  struct StdoutStream { | ||||||
|  | @@ -233,7 +235,11 @@ fail:
 | ||||||
|  |          return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) {
 | ||||||
|  | +static int stdout_stream_log(
 | ||||||
|  | +                StdoutStream *s,
 | ||||||
|  | +                const char *p,
 | ||||||
|  | +                LineBreak line_break) {
 | ||||||
|  | +
 | ||||||
|  |          struct iovec *iovec; | ||||||
|  |          int priority; | ||||||
|  |          char syslog_priority[] = "PRIORITY=\0"; | ||||||
|  | @@ -245,6 +251,9 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea
 | ||||||
|  |          assert(s); | ||||||
|  |          assert(p); | ||||||
|  |   | ||||||
|  | +        assert(line_break >= 0);
 | ||||||
|  | +        assert(line_break < _LINE_BREAK_MAX);
 | ||||||
|  | +
 | ||||||
|  |          if (s->context) | ||||||
|  |                  (void) client_context_maybe_refresh(s->server, s->context, NULL, NULL, 0, NULL, USEC_INFINITY); | ||||||
|  |          else if (pid_is_valid(s->ucred.pid)) { | ||||||
|  | @@ -296,17 +305,19 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea
 | ||||||
|  |                          iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier); | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | -        if (line_break != LINE_BREAK_NEWLINE) {
 | ||||||
|  | -                const char *c;
 | ||||||
|  | +        static const char * const line_break_field_table[_LINE_BREAK_MAX] = {
 | ||||||
|  | +                [LINE_BREAK_NEWLINE]    = NULL, /* Do not add field if traditional newline */
 | ||||||
|  | +                [LINE_BREAK_NUL]        = "_LINE_BREAK=nul",
 | ||||||
|  | +                [LINE_BREAK_LINE_MAX]   = "_LINE_BREAK=line-max",
 | ||||||
|  | +                [LINE_BREAK_EOF]        = "_LINE_BREAK=eof",
 | ||||||
|  | +        };
 | ||||||
|  |   | ||||||
|  | -                /* If this log message was generated due to an uncommon line break then mention this in the log
 | ||||||
|  | -                 * entry */
 | ||||||
|  | +        const char *c = line_break_field_table[line_break];
 | ||||||
|  |   | ||||||
|  | -                c =     line_break == LINE_BREAK_NUL ?      "_LINE_BREAK=nul" :
 | ||||||
|  | -                        line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" :
 | ||||||
|  | -                                                            "_LINE_BREAK=eof";
 | ||||||
|  | +        /* If this log message was generated due to an uncommon line break then mention this in the log
 | ||||||
|  | +         * entry */
 | ||||||
|  | +        if (c)
 | ||||||
|  |                  iovec[n++] = IOVEC_MAKE_STRING(c); | ||||||
|  | -        }
 | ||||||
|  |   | ||||||
|  |          message = strappend("MESSAGE=", p); | ||||||
|  |          if (message) | ||||||
| @ -0,0 +1,27 @@ | |||||||
|  | From cd85a657c932725ac7c1b506dc6dd4270d1dc068 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Tue, 12 May 2020 19:15:38 +0200 | ||||||
|  | Subject: [PATCH] journald: use the fact that client_context_release() returns | ||||||
|  |  NULL | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 020b4a023c2c6dda83afb9a82a62e640569c40c1) | ||||||
|  | 
 | ||||||
|  | Related: #2029426 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-stream.c | 3 +-- | ||||||
|  |  1 file changed, 1 insertion(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
 | ||||||
|  | index 58752a5a24..ab1a855943 100644
 | ||||||
|  | --- a/src/journal/journald-stream.c
 | ||||||
|  | +++ b/src/journal/journald-stream.c
 | ||||||
|  | @@ -570,8 +570,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
 | ||||||
|  |                          goto terminate; | ||||||
|  |   | ||||||
|  |                  s->ucred = *ucred; | ||||||
|  | -                client_context_release(s->server, s->context);
 | ||||||
|  | -                s->context = NULL;
 | ||||||
|  | +                s->context = client_context_release(s->server, s->context);
 | ||||||
|  |          } | ||||||
|  |   | ||||||
|  |          s->length += l; | ||||||
							
								
								
									
										219
									
								
								SOURCES/0898-journald-rework-pid-change-handling.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								SOURCES/0898-journald-rework-pid-change-handling.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,219 @@ | |||||||
|  | From 538bd9b42dabf1145cf7ab77f32347d516b01e88 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Tue, 12 May 2020 18:56:34 +0200 | ||||||
|  | Subject: [PATCH] journald: rework pid change handling | ||||||
|  | 
 | ||||||
|  | Let's introduce an explicit line ending marker for line endings due to | ||||||
|  | pid change. | ||||||
|  | 
 | ||||||
|  | Let's also make sure we don't get confused with buffer management. | ||||||
|  | 
 | ||||||
|  | Fixes: #15654 | ||||||
|  | (cherry picked from commit 45ba1ea5e9264d385fa565328fe957ef1d78caa1) | ||||||
|  | 
 | ||||||
|  | Resolves: #2029426 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-stream.c | 99 +++++++++++++++++++++++------------ | ||||||
|  |  1 file changed, 66 insertions(+), 33 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
 | ||||||
|  | index ab1a855943..5be5b0939c 100644
 | ||||||
|  | --- a/src/journal/journald-stream.c
 | ||||||
|  | +++ b/src/journal/journald-stream.c
 | ||||||
|  | @@ -54,6 +54,7 @@ typedef enum LineBreak {
 | ||||||
|  |          LINE_BREAK_NUL, | ||||||
|  |          LINE_BREAK_LINE_MAX, | ||||||
|  |          LINE_BREAK_EOF, | ||||||
|  | +        LINE_BREAK_PID_CHANGE,
 | ||||||
|  |          _LINE_BREAK_MAX, | ||||||
|  |          _LINE_BREAK_INVALID = -1, | ||||||
|  |  } LineBreak; | ||||||
|  | @@ -310,6 +311,7 @@ static int stdout_stream_log(
 | ||||||
|  |                  [LINE_BREAK_NUL]        = "_LINE_BREAK=nul", | ||||||
|  |                  [LINE_BREAK_LINE_MAX]   = "_LINE_BREAK=line-max", | ||||||
|  |                  [LINE_BREAK_EOF]        = "_LINE_BREAK=eof", | ||||||
|  | +                [LINE_BREAK_PID_CHANGE] = "_LINE_BREAK=pid-change",
 | ||||||
|  |          }; | ||||||
|  |   | ||||||
|  |          const char *c = line_break_field_table[line_break]; | ||||||
|  | @@ -431,21 +433,43 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
 | ||||||
|  |          assert_not_reached("Unknown stream state"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
 | ||||||
|  | -        char *p;
 | ||||||
|  | -        size_t remaining;
 | ||||||
|  | +static int stdout_stream_found(
 | ||||||
|  | +                StdoutStream *s,
 | ||||||
|  | +                char *p,
 | ||||||
|  | +                size_t l,
 | ||||||
|  | +                LineBreak line_break) {
 | ||||||
|  | +
 | ||||||
|  | +        char saved;
 | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  |          assert(s); | ||||||
|  | +        assert(p);
 | ||||||
|  | +
 | ||||||
|  | +        /* Let's NUL terminate the specified buffer for this call, and revert back afterwards */
 | ||||||
|  | +        saved = p[l];
 | ||||||
|  | +        p[l] = 0;
 | ||||||
|  | +        r = stdout_stream_line(s, p, line_break);
 | ||||||
|  | +        p[l] = saved;
 | ||||||
|  |   | ||||||
|  | -        p = s->buffer;
 | ||||||
|  | -        remaining = s->length;
 | ||||||
|  | +        return r;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int stdout_stream_scan(
 | ||||||
|  | +                StdoutStream *s,
 | ||||||
|  | +                char *p,
 | ||||||
|  | +                size_t remaining,
 | ||||||
|  | +                LineBreak force_flush,
 | ||||||
|  | +                size_t *ret_consumed) {
 | ||||||
|  |   | ||||||
|  | -        /* XXX: This function does nothing if (s->length == 0) */
 | ||||||
|  | +        size_t consumed = 0;
 | ||||||
|  | +        int r;
 | ||||||
|  | +
 | ||||||
|  | +        assert(s);
 | ||||||
|  | +        assert(p);
 | ||||||
|  |   | ||||||
|  |          for (;;) { | ||||||
|  |                  LineBreak line_break; | ||||||
|  | -                size_t skip;
 | ||||||
|  | +                size_t skip, found;
 | ||||||
|  |                  char *end1, *end2; | ||||||
|  |   | ||||||
|  |                  end1 = memchr(p, '\n', remaining); | ||||||
|  | @@ -453,43 +477,40 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
 | ||||||
|  |   | ||||||
|  |                  if (end2) { | ||||||
|  |                          /* We found a NUL terminator */ | ||||||
|  | -                        skip = end2 - p + 1;
 | ||||||
|  | +                        found = end2 - p;
 | ||||||
|  | +                        skip = found + 1;
 | ||||||
|  |                          line_break = LINE_BREAK_NUL; | ||||||
|  |                  } else if (end1) { | ||||||
|  |                          /* We found a \n terminator */ | ||||||
|  | -                        *end1 = 0;
 | ||||||
|  | -                        skip = end1 - p + 1;
 | ||||||
|  | +                        found = end1 - p;
 | ||||||
|  | +                        skip = found + 1;
 | ||||||
|  |                          line_break = LINE_BREAK_NEWLINE; | ||||||
|  |                  } else if (remaining >= s->server->line_max) { | ||||||
|  |                          /* Force a line break after the maximum line length */ | ||||||
|  | -                        *(p + s->server->line_max) = 0;
 | ||||||
|  | -                        skip = remaining;
 | ||||||
|  | +                        found = skip = s->server->line_max;
 | ||||||
|  |                          line_break = LINE_BREAK_LINE_MAX; | ||||||
|  |                  } else | ||||||
|  |                          break; | ||||||
|  |   | ||||||
|  | -                r = stdout_stream_line(s, p, line_break);
 | ||||||
|  | +                r = stdout_stream_found(s, p, found, line_break);
 | ||||||
|  |                  if (r < 0) | ||||||
|  |                          return r; | ||||||
|  |   | ||||||
|  | -                remaining -= skip;
 | ||||||
|  |                  p += skip; | ||||||
|  | +                consumed += skip;
 | ||||||
|  | +                remaining -= skip;
 | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | -        if (force_flush && remaining > 0) {
 | ||||||
|  | -                p[remaining] = 0;
 | ||||||
|  | -                r = stdout_stream_line(s, p, LINE_BREAK_EOF);
 | ||||||
|  | +        if (force_flush >= 0 && remaining > 0) {
 | ||||||
|  | +                r = stdout_stream_found(s, p, remaining, force_flush);
 | ||||||
|  |                  if (r < 0) | ||||||
|  |                          return r; | ||||||
|  |   | ||||||
|  | -                p += remaining;
 | ||||||
|  | -                remaining = 0;
 | ||||||
|  | +                consumed += remaining;
 | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | -        if (p > s->buffer) {
 | ||||||
|  | -                memmove(s->buffer, p, remaining);
 | ||||||
|  | -                s->length = remaining;
 | ||||||
|  | -        }
 | ||||||
|  | +        if (ret_consumed)
 | ||||||
|  | +                *ret_consumed = consumed;
 | ||||||
|  |   | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  | @@ -497,11 +518,12 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
 | ||||||
|  |  static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { | ||||||
|  |          uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; | ||||||
|  |          StdoutStream *s = userdata; | ||||||
|  | +        size_t limit, consumed;
 | ||||||
|  |          struct ucred *ucred = NULL; | ||||||
|  |          struct cmsghdr *cmsg; | ||||||
|  |          struct iovec iovec; | ||||||
|  | -        size_t limit;
 | ||||||
|  |          ssize_t l; | ||||||
|  | +        char *p;
 | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  |          struct msghdr msghdr = { | ||||||
|  | @@ -529,7 +551,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
 | ||||||
|  |          /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, | ||||||
|  |           * always leave room for a terminating NUL we might need to add. */ | ||||||
|  |          limit = MIN(s->allocated - 1, s->server->line_max); | ||||||
|  | -
 | ||||||
|  | +        assert(s->length <= limit);
 | ||||||
|  |          iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); | ||||||
|  |   | ||||||
|  |          l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); | ||||||
|  | @@ -543,7 +565,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
 | ||||||
|  |          cmsg_close_all(&msghdr); | ||||||
|  |   | ||||||
|  |          if (l == 0) { | ||||||
|  | -                stdout_stream_scan(s, true);
 | ||||||
|  | +                (void) stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_EOF, NULL);
 | ||||||
|  |                  goto terminate; | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | @@ -562,22 +584,33 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
 | ||||||
|  |           * in the meantime. | ||||||
|  |           */ | ||||||
|  |          if (ucred && ucred->pid != s->ucred.pid) { | ||||||
|  | -                /* force out any previously half-written lines from a
 | ||||||
|  | -                 * different process, before we switch to the new ucred
 | ||||||
|  | -                 * structure for everything we just added */
 | ||||||
|  | -                r = stdout_stream_scan(s, true);
 | ||||||
|  | +                /* Force out any previously half-written lines from a different process, before we switch to
 | ||||||
|  | +                 * the new ucred structure for everything we just added */
 | ||||||
|  | +                r = stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_PID_CHANGE, NULL);
 | ||||||
|  |                  if (r < 0) | ||||||
|  |                          goto terminate; | ||||||
|  |   | ||||||
|  | -                s->ucred = *ucred;
 | ||||||
|  |                  s->context = client_context_release(s->server, s->context); | ||||||
|  | +
 | ||||||
|  | +                p = s->buffer + s->length;
 | ||||||
|  | +        } else {
 | ||||||
|  | +                p = s->buffer;
 | ||||||
|  | +                l += s->length;
 | ||||||
|  |          } | ||||||
|  |   | ||||||
|  | -        s->length += l;
 | ||||||
|  | -        r = stdout_stream_scan(s, false);
 | ||||||
|  | +        /* Always copy in the new credentials */
 | ||||||
|  | +        if (ucred)
 | ||||||
|  | +                s->ucred = *ucred;
 | ||||||
|  | +
 | ||||||
|  | +        r = stdout_stream_scan(s, p, l, _LINE_BREAK_INVALID, &consumed);
 | ||||||
|  |          if (r < 0) | ||||||
|  |                  goto terminate; | ||||||
|  |   | ||||||
|  | +        /* Move what wasn't consumed to the front of the buffer */
 | ||||||
|  | +        assert(consumed <= (size_t) l);
 | ||||||
|  | +        s->length = l - consumed;
 | ||||||
|  | +        memmove(s->buffer, p + consumed, s->length);
 | ||||||
|  | +
 | ||||||
|  |          return 1; | ||||||
|  |   | ||||||
|  |  terminate: | ||||||
							
								
								
									
										34
									
								
								SOURCES/0899-test-Add-a-test-case-for-15654.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								SOURCES/0899-test-Add-a-test-case-for-15654.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | From e019afeefb396ea42d03f4c3f9713e262aff6450 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Benjamin Robin <dev@benjarobin.fr> | ||||||
|  | Date: Wed, 6 May 2020 23:28:02 +0200 | ||||||
|  | Subject: [PATCH] test: Add a test case for #15654 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit c11d8fd1dab3bc3f0abbc861ba5eb34518cec1da) | ||||||
|  | 
 | ||||||
|  | Related: #2029426 | ||||||
|  | ---
 | ||||||
|  |  test/TEST-04-JOURNAL/test-journal.sh | 11 +++++++++++ | ||||||
|  |  1 file changed, 11 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh
 | ||||||
|  | index a3db1a7472..bdf137cd69 100755
 | ||||||
|  | --- a/test/TEST-04-JOURNAL/test-journal.sh
 | ||||||
|  | +++ b/test/TEST-04-JOURNAL/test-journal.sh
 | ||||||
|  | @@ -76,6 +76,17 @@ journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output
 | ||||||
|  |  grep -q "^_PID=$PID" /output | ||||||
|  |  grep -vq "^_PID=$PID" /output | ||||||
|  |   | ||||||
|  | +# https://github.com/systemd/systemd/issues/15654
 | ||||||
|  | +ID=$(journalctl --new-id128 | sed -n 2p)
 | ||||||
|  | +printf "This will\nusually fail\nand be truncated\n">/expected
 | ||||||
|  | +systemd-cat -t "$ID" /bin/sh -c 'env echo -n "This will";echo;env echo -n "usually fail";echo;env echo -n "and be truncated";echo;'
 | ||||||
|  | +journalctl --sync
 | ||||||
|  | +journalctl -b -o cat -t "$ID" >/output
 | ||||||
|  | +cmp /expected /output
 | ||||||
|  | +
 | ||||||
|  | +# Add new tests before here, the journald restarts below
 | ||||||
|  | +# may make tests flappy.
 | ||||||
|  | +
 | ||||||
|  |  # Don't lose streams on restart | ||||||
|  |  systemctl start forever-print-hola | ||||||
|  |  sleep 3 | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | From afcfb65ce7514bf32e59e0b9d212ae18d023a4b5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Benjamin Robin <dev@benjarobin.fr> | ||||||
|  | Date: Sat, 9 May 2020 12:01:07 +0200 | ||||||
|  | Subject: [PATCH] test: Stricter test case for #15654 (Add more checks) | ||||||
|  | 
 | ||||||
|  | Check: | ||||||
|  |  - There is only 3 messages logged with type stdout | ||||||
|  |  - Check all messages logged does not have new line: LINE_BREAK=eof | ||||||
|  |  - Check that the 3 messages are logged from a different PID | ||||||
|  |  - Check the 3 MESSAGE= content | ||||||
|  | (cherry picked from commit d38b3b74dbde2d65b23e5963354c3db96acd3420) | ||||||
|  | 
 | ||||||
|  | Related: #2029426 | ||||||
|  | ---
 | ||||||
|  |  test/TEST-04-JOURNAL/test-journal.sh | 4 ++++ | ||||||
|  |  1 file changed, 4 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh
 | ||||||
|  | index bdf137cd69..641259ce24 100755
 | ||||||
|  | --- a/test/TEST-04-JOURNAL/test-journal.sh
 | ||||||
|  | +++ b/test/TEST-04-JOURNAL/test-journal.sh
 | ||||||
|  | @@ -83,6 +83,10 @@ systemd-cat -t "$ID" /bin/sh -c 'env echo -n "This will";echo;env echo -n "usual
 | ||||||
|  |  journalctl --sync | ||||||
|  |  journalctl -b -o cat -t "$ID" >/output | ||||||
|  |  cmp /expected /output | ||||||
|  | +[[ $(journalctl -b -o export -t "$ID" --output-fields=_TRANSPORT | grep -Pc "^_TRANSPORT=stdout$") -eq 3 ]]
 | ||||||
|  | +[[ $(journalctl -b -o export -t "$ID" --output-fields=_LINE_BREAK | grep -Pc "^_LINE_BREAK=pid-change$") -eq 3 ]]
 | ||||||
|  | +[[ $(journalctl -b -o export -t "$ID" --output-fields=_PID | sort -u | grep -c "^_PID=.*$") -eq 3 ]]
 | ||||||
|  | +[[ $(journalctl -b -o export -t "$ID" --output-fields=MESSAGE | grep -Pc "^MESSAGE=(This will|usually fail|and be truncated)$") -eq 3 ]]
 | ||||||
|  |   | ||||||
|  |  # Add new tests before here, the journald restarts below | ||||||
|  |  # may make tests flappy. | ||||||
							
								
								
									
										42
									
								
								SOURCES/0901-man-document-the-new-_LINE_BREAK-type.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								SOURCES/0901-man-document-the-new-_LINE_BREAK-type.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | From 2f55aeadef3dcdf65c61f24a41178148c3544ac3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lennart Poettering <lennart@poettering.net> | ||||||
|  | Date: Wed, 13 May 2020 00:09:43 +0200 | ||||||
|  | Subject: [PATCH] man: document the new _LINE_BREAK= type | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit a3d9aee14fa2f7df429dc401582877176206b7fd) | ||||||
|  | 
 | ||||||
|  | Related: #2029426 | ||||||
|  | ---
 | ||||||
|  |  man/systemd.journal-fields.xml | 19 ++++++++++--------- | ||||||
|  |  1 file changed, 10 insertions(+), 9 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml
 | ||||||
|  | index 0c95c4cd95..ad2b94dbd5 100644
 | ||||||
|  | --- a/man/systemd.journal-fields.xml
 | ||||||
|  | +++ b/man/systemd.journal-fields.xml
 | ||||||
|  | @@ -326,15 +326,16 @@
 | ||||||
|  |        <varlistentry> | ||||||
|  |          <term><varname>_LINE_BREAK=</varname></term> | ||||||
|  |          <listitem> | ||||||
|  | -          <para>Only applies to <literal>_TRANSPORT=stdout</literal> records: indicates that the log message in the
 | ||||||
|  | -          standard output/error stream was not terminated with a normal newline character (<literal>\n</literal>,
 | ||||||
|  | -          i.e. ASCII 10). Specifically, when set this field is one of <option>nul</option> (in case the line was
 | ||||||
|  | -          terminated by a NUL byte), <option>line-max</option> (in case the maximum log line length was reached, as
 | ||||||
|  | -          configured with <varname>LineMax=</varname> in
 | ||||||
|  | -          <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>) or
 | ||||||
|  | -          <option>eof</option> (if this was the last log record of a stream and the stream ended without a final
 | ||||||
|  | -          newline character). Note that this record is not generated when a normal newline character was used for
 | ||||||
|  | -          marking the log line end.</para>
 | ||||||
|  | +          <para>Only applies to <literal>_TRANSPORT=stdout</literal> records: indicates that the log message
 | ||||||
|  | +          in the standard output/error stream was not terminated with a normal newline character
 | ||||||
|  | +          (<literal>\n</literal>, i.e. ASCII 10). Specifically, when set this field is one of
 | ||||||
|  | +          <option>nul</option> (in case the line was terminated by a NUL byte), <option>line-max</option> (in
 | ||||||
|  | +          case the maximum log line length was reached, as configured with <varname>LineMax=</varname> in
 | ||||||
|  | +          <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
 | ||||||
|  | +          <option>eof</option> (if this was the last log record of a stream and the stream ended without a
 | ||||||
|  | +          final newline character), or <option>pid-change</option> (if the process which generated the log
 | ||||||
|  | +          output changed in the middle of a line). Note that this record is not generated when a normal
 | ||||||
|  | +          newline character was used for marking the log line end.</para>
 | ||||||
|  |          </listitem> | ||||||
|  |        </varlistentry> | ||||||
|  |      </variablelist> | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | From 47cc8f7e1d153e576f146d309b4043739997a673 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Tardon <dtardon@redhat.com> | ||||||
|  | Date: Mon, 13 Mar 2023 14:22:28 +0100 | ||||||
|  | Subject: [PATCH] journald-server: always create state file in signal handler | ||||||
|  | 
 | ||||||
|  | `journalctl --flush` waits on that file, so we must create if even if | ||||||
|  | nothing has really happened. | ||||||
|  | 
 | ||||||
|  | RHEL-only | ||||||
|  | 
 | ||||||
|  | Resolves: #2174645 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-server.c | 5 +++++ | ||||||
|  |  1 file changed, 5 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
 | ||||||
|  | index 279a32768c..c72cb68095 100644
 | ||||||
|  | --- a/src/journal/journald-server.c
 | ||||||
|  | +++ b/src/journal/journald-server.c
 | ||||||
|  | @@ -1188,6 +1188,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
 | ||||||
|  |   | ||||||
|  |  static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { | ||||||
|  |          Server *s = userdata; | ||||||
|  | +        int r;
 | ||||||
|  |   | ||||||
|  |          assert(s); | ||||||
|  |   | ||||||
|  | @@ -1197,6 +1198,10 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *
 | ||||||
|  |          server_sync(s); | ||||||
|  |          server_vacuum(s, false); | ||||||
|  |   | ||||||
|  | +        r = touch("/run/systemd/journal/flushed");
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
 | ||||||
|  | +
 | ||||||
|  |          server_space_usage_message(s, NULL); | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
| @ -0,0 +1,62 @@ | |||||||
|  | From 7a7b0c4ec7a5595a44d9c70d8270b0724a8b8c45 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Tardon <dtardon@redhat.com> | ||||||
|  | Date: Mon, 13 Mar 2023 14:31:38 +0100 | ||||||
|  | Subject: [PATCH] journald-server: move relinquish code into function | ||||||
|  | 
 | ||||||
|  | No functional change, just refactoring. | ||||||
|  | 
 | ||||||
|  | RHEL-only | ||||||
|  | 
 | ||||||
|  | Related: #2174645 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-server.c | 23 ++++++++++++++++------- | ||||||
|  |  1 file changed, 16 insertions(+), 7 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
 | ||||||
|  | index c72cb68095..aa70db95cc 100644
 | ||||||
|  | --- a/src/journal/journald-server.c
 | ||||||
|  | +++ b/src/journal/journald-server.c
 | ||||||
|  | @@ -1258,20 +1258,16 @@ static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo
 | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  | -static int dispatch_sigrtmin2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
 | ||||||
|  | -        Server *s = userdata;
 | ||||||
|  | +static void relinquish_var(Server *s) {
 | ||||||
|  |          int r; | ||||||
|  |   | ||||||
|  |          assert(s); | ||||||
|  |   | ||||||
|  |          if (s->storage == STORAGE_NONE) | ||||||
|  | -                return 0;
 | ||||||
|  | +                return;
 | ||||||
|  |   | ||||||
|  |          if (s->runtime_journal && !s->system_journal) | ||||||
|  | -                return 0;
 | ||||||
|  | -
 | ||||||
|  | -        log_debug("Received request to relinquish /var from PID " PID_FMT, si->ssi_pid);
 | ||||||
|  | +                return;
 | ||||||
|  |   | ||||||
|  |          (void) system_journal_open(s, false, true); | ||||||
|  |   | ||||||
|  | @@ -1286,6 +1282,19 @@ static int dispatch_sigrtmin2(sd_event_source *es, const struct signalfd_siginfo
 | ||||||
|  |          if (r < 0) | ||||||
|  |                  log_warning_errno(r, "Failed to write /run/systemd/journal/relinquished, ignoring: %m"); | ||||||
|  |   | ||||||
|  | +        return;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int dispatch_sigrtmin2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
 | ||||||
|  | +        Server *s = userdata;
 | ||||||
|  | +
 | ||||||
|  | +        assert(s);
 | ||||||
|  | +        assert(si);
 | ||||||
|  | +
 | ||||||
|  | +        log_debug("Received request to relinquish /var from PID " PID_FMT, si->ssi_pid);
 | ||||||
|  | +
 | ||||||
|  | +        relinquish_var(s);
 | ||||||
|  | +
 | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
| @ -0,0 +1,58 @@ | |||||||
|  | From 980add7d84084a474c6c604c0670743c2d1e624c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Tardon <dtardon@redhat.com> | ||||||
|  | Date: Mon, 13 Mar 2023 14:32:20 +0100 | ||||||
|  | Subject: [PATCH] journald-server: always touch state file in signal handler | ||||||
|  | 
 | ||||||
|  | `journalctl --relinquish-var` waits on that file, so we must create if | ||||||
|  | even if nothing has really happened. | ||||||
|  | 
 | ||||||
|  | RHEL-only | ||||||
|  | 
 | ||||||
|  | Related: #2174645 | ||||||
|  | ---
 | ||||||
|  |  src/journal/journald-server.c | 12 +++++++----- | ||||||
|  |  1 file changed, 7 insertions(+), 5 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
 | ||||||
|  | index aa70db95cc..4788ff78bb 100644
 | ||||||
|  | --- a/src/journal/journald-server.c
 | ||||||
|  | +++ b/src/journal/journald-server.c
 | ||||||
|  | @@ -1259,8 +1259,6 @@ static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void relinquish_var(Server *s) { | ||||||
|  | -        int r;
 | ||||||
|  | -
 | ||||||
|  |          assert(s); | ||||||
|  |   | ||||||
|  |          if (s->storage == STORAGE_NONE) | ||||||
|  | @@ -1278,15 +1276,15 @@ static void relinquish_var(Server *s) {
 | ||||||
|  |          if (unlink("/run/systemd/journal/flushed") < 0 && errno != ENOENT) | ||||||
|  |                  log_warning_errno(errno, "Failed to unlink /run/systemd/journal/flushed, ignoring: %m")  ; | ||||||
|  |   | ||||||
|  | -        r = write_timestamp_file_atomic("/run/systemd/journal/relinquished", now(CLOCK_MONOTONIC));
 | ||||||
|  | -        if (r < 0)
 | ||||||
|  | -                log_warning_errno(r, "Failed to write /run/systemd/journal/relinquished, ignoring: %m");
 | ||||||
|  | +        /* NOTE: We don't create our own state file here, because dispatch_sigrtmin2() has to do it anyway.
 | ||||||
|  | +         * But if this function is ever called from another place, the creation must be done here too. */
 | ||||||
|  |   | ||||||
|  |          return; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int dispatch_sigrtmin2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { | ||||||
|  |          Server *s = userdata; | ||||||
|  | +        int r;
 | ||||||
|  |   | ||||||
|  |          assert(s); | ||||||
|  |          assert(si); | ||||||
|  | @@ -1295,6 +1293,10 @@ static int dispatch_sigrtmin2(sd_event_source *es, const struct signalfd_siginfo
 | ||||||
|  |   | ||||||
|  |          relinquish_var(s); | ||||||
|  |   | ||||||
|  | +        r = write_timestamp_file_atomic("/run/systemd/journal/relinquished", now(CLOCK_MONOTONIC));
 | ||||||
|  | +        if (r < 0)
 | ||||||
|  | +                log_warning_errno(r, "Failed to write /run/systemd/journal/relinquished, ignoring: %m");
 | ||||||
|  | +
 | ||||||
|  |          return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
| @ -8,4 +8,5 @@ account  include system-auth | |||||||
| session  required pam_selinux.so close | session  required pam_selinux.so close | ||||||
| session  required pam_selinux.so nottys open | session  required pam_selinux.so nottys open | ||||||
| session  required pam_loginuid.so | session  required pam_loginuid.so | ||||||
|  | session  required pam_namespace.so | ||||||
| session  include system-auth | session  include system-auth | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ | |||||||
| Name:           systemd | Name:           systemd | ||||||
| Url:            http://www.freedesktop.org/wiki/Software/systemd | Url:            http://www.freedesktop.org/wiki/Software/systemd | ||||||
| Version:        239 | Version:        239 | ||||||
| Release:        68%{?dist}.4 | Release:        74%{?dist} | ||||||
| # For a breakdown of the licensing, see README | # For a breakdown of the licensing, see README | ||||||
| License:        LGPLv2+ and MIT and GPLv2+ | License:        LGPLv2+ and MIT and GPLv2+ | ||||||
| Summary:        System and Service Manager | Summary:        System and Service Manager | ||||||
| @ -881,13 +881,79 @@ Patch0828: 0828-core-load-fragment-move-config_parse_sec_fix_0-to-sr.patch | |||||||
| Patch0829: 0829-sd-event-add-relative-timer-calls.patch | Patch0829: 0829-sd-event-add-relative-timer-calls.patch | ||||||
| Patch0830: 0830-logind-add-option-to-stop-idle-sessions-after-specif.patch | Patch0830: 0830-logind-add-option-to-stop-idle-sessions-after-specif.patch | ||||||
| Patch0831: 0831-logind-schedule-idle-check-full-interval-from-now-if.patch | Patch0831: 0831-logind-schedule-idle-check-full-interval-from-now-if.patch | ||||||
| Patch0832: 0832-time-util-fix-buffer-over-run.patch | Patch0832: 0832-ci-lint-add-shell-linter-Differential-ShellCheck.patch | ||||||
| Patch0833: 0833-core-move-reset_arguments-to-the-end-of-main-s-finis.patch | Patch0833: 0833-meson-do-not-compare-objects-of-different-types.patch | ||||||
| Patch0834: 0834-basic-recognize-pdfs-filesystem-as-a-network-filesys.patch | Patch0834: 0834-journal-remote-use-MHD_HTTP_CONTENT_TOO_LARGE-as-MHD.patch | ||||||
| Patch0835: 0835-core-bring-manager_startup-and-manager_reload-more-i.patch | Patch0835: 0835-Fix-build-with-httpd-0.9.71.patch | ||||||
| Patch0836: 0836-basic-add-STRERROR-wrapper-for-strerror_r.patch | Patch0836: 0836-ci-replace-LGTM-with-CodeQL.patch | ||||||
| Patch0837: 0837-coredump-put-context-array-into-a-struct.patch | Patch0837: 0837-ci-mergify-Update-policy-Drop-LGTM-checks.patch | ||||||
| Patch0838: 0838-coredump-do-not-allow-user-to-access-coredumps-with-.patch | Patch0838: 0838-time-util-fix-buffer-over-run.patch | ||||||
|  | Patch0839: 0839-basic-recognize-pdfs-filesystem-as-a-network-filesys.patch | ||||||
|  | Patch0840: 0840-core-move-reset_arguments-to-the-end-of-main-s-finis.patch | ||||||
|  | Patch0841: 0841-manager-move-inc.-of-n_reloading-into-a-function.patch | ||||||
|  | Patch0842: 0842-core-Add-new-DBUS-properties-UnitsReloadStartTimesta.patch | ||||||
|  | Patch0843: 0843-core-Indicate-the-time-when-the-manager-started-load.patch | ||||||
|  | Patch0844: 0844-core-do-not-touch-run-systemd-systemd-units-load-fro.patch | ||||||
|  | Patch0845: 0845-sysctl-downgrade-message-when-we-have-no-permission.patch | ||||||
|  | Patch0846: 0846-core-respect-SELinuxContext-for-socket-creation.patch | ||||||
|  | Patch0847: 0847-manager-use-target-process-context-to-set-socket-con.patch | ||||||
|  | Patch0848: 0848-virt-detect-Amazon-EC2-Nitro-instance.patch | ||||||
|  | Patch0849: 0849-machine-id-setup-generate-machine-id-from-DMI-produc.patch | ||||||
|  | Patch0850: 0850-virt-use-string-table-to-detect-VM-or-container.patch | ||||||
|  | Patch0851: 0851-fileio-introduce-read_full_virtual_file-for-reading-.patch | ||||||
|  | Patch0852: 0852-Use-BIOS-characteristics-to-distinguish-EC2-bare-met.patch | ||||||
|  | Patch0853: 0853-device-drop-refuse_after.patch | ||||||
|  | Patch0854: 0854-manager-limit-access-to-private-dbus-socket.patch | ||||||
|  | Patch0855: 0855-journalctl-do-not-treat-EINTR-as-an-error-when-waiti.patch | ||||||
|  | Patch0856: 0856-core-bring-manager_startup-and-manager_reload-more-i.patch | ||||||
|  | Patch0857: 0857-pam-add-a-call-to-pam_namespace.patch | ||||||
|  | Patch0858: 0858-virt-Support-detection-for-ARM64-Hyper-V-guests.patch | ||||||
|  | Patch0859: 0859-virt-Fix-the-detection-for-Hyper-V-VMs.patch | ||||||
|  | Patch0860: 0860-basic-add-STRERROR-wrapper-for-strerror_r.patch | ||||||
|  | Patch0861: 0861-coredump-put-context-array-into-a-struct.patch | ||||||
|  | Patch0862: 0862-coredump-do-not-allow-user-to-access-coredumps-with-.patch | ||||||
|  | Patch0863: 0863-logind-remember-our-idle-state-and-use-it-to-detect-.patch | ||||||
|  | Patch0864: 0864-test-import-logind-test-from-debian-ubuntu-test-suit.patch | ||||||
|  | Patch0865: 0865-test-introduce-inst_recursive-helper-function.patch | ||||||
|  | Patch0866: 0866-tests-verify-that-Lock-D-Bus-signal-is-sent-when-Idl.patch | ||||||
|  | Patch0867: 0867-systemctl-simplify-halt_main.patch | ||||||
|  | Patch0868: 0868-systemctl-shutdown-don-t-fallback-on-auth-fail.patch | ||||||
|  | Patch0869: 0869-systemctl-reintroduce-the-original-halt_main.patch | ||||||
|  | Patch0870: 0870-systemctl-preserve-old-behavior-unless-requested.patch | ||||||
|  | Patch0871: 0871-pam_systemd-suppress-LOG_DEBUG-log-messages-if-debug.patch | ||||||
|  | Patch0872: 0872-udev-net_id-introduce-naming-scheme-for-RHEL-8.8.patch | ||||||
|  | Patch0873: 0873-journald-add-API-to-move-logging-from-var-to-run-aga.patch | ||||||
|  | Patch0874: 0874-journalctl-add-new-relinquish-and-smart-relinquish-o.patch | ||||||
|  | Patch0875: 0875-units-automatically-revert-to-run-logging-on-shutdow.patch | ||||||
|  | Patch0876: 0876-pstore-Tool-to-archive-contents-of-pstore.patch | ||||||
|  | Patch0877: 0877-meson-drop-redundant-line.patch | ||||||
|  | Patch0878: 0878-pstore-drop-unnecessary-initializations.patch | ||||||
|  | Patch0879: 0879-pstopre-fix-return-value-of-list_files.patch | ||||||
|  | Patch0880: 0880-pstore-remove-temporary-file-on-failure.patch | ||||||
|  | Patch0881: 0881-pstore-do-not-add-FILE-journal-entry-if-content_size.patch | ||||||
|  | Patch0882: 0882-pstore-run-only-when-sys-fs-pstore-is-not-empty.patch | ||||||
|  | Patch0883: 0883-pstore-fix-use-after-free.patch | ||||||
|  | Patch0884: 0884-pstore-refuse-to-run-if-arguments-are-specified.patch | ||||||
|  | Patch0885: 0885-pstore-allow-specifying-src-and-dst-dirs-are-argumen.patch | ||||||
|  | Patch0886: 0886-pstore-rework-memory-handling-for-dmesg.patch | ||||||
|  | Patch0887: 0887-pstore-fixes-for-dmesg.txt-reconstruction.patch | ||||||
|  | Patch0888: 0888-pstore-Don-t-start-systemd-pstore.service-in-contain.patch | ||||||
|  | Patch0889: 0889-units-pull-in-systemd-pstore.service-from-sysinit.ta.patch | ||||||
|  | Patch0890: 0890-units-drop-dependency-on-systemd-remount-fs.service-.patch | ||||||
|  | Patch0891: 0891-units-make-sure-systemd-pstore-stops-at-shutdown.patch | ||||||
|  | Patch0892: 0892-pstore-Run-after-modules-are-loaded.patch | ||||||
|  | Patch0893: 0893-pstore-do-not-try-to-load-all-known-pstore-modules.patch | ||||||
|  | Patch0894: 0894-logind-session-make-stopping-of-idle-session-visible.patch | ||||||
|  | Patch0895: 0895-journald-Increase-stdout-buffer-size-sooner-when-alm.patch | ||||||
|  | Patch0896: 0896-journald-rework-end-of-line-marker-handling-to-use-a.patch | ||||||
|  | Patch0897: 0897-journald-use-the-fact-that-client_context_release-re.patch | ||||||
|  | Patch0898: 0898-journald-rework-pid-change-handling.patch | ||||||
|  | Patch0899: 0899-test-Add-a-test-case-for-15654.patch | ||||||
|  | Patch0900: 0900-test-Stricter-test-case-for-15654-Add-more-checks.patch | ||||||
|  | Patch0901: 0901-man-document-the-new-_LINE_BREAK-type.patch | ||||||
|  | Patch0902: 0902-journald-server-always-create-state-file-in-signal-h.patch | ||||||
|  | Patch0903: 0903-journald-server-move-relinquish-code-into-function.patch | ||||||
|  | Patch0904: 0904-journald-server-always-touch-state-file-in-signal-ha.patch | ||||||
| 
 | 
 | ||||||
| %ifarch %{ix86} x86_64 aarch64 | %ifarch %{ix86} x86_64 aarch64 | ||||||
| %global have_gnu_efi 1 | %global have_gnu_efi 1 | ||||||
| @ -1305,7 +1371,8 @@ python3 %{SOURCE2} %buildroot <<EOF | |||||||
| EOF | EOF | ||||||
| 
 | 
 | ||||||
| %check | %check | ||||||
| %meson_test | # Add --num-processes 1 as workaround for issues on ppc64le - AttributeError: 'NoneType' object has no attribute '_add_reader' - https://github.com/python/cpython/issues/82200 | ||||||
|  | %meson_test --num-processes 1 | ||||||
| 
 | 
 | ||||||
| ############################################################################################# | ############################################################################################# | ||||||
| 
 | 
 | ||||||
| @ -1517,28 +1584,96 @@ fi | |||||||
| %files tests -f .file-list-tests | %files tests -f .file-list-tests | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
| * Mon Jan 30 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-68.4 | * Tue Mar 14 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-74 | ||||||
| - basic: add STRERROR() wrapper for strerror_r() (#2155519) | - journald-server: always create state file in signal handler (#2174645) | ||||||
| - coredump: put context array into a struct (#2155519) | - journald-server: move relinquish code into function (#2174645) | ||||||
| - coredump: do not allow user to access coredumps with changed uid/gid/capabilities (#2155519) | - journald-server: always touch state file in signal handler (#2174645) | ||||||
| 
 | 
 | ||||||
| * Fri Jan 27 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-68.3 | * Mon Feb 27 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-73 | ||||||
| - core: bring manager_startup() and manager_reload() more inline (#2164049) | - journald: add API to move logging from /var to /run again (#1873540) | ||||||
|  | - journalctl: add new --relinquish and --smart-relinquish options (#1873540) | ||||||
|  | - units: automatically revert to /run logging on shutdown if necessary (#1873540) | ||||||
|  | - pstore: Tool to archive contents of pstore (#2158832) | ||||||
|  | - meson: drop redundant line (#2158832) | ||||||
|  | - pstore: drop unnecessary initializations (#2158832) | ||||||
|  | - pstopre: fix return value of list_files() (#2158832) | ||||||
|  | - pstore: remove temporary file on failure (#2158832) | ||||||
|  | - pstore: do not add FILE= journal entry if content_size == 0 (#2158832) | ||||||
|  | - pstore: run only when /sys/fs/pstore is not empty (#2158832) | ||||||
|  | - pstore: fix use after free (#2158832) | ||||||
|  | - pstore: refuse to run if arguments are specified (#2158832) | ||||||
|  | - pstore: allow specifying src and dst dirs are arguments (#2158832) | ||||||
|  | - pstore: rework memory handling for dmesg (#2158832) | ||||||
|  | - pstore: fixes for dmesg.txt reconstruction (#2158832) | ||||||
|  | - pstore: Don't start systemd-pstore.service in containers (#2158832) | ||||||
|  | - units: pull in systemd-pstore.service from sysinit.target (#2158832) | ||||||
|  | - units: drop dependency on systemd-remount-fs.service from systemd-pstore.service (#2158832) | ||||||
|  | - units: make sure systemd-pstore stops at shutdown (#2158832) | ||||||
|  | - pstore: Run after modules are loaded (#2158832) | ||||||
|  | - pstore: do not try to load all known pstore modules (#2158832) | ||||||
|  | - logind-session: make stopping of idle session visible to admins (#2156780) | ||||||
|  | - journald: Increase stdout buffer size sooner, when almost full (#2029426) | ||||||
|  | - journald: rework end of line marker handling to use a field table (#2029426) | ||||||
|  | - journald: use the fact that client_context_release() returns NULL (#2029426) | ||||||
|  | - journald: rework pid change handling (#2029426) | ||||||
|  | - test: Add a test case for #15654 (#2029426) | ||||||
|  | - test: Stricter test case for #15654 (Add more checks) (#2029426) | ||||||
|  | - man: document the new _LINE_BREAK= type (#2029426) | ||||||
| 
 | 
 | ||||||
| * Mon Nov 21 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-68.2 | * Fri Feb 17 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-72 | ||||||
| - basic: recognize pdfs filesystem as a network filesystem (#2143100) | - test: import logind test from debian/ubuntu test suite (#1866955) | ||||||
|  | - test: introduce inst_recursive() helper function (#1866955) | ||||||
|  | - tests: verify that Lock D-Bus signal is sent when IdleAction=lock (#1866955) | ||||||
|  | - systemctl: simplify halt_main() (#2053273) | ||||||
|  | - systemctl: shutdown don't fallback on auth fail (#2053273) | ||||||
|  | - systemctl: reintroduce the original halt_main() (#2053273) | ||||||
|  | - systemctl: preserve old behavior unless requested (#2053273) | ||||||
|  | - pam_systemd: suppress LOG_DEBUG log messages if debugging is off (#2170084) | ||||||
|  | - udev/net_id: introduce naming scheme for RHEL-8.8 (#2170499) | ||||||
|  | - pam: add a call to pam_namespace (#1861836) | ||||||
| 
 | 
 | ||||||
| * Mon Nov 07 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-68.1 | * Tue Jan 31 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-71 | ||||||
| - time-util: fix buffer-over-run (#2139390) | - manager: limit access to private dbus socket (#2119405) | ||||||
| - core: move reset_arguments() to the end of main's finish (#2127170) | - journalctl: do not treat EINTR as an error when waiting for events (#2161683) | ||||||
|  | - core: bring manager_startup() and manager_reload() more inline (#2059633) | ||||||
|  | - pam: add a call to pam_namespace (#1861836) | ||||||
|  | - virt: Support detection for ARM64 Hyper-V guests (#2158307) | ||||||
|  | - virt: Fix the detection for Hyper-V VMs (#2158307) | ||||||
|  | - basic: add STRERROR() wrapper for strerror_r() (#2155520) | ||||||
|  | - coredump: put context array into a struct (#2155520) | ||||||
|  | - coredump: do not allow user to access coredumps with changed uid/gid/capabilities (#2155520) | ||||||
| 
 | 
 | ||||||
| * Tue Sep 27 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-68 | * Mon Jan 16 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-70 | ||||||
|  | - basic: recognize pdfs filesystem as a network filesystem (#2094661) | ||||||
|  | - core: move reset_arguments() to the end of main's finish (#2127131) | ||||||
|  | - manager: move inc. of n_reloading into a function (#2136869) | ||||||
|  | - core: Add new DBUS properties UnitsReloadStartTimestamp and UnitsLoadTimestampMontonic (#2136869) | ||||||
|  | - core: Indicate the time when the manager started loading units the last time (#2136869) | ||||||
|  | - core: do not touch /run/systemd/systemd-units-load from user session instances (#2136869) | ||||||
|  | - sysctl: downgrade message when we have no permission (#2158160) | ||||||
|  | - core: respect SELinuxContext= for socket creation (#2136738) | ||||||
|  | - manager: use target process context to set socket context (#2136738) | ||||||
|  | - virt: detect Amazon EC2 Nitro instance (#2117948) | ||||||
|  | - machine-id-setup: generate machine-id from DMI product ID on Amazon EC2 (#2117948) | ||||||
|  | - virt: use string table to detect VM or container (#2117948) | ||||||
|  | - fileio: introduce read_full_virtual_file() for reading virtual files in sysfs, procfs (#2117948) | ||||||
|  | - Use BIOS characteristics to distinguish EC2 bare-metal from VMs (#2117948) | ||||||
|  | - device: drop refuse_after (#2043524) | ||||||
|  | 
 | ||||||
|  | * Tue Nov 08 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-69 | ||||||
| - logind: optionally watch utmp for login data (#2122288) | - logind: optionally watch utmp for login data (#2122288) | ||||||
| - logind: add hashtable for finding session by leader PID (#2122288) | - logind: add hashtable for finding session by leader PID (#2122288) | ||||||
| - core/load-fragment: move config_parse_sec_fix_0 to src/shared (#2122288) | - core/load-fragment: move config_parse_sec_fix_0 to src/shared (#2122288) | ||||||
| - sd-event: add relative timer calls (#2122288) | - sd-event: add relative timer calls (#2122288) | ||||||
| - logind: add option to stop idle sessions after specified timeout (#2122288) | - logind: add option to stop idle sessions after specified timeout (#2122288) | ||||||
| - logind: schedule idle check full interval from now if we couldn't figure out atime timestamp (#2122288) | - logind: schedule idle check full interval from now if we couldn't figure out atime timestamp (#2122288) | ||||||
|  | - ci(lint): add shell linter - Differential ShellCheck (#2122499) | ||||||
|  | - meson: do not compare objects of different types (#2122499) | ||||||
|  | - journal-remote: use MHD_HTTP_CONTENT_TOO_LARGE as MHD_HTTP_PAYLOAD_TOO_LARGE is deprecated since 0.9.74 (#2122499) | ||||||
|  | - Fix build with µhttpd 0.9.71 (#2122499) | ||||||
|  | - ci: replace LGTM with CodeQL (#2122499) | ||||||
|  | - ci(mergify): Update policy - Drop LGTM checks (#2122499) | ||||||
|  | - time-util: fix buffer-over-run (#2139391) | ||||||
| 
 | 
 | ||||||
| * Fri Aug 26 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-67 | * Fri Aug 26 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-67 | ||||||
| - resolved: pin stream while calling callbacks for it (#2110549) | - resolved: pin stream while calling callbacks for it (#2110549) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user