Safeguard
Application Security•

CWE-558 Use of getlogin() in Multithreaded Applications

getlogin() is not reentrant, so another thread can change the username you just read. Why CWE-558 matters and why getlogin_r() is only part of the answer.

Safeguard Security Team
3 min read

CWE-558, Use of getlogin() in Multithreaded Application, is a C and C++ weakness. MITRE says the product uses getlogin() in a multithreaded context, potentially causing it to return incorrect values.

How it happens

The function returns a pointer to a string holding the name of the user associated with the calling process. The trouble is where that string lives. MITRE explains that getlogin() is not reentrant: the contents are not locked out when it is called from elsewhere, so the value of the string can be changed by another process. That makes it risky, and the results cannot be trusted.

/* Vulnerable: the returned buffer can change under you */
char *user = getlogin();
if (user != NULL && strcmp(user, "admin") == 0) {
    grant_access();
}

The code reads a name and then acts on it. Between the read and the use, the buffer can hold a different name.

What an attacker gains

MITRE lists integrity and access control effects: modifying application data and bypassing a protection mechanism. If the username drives a decision, a wrong value can mean the wrong person gets treated as the right one.

How to find it

  • Search the code for calls to getlogin. As MITRE suggests for similar checks, even grep gets you the call sites.
  • Look at what each call site does with the result, particularly if it feeds a permission or logging decision.
  • MITRE notes static analysis can find some instances of this weakness.
grep -rn "getlogin" src/

How to fix it

MITRE gives two mitigations:

  1. At design time, do not use names for security purposes. Names are easy to forge and can have overlapping user IDs, potentially causing confusion or impersonation.
  2. At implementation time, use getlogin_r() instead. It is reentrant, which means other processes are locked out from changing the username.
/* Safer: caller supplies the buffer */
char user[256];
if (getlogin_r(user, sizeof(user)) == 0) {
    log_event(user);
}

Note the first point. Even a correct name is a weak basis for a security decision. Prefer numeric user IDs and the system's own authorization checks for access control, and use the name only for display and logs.

Quick check

Does getlogin_r() make a username safe to use for authorization?

It fixes the shared buffer problem. MITRE still advises against using names for security purposes because names are easy to forge and can overlap.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.