Main Content

CWE Rule 558

Use of getlogin() in Multithreaded Application

Since R2023a

Description

Rule Description

The application uses the getlogin() function in a multithreaded context, potentially causing it to return incorrect values.

Polyspace Implementation

The rule checker checks for Unsafe standard function.

Examples

expand all

Issue

This issue occurs when you use standard functions that are unsafe and must not be used for security-related programming. Functions can be unsafe for many reasons. Some functions are unsafe because they are nonreentrant. Other functions change behavior depending on the target or platform, making some implementations unsafe.

Risk

Some unsafe functions are not reentrant, meaning that the contents of the function are not locked during a call. So, an attacker can change the values midstream.

getlogin specifically can be unsafe depending on the implementation. Some implementations of getlogin return only the first eight characters of a log-in name. An attacker can use a different login with the same first eight characters to gain entry and manipulate the program.

Fix

Avoid unsafe functions for security-related purposes. If you cannot avoid unsafe functions, use a safer version of the function instead. For getlogin, use getlogin_r.

Example — Using getlogin
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <string.h>
#include <stdlib.h>


volatile int rd = 1;

int login_name_check(char *user)
{
    int r = -2;
    char *name = getlogin();  //Noncompliant
    if (name != NULL)
    {
        if (strcmp(name, user) == 0)
        {
            r = 0;
        }
        else
            r = -1;
    }

    return r;
}

This example uses getlogin to compare the user name of the current user to the given user name. However, getlogin can return something other than the current user name because a parallel process can change the string.

Correction — Use getlogin_r

One possible correction is to use getlogin_r instead of getlogin. getlogin_r is reentrant, so you can trust the result.

#define _POSIX_C_SOURCE 199506L // use of getlogin_r
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <string.h>
#include <stdlib.h>


volatile int rd = 1;

enum {  NAME_MAX_SIZE=64  };

int login_name_check(char *user)
{
    int r;
    char name[NAME_MAX_SIZE];
    
    if (getlogin_r(name, sizeof(name)) == 0) 
    {
        if ((strlen(user) < sizeof(name)) && 
                     (strncmp(name, user, strlen(user)) == 0))
        {
            r = 0;
        }
        else
            r = -1;
    }
    else
        r = -2;
    return r;
}

Check Information

Category: Others

Version History

Introduced in R2023a