4cad4c
From af20a66874296f71618819ebce9d4335b195728c Mon Sep 17 00:00:00 2001
4cad4c
From: Lennart Poettering <lennart@poettering.net>
4cad4c
Date: Wed, 22 Jan 2020 12:04:38 +0100
4cad4c
Subject: [PATCH] logind: check PolicyKit before allowing VT switch
4cad4c
4cad4c
Let's lock this down a bit. Effectively nothing much changes, since the
4cad4c
default PK policy will allow users on the VT to change VT. Only users
4cad4c
with no local VT session won't be able to switch VTs.
4cad4c
4cad4c
(cherry picked from commit 4acf0cfd2f92edb94ad48d04f1ce6c9ab4e19d55)
4cad4c
4cad4c
Resolves: #1797679
4cad4c
---
4cad4c
 src/login/logind-dbus.c                 | 16 +++++++
4cad4c
 src/login/logind-seat-dbus.c            | 58 ++++++++++++++++++++++++-
4cad4c
 src/login/logind-session-dbus.c         | 15 +++++++
4cad4c
 src/login/org.freedesktop.login1.policy | 10 +++++
4cad4c
 4 files changed, 98 insertions(+), 1 deletion(-)
4cad4c
4cad4c
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
4cad4c
index dca7f4a30f..3f122fcbd9 100644
4cad4c
--- a/src/login/logind-dbus.c
4cad4c
+++ b/src/login/logind-dbus.c
4cad4c
@@ -913,6 +913,8 @@ static int method_activate_session(sd_bus_message *message, void *userdata, sd_b
4cad4c
         if (r < 0)
4cad4c
                 return r;
4cad4c
 
4cad4c
+        /* PolicyKit is done by bus_session_method_activate() */
4cad4c
+
4cad4c
         return bus_session_method_activate(message, session, error);
4cad4c
 }
4cad4c
 
