diff -Nru gnome-control-center-45.0/debian/changelog gnome-control-center-45.0/debian/changelog --- gnome-control-center-45.0/debian/changelog 2023-10-10 20:20:37.000000000 +1030 +++ gnome-control-center-45.0/debian/changelog 2023-11-20 14:22:06.000000000 +1030 @@ -1,3 +1,14 @@ +gnome-control-center (1:45.0-1ubuntu4) noble; urgency=medium + + * SECURITY UPDATE: SSH remote access status not displayed correctly (LP: #2039577) + - d/p/u/lp2039577.patch: Check the status of both the sshd service and + socket since either could be in use. Also when enabling remote access, + enable this via the socket rather than the service. + - debian/rules: set SSHD_SOCKET=ssh.socket via CPPFLAGS in debian/rules. + - CVE-2023-5616 + + -- Alex Murray Mon, 20 Nov 2023 14:22:06 +1030 + gnome-control-center (1:45.0-1ubuntu3) mantic; urgency=medium * d/p/u/Disable-non-working-camera-microphones-panels.patch: diff -Nru gnome-control-center-45.0/debian/patches/series gnome-control-center-45.0/debian/patches/series --- gnome-control-center-45.0/debian/patches/series 2023-10-10 20:20:37.000000000 +1030 +++ gnome-control-center-45.0/debian/patches/series 2023-11-20 13:21:31.000000000 +1030 @@ -26,3 +26,4 @@ ubuntu/applications-Launch-snap-store-if-it-is-installed.patch ubuntu/display-Allow-fractional-scaling-to-be-enabled.patch #ubuntu/mouse-Add-animations-following-the-accent-colors.patch +ubuntu/lp2039577.patch diff -Nru gnome-control-center-45.0/debian/patches/ubuntu/lp2039577.patch gnome-control-center-45.0/debian/patches/ubuntu/lp2039577.patch --- gnome-control-center-45.0/debian/patches/ubuntu/lp2039577.patch 1970-01-01 09:30:00.000000000 +0930 +++ gnome-control-center-45.0/debian/patches/ubuntu/lp2039577.patch 2023-11-20 14:22:06.000000000 +1030 @@ -0,0 +1,363 @@ +--- a/panels/sharing/cc-remote-login.c ++++ b/panels/sharing/cc-remote-login.c +@@ -25,16 +25,81 @@ + #define SSHD_SERVICE "sshd.service" + #endif + ++#ifndef SSHD_SOCKET ++#define SSHD_SOCKET "sshd.socket" ++#endif ++ ++typedef enum { ++ CC_SYSTEMD_UNIT_UNKNOWN, ++ CC_SYSTEMD_UNIT_SSHD_SERVICE, ++ CC_SYSTEMD_UNIT_SSHD_SOCKET, ++} CcSystemdUnit; ++ ++typedef enum { ++ CC_SYSTEMD_SERVICE_STATE_UNKNOWN, ++ CC_SYSTEMD_SERVICE_STATE_DISABLED, ++ CC_SYSTEMD_SERVICE_STATE_ENABLED_AND_ACTIVE, ++} CcSystemdServiceState; ++ ++typedef struct ++{ ++ CcSystemdUnit unit; ++ CcSystemdServiceState state; ++} CcSystemdService; ++ ++#define CC_CONTAINER_OF(ptr, type, member) \ ++ ((type *) ((guint8 *) (ptr) - G_STRUCT_OFFSET (type, member))) ++ ++#define CC_SYSTEMD_SERVICE_UNIT_NAME(service) \ ++ ((service)->unit == CC_SYSTEMD_UNIT_SSHD_SERVICE ? SSHD_SERVICE : \ ++ (service)->unit == CC_SYSTEMD_UNIT_SSHD_SOCKET ? SSHD_SOCKET : "UNKNOWN") ++ + typedef struct + { + AdwSwitchRow *widget; + GtkWidget *row; + GCancellable *cancellable; ++ CcSystemdService sshd_service; ++ CcSystemdService sshd_socket; + } CallbackData; + + G_DEFINE_AUTOPTR_CLEANUP_FUNC (CallbackData, g_free) + + static void ++cc_systemd_service_cleanup (CcSystemdService *service) ++{ ++ CallbackData *callback_data; ++ ++ if (service->unit == CC_SYSTEMD_UNIT_SSHD_SERVICE) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_service); ++ } ++ else if (service->unit == CC_SYSTEMD_UNIT_SSHD_SOCKET) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_socket); ++ } ++ else ++ { ++ g_assert_not_reached (); ++ } ++ ++ service->unit = CC_SYSTEMD_UNIT_UNKNOWN; ++ ++ if (callback_data->sshd_service.unit == CC_SYSTEMD_UNIT_UNKNOWN && ++ callback_data->sshd_socket.unit == CC_SYSTEMD_UNIT_UNKNOWN) ++ { ++ g_free(callback_data); ++ } ++} ++ ++G_DEFINE_AUTOPTR_CLEANUP_FUNC (CcSystemdService, cc_systemd_service_cleanup) ++ ++static void ++state_ready_callback (GObject *source_object, ++ GAsyncResult *result, ++ gpointer user_data); ++ ++static void + set_switch_state (AdwSwitchRow *widget, + gboolean active) + { +@@ -52,7 +117,8 @@ + GAsyncResult *result, + gpointer user_data) + { +- g_autoptr(CallbackData) callback_data = user_data; ++ CallbackData *callback_data; ++ g_autoptr(CcSystemdService) service = user_data; + g_autoptr(GVariant) active_variant = NULL; + g_autoptr(GVariant) child_variant = NULL; + g_autoptr(GVariant) tmp_variant = NULL; +@@ -75,15 +141,51 @@ + return; + } + ++ if (service->unit == CC_SYSTEMD_UNIT_SSHD_SERVICE) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_service); ++ } ++ else if (service->unit == CC_SYSTEMD_UNIT_SSHD_SOCKET) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_socket); ++ } ++ else ++ { ++ g_assert_not_reached (); ++ } ++ + child_variant = g_variant_get_child_value (active_variant, 0); + tmp_variant = g_variant_get_variant (child_variant); + active_state = g_variant_get_string (tmp_variant, NULL); + + active = g_str_equal (active_state, "active"); + +- /* set the switch to the correct state */ +- if (callback_data->widget) +- set_switch_state (callback_data->widget, active); ++ if (active) ++ { ++ g_debug ("%s is active...", CC_SYSTEMD_SERVICE_UNIT_NAME (service)); ++ service->state = CC_SYSTEMD_SERVICE_STATE_ENABLED_AND_ACTIVE; ++ } ++ else ++ { ++ g_debug ("%s is not active...", CC_SYSTEMD_SERVICE_UNIT_NAME (service)); ++ service->state = CC_SYSTEMD_SERVICE_STATE_DISABLED; ++ } ++ ++ /* if we now have states for both the service and the socket, then we can ++ * set the switch state */ ++ if (callback_data->sshd_service.state != CC_SYSTEMD_SERVICE_STATE_UNKNOWN && ++ callback_data->sshd_socket.state != CC_SYSTEMD_SERVICE_STATE_UNKNOWN) ++ { ++ gboolean active = (callback_data->sshd_service.state == CC_SYSTEMD_SERVICE_STATE_ENABLED_AND_ACTIVE || ++ callback_data->sshd_socket.state == CC_SYSTEMD_SERVICE_STATE_ENABLED_AND_ACTIVE); ++ ++ /* set the switch to the correct state */ ++ if (callback_data->widget) ++ { ++ g_debug ("Setting switch state for %s: %d", CC_SYSTEMD_SERVICE_UNIT_NAME (service), active); ++ set_switch_state (callback_data->widget, active); ++ } ++ } + } + + static void +@@ -91,12 +193,26 @@ + GAsyncResult *result, + gpointer user_data) + { +- g_autoptr(CallbackData) callback_data = user_data; ++ CallbackData *callback_data; ++ g_autoptr(CcSystemdService) service = user_data; + g_autoptr(GVariant) path_variant = NULL; + g_autoptr(GVariant) child_variant = NULL; + const gchar *object_path; + g_autoptr(GError) error = NULL; + ++ if (service->unit == CC_SYSTEMD_UNIT_SSHD_SERVICE) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_service); ++ } ++ else if (service->unit == CC_SYSTEMD_UNIT_SSHD_SOCKET) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_socket); ++ } ++ else ++ { ++ g_assert_not_reached (); ++ } ++ + path_variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), + result, &error); + +@@ -131,8 +247,8 @@ + -1, + callback_data->cancellable, + active_state_ready_callback, +- callback_data); +- g_steal_pointer (&callback_data); ++ service); ++ g_steal_pointer (&service); + } + + static void +@@ -140,12 +256,26 @@ + GAsyncResult *result, + gpointer user_data) + { +- g_autoptr(CallbackData) callback_data = user_data; ++ CallbackData *callback_data; ++ g_autoptr(CcSystemdService) service = user_data; + g_autoptr(GVariant) state_variant = NULL; + g_autoptr(GVariant) child_variant = NULL; + const gchar *state_string; + g_autoptr(GError) error = NULL; + ++ if (service->unit == CC_SYSTEMD_UNIT_SSHD_SERVICE) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_service); ++ } ++ else if (service->unit == CC_SYSTEMD_UNIT_SSHD_SOCKET) ++ { ++ callback_data = CC_CONTAINER_OF (service, CallbackData, sshd_socket); ++ } ++ else ++ { ++ g_assert_not_reached (); ++ } ++ + state_variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), + result, &error); + if (!state_variant) +@@ -156,9 +286,13 @@ + /* this may fail if systemd or remote login service is not available */ + g_debug ("Error getting remote login state: %s", error->message); + ++ + /* hide the remote login row, since the service is not available */ + if (callback_data->row) +- gtk_widget_set_visible (callback_data->row, FALSE); ++ { ++ g_debug ("Setting widget visibility FALSE for %s", CC_SYSTEMD_SERVICE_UNIT_NAME (service)); ++ gtk_widget_set_visible (callback_data->row, FALSE); ++ } + + return; + } +@@ -168,30 +302,46 @@ + + if (g_str_equal (state_string, "enabled")) + { ++ g_debug ("%s is enabled - checking if running...", CC_SYSTEMD_SERVICE_UNIT_NAME (service)); + /* service is enabled, so check whether it is running or not */ + g_dbus_connection_call (G_DBUS_CONNECTION (source_object), + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnit", +- g_variant_new ("(s)", SSHD_SERVICE), ++ g_variant_new ("(s)", CC_SYSTEMD_SERVICE_UNIT_NAME (service)), + (GVariantType*) "(o)", + G_DBUS_CALL_FLAGS_NONE, + -1, + callback_data->cancellable, + path_ready_callback, +- callback_data); +- g_steal_pointer (&callback_data); ++ service); ++ g_steal_pointer (&service); + } + else if (g_str_equal (state_string, "disabled")) + { +- /* service is available, but is currently disabled */ +- set_switch_state (callback_data->widget, FALSE); ++ g_debug ("%s is disabled...", CC_SYSTEMD_SERVICE_UNIT_NAME (service)); ++ service->state = CC_SYSTEMD_SERVICE_STATE_DISABLED; ++ /* if we now have states for both the service and the socket, then we can ++ * set the switch state */ ++ if (callback_data->sshd_service.state != CC_SYSTEMD_SERVICE_STATE_UNKNOWN && ++ callback_data->sshd_socket.state != CC_SYSTEMD_SERVICE_STATE_UNKNOWN) ++ { ++ gboolean active = (callback_data->sshd_service.state == CC_SYSTEMD_SERVICE_STATE_ENABLED_AND_ACTIVE || ++ callback_data->sshd_socket.state == CC_SYSTEMD_SERVICE_STATE_ENABLED_AND_ACTIVE); ++ ++ /* set the switch to the correct state */ ++ if (callback_data->widget) ++ { ++ g_debug ("Setting switch state for %s: %d", CC_SYSTEMD_SERVICE_UNIT_NAME (service), active); ++ set_switch_state (callback_data->widget, active); ++ } ++ } + } + else + { + /* unknown state */ +- g_warning ("Unknown state %s for %s", state_string, SSHD_SERVICE); ++ g_warning ("Unknown state %s for %s", state_string, CC_SYSTEMD_SERVICE_UNIT_NAME (service)); + } + } + +@@ -225,7 +375,19 @@ + -1, + callback_data->cancellable, + state_ready_callback, +- callback_data); ++ &callback_data->sshd_service); ++ g_dbus_connection_call (connection, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "GetUnitFileState", ++ g_variant_new ("(s)", SSHD_SOCKET), ++ (GVariantType*) "(s)", ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ callback_data->cancellable, ++ state_ready_callback, ++ &callback_data->sshd_socket); + g_steal_pointer (&callback_data); + } + +@@ -243,6 +405,10 @@ + callback_data->widget = widget; + callback_data->row = row; + callback_data->cancellable = cancellable; ++ callback_data->sshd_service.unit = CC_SYSTEMD_UNIT_SSHD_SERVICE; ++ callback_data->sshd_service.state = CC_SYSTEMD_SERVICE_STATE_UNKNOWN; ++ callback_data->sshd_socket.unit = CC_SYSTEMD_UNIT_SSHD_SOCKET; ++ callback_data->sshd_socket.state = CC_SYSTEMD_SERVICE_STATE_UNKNOWN; + + g_bus_get (G_BUS_TYPE_SYSTEM, callback_data->cancellable, + bus_ready_callback, callback_data); +--- a/panels/sharing/cc-remote-login-helper.c ++++ b/panels/sharing/cc-remote-login-helper.c +@@ -25,6 +25,10 @@ + #define SSHD_SERVICE "sshd.service" + #endif + ++#ifndef SSHD_SOCKET ++#define SSHD_SOCKET "sshd.socket" ++#endif ++ + int + main (int argc, + char **argv) +@@ -39,11 +43,18 @@ + { + g_autoptr(GError) error = NULL; + +- if (!cc_enable_service (SSHD_SERVICE, G_BUS_TYPE_SYSTEM, &error)) ++ /* on lunar+ we want to ensure the service is disabled and enable the ++ socket to match the default behaviour */ ++ if (!cc_disable_service (SSHD_SERVICE, G_BUS_TYPE_SYSTEM, &error)) + { + g_critical ("Failed to enable %s: %s", SSHD_SERVICE, error->message); + return EXIT_FAILURE; + } ++ else if (!cc_enable_service (SSHD_SOCKET, G_BUS_TYPE_SYSTEM, &error)) ++ { ++ g_critical ("Failed to enable %s: %s", SSHD_SOCKET, error->message); ++ return EXIT_FAILURE; ++ } + else + { + return EXIT_SUCCESS; +@@ -55,7 +66,12 @@ + + if (!cc_disable_service (SSHD_SERVICE, G_BUS_TYPE_SYSTEM, &error)) + { +- g_critical ("Failed to enable %s: %s", SSHD_SERVICE, error->message); ++ g_critical ("Failed to disable %s: %s", SSHD_SERVICE, error->message); ++ return EXIT_FAILURE; ++ } ++ else if (!cc_disable_service (SSHD_SOCKET, G_BUS_TYPE_SYSTEM, &error)) ++ { ++ g_critical ("Failed to disable %s: %s", SSHD_SOCKET, error->message); + return EXIT_FAILURE; + } + else diff -Nru gnome-control-center-45.0/debian/rules gnome-control-center-45.0/debian/rules --- gnome-control-center-45.0/debian/rules 2023-10-10 20:20:37.000000000 +1030 +++ gnome-control-center-45.0/debian/rules 2023-11-20 14:22:06.000000000 +1030 @@ -1,7 +1,7 @@ #!/usr/bin/make -f export DEB_BUILD_MAINT_OPTIONS = hardening=+all -export DEB_CPPFLAGS_MAINT_APPEND = -DSSHD_SERVICE=\"ssh.service\" +export DEB_CPPFLAGS_MAINT_APPEND = -DSSHD_SERVICE=\"ssh.service\" -DSSHD_SOCKET=\"ssh.socket\" export DEB_LDFLAGS_MAINT_APPEND = -Wl,-O1 -Wl,-z,defs # Not in Ubuntu main yet https://launchpad.net/bugs/1892456