summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-05-25 10:15:37 +0200
committerGitHub <noreply@github.com>2023-05-25 10:15:37 +0200
commitcd8910f053babe4b8d3dc9de57dcb7be380ded87 (patch)
treefc6ba6f68c2724776cdcc52675fa07af979c837c
parentMerge pull request #27769 from YHNdnzj/loginctl-followup (diff)
parenttree-wide: check memstream buffer after closing the handle (diff)
downloadsystemd-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.c3
-rw-r--r--src/basic/string-util.c17
-rw-r--r--src/busctl/busctl.c3
-rw-r--r--src/core/manager-dump.c3
-rw-r--r--src/coredump/coredump.c3
-rw-r--r--src/journal/journalctl.c4
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.c4
-rw-r--r--src/libsystemd/sd-bus/bus-match.c7
-rw-r--r--src/libsystemd/sd-journal/catalog.c23
-rw-r--r--src/network/generator/network-generator.c75
-rw-r--r--src/oom/oomd-manager.c3
-rw-r--r--src/oom/oomd-util.c5
-rw-r--r--src/resolve/resolved-dns-dnssec.c6
-rw-r--r--src/resolve/resolved-dns-rr.c7
-rw-r--r--src/resolve/resolved-manager.c5
-rw-r--r--src/shared/bus-util.c3
-rw-r--r--src/shared/calendarspec.c18
-rw-r--r--src/shared/elf-util.c10
-rw-r--r--src/shared/format-table.c3
-rw-r--r--src/shared/json.c29
-rw-r--r--src/shared/specifier.c4
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;