mirror of
https://github.com/systemd/systemd.git
synced 2025-01-12 13:18:14 +03:00
Merge pull request #31319 from poettering/journal-tighten-memfd-flags
journald: tighten checks on incoming memfds a bit
This commit is contained in:
commit
63091fa38c
@ -22,6 +22,7 @@
|
|||||||
#include "journald-wall.h"
|
#include "journald-wall.h"
|
||||||
#include "memfd-util.h"
|
#include "memfd-util.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
|
#include "missing_fcntl.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
@ -342,16 +343,41 @@ void server_process_native_file(
|
|||||||
assert(s);
|
assert(s);
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
/* If it's a memfd, check if it is sealed. If so, we can just
|
if (fstat(fd, &st) < 0) {
|
||||||
* mmap it and use it, and do not need to copy the data out. */
|
log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT, "Failed to stat passed file, ignoring: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = stat_verify_regular(&st);
|
||||||
|
if (r < 0) {
|
||||||
|
log_ratelimit_error_errno(r, JOURNAL_LOG_RATELIMIT, "File passed is not regular, ignoring: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int flags = fcntl(fd, F_GETFL);
|
||||||
|
if (flags < 0) {
|
||||||
|
log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT, "Failed to get flags of passed file, ignoring: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & ~(O_ACCMODE|RAW_O_LARGEFILE)) != 0) {
|
||||||
|
log_ratelimit_error(JOURNAL_LOG_RATELIMIT, "Unexpected flags of passed memory fd, ignoring message: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it's a memfd, check if it is sealed. If so, we can just mmap it and use it, and do not need to
|
||||||
|
* copy the data out. */
|
||||||
sealed = memfd_get_sealed(fd) > 0;
|
sealed = memfd_get_sealed(fd) > 0;
|
||||||
|
|
||||||
if (!sealed && (!ucred || ucred->uid != 0)) {
|
if (!sealed && (!ucred || ucred->uid != 0)) {
|
||||||
_cleanup_free_ char *k = NULL;
|
_cleanup_free_ char *k = NULL;
|
||||||
const char *e;
|
const char *e;
|
||||||
|
|
||||||
/* If this is not a sealed memfd, and the peer is unknown or
|
/* If this is not a sealed memfd, and the peer is unknown or unprivileged, then verify the
|
||||||
* unprivileged, then verify the path. */
|
* path. */
|
||||||
|
|
||||||
r = fd_get_path(fd, &k);
|
r = fd_get_path(fd, &k);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -374,23 +400,8 @@ void server_process_native_file(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat(fd, &st) < 0) {
|
/* When !sealed, set a lower memory limit. We have to read the file, effectively doubling memory
|
||||||
log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
|
* use. */
|
||||||
"Failed to stat passed file, ignoring: %m");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISREG(st.st_mode)) {
|
|
||||||
log_ratelimit_error(JOURNAL_LOG_RATELIMIT,
|
|
||||||
"File passed is not regular. Ignoring.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (st.st_size <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* When !sealed, set a lower memory limit. We have to read the file,
|
|
||||||
* effectively doubling memory use. */
|
|
||||||
if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2)) {
|
if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2)) {
|
||||||
log_ratelimit_error(JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_error(JOURNAL_LOG_RATELIMIT,
|
||||||
"File passed too large (%"PRIu64" bytes). Ignoring.",
|
"File passed too large (%"PRIu64" bytes). Ignoring.",
|
||||||
@ -426,8 +437,7 @@ void server_process_native_file(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Refuse operating on file systems that have
|
/* Refuse operating on file systems that have mandatory locking enabled, see:
|
||||||
* mandatory locking enabled, see:
|
|
||||||
*
|
*
|
||||||
* https://github.com/systemd/systemd/issues/1822
|
* https://github.com/systemd/systemd/issues/1822
|
||||||
*/
|
*/
|
||||||
@ -437,13 +447,10 @@ void server_process_native_file(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the fd non-blocking. On regular files this has
|
/* Make the fd non-blocking. On regular files this has the effect of bypassing mandatory
|
||||||
* the effect of bypassing mandatory locking. Of
|
* locking. Of course, this should normally not be necessary given the check above, but let's
|
||||||
* course, this should normally not be necessary given
|
* better be safe than sorry, after all NFS is pretty confusing regarding file system flags,
|
||||||
* the check above, but let's better be safe than
|
* and we better don't trust it, and so is SMB. */
|
||||||
* sorry, after all NFS is pretty confusing regarding
|
|
||||||
* file system flags, and we better don't trust it,
|
|
||||||
* and so is SMB. */
|
|
||||||
r = fd_nonblock(fd, true);
|
r = fd_nonblock(fd, true);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_ratelimit_error_errno(r, JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_error_errno(r, JOURNAL_LOG_RATELIMIT,
|
||||||
@ -451,9 +458,8 @@ void server_process_native_file(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The file is not sealed, we can't map the file here, since
|
/* The file is not sealed, we can't map the file here, since clients might then truncate it
|
||||||
* clients might then truncate it and trigger a SIGBUS for
|
* and trigger a SIGBUS for us. So let's stupidly read it. */
|
||||||
* us. So let's stupidly read it. */
|
|
||||||
|
|
||||||
p = malloc(st.st_size);
|
p = malloc(st.st_size);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
Loading…
Reference in New Issue
Block a user