Skip to content

Commit 1a823cd

Browse files
stoeckmannpoettering
authored andcommitted
core: check size before mmap
The data type off_t can be 64 on 32 bit systems if they have large file support. Since mmap expects a size_t with 32 bits as second argument truncation could occur. At worst these huge files could lead to mmaps smaller than the previous check for small files. This in turn shouldn't have a lot of impact because mmap allocates at page size boundaries. This also made the PAGE_ALIGN call in open_mmap unneeded. In fact it was neither in sync with other mmap calls nor with its own munmap counterpart in error path. If such large files are encountered, which is very unlikely in these code paths, treat them with the same error as if they are too small.
1 parent 94ce42b commit 1a823cd

File tree

6 files changed

+21
-3
lines changed

6 files changed

+21
-3
lines changed

src/basic/fileio.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ typedef enum ReadLineFlags {
110110

111111
int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret);
112112

113+
static inline bool file_offset_beyond_memory_size(off_t x) {
114+
if (x < 0) /* off_t is signed, filter that out */
115+
return false;
116+
return (uint64_t) x > (uint64_t) SIZE_MAX;
117+
}
118+
113119
static inline int read_line(FILE *f, size_t limit, char **ret) {
114120
return read_line_full(f, limit, 0, ret);
115121
}

src/basic/locale-util.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "dirent-util.h"
1515
#include "env-util.h"
1616
#include "fd-util.h"
17+
#include "fileio.h"
1718
#include "hashmap.h"
1819
#include "locale-util.h"
1920
#include "path-util.h"
@@ -112,6 +113,9 @@ static int add_locales_from_archive(Set *locales) {
112113
if (st.st_size < (off_t) sizeof(struct locarhead))
113114
return -EBADMSG;
114115

116+
if (file_offset_beyond_memory_size(st.st_size))
117+
return -EFBIG;
118+
115119
p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
116120
if (p == MAP_FAILED)
117121
return -errno;

src/boot/bootctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static int get_file_version(int fd, char **v) {
219219
if (r < 0)
220220
return log_error_errno(r, "EFI binary is not a regular file: %m");
221221

222-
if (st.st_size < 27) {
222+
if (st.st_size < 27 || file_offset_beyond_memory_size(st.st_size)) {
223223
*v = NULL;
224224
return 0;
225225
}

src/libsystemd/sd-hwdb/sd-hwdb.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "alloc-util.h"
1717
#include "fd-util.h"
18+
#include "fileio.h"
1819
#include "hashmap.h"
1920
#include "hwdb-internal.h"
2021
#include "nulstr-util.h"
@@ -312,6 +313,9 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) {
312313
if (hwdb->st.st_size < (off_t) offsetof(struct trie_header_f, strings_len) + 8)
313314
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
314315
"File %s is too short: %m", hwdb_bin_path);
316+
if (file_offset_beyond_memory_size(hwdb->st.st_size))
317+
return log_debug_errno(SYNTHETIC_ERRNO(EFBIG),
318+
"File %s is too long: %m", hwdb_bin_path);
315319

316320
hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0);
317321
if (hwdb->map == MAP_FAILED)

src/libsystemd/sd-journal/catalog.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,10 +521,10 @@ static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p
521521
if (fstat(fd, &st) < 0)
522522
return -errno;
523523

524-
if (st.st_size < (off_t) sizeof(CatalogHeader))
524+
if (st.st_size < (off_t) sizeof(CatalogHeader) || file_offset_beyond_memory_size(st.st_size))
525525
return -EINVAL;
526526

527-
p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0);
527+
p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
528528
if (p == MAP_FAILED)
529529
return -errno;
530530

src/libsystemd/sd-journal/compress.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "alloc-util.h"
2626
#include "compress.h"
2727
#include "fd-util.h"
28+
#include "fileio.h"
2829
#include "io-util.h"
2930
#include "journal-def.h"
3031
#include "macro.h"
@@ -807,6 +808,9 @@ int decompress_stream_lz4(int in, int out, uint64_t max_bytes) {
807808
if (fstat(in, &st) < 0)
808809
return log_debug_errno(errno, "fstat() failed: %m");
809810

811+
if (file_offset_beyond_memory_size(st.st_size))
812+
return -EFBIG;
813+
810814
buf = malloc(LZ4_BUFSIZE);
811815
if (!buf)
812816
return -ENOMEM;

0 commit comments

Comments
 (0)