mirror of
https://github.com/systemd/systemd.git
synced 2024-11-02 10:51:20 +03:00
coredump: simplify compression logic a bit
This also make sure we remove the original coredump temporary file if we successfully managed to compress the coredump.
This commit is contained in:
parent
8c9571d0ae
commit
b59233e6a3
@ -139,6 +139,8 @@ static int fix_acl(int fd, uid_t uid) {
|
|||||||
acl_entry_t entry;
|
acl_entry_t entry;
|
||||||
acl_permset_t permset;
|
acl_permset_t permset;
|
||||||
|
|
||||||
|
assert(fd >= 0);
|
||||||
|
|
||||||
if (uid <= SYSTEM_UID_MAX)
|
if (uid <= SYSTEM_UID_MAX)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -189,6 +191,8 @@ static int fix_xattr(int fd, const char *info[_INFO_LEN]) {
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
assert(fd >= 0);
|
||||||
|
|
||||||
/* Attach some metadata to coredumps via extended
|
/* Attach some metadata to coredumps via extended
|
||||||
* attributes. Just because we can. */
|
* attributes. Just because we can. */
|
||||||
|
|
||||||
@ -208,8 +212,17 @@ static int fix_xattr(int fd, const char *info[_INFO_LEN]) {
|
|||||||
|
|
||||||
#define filename_escape(s) xescape((s), "./ ")
|
#define filename_escape(s) xescape((s), "./ ")
|
||||||
|
|
||||||
static int fix_permissions(int fd, const char *filename, const char *target,
|
static int fix_permissions(
|
||||||
const char *info[_INFO_LEN], uid_t uid) {
|
int fd,
|
||||||
|
const char *filename,
|
||||||
|
const char *target,
|
||||||
|
const char *info[_INFO_LEN],
|
||||||
|
uid_t uid) {
|
||||||
|
|
||||||
|
assert(fd >= 0);
|
||||||
|
assert(filename);
|
||||||
|
assert(target);
|
||||||
|
assert(info);
|
||||||
|
|
||||||
/* Ignore errors on these */
|
/* Ignore errors on these */
|
||||||
fchmod(fd, 0640);
|
fchmod(fd, 0640);
|
||||||
@ -231,7 +244,7 @@ static int fix_permissions(int fd, const char *filename, const char *target,
|
|||||||
|
|
||||||
static int maybe_remove_external_coredump(const char *filename, off_t size) {
|
static int maybe_remove_external_coredump(const char *filename, off_t size) {
|
||||||
|
|
||||||
/* Returns 1 if might remove, 0 if will not remove, <0 on error. */
|
/* Returns 1 if might remove, 0 if will not remove, < 0 on error. */
|
||||||
|
|
||||||
if (IN_SET(arg_storage, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_BOTH) &&
|
if (IN_SET(arg_storage, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_BOTH) &&
|
||||||
size <= arg_external_size_max)
|
size <= arg_external_size_max)
|
||||||
@ -248,6 +261,45 @@ static int maybe_remove_external_coredump(const char *filename, off_t size) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int make_filename(const char *info[_INFO_LEN], char **ret) {
|
||||||
|
_cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL;
|
||||||
|
sd_id128_t boot;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(info);
|
||||||
|
|
||||||
|
c = filename_escape(info[INFO_COMM]);
|
||||||
|
if (!c)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
u = filename_escape(info[INFO_UID]);
|
||||||
|
if (!u)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = sd_id128_get_boot(&boot);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
p = filename_escape(info[INFO_PID]);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
t = filename_escape(info[INFO_TIMESTAMP]);
|
||||||
|
if (!t)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (asprintf(ret,
|
||||||
|
"/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000",
|
||||||
|
c,
|
||||||
|
u,
|
||||||
|
SD_ID128_FORMAT_VAL(boot),
|
||||||
|
p,
|
||||||
|
t) < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int save_external_coredump(
|
static int save_external_coredump(
|
||||||
const char *info[_INFO_LEN],
|
const char *info[_INFO_LEN],
|
||||||
uid_t uid,
|
uid_t uid,
|
||||||
@ -255,9 +307,8 @@ static int save_external_coredump(
|
|||||||
int *ret_fd,
|
int *ret_fd,
|
||||||
off_t *ret_size) {
|
off_t *ret_size) {
|
||||||
|
|
||||||
_cleanup_free_ char *p = NULL, *t = NULL, *c = NULL, *fn = NULL, *tmp = NULL, *u = NULL;
|
_cleanup_free_ char *fn = NULL, *tmp = NULL;
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
sd_id128_t boot;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -266,38 +317,12 @@ static int save_external_coredump(
|
|||||||
assert(ret_fd);
|
assert(ret_fd);
|
||||||
assert(ret_size);
|
assert(ret_size);
|
||||||
|
|
||||||
c = filename_escape(info[INFO_COMM]);
|
r = make_filename(info, &fn);
|
||||||
if (!c)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
p = filename_escape(info[INFO_PID]);
|
|
||||||
if (!p)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
u = filename_escape(info[INFO_UID]);
|
|
||||||
if (!u)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
t = filename_escape(info[INFO_TIMESTAMP]);
|
|
||||||
if (!t)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
r = sd_id128_get_boot(&boot);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error("Failed to determine boot ID: %s", strerror(-r));
|
log_error("Failed to determine coredump file name: %s", strerror(-r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = asprintf(&fn,
|
|
||||||
"/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000",
|
|
||||||
c,
|
|
||||||
u,
|
|
||||||
SD_ID128_FORMAT_VAL(boot),
|
|
||||||
p,
|
|
||||||
t);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
tmp = tempfn_random(fn);
|
tmp = tempfn_random(fn);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
@ -329,7 +354,7 @@ static int save_external_coredump(
|
|||||||
|
|
||||||
if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
|
if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
|
||||||
log_error("Failed to seek on %s: %m", tmp);
|
log_error("Failed to seek on %s: %m", tmp);
|
||||||
goto uncompressed;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_XZ
|
#ifdef HAVE_XZ
|
||||||
@ -337,45 +362,51 @@ static int save_external_coredump(
|
|||||||
if (maybe_remove_external_coredump(NULL, st.st_size) == 0
|
if (maybe_remove_external_coredump(NULL, st.st_size) == 0
|
||||||
&& arg_compress) {
|
&& arg_compress) {
|
||||||
|
|
||||||
_cleanup_free_ char *fn2 = NULL;
|
_cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL;
|
||||||
char *tmp2;
|
_cleanup_close_ int fd_compressed = -1;
|
||||||
_cleanup_close_ int fd2 = -1;
|
|
||||||
|
|
||||||
tmp2 = strappenda(tmp, ".xz");
|
fn_compressed = strappend(fn, ".xz");
|
||||||
fd2 = open(tmp2, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640);
|
if (!fn_compressed) {
|
||||||
if (fd2 < 0) {
|
r = log_oom();
|
||||||
log_error("Failed to create file %s: %m", tmp2);
|
|
||||||
goto uncompressed;
|
goto uncompressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = compress_stream(fd, fd2, LZMA_PRESET_DEFAULT, -1);
|
tmp_compressed = tempfn_random(fn_compressed);
|
||||||
|
if (!tmp_compressed) {
|
||||||
|
r = log_oom();
|
||||||
|
goto uncompressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_compressed = open(tmp_compressed, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640);
|
||||||
|
if (fd_compressed < 0) {
|
||||||
|
log_error("Failed to create file %s: %m", tmp_compressed);
|
||||||
|
goto uncompressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = compress_stream(fd, fd_compressed, LZMA_PRESET_DEFAULT, -1);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error("Failed to compress %s: %s", tmp2, strerror(-r));
|
log_error("Failed to compress %s: %s", tmp_compressed, strerror(-r));
|
||||||
unlink_noerrno(tmp2);
|
goto fail_compressed;
|
||||||
goto fail2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn2 = strappend(fn, ".xz");
|
r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, info, uid);
|
||||||
if (!fn2) {
|
|
||||||
log_oom();
|
|
||||||
goto fail2;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = fix_permissions(fd2, tmp2, fn2, info, uid);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail2;
|
goto fail_compressed;
|
||||||
|
|
||||||
*ret_filename = fn2; /* compressed */
|
/* OK, this worked, we can get rid of the uncompressed version now */
|
||||||
|
unlink_noerrno(tmp);
|
||||||
|
|
||||||
|
*ret_filename = fn_compressed; /* compressed */
|
||||||
*ret_fd = fd; /* uncompressed */
|
*ret_fd = fd; /* uncompressed */
|
||||||
*ret_size = st.st_size; /* uncompressed */
|
*ret_size = st.st_size; /* uncompressed */
|
||||||
|
|
||||||
fn2 = NULL;
|
fn_compressed = NULL;
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail2:
|
fail_compressed:
|
||||||
unlink_noerrno(tmp2);
|
unlink_noerrno(tmp_compressed);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user