Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package open-vm-tools for openSUSE:Factory checked in at 2023-10-29 19:39:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/open-vm-tools (Old) and /work/SRC/openSUSE:Factory/.open-vm-tools.new.17445 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "open-vm-tools" Sun Oct 29 19:39:41 2023 rev:119 rq:1120828 version:12.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/open-vm-tools/open-vm-tools.changes 2023-10-24 20:06:55.765410032 +0200 +++ /work/SRC/openSUSE:Factory/.open-vm-tools.new.17445/open-vm-tools.changes 2023-10-29 19:39:46.662961457 +0100 @@ -1,0 +2,11 @@ +Fri Oct 27 14:42:23 UTC 2023 - Kirk Allan <kal...@suse.com> + +- Fix (bsc#1216432) - VUL-0: CVE-2023-34058: open-vm-tools: SAML token + signature bypass vulnerability. +- Fix (bsc#1216433) - VUL-0: : CVE-2023-34059: open-vm-tools: file + descriptor hijack vulnerability ++ Add patch: + - CVE-2023-34058.patch + - CVE-2023-34059.patch + +------------------------------------------------------------------- New: ---- CVE-2023-34058.patch CVE-2023-34059.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ open-vm-tools.spec ++++++ --- /var/tmp/diff_new_pack.Cf0NvU/_old 2023-10-29 19:39:49.703072056 +0100 +++ /var/tmp/diff_new_pack.Cf0NvU/_new 2023-10-29 19:39:49.703072056 +0100 @@ -156,6 +156,8 @@ Supplements: modalias(pci:v000015ADd*sv*sd*bc*sc*i*) ExclusiveArch: %ix86 x86_64 aarch64 #Upstream patches +Patch2: CVE-2023-34058.patch +Patch3: CVE-2023-34059.patch #SUSE specific patches Patch0: pam-vmtoolsd.patch @@ -258,6 +260,8 @@ # fix for an rpmlint warning regarding wrong line feeds sed -i -e "s/\r//" README #Upstream patches +%patch2 -p2 +%patch3 -p2 #SUSE specific patches %patch0 -p2 ++++++ CVE-2023-34058.patch ++++++ >From 6822b5a84f8cfa60d46479d6b8f1c63eb85eac87 Mon Sep 17 00:00:00 2001 From: John Wolfe <jwo...@vmware.com> Date: Wed, 18 Oct 2023 09:04:07 -0700 Subject: [PATCH] Address CVE-2023-34058 VGAuth: don't accept tokens with unrelated certs. --- open-vm-tools/vgauth/common/certverify.c | 145 ++++++++++++++++++++++++ open-vm-tools/vgauth/common/certverify.h | 4 + open-vm-tools/vgauth/common/prefs.h | 2 + open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c | 14 +++ 4 files changed, 165 insertions(+) diff --git a/open-vm-tools/vgauth/common/certverify.c b/open-vm-tools/vgauth/common/certverify.c index 0ed78ed..e1d7cc6 100644 --- a/open-vm-tools/vgauth/common/certverify.c +++ b/open-vm-tools/vgauth/common/certverify.c @@ -914,3 +914,148 @@ done: return err; } + + +/* + * Finds a cert with a subject (if checkSubj is set) or issuer (if + * checkSUbj is unset), matching 'val' in the list + * of certs. Returns a match or NULL. + */ + +static X509 * +FindCert(GList *cList, + X509_NAME *val, + int checkSubj) +{ + GList *l; + X509 *c; + X509_NAME *v; + + l = cList; + while (l != NULL) { + c = (X509 *) l->data; + if (checkSubj) { + v = X509_get_subject_name(c); + } else { + v = X509_get_issuer_name(c); + } + if (X509_NAME_cmp(val, v) == 0) { + return c; + } + l = l->next; + } + return NULL; +} + + +/* + ****************************************************************************** + * CertVerify_CheckForUnrelatedCerts -- */ /** + * + * Looks over a list of certs. If it finds that they are not all + * part of the same chain, returns failure. + * + * @param[in] numCerts The number of certs in the chain. + * @param[in] pemCerts The chain of certificates to verify. + * + * @return VGAUTH_E_OK on success, VGAUTH_E_FAIL if unrelated certs are found. + * + ****************************************************************************** + */ + +VGAuthError +CertVerify_CheckForUnrelatedCerts(int numCerts, + const char **pemCerts) +{ + VGAuthError err = VGAUTH_E_FAIL; + int chainLen = 0; + int i; + X509 **certs = NULL; + GList *rawList = NULL; + X509 *baseCert; + X509 *curCert; + X509_NAME *subject; + X509_NAME *issuer; + + /* common single cert case; nothing to do */ + if (numCerts == 1) { + return VGAUTH_E_OK; + } + + /* convert all PEM to X509 objects */ + certs = g_malloc0(numCerts * sizeof(X509 *)); + for (i = 0; i < numCerts; i++) { + certs[i] = CertStringToX509(pemCerts[i]); + if (NULL == certs[i]) { + g_warning("%s: failed to convert cert to X509\n", __FUNCTION__); + goto done; + } + } + + /* choose the cert to start the chain. shouldn't matter which */ + baseCert = certs[0]; + + /* put the rest into a list */ + for (i = 1; i < numCerts; i++) { + rawList = g_list_append(rawList, certs[i]); + } + + /* now chase down to a leaf, looking for certs the baseCert issued */ + subject = X509_get_subject_name(baseCert); + while ((curCert = FindCert(rawList, subject, 0)) != NULL) { + /* pull it from the list */ + rawList = g_list_remove(rawList, curCert); + /* set up the next find */ + subject = X509_get_subject_name(curCert); + } + + /* + * walk up to the root cert, by finding a cert where the + * issuer equals the subject of the current + */ + issuer = X509_get_issuer_name(baseCert); + while ((curCert = FindCert(rawList, issuer, 1)) != NULL) { + /* pull it from the list */ + rawList = g_list_remove(rawList, curCert); + /* set up the next find */ + issuer = X509_get_issuer_name(curCert); + } + + /* + * At this point, anything on the list should be certs that are not part + * of the chain that includes the original 'baseCert'. + * + * For a valid token, the list should be empty. + */ + chainLen = g_list_length(rawList); + if (chainLen != 0 ) { + GList *l; + + g_warning("%s: %d unrelated certs found in list\n", + __FUNCTION__, chainLen); + + /* debug helper */ + l = rawList; + while (l != NULL) { + X509* c = (X509 *) l->data; + char *s = X509_NAME_oneline(X509_get_subject_name(c), NULL, 0); + + g_debug("%s: unrelated cert subject: %s\n", __FUNCTION__, s); + free(s); + l = l->next; + } + + goto done; + } + + g_debug("%s: Success! no unrelated certs found\n", __FUNCTION__); + err = VGAUTH_E_OK; + +done: + g_list_free(rawList); + for (i = 0; i < numCerts; i++) { + X509_free(certs[i]); + } + g_free(certs); + return err; +} diff --git a/open-vm-tools/vgauth/common/certverify.h b/open-vm-tools/vgauth/common/certverify.h index d7c6410..f582bb8 100644 --- a/open-vm-tools/vgauth/common/certverify.h +++ b/open-vm-tools/vgauth/common/certverify.h @@ -67,6 +67,10 @@ VGAuthError CertVerify_CheckSignatureUsingCert(VGAuthHashAlg hash, size_t signatureLen, const unsigned char *signature); + +VGAuthError CertVerify_CheckForUnrelatedCerts(int numCerts, + const char **pemCerts); + gchar * CertVerify_StripPEMCert(const gchar *pemCert); gchar * CertVerify_CertToX509String(const gchar *pemCert); diff --git a/open-vm-tools/vgauth/common/prefs.h b/open-vm-tools/vgauth/common/prefs.h index ff11692..87ccc9b 100644 --- a/open-vm-tools/vgauth/common/prefs.h +++ b/open-vm-tools/vgauth/common/prefs.h @@ -136,6 +136,8 @@ msgCatalog = /etc/vmware-tools/vgauth/messages #define VGAUTH_PREF_ALIASSTORE_DIR "aliasStoreDir" /** The number of seconds slack allowed in either direction in SAML token date checks. */ #define VGAUTH_PREF_CLOCK_SKEW_SECS "clockSkewAdjustment" +/** If unrelated certificates are allowed in a SAML token */ +#define VGAUTH_PREF_ALLOW_UNRELATED_CERTS "allowUnrelatedCerts" /** Ticket group name. */ #define VGAUTH_PREF_GROUP_NAME_TICKET "ticket" diff --git a/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c b/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c index 14cba1b..57e9316 100644 --- a/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c +++ b/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c @@ -49,6 +49,7 @@ #include "vmxlog.h" static int gClockSkewAdjustment = VGAUTH_PREF_DEFAULT_CLOCK_SKEW_SECS; +static gboolean gAllowUnrelatedCerts = FALSE; static xmlSchemaPtr gParsedSchemas = NULL; static xmlSchemaValidCtxtPtr gSchemaValidateCtx = NULL; @@ -369,6 +370,10 @@ LoadPrefs(void) VGAUTH_PREF_DEFAULT_CLOCK_SKEW_SECS); Log("%s: Allowing %d of clock skew for SAML date validation\n", __FUNCTION__, gClockSkewAdjustment); + gAllowUnrelatedCerts = Pref_GetBool(gPrefs, + VGAUTH_PREF_ALLOW_UNRELATED_CERTS, + VGAUTH_PREF_GROUP_NAME_SERVICE, + FALSE); } @@ -1697,6 +1702,15 @@ SAML_VerifyBearerTokenAndChain(const char *xmlText, return VGAUTH_E_AUTHENTICATION_DENIED; } + if (!gAllowUnrelatedCerts) { + err = CertVerify_CheckForUnrelatedCerts(num, (const char **) certChain); + if (err != VGAUTH_E_OK) { + VMXLog_Log(VMXLOG_LEVEL_WARNING, + "Unrelated certs found in SAML token, failing\n"); + return VGAUTH_E_AUTHENTICATION_DENIED; + } + } + subj.type = SUBJECT_TYPE_NAMED; subj.name = *subjNameOut; err = ServiceVerifyAndCheckTrustCertChainForSubject(num, -- 2.6.2 ++++++ CVE-2023-34059.patch ++++++ >From 2011181cbe60b256ced8d28daf7b704e8613467c Mon Sep 17 00:00:00 2001 From: John Wolfe <jwo...@vmware.com> Date: Wed, 18 Oct 2023 09:11:54 -0700 Subject: [PATCH] Address CVE-2023-34059 Fix file descriptor vulnerability in the open-vm-tools vmware-user-suid-wrapper on Linux. - Moving the privilege drop logic (dropping privilege to the real uid and gid of the process for the vmusr service) from suidWrapper to vmtoolsd code. --- open-vm-tools/services/vmtoolsd/mainPosix.c | 76 +++++++++++++++++++++++++++ open-vm-tools/vmware-user-suid-wrapper/main.c | 26 ++------- 2 files changed, 79 insertions(+), 23 deletions(-) diff --git a/open-vm-tools/services/vmtoolsd/mainPosix.c b/open-vm-tools/services/vmtoolsd/mainPosix.c index fd2667c..8b46979 100644 --- a/open-vm-tools/services/vmtoolsd/mainPosix.c +++ b/open-vm-tools/services/vmtoolsd/mainPosix.c @@ -28,10 +28,12 @@ #include <signal.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <glib/gstdio.h> #include "file.h" #include "guestApp.h" #include "hostinfo.h" +#include "su.h" #include "system.h" #include "unicode.h" #include "util.h" @@ -155,6 +157,59 @@ ToolsCoreWorkAroundLoop(ToolsServiceState *state, /** + * Tools function to set close-on-exec flg for the fd. + * + * @param[in] fd open file descriptor. + * + * @return TRUE on success, FALSE otherwise. + */ + +static gboolean +ToolsSetCloexecFlag(int fd) +{ + int flags; + + if (fd == -1) { + /* fd is not present, no need to manipulate */ + return TRUE; + } + + flags = fcntl(fd, F_GETFD, 0); + if (flags < 0) { + g_printerr("Couldn't get the flags set for fd %d, error %u.", fd, errno); + return FALSE; + } + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) < 0) { + g_printerr("Couldn't set close-on-exec for fd %d, error %u.", fd, errno); + return FALSE; + } + + return TRUE; +} + + +/** + * Tools function to close the fds. + */ + +static void +ToolsCloseFds(void) +{ + if (gState.ctx.blockFD != -1) { + close(gState.ctx.blockFD); + } + + /* + * uinputFD will be available only for wayland. + */ + if (gState.ctx.uinputFD != -1) { + close(gState.ctx.uinputFD); + } +} + + +/** * Tools daemon entry function. * * @param[in] argc Argument count. @@ -210,6 +265,27 @@ main(int argc, g_free(argvCopy); argvCopy = NULL; + /* + * Drops privilege to the real uid and gid of the process + * for the "vmusr" service. + */ + if (TOOLS_IS_USER_SERVICE(&gState)) { + uid_t uid = getuid(); + gid_t gid = getgid(); + + if ((Id_SetREUid(uid, uid) != 0) || + (Id_SetREGid(gid, gid) != 0)) { + g_printerr("could not drop privileges: %s", strerror(errno)); + ToolsCloseFds(); + goto exit; + } + if (!ToolsSetCloexecFlag(gState.ctx.blockFD) || + !ToolsSetCloexecFlag(gState.ctx.uinputFD)) { + ToolsCloseFds(); + goto exit; + } + } + if (gState.pidFile != NULL) { /* * If argv[0] is not an absolute path, make it so; all other path diff --git a/open-vm-tools/vmware-user-suid-wrapper/main.c b/open-vm-tools/vmware-user-suid-wrapper/main.c index e9d7e50..a19af53 100644 --- a/open-vm-tools/vmware-user-suid-wrapper/main.c +++ b/open-vm-tools/vmware-user-suid-wrapper/main.c @@ -156,8 +156,7 @@ MaskSignals(void) * * Obtains the library directory from the Tools locations database, then * opens a file descriptor (while still root) to add and remove blocks, - * drops privilege to the real uid of this process, and finally starts - * vmware-user. + * and finally starts vmware-user. * * Results: * Parent: TRUE on success, FALSE on failure. @@ -173,8 +172,6 @@ static Bool StartVMwareUser(char *const envp[]) { pid_t pid; - uid_t uid; - gid_t gid; int blockFd = -1; char blockFdStr[8]; int uinputFd = -1; @@ -191,8 +188,8 @@ StartVMwareUser(char *const envp[]) } /* - * Now create a child process, obtain a file descriptor as root, downgrade - * privilege, and run vmware-user. + * Now create a child process, obtain a file descriptor as root and + * run vmware-user. */ pid = fork(); if (pid == -1) { @@ -229,23 +226,6 @@ StartVMwareUser(char *const envp[]) } } - uid = getuid(); - gid = getgid(); - - if ((setreuid(uid, uid) != 0) || - (setregid(gid, gid) != 0)) { - Error("could not drop privileges: %s\n", strerror(errno)); - if (blockFd != -1) { - close(blockFd); - } - if (useWayland) { - if (uinputFd != -1) { - close(uinputFd); - } - } - return FALSE; - } - /* * Since vmware-user provides features that don't depend on vmblock, we * invoke vmware-user even if we couldn't obtain a file descriptor or we -- 2.6.2