1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-23 21:35:11 +03:00

coredump: split out parse_auxv() to src/shared/

No functional change. (We already checked for ELFCLASS32 or ELFCLASS64 before,
so even though there's a new check for other architectures, the only caller
only passes ELFCLASS32 or ELFCLASS64.)
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2023-03-22 09:53:16 +01:00
parent f1710073c7
commit cb38fdbedb
3 changed files with 107 additions and 69 deletions

View File

@ -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;

View File

@ -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")];

View File

@ -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);