fix CVE-2022-4415
This commit is contained in:
parent
859f9b610a
commit
37cc3c3e20
@ -0,0 +1,102 @@
|
|||||||
|
From 2c5d05b3cd986568105d67891e4010b868dea24f Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||||
|
Date: Fri, 7 Oct 2022 12:28:31 +0200
|
||||||
|
Subject: [PATCH] basic: add STRERROR() wrapper for strerror_r()
|
||||||
|
|
||||||
|
Conflict:Modify the content in meson.build.
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/2c5d05b3cd986568105d67891e4010b868dea24f
|
||||||
|
|
||||||
|
---
|
||||||
|
src/basic/errno-util.h | 10 +++++++++
|
||||||
|
src/test/meson.build | 2 ++
|
||||||
|
src/test/test-errno-util.c | 44 ++++++++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 56 insertions(+)
|
||||||
|
create mode 100644 src/test/test-errno-util.c
|
||||||
|
|
||||||
|
diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h
|
||||||
|
index a71864ca60..f0d24d95cb 100644
|
||||||
|
--- a/src/basic/errno-util.h
|
||||||
|
+++ b/src/basic/errno-util.h
|
||||||
|
@@ -6,6 +6,16 @@
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
|
||||||
|
+/* strerror(3) says that glibc uses a maximum length of 1024 bytes. */
|
||||||
|
+#define ERRNO_BUF_LEN 1024
|
||||||
|
+
|
||||||
|
+/* Note: the lifetime of the compound literal is the immediately surrounding block,
|
||||||
|
+ * see C11 §6.5.2.5, and
|
||||||
|
+ * https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks
|
||||||
|
+ *
|
||||||
|
+ * Note that we use the GNU variant of strerror_r() here. */
|
||||||
|
+#define STRERROR(errnum) strerror_r(abs(errnum), (char[ERRNO_BUF_LEN]){}, ERRNO_BUF_LEN)
|
||||||
|
+
|
||||||
|
static inline void _reset_errno_(int *saved_errno) {
|
||||||
|
if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */
|
||||||
|
return;
|
||||||
|
diff --git a/src/test/meson.build b/src/test/meson.build
|
||||||
|
index 31ac149b96..86fc1d4fc0 100644
|
||||||
|
--- a/src/test/meson.build
|
||||||
|
+++ b/src/test/meson.build
|
||||||
|
@@ -615,6 +615,8 @@ tests += [
|
||||||
|
[['src/test/test-arphrd-list.c',
|
||||||
|
generated_gperf_headers]],
|
||||||
|
|
||||||
|
+ [['src/test/test-errno-util.c']],
|
||||||
|
+
|
||||||
|
[['src/test/test-ip-protocol-list.c',
|
||||||
|
shared_generated_gperf_headers]],
|
||||||
|
|
||||||
|
diff --git a/src/test/test-errno-util.c b/src/test/test-errno-util.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..284f451002
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/test/test-errno-util.c
|
||||||
|
@@ -0,0 +1,44 @@
|
||||||
|
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
+
|
||||||
|
+#include "errno-util.h"
|
||||||
|
+#include "stdio-util.h"
|
||||||
|
+#include "string-util.h"
|
||||||
|
+#include "tests.h"
|
||||||
|
+
|
||||||
|
+TEST(strerror_not_threadsafe) {
|
||||||
|
+ /* Just check that strerror really is not thread-safe. */
|
||||||
|
+ log_info("strerror(%d) → %s", 200, strerror(200));
|
||||||
|
+ log_info("strerror(%d) → %s", 201, strerror(201));
|
||||||
|
+ log_info("strerror(%d) → %s", INT_MAX, strerror(INT_MAX));
|
||||||
|
+
|
||||||
|
+ log_info("strerror(%d), strerror(%d) → %p, %p", 200, 201, strerror(200), strerror(201));
|
||||||
|
+
|
||||||
|
+ /* This call is not allowed, because the first returned string becomes invalid when
|
||||||
|
+ * we call strerror the second time:
|
||||||
|
+ *
|
||||||
|
+ * log_info("strerror(%d), strerror(%d) → %s, %s", 200, 201, strerror(200), strerror(201));
|
||||||
|
+ */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+TEST(STRERROR) {
|
||||||
|
+ /* Just check that STRERROR really is thread-safe. */
|
||||||
|
+ log_info("STRERROR(%d) → %s", 200, STRERROR(200));
|
||||||
|
+ log_info("STRERROR(%d) → %s", 201, STRERROR(201));
|
||||||
|
+ log_info("STRERROR(%d), STRERROR(%d) → %s, %s", 200, 201, STRERROR(200), STRERROR(201));
|
||||||
|
+
|
||||||
|
+ const char *a = STRERROR(200), *b = STRERROR(201);
|
||||||
|
+ assert_se(strstr(a, "200"));
|
||||||
|
+ assert_se(strstr(b, "201"));
|
||||||
|
+
|
||||||
|
+ /* Check with negative values */
|
||||||
|
+ assert_se(streq(a, STRERROR(-200)));
|
||||||
|
+ assert_se(streq(b, STRERROR(-201)));
|
||||||
|
+
|
||||||
|
+ const char *c = STRERROR(INT_MAX);
|
||||||
|
+ char buf[DECIMAL_STR_MAX(int)];
|
||||||
|
+ xsprintf(buf, "%d", INT_MAX); /* INT_MAX is hexadecimal, use printf to convert to decimal */
|
||||||
|
+ log_info("STRERROR(%d) → %s", INT_MAX, c);
|
||||||
|
+ assert_se(strstr(c, buf));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_TEST_MAIN(LOG_INFO);
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
83
backport-CVE-2022-4415-coredump-adjust-whitespace.patch
Normal file
83
backport-CVE-2022-4415-coredump-adjust-whitespace.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
From 510a146634f3e095b34e2a26023b1b1f99dcb8c0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||||
|
Date: Tue, 29 Nov 2022 09:00:16 +0100
|
||||||
|
Subject: [PATCH] coredump: adjust whitespace
|
||||||
|
|
||||||
|
Conflict:Delete the modification of parse_config.
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/510a146634f3e095b34e2a26023b1b1f99dcb8c0
|
||||||
|
|
||||||
|
---
|
||||||
|
src/coredump/coredump.c | 56 ++++++++++++++++++++---------------------
|
||||||
|
1 file changed, 28 insertions(+), 28 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||||
|
index 50220c5ec7..9ce2b92ded 100644
|
||||||
|
--- a/src/coredump/coredump.c
|
||||||
|
+++ b/src/coredump/coredump.c
|
||||||
|
@@ -111,16 +111,16 @@ enum {
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const meta_field_names[_META_MAX] = {
|
||||||
|
- [META_ARGV_PID] = "COREDUMP_PID=",
|
||||||
|
- [META_ARGV_UID] = "COREDUMP_UID=",
|
||||||
|
- [META_ARGV_GID] = "COREDUMP_GID=",
|
||||||
|
- [META_ARGV_SIGNAL] = "COREDUMP_SIGNAL=",
|
||||||
|
- [META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
|
||||||
|
- [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
|
||||||
|
- [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
|
||||||
|
- [META_COMM] = "COREDUMP_COMM=",
|
||||||
|
- [META_EXE] = "COREDUMP_EXE=",
|
||||||
|
- [META_UNIT] = "COREDUMP_UNIT=",
|
||||||
|
+ [META_ARGV_PID] = "COREDUMP_PID=",
|
||||||
|
+ [META_ARGV_UID] = "COREDUMP_UID=",
|
||||||
|
+ [META_ARGV_GID] = "COREDUMP_GID=",
|
||||||
|
+ [META_ARGV_SIGNAL] = "COREDUMP_SIGNAL=",
|
||||||
|
+ [META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
|
||||||
|
+ [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
|
||||||
|
+ [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
|
||||||
|
+ [META_COMM] = "COREDUMP_COMM=",
|
||||||
|
+ [META_EXE] = "COREDUMP_EXE=",
|
||||||
|
+ [META_UNIT] = "COREDUMP_UNIT=",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Context {
|
||||||
|
@@ -139,9 +139,9 @@ typedef enum CoredumpStorage {
|
||||||
|
} CoredumpStorage;
|
||||||
|
|
||||||
|
static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
|
||||||
|
- [COREDUMP_STORAGE_NONE] = "none",
|
||||||
|
+ [COREDUMP_STORAGE_NONE] = "none",
|
||||||
|
[COREDUMP_STORAGE_EXTERNAL] = "external",
|
||||||
|
- [COREDUMP_STORAGE_JOURNAL] = "journal",
|
||||||
|
+ [COREDUMP_STORAGE_JOURNAL] = "journal",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage);
|
||||||
|
@@ -209,15 +209,15 @@ static int fix_acl(int fd, uid_t uid) {
|
||||||
|
static int fix_xattr(int fd, const Context *context) {
|
||||||
|
|
||||||
|
static const char * const xattrs[_META_MAX] = {
|
||||||
|
- [META_ARGV_PID] = "user.coredump.pid",
|
||||||
|
- [META_ARGV_UID] = "user.coredump.uid",
|
||||||
|
- [META_ARGV_GID] = "user.coredump.gid",
|
||||||
|
- [META_ARGV_SIGNAL] = "user.coredump.signal",
|
||||||
|
- [META_ARGV_TIMESTAMP] = "user.coredump.timestamp",
|
||||||
|
- [META_ARGV_RLIMIT] = "user.coredump.rlimit",
|
||||||
|
- [META_ARGV_HOSTNAME] = "user.coredump.hostname",
|
||||||
|
- [META_COMM] = "user.coredump.comm",
|
||||||
|
- [META_EXE] = "user.coredump.exe",
|
||||||
|
+ [META_ARGV_PID] = "user.coredump.pid",
|
||||||
|
+ [META_ARGV_UID] = "user.coredump.uid",
|
||||||
|
+ [META_ARGV_GID] = "user.coredump.gid",
|
||||||
|
+ [META_ARGV_SIGNAL] = "user.coredump.signal",
|
||||||
|
+ [META_ARGV_TIMESTAMP] = "user.coredump.timestamp",
|
||||||
|
+ [META_ARGV_RLIMIT] = "user.coredump.rlimit",
|
||||||
|
+ [META_ARGV_HOSTNAME] = "user.coredump.hostname",
|
||||||
|
+ [META_COMM] = "user.coredump.comm",
|
||||||
|
+ [META_EXE] = "user.coredump.exe",
|
||||||
|
};
|
||||||
|
|
||||||
|
int r = 0;
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,386 @@
|
|||||||
|
From 3e4d0f6cf99f8677edd6a237382a65bfe758de03 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||||
|
Date: Mon, 28 Nov 2022 12:12:55 +0100
|
||||||
|
Subject: [PATCH] coredump: do not allow user to access coredumps with changed
|
||||||
|
uid/gid/capabilities
|
||||||
|
|
||||||
|
When the user starts a program which elevates its permissions via setuid,
|
||||||
|
setgid, or capabilities set on the file, it may access additional information
|
||||||
|
which would then be visible in the coredump. We shouldn't make the the coredump
|
||||||
|
visible to the user in such cases.
|
||||||
|
|
||||||
|
Reported-by: Matthias Gerstner <mgerstner@suse.de>
|
||||||
|
|
||||||
|
This reads the /proc/<pid>/auxv file and attaches it to the process metadata as
|
||||||
|
PROC_AUXV. Before the coredump is submitted, it is parsed and if either
|
||||||
|
at_secure was set (which the kernel will do for processes that are setuid,
|
||||||
|
setgid, or setcap), or if the effective uid/gid don't match uid/gid, the file
|
||||||
|
is not made accessible to the user. If we can't access this data, we assume the
|
||||||
|
file should not be made accessible either. In principle we could also access
|
||||||
|
the auxv data from a note in the core file, but that is much more complex and
|
||||||
|
it seems better to use the stand-alone file that is provided by the kernel.
|
||||||
|
|
||||||
|
Attaching auxv is both convient for this patch (because this way it's passed
|
||||||
|
between the stages along with other fields), but I think it makes sense to save
|
||||||
|
it in general.
|
||||||
|
|
||||||
|
We use the information early in the core file to figure out if the program was
|
||||||
|
32-bit or 64-bit and its endianness. This way we don't need heuristics to guess
|
||||||
|
whether the format of the auxv structure. This test might reject some cases on
|
||||||
|
fringe architecutes. But the impact would be limited: we just won't grant the
|
||||||
|
user permissions to view the coredump file. If people report that we're missing
|
||||||
|
some cases, we can always enhance this to support more architectures.
|
||||||
|
|
||||||
|
I tested auxv parsing on amd64, 32-bit program on amd64, arm64, arm32, and
|
||||||
|
ppc64el, but not the whole coredump handling.
|
||||||
|
|
||||||
|
Conflict:Change 'r = fsync_full(fd);' to 'if (fsync(fd) < 0)'.
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/3e4d0f6cf99f8677edd6a237382a65bfe758de03
|
||||||
|
|
||||||
|
---
|
||||||
|
src/basic/io-util.h | 9 ++
|
||||||
|
src/coredump/coredump.c | 196 +++++++++++++++++++++++++++++++++++++---
|
||||||
|
2 files changed, 192 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
|
||||||
|
index 39728e06bc..3afb134266 100644
|
||||||
|
--- a/src/basic/io-util.h
|
||||||
|
+++ b/src/basic/io-util.h
|
||||||
|
@@ -91,7 +91,16 @@ struct iovec_wrapper *iovw_new(void);
|
||||||
|
struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw);
|
||||||
|
struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw);
|
||||||
|
void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors);
|
||||||
|
+
|
||||||
|
int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len);
|
||||||
|
+static inline int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) {
|
||||||
|
+ /* Move data into iovw or free on error */
|
||||||
|
+ int r = iovw_put(iovw, data, len);
|
||||||
|
+ if (r < 0)
|
||||||
|
+ free(data);
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value);
|
||||||
|
int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value);
|
||||||
|
void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new);
|
||||||
|
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||||
|
index 9ce2b92ded..b6f3a2f256 100644
|
||||||
|
--- a/src/coredump/coredump.c
|
||||||
|
+++ b/src/coredump/coredump.c
|
||||||
|
@@ -4,6 +4,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
+#include <sys/auxv.h>
|
||||||
|
#include <sys/xattr.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@@ -107,6 +108,7 @@ enum {
|
||||||
|
|
||||||
|
META_EXE = _META_MANDATORY_MAX,
|
||||||
|
META_UNIT,
|
||||||
|
+ META_PROC_AUXV,
|
||||||
|
_META_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -121,10 +123,12 @@ static const char * const meta_field_names[_META_MAX] = {
|
||||||
|
[META_COMM] = "COREDUMP_COMM=",
|
||||||
|
[META_EXE] = "COREDUMP_EXE=",
|
||||||
|
[META_UNIT] = "COREDUMP_UNIT=",
|
||||||
|
+ [META_PROC_AUXV] = "COREDUMP_PROC_AUXV=",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Context {
|
||||||
|
const char *meta[_META_MAX];
|
||||||
|
+ size_t meta_size[_META_MAX];
|
||||||
|
pid_t pid;
|
||||||
|
bool is_pid1;
|
||||||
|
bool is_journald;
|
||||||
|
@@ -186,13 +190,16 @@ static uint64_t storage_size_max(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fix_acl(int fd, uid_t uid) {
|
||||||
|
+static int fix_acl(int fd, uid_t uid, bool allow_user) {
|
||||||
|
+ assert(fd >= 0);
|
||||||
|
+ assert(uid_is_valid(uid));
|
||||||
|
|
||||||
|
#if HAVE_ACL
|
||||||
|
int r;
|
||||||
|
|
||||||
|
- assert(fd >= 0);
|
||||||
|
- assert(uid_is_valid(uid));
|
||||||
|
+ /* We don't allow users to read coredumps if the uid or capabilities were changed. */
|
||||||
|
+ if (!allow_user)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
|
||||||
|
return 0;
|
||||||
|
@@ -252,7 +259,8 @@ static int fix_permissions(
|
||||||
|
const char *filename,
|
||||||
|
const char *target,
|
||||||
|
const Context *context,
|
||||||
|
- uid_t uid) {
|
||||||
|
+ uid_t uid,
|
||||||
|
+ bool allow_user) {
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
@@ -262,7 +270,7 @@ static int fix_permissions(
|
||||||
|
|
||||||
|
/* Ignore errors on these */
|
||||||
|
(void) fchmod(fd, 0640);
|
||||||
|
- (void) fix_acl(fd, uid);
|
||||||
|
+ (void) fix_acl(fd, uid, allow_user);
|
||||||
|
(void) fix_xattr(fd, context);
|
||||||
|
|
||||||
|
if (fsync(fd) < 0)
|
||||||
|
@@ -332,6 +340,153 @@ static int make_filename(const Context *context, char **ret) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int parse_auxv64(
|
||||||
|
+ const uint64_t *auxv,
|
||||||
|
+ size_t size_bytes,
|
||||||
|
+ int *at_secure,
|
||||||
|
+ uid_t *uid,
|
||||||
|
+ uid_t *euid,
|
||||||
|
+ gid_t *gid,
|
||||||
|
+ gid_t *egid) {
|
||||||
|
+
|
||||||
|
+ assert(auxv || size_bytes == 0);
|
||||||
|
+
|
||||||
|
+ if (size_bytes % (2 * sizeof(uint64_t)) != 0)
|
||||||
|
+ return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
|
||||||
|
+
|
||||||
|
+ size_t words = size_bytes / sizeof(uint64_t);
|
||||||
|
+
|
||||||
|
+ /* Note that we set output variables even on error. */
|
||||||
|
+
|
||||||
|
+ for (size_t i = 0; i + 1 < words; i += 2)
|
||||||
|
+ switch (auxv[i]) {
|
||||||
|
+ case AT_SECURE:
|
||||||
|
+ *at_secure = auxv[i + 1] != 0;
|
||||||
|
+ break;
|
||||||
|
+ case AT_UID:
|
||||||
|
+ *uid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_EUID:
|
||||||
|
+ *euid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_GID:
|
||||||
|
+ *gid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_EGID:
|
||||||
|
+ *egid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_NULL:
|
||||||
|
+ if (auxv[i + 1] != 0)
|
||||||
|
+ goto error;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ error:
|
||||||
|
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
|
||||||
|
+ "AT_NULL terminator not found, cannot parse auxv structure.");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int parse_auxv32(
|
||||||
|
+ const uint32_t *auxv,
|
||||||
|
+ size_t size_bytes,
|
||||||
|
+ int *at_secure,
|
||||||
|
+ uid_t *uid,
|
||||||
|
+ uid_t *euid,
|
||||||
|
+ gid_t *gid,
|
||||||
|
+ gid_t *egid) {
|
||||||
|
+
|
||||||
|
+ assert(auxv || size_bytes == 0);
|
||||||
|
+
|
||||||
|
+ size_t words = size_bytes / sizeof(uint32_t);
|
||||||
|
+
|
||||||
|
+ if (size_bytes % (2 * sizeof(uint32_t)) != 0)
|
||||||
|
+ return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
|
||||||
|
+
|
||||||
|
+ /* Note that we set output variables even on error. */
|
||||||
|
+
|
||||||
|
+ for (size_t i = 0; i + 1 < words; i += 2)
|
||||||
|
+ switch (auxv[i]) {
|
||||||
|
+ case AT_SECURE:
|
||||||
|
+ *at_secure = auxv[i + 1] != 0;
|
||||||
|
+ break;
|
||||||
|
+ case AT_UID:
|
||||||
|
+ *uid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_EUID:
|
||||||
|
+ *euid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_GID:
|
||||||
|
+ *gid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_EGID:
|
||||||
|
+ *egid = auxv[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ case AT_NULL:
|
||||||
|
+ if (auxv[i + 1] != 0)
|
||||||
|
+ goto error;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ error:
|
||||||
|
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
|
||||||
|
+ "AT_NULL terminator not found, cannot parse auxv structure.");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int grant_user_access(int core_fd, const Context *context) {
|
||||||
|
+ int at_secure = -1;
|
||||||
|
+ uid_t uid = UID_INVALID, euid = UID_INVALID;
|
||||||
|
+ uid_t gid = GID_INVALID, egid = GID_INVALID;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ assert(core_fd >= 0);
|
||||||
|
+ assert(context);
|
||||||
|
+
|
||||||
|
+ if (!context->meta[META_PROC_AUXV])
|
||||||
|
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), "No auxv data, not adjusting permissions.");
|
||||||
|
+
|
||||||
|
+ uint8_t elf[EI_NIDENT];
|
||||||
|
+ errno = 0;
|
||||||
|
+ if (pread(core_fd, &elf, sizeof(elf), 0) != sizeof(elf))
|
||||||
|
+ return log_warning_errno(errno_or_else(EIO),
|
||||||
|
+ "Failed to pread from coredump fd: %s", STRERROR_OR_EOF(errno));
|
||||||
|
+
|
||||||
|
+ if (elf[EI_MAG0] != ELFMAG0 ||
|
||||||
|
+ elf[EI_MAG1] != ELFMAG1 ||
|
||||||
|
+ elf[EI_MAG2] != ELFMAG2 ||
|
||||||
|
+ elf[EI_MAG3] != ELFMAG3 ||
|
||||||
|
+ elf[EI_VERSION] != EV_CURRENT)
|
||||||
|
+ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
|
||||||
|
+ "Core file does not have ELF header, not adjusting permissions.");
|
||||||
|
+ if (!IN_SET(elf[EI_CLASS], ELFCLASS32, ELFCLASS64) ||
|
||||||
|
+ !IN_SET(elf[EI_DATA], ELFDATA2LSB, ELFDATA2MSB))
|
||||||
|
+ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
|
||||||
|
+ "Core file has strange ELF class, not adjusting permissions.");
|
||||||
|
+
|
||||||
|
+ if ((elf[EI_DATA] == ELFDATA2LSB) != (__BYTE_ORDER == __LITTLE_ENDIAN))
|
||||||
|
+ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
|
||||||
|
+ "Core file has non-native endianness, not adjusting permissions.");
|
||||||
|
+
|
||||||
|
+ if (elf[EI_CLASS] == ELFCLASS64)
|
||||||
|
+ r = parse_auxv64((const uint64_t*) context->meta[META_PROC_AUXV],
|
||||||
|
+ context->meta_size[META_PROC_AUXV],
|
||||||
|
+ &at_secure, &uid, &euid, &gid, &egid);
|
||||||
|
+ else
|
||||||
|
+ r = parse_auxv32((const uint32_t*) context->meta[META_PROC_AUXV],
|
||||||
|
+ context->meta_size[META_PROC_AUXV],
|
||||||
|
+ &at_secure, &uid, &euid, &gid, &egid);
|
||||||
|
+ if (r < 0)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ /* We allow access if we got all the data and at_secure is not set and
|
||||||
|
+ * the uid/gid matches euid/egid. */
|
||||||
|
+ bool ret =
|
||||||
|
+ at_secure == 0 &&
|
||||||
|
+ uid != UID_INVALID && euid != UID_INVALID && uid == euid &&
|
||||||
|
+ gid != GID_INVALID && egid != GID_INVALID && gid == egid;
|
||||||
|
+ log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)",
|
||||||
|
+ ret ? "permit" : "restrict",
|
||||||
|
+ uid, euid, gid, egid, yes_no(at_secure));
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int save_external_coredump(
|
||||||
|
const Context *context,
|
||||||
|
int input_fd,
|
||||||
|
@@ -454,6 +609,8 @@ static int save_external_coredump(
|
||||||
|
context->meta[META_ARGV_PID], context->meta[META_COMM]);
|
||||||
|
truncated = r == 1;
|
||||||
|
|
||||||
|
+ bool allow_user = grant_user_access(fd, context) > 0;
|
||||||
|
+
|
||||||
|
#if HAVE_COMPRESSION
|
||||||
|
if (arg_compress) {
|
||||||
|
_cleanup_(unlink_and_freep) char *tmp_compressed = NULL;
|
||||||
|
@@ -491,7 +648,7 @@ static int save_external_coredump(
|
||||||
|
uncompressed_size += partial_uncompressed_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
- r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid);
|
||||||
|
+ r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid, allow_user);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
@@ -518,7 +675,7 @@ static int save_external_coredump(
|
||||||
|
"SIZE_LIMIT=%"PRIu64, max_size,
|
||||||
|
"MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR);
|
||||||
|
|
||||||
|
- r = fix_permissions(fd, tmp, fn, context, uid);
|
||||||
|
+ r = fix_permissions(fd, tmp, fn, context, uid, allow_user);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to fix permissions and finalize coredump %s into %s: %m", coredump_tmpfile_name(tmp), fn);
|
||||||
|
|
||||||
|
@@ -766,7 +923,7 @@ static int change_uid_gid(const Context *context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static int submit_coredump(
|
||||||
|
- Context *context,
|
||||||
|
+ const Context *context,
|
||||||
|
struct iovec_wrapper *iovw,
|
||||||
|
int input_fd) {
|
||||||
|
|
||||||
|
@@ -945,16 +1102,15 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||||
|
struct iovec *iovec = iovw->iovec + n;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ELEMENTSOF(meta_field_names); i++) {
|
||||||
|
- char *p;
|
||||||
|
-
|
||||||
|
/* Note that these strings are NUL terminated, because we made sure that a
|
||||||
|
* trailing NUL byte is in the buffer, though not included in the iov_len
|
||||||
|
* count (see process_socket() and gather_pid_metadata_*()) */
|
||||||
|
assert(((char*) iovec->iov_base)[iovec->iov_len] == 0);
|
||||||
|
|
||||||
|
- p = startswith(iovec->iov_base, meta_field_names[i]);
|
||||||
|
+ const char *p = startswith(iovec->iov_base, meta_field_names[i]);
|
||||||
|
if (p) {
|
||||||
|
context->meta[i] = p;
|
||||||
|
+ context->meta_size[i] = iovec->iov_len - strlen(meta_field_names[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1191,6 +1347,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
|
||||||
|
uid_t owner_uid;
|
||||||
|
pid_t pid;
|
||||||
|
char *t;
|
||||||
|
+ size_t size;
|
||||||
|
const char *p;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
@@ -1255,13 +1412,26 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
|
||||||
|
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_LIMITS=", t);
|
||||||
|
|
||||||
|
p = procfs_file_alloca(pid, "cgroup");
|
||||||
|
- if (read_full_virtual_file(p, &t, NULL) >=0)
|
||||||
|
+ if (read_full_virtual_file(p, &t, NULL) >= 0)
|
||||||
|
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_CGROUP=", t);
|
||||||
|
|
||||||
|
p = procfs_file_alloca(pid, "mountinfo");
|
||||||
|
- if (read_full_virtual_file(p, &t, NULL) >=0)
|
||||||
|
+ if (read_full_virtual_file(p, &t, NULL) >= 0)
|
||||||
|
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MOUNTINFO=", t);
|
||||||
|
|
||||||
|
+ /* We attach /proc/auxv here. ELF coredumps also contain a note for this (NT_AUXV), see elf(5). */
|
||||||
|
+ p = procfs_file_alloca(pid, "auxv");
|
||||||
|
+ if (read_full_virtual_file(p, &t, &size) >= 0) {
|
||||||
|
+ char *buf = malloc(strlen("COREDUMP_PROC_AUXV=") + size + 1);
|
||||||
|
+ if (buf) {
|
||||||
|
+ /* Add a dummy terminator to make save_context() happy. */
|
||||||
|
+ *((uint8_t*) mempcpy(stpcpy(buf, "COREDUMP_PROC_AUXV="), t, size)) = '\0';
|
||||||
|
+ (void) iovw_consume(iovw, buf, size + strlen("COREDUMP_PROC_AUXV="));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free(t);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (get_process_cwd(pid, &t) >= 0)
|
||||||
|
(void) iovw_put_string_field_free(iovw, "COREDUMP_CWD=", t);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
107
backport-CVE-2022-4415-test-Add-TEST_RET-macro.patch
Normal file
107
backport-CVE-2022-4415-test-Add-TEST_RET-macro.patch
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
From 4c0acc0761aae0370e20e118b9db3b704e9045cd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Janssen <medhefgo@web.de>
|
||||||
|
Date: Thu, 25 Nov 2021 10:27:51 +0100
|
||||||
|
Subject: [PATCH] test: Add TEST_RET macro
|
||||||
|
|
||||||
|
This declares a test function whose return code will be passed from
|
||||||
|
main(). The first test that does not return EXIT_SUCCESS wins.
|
||||||
|
|
||||||
|
Conflict:NA
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/4c0acc0761aae0370e20e118b9db3b704e9045cd
|
||||||
|
|
||||||
|
---
|
||||||
|
src/shared/tests.h | 54 ++++++++++++++++++++++++++++++++--------------
|
||||||
|
1 file changed, 38 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/shared/tests.h b/src/shared/tests.h
|
||||||
|
index 872b9b2d6c..d1c96ef35b 100644
|
||||||
|
--- a/src/shared/tests.h
|
||||||
|
+++ b/src/shared/tests.h
|
||||||
|
@@ -46,46 +46,68 @@ bool can_memlock(void);
|
||||||
|
const char *ci_environment(void);
|
||||||
|
|
||||||
|
typedef struct TestFunc {
|
||||||
|
- void (*f)(void);
|
||||||
|
- const char * const n;
|
||||||
|
+ union f {
|
||||||
|
+ void (*void_func)(void);
|
||||||
|
+ int (*int_func)(void);
|
||||||
|
+ } f;
|
||||||
|
+ const char * const name;
|
||||||
|
+ bool has_ret;
|
||||||
|
} TestFunc;
|
||||||
|
|
||||||
|
/* See static-destruct.h for an explanation of how this works. */
|
||||||
|
-#define REGISTER_TEST(func) \
|
||||||
|
- static void func(void); \
|
||||||
|
- _section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_ \
|
||||||
|
- static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = { \
|
||||||
|
- .f = &(func), \
|
||||||
|
- .n = STRINGIFY(func), \
|
||||||
|
+#define REGISTER_TEST(func) \
|
||||||
|
+ _section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_ \
|
||||||
|
+ static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = { \
|
||||||
|
+ .f = (union f) &(func), \
|
||||||
|
+ .name = STRINGIFY(func), \
|
||||||
|
+ .has_ret = __builtin_types_compatible_p(typeof((union f){}.int_func), typeof(&(func))), \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[];
|
||||||
|
extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[];
|
||||||
|
|
||||||
|
-#define TEST(name) \
|
||||||
|
- REGISTER_TEST(test_##name); \
|
||||||
|
+#define TEST(name) \
|
||||||
|
+ static void test_##name(void); \
|
||||||
|
+ REGISTER_TEST(test_##name); \
|
||||||
|
static void test_##name(void)
|
||||||
|
|
||||||
|
-static inline void run_test_table(void) {
|
||||||
|
+#define TEST_RET(name) \
|
||||||
|
+ static int test_##name(void); \
|
||||||
|
+ REGISTER_TEST(test_##name); \
|
||||||
|
+ static int test_##name(void)
|
||||||
|
+
|
||||||
|
+static inline int run_test_table(void) {
|
||||||
|
+ int r = EXIT_SUCCESS;
|
||||||
|
+
|
||||||
|
if (!__start_SYSTEMD_TEST_TABLE)
|
||||||
|
- return;
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*));
|
||||||
|
while (t < __stop_SYSTEMD_TEST_TABLE) {
|
||||||
|
- log_info("/* %s */", t->n);
|
||||||
|
- t->f();
|
||||||
|
+ log_info("/* %s */", t->name);
|
||||||
|
+
|
||||||
|
+ if (t->has_ret) {
|
||||||
|
+ int r2 = t->f.int_func();
|
||||||
|
+ if (r == EXIT_SUCCESS)
|
||||||
|
+ r = r2;
|
||||||
|
+ } else
|
||||||
|
+ t->f.void_func();
|
||||||
|
+
|
||||||
|
t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*));
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_CUSTOM_TEST_MAIN(log_level, intro, outro) \
|
||||||
|
int main(int argc, char *argv[]) { \
|
||||||
|
+ int _r = EXIT_SUCCESS; \
|
||||||
|
test_setup_logging(log_level); \
|
||||||
|
save_argc_argv(argc, argv); \
|
||||||
|
intro; \
|
||||||
|
- run_test_table(); \
|
||||||
|
+ _r = run_test_table(); \
|
||||||
|
outro; \
|
||||||
|
- return EXIT_SUCCESS; \
|
||||||
|
+ return _r; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_TEST_MAIN(log_level) DEFINE_CUSTOM_TEST_MAIN(log_level, , )
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
From 0578dfe3eb2ceb8571b62a904dec0ddf410f6352 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Janssen <medhefgo@web.de>
|
||||||
|
Date: Thu, 25 Nov 2021 10:45:15 +0100
|
||||||
|
Subject: [PATCH] test: Add sd_booted condition test to TEST macro
|
||||||
|
|
||||||
|
Note that this will only report test skips if they use TEST_RET macro.
|
||||||
|
Regular TEST macros can still be skipped, but this will not be reported
|
||||||
|
back to main();
|
||||||
|
|
||||||
|
Conflict:NA
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/0578dfe3eb2ceb8571b62a904dec0ddf410f6352
|
||||||
|
|
||||||
|
---
|
||||||
|
src/shared/tests.h | 43 ++++++++++++++++++++++++++-----------------
|
||||||
|
1 file changed, 26 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/shared/tests.h b/src/shared/tests.h
|
||||||
|
index d1c96ef35b..95283e2829 100644
|
||||||
|
--- a/src/shared/tests.h
|
||||||
|
+++ b/src/shared/tests.h
|
||||||
|
@@ -39,7 +39,7 @@ bool can_memlock(void);
|
||||||
|
if (sd_booted() > 0) { \
|
||||||
|
x; \
|
||||||
|
} else { \
|
||||||
|
- printf("systemd not booted skipping '%s'\n", #x); \
|
||||||
|
+ printf("systemd not booted, skipping '%s'\n", #x); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Provide a convenient way to check if we're running in CI. */
|
||||||
|
@@ -51,29 +51,31 @@ typedef struct TestFunc {
|
||||||
|
int (*int_func)(void);
|
||||||
|
} f;
|
||||||
|
const char * const name;
|
||||||
|
- bool has_ret;
|
||||||
|
+ bool has_ret:1;
|
||||||
|
+ bool sd_booted:1;
|
||||||
|
} TestFunc;
|
||||||
|
|
||||||
|
/* See static-destruct.h for an explanation of how this works. */
|
||||||
|
-#define REGISTER_TEST(func) \
|
||||||
|
+#define REGISTER_TEST(func, ...) \
|
||||||
|
_section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_ \
|
||||||
|
static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = { \
|
||||||
|
.f = (union f) &(func), \
|
||||||
|
.name = STRINGIFY(func), \
|
||||||
|
.has_ret = __builtin_types_compatible_p(typeof((union f){}.int_func), typeof(&(func))), \
|
||||||
|
+ ##__VA_ARGS__ \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[];
|
||||||
|
extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[];
|
||||||
|
|
||||||
|
-#define TEST(name) \
|
||||||
|
- static void test_##name(void); \
|
||||||
|
- REGISTER_TEST(test_##name); \
|
||||||
|
+#define TEST(name, ...) \
|
||||||
|
+ static void test_##name(void); \
|
||||||
|
+ REGISTER_TEST(test_##name, ##__VA_ARGS__); \
|
||||||
|
static void test_##name(void)
|
||||||
|
|
||||||
|
-#define TEST_RET(name) \
|
||||||
|
- static int test_##name(void); \
|
||||||
|
- REGISTER_TEST(test_##name); \
|
||||||
|
+#define TEST_RET(name, ...) \
|
||||||
|
+ static int test_##name(void); \
|
||||||
|
+ REGISTER_TEST(test_##name, ##__VA_ARGS__); \
|
||||||
|
static int test_##name(void)
|
||||||
|
|
||||||
|
static inline int run_test_table(void) {
|
||||||
|
@@ -84,14 +86,21 @@ static inline int run_test_table(void) {
|
||||||
|
|
||||||
|
const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*));
|
||||||
|
while (t < __stop_SYSTEMD_TEST_TABLE) {
|
||||||
|
- log_info("/* %s */", t->name);
|
||||||
|
-
|
||||||
|
- if (t->has_ret) {
|
||||||
|
- int r2 = t->f.int_func();
|
||||||
|
- if (r == EXIT_SUCCESS)
|
||||||
|
- r = r2;
|
||||||
|
- } else
|
||||||
|
- t->f.void_func();
|
||||||
|
+
|
||||||
|
+ if (t->sd_booted && sd_booted() <= 0) {
|
||||||
|
+ log_info("/* systemd not booted, skipping %s */", t->name);
|
||||||
|
+ if (t->has_ret && r == EXIT_SUCCESS)
|
||||||
|
+ r = EXIT_TEST_SKIP;
|
||||||
|
+ } else {
|
||||||
|
+ log_info("/* %s */", t->name);
|
||||||
|
+
|
||||||
|
+ if (t->has_ret) {
|
||||||
|
+ int r2 = t->f.int_func();
|
||||||
|
+ if (r == EXIT_SUCCESS)
|
||||||
|
+ r = r2;
|
||||||
|
+ } else
|
||||||
|
+ t->f.void_func();
|
||||||
|
+ }
|
||||||
|
|
||||||
|
t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*));
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
From 9cc615460830afdb51ad23e594906bbe60a3b25a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Janssen <medhefgo@web.de>
|
||||||
|
Date: Fri, 12 Nov 2021 10:54:44 +0100
|
||||||
|
Subject: [PATCH] test: Create convenience macros to declare tests
|
||||||
|
|
||||||
|
Conflict:Delete all contents in test-macro.c.
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/9cc615460830afdb51ad23e594906bbe60a3b25a
|
||||||
|
|
||||||
|
---
|
||||||
|
src/shared/tests.h | 47 ++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 47 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/shared/tests.h b/src/shared/tests.h
|
||||||
|
index c1350763ad..f333ebd842 100644
|
||||||
|
--- a/src/shared/tests.h
|
||||||
|
+++ b/src/shared/tests.h
|
||||||
|
@@ -43,3 +43,50 @@ bool can_memlock(void);
|
||||||
|
|
||||||
|
/* Provide a convenient way to check if we're running in CI. */
|
||||||
|
const char *ci_environment(void);
|
||||||
|
+
|
||||||
|
+typedef struct TestFunc {
|
||||||
|
+ void (*f)(void);
|
||||||
|
+ const char * const n;
|
||||||
|
+} TestFunc;
|
||||||
|
+
|
||||||
|
+/* See static-destruct.h for an explanation of how this works. */
|
||||||
|
+#define REGISTER_TEST(func) \
|
||||||
|
+ static void func(void); \
|
||||||
|
+ _section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_ \
|
||||||
|
+ static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = { \
|
||||||
|
+ .f = &(func), \
|
||||||
|
+ .n = STRINGIFY(func), \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[];
|
||||||
|
+extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[];
|
||||||
|
+
|
||||||
|
+#define TEST(name) \
|
||||||
|
+ REGISTER_TEST(test_##name); \
|
||||||
|
+ static void test_##name(void)
|
||||||
|
+
|
||||||
|
+static inline void run_test_table(void) {
|
||||||
|
+ if (!__start_SYSTEMD_TEST_TABLE)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*));
|
||||||
|
+ while (t < __stop_SYSTEMD_TEST_TABLE) {
|
||||||
|
+ log_info("/* %s */", t->n);
|
||||||
|
+ t->f();
|
||||||
|
+ t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define DEFINE_TEST_MAIN \
|
||||||
|
+ int main(int argc, char *argv[]) { \
|
||||||
|
+ test_setup_logging(LOG_INFO); \
|
||||||
|
+ run_test_table(); \
|
||||||
|
+ return EXIT_SUCCESS; \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#define DEFINE_CUSTOM_TEST_MAIN(impl) \
|
||||||
|
+ int main(int argc, char *argv[]) { \
|
||||||
|
+ test_setup_logging(LOG_INFO); \
|
||||||
|
+ run_test_table(); \
|
||||||
|
+ return impl(); \
|
||||||
|
+ }
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
From a40b728e1172cc07a09e12dd56089ab37c8c5924 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Janssen <medhefgo@web.de>
|
||||||
|
Date: Tue, 23 Nov 2021 13:40:27 +0100
|
||||||
|
Subject: [PATCH] test: Slightly rework DEFINE_TEST_MAIN macros
|
||||||
|
|
||||||
|
- A lot of tests want a different log level
|
||||||
|
- Provides saved_argc/saved_argv to tests
|
||||||
|
- Separate intro/outro is more flexible
|
||||||
|
|
||||||
|
Conflict:Delete content in test-macro.c.
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/a40b728e1172cc07a09e12dd56089ab37c8c5924
|
||||||
|
|
||||||
|
---
|
||||||
|
src/shared/tests.h | 21 ++++++++++-----------
|
||||||
|
1 file changed, 10 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/shared/tests.h b/src/shared/tests.h
|
||||||
|
index f333ebd842..872b9b2d6c 100644
|
||||||
|
--- a/src/shared/tests.h
|
||||||
|
+++ b/src/shared/tests.h
|
||||||
|
@@ -6,6 +6,7 @@
|
||||||
|
#include "sd-daemon.h"
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
+#include "util.h"
|
||||||
|
|
||||||
|
static inline bool manager_errno_skip_test(int r) {
|
||||||
|
return IN_SET(abs(r),
|
||||||
|
@@ -77,16 +78,14 @@ static inline void run_test_table(void) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-#define DEFINE_TEST_MAIN \
|
||||||
|
- int main(int argc, char *argv[]) { \
|
||||||
|
- test_setup_logging(LOG_INFO); \
|
||||||
|
- run_test_table(); \
|
||||||
|
- return EXIT_SUCCESS; \
|
||||||
|
+#define DEFINE_CUSTOM_TEST_MAIN(log_level, intro, outro) \
|
||||||
|
+ int main(int argc, char *argv[]) { \
|
||||||
|
+ test_setup_logging(log_level); \
|
||||||
|
+ save_argc_argv(argc, argv); \
|
||||||
|
+ intro; \
|
||||||
|
+ run_test_table(); \
|
||||||
|
+ outro; \
|
||||||
|
+ return EXIT_SUCCESS; \
|
||||||
|
}
|
||||||
|
|
||||||
|
-#define DEFINE_CUSTOM_TEST_MAIN(impl) \
|
||||||
|
- int main(int argc, char *argv[]) { \
|
||||||
|
- test_setup_logging(LOG_INFO); \
|
||||||
|
- run_test_table(); \
|
||||||
|
- return impl(); \
|
||||||
|
- }
|
||||||
|
+#define DEFINE_TEST_MAIN(log_level) DEFINE_CUSTOM_TEST_MAIN(log_level, , )
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
From f69ae8585f5ce6cd8d1e6f3ccd6c9c2cf153e846 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||||
|
Date: Mon, 10 Oct 2022 21:19:43 +0200
|
||||||
|
Subject: [PATCH] tree-wide: define and use STRERROR_OR_EOF()
|
||||||
|
|
||||||
|
Conflict:NA
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/f69ae8585f5ce6cd8d1e6f3ccd6c9c2cf153e846
|
||||||
|
|
||||||
|
---
|
||||||
|
src/basic/errno-util.h | 5 +++++
|
||||||
|
src/journal-remote/journal-gatewayd.c | 4 ++--
|
||||||
|
src/libsystemd/sd-bus/test-bus-chat.c | 2 +-
|
||||||
|
src/login/logind-seat.c | 8 ++++----
|
||||||
|
src/test/test-errno-util.c | 6 ++++++
|
||||||
|
5 files changed, 18 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h
|
||||||
|
index f0d24d95cb..1e2e5b9f15 100644
|
||||||
|
--- a/src/basic/errno-util.h
|
||||||
|
+++ b/src/basic/errno-util.h
|
||||||
|
@@ -16,6 +16,11 @@
|
||||||
|
* Note that we use the GNU variant of strerror_r() here. */
|
||||||
|
#define STRERROR(errnum) strerror_r(abs(errnum), (char[ERRNO_BUF_LEN]){}, ERRNO_BUF_LEN)
|
||||||
|
|
||||||
|
+/* A helper to print an error message or message for functions that return 0 on EOF.
|
||||||
|
+ * Note that we can't use ({ … }) to define a temporary variable, so errnum is
|
||||||
|
+ * evaluated twice. */
|
||||||
|
+#define STRERROR_OR_EOF(errnum) ((errnum) != 0 ? STRERROR(errnum) : "Unexpected EOF")
|
||||||
|
+
|
||||||
|
static inline void _reset_errno_(int *saved_errno) {
|
||||||
|
if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */
|
||||||
|
return;
|
||||||
|
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
|
||||||
|
index 3e2a85ce29..34def4670e 100644
|
||||||
|
--- a/src/journal-remote/journal-gatewayd.c
|
||||||
|
+++ b/src/journal-remote/journal-gatewayd.c
|
||||||
|
@@ -256,7 +256,7 @@ static ssize_t request_reader_entries(
|
||||||
|
errno = 0;
|
||||||
|
k = fread(buf, 1, n, m->tmp);
|
||||||
|
if (k != n) {
|
||||||
|
- log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF");
|
||||||
|
+ log_error("Failed to read from file: %s", STRERROR_OR_EOF(errno));
|
||||||
|
return MHD_CONTENT_READER_END_WITH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -600,7 +600,7 @@ static ssize_t request_reader_fields(
|
||||||
|
errno = 0;
|
||||||
|
k = fread(buf, 1, n, m->tmp);
|
||||||
|
if (k != n) {
|
||||||
|
- log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF");
|
||||||
|
+ log_error("Failed to read from file: %s", STRERROR_OR_EOF(errno));
|
||||||
|
return MHD_CONTENT_READER_END_WITH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
|
||||||
|
index df6dd62151..93e8ebfb1b 100644
|
||||||
|
--- a/src/libsystemd/sd-bus/test-bus-chat.c
|
||||||
|
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
|
||||||
|
@@ -308,7 +308,7 @@ static void* client1(void *p) {
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (read(pp[0], &x, 1) <= 0) {
|
||||||
|
- log_error("Failed to read from pipe: %s", errno != 0 ? strerror_safe(errno) : "early read");
|
||||||
|
+ log_error("Failed to read from pipe: %s", STRERROR_OR_EOF(errno));
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
|
||||||
|
index 43c72da11f..d8ad424bfe 100644
|
||||||
|
--- a/src/login/logind-seat.c
|
||||||
|
+++ b/src/login/logind-seat.c
|
||||||
|
@@ -389,11 +389,11 @@ int seat_read_active_vt(Seat *s) {
|
||||||
|
if (lseek(s->manager->console_active_fd, SEEK_SET, 0) < 0)
|
||||||
|
return log_error_errno(errno, "lseek on console_active_fd failed: %m");
|
||||||
|
|
||||||
|
+ errno = 0;
|
||||||
|
k = read(s->manager->console_active_fd, t, sizeof(t)-1);
|
||||||
|
- if (k <= 0) {
|
||||||
|
- log_error("Failed to read current console: %s", k < 0 ? strerror_safe(errno) : "EOF");
|
||||||
|
- return k < 0 ? -errno : -EIO;
|
||||||
|
- }
|
||||||
|
+ if (k <= 0)
|
||||||
|
+ return log_error_errno(errno ?: EIO,
|
||||||
|
+ "Failed to read current console: %s", STRERROR_OR_EOF(errno));
|
||||||
|
|
||||||
|
t[k] = 0;
|
||||||
|
truncate_nl(t);
|
||||||
|
diff --git a/src/test/test-errno-util.c b/src/test/test-errno-util.c
|
||||||
|
index 284f451002..f858927c92 100644
|
||||||
|
--- a/src/test/test-errno-util.c
|
||||||
|
+++ b/src/test/test-errno-util.c
|
||||||
|
@@ -41,4 +41,10 @@ TEST(STRERROR) {
|
||||||
|
assert_se(strstr(c, buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
+TEST(STRERROR_OR_ELSE) {
|
||||||
|
+ log_info("STRERROR_OR_ELSE(0, \"EOF\") → %s", STRERROR_OR_EOF(0));
|
||||||
|
+ log_info("STRERROR_OR_ELSE(EPERM, \"EOF\") → %s", STRERROR_OR_EOF(EPERM));
|
||||||
|
+ log_info("STRERROR_OR_ELSE(-EPERM, \"EOF\") → %s", STRERROR_OR_EOF(-EPERM));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
DEFINE_TEST_MAIN(LOG_INFO);
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
32
backport-coredump-Fix-format-string-type-mismatch.patch
Normal file
32
backport-coredump-Fix-format-string-type-mismatch.patch
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
From 08e86b15fc22a8e9f1ee0a791dfd35b2fc25e4c4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||||
|
Date: Sun, 22 May 2022 14:36:07 +0200
|
||||||
|
Subject: [PATCH] coredump: Fix format string type mismatch
|
||||||
|
|
||||||
|
Fixes #23471
|
||||||
|
|
||||||
|
Conflict:NA
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/08e86b15fc22a8e9f1ee0a791dfd35b2fc25e4c4
|
||||||
|
|
||||||
|
---
|
||||||
|
src/coredump/coredump.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||||
|
index c9747416ad..994d968d87 100644
|
||||||
|
--- a/src/coredump/coredump.c
|
||||||
|
+++ b/src/coredump/coredump.c
|
||||||
|
@@ -512,8 +512,8 @@ static int save_external_coredump(
|
||||||
|
|
||||||
|
if (truncated)
|
||||||
|
log_struct(LOG_INFO,
|
||||||
|
- LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size),
|
||||||
|
- "SIZE_LIMIT=%zu", max_size,
|
||||||
|
+ LOG_MESSAGE("Core file was truncated to %"PRIu64" bytes.", max_size),
|
||||||
|
+ "SIZE_LIMIT=%"PRIu64, max_size,
|
||||||
|
"MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR);
|
||||||
|
|
||||||
|
r = fix_permissions(fd, tmp, fn, context, uid);
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
35
backport-coredump-drop-an-unused-variable.patch
Normal file
35
backport-coredump-drop-an-unused-variable.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
From 9abe4cfc39579037937c63602ce8fe4f51746d38 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||||
|
Date: Sat, 20 Aug 2022 21:04:24 +0200
|
||||||
|
Subject: [PATCH] coredump: drop an unused variable
|
||||||
|
|
||||||
|
Conflict:NA
|
||||||
|
Reference:https://github.com/systemd/systemd/commit/9abe4cfc39579037937c63602ce8fe4f51746d38
|
||||||
|
|
||||||
|
---
|
||||||
|
src/coredump/coredump.c | 2 --
|
||||||
|
1 file changed, 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||||
|
index 3ec41a32c3..98e7492811 100644
|
||||||
|
--- a/src/coredump/coredump.c
|
||||||
|
+++ b/src/coredump/coredump.c
|
||||||
|
@@ -931,7 +931,6 @@ log:
|
||||||
|
}
|
||||||
|
|
||||||
|
static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||||
|
- unsigned count = 0;
|
||||||
|
const char *unit;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
@@ -955,7 +954,6 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||||
|
p = startswith(iovec->iov_base, meta_field_names[i]);
|
||||||
|
if (p) {
|
||||||
|
context->meta[i] = p;
|
||||||
|
- count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
15
systemd.spec
15
systemd.spec
@ -21,7 +21,7 @@
|
|||||||
Name: systemd
|
Name: systemd
|
||||||
Url: https://www.freedesktop.org/wiki/Software/systemd
|
Url: https://www.freedesktop.org/wiki/Software/systemd
|
||||||
Version: 249
|
Version: 249
|
||||||
Release: 43
|
Release: 44
|
||||||
License: MIT and LGPLv2+ and GPLv2+
|
License: MIT and LGPLv2+ and GPLv2+
|
||||||
Summary: System and Service Manager
|
Summary: System and Service Manager
|
||||||
|
|
||||||
@ -412,6 +412,16 @@ Patch6363: backport-core-replace-slice-dependencies-as-they-get-added.patch
|
|||||||
Patch6364: backport-scsi_id-retry-inquiry-ioctl-if-host_byte-is-DID_TRAN.patch
|
Patch6364: backport-scsi_id-retry-inquiry-ioctl-if-host_byte-is-DID_TRAN.patch
|
||||||
Patch6365: backport-revert-units-add-ProtectClock-yes.patch
|
Patch6365: backport-revert-units-add-ProtectClock-yes.patch
|
||||||
Patch6366: backport-fix-CVE-2022-3821.patch
|
Patch6366: backport-fix-CVE-2022-3821.patch
|
||||||
|
Patch6367: backport-CVE-2022-4415-test-Create-convenience-macros-to-declare-tests.patch
|
||||||
|
Patch6368: backport-CVE-2022-4415-test-Slightly-rework-DEFINE_TEST_MAIN-macros.patch
|
||||||
|
Patch6369: backport-CVE-2022-4415-test-Add-TEST_RET-macro.patch
|
||||||
|
Patch6370: backport-CVE-2022-4415-test-Add-sd_booted-condition-test-to-TEST-macro.patch
|
||||||
|
Patch6371: backport-CVE-2022-4415-basic-add-STRERROR-wrapper-for-strerror_r.patch
|
||||||
|
Patch6372: backport-CVE-2022-4415-tree-wide-define-and-use-STRERROR_OR_EOF.patch
|
||||||
|
Patch6373: backport-coredump-Fix-format-string-type-mismatch.patch
|
||||||
|
Patch6374: backport-coredump-drop-an-unused-variable.patch
|
||||||
|
Patch6375: backport-CVE-2022-4415-coredump-adjust-whitespace.patch
|
||||||
|
Patch6376: backport-CVE-2022-4415-dont-allow-user-access-coredumps-with-changed-uid.patch
|
||||||
|
|
||||||
Patch9001: update-rtc-with-system-clock-when-shutdown.patch
|
Patch9001: update-rtc-with-system-clock-when-shutdown.patch
|
||||||
Patch9002: udev-add-actions-while-rename-netif-failed.patch
|
Patch9002: udev-add-actions-while-rename-netif-failed.patch
|
||||||
@ -1864,6 +1874,9 @@ fi
|
|||||||
%{_libdir}/security/pam_systemd.so
|
%{_libdir}/security/pam_systemd.so
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Dec 28 2022 huyubiao<huyubiao@huawei.com> - 249-44
|
||||||
|
- fix CVE-2022-4415
|
||||||
|
|
||||||
* Mon Dec 12 2022 huajingyun<huajingyun@loongson.cn> - 249-43
|
* Mon Dec 12 2022 huajingyun<huajingyun@loongson.cn> - 249-43
|
||||||
- Add loongarch for missing_syscall_def.h
|
- Add loongarch for missing_syscall_def.h
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user