4cad4c
@@ -944,6 +946,20 @@ static int method_activate_session_on_seat(sd_bus_message *message, void *userda
4cad4c
         if (session->seat != seat)
4cad4c
                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
4cad4c
 
4cad4c
+        r = bus_verify_polkit_async(
4cad4c
+                        message,
4cad4c
+                        CAP_SYS_ADMIN,
4cad4c
+                        "org.freedesktop.login1.chvt",
4cad4c
+                        NULL,
4cad4c
+                        false,
4cad4c
+                        UID_INVALID,
4cad4c
+                        &m->polkit_registry,
4cad4c
+                        error);
4cad4c
+        if (r < 0)
4cad4c
+                return r;
4cad4c
+        if (r == 0)
4cad4c
+                return 1; /* Will call us back */
4cad4c
+
4cad4c
         r = session_activate(session);
4cad4c
         if (r < 0)
4cad4c
                 return r;
4cad4c
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
4cad4c
index c4d9b067c6..2e590a8f21 100644
4cad4c
--- a/src/login/logind-seat-dbus.c
4cad4c
+++ b/src/login/logind-seat-dbus.c
4cad4c
@@ -174,6 +174,20 @@ static int method_activate_session(sd_bus_message *message, void *userdata, sd_b
4cad4c
         if (session->seat != s)
4cad4c
                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
4cad4c
 
4cad4c
+        r = bus_verify_polkit_async(
4cad4c
+                        message,
4cad4c
+                        CAP_SYS_ADMIN,
4cad4c
+                        "org.freedesktop.login1.chvt",
4cad4c
+                        NULL,
4cad4c
+                        false,
4cad4c
+                        UID_INVALID,
4cad4c
+                        &s->manager->polkit_registry,
4cad4c
+                        error);
4cad4c
+        if (r < 0)
4cad4c
+                return r;
4cad4c
+        if (r == 0)
4cad4c
+                return 1; /* Will call us back */
4cad4c
+
4cad4c
         r = session_activate(session);
4cad4c
         if (r < 0)
4cad4c
                 return r;
4cad4c
@@ -194,7 +208,21 @@ static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_erro
4cad4c
                 return r;
4cad4c
 
4cad4c
         if (to <= 0)
4cad4c
-                return -EINVAL;
4cad4c
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
4cad4c
+
4cad4c
+        r = bus_verify_polkit_async(
4cad4c
+                        message,
4cad4c
+                        CAP_SYS_ADMIN,
4cad4c
+                        "org.freedesktop.login1.chvt",
4cad4c
+                        NULL,
4cad4c
+                        false,
4cad4c
+                        UID_INVALID,
4cad4c
+                        &s->manager->polkit_registry,
4cad4c
+                        error);
4cad4c
+        if (r < 0)
4cad4c
+                return r;
4cad4c
+        if (r == 0)
4cad4c
+                return 1; /* Will call us back */
4cad4c
 
4cad4c
         r = seat_switch_to(s, to);
4cad4c
         if (r < 0)
4cad4c
@@ -210,6 +238,20 @@ static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus
4cad4c
         assert(message);
4cad4c
         assert(s);
4cad4c
 
4cad4c
+        r = bus_verify_polkit_async(
4cad4c
+                        message,
4cad4c
+                        CAP_SYS_ADMIN,
4cad4c
+                        "org.freedesktop.login1.chvt",
4cad4c
+                        NULL,
4cad4c
+                        false,
4cad4c
+                        UID_INVALID,
4cad4c
+                        &s->manager->polkit_registry,
4cad4c
+                        error);
4cad4c
+        if (r < 0)
4cad4c
+                return r;
4cad4c
+        if (r == 0)
4cad4c
+                return 1; /* Will call us back */
4cad4c
+
4cad4c
         r = seat_switch_to_next(s);
4cad4c
         if (r < 0)
4cad4c
                 return r;
4cad4c
@@ -224,6 +266,20 @@ static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd
4cad4c
         assert(message);
4cad4c
         assert(s);
4cad4c
 
4cad4c
+        r = bus_verify_polkit_async(
4cad4c
+                        message,
4cad4c
+                        CAP_SYS_ADMIN,
4cad4c
+                        "org.freedesktop.login1.chvt",
4cad4c
+                        NULL,
4cad4c
+                        false,
4cad4c
+                        UID_INVALID,
4cad4c
+                        &s->manager->polkit_registry,
4cad4c
+                        error);
4cad4c
+        if (r < 0)
4cad4c
+                return r;
4cad4c
+        if (r == 0)
4cad4c
+                return 1; /* Will call us back */
4cad4c
+
4cad4c
         r = seat_switch_to_previous(s);
4cad4c
         if (r < 0)
4cad4c
                 return r;
4cad4c
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
4cad4c
index 25c4981dc0..88a2d33dc8 100644
4cad4c
--- a/src/login/logind-session-dbus.c
4cad4c
+++ b/src/login/logind-session-dbus.c
4cad4c
@@ -13,6 +13,7 @@
4cad4c
 #include "logind.h"
4cad4c
 #include "signal-util.h"
4cad4c
 #include "strv.h"
4cad4c
+#include "user-util.h"
4cad4c
 #include "util.h"
4cad4c
 
4cad4c
 static int property_get_user(
4cad4c
@@ -182,6 +183,20 @@ int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_
4cad4c
         assert(message);
4cad4c
         assert(s);
4cad4c
 
4cad4c
+        r = bus_verify_polkit_async(
4cad4c
+                        message,
4cad4c
+                        CAP_SYS_ADMIN,
4cad4c
+                        "org.freedesktop.login1.chvt",
4cad4c
+                        NULL,
4cad4c
+                        false,
4cad4c
+                        UID_INVALID,
4cad4c
+                        &s->manager->polkit_registry,
4cad4c
+                        error);
4cad4c
+        if (r < 0)
4cad4c
+                return r;
4cad4c
+        if (r == 0)
4cad4c
+                return 1; /* Will call us back */
4cad4c
+
4cad4c
         r = session_activate(s);
4cad4c
         if (r < 0)
4cad4c
                 return r;
4cad4c
diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy
4cad4c
index f1d1f956d3..83760e1580 100644
4cad4c
--- a/src/login/org.freedesktop.login1.policy
4cad4c
+++ b/src/login/org.freedesktop.login1.policy
4cad4c
@@ -357,4 +357,14 @@
4cad4c
                 </defaults>
4cad4c
         </action>
4cad4c
 
4cad4c
+        <action id="org.freedesktop.login1.chvt">
4cad4c
+                <description gettext-domain="systemd">Change Session</description>
4cad4c
+                <message gettext-domain="systemd">Authentication is required for changing the virtual terminal.</message>
4cad4c
+                <defaults>
4cad4c
+                        <allow_any>auth_admin_keep</allow_any>
4cad4c
+                        <allow_inactive>auth_admin_keep</allow_inactive>
4cad4c
+                        <allow_active>yes</allow_active>
4cad4c
+                </defaults>
4cad4c
+        </action>
4cad4c
+
4cad4c
 </policyconfig>