Skip to content

Commit

Permalink
qrexec: try service name without argument for long arguments
Browse files Browse the repository at this point in the history
Do not fail immediately if service name with the argument is too long
for the path name, but try the name without the argument anyway.

While at it, fix missing error handling for StringCchPrintf.

Part of QubesOS/qubes-issues#4909
  • Loading branch information
marmarek committed Jan 31, 2024
1 parent b42d97a commit 5be4dff
Showing 1 changed file with 48 additions and 18 deletions.
66 changes: 48 additions & 18 deletions src/qrexec-agent/qrexec-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,24 +492,34 @@ static DWORD InterceptRPCRequest(IN OUT WCHAR *commandLine, OUT WCHAR **serviceC
// Leave trailing backslash
separator++;
*separator = L'\0';
if (wcslen(serviceFilePath) + wcslen(L"qubes-rpc\\") + wcslen(serviceName) > MAX_PATH)
if (wcslen(serviceFilePath) + wcslen(L"qubes-rpc\\_") > MAX_PATH)
{
free(*sourceDomainName);
LogError("RPC service config file path too long");
return ERROR_PATH_NOT_FOUND;
}

PathAppendW(serviceFilePath, L"qubes-rpc");
PathAppendW(serviceFilePath, serviceName);

serviceConfigFile = CreateFile(
serviceFilePath, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (wcslen(serviceFilePath) + wcslen(serviceName) > MAX_PATH)
{
LogError("RPC service config file path too long, trying without argument");
// append dummy service for uniform handling below
PathAppendW(serviceFilePath, L"_");
serviceConfigFile = INVALID_HANDLE_VALUE;
}
else
{
PathAppendW(serviceFilePath, serviceName);

serviceConfigFile = CreateFile(
serviceFilePath, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
}

if (serviceConfigFile == INVALID_HANDLE_VALUE)
{
Expand All @@ -531,6 +541,13 @@ static DWORD InterceptRPCRequest(IN OUT WCHAR *commandLine, OUT WCHAR **serviceC
}
newsep++;
*newsep = L'\0';
if (wcslen(serviceFilePath) + wcslen(serviceName) > MAX_PATH)
{
free(*sourceDomainName);
LogError("RPC service config file path too long");
return ERROR_PATH_NOT_FOUND;
}

PathAppendW(serviceFilePath, serviceName);

serviceConfigFile = CreateFile(
Expand Down Expand Up @@ -683,7 +700,15 @@ BOOL VchanSendHello(
*/
static DWORD StartChild(int domain, int port, PWSTR userName, PWSTR commandLine, BOOL isServer, BOOL piped, BOOL interactive)
{
PWSTR command = malloc(MAX_PATH_LONG * sizeof(WCHAR));
size_t const commandlen = wcslen(L"qrexec-wrapper.exe ") +
10 + // domain (int)
10 + // port (int)
wcslen(userName ? : L"(null)") +
1 + // flags (see below)
wcslen(commandLine ? : L"(null)") +
4 + // separators
1; // final NUL
PWSTR command = malloc(commandlen * sizeof(WCHAR));
int flags = 0;
HANDLE wrapper;
DWORD status;
Expand All @@ -705,12 +730,17 @@ static DWORD StartChild(int domain, int port, PWSTR userName, PWSTR commandLine,
if (piped) flags |= 0x02;
if (interactive) flags |= 0x04;

StringCchPrintf(command, MAX_PATH_LONG, L"qrexec-wrapper.exe %d%c%d%c%s%c%d%c%s",
domain, QUBES_ARGUMENT_SEPARATOR,
port, QUBES_ARGUMENT_SEPARATOR,
userName, QUBES_ARGUMENT_SEPARATOR,
flags, QUBES_ARGUMENT_SEPARATOR,
commandLine);
if (FAILED(StringCchPrintf(command, commandlen, L"qrexec-wrapper.exe %d%c%d%c%s%c%d%c%s",
domain, QUBES_ARGUMENT_SEPARATOR,
port, QUBES_ARGUMENT_SEPARATOR,
userName, QUBES_ARGUMENT_SEPARATOR,
flags, QUBES_ARGUMENT_SEPARATOR,
commandLine)))
{
free(command);
LogError("Failed to prepare qrexec-wrapper command");
return ERROR_NOT_ENOUGH_MEMORY;
}

// wrapper will run as current user (SYSTEM, we're a service)
status = CreateNormalProcessAsCurrentUser(command, &wrapper);
Expand Down

0 comments on commit 5be4dff

Please sign in to comment.