diff options
-rw-r--r-- | src/coredump/coredump.c | 74 | ||||
-rw-r--r-- | src/shared/coredump-util.c | 92 | ||||
-rw-r--r-- | src/shared/coredump-util.h | 10 |
3 files changed, 107 insertions, 69 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 1f259cf669..b7a62e72b0 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -49,7 +49,6 @@ #include "sync-util.h" #include "tmpfile-util.h" #include "uid-alloc-range.h" -#include "unaligned.h" #include "user-util.h" /* The maximum size up to which we process coredumps. We use 1G on 32bit systems, and 32G on 64bit systems */ @@ -336,66 +335,6 @@ static int make_filename(const Context *context, char **ret) { return 0; } -#define _DEFINE_PARSE_AUXV(size, type, unaligned_read) \ - static int parse_auxv##size( \ - const void *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(type)) != 0) \ - return log_warning_errno(SYNTHETIC_ERRNO(EIO), \ - "Incomplete auxv structure (%zu bytes).", \ - size_bytes); \ - \ - size_t words = size_bytes / sizeof(type); \ - \ - /* Note that we set output variables even on error. */ \ - \ - for (size_t i = 0; i + 1 < words; i += 2) { \ - type key, val; \ - \ - key = unaligned_read((uint8_t*) auxv + i * sizeof(type)); \ - val = unaligned_read((uint8_t*) auxv + (i + 1) * sizeof(type)); \ - \ - switch (key) { \ - case AT_SECURE: \ - *at_secure = val != 0; \ - break; \ - case AT_UID: \ - *uid = val; \ - break; \ - case AT_EUID: \ - *euid = val; \ - break; \ - case AT_GID: \ - *gid = val; \ - break; \ - case AT_EGID: \ - *egid = val; \ - break; \ - case AT_NULL: \ - if (val != 0) \ - goto error; \ - return 0; \ - } \ - } \ - error: \ - return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), \ - "AT_NULL terminator not found, cannot parse auxv structure."); \ - } - -#define DEFINE_PARSE_AUXV(size)\ - _DEFINE_PARSE_AUXV(size, uint##size##_t, unaligned_read_ne##size) - -DEFINE_PARSE_AUXV(32); -DEFINE_PARSE_AUXV(64); - static int grant_user_access(int core_fd, const Context *context) { int at_secure = -1; uid_t uid = UID_INVALID, euid = UID_INVALID; @@ -430,14 +369,11 @@ static int grant_user_access(int core_fd, const Context *context) { return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), "Core file has non-native endianness, not adjusting permissions."); - if (elf[EI_CLASS] == ELFCLASS64) - r = parse_auxv64(context->meta[META_PROC_AUXV], - context->meta_size[META_PROC_AUXV], - &at_secure, &uid, &euid, &gid, &egid); - else - r = parse_auxv32(context->meta[META_PROC_AUXV], - context->meta_size[META_PROC_AUXV], - &at_secure, &uid, &euid, &gid, &egid); + r = parse_auxv(LOG_WARNING, + /* elf_class= */ elf[EI_CLASS], + context->meta[META_PROC_AUXV], + context->meta_size[META_PROC_AUXV], + &at_secure, &uid, &euid, &gid, &egid); if (r < 0) return r; diff --git a/src/shared/coredump-util.c b/src/shared/coredump-util.c index 3d2f179049..bf8ea00b14 100644 --- a/src/shared/coredump-util.c +++ b/src/shared/coredump-util.c @@ -1,9 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include <elf.h> + #include "coredump-util.h" #include "extract-word.h" #include "fileio.h" #include "string-table.h" +#include "unaligned.h" #include "virt.h" static const char *const coredump_filter_table[_COREDUMP_FILTER_MAX] = { @@ -65,6 +68,95 @@ int coredump_filter_mask_from_string(const char *s, uint64_t *ret) { return 0; } +#define _DEFINE_PARSE_AUXV(size, type, unaligned_read) \ + static int parse_auxv##size( \ + int log_level, \ + const void *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); \ + assert(at_secure); \ + assert(uid); \ + assert(euid); \ + assert(gid); \ + assert(egid); \ + \ + if (size_bytes % (2 * sizeof(type)) != 0) \ + return log_full_errno(log_level, \ + SYNTHETIC_ERRNO(EIO), \ + "Incomplete auxv structure (%zu bytes).", \ + size_bytes); \ + \ + size_t words = size_bytes / sizeof(type); \ + \ + /* Note that we set output variables even on error. */ \ + \ + for (size_t i = 0; i + 1 < words; i += 2) { \ + type key, val; \ + \ + key = unaligned_read((uint8_t*) auxv + i * sizeof(type)); \ + val = unaligned_read((uint8_t*) auxv + (i + 1) * sizeof(type)); \ + \ + switch (key) { \ + case AT_SECURE: \ + *at_secure = val != 0; \ + break; \ + case AT_UID: \ + *uid = val; \ + break; \ + case AT_EUID: \ + *euid = val; \ + break; \ + case AT_GID: \ + *gid = val; \ + break; \ + case AT_EGID: \ + *egid = val; \ + break; \ + case AT_NULL: \ + if (val != 0) \ + goto error; \ + return 0; \ + } \ + } \ + error: \ + return log_full_errno(log_level, \ + SYNTHETIC_ERRNO(ENODATA), \ + "AT_NULL terminator not found, cannot parse auxv structure."); \ + } + +#define DEFINE_PARSE_AUXV(size) \ + _DEFINE_PARSE_AUXV(size, uint##size##_t, unaligned_read_ne##size) + +DEFINE_PARSE_AUXV(32); +DEFINE_PARSE_AUXV(64); + +int parse_auxv(int log_level, + uint8_t elf_class, + const void *auxv, + size_t size_bytes, + int *at_secure, + uid_t *uid, + uid_t *euid, + gid_t *gid, + gid_t *egid) { + + switch (elf_class) { + case ELFCLASS64: + return parse_auxv64(log_level, auxv, size_bytes, at_secure, uid, euid, gid, egid); + case ELFCLASS32: + return parse_auxv32(log_level, auxv, size_bytes, at_secure, uid, euid, gid, egid); + default: + return log_full_errno(log_level, SYNTHETIC_ERRNO(EPROTONOSUPPORT), + "Unknown ELF class %d.", elf_class); + } +} + int set_coredump_filter(uint64_t value) { char t[STRLEN("0xFFFFFFFF")]; diff --git a/src/shared/coredump-util.h b/src/shared/coredump-util.h index 8eda86dfdb..99dbfde730 100644 --- a/src/shared/coredump-util.h +++ b/src/shared/coredump-util.h @@ -26,5 +26,15 @@ const char* coredump_filter_to_string(CoredumpFilter i) _const_; CoredumpFilter coredump_filter_from_string(const char *s) _pure_; int coredump_filter_mask_from_string(const char *s, uint64_t *ret); +int parse_auxv(int log_level, + uint8_t elf_class, + const void *auxv, + size_t size_bytes, + int *at_secure, + uid_t *uid, + uid_t *euid, + gid_t *gid, + gid_t *egid); + int set_coredump_filter(uint64_t value); void disable_coredumps(void); |