CERT C: Rule POS38-C

Остерегайтесь условий гонки при использовании вилок и файловых дескрипторов

Описание

Определение правила

Остерегайтесь условий гонки при использовании вилок и файловых дескрипторов.[1]

Реализация Polyspace

Эта проверка проверяет доступность дескриптора файла для дочернего процесса.

Примеры

расширить все

Проблема

Воздействие дескриптора файла на дочерний процесс происходит, когда процесс соединяется, и дочерний процесс использует дескрипторы файлов, унаследованные от родительского процесса.

Риск

Когда вы разворачиваете дочерний процесс, дескрипторы файлов копируются из родительского процесса, что означает, что у вас могут быть параллельные операции с одним и тем же файлом. Использование одного и того же дескриптора файла в родительских и дочерних процессах может привести к расовым условиям, которые могут не быть захвачены во время стандартной отладки. Если вы неправильно управляете разрешениями и привилегиями дескриптора файла, содержимое файла уязвимо для атак, направленных на дочерний процесс.

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

Убедитесь, что файл не был изменен до раскрутки процесса. Закройте все наследуемые дескрипторы файлов и снова откройте их с более строгими разрешениями и привилегиями, такими как разрешение только для чтения.

Пример - Дескриптор файла, доступ к которому осуществляется из Forked Process
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <fcntl.h>
# include <sys/types.h>
# include <sys/stat.h>



const char *test_file="/home/user/test.txt";

void func(void)
{
    char c;
    pid_t pid;
	/* create file descriptor in read and write mode */
    int fd = open(test_file, O_RDWR); 
    if (fd == -1)
    {
        /* Handle error */
		abort();
    }
	/* fork process */
    pid = fork();
    if (pid == -1)
    {
        /* Handle error */
		abort();
    }
    else if (pid == 0)
    {   /* Child process accesses file descriptor inherited 
		from parent process */
        (void)read(fd, &c, 1);
	}
    else
    {   /* Parent process access same file descriptor as 
		child process */
        (void)read(fd, &c, 1);
    }
}
      

В этом примере дескриптор файла fd создается в режиме чтения и записи. Затем процесс разветвляется. Дочерний процесс наследует и обращается к fd с теми же разрешениями, что и родительский процесс. Между родительским и дочерним процессами существует условие расы. Содержимое файла уязвимо для атак через дочерний процесс.

Коррекция - закройте и повторно откройте наследованный дескриптор файла

После создания дескриптора файла проверьте файл на наличие подделки. Затем закройте наследуемый дескриптор файла в дочернем процессе и снова откройте его в режиме только для чтения.

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <fcntl.h>
# include <sys/types.h>
# include <sys/stat.h>


const char *test_file="/home/user/test.txt";

void func(void)
{
    char c;
    pid_t pid;

    /* Get the state of file for further file tampering checking */
	
	/* create file descriptor in read and write mode */
    int fd = open(test_file, O_RDWR);  
    if (fd == -1)
    {
        /* Handle error */
		abort();
    }

    /* Be sure the file was not tampered with while opening */
	
	/* fork process */

    pid = fork();
    if (pid == -1)
    {
        /* Handle error */
        (void)close(fd);
		abort();
    }
    else if (pid == 0)
    {  /* Close file descriptor in child process and repoen 
		it in read only mode */
		
        (void)close(fd);
        fd = open(test_file, O_RDONLY); 
        if (fd == -1)
        {
            /* Handle error */
			abort();
        }


        (void)read(fd, &c, 1);
        (void)close(fd);
    }
    else
    {  /* Parent acceses original file descriptor */
        (void)read(fd, &c, 1);
        (void)close(fd);
    }
}

Проверяйте информацию

Группа: Правило 50. POSIX (POS)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.