exponenta event banner

Неправильное использование канала readlink ()

Третий аргумент readlink не оставляет места для пустого терминатора в буфере

Описание

Этот дефект возникает при передаче аргумента размера буфера readlink() не оставляет места для пустого терминатора в буфере.

Например:

ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf));
Третий аргумент точно равен размеру второго аргумента. Для достаточно больших символьных ссылок, это использование readlink() не оставляет места для ввода пустого признака конца.

Риск

readlink() функция копирует содержимое символьной ссылки (первый аргумент) в буфер (второй аргумент). Однако функция не добавляет к скопированному содержимому терминатор null. После использования readlink(), необходимо явно добавить в буфер терминатор NULL.

При заполнении всего буфера при использовании readlink, вы не оставляете места для этого пустого терминатора.

Зафиксировать

При использовании readlink() убедитесь, что третий аргумент меньше размера буфера.

Затем добавьте в буфер нуль-терминатор. Чтобы определить, куда добавить терминатор null, проверьте возвращаемое значение readlink(). Если возвращаемое значение равно -1, произошла ошибка. В противном случае возвращаемое значение представляет собой количество скопированных символов (байт).

Примеры

развернуть все

#include <unistd.h>

#define SIZE1024 1024

extern void display_path(const char *);

void func() {
    char buf[SIZE1024];
    ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf));
    if (len > 0) {
        buf[len - 1] = '\0';
    }
    display_path(buf);
}

В этом примере третий аргумент readlink точно соответствует размеру буфера (второй аргумент). Если первый аргумент достаточно длинный, это использование readlink не оставляет места для пустого терминатора.

Кроме того, если символы не копируются, возвращается значение readlink равно 0. Следующая инструкция приводит к недопотою буфера, когда len равно 0.

buf[len - 1] = '\0';

Исправление - убедитесь, что аргумент размера меньше размера буфера

Одной из возможных корректировок является проверка того, что третий аргумент readlink на единицу меньше размера второго аргумента.

Следующий исправленный код также учитывает readlink возврат 0.

#include <stdlib.h>
#include <unistd.h>

#define fatal_error() abort()
#define SIZE1024 1024

extern void display_path(const char *);

void func() {
    char buf[SIZE1024];
    ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf) - 1); 
    if (len != -1) {
        buf[len] = '\0';
        display_path(buf);
    }
    else {
        /* Handle error */
        fatal_error();
    }
}

Информация о результатах

Группа: Безопасность
Язык: C | C++
По умолчанию: Откл.
Синтаксис командной строки: READLINK_MISUSE
Воздействие: среднее
ИДЕНТИФИКАТОР CWE: 170
Представлен в R2017a