8d419f
From 5cfd162864213c5247d97ea31cfacce98b1caefc Mon Sep 17 00:00:00 2001
8d419f
From: David Tardon <dtardon@redhat.com>
8d419f
Date: Fri, 10 Jun 2022 15:07:01 +0200
8d419f
Subject: [PATCH] logind-session-dbus: allow to set display name via dbus
8d419f
8d419f
Currently, the only way to set display name of a graphical session is to
8d419f
pass it to CreateSession(). But modern display managers like gdm start
8d419f
the display server as part of the user session, which means that the
8d419f
display name isn't known yet when the session is being created. Hence,
8d419f
let's make it possible to set it later.
8d419f
8d419f
(cherry picked from commit 4885d7490b23e08d8444e5a68927ce9ce8727e5a)
8d419f
8d419f
Resolves: #2100340
8d419f
---
8d419f
 man/org.freedesktop.login1.xml        |  8 ++++++++
8d419f
 src/login/logind-session-dbus.c       | 29 +++++++++++++++++++++++++++
8d419f
 src/login/logind-session.c            | 20 ++++++++++++++++++
8d419f
 src/login/logind-session.h            |  1 +
8d419f
 src/login/org.freedesktop.login1.conf |  4 ++++
8d419f
 5 files changed, 62 insertions(+)
