Skip to content

IPC: busy-wait in waitUntilAccepted() and unauthenticated shared memory #719

@grisutheguru

Description

@grisutheguru

Summary

The IPC mechanism has a busy-wait loop consuming 100% CPU and lacks authentication, allowing any same-user process to inject events.

Details

Busy-wait loop (src/ipc.cpp:234-249)

bool IPC::waitUntilAccepted(time_t postTime, int32_t timeout /*=-1*/)
{
    bool result = false;
    const time_t start = time(nullptr);
    forever {
        result = isEventAccepted(postTime);
        if (result || (timeout > 0 && difftime(time(nullptr), start) >= timeout)) {
            break;
        }
        qApp->processEvents();
        QThread::msleep(0);  // yields but does NOT actually sleep
    }
    return result;
}

With timeout == -1 (the default), this is an infinite busy-wait. Even with a positive timeout, the loop polls at maximum speed. QThread::msleep(0) only yields the time slice but doesn't sleep.

Fix: Use QThread::msleep(50) for a reasonable poll interval, or replace with QEventLoop + QTimer. Add a maximum timeout even for the -1 case.

Unauthenticated shared memory (src/ipc.cpp:34-42)

The shared memory key is "qtox-2-<USERNAME>". Any process running as the same user can:

  1. Attach to the segment
  2. Inject events (e.g., tox: URIs that trigger friend request dialogs)
  3. Read event data from the queue

Additionally, getenv("USER") returns NULL if unset, causing all users without the variable to share IPC key "qtox-2-" (line 37-40).

Fix for username: Use getpwuid(getuid()) on POSIX, GetUserNameW() on Windows instead of environment variables.

Fix for authentication: Add a random shared secret initialized at first launch and stored in the profile. Verify it in a HMAC field on each IPCEvent.

Impact

Busy-wait causes 100% CPU on one core during IPC synchronization. Unauthenticated IPC allows local event injection (low severity for desktop app, but relevant for privacy-focused software).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions