diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 0b252eb28fb..8dd3f8cd950 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -100,7 +100,7 @@ int cg_read_event( if (r < 0) return r; - r = read_full_file(events, &content, NULL); + r = read_full_virtual_file(events, &content, NULL); if (r < 0) return r; diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 8560982aab2..6e42b60c3fe 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -368,7 +368,6 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re struct stat st; size_t n, size; int n_retries; - char *p; assert(ret_contents); @@ -405,18 +404,21 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re /* Be prepared for files from /proc which generally report a file size of 0. */ if (st.st_size > 0) { + if (st.st_size > SSIZE_MAX) /* safety check in case off_t is 64bit and size_t 32bit */ + return -E2BIG; + size = st.st_size; n_retries--; } else - size = size * 2; + /* Double the buffer size (saturate in case of overflow) */ + size = size > SSIZE_MAX / 2 ? SSIZE_MAX : size * 2; if (size > READ_FULL_BYTES_MAX) return -E2BIG; - p = realloc(buf, size + 1); - if (!p) + buf = malloc(size + 1); + if (!buf) return -ENOMEM; - buf = TAKE_PTR(p); for (;;) { ssize_t k; @@ -445,12 +447,18 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re if (lseek(fd, 0, SEEK_SET) < 0) return -errno; + + buf = mfree(buf); } if (n < size) { + char *p; + + /* Return rest of the buffer to libc */ p = realloc(buf, n + 1); if (!p) return -ENOMEM; + buf = TAKE_PTR(p); } diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index adf10a45481..c8f6675eb86 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -114,7 +114,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mn xsprintf(path, "/proc/self/fdinfo/%i", subfd); } - r = read_full_file(path, &fdinfo, NULL); + r = read_full_virtual_file(path, &fdinfo, NULL); if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ return -EOPNOTSUPP; if (r < 0) diff --git a/src/basic/process-util.c b/src/basic/process-util.c index d3eb3ad18ba..eb257144f02 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1548,7 +1548,7 @@ int pidfd_get_pid(int fd, pid_t *ret) { xsprintf(path, "/proc/self/fdinfo/%i", fd); - r = read_full_file(path, &fdinfo, NULL); + r = read_full_virtual_file(path, &fdinfo, NULL); if (r == -ENOENT) /* if fdinfo doesn't exist we assume the process does not exist */ return -ESRCH; if (r < 0) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 72e859a565d..2fb2404500e 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -1125,23 +1125,23 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) { (void) iovw_put_string_field_free(iovw, "COREDUMP_OPEN_FDS=", t); p = procfs_file_alloca(pid, "status"); - if (read_full_file(p, &t, NULL) >= 0) + if (read_full_virtual_file(p, &t, NULL) >= 0) (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_STATUS=", t); p = procfs_file_alloca(pid, "maps"); - if (read_full_file(p, &t, NULL) >= 0) + if (read_full_virtual_file(p, &t, NULL) >= 0) (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MAPS=", t); p = procfs_file_alloca(pid, "limits"); - if (read_full_file(p, &t, NULL) >= 0) + if (read_full_virtual_file(p, &t, NULL) >= 0) (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_LIMITS=", t); p = procfs_file_alloca(pid, "cgroup"); - if (read_full_file(p, &t, NULL) >=0) + if (read_full_virtual_file(p, &t, NULL) >=0) (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_CGROUP=", t); p = procfs_file_alloca(pid, "mountinfo"); - if (read_full_file(p, &t, NULL) >=0) + if (read_full_virtual_file(p, &t, NULL) >=0) (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MOUNTINFO=", t); if (get_process_cwd(pid, &t) >= 0) diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 3134d8ef172..5e748fdb462 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -1002,7 +1002,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { const char *p; p = procfs_file_alloca(pid, "cmdline"); - r = read_full_file(p, &c->cmdline, &c->cmdline_size); + r = read_full_virtual_file(p, &c->cmdline, &c->cmdline_size); if (r == -ENOENT) return -ESRCH; if (r < 0) { diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 964ef1318ed..e556a6f838c 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -513,7 +513,7 @@ int device_read_uevent_file(sd_device *device) { path = strjoina(syspath, "/uevent"); - r = read_full_file(path, &uevent, &uevent_len); + r = read_full_virtual_file(path, &uevent, &uevent_len); if (r == -EACCES) { /* empty uevent files may be write-only */ device->uevent_loaded = true; diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c index 9d59c608c15..6ce38f10a3e 100644 --- a/src/pstore/pstore.c +++ b/src/pstore/pstore.c @@ -342,7 +342,7 @@ static int list_files(PStoreList *list, const char *sourcepath) { size_t buf_size; /* Now read contents of pstore file */ - r = read_full_file(ifd_path, &buf, &buf_size); + r = read_full_virtual_file(ifd_path, &buf, &buf_size); if (r < 0) { log_warning_errno(r, "Failed to read file %s, skipping: %m", ifd_path); continue; diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c index 11244537991..cccea2f7275 100644 --- a/src/shared/acpi-fpdt.c +++ b/src/shared/acpi-fpdt.c @@ -72,7 +72,7 @@ int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) { struct acpi_fpdt_boot_header hbrec; struct acpi_fpdt_boot brec; - r = read_full_file("/sys/firmware/acpi/tables/FPDT", &buf, &l); + r = read_full_virtual_file("/sys/firmware/acpi/tables/FPDT", &buf, &l); if (r < 0) return r; diff --git a/src/systemctl/systemctl-edit.c b/src/systemctl/systemctl-edit.c index 4186ec3aea7..7cb58c5208d 100644 --- a/src/systemctl/systemctl-edit.c +++ b/src/systemctl/systemctl-edit.c @@ -146,7 +146,6 @@ static int create_edit_temp_file(const char *new_path, const char *original_path _cleanup_free_ char *new_contents = NULL; _cleanup_fclose_ FILE *f = NULL; char **path; - size_t size; r = mac_selinux_create_file_prepare(new_path, S_IFREG); if (r < 0) @@ -161,7 +160,7 @@ static int create_edit_temp_file(const char *new_path, const char *original_path if (r < 0) return log_error_errno(errno, "Failed to change mode of \"%s\": %m", t); - r = read_full_file(new_path, &new_contents, &size); + r = read_full_file(new_path, &new_contents, NULL); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to read \"%s\": %m", new_path); @@ -182,7 +181,7 @@ static int create_edit_temp_file(const char *new_path, const char *original_path if (path_equal(*path, new_path)) continue; - r = read_full_file(*path, &contents, &size); + r = read_full_file(*path, &contents, NULL); if (r < 0) return log_error_errno(r, "Failed to read \"%s\": %m", *path); @@ -468,10 +467,12 @@ static int trim_edit_markers(const char *path) { int r; /* Trim out the lines between the two markers */ - r = read_full_file(path, &contents, &size); + r = read_full_file(path, &contents, NULL); if (r < 0) return log_error_errno(r, "Failed to read temporary file \"%s\": %m", path); + size = strlen(contents); + contents_start = strstr(contents, EDIT_MARKER_START); if (contents_start) contents_start += strlen(EDIT_MARKER_START);