From 3e272c78feb5e0489cdd4b8f24d536bbb251075e Mon Sep 17 00:00:00 2001 From: zhangxianting Date: Mon, 1 Jul 2024 23:35:09 +0800 Subject: [PATCH] fix CVE-2024-36041 --- Authenticate-local-clients.patch | 127 ++++++++++ Remove-iceauth-dependency.patch | 404 +++++++++++++++++++++++++++++++ plasma-workspace.spec | 11 +- 3 files changed, 541 insertions(+), 1 deletion(-) create mode 100644 Authenticate-local-clients.patch create mode 100644 Remove-iceauth-dependency.patch diff --git a/Authenticate-local-clients.patch b/Authenticate-local-clients.patch new file mode 100644 index 0000000..f8fe58b --- /dev/null +++ b/Authenticate-local-clients.patch @@ -0,0 +1,127 @@ +From da843d3fdb143ed44094c8e6246cfb8305f6f09f Mon Sep 17 00:00:00 2001 +From: David Edmundson +Date: Sat, 13 Apr 2024 23:07:19 +0100 +Subject: [PATCH] Authenticate local clients + +ksmserver currently authenticates remote clients, but allows local +connections through. + +This is a security risk that can allow another user on the same system +to access the user's session management session without authentication. + +Co-authored-by: Fabian Vogt +--- + ksmserver/server.cpp | 57 ++++---------------------------------------- + 1 file changed, 5 insertions(+), 52 deletions(-) + +diff --git a/ksmserver/server.cpp b/ksmserver/server.cpp +index 8a408cf73b..62bb8fb74d 100644 +--- a/ksmserver/server.cpp ++++ b/ksmserver/server.cpp +@@ -158,15 +158,6 @@ static QTemporaryFile *remTempFile = nullptr; + + static IceListenObj *listenObjs = nullptr; + int numTransports = 0; +-static bool only_local = 0; +- +-static Bool HostBasedAuthProc(char * /*hostname*/) +-{ +- if (only_local) +- return true; +- else +- return false; +-} + + Status KSMRegisterClientProc(SmsConn /* smsConn */, SmPointer managerData, char *previousId) + { +@@ -311,33 +302,6 @@ static void write_iceauth(FILE *addfp, FILE *removefp, IceAuthDataEntry *entry) + + #define MAGIC_COOKIE_LEN 16 + +-Status SetAuthentication_local(int count, IceListenObj *listenObjs) +-{ +- int i; +- for (i = 0; i < count; i++) { +- char *prot = IceGetListenConnectionString(listenObjs[i]); +- if (!prot) +- continue; +- char *host = strchr(prot, '/'); +- char *sock = nullptr; +- if (host) { +- *host = 0; +- host++; +- sock = strchr(host, ':'); +- if (sock) { +- *sock = 0; +- sock++; +- } +- } +- qCDebug(KSMSERVER) << "KSMServer: SetAProc_loc: conn " << (unsigned)i << ", prot=" << prot << ", file=" << sock; +- if (sock && !strcmp(prot, "local")) { +- chmod(sock, 0700); +- } +- IceSetHostBasedAuthProc(listenObjs[i], HostBasedAuthProc); +- free(prot); +- } +- return 1; +-} + + Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry **authDataEntries) + { +@@ -372,8 +336,6 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry * + write_iceauth(addAuthFile, remAuthFile, &(*authDataEntries)[i + 1]); + + IceSetPaAuthData(2, &(*authDataEntries)[i]); +- +- IceSetHostBasedAuthProc(listenObjs[i / 2], HostBasedAuthProc); + } + fclose(addAuthFile); + fclose(remAuthFile); +@@ -397,9 +359,6 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry * + void FreeAuthenticationData(int count, IceAuthDataEntry *authDataEntries) + { + /* Each transport has entries for ICE and XSMP */ +- if (only_local) +- return; +- + for (int i = 0; i < count * 2; i++) { + free(authDataEntries[i].network_id); + free(authDataEntries[i].auth_data); +@@ -542,16 +501,14 @@ KSMServer::KSMServer(InitFlags flags) + clientInteracting = nullptr; + xonCommand = config.readEntry("xonCommand", "xon"); + +- only_local = flags.testFlag(InitFlag::OnlyLocal); + #ifdef HAVE__ICETRANSNOLISTEN +- if (only_local) ++ if (flags.testFlag(InitFlag::OnlyLocal)) { + _IceTransNoListen("tcp"); +-#else +- only_local = false; ++ } + #endif + + char errormsg[256]; +- if (!SmsInitialize((char *)KSMVendorString, (char *)KSMReleaseString, KSMNewClientProc, (SmPointer)this, HostBasedAuthProc, 256, errormsg)) { ++ if (!SmsInitialize((char *)KSMVendorString, (char *)KSMReleaseString, KSMNewClientProc, (SmPointer)this, nullptr, 256, errormsg)) { + qCWarning(KSMSERVER, "KSMServer: could not register XSM protocol"); + } + +@@ -594,12 +551,8 @@ KSMServer::KSMServer(InitFlags flags) + free(session_manager); + } + +- if (only_local) { +- if (!SetAuthentication_local(numTransports, listenObjs)) +- qFatal("KSMSERVER: authentication setup failed."); +- } else { +- if (!SetAuthentication(numTransports, listenObjs, &authDataEntries)) +- qFatal("KSMSERVER: authentication setup failed."); ++ if (!SetAuthentication(numTransports, listenObjs, &authDataEntries)) { ++ qFatal("KSMSERVER: authentication setup failed."); + } + + IceAddConnectionWatch(KSMWatchProc, (IcePointer)this); +-- +GitLab + diff --git a/Remove-iceauth-dependency.patch b/Remove-iceauth-dependency.patch new file mode 100644 index 0000000..98c5b3b --- /dev/null +++ b/Remove-iceauth-dependency.patch @@ -0,0 +1,404 @@ +From 1d5aa1d27bff87b2d242ed759cfb2ce15a5c3de7 Mon Sep 17 00:00:00 2001 +From: David Edmundson +Date: Sat, 13 Apr 2024 23:30:34 +0100 +Subject: [PATCH] Remove iceauth dependency + +Previously the tool iceauth was used to write authentication to and from +the iceauthority file, running a set of commands to manipulate the file. + +This external dependency is not often installed, which may create a +problem +now that all paths go through authentication. If iceauth is not +currently installed +ksmserver will assert rendering the session useless. + +This patch writes and manages the file directly removing the need for +external tools. + +Co-authored-by: Fabian Vogt +--- + ksmserver/server.cpp | 281 ++++++++++++++++++++++--------------------- + ksmserver/server.h | 2 + + 2 files changed, 148 insertions(+), 135 deletions(-) + +diff --git a/ksmserver/server.cpp b/ksmserver/server.cpp +index 62bb8fb74d..f88de40dba 100644 +--- a/ksmserver/server.cpp ++++ b/ksmserver/server.cpp +@@ -54,6 +54,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -287,37 +288,34 @@ static void fprintfhex(FILE *fp, unsigned int len, char *cp) + } + } + +-/* +- * We use temporary files which contain commands to add/remove entries from +- * the .ICEauthority file. +- */ +-static void write_iceauth(FILE *addfp, FILE *removefp, IceAuthDataEntry *entry) +-{ +- fprintf(addfp, "add %s \"\" %s %s ", entry->protocol_name, entry->network_id, entry->auth_name); +- fprintfhex(addfp, entry->auth_data_length, entry->auth_data); +- fprintf(addfp, "\n"); +- +- fprintf(removefp, "remove protoname=%s protodata=\"\" netid=%s authname=%s\n", entry->protocol_name, entry->network_id, entry->auth_name); +-} +- + #define MAGIC_COOKIE_LEN 16 + +- + Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry **authDataEntries) + { +- QTemporaryFile addTempFile; +- remTempFile = new QTemporaryFile; ++ char *filename = IceAuthFileName(); ++ FILE *fp; + +- if (!addTempFile.open() || !remTempFile->open()) ++ if (IceLockAuthFile(filename, 10, 2, 600) != IceAuthLockSuccess) { ++ qWarning() << "Could not lock ICEAuthority file"; + return 0; ++ } ++ auto cleanup = qScopeGuard([filename]() { ++ IceUnlockAuthFile(filename); ++ }); + +- if ((*authDataEntries = (IceAuthDataEntry *)malloc(count * 2 * sizeof(IceAuthDataEntry))) == nullptr) ++ if ((fp = fopen(filename, "ab")) == NULL) { ++ qWarning() << "Could not open ICEAuthority file"; + return 0; ++ } + +- FILE *addAuthFile = fopen(QFile::encodeName(addTempFile.fileName()).constData(), "r+"); +- FILE *remAuthFile = fopen(QFile::encodeName(remTempFile->fileName()).constData(), "r+"); ++ if ((*authDataEntries = (IceAuthDataEntry *)malloc(count * 2 * sizeof(IceAuthDataEntry))) == nullptr) { ++ (void)fclose(fp); ++ return 0; ++ } + + for (int i = 0; i < numTransports * 2; i += 2) { ++ // ICE Auth Data ++ + (*authDataEntries)[i].network_id = IceGetListenConnectionString(listenObjs[i / 2]); + (*authDataEntries)[i].protocol_name = (char *)"ICE"; + (*authDataEntries)[i].auth_name = (char *)"MIT-MAGIC-COOKIE-1"; +@@ -325,6 +323,23 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry * + (*authDataEntries)[i].auth_data = IceGenerateMagicCookie(MAGIC_COOKIE_LEN); + (*authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN; + ++ // ICE Auth File ++ { ++ IceAuthFileEntry *file_entry = (IceAuthFileEntry *)malloc(sizeof(IceAuthFileEntry)); ++ file_entry->protocol_name = strdup("ICE"); ++ file_entry->protocol_data = NULL; ++ file_entry->protocol_data_length = 0; ++ file_entry->network_id = IceGetListenConnectionString(listenObjs[i / 2]); ++ file_entry->auth_name = strdup("MIT-MAGIC-COOKIE-1"); ++ file_entry->auth_data = strdup((*authDataEntries)[i].auth_data); ++ file_entry->auth_data_length = MAGIC_COOKIE_LEN; ++ if (IceWriteAuthFileEntry(fp, file_entry) != 0) { ++ qWarning("Failed to write ice auth file entry"); ++ } ++ IceFreeAuthFileEntry(file_entry); ++ } ++ ++ // XSMP Auth Data + (*authDataEntries)[i + 1].network_id = IceGetListenConnectionString(listenObjs[i / 2]); + (*authDataEntries)[i + 1].protocol_name = (char *)"XSMP"; + (*authDataEntries)[i + 1].auth_name = (char *)"MIT-MAGIC-COOKIE-1"; +@@ -332,141 +347,127 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry * + (*authDataEntries)[i + 1].auth_data = IceGenerateMagicCookie(MAGIC_COOKIE_LEN); + (*authDataEntries)[i + 1].auth_data_length = MAGIC_COOKIE_LEN; + +- write_iceauth(addAuthFile, remAuthFile, &(*authDataEntries)[i]); +- write_iceauth(addAuthFile, remAuthFile, &(*authDataEntries)[i + 1]); ++ // XSMP Auth file ++ { ++ IceAuthFileEntry *file_entry = (IceAuthFileEntry *)malloc(sizeof(IceAuthFileEntry)); ++ file_entry->protocol_name = strdup("XSMP"); ++ file_entry->protocol_data = NULL; ++ file_entry->protocol_data_length = 0; ++ file_entry->network_id = IceGetListenConnectionString(listenObjs[i / 2]); ++ file_entry->auth_name = strdup("MIT-MAGIC-COOKIE-1"); ++ file_entry->auth_data = strdup((*authDataEntries)[i + 1].auth_data); ++ file_entry->auth_data_length = MAGIC_COOKIE_LEN; ++ if (IceWriteAuthFileEntry(fp, file_entry) != 0) { ++ qWarning("Failed to write xsmp ice auth file entry"); ++ } ++ IceFreeAuthFileEntry(file_entry); ++ } + + IceSetPaAuthData(2, &(*authDataEntries)[i]); + } +- fclose(addAuthFile); +- fclose(remAuthFile); +- +- QString iceAuth = QStandardPaths::findExecutable(QStringLiteral("iceauth")); +- if (iceAuth.isEmpty()) { +- qCWarning(KSMSERVER, "KSMServer: could not find iceauth"); +- return 0; +- } +- +- KProcess p; +- p << iceAuth << QStringLiteral("source") << addTempFile.fileName(); +- p.execute(); + + return (1); + } + +-/* +- * Free up authentication data. +- */ +-void FreeAuthenticationData(int count, IceAuthDataEntry *authDataEntries) +-{ +- /* Each transport has entries for ICE and XSMP */ +- for (int i = 0; i < count * 2; i++) { +- free(authDataEntries[i].network_id); +- free(authDataEntries[i].auth_data); +- } +- +- free(authDataEntries); +- +- QString iceAuth = QStandardPaths::findExecutable(QStringLiteral("iceauth")); +- if (iceAuth.isEmpty()) { +- qCWarning(KSMSERVER, "KSMServer: could not find iceauth"); +- return; +- } ++ /* ++ * Free up authentication data. ++ */ ++ void FreeAuthenticationData(int count, IceAuthDataEntry *authDataEntries) ++ { ++ /* Each transport has entries for ICE and XSMP */ ++ for (int i = 0; i < count * 2; i++) { ++ free(authDataEntries[i].network_id); ++ free(authDataEntries[i].auth_data); ++ } + +- if (remTempFile) { +- KProcess p; +- p << iceAuth << QStringLiteral("source") << remTempFile->fileName(); +- p.execute(); +- } ++ free(authDataEntries); ++ } + +- delete remTempFile; +- remTempFile = nullptr; +-} ++ static int Xio_ErrorHandler(Display *) ++ { ++ qCWarning(KSMSERVER, "ksmserver: Fatal IO error: client killed"); + +-static int Xio_ErrorHandler(Display *) +-{ +- qCWarning(KSMSERVER, "ksmserver: Fatal IO error: client killed"); ++ // Don't do anything that might require the X connection ++ if (the_server) { ++ KSMServer *server = the_server; ++ the_server = nullptr; ++ server->cleanUp(); ++ // Don't delete server!! ++ } + +- // Don't do anything that might require the X connection +- if (the_server) { +- KSMServer *server = the_server; +- the_server = nullptr; +- server->cleanUp(); +- // Don't delete server!! +- } ++ exit(0); // Don't report error, it's not our fault. ++ return 0; // Bogus return value, notreached ++ } + +- exit(0); // Don't report error, it's not our fault. +- return 0; // Bogus return value, notreached +-} ++ void KSMServer::setupXIOErrorHandler() ++ { ++ XSetIOErrorHandler(Xio_ErrorHandler); ++ } + +-void KSMServer::setupXIOErrorHandler() +-{ +- XSetIOErrorHandler(Xio_ErrorHandler); +-} ++ static int wake_up_socket = -1; ++ static void sighandler(int sig) ++ { ++ if (sig == SIGHUP) { ++ signal(SIGHUP, sighandler); ++ return; ++ } + +-static int wake_up_socket = -1; +-static void sighandler(int sig) +-{ +- if (sig == SIGHUP) { +- signal(SIGHUP, sighandler); +- return; +- } ++ char ch = 0; ++ (void)::write(wake_up_socket, &ch, 1); ++ } + +- char ch = 0; +- (void)::write(wake_up_socket, &ch, 1); +-} ++ void KSMWatchProc(IceConn iceConn, IcePointer client_data, Bool opening, IcePointer * watch_data) ++ { ++ KSMServer *ds = (KSMServer *)client_data; + +-void KSMWatchProc(IceConn iceConn, IcePointer client_data, Bool opening, IcePointer *watch_data) +-{ +- KSMServer *ds = (KSMServer *)client_data; ++ if (opening) { ++ *watch_data = (IcePointer)ds->watchConnection(iceConn); ++ } else { ++ ds->removeConnection((KSMConnection *)*watch_data); ++ } ++ } + +- if (opening) { +- *watch_data = (IcePointer)ds->watchConnection(iceConn); +- } else { +- ds->removeConnection((KSMConnection *)*watch_data); +- } +-} ++ static Status KSMNewClientProc(SmsConn conn, SmPointer manager_data, unsigned long *mask_ret, SmsCallbacks *cb, char **failure_reason_ret) ++ { ++ *failure_reason_ret = nullptr; + +-static Status KSMNewClientProc(SmsConn conn, SmPointer manager_data, unsigned long *mask_ret, SmsCallbacks *cb, char **failure_reason_ret) +-{ +- *failure_reason_ret = nullptr; ++ void *client = ((KSMServer *)manager_data)->newClient(conn); ++ if (client == NULL) { ++ const char *errstr = "Connection rejected: ksmserver is shutting down"; ++ qCWarning(KSMSERVER, "%s", errstr); + +- void *client = ((KSMServer *)manager_data)->newClient(conn); +- if (client == NULL) { +- const char *errstr = "Connection rejected: ksmserver is shutting down"; +- qCWarning(KSMSERVER, "%s", errstr); ++ if ((*failure_reason_ret = (char *)malloc(strlen(errstr) + 1)) != NULL) { ++ strcpy(*failure_reason_ret, errstr); ++ } ++ return 0; ++ } + +- if ((*failure_reason_ret = (char *)malloc(strlen(errstr) + 1)) != NULL) { +- strcpy(*failure_reason_ret, errstr); ++ cb->register_client.callback = KSMRegisterClientProc; ++ cb->register_client.manager_data = client; ++ cb->interact_request.callback = KSMInteractRequestProc; ++ cb->interact_request.manager_data = client; ++ cb->interact_done.callback = KSMInteractDoneProc; ++ cb->interact_done.manager_data = client; ++ cb->save_yourself_request.callback = KSMSaveYourselfRequestProc; ++ cb->save_yourself_request.manager_data = client; ++ cb->save_yourself_phase2_request.callback = KSMSaveYourselfPhase2RequestProc; ++ cb->save_yourself_phase2_request.manager_data = client; ++ cb->save_yourself_done.callback = KSMSaveYourselfDoneProc; ++ cb->save_yourself_done.manager_data = client; ++ cb->close_connection.callback = KSMCloseConnectionProc; ++ cb->close_connection.manager_data = client; ++ cb->set_properties.callback = KSMSetPropertiesProc; ++ cb->set_properties.manager_data = client; ++ cb->delete_properties.callback = KSMDeletePropertiesProc; ++ cb->delete_properties.manager_data = client; ++ cb->get_properties.callback = KSMGetPropertiesProc; ++ cb->get_properties.manager_data = client; ++ ++ *mask_ret = SmsRegisterClientProcMask | SmsInteractRequestProcMask | SmsInteractDoneProcMask | SmsSaveYourselfRequestProcMask ++ | SmsSaveYourselfP2RequestProcMask | SmsSaveYourselfDoneProcMask | SmsCloseConnectionProcMask | SmsSetPropertiesProcMask ++ | SmsDeletePropertiesProcMask | SmsGetPropertiesProcMask; ++ return 1; + } +- return 0; +- } +- +- cb->register_client.callback = KSMRegisterClientProc; +- cb->register_client.manager_data = client; +- cb->interact_request.callback = KSMInteractRequestProc; +- cb->interact_request.manager_data = client; +- cb->interact_done.callback = KSMInteractDoneProc; +- cb->interact_done.manager_data = client; +- cb->save_yourself_request.callback = KSMSaveYourselfRequestProc; +- cb->save_yourself_request.manager_data = client; +- cb->save_yourself_phase2_request.callback = KSMSaveYourselfPhase2RequestProc; +- cb->save_yourself_phase2_request.manager_data = client; +- cb->save_yourself_done.callback = KSMSaveYourselfDoneProc; +- cb->save_yourself_done.manager_data = client; +- cb->close_connection.callback = KSMCloseConnectionProc; +- cb->close_connection.manager_data = client; +- cb->set_properties.callback = KSMSetPropertiesProc; +- cb->set_properties.manager_data = client; +- cb->delete_properties.callback = KSMDeletePropertiesProc; +- cb->delete_properties.manager_data = client; +- cb->get_properties.callback = KSMGetPropertiesProc; +- cb->get_properties.manager_data = client; +- +- *mask_ret = SmsRegisterClientProcMask | SmsInteractRequestProcMask | SmsInteractDoneProcMask | SmsSaveYourselfRequestProcMask +- | SmsSaveYourselfP2RequestProcMask | SmsSaveYourselfDoneProcMask | SmsCloseConnectionProcMask | SmsSetPropertiesProcMask | SmsDeletePropertiesProcMask +- | SmsGetPropertiesProcMask; +- return 1; +-} + + #ifdef HAVE__ICETRANSNOLISTEN + extern "C" int _IceTransNoListen(const char *protocol); +@@ -490,6 +491,12 @@ KSMServer::KSMServer(InitFlags flags) + QSocketNotifier *n = new QSocketNotifier(sockets[1], QSocketNotifier::Read, this); + qApp->connect(n, &QSocketNotifier::activated, &QApplication::quit); + ++ const QString runtimeDirectory = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); ++ iceAuthFile.setFileTemplate(runtimeDirectory + QStringLiteral("/iceauth_XXXXXX")); ++ if (!iceAuthFile.open()) ++ qFatal("Failed to create ICEauthority file"); ++ setenv("ICEAUTHORITY", qPrintable(iceAuthFile.fileName()), true); ++ + new KSMServerInterfaceAdaptor(this); + QDBusConnection::sessionBus().registerObject(QStringLiteral("/KSMServer"), this); + the_server = this; +@@ -545,7 +552,11 @@ KSMServer::KSMServer(InitFlags flags) + fclose(f); + setenv("SESSION_MANAGER", session_manager, true); + +- auto updateEnvJob = new UpdateLaunchEnvJob(QStringLiteral("SESSION_MANAGER"), QString::fromLatin1(session_manager)); ++ QProcessEnvironment newEnv; ++ newEnv.insert(QStringLiteral("SESSION_MANAGER"), QString::fromLatin1(session_manager)); ++ newEnv.insert(QStringLiteral("ICEAUTHORITY"), iceAuthFile.fileName()); ++ ++ auto updateEnvJob = new UpdateLaunchEnvJob(newEnv); + updateEnvJob->exec(); + + free(session_manager); +diff --git a/ksmserver/server.h b/ksmserver/server.h +index b8904ff0c3..b40629131d 100644 +--- a/ksmserver/server.h ++++ b/ksmserver/server.h +@@ -25,6 +25,7 @@ extern "C" { + #include + #include + #include ++#include + + #include + #include +@@ -223,5 +224,6 @@ private: + OrgKdeKWinSessionInterface *m_kwinInterface; + + int sockets[2]; ++ QTemporaryFile iceAuthFile; + friend bool readFromPipe(int pipe); + }; +-- +GitLab + diff --git a/plasma-workspace.spec b/plasma-workspace.spec index e432301..dd0996f 100644 --- a/plasma-workspace.spec +++ b/plasma-workspace.spec @@ -11,7 +11,7 @@ Name: plasma-workspace Summary: Plasma workspace, applications and applets Version: 5.27.10 -Release: 1 +Release: 2 License: GPLv2+ URL: https://invent.kde.org/plasma/%{name} @@ -43,6 +43,10 @@ Patch107: plasma-workspace-5.25.90-enable-lock-logout-action.patch # Hide virtual keyboard indicator on sddm. # Do not remove this as it breaks Fedora's QA policy Patch108: hide-virtual-keyboard-indicator-on-sddm.patch +# https://invent.kde.org/plasma/plasma-workspace/-/commit/da843d3fdb143ed44094c8e6246cfb8305f6f09f +Patch109: Authenticate-local-clients.patch +# https://invent.kde.org/plasma/plasma-workspace/-/commit/1d5aa1d27bff87b2d242ed759cfb2ce15a5c3de7 +Patch110: Remove-iceauth-dependency.patch # udev BuildRequires: zlib-devel @@ -332,6 +336,8 @@ Requires: xsetroot %patch106 -p1 %patch107 -p1 %patch108 -p1 +%patch109 -p1 +%patch110 -p1 %build mkdir %{_target_platform} @@ -591,6 +597,9 @@ setsebool -P selinuxuser_execmod 1 %endif %changelog +* Mon Jul 08 2024 zhangxianting - 5.27.10-2 +- CVE-2024-36041 + * Tue Jan 09 2024 jiangxinyu - 5.27.10-1 - Update package to version 5.27.10