ПроблемаИнформационная утечка через дополнение структуры происходит, когда вы не инициализируете дополнительные данные структуры или объединения прежде, чем передать его через доверительный контур. Компилятор добавляет дополнительные байты в структуру или объединение, чтобы гарантировать соответствующее выравнивание памяти ее членов. Битовые поля устройств хранения данных могут также иметь дополнительные биты.
Информационная утечка через дополнение структуры повышает дефект когда:
Вы вызываете недоверяемую функцию со структурой или аргументом типа указателя объединения, содержащим неинициализированные дополнительные данные.
Все внешние функции рассматриваются недоверяемыми.
Вы копируете или присваиваете структуру или объединение, содержащее неинициализированные дополнительные данные к недоверяемому объекту.
Вся внешняя структура или объекты объединения, выходные параметры всех внешне соединенных функций и указатель возврата всех внешних функций рассматриваются недоверяемыми объектами.
РискДополнительные байты переданной структуры или объединения могут содержать уязвимую информацию, к которой может получить доступ недоверяемый источник.
ФиксацияПредотвратите сложение дополнения байтов для выравнивания памяти при помощи pack
прагма или атрибут поддержаны вашим компилятором.
Явным образом объявите и инициализируйте дополнительные байты как поля в структуре или объединении.
Явным образом объявите и инициализируйте соответствие битовых полей дополнению битов, даже если вы используете pack
прагма или атрибут поддержаны вашим компилятором.
Пример - структура с дополнением байтов, пройден к внешней функции#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef struct s_padding
{
/* Padding bytes may be introduced between
* 'char c' and 'int i'
*/
char c;
int i;
/*Padding bits may be introduced around the bit-fields
* even if you use "#pragma pack" (Windows) or
* __attribute__((__packed__)) (GNU)*/
unsigned int bf1:1;
unsigned int bf2:2;
unsigned char buffer[20];
} S_Padding ;
/* External function */
extern void copy_object(void *out, void *in, size_t s);
void func(void *out_buffer)
{
/*Padding bytes not initialized*/
S_Padding s = {'A', 10, 1, 3, {}};
/*Structure passed to external function*/
copy_object((void *)out_buffer, (void *)&s, sizeof(s));
}
void main(void)
{
S_Padding s1;
func(&s1);
}
В этом примере, структура s1
может иметь дополнительные байты между char c
и int i
члены. Битовые поля устройств хранения данных структуры могут также содержать дополнительные биты. Содержимое дополнительных байтов и битов доступно для недоверяемого источника когда s1
передается func
.
Коррекция — использует pack
Прагма, чтобы предотвратить дополнительные байтыОдна возможная коррекция в Microsoft® Visual Studio®is, чтобы использовать #pragma pack()
предотвратить дополнительные байты между элементами структуры. Предотвратить дополнительные биты в битовых полях s1
, явным образом объявите и инициализируйте битовые поля, даже если вы используете #pragma pack()
.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define CHAR_BIT 8
#pragma pack(push, 1)
typedef struct s_padding
{
/*No Padding bytes when you use "#pragma pack" (Windows) or
* __attribute__((__packed__)) (GNU)*/
char c;
int i;
unsigned int bf1:1;
unsigned int bf2:2;
/* Padding bits explicitely declared */
unsigned int bf_filler : sizeof(unsigned) * CHAR_BIT - 3;
unsigned char buffer[20];
}
S_Padding;
#pragma pack(pop)
/* External function */
extern void copy_object(void *out, void *in, size_t s);
void func(void *out_buffer)
{
S_Padding s = {'A', 10, 1, 3, 0 /* padding bits */, {}};
copy_object((void *)out_buffer, (void *)&s, sizeof(s));
}
void main(void)
{
S_Padding s1;
func(&s1);
}