1
0
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:
Lennart Poettering 2014-06-27 19:32:14 +02:00
parent 8c9571d0ae
commit b59233e6a3

View File

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