]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Add RpcChannel_SendOneRawPriv()
authorOliver Kurth <okurth@vmware.com>
Mon, 5 Aug 2019 18:21:59 +0000 (11:21 -0700)
committerOliver Kurth <okurth@vmware.com>
Mon, 5 Aug 2019 18:21:59 +0000 (11:21 -0700)
Send privileged guest RPC "guestStore.connect" with it after the
vmsvc RPC channel falls back to backdoor.

open-vm-tools/lib/include/vmware/tools/guestrpc.h
open-vm-tools/lib/rpcChannel/bdoorChannel.c
open-vm-tools/lib/rpcChannel/rpcChannel.c
open-vm-tools/lib/rpcChannel/rpcChannelInt.h
open-vm-tools/lib/rpcChannel/vsockChannel.c

index ee34802d549220c9595dc7876461698c0be0ebfb..2fecfdfd90bb8f495ed17b6bf8db45a17e2c1db4 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2008,2014-2016,2018 VMware, Inc. All rights reserved.
+ * Copyright (C) 2008,2014-2016,2018-2019 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -204,15 +204,36 @@ RpcChannel_SendOneRaw(const char *data,
                       char **result,
                       size_t *resultLen);
 
+#if defined(__linux__) || defined(_WIN32)
+gboolean
+RpcChannel_SendOneRawPriv(const char *data,
+                          size_t dataLen,
+                          char **result,
+                          size_t *resultLen);
+#endif
+
 gboolean
 RpcChannel_SendOne(char **reply,
                    size_t *repLen,
                    const char *reqFmt,
                    ...);
 
+#if defined(__linux__) || defined(_WIN32)
+gboolean
+RpcChannel_SendOnePriv(char **reply,
+                       size_t *repLen,
+                       const char *reqFmt,
+                       ...);
+#endif
+
 RpcChannel *
 RpcChannel_New(void);
 
+#if defined(__linux__) || defined(_WIN32)
+RpcChannel *
+VSockChannel_New(void);
+#endif
+
 void
 RpcChannel_SetBackdoorOnly(void);
 
index 8856c60b0c9c2ab4f3d6ad5bdc1658e833187cd5..d3572a8d2084fd57c0521e8f6f9801dd4dea894d 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2008-2016,2018 VMware, Inc. All rights reserved.
+ * Copyright (C) 2008-2016,2018-2019 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -271,6 +271,7 @@ BackdoorChannel_New(void)
 
    BackdoorChannelSetCallbacks(ret);
    ret->_private = bdoor;
+   g_mutex_init(&ret->outLock);
 
    return ret;
 }
index 0dcb3ffb0b0152b0678ca05b10803d32cfc54f21..837a0abb946bdd2ad0b4e7aa00a4e6520b52920d 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2008-2016,2018 VMware, Inc. All rights reserved.
+ * Copyright (C) 2008-2016,2018-2019 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -129,7 +129,7 @@ RpcChannelRestart(gpointer _chan)
    RpcChannelStopNoLock(&chan->impl);
 
    /* Clear vSocket channel failure */
-   Debug(LGPFX "Clearing backdoor behavior ...\n");
+   Log(LGPFX "Clearing backdoor behavior ...\n");
    gVSocketFailed = FALSE;
 
    chanStarted = RpcChannel_Start(&chan->impl);
@@ -184,9 +184,9 @@ RpcChannelCheckReset(gpointer _chan)
    }
 
    /* Reset was successful. */
-   Debug(LGPFX "Channel was reset successfully.\n");
+   Log(LGPFX "Channel was reset successfully.\n");
    chan->rpcResetErrorCount = 0;
-   Debug(LGPFX "Clearing backdoor behavior ...\n");
+   Log(LGPFX "Clearing backdoor behavior ...\n");
    gVSocketFailed = FALSE;
 
    if (chan->resetCb != NULL) {
@@ -806,9 +806,6 @@ RpcChannel_New(void)
 #else
    chan = BackdoorChannel_New();
 #endif
-   if (chan) {
-      g_mutex_init(&chan->outLock);
-   }
    return chan;
 }
 
@@ -852,14 +849,14 @@ RpcChannel_Start(RpcChannel *chan)
    ok = funcs->start(chan);
 
    if (!ok && funcs->onStartErr != NULL) {
-      Debug(LGPFX "Fallback to backdoor ...\n");
+      Log(LGPFX "Fallback to backdoor ...\n");
       funcs->onStartErr(chan);
       ok = BackdoorChannel_Fallback(chan);
       /*
        * As vSocket is not available, we stick the backdoor
        * behavior until the channel is reset/restarted.
        */
-      Debug(LGPFX "Sticking backdoor behavior ...\n");
+      Log(LGPFX "Sticking backdoor behavior ...\n");
       gVSocketFailed = TRUE;
    }
 
