diff --git a/src/basic/fileio.h b/src/basic/fileio.h index cea3dd893d..9151d8237a 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -110,6 +110,12 @@ typedef enum ReadLineFlags { int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret); +static inline bool file_offset_beyond_memory_size(off_t x) { + if (x < 0) /* off_t is signed, filter that out */ + return false; + return (uint64_t) x > (uint64_t) SIZE_MAX; +} + static inline int read_line(FILE *f, size_t limit, char **ret) { return read_line_full(f, limit, 0, ret); } diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c index 7f1a2f15f7..cb99641263 100644 --- a/src/basic/locale-util.c +++ b/src/basic/locale-util.c @@ -14,6 +14,7 @@ #include "dirent-util.h" #include "env-util.h" #include "fd-util.h" +#include "fileio.h" #include "hashmap.h" #include "locale-util.h" #include "path-util.h" @@ -112,6 +113,9 @@ static int add_locales_from_archive(Set *locales) { if (st.st_size < (off_t) sizeof(struct locarhead)) return -EBADMSG; + if (file_offset_beyond_memory_size(st.st_size)) + return -EFBIG; + p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (p == MAP_FAILED) return -errno; diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index c81411c857..1f4dd69d08 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -219,7 +219,7 @@ static int get_file_version(int fd, char **v) { if (r < 0) return log_error_errno(r, "EFI binary is not a regular file: %m"); - if (st.st_size < 27) { + if (st.st_size < 27 || file_offset_beyond_memory_size(st.st_size)) { *v = NULL; return 0; } diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 53601765fe..748cf26934 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -15,6 +15,7 @@ #include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "hashmap.h" #include "hwdb-internal.h" #include "nulstr-util.h" @@ -312,6 +313,9 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) { if (hwdb->st.st_size < (off_t) offsetof(struct trie_header_f, strings_len) + 8) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "File %s is too short: %m", hwdb_bin_path); + if (file_offset_beyond_memory_size(hwdb->st.st_size)) + return log_debug_errno(SYNTHETIC_ERRNO(EFBIG), + "File %s is too long: %m", hwdb_bin_path); hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0); if (hwdb->map == MAP_FAILED) diff --git a/src/libsystemd/sd-journal/catalog.c b/src/libsystemd/sd-journal/catalog.c index 16bd4a63f1..e2397f47e3 100644 --- a/src/libsystemd/sd-journal/catalog.c +++ b/src/libsystemd/sd-journal/catalog.c @@ -521,10 +521,10 @@ static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p if (fstat(fd, &st) < 0) return -errno; - if (st.st_size < (off_t) sizeof(CatalogHeader)) + if (st.st_size < (off_t) sizeof(CatalogHeader) || file_offset_beyond_memory_size(st.st_size)) return -EINVAL; - p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0); + p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (p == MAP_FAILED) return -errno; diff --git a/src/libsystemd/sd-journal/compress.c b/src/libsystemd/sd-journal/compress.c index 837abab76c..cb2e82667f 100644 --- a/src/libsystemd/sd-journal/compress.c +++ b/src/libsystemd/sd-journal/compress.c @@ -25,6 +25,7 @@ #include "alloc-util.h" #include "compress.h" #include "fd-util.h" +#include "fileio.h" #include "io-util.h" #include "journal-def.h" #include "macro.h" @@ -807,6 +808,9 @@ int decompress_stream_lz4(int in, int out, uint64_t max_bytes) { if (fstat(in, &st) < 0) return log_debug_errno(errno, "fstat() failed: %m"); + if (file_offset_beyond_memory_size(st.st_size)) + return -EFBIG; + buf = malloc(LZ4_BUFSIZE); if (!buf) return -ENOMEM;