]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
busctl: Support file descriptors in busctl
authorRyan Wilson <ryantimwilson@meta.com>
Mon, 30 Sep 2024 16:52:55 +0000 (09:52 -0700)
committerRyan Wilson <ryantimwilson@meta.com>
Sun, 6 Oct 2024 21:11:31 +0000 (14:11 -0700)
Previously using file descriptors as input arguments in busctl was
unsupported with "UNIX file descriptor not supported as type."

We fix this by parsing the file descriptor as an integer and verifying
it is an available file descriptor in busctl.

Fixes: #14954
Replaces: #34551

src/busctl/busctl.c

index 1b0b72085e6465e900053ef8e8b47ec9bd8c42ef..beff530b924cb4a187c297f736c6195d2450b891 100644 (file)
@@ -17,6 +17,7 @@
 #include "capsule-util.h"
 #include "escape.h"
 #include "fd-util.h"
+#include "fdset.h"
 #include "fileio.h"
 #include "format-table.h"
 #include "glyph-util.h"
@@ -1477,12 +1478,13 @@ static int status(int argc, char **argv, void *userdata) {
         return 0;
 }
 
-static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) {
+static int message_append_cmdline(sd_bus_message *m, const char *signature, FDSet **passed_fdset, char ***x) {
         char **p;
         int r;
 
         assert(m);
         assert(signature);
+        assert(passed_fdset);
         assert(x);
 
         p = *x;
@@ -1631,7 +1633,7 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
                                         return bus_log_create_error(r);
 
                                 for (unsigned i = 0; i < n; i++) {
-                                        r = message_append_cmdline(m, s, &p);
+                                        r = message_append_cmdline(m, s, passed_fdset, &p);
                                         if (r < 0)
                                                 return r;
                                 }
@@ -1648,7 +1650,7 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
                         if (r < 0)
                                 return bus_log_create_error(r);
 
-                        r = message_append_cmdline(m, v, &p);
+                        r = message_append_cmdline(m, v, passed_fdset, &p);
                         if (r < 0)
                                 return r;
 
@@ -1680,7 +1682,7 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
                                 if (r < 0)
                                         return bus_log_create_error(r);
 
-                                r = message_append_cmdline(m, s, &p);
+                                r = message_append_cmdline(m, s, passed_fdset, &p);
                                 if (r < 0)
                                         return r;
                         }
@@ -1691,9 +1693,25 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
                         break;
                 }
 
-                case SD_BUS_TYPE_UNIX_FD:
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "UNIX file descriptor not supported as type.");
+                case SD_BUS_TYPE_UNIX_FD: {
+                        int fd;
+
+                        fd = parse_fd(v);
+                        if (fd < 0)
+                                return log_error_errno(fd, "Failed to parse '%s' as a file descriptor: %m", v);
+
+                        if (!*passed_fdset) {
+                                r = fdset_new_fill(/* filter_cloexec= */ 0, passed_fdset);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to create fd set: %m");
+                        }
+
+                        if (!fdset_contains(*passed_fdset, fd))
+                                return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Failed to find file descriptor '%s' among passed file descriptors.", v);
+
+                        r = sd_bus_message_append_basic(m, t, &fd);
+                        break;
+                }
 
                 default:
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@@ -2049,6 +2067,7 @@ static int call(int argc, char **argv, void *userdata) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_fdset_free_ FDSet *passed_fdset = NULL;
         int r;
 
         r = acquire_bus(false, &bus);
@@ -2085,7 +2104,7 @@ static int call(int argc, char **argv, void *userdata) {
 
                 p = argv+6;
 
-                r = message_append_cmdline(m, argv[5], &p);
+                r = message_append_cmdline(m, argv[5], &passed_fdset, &p);
                 if (r < 0)
                         return r;
 
@@ -2151,6 +2170,7 @@ static int call(int argc, char **argv, void *userdata) {
 static int emit_signal(int argc, char **argv, void *userdata) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_fdset_free_ FDSet *passed_fdset = NULL;
         int r;
 
         r = acquire_bus(false, &bus);
@@ -2176,7 +2196,7 @@ static int emit_signal(int argc, char **argv, void *userdata) {
 
                 p = argv+5;
 
-                r = message_append_cmdline(m, argv[4], &p);
+                r = message_append_cmdline(m, argv[4], &passed_fdset, &p);
                 if (r < 0)
                         return r;
 
@@ -2265,6 +2285,7 @@ static int set_property(int argc, char **argv, void *userdata) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_fdset_free_ FDSet *passed_fdset = NULL;
         char **p;
         int r;
 
@@ -2286,7 +2307,7 @@ static int set_property(int argc, char **argv, void *userdata) {
                 return bus_log_create_error(r);
 
         p = argv + 6;
-        r = message_append_cmdline(m, argv[5], &p);
+        r = message_append_cmdline(m, argv[5], &passed_fdset, &p);
         if (r < 0)
                 return r;