@@ -996,7 +993,7 @@ RpcChannel_Send(RpcChannel *chan,
       resLen = 0;
 
       /* retry once */
-      Debug(LGPFX "Stop RpcOut channel and try to send again ...\n");
+      Log(LGPFX "Stop RpcOut channel and try to send again ...\n");
       funcs->stopRpcOut(chan);
       if (RpcChannel_Start(chan)) {
          /* The channel may get switched from vsocket to backdoor */
@@ -1038,22 +1035,28 @@ exit:
  * @param[in]  dataLen     data length
  * @param[in]  result      reply, should be freed by calling RpcChannel_Free.
  * @param[in]  resultLen   reply length
+ * @param[in]  priv        TRUE : create VSock channel for privileged guest RPC.
+                           FALSE: follow regular RPC channel creation process.
 
  * @returns    TRUE on success.
  */
 
-gboolean
-RpcChannel_SendOneRaw(const char *data,
-                      size_t dataLen,
-                      char **result,
-                      size_t *resultLen)
+static gboolean
+RpcChannelSendOneRaw(const char *data,
+                     size_t dataLen,
+                     char **result,
+                     size_t *resultLen,
+                     gboolean priv)
 {
    RpcChannel *chan;
-   gboolean status;
-
-   status = FALSE;
+   gboolean status = FALSE;
 
+#if (defined(__linux__) && !defined(USERWORLD)) || defined(_WIN32)
+   chan = priv ? VSockChannel_New() : RpcChannel_New();
+#else
    chan = RpcChannel_New();
+#endif
+
    if (chan == NULL) {
       if (result != NULL) {
          *result = Util_SafeStrdup("RpcChannel: Unable to create "
@@ -1072,6 +1075,14 @@ RpcChannel_SendOneRaw(const char *data,
          }
       }
       goto sent;
+   } else if (RpcChannel_GetType(chan) != RPCCHANNEL_TYPE_PRIV_VSOCK) {
+      if (result != NULL) {
+         *result = Util_SafeStrdup("Permission denied");
+         if (resultLen != NULL) {
+            *resultLen = strlen(*result);
+         }
+      }
+      goto sent;
    } else if (!RpcChannel_Send(chan, data, dataLen, result, resultLen)) {
       /* We already have the description of the error */
       goto sent;
@@ -1091,6 +1102,54 @@ sent:
 }
 
 
+/**
+ * Open/close RpcChannel each time for sending a Rpc message, this is a wrapper
+ * for RpcChannel APIs.
+ *
+ * @param[in]  data        request data
+ * @param[in]  dataLen     data length
+ * @param[in]  result      reply, should be freed by calling RpcChannel_Free.
+ * @param[in]  resultLen   reply length
+
+ * @returns    TRUE on success.
+ */
+
+gboolean
+RpcChannel_SendOneRaw(const char *data,
+                      size_t dataLen,
+                      char **result,
+                      size_t *resultLen)
+{
+   return RpcChannelSendOneRaw(data, dataLen, result, resultLen, FALSE);
+}
+
+
+#if defined(__linux__) || defined(_WIN32)
+
+/**
+ * Open/close VSock RPC Channel each time for sending a privileged Rpc message,
+ * this is a wrapper for RpcChannel APIs.
+ *
+ * @param[in]  data        request data
+ * @param[in]  dataLen     data length
+ * @param[in]  result      reply, should be freed by calling RpcChannel_Free.
+ * @param[in]  resultLen   reply length
+
+ * @returns    TRUE on success.
+ */
+
+gboolean
+RpcChannel_SendOneRawPriv(const char *data,
+                          size_t dataLen,
+                          char **result,
+                          size_t *resultLen)
+{
+   return RpcChannelSendOneRaw(data, dataLen, result, resultLen, TRUE);
+}
+
+#endif
+
+
 /**
  * Open/close RpcChannel each time for sending a Rpc message, this is a wrapper
  * for RpcChannel APIs.
@@ -1098,18 +1157,20 @@ sent:
  * @param[out] reply       reply, should be freed by calling RpcChannel_Free.
  * @param[out] repLen      reply length
  * @param[in]  reqFmt      request data
- * @param[in]  ...         optional arguments depending on reqFmt.
+ * @param[in]  args        optional arguments depending on reqFmt.
+ * @param[in]  priv        TRUE : create VSock channel for privileged guest RPC.
+                           FALSE: follow regular RPC channel creation process.
 
  * @returns    TRUE on success.
  */
 
-gboolean
-RpcChannel_SendOne(char **reply,
-                   size_t *repLen,
-                   char const *reqFmt,
-                   ...)
+static gboolean
+RpcChannelSendOne(char **reply,
+                  size_t *repLen,
+                  char const *reqFmt,
+                  va_list args,
+                  gboolean priv)
 {
-   va_list args;
    gboolean status;
    char *request;
    size_t reqLen = 0;
@@ -1117,9 +1178,7 @@ RpcChannel_SendOne(char **reply,
    status = FALSE;
 
    /* Format the request string */
-   va_start(args, reqFmt);
    request = Str_Vasprintf(&reqLen, reqFmt, args);
-   va_end(args);
 
    /*
     * If Str_Vasprintf failed, write NULL into the reply if the caller wanted
@@ -1129,32 +1188,7 @@ RpcChannel_SendOne(char **reply,
       goto error;
    }
 
-   /*
-    * If the command doesn't contain a space, add one to the end to maintain
-    * compatibility with old VMXs.
-    *
-    * For a long time, the GuestRpc logic in the VMX was wired to expect a
-    * trailing space in every command, even commands without arguments. That is
-    * no longer true, but we must continue to add a trailing space because we
-    * don't know whether we're talking to an old or new VMX.
-    */
-   if (request[reqLen - 1] != ' ') {
-      char *tmp;
-
-      tmp = Str_Asprintf(NULL, "%s ", request);
-      free(request);
-      request = tmp;
-
-      /*
-       * If Str_Asprintf failed, write NULL into reply if the caller wanted
-       * a reply back.
-       */
-      if (request == NULL) {
-         goto error;
-      }
-   }
-
-   status = RpcChannel_SendOneRaw(request, reqLen, reply, repLen);
+   status = RpcChannelSendOneRaw(request, reqLen, reply, repLen, priv);
 
    free(request);
 
@@ -1170,3 +1204,65 @@ error:
    }
    return FALSE;
 }
+
+
+/**
+ * Open/close RpcChannel each time for sending a Rpc message, this is a wrapper
+ * for RpcChannel APIs.
+ *
+ * @param[out] reply       reply, should be freed by calling RpcChannel_Free.
+ * @param[out] repLen      reply length
+ * @param[in]  reqFmt      request data
+ * @param[in]  ...         optional arguments depending on reqFmt.
+
+ * @returns    TRUE on success.
+ */
+
+gboolean
+RpcChannel_SendOne(char **reply,
+                   size_t *repLen,
+                   char const *reqFmt,
+                   ...)
+{
+   va_list args;
+   gboolean status;
+
+   va_start(args, reqFmt);
+   status = RpcChannelSendOne(reply, repLen, reqFmt, args, FALSE);
+   va_end(args);
+
+   return status;
+}
+
+
+#if defined(__linux__) || defined(_WIN32)
+
+/**
+ * Open/close VSock RPC Channel each time for sending a privileged Rpc message,
+ * this is a wrapper for RpcChannel APIs.
+ *
+ * @param[out] reply       reply, should be freed by calling RpcChannel_Free.
+ * @param[out] repLen      reply length
+ * @param[in]  reqFmt      request data
+ * @param[in]  ...         optional arguments depending on reqFmt.
+
+ * @returns    TRUE on success.
+ */
+
+gboolean
+RpcChannel_SendOnePriv(char **reply,
+                       size_t *repLen,
+                       char const *reqFmt,
+                       ...)
+{
+   va_list args;
+   gboolean status;
+
+   va_start(args, reqFmt);
+   status = RpcChannelSendOne(reply, repLen, reqFmt, args, TRUE);
+   va_end(args);
+
+   return status;
+}
+
+#endif
index 47806a7699cb7d5ecb1eb4693b0d59fdc81c3dac..6584fc21f54c34a56d18e21040304ca355130385 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2008-2016,2018 VMware, Inc. All rights reserved.
+ * Copyright (C) 2008-2016,2018-2019 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -77,8 +77,6 @@ struct _RpcChannel {
    gboolean                  outStarted;
 };
 
-RpcChannel *VSockChannel_New(void);
-RpcChannel *BackdoorChannel_New(void);
 gboolean
 BackdoorChannel_Fallback(RpcChannel *chan);
 
index e8b80a2426211ded2346e08c03b80667f55cb172..db2eb737eef47aea4437e79eb5dc424e9403a82b 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2013-2016,2018 VMware, Inc. All rights reserved.
+ * Copyright (C) 2013-2016,2018-2019 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -588,6 +588,7 @@ VSockChannel_New(void)
 
    chan->_private = vsock;
    chan->funcs = &funcs;
+   g_mutex_init(&chan->outLock);
 
    return chan;
 }