From: Lennart Poettering Date: Mon, 27 Mar 2023 16:16:03 +0000 (+0200) Subject: analyze: add new fdstore verb X-Git-Tag: v254-rc1~864^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5f43c97cd24b25f846d005eccd7837a2cd279230;p=thirdparty%2Fsystemd.git analyze: add new fdstore verb --- diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index ad6d691a1d1..9fd28e6f45c 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -156,6 +156,12 @@ malloc D-BUS SERVICE + + systemd-analyze + OPTIONS + fdstore + UNIT + @@ -803,8 +809,37 @@ $ systemd-analyze verify /tmp/source:alias.service } + + + + <command>systemd-analyze fdstore <optional><replaceable>UNIT</replaceable>...</optional></command> + + Lists the current contents of the specified service unit's file descriptor store. This shows + names, inode types, device numbers, inode numbers, paths and open modes of the open file + descriptors. The specified units must have FileDescriptorStoreMax= enabled, see + systemd.service5 for + details. + + + Table output + $ systemd-analyze fdstore systemd-journald.service +FDNAME TYPE DEVNO INODE RDEVNO PATH FLAGS +stored sock 0:8 4218620 - socket:[4218620] ro +stored sock 0:8 4213198 - socket:[4213198] ro +stored sock 0:8 4213190 - socket:[4213190] ro +… + + Note: the "DEVNO" column refers to the major/minor numbers of the device node backing the file + system the file descriptor's inode is on. The "RDEVNO" column refers to the major/minor numbers of the + device node itself if the file descriptor refers to one. Compare with corresponding + .st_dev and .st_rdev fields in struct stat (see + stat2 for + details). The listed inode numbers in the "INODE" column are on the file system indicated by + "DEVNO". + diff --git a/man/systemd.service.xml b/man/systemd.service.xml index e8be2ff4685..665128ee77f 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -1141,7 +1141,18 @@ fully stopped and no job is queued or being executed for it. If this option is used, NotifyAccess= (see above) should be set to open access to the notification socket provided by systemd. If NotifyAccess= is not set, it will be implicitly set to - . + . + + The fdstore command of + systemd-analyze1 + may be used to list the current contents of a service's file descriptor store. + + Note that the service manager will only pass file descriptors contained in the file descriptor + store to the service's own processes, never to other clients via IPC or similar. However, it does + allow unprivileged clients to query the list of currently open file descriptors of a + service. Sensitive data may hence be safely placed inside the referenced files, but should not be + attached to the metadata (e.g. included in filenames) of the stored file + descriptors. diff --git a/src/analyze/analyze-fdstore.c b/src/analyze/analyze-fdstore.c new file mode 100644 index 00000000000..13db7f50883 --- /dev/null +++ b/src/analyze/analyze-fdstore.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "analyze-fdstore.h" +#include "analyze.h" +#include "bus-error.h" +#include "bus-locator.h" +#include "fd-util.h" +#include "format-table.h" + +static int dump_fdstore(sd_bus *bus, const char *arg) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + _cleanup_free_ char *unit = NULL; + int r; + + assert(bus); + assert(arg); + + r = unit_name_mangle_with_suffix(arg, NULL, UNIT_NAME_MANGLE_GLOB, ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to mangle name '%s': %m", arg); + + r = bus_call_method( + bus, + bus_systemd_mgr, + "DumpUnitFileDescriptorStore", + &error, + &reply, + "s", unit); + if (r < 0) + return log_error_errno(r, "Failed to call DumpUnitFileDescriptorStore: %s", + bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "(suuutuusu)"); + if (r < 0) + return bus_log_parse_error(r); + + table = table_new("fdname", "type", "devno", "inode", "rdevno", "path", "flags"); + if (!table) + return log_oom(); + + table_set_ersatz_string(table, TABLE_ERSATZ_DASH); + + (void) table_set_align_percent(table, TABLE_HEADER_CELL(3), 100); + + for (;;) { + uint32_t mode, major, minor, rmajor, rminor, flags; + const char *fdname, *path; + uint64_t inode; + + r = sd_bus_message_read( + reply, + "(suuutuusu)", + &fdname, + &mode, + &major, &minor, + &inode, + &rmajor, &rminor, + &path, + &flags); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + r = table_add_many( + table, + TABLE_STRING, fdname, + TABLE_MODE_INODE_TYPE, mode, + TABLE_DEVNUM, makedev(major, minor), + TABLE_UINT64, inode, + TABLE_DEVNUM, makedev(rmajor, rminor), + TABLE_PATH, path, + TABLE_STRING, accmode_to_string(flags)); + if (r < 0) + return table_log_add_error(r); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return r; + + if (FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && table_get_rows(table) <= 0) + log_info("No file descriptors in fdstore of '%s'.", unit); + else { + r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, /* show_header= */true); + if (r < 0) + return log_error_errno(r, "Failed to output table: %m"); + } + + return EXIT_SUCCESS; +} + +int verb_fdstore(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return bus_log_connect_error(r, arg_transport); + + STRV_FOREACH(arg, strv_skip(argv, 1)) { + r = dump_fdstore(bus, *arg); + if (r < 0) + return r; + } + + return EXIT_SUCCESS; +} diff --git a/src/analyze/analyze-fdstore.h b/src/analyze/analyze-fdstore.h new file mode 100644 index 00000000000..0b990db3955 --- /dev/null +++ b/src/analyze/analyze-fdstore.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-bus.h" + +int verb_fdstore(int argc, char *argv[], void *userdata); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 12c0bd653fa..0246da4b45d 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -17,11 +17,13 @@ #include "analyze-calendar.h" #include "analyze-capability.h" #include "analyze-cat-config.h" +#include "analyze-compare-versions.h" #include "analyze-condition.h" #include "analyze-critical-chain.h" #include "analyze-dot.h" #include "analyze-dump.h" #include "analyze-exit-status.h" +#include "analyze-fdstore.h" #include "analyze-filesystems.h" #include "analyze-inspect-elf.h" #include "analyze-log-control.h" @@ -36,7 +38,6 @@ #include "analyze-timestamp.h" #include "analyze-unit-files.h" #include "analyze-unit-paths.h" -#include "analyze-compare-versions.h" #include "analyze-verify.h" #include "build.h" #include "bus-error.h" @@ -229,6 +230,7 @@ static int help(int argc, char *argv[], void *userdata) { " security [UNIT...] Analyze security of unit\n" " inspect-elf FILE... Parse and print ELF package metadata\n" " malloc [D-BUS SERVICE...] Dump malloc stats of a D-Bus service\n" + " fdstore SERVICE... Show file descriptor store contents of service\n" "\nOptions:\n" " --recursive-errors=MODE Control which units are verified\n" " --offline=BOOL Perform a security review on unit file(s)\n" @@ -531,9 +533,9 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --offline= is only supported for security right now."); - if (arg_json_format_flags != JSON_FORMAT_OFF && !STRPTR_IN_SET(argv[optind], "security", "inspect-elf", "plot")) + if (arg_json_format_flags != JSON_FORMAT_OFF && !STRPTR_IN_SET(argv[optind], "security", "inspect-elf", "plot", "fdstore")) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Option --json= is only supported for security, inspect-elf, and plot right now."); + "Option --json= is only supported for security, inspect-elf, plot, and fdstore right now."); if (arg_threshold != 100 && !streq_ptr(argv[optind], "security")) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -620,6 +622,7 @@ static int run(int argc, char *argv[]) { { "security", VERB_ANY, VERB_ANY, 0, verb_security }, { "inspect-elf", 2, VERB_ANY, 0, verb_elf_inspection }, { "malloc", VERB_ANY, VERB_ANY, 0, verb_malloc }, + { "fdstore", 2, VERB_ANY, 0, verb_fdstore }, {} }; diff --git a/src/analyze/meson.build b/src/analyze/meson.build index ac40600a6de..695089a0bed 100644 --- a/src/analyze/meson.build +++ b/src/analyze/meson.build @@ -11,6 +11,7 @@ systemd_analyze_sources = files( 'analyze-dot.c', 'analyze-dump.c', 'analyze-exit-status.c', + 'analyze-fdstore.c', 'analyze-filesystems.c', 'analyze-inspect-elf.c', 'analyze-log-control.c',