/*********************************************************
- * 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
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);
}
/* 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) {
#else
chan = BackdoorChannel_New();
#endif
- if (chan) {
- g_mutex_init(&chan->outLock);
- }
return 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;
}
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 */
* @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 "
}
}
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;
}
+/**
+ * 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.
* @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;
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
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);
}
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