8d419f
8d419f
diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml
8d419f
index d25287b18b..c11324ee3b 100644
8d419f
--- a/man/org.freedesktop.login1.xml
8d419f
+++ b/man/org.freedesktop.login1.xml
8d419f
@@ -1045,6 +1045,7 @@ node /org/freedesktop/login1/session/1 {
8d419f
       TakeControl(in  b force);
8d419f
       ReleaseControl();
8d419f
       SetType(in  s type);
8d419f
+      SetDisplay(in  s display);
8d419f
       TakeDevice(in  u major,
8d419f
                  in  u minor,
8d419f
                  out h fd,
8d419f
@@ -1142,6 +1143,8 @@ node /org/freedesktop/login1/session/1 {
8d419f
 
8d419f
     <variablelist class="dbus-method" generated="True" extra-ref="SetType()"/>
8d419f
 
8d419f
+    <variablelist class="dbus-method" generated="True" extra-ref="SetDisplay()"/>
8d419f
+
8d419f
     <variablelist class="dbus-method" generated="True" extra-ref="TakeDevice()"/>
8d419f
 
8d419f
     <variablelist class="dbus-method" generated="True" extra-ref="ReleaseDevice()"/>
8d419f
@@ -1238,6 +1241,11 @@ node /org/freedesktop/login1/session/1 {
8d419f
       connection. This should help prevent a session from entering an inconsistent state, for example if the
8d419f
       controller crashes. The only argument <varname>type</varname> is the new session type.</para>
8d419f
 
8d419f
+      <para><function>SetDisplay()</function> allows the display name of the graphical session to be changed. This is
8d419f
+      useful if the display server is started as part of the session. It can only be called by session's current
8d419f
+      controller. If <function>TakeControl()</function> has not been called, this method will fail. The only argument
8d419f
+      <varname>display</varname> is the new display name.</para>
8d419f
+
8d419f
       <para><function>TakeDevice()</function> allows a session controller to get a file descriptor for a
8d419f
       specific device. Pass in the major and minor numbers of the character device and
8d419f
       <filename>systemd-logind</filename> will return a file descriptor for the device. Only a limited set of
8d419f
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
8d419f
index ff4cd0a631..5480d7b2f4 100644
8d419f
--- a/src/login/logind-session-dbus.c
8d419f
+++ b/src/login/logind-session-dbus.c
8d419f
@@ -413,6 +413,30 @@ static int method_set_type(sd_bus_message *message, void *userdata, sd_bus_error
8d419f
         return sd_bus_reply_method_return(message, NULL);
8d419f
 }
8d419f
 
8d419f
+static int method_set_display(sd_bus_message *message, void *userdata, sd_bus_error *error) {
8d419f
+        Session *s = ASSERT_PTR(userdata);
8d419f
+        const char *display;
8d419f
+        int r;
8d419f
+
8d419f
+        assert(message);
8d419f
+
8d419f
+        r = sd_bus_message_read(message, "s", &display);
8d419f
+        if (r < 0)
8d419f
+                return r;
8d419f
+
8d419f
+        if (!session_is_controller(s, sd_bus_message_get_sender(message)))
8d419f
+                return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set display");
8d419f
+
8d419f
+        if (!SESSION_TYPE_IS_GRAPHICAL(s->type))
8d419f
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Setting display is only supported for graphical sessions");
8d419f
+
8d419f
+        r = session_set_display(s, display);
8d419f
+        if (r < 0)
8d419f
+                return r;
8d419f
+
8d419f
+        return sd_bus_reply_method_return(message, NULL);
8d419f
+}
8d419f
+
8d419f
 static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
8d419f
         Session *s = userdata;
8d419f
         uint32_t major, minor;
8d419f
@@ -901,6 +925,11 @@ static const sd_bus_vtable session_vtable[] = {
8d419f
                                 SD_BUS_NO_RESULT,
8d419f
                                 method_set_type,
8d419f
                                 SD_BUS_VTABLE_UNPRIVILEGED),
8d419f
+        SD_BUS_METHOD_WITH_ARGS("SetDisplay",
8d419f
+                                SD_BUS_ARGS("s", display),
8d419f
+                                SD_BUS_NO_RESULT,
8d419f
+                                method_set_display,
8d419f
+                                SD_BUS_VTABLE_UNPRIVILEGED),
8d419f
         SD_BUS_METHOD_WITH_ARGS("TakeDevice",
8d419f
                                 SD_BUS_ARGS("u", major, "u", minor),
8d419f
                                 SD_BUS_RESULT("h", fd, "b", inactive),
8d419f
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
8d419f
index ab98a5055d..a052596e57 100644
8d419f
--- a/src/login/logind-session.c
8d419f
+++ b/src/login/logind-session.c
8d419f
@@ -1044,6 +1044,26 @@ void session_set_type(Session *s, SessionType t) {
8d419f
         session_send_changed(s, "Type", NULL);
8d419f
 }
8d419f
 
8d419f
+int session_set_display(Session *s, const char *display) {
8d419f
+        int r;
8d419f
+
8d419f
+        assert(s);
8d419f
+        assert(display);
8d419f
+
8d419f
+        if (streq(s->display, display))
8d419f
+                return 0;
8d419f
+
8d419f
+        r = free_and_strdup(&s->display, display);
8d419f
+        if (r < 0)
8d419f
+                return r;
8d419f
+
8d419f
+        session_save(s);
8d419f
+
8d419f
+        session_send_changed(s, "Display", NULL);
8d419f
+
8d419f
+        return 1;
8d419f
+}
8d419f
+
8d419f
 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
8d419f
         Session *s = userdata;
8d419f
 
8d419f
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
8d419f
index 5c35071dc5..6b6ac2d573 100644
8d419f
--- a/src/login/logind-session.h
8d419f
+++ b/src/login/logind-session.h
8d419f
@@ -137,6 +137,7 @@ int session_set_idle_hint(Session *s, bool b);
8d419f
 int session_get_locked_hint(Session *s);
8d419f
 void session_set_locked_hint(Session *s, bool b);
8d419f
 void session_set_type(Session *s, SessionType t);
8d419f
+int session_set_display(Session *s, const char *display);
8d419f
 int session_create_fifo(Session *s);
8d419f
 int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error);
8d419f
 int session_stop(Session *s, bool force);
8d419f
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
8d419f
index 95d2ef0f06..6113b64aa7 100644
8d419f
--- a/src/login/org.freedesktop.login1.conf
8d419f
+++ b/src/login/org.freedesktop.login1.conf
8d419f
@@ -346,6 +346,10 @@
8d419f
                        send_interface="org.freedesktop.login1.User"
8d419f
                        send_member="Kill"/>
8d419f
 
8d419f
+                
8d419f
+                       send_interface="org.freedesktop.login1.Session"
8d419f
+                       send_member="SetDisplay"/>
8d419f
+
8d419f
                 <allow receive_sender="org.freedesktop.login1"/>
8d419f
         </policy>
8d419f