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:
- 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.
- 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.