diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-05-25 10:15:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-25 10:15:37 +0200 |
commit | cd8910f053babe4b8d3dc9de57dcb7be380ded87 (patch) | |
tree | fc6ba6f68c2724776cdcc52675fa07af979c837c | |
parent | Merge pull request #27769 from YHNdnzj/loginctl-followup (diff) | |
parent | tree-wide: check memstream buffer after closing the handle (diff) | |
download | systemd-cd8910f053babe4b8d3dc9de57dcb7be380ded87.tar.xz systemd-cd8910f053babe4b8d3dc9de57dcb7be380ded87.zip |
Merge pull request #27770 from mrc0mmand/more-nallocfuzz-shenanigans
A couple of fixes for potential issues during OOM situations
-rw-r--r-- | src/basic/env-file.c | 3 | ||||
-rw-r--r-- | src/basic/string-util.c | 17 | ||||
-rw-r--r-- | src/busctl/busctl.c | 3 | ||||
-rw-r--r-- | src/core/manager-dump.c | 3 | ||||
-rw-r--r-- | src/coredump/coredump.c | 3 | ||||
-rw-r--r-- | src/journal/journalctl.c | 4 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-introspect.c | 4 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-match.c | 7 | ||||
-rw-r--r-- | src/libsystemd/sd-journal/catalog.c | 23 | ||||
-rw-r--r-- | src/network/generator/network-generator.c | 75 | ||||
-rw-r--r-- | src/oom/oomd-manager.c | 3 | ||||
-rw-r--r-- | src/oom/oomd-util.c | 5 | ||||
-rw-r--r-- | src/resolve/resolved-dns-dnssec.c | 6 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.c | 7 | ||||
-rw-r--r-- | src/resolve/resolved-manager.c | 5 | ||||
-rw-r--r-- | src/shared/bus-util.c | 3 | ||||
-rw-r--r-- | src/shared/calendarspec.c | 18 | ||||
-rw-r--r-- | src/shared/elf-util.c | 10 | ||||
-rw-r--r-- | src/shared/format-table.c | 3 | ||||
-rw-r--r-- | src/shared/json.c | 29 | ||||
-rw-r--r-- | src/shared/specifier.c | 4 |
21 files changed, 152 insertions, 83 deletions
diff --git a/src/basic/env-file.c b/src/basic/env-file.c index 7b3e209ddc..58d7b3ec35 100644 --- a/src/basic/env-file.c +++ b/src/basic/env-file.c @@ -330,8 +330,7 @@ static int parse_env_file_push( if (streq(key, k)) { va_end(aq); - free(*v); - *v = value; + free_and_replace(*v, value); return 1; } diff --git a/src/basic/string-util.c b/src/basic/string-util.c index d4141968df..61737ffb41 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -9,6 +9,7 @@ #include "alloc-util.h" #include "escape.h" #include "extract-word.h" +#include "fd-util.h" #include "fileio.h" #include "gunicode.h" #include "locale-util.h" @@ -603,9 +604,9 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { STATE_CSI, STATE_CSO, } state = STATE_OTHER; - char *obuf = NULL; + _cleanup_free_ char *obuf = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t osz = 0, isz, shift[2] = {}, n_carriage_returns = 0; - FILE *f; assert(ibuf); assert(*ibuf); @@ -713,11 +714,13 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { } } - if (fflush_and_check(f) < 0) { - fclose(f); - return mfree(obuf); - } - fclose(f); + if (fflush_and_check(f) < 0) + return NULL; + + f = safe_fclose(f); + + if (!obuf) + return NULL; free_and_replace(*ibuf, obuf); diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index 965ded9675..4d69aee5eb 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -1072,6 +1072,9 @@ static int introspect(int argc, char **argv, void *userdata) { mf = safe_fclose(mf); + if (!buf) + return bus_log_parse_error(ENOMEM); + z = set_get(members, &((Member) { .type = "property", .interface = m->interface, diff --git a/src/core/manager-dump.c b/src/core/manager-dump.c index 5a92356d48..35143ebddf 100644 --- a/src/core/manager-dump.c +++ b/src/core/manager-dump.c @@ -95,6 +95,9 @@ int manager_get_dump_string(Manager *m, char **patterns, char **ret) { f = safe_fclose(f); + if (!dump) + return -ENOMEM; + *ret = TAKE_PTR(dump); return 0; diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 5fdcfa7437..a6b0d96488 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -707,6 +707,9 @@ static int compose_open_fds(pid_t pid, char **open_fds) { if (errno > 0) return -errno; + if (!buffer) + return -ENOMEM; + *open_fds = TAKE_PTR(buffer); return 0; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 5f3a121ac9..e379203d5d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1811,6 +1811,10 @@ static int format_journal_url( return r; f = safe_fclose(f); + + if (!url) + return -ENOMEM; + *ret_url = TAKE_PTR(url); return 0; } diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c index 49236a8e12..3d4c47c6dd 100644 --- a/src/libsystemd/sd-bus/bus-introspect.c +++ b/src/libsystemd/sd-bus/bus-introspect.c @@ -268,6 +268,10 @@ int introspect_finish(struct introspect *i, char **ret) { return r; i->f = safe_fclose(i->f); + + if (!i->introspection) + return -ENOMEM; + *ret = TAKE_PTR(i->introspection); return 0; diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index 703b9ac038..cc043abfe3 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -824,6 +824,7 @@ int bus_match_parse( char *bus_match_to_string(struct bus_match_component *components, size_t n_components) { _cleanup_free_ char *buffer = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t size = 0; int r; @@ -832,7 +833,7 @@ char *bus_match_to_string(struct bus_match_component *components, size_t n_compo assert(components); - FILE *f = open_memstream_unlocked(&buffer, &size); + f = open_memstream_unlocked(&buffer, &size); if (!f) return NULL; @@ -855,9 +856,11 @@ char *bus_match_to_string(struct bus_match_component *components, size_t n_compo } r = fflush_and_check(f); - safe_fclose(f); if (r < 0) return NULL; + + f = safe_fclose(f); + return TAKE_PTR(buffer); } diff --git a/src/libsystemd/sd-journal/catalog.c b/src/libsystemd/sd-journal/catalog.c index 7527abf636..06cf396b95 100644 --- a/src/libsystemd/sd-journal/catalog.c +++ b/src/libsystemd/sd-journal/catalog.c @@ -145,7 +145,9 @@ static int finish_item( char *payload, size_t payload_size) { _cleanup_free_ CatalogItem *i = NULL; - _cleanup_free_ char *prev = NULL, *combined = NULL; + _cleanup_free_ char *combined = NULL; + char *prev; + int r; assert(h); assert(payload); @@ -168,19 +170,24 @@ static int finish_item( if (!combined) return log_oom(); - if (ordered_hashmap_update(h, i, combined) < 0) - return log_oom(); - combined = NULL; + r = ordered_hashmap_update(h, i, combined); + if (r < 0) + return r; + + TAKE_PTR(combined); + free(prev); } else { /* A new item */ combined = memdup(payload, payload_size + 1); if (!combined) return log_oom(); - if (ordered_hashmap_put(h, i, combined) < 0) - return log_oom(); - i = NULL; - combined = NULL; + r = ordered_hashmap_put(h, i, combined); + if (r < 0) + return r; + + TAKE_PTR(i); + TAKE_PTR(combined); } return 0; diff --git a/src/network/generator/network-generator.c b/src/network/generator/network-generator.c index 1090934bfc..569dcdf511 100644 --- a/src/network/generator/network-generator.c +++ b/src/network/generator/network-generator.c @@ -1199,30 +1199,31 @@ void link_dump(Link *link, FILE *f) { int network_format(Network *network, char **ret) { _cleanup_free_ char *s = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t sz = 0; int r; assert(network); assert(ret); - { - _cleanup_fclose_ FILE *f = NULL; - - f = open_memstream_unlocked(&s, &sz); - if (!f) - return -ENOMEM; + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; - network_dump(network, f); + network_dump(network, f); - /* Add terminating 0, so that the output buffer is a valid string. */ - fputc('\0', f); + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); - r = fflush_and_check(f); - } + r = fflush_and_check(f); if (r < 0) return r; - assert(s); + f = safe_fclose(f); + + if (!s) + return -ENOMEM; + *ret = TAKE_PTR(s); assert(sz > 0); return (int) sz - 1; @@ -1230,30 +1231,31 @@ int network_format(Network *network, char **ret) { int netdev_format(NetDev *netdev, char **ret) { _cleanup_free_ char *s = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t sz = 0; int r; assert(netdev); assert(ret); - { - _cleanup_fclose_ FILE *f = NULL; - - f = open_memstream_unlocked(&s, &sz); - if (!f) - return -ENOMEM; + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; - netdev_dump(netdev, f); + netdev_dump(netdev, f); - /* Add terminating 0, so that the output buffer is a valid string. */ - fputc('\0', f); + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); - r = fflush_and_check(f); - } + r = fflush_and_check(f); if (r < 0) return r; - assert(s); + f = safe_fclose(f); + + if (!s) + return -ENOMEM; + *ret = TAKE_PTR(s); assert(sz > 0); return (int) sz - 1; @@ -1261,30 +1263,31 @@ int netdev_format(NetDev *netdev, char **ret) { int link_format(Link *link, char **ret) { _cleanup_free_ char *s = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t sz = 0; int r; assert(link); assert(ret); - { - _cleanup_fclose_ FILE *f = NULL; - - f = open_memstream_unlocked(&s, &sz); - if (!f) - return -ENOMEM; + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; - link_dump(link, f); + link_dump(link, f); - /* Add terminating 0, so that the output buffer is a valid string. */ - fputc('\0', f); + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); - r = fflush_and_check(f); - } + r = fflush_and_check(f); if (r < 0) return r; - assert(s); + f = safe_fclose(f); + + if (!s) + return -ENOMEM; + *ret = TAKE_PTR(s); assert(sz > 0); return (int) sz - 1; diff --git a/src/oom/oomd-manager.c b/src/oom/oomd-manager.c index 08a29ec77b..3f050cdbb2 100644 --- a/src/oom/oomd-manager.c +++ b/src/oom/oomd-manager.c @@ -847,6 +847,9 @@ int manager_get_dump_string(Manager *m, char **ret) { f = safe_fclose(f); + if (!dump) + return -ENOMEM; + *ret = TAKE_PTR(dump); return 0; } diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c index 49c10b5e16..6309d2c473 100644 --- a/src/oom/oomd-util.c +++ b/src/oom/oomd-util.c @@ -299,6 +299,11 @@ static int dump_kill_candidates(OomdCGroupContext **sorted, int n, int dump_unti if (r < 0) return r; + f = safe_fclose(f); + + if (!dump) + return -ENOMEM; + return log_dump(LOG_INFO, dump); } diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index fc076856b6..e7c18c29a0 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -867,10 +867,14 @@ static int dnssec_rrset_serialize_sig( } r = fflush_and_check(f); - f = safe_fclose(f); /* sig_data may be reallocated when f is closed. */ if (r < 0) return r; + f = safe_fclose(f); /* sig_data may be reallocated when f is closed. */ + + if (!sig_data) + return -ENOMEM; + *ret_sig_data = TAKE_PTR(sig_data); *ret_sig_size = sig_size; return 0; diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index d3175b1b9d..44d1d1f1e6 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -1222,19 +1222,20 @@ int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) { return 0; r = dns_packet_append_rr(&packet, rr, 0, &start, &rds); - if (r < 0) + if (r < 0) { + dns_packet_unref(&packet); return r; + } assert(start == 0); assert(packet._data); free(rr->wire_format); - rr->wire_format = packet._data; + rr->wire_format = TAKE_PTR(packet._data); rr->wire_format_size = packet.size; rr->wire_format_rdata_offset = rds; rr->wire_format_canonical = canonical; - packet._data = NULL; dns_packet_unref(&packet); return 0; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 184d8e3f3d..67786d39fd 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -519,6 +519,11 @@ static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si if (fflush_and_check(f) < 0) return log_oom(); + f = safe_fclose(f); + + if (!buffer) + return -ENOMEM; + log_dump(LOG_INFO, buffer); return 0; } diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index ca0d77c136..b99883a088 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -628,6 +628,9 @@ static int method_dump_memory_state_by_fd(sd_bus_message *message, void *userdat dump_file = safe_fclose(dump_file); + if (!dump) + return -ENOMEM; + fd = acquire_data_fd(dump, dump_size, 0); if (fd < 0) return fd; diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c index 78902dfbda..fa19e4c95a 100644 --- a/src/shared/calendarspec.c +++ b/src/shared/calendarspec.c @@ -12,6 +12,7 @@ #include "alloc-util.h" #include "calendarspec.h" #include "errno-util.h" +#include "fd-util.h" #include "fileio.h" #include "macro.h" #include "parse-util.h" @@ -336,9 +337,9 @@ static void format_chain(FILE *f, int space, const CalendarComponent *c, bool us } int calendar_spec_to_string(const CalendarSpec *c, char **p) { - char *buf = NULL; + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t sz = 0; - FILE *f; int r; assert(c); @@ -383,14 +384,15 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) { } r = fflush_and_check(f); - fclose(f); - - if (r < 0) { - free(buf); + if (r < 0) return r; - } - *p = buf; + f = safe_fclose(f); + + if (!buf) + return -ENOMEM; + + *p = TAKE_PTR(buf); return 0; } diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c index 98c47d9125..5885215a1c 100644 --- a/src/shared/elf-util.c +++ b/src/shared/elf-util.c @@ -621,8 +621,13 @@ static int parse_core(int fd, const char *executable, char **ret, JsonVariant ** return log_warning_errno(r, "Could not parse core file, flushing file buffer failed: %m"); c.f = safe_fclose(c.f); + + if (!buf) + return log_oom(); + *ret = TAKE_PTR(buf); } + if (ret_package_metadata) *ret_package_metadata = TAKE_PTR(package_metadata); @@ -735,8 +740,13 @@ static int parse_elf(int fd, const char *executable, char **ret, JsonVariant **r return log_warning_errno(r, "Could not parse ELF file, flushing file buffer failed: %m"); c.f = safe_fclose(c.f); + + if (!buf) + return log_oom(); + *ret = TAKE_PTR(buf); } + if (ret_package_metadata) *ret_package_metadata = TAKE_PTR(elf_metadata); diff --git a/src/shared/format-table.c b/src/shared/format-table.c index 204e8b68b6..83b749d677 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -2537,6 +2537,9 @@ int table_format(Table *t, char **ret) { f = safe_fclose(f); + if (!buf) + return -ENOMEM; + *ret = TAKE_PTR(buf); return 0; diff --git a/src/shared/json.c b/src/shared/json.c index 73050b55c8..5bf00f009f 100644 --- a/src/shared/json.c +++ b/src/shared/json.c @@ -1769,6 +1769,7 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { _cleanup_free_ char *s = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t sz = 0; int r; @@ -1781,26 +1782,26 @@ int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { if (flags & JSON_FORMAT_OFF) return -ENOEXEC; - { - _cleanup_fclose_ FILE *f = NULL; - - f = open_memstream_unlocked(&s, &sz); - if (!f) - return -ENOMEM; + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; - r = json_variant_dump(v, flags, f, NULL); - if (r < 0) - return r; + r = json_variant_dump(v, flags, f, NULL); + if (r < 0) + return r; - /* Add terminating 0, so that the output buffer is a valid string. */ - fputc('\0', f); + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); - r = fflush_and_check(f); - } + r = fflush_and_check(f); if (r < 0) return r; - assert(s); + f = safe_fclose(f); + + if (!s) + return -ENOMEM; + *ret = TAKE_PTR(s); assert(sz > 0); return (int) sz - 1; diff --git a/src/shared/specifier.c b/src/shared/specifier.c index 31390fbd89..e5a1f94f2a 100644 --- a/src/shared/specifier.c +++ b/src/shared/specifier.c @@ -284,7 +284,7 @@ int specifier_architecture(char specifier, const void *data, const char *root, c * installation. */ static int parse_os_release_specifier(const char *root, const char *id, char **ret) { - char *v = NULL; + _cleanup_free_ char *v = NULL; int r; assert(ret); @@ -293,7 +293,7 @@ static int parse_os_release_specifier(const char *root, const char *id, char **r if (r >= 0) /* parse_os_release() calls parse_env_file() which only sets the return value for * entries found. Let's make sure we set the return value in all cases. */ - *ret = v; + *ret = TAKE_PTR(v); /* Translate error for missing os-release file to EUNATCH. */ return r == -ENOENT ? -EUNATCH : r; |