Projects
Mega:24.09
dbus
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
_service:tar_scm:dbus.spec
Changed
@@ -1,7 +1,7 @@ Name: dbus Epoch: 1 Version: 1.14.8 -Release: 2 +Release: 3 Summary: System Message Bus License: AFLv3.0 or GPLv2+ URL: http://www.freedesktop.org/Software/dbus/ @@ -13,6 +13,10 @@ Patch6001: backport-tools-Use-Python3-for-GetAllMatchRules.patch Patch6002: backport-Do-not-crash-when-reloading-configuration.patch +Patch6003: backport-bus-Don-t-crash-if-bus_context_create_client_policy-.patch +Patch6004: backport-bus-When-failing-to-reload-client-policy-continue-it.patch +Patch6005: backport-test-Add-a-targeted-test-for-_dbus_unix_groups_from_.patch +Patch6006: backport-userdb-Add-proper-error-reporting-when-getting-group.patch BuildRequires: systemd-devel expat-devel libselinux-devel audit-libs-devel doxygen xmlto cmake BuildRequires: autoconf-archive libtool libX11-devel libcap-ng-devel libxslt @@ -93,6 +97,9 @@ %autosetup -n %{name}-%{version} -p1 %build +# We need to use autoreconf to recreate aclocal.m4, When automake's version mismatch. +autoreconf -vfi + %configure \ --disable-static \ --enable-inotify \ @@ -225,6 +232,13 @@ %exclude %{_pkgdocdir}/README %changelog +* Wed Jul 31 2024 hongjinghao <hongjinghao@huawei.com> - 1:1.14.8-3 +- sync patch from upstream + backport-bus-Don-t-crash-if-bus_context_create_client_policy-.patch + backport-bus-When-failing-to-reload-client-policy-continue-it.patch + backport-test-Add-a-targeted-test-for-_dbus_unix_groups_from_.patch + backport-userdb-Add-proper-error-reporting-when-getting-group.patch + * Wed Feb 21 2024 hongjinghao <hongjinghao@huawei.com> - 1:1.14.8-2 - add backport-Do-not-crash-when-reloading-configuration.patch
View file
_service:tar_scm:backport-bus-Don-t-crash-if-bus_context_create_client_policy-.patch
Added
@@ -0,0 +1,74 @@ +From 678e73bfd034f2d32dde5ffd1c6b63c456989541 Mon Sep 17 00:00:00 2001 +From: Peter Benie <pjb1008> +Date: Fri, 23 Jun 2023 11:51:00 +0100 +Subject: PATCH bus: Don't crash if bus_context_create_client_policy() fails + +If policy creation fails, we can't usefully leave a NULL policy in the +BusConnectionData. If we did, the next attempt to reload policy would +crash with a NULL dereference when we tried to unref it, or with +an assertion failure. + +One situation in which we can legitimately fail to create a client policy +is an out-of-memory condition. Another is if we are unable to look up a +connection's supplementary groups with SO_PEERGROUPS, and also unable to +look up the connection's uid's groups in the system user database, for +example because it belongs to a user account that has been deleted (which +is sysadmin error, but can happen, particularly in automated test systems) +or because a service required by a Name Service Switch plugin has failed. + +Keeping the last known policy is consistent with what happens to all +the connections that are after this one in iteration order: after we +early-return, all of those connections retain their previous policies +(which doesn't seem ideal either, but that's how this has always worked). + +smcv: Add commit message +Co-authored-by: Simon McVittie <smcv@collabora.com> +Resolves: https://gitlab.freedesktop.org/dbus/dbus/-/issues/343 + +Conflict:NA +Reference:https://gitlab.freedesktop.org/dbus/dbus/-/commit/678e73bfd034f2d32dde5ffd1c6b63c456989541 + +(cherry picked from commit 63522f2887878e6b9e40c9bb6742484679631ea9) +--- + bus/connection.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/bus/connection.c b/bus/connection.c +index 215f0230..7a482e2b 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -1636,22 +1636,26 @@ bus_connections_reload_policy (BusConnections *connections, + link; + link = _dbus_list_get_next_link (&(connections->completed), link)) + { ++ BusClientPolicy *policy; ++ + connection = link->data; + d = BUS_CONNECTION_DATA (connection); + _dbus_assert (d != NULL); + _dbus_assert (d->policy != NULL); + +- bus_client_policy_unref (d->policy); +- d->policy = bus_context_create_client_policy (connections->context, +- connection, +- error); +- if (d->policy == NULL) ++ policy = bus_context_create_client_policy (connections->context, ++ connection, ++ error); ++ if (policy == NULL) + { + _dbus_verbose ("Failed to create security policy for connection %p\n", + connection); + _DBUS_ASSERT_ERROR_IS_SET (error); + return FALSE; + } ++ ++ bus_client_policy_unref (d->policy); ++ d->policy = policy; + } + + return TRUE; +-- +2.27.0 +
View file
_service:tar_scm:backport-bus-When-failing-to-reload-client-policy-continue-it.patch
Added
@@ -0,0 +1,115 @@ +From b14c778eb5156f649610804bc4ce3a762aa2b58b Mon Sep 17 00:00:00 2001 +From: Simon McVittie <smcv@collabora.com> +Date: Thu, 29 Jun 2023 19:52:39 +0100 +Subject: PATCH bus: When failing to reload client policy, continue iteration + +If we have a large number of connections to the bus, and we fail to +reload the policy for one of them (perhaps because its uid no longer +exists in the system user database), previously we would crash, which +is obviously unintended. After the previous commit, we would stop +iteration through the list of client connections, which doesn't seem +great either: one bad connection shouldn't prevent us from reloading +the rest of our state. + +Instead, let's distinguish between new connections (where we want +failure to establish a security policy to be fatal), and pre-existing +connections (where the current security policy is presumably good +enough to keep using if we have nothing better). If we're unable to +reload the policy for a pre-existing connection, log a warning and +carry on iterating. + +Helps: https://gitlab.freedesktop.org/dbus/dbus/-/issues/343 +Signed-off-by: Simon McVittie <smcv@collabora.com> + +Conflict:NA +Reference:https://gitlab.freedesktop.org/dbus/dbus/-/commit/b14c778eb5156f649610804bc4ce3a762aa2b58b +--- + bus/bus.c | 35 +++++++++++++++++++++++++++++++++-- + bus/bus.h | 1 + + bus/connection.c | 2 ++ + 3 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/bus/bus.c b/bus/bus.c +index 2ad8e789..f5100739 100644 +--- a/bus/bus.c ++++ b/bus/bus.c +@@ -1285,11 +1285,42 @@ bus_context_get_policy (BusContext *context) + BusClientPolicy* + bus_context_create_client_policy (BusContext *context, + DBusConnection *connection, ++ BusClientPolicy *previous, + DBusError *error) + { ++ BusClientPolicy *client; ++ DBusError local_error = DBUS_ERROR_INIT; ++ const char *conn; ++ const char *loginfo; ++ + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +- return bus_policy_create_client_policy (context->policy, connection, +- error); ++ ++ client = bus_policy_create_client_policy (context->policy, connection, ++ &local_error); ++ ++ /* On success, use new policy */ ++ if (client != NULL) ++ return client; ++ ++ /* On failure while setting up a new connection, fail */ ++ if (previous == NULL) ++ { ++ dbus_move_error (&local_error, error); ++ return NULL; ++ } ++ ++ /* On failure while reloading, keep the previous policy */ ++ conn = bus_connection_get_name (connection); ++ loginfo = bus_connection_get_loginfo (connection); ++ ++ if (conn == NULL) ++ conn = "(inactive)"; ++ ++ bus_context_log (context, DBUS_SYSTEM_LOG_WARNING, ++ "Unable to reload policy for connection \"%s\" (%s), " ++ "keeping current policy: %s", ++ conn, loginfo, local_error.message); ++ return bus_client_policy_ref (previous); + } + + int +diff --git a/bus/bus.h b/bus/bus.h +index 2e0de825..6ebea2c8 100644 +--- a/bus/bus.h ++++ b/bus/bus.h +@@ -109,6 +109,7 @@ BusPolicy* bus_context_get_policy (BusContext + + BusClientPolicy* bus_context_create_client_policy (BusContext *context, + DBusConnection *connection, ++ BusClientPolicy *previous, + DBusError *error); + int bus_context_get_activation_timeout (BusContext *context); + int bus_context_get_auth_timeout (BusContext *context); +diff --git a/bus/connection.c b/bus/connection.c +index 8a8ce5f4..b7439296 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -1560,6 +1560,7 @@ bus_connection_complete (DBusConnection *connection, + + d->policy = bus_context_create_client_policy (d->connections->context, + connection, ++ NULL, + error); + + /* we may have a NULL policy on OOM or error getting list of +@@ -1645,6 +1646,7 @@ bus_connections_reload_policy (BusConnections *connections, + + policy = bus_context_create_client_policy (connections->context, + connection, ++ d->policy, + error); + if (policy == NULL) + { +-- +2.27.0 +
View file
_service:tar_scm:backport-test-Add-a-targeted-test-for-_dbus_unix_groups_from_.patch
Added
@@ -0,0 +1,190 @@ +From 5337c629e945dec1b53884aa16daceb0500dea9b Mon Sep 17 00:00:00 2001 +From: Simon McVittie <smcv@collabora.com> +Date: Thu, 29 Jun 2023 16:54:46 +0100 +Subject: PATCH test: Add a targeted test for _dbus_unix_groups_from_uid() + +Helps: https://gitlab.freedesktop.org/dbus/dbus/-/issues/343 +Signed-off-by: Simon McVittie <smcv@collabora.com> + +Conflict:Adapt context +Reference:https://gitlab.freedesktop.org/dbus/dbus/-/commit/5337c629e945dec1b53884aa16daceb0500dea9b +--- + test/Makefile.am | 4 ++ + test/internals/userdb.c | 143 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 147 insertions(+) + create mode 100644 test/internals/userdb.c + +diff --git a/test/Makefile.am b/test/Makefile.am +index 3bbf7f73..ffba702a 100644 +--- a/test/Makefile.am ++++ b/test/Makefile.am +@@ -121,6 +121,9 @@ test_server_oom_LDADD = libdbus-testutils.la $(GLIB_LIBS) + test_syslog_SOURCES = internals/syslog.c + test_syslog_LDADD = libdbus-testutils.la $(GLIB_LIBS) + ++test_userdb_SOURCES = internals/userdb.c ++test_userdb_LDADD = libdbus-testutils.la $(GLIB_LIBS) ++ + test_variant_SOURCES = internals/variant.c + test_variant_LDADD = libdbus-testutils.la $(GLIB_LIBS) + +@@ -181,6 +184,7 @@ installable_tests += \ + test-sysdeps \ + test-syslog \ + test-uid-permissions \ ++ test-userdb \ + test-variant \ + $(NULL) + +diff --git a/test/internals/userdb.c b/test/internals/userdb.c +new file mode 100644 +index 00000000..905791b3 +--- /dev/null ++++ b/test/internals/userdb.c +@@ -0,0 +1,143 @@ ++/* ++ * Copyright © 2023 Collabora Ltd. ++ * SPDX-License-Identifier: MIT ++ */ ++ ++#include <config.h> ++ ++#include <glib.h> ++ ++#include <dbus/dbus.h> ++#include "dbus/dbus-sysdeps.h" ++#include "test-utils-glib.h" ++ ++#ifdef DBUS_UNIX ++#include <errno.h> ++#include <pwd.h> ++#include <sys/types.h> ++#include <unistd.h> ++ ++#include "dbus/dbus-sysdeps-unix.h" ++#include "dbus/dbus-userdb.h" ++#endif ++ ++typedef struct ++{ ++ int dummy; ++} Fixture; ++ ++static void ++setup (Fixture *f G_GNUC_UNUSED, ++ gconstpointer context G_GNUC_UNUSED) ++{ ++} ++ ++static void ++test_groups_from_uid (Fixture *f, ++ gconstpointer context G_GNUC_UNUSED) ++{ ++ DBusError error = DBUS_ERROR_INIT; ++ dbus_gid_t *gids = NULL; ++ int n_gids = -1; ++ dbus_bool_t ret; ++#ifdef DBUS_UNIX ++ int i; ++#endif ++ ++ /* We assume that uid 0 (root) is available on all Unix systems, ++ * so this should succeed */ ++ ret = _dbus_unix_groups_from_uid (0, &gids, &n_gids, &error); ++ ++#ifdef DBUS_UNIX ++ test_assert_no_error (&error); ++ g_assert_true (ret); ++ g_assert_cmpint (n_gids, >=, 0); ++ ++ g_test_message ("Groups of uid 0:"); ++ ++ for (i = 0; i < n_gids; i++) ++ { ++ g_test_message ("%d: %ld", i, (long) gidsi); ++ g_assert_cmpint (gidsi, >=, 0); ++ } ++#else ++ g_assert_cmpstr (error.name, ==, DBUS_ERROR_NOT_SUPPORTED); ++ g_assert_false (ret); ++ g_test_message ("Getting Unix groups on Windows failed as expected: %s: %s", ++ error.name, error.message); ++ g_assert_null (gids); ++ g_assert_cmpint (n_gids, <=, 0); ++#endif ++ ++ dbus_free (gids); ++ dbus_error_free (&error); ++ ++#ifdef DBUS_UNIX ++ /* Assume that the current uid is something sensible */ ++ ret = _dbus_unix_groups_from_uid (geteuid (), &gids, &n_gids, &error); ++ test_assert_no_error (&error); ++ g_assert_true (ret); ++ g_assert_cmpint (n_gids, >=, 0); ++ ++ g_test_message ("Groups of uid %ld:", (long) geteuid ()); ++ ++ for (i = 0; i < n_gids; i++) ++ { ++ g_test_message ("%d: %ld", i, (long) gidsi); ++ g_assert_cmpint (gidsi, >=, 0); ++ } ++ ++ g_test_message ("Total: %i groups", n_gids); ++ ++ dbus_free (gids); ++ dbus_error_free (&error); ++ ++ errno = 0; ++ ++ /* arbitrarily chosen, probably isn't a valid uid */ ++ if (getpwuid (31337) == NULL) ++ { ++ g_test_message ("uid 31337 doesn't exist: %s", ++ errno == 0 ? "(no errno)" : g_strerror (errno)); ++ ret = _dbus_unix_groups_from_uid (31337, &gids, &n_gids, &error); ++ g_assert_nonnull (error.name); ++ g_assert_nonnull (error.message); ++ g_assert_false (ret); ++ g_test_message ("Getting groups from non-uid failed as expected: %s: %s", ++ error.name, error.message); ++ /* The Unix implementation always clears gids/n_gids, ++ * even on failure, and even if they were uninitialized */ ++ g_assert_null (gids); ++ g_assert_cmpint (n_gids, ==, 0); ++ ++ dbus_free (gids); ++ dbus_error_free (&error); ++ } ++ else ++ { ++ g_test_skip ("against our expectations, uid 31337 exists on this system"); ++ } ++#endif ++} ++ ++static void ++teardown (Fixture *f G_GNUC_UNUSED, ++ gconstpointer context G_GNUC_UNUSED) ++{ ++} ++ ++int ++main (int argc, ++ char **argv) ++{ ++ int ret; ++ ++ test_init (&argc, &argv); ++ ++ g_test_add ("/userdb/groups_from_uid", ++ Fixture, NULL, setup, test_groups_from_uid, teardown); ++ ++ ret = g_test_run (); ++ dbus_shutdown (); ++ return ret; ++} +-- +2.27.0 +
View file
_service:tar_scm:backport-userdb-Add-proper-error-reporting-when-getting-group.patch
Added
@@ -0,0 +1,232 @@ +From fc757d494089b7e1e4e37b7eaaa798cd7e9ad391 Mon Sep 17 00:00:00 2001 +From: Simon McVittie <smcv@collabora.com> +Date: Thu, 29 Jun 2023 16:06:39 +0100 +Subject: PATCH userdb: Add proper error reporting when getting groups from a + uid + +Previously, if dbus_connection_get_unix_user() succeeded but +_dbus_unix_groups_from_uid() failed, then bus_connection_get_unix_groups() +would incorrectly fail without setting the error indicator, resulting +in "(null)" being logged, which is rather unhelpful. + +This also lets us distinguish between ENOMEM and other errors, such as +the uid not existing in the system's user database. + +Fixes: 145fb99b (untitled refactoring commit, 2006-12-12) +Helps: https://gitlab.freedesktop.org/dbus/dbus/-/issues/343 +Signed-off-by: Simon McVittie <smcv@collabora.com> + +Conflict:Adapt Context +Reference:https://gitlab.freedesktop.org/dbus/dbus/-/commit/fc757d494089b7e1e4e37b7eaaa798cd7e9ad391 +--- + bus/connection.c | 2 +- + bus/policy.c | 2 +- + dbus/dbus-sysdeps-util-unix.c | 6 ++++-- + dbus/dbus-sysdeps-util-win.c | 15 ++++++++++++--- + dbus/dbus-sysdeps.h | 3 ++- + dbus/dbus-userdb-util.c | 15 ++++++++++----- + dbus/dbus-userdb.h | 3 ++- + test/internals/misc-internals.c | 4 ++-- + 8 files changed, 34 insertions(+), 16 deletions(-) + +diff --git a/bus/connection.c b/bus/connection.c +index 557aaf6..b912d89 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -1079,7 +1079,7 @@ bus_connection_get_unix_groups (DBusConnection *connection, + + if (dbus_connection_get_unix_user (connection, &uid)) + { +- if (!_dbus_unix_groups_from_uid (uid, groups, n_groups)) ++ if (!_dbus_unix_groups_from_uid (uid, groups, n_groups, error)) + { + _dbus_verbose ("Did not get any groups for UID %lu\n", + uid); +diff --git a/bus/policy.c b/bus/policy.c +index 74cb41b..b6890c7 100644 +--- a/bus/policy.c ++++ b/bus/policy.c +@@ -450,7 +450,7 @@ bus_policy_allow_unix_user (BusPolicy *policy, + int n_group_ids; + + /* On OOM or error we always reject the user */ +- if (!_dbus_unix_groups_from_uid (uid, &group_ids, &n_group_ids)) ++ if (!_dbus_unix_groups_from_uid (uid, &group_ids, &n_group_ids, NULL)) + { + _dbus_verbose ("Did not get any groups for UID %lu\n", + uid); +diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c +index 9fe7d55..eb5654e 100644 +--- a/dbus/dbus-sysdeps-util-unix.c ++++ b/dbus/dbus-sysdeps-util-unix.c +@@ -992,14 +992,16 @@ _dbus_parse_unix_group_from_config (const DBusString *groupname, + * @param uid the UID + * @param group_ids return location for array of group IDs + * @param n_group_ids return location for length of returned array ++ * @param error error location + * @returns #TRUE if the UID existed and we got some credentials + */ + dbus_bool_t + _dbus_unix_groups_from_uid (dbus_uid_t uid, + dbus_gid_t **group_ids, +- int *n_group_ids) ++ int *n_group_ids, ++ DBusError *error) + { +- return _dbus_groups_from_uid (uid, group_ids, n_group_ids); ++ return _dbus_groups_from_uid (uid, group_ids, n_group_ids, error); + } + + /** +diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c +index c572fcd..5e4634f 100644 +--- a/dbus/dbus-sysdeps-util-win.c ++++ b/dbus/dbus-sysdeps-util-win.c +@@ -649,6 +649,13 @@ dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid) + unix emulation functions - should be removed sometime in the future + =====================================================================*/ + ++static void ++set_unix_uid_unsupported (DBusError *error) ++{ ++ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, ++ "UNIX user IDs not supported on Windows"); ++} ++ + /** + * Checks to see if the UNIX user ID is at the console. + * Should always fail on Windows (set the error to +@@ -662,8 +669,7 @@ dbus_bool_t + _dbus_unix_user_is_at_console (dbus_uid_t uid, + DBusError *error) + { +- dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, +- "UNIX user IDs not supported on Windows\n"); ++ set_unix_uid_unsupported (error); + return FALSE; + } + +@@ -707,13 +713,16 @@ _dbus_parse_unix_user_from_config (const DBusString *username, + * @param uid the UID + * @param group_ids return location for array of group IDs + * @param n_group_ids return location for length of returned array ++ * @param error error location + * @returns #TRUE if the UID existed and we got some credentials + */ + dbus_bool_t + _dbus_unix_groups_from_uid (dbus_uid_t uid, + dbus_gid_t **group_ids, +- int *n_group_ids) ++ int *n_group_ids, ++ DBusError *error) + { ++ set_unix_uid_unsupported (error); + return FALSE; + } + +diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h +index e7e36ad..3363733 100644 +--- a/dbus/dbus-sysdeps.h ++++ b/dbus/dbus-sysdeps.h +@@ -298,7 +298,8 @@ dbus_bool_t _dbus_parse_unix_group_from_config (const DBusString *groupname, + dbus_gid_t *gid_p); + dbus_bool_t _dbus_unix_groups_from_uid (dbus_uid_t uid, + dbus_gid_t **group_ids, +- int *n_group_ids); ++ int *n_group_ids, ++ DBusError *error); + dbus_bool_t _dbus_unix_user_is_at_console (dbus_uid_t uid, + DBusError *error); + dbus_bool_t _dbus_unix_user_is_process_owner (dbus_uid_t uid); +diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c +index 1ca21eb..0093ee4 100644 +--- a/dbus/dbus-userdb-util.c ++++ b/dbus/dbus-userdb-util.c +@@ -373,31 +373,35 @@ _dbus_user_database_lookup_group (DBusUserDatabase *db, + * @param uid the UID + * @param group_ids return location for array of group IDs + * @param n_group_ids return location for length of returned array ++ * @param error error to fill in on failure + * @returns #TRUE if the UID existed and we got some credentials + */ + dbus_bool_t + _dbus_groups_from_uid (dbus_uid_t uid, + dbus_gid_t **group_ids, +- int *n_group_ids) ++ int *n_group_ids, ++ DBusError *error) + { + DBusUserDatabase *db; + const DBusUserInfo *info; + *group_ids = NULL; + *n_group_ids = 0; + +- /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) +- return FALSE; ++ { ++ _DBUS_SET_OOM (error); ++ return FALSE; ++ } + + db = _dbus_user_database_get_system (); + if (db == NULL) + { ++ _DBUS_SET_OOM (error); + _dbus_user_database_unlock_system (); + return FALSE; + } + +- if (!_dbus_user_database_get_uid (db, uid, +- &info, NULL)) ++ if (!_dbus_user_database_get_uid (db, uid, &info, error)) + { + _dbus_user_database_unlock_system (); + return FALSE; +@@ -410,6 +414,7 @@ _dbus_groups_from_uid (dbus_uid_t uid, + *group_ids = dbus_new (dbus_gid_t, info->n_group_ids); + if (*group_ids == NULL) + { ++ _DBUS_SET_OOM (error); + _dbus_user_database_unlock_system (); + return FALSE; + } +diff --git a/dbus/dbus-userdb.h b/dbus/dbus-userdb.h +index fcb515c..9026caa 100644 +--- a/dbus/dbus-userdb.h ++++ b/dbus/dbus-userdb.h +@@ -100,7 +100,8 @@ dbus_bool_t _dbus_get_user_id_and_primary_group (const DBusString *username, + dbus_gid_t *gid_p);
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2