]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pid1: add DumpFileDescriptorStore() bus call that returns fdstore content info
authorLennart Poettering <lennart@poettering.net>
Mon, 27 Mar 2023 16:16:40 +0000 (18:16 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 29 Mar 2023 16:53:20 +0000 (18:53 +0200)
man/org.freedesktop.systemd1.xml
src/basic/missing_fcntl.h
src/core/dbus-manager.c
src/core/dbus-service.c
src/core/dbus-service.h
src/libsystemd/sd-bus/bus-common-errors.c
src/libsystemd/sd-bus/bus-common-errors.h

index ab94a90b7cfd181a3c30a9581a3945fb2f0fe7d8..1a82a19bbdc589f8399e0805502cb38a130e0192 100644 (file)
@@ -273,6 +273,8 @@ node /org/freedesktop/systemd1 {
       LookupDynamicUserByUID(in  u uid,
                              out s name);
       GetDynamicUsers(out a(us) users);
+      DumpUnitFileDescriptorStore(in  s name,
+                                  out a(suuutuusu) entries);
     signals:
       UnitNew(s id,
               o unit);
@@ -974,6 +976,8 @@ node /org/freedesktop/systemd1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="GetDynamicUsers()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="DumpUnitFileDescriptorStore()"/>
+
     <variablelist class="dbus-signal" generated="True" extra-ref="UnitNew"/>
 
     <variablelist class="dbus-signal" generated="True" extra-ref="UnitRemoved"/>
@@ -1531,6 +1535,11 @@ node /org/freedesktop/systemd1 {
       <ulink url="https://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface">New Control Group
       Interface</ulink> for more information how to make use of this functionality for resource control
       purposes.</para>
+
+      <para><function>DumpUnitFileDescriptorStore()</function> returns an array with information about the
+      file descriptors currently in the file descriptor store of the specified unit. This call is equivalent
+      to <function>DumpFileDescriptorStore()</function> on the
+      <interfacename>org.freedesktop.systemd1.Service</interfacename>. For further details, see below.</para>
     </refsect2>
 
     <refsect2>
@@ -2548,6 +2557,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
                  in  b read_only,
                  in  b mkdir,
                  in  a(ss) options);
+      DumpFileDescriptorStore(out a(suuutuusu) entries);
       GetProcesses(out a(sus) processes);
       AttachProcesses(in  s subcgroup,
                       in  au pids);
@@ -3742,6 +3752,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-method" generated="True" extra-ref="MountImage()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="DumpFileDescriptorStore()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="GetProcesses()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
@@ -4393,6 +4405,16 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       directly on the Manager object has the advantage of not requiring a <function>GetUnit()</function> call
       to get the unit object for a specific unit name. Calling the methods on the Manager object is hence a round
       trip optimization.</para>
+
+      <para><function>DumpFileDescriptorStore()</function> returns an array with information about the file
+      descriptors currently in the file descriptor store of the service. Each entry consists of a file
+      descriptor name (i.e. the <varname>FDNAME=</varname> field), the file descriptor inode type and access
+      mode as integer (i.e. a <type>mode_t</type> value, flags such as <constant>S_IFREG</constant>,
+      <constant>S_IRUSR</constant>, …), the major and minor numbers of the device number of the file system
+      backing the inode of the file descriptor, the inode number, the major and minor numbers of the device
+      number if this refers to a character or block device node, a file system path pointing to the inode,
+      and the file descriptor flags (i.e. <constant>O_RDWR</constant>, <constant>O_RDONLY</constant>,
+      …).</para>
     </refsect2>
 
     <refsect2>
index 00937d2af03d91ff58743f76baf8e7487114c501..79e95a8f6fda9e0839ea21130f2d0dc60d86110b 100644 (file)
 #ifndef O_TMPFILE
 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
 #endif
+
+/* So O_LARGEFILE is generally implied by glibc, and defined to zero hence, because we only build in LFS
+ * mode. However, when invoking fcntl(F_GETFL) the flag is ORed into the result anyway — glibc does not mask
+ * it away. Which sucks. Let's define the actual value here, so that we can mask it ourselves. */
+#if O_LARGEFILE != 0
+#define RAW_O_LARGEFILE O_LARGEFILE
+#else
+#define RAW_O_LARGEFILE 0100000
+#endif
index c88ef93443c97c263873e732bba9a433506757fc..2cb9efc14e18d5b5526b460c231b0a9998cbd09b 100644 (file)
@@ -2840,6 +2840,10 @@ static int method_set_show_status(sd_bus_message *message, void *userdata, sd_bu
         return sd_bus_reply_method_return(message, NULL);
 }
 
+static int method_dump_unit_descriptor_store(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return method_generic_unit_operation(message, userdata, error, bus_service_method_dump_file_descriptor_store, 0);
+}
+
 const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_VTABLE_START(0),
 
@@ -3385,6 +3389,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
                                 SD_BUS_RESULT("a(us)", users),
                                 method_get_dynamic_users,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DumpUnitFileDescriptorStore",
+                                SD_BUS_ARGS("s", name),
+                                SD_BUS_RESULT("a(suuutuusu)", entries),
+                                method_dump_unit_descriptor_store,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
 
         SD_BUS_SIGNAL_WITH_ARGS("UnitNew",
                                 SD_BUS_ARGS("s", id, "o", unit),
index ddfffe80fd6c1977852ffdc9ec77b4655746bc27..742893370f68c10347742932e737f4658f56c256 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "alloc-util.h"
 #include "async.h"
+#include "bus-common-errors.h"
 #include "bus-get-properties.h"
 #include "dbus-cgroup.h"
 #include "dbus-execute.h"
@@ -16,6 +17,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "locale-util.h"
+#include "missing_fcntl.h"
 #include "mount-util.h"
 #include "open-file.h"
 #include "parse-util.h"
@@ -218,6 +220,72 @@ int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_b
         return bus_service_method_mount(message, userdata, error, true);
 }
 
+int bus_service_method_dump_file_descriptor_store(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        Service *s = ASSERT_PTR(userdata);
+        int r;
+
+        assert(message);
+
+        r = mac_selinux_unit_access_check(UNIT(s), message, "status", error);
+        if (r < 0)
+                return r;
+
+        if (s->n_fd_store_max == 0 && s->n_fd_store == 0)
+                return sd_bus_error_setf(error, BUS_ERROR_FILE_DESCRIPTOR_STORE_DISABLED, "File descriptor store not enabled for %s.", UNIT(s)->id);
+
+        r = sd_bus_message_new_method_return(message, &reply);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_open_container(reply, 'a', "(suuutuusu)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(fd_store, i, s->fd_store) {
+                _cleanup_free_ char *path = NULL;
+                struct stat st;
+                int flags;
+
+                if (fstat(i->fd, &st) < 0) {
+                        log_debug_errno(errno, "Failed to stat() file descriptor entry '%s', skipping.", strna(i->fdname));
+                        continue;
+                }
+
+                flags = fcntl(i->fd, F_GETFL);
+                if (flags < 0) {
+                        log_debug_errno(errno, "Failed to issue F_GETFL on file descriptor entry '%s', skipping.", strna(i->fdname));
+                        continue;
+                }
+
+                /* glibc implies O_LARGEFILE everywhere on 64bit off_t builds, but forgets to hide it away on
+                 * F_GETFL, but provides no definition to check for that. Let's mask the flag away manually,
+                 * to not confuse clients. */
+                flags &= ~RAW_O_LARGEFILE;
+
+                (void) fd_get_path(i->fd, &path);
+
+                r = sd_bus_message_append(
+                                reply,
+                                "(suuutuusu)",
+                                i->fdname,
+                                (uint32_t) st.st_mode,
+                                (uint32_t) major(st.st_dev), (uint32_t) minor(st.st_dev),
+                                (uint64_t) st.st_ino,
+                                (uint32_t) major(st.st_rdev), (uint32_t) minor(st.st_rdev),
+                                path,
+                                (uint32_t) flags);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(NULL, reply, NULL);
+}
+
 const sd_bus_vtable bus_service_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -292,6 +360,12 @@ const sd_bus_vtable bus_service_vtable[] = {
                                  bus_service_method_mount_image,
                                  SD_BUS_VTABLE_UNPRIVILEGED),
 
+        SD_BUS_METHOD_WITH_ARGS("DumpFileDescriptorStore",
+                                SD_BUS_NO_ARGS,
+                                SD_BUS_ARGS("a(suuutuusu)", entries),
+                                bus_service_method_dump_file_descriptor_store,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
+
         /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
         SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
         SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
index 9a054658025b9d5d3368530d68ca5e8fa882c1fd..aea6cf77f30a2bd2fe46c42493a3c79705709a81 100644 (file)
@@ -12,3 +12,4 @@ int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitW
 int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_service_commit_properties(Unit *u);
+int bus_service_method_dump_file_descriptor_store(sd_bus_message *message, void *userdata, sd_bus_error *error);
index 0eaedec87c77fe41afcc7f58de95c71d39dd4e4b..df26fd75cd19a453d09a49113a61ad5d06e27664 100644 (file)
@@ -32,6 +32,8 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER,         ESRCH),
         SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED,               EUNATCH),
         SD_BUS_ERROR_MAP(BUS_ERROR_DISK_FULL,                    ENOSPC),
+        SD_BUS_ERROR_MAP(BUS_ERROR_FILE_DESCRIPTOR_STORE_DISABLED,
+                                                                 EHOSTDOWN),
 
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE,              ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE,                ENOENT),
index b6c2e93ea5b0580b3419fc7d4690a5b4f275b6ff..3a0eef49ef57b93d6c99a4037bd0b2d90c30b7db 100644 (file)
@@ -32,6 +32,8 @@
 #define BUS_ERROR_UNIT_BUSY                    "org.freedesktop.systemd1.UnitBusy"
 #define BUS_ERROR_UNIT_INACTIVE                "org.freedesktop.systemd1.UnitInactive"
 #define BUS_ERROR_FREEZE_CANCELLED             "org.freedesktop.systemd1.FreezeCancelled"
+#define BUS_ERROR_FILE_DESCRIPTOR_STORE_DISABLED        \
+                                               "org.freedesktop.systemd1.FileDescriptorStoreDisabled"
 
 #define BUS_ERROR_NO_SUCH_MACHINE              "org.freedesktop.machine1.NoSuchMachine"
 #define BUS_ERROR_NO_SUCH_IMAGE                "org.freedesktop.machine1.NoSuchImage"