Инструкция по проведению разметки результатов статического анализа ядра Linux
В рамках первичного анализа предупреждений необходимо выполнить следующие шаги.
1. Выставить вердикт:
- «Подтверждено» (
`Confirmed`) - ошибка, которую рекомендуется исправить; - «Не актуально» (
`Won't fix`) - истинное срабатывание, которое по тем или иным причинам исправлять нецелесообразно (в коде, действительно, присутствует проблема, о которой сообщил инструмент, но эта проблема не создаёт недостатков в ходе функционирования программы); - «Ложное срабатывание» (
`False Positive`) - ложное срабатывание инструмента статического анализа (проблема, о которой сообщил инструмент, на самом деле в коде отсутствует).
2. На вкладке `Comment` необходимо оставить комментарий, поясняющий
вердикт. Комментарий должен быть достаточен, чтобы другой эксперт мог понять основания для принятого решения без
проведения тщательного анализа исходных текстов ядра. Формулировка пояснений общего вида, таких как «Не
эксплуатируемо», «Не несёт угроз безопасности информации», «Не применимо» и т. п. не допускается. Комментарий
необходимо оставлять, вне зависимости от того, какой вердикт выставлен. Для вердикта «Подтверждено» (`Confirmed`) в
комментарии необходимо указывать какая ошибка подлежит устранению.
Основное отличие между статусами `Won't fix` и `False Positive` с точки зрения дальнейших процедур заключается в
том, что для `False Positive` мы рассчитываем, что их можно устранить доработкой инструмента и с этой целью они
будут передаваться разработчикам инструмента Svace.
Для предупреждений с вердиктом «Подтверждено» также необходимо провести оценку значимости выявленной проблемы с точки зрения безопасности. Выделяется три градации:
- (Косметическая) Влияние на безопасность системы полностью отсутствует (например, лишняя проверка, недостижимый код).
- (Незначительная) Влияние на безопасность системы незначительное (например, проблемы, проявляющиеся при обработке ошибок, которые сложно инициировать непривилегированному пользователю).
- (Значительная) Существуют сценарии, в которых влияние проблемы на безопасность системы может быть значительным.
Для отражения сделанной оценки используется атрибут `Marker severity` (Серьезность маркера) в Svacer: `Minor`,
`Major` и `Critical`. Обоснование для выставленной оценки должно быть зафиксировано в комментарии к предупреждению.
Типовые ситуации при разметке предупреждений в ядре
- Защитное программирование
- Недостижимый код, зависящий от конфигурации
- FREE_OF_ARITHM при получении указателя на структуру по указателю на одно из её полей
- VARIABLE_IS_NOT_ARRAY.PROC при работе с массивами длины
1 - SIGNED_TO_BIGGER_UNSIGNED
- DEREF_AFTER_FREE при итерации по спискам
- SIZEOF_POINTER_TYPE для функций, не связанных с выделением памяти
- PROC_USE.VULNERABLE при использовании функции
sprintf() - NULL_AFTER_DEREF
- NO_CAST.INTEGER_OVERFLOW
- DEREF_OF_NULL.RET.STAT для
mempool_alloc()с маской GFP_NOFS - DIVISION_BY_ZERO.UNDER_CHECK для делителя, полученного из выражения с возможностью переполнения
- UNCHECKED_FUNC_RES.STAT: игнорирование возвращаемого значения
of_property_*() - NO_EFFECT: игнорирование предупреждения на проверку вида
len < 0, когдаlenобъявлена какunsigned - NO_CAST.INTEGER_OVERFLOW: проверка размера памяти должна проводится перед передачей ее в функцию аллокации
Защитное программирование
В качестве примера можно привести детекторы вида UNREACHABLE_CODE.ENUM или UNREACHABLE_CODE.DEFAULT, срабатывания которых сообщают о недостижимости кода в switch для ветки по умолчанию, в которой содержится та или иная отладочная печать. Например:
switch () {
case ENUM1:
...
default:
dev_dbg(ice_pf_to_dev(pf), "Invalid container type %d\n", c_type);
return -EINVAL;
}
Этот код, действительно, недостижим при нормальной работе ядра. Тем не менее, его, как правило, имеет смысл оставить, чтобы при возникновении нештатных ситуаций, управление пошло по более контролируемой логике, и в журнале появилась информация об обнаружении нештатной ситуации.
Аналогичная ситуация возникает при срабатывании детекторов вида UNREACHABLE_CODE при вызове функций, которые всегда возвращают ноль. Тем не менее, для многих из них можно предположить, что реализация со временем может измениться, и функция начнёт возвращать код ошибки. Поэтому обработку кода ошибки можно оставить на будущее.
В этом случае рекомендуется выставить вердикт Won't fix и написать комментарий:
Защитное программирование.
Недостижимый код, зависящий от конфигурации
Детекторы вида UNREACHABLE_CODE.* сообщают о недостижимости кода, который, действительно, недостижим в конфигурации, которая подвергалась статическому анализу, но может быть достижим в другой конфигурации. В SVACE в будущем планируется поддержать выявление таких ситуаций и подавлять такие предупреждения.
До тех пор при разметке предупреждений рекомендуется выставить вердикт Won't fix и написать комментарий Код достижим в другой конфигурации.
FREE_OF_ARITHM при получении указателя на структуру по указателю на одно из её полей
Срабатывает детектор FREE_OF_ARITHM, сигнализирующий о том, что происходит освобождение указателя, полученного смещением относительно указателя, поступившего на вход анализируемой функции.
Стандартный приём, используемый в ядре Linux: работа с указателем на одно из полей структуры (например, на поля, которые являются ссылками вперед-назад для двунаправленного списка) и при необходимости получение указателя на начало структуры путём применения макроса container_of к указателю на её поле. Используется для работы со списками, RCU, в различных видах циклов и в других случах. Если при приведении используется макрос contaner_of, вызванный с корректными параметрами, то использование такого приёма является безопасным, а освобождение памяти — корректным.
Пример:
struct ip6_flowlabel {
...
struct rcu_head rcu;
...
};
static void fl_free_rcu(struct rcu_head *head)
{
struct ip6_flowlabel *fl = container_of(head, struct ip6_flowlabel, rcu);
...
kfree(fl); // <-- FREE_OF_ARITHM
}
static void fl_free(struct ip6_flowlabel *fl)
{
...
call_rcu(&fl->rcu, fl_free_rcu);
}
При разметке предупреждений рекомендуется выставить вердикт Won't fix и написать комментарий:
Использование container_of для получения указателя на начало структуры.
VARIABLE_IS_NOT_ARRAY.PROC при работе с массивами длины 1
Возникает при передаче переменной как массива (указатель и длина) при вызове функций типа of_property_read_*() или copy_from_user().
Пример:
static int mmc_of_get_func_num(struct device_node *node)
{
u32 reg;
int ret;
ret = of_property_read_u32(node, "reg", ®);
if (ret < 0)
return ret;
return reg;
}
При применении этого правила важно убедиться, что тип указателя у вызываемой функции совпадает с типом переменной, а в качестве длины массива передаётся единица.
Рекомендации по разметке: Won't fix с комментарием:
Переменная рассматривается как массив размера .1 с целью унификации кода при работе как с единичными объектами, так и с массивами
SIGNED_TO_BIGGER_UNSIGNED
Возникает при присваивании выражения знакового типа переменной беззнакового типа большей разрядности (при этом происходит sign extension). Как правило, надо исправлять типы переменных.
Пример:
int typec_set_mode(struct typec_port *port, int mode)
{
struct typec_mux_state state = { };
state.mode = mode;
return typec_mux_set(port->mux, &state);
}
Рекомендации по разметке: Confirmed/Minor/Fix required.
DEREF_AFTER_FREE при итерации по спискам
Срабатывают следущие детекторы: DEREF_AFTER_FREE.
Стандартный прием безопасного удаления элемента списка при обходе. Для этого используется макрос
list_for_each_entry_safe():
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member), \
n = list_next_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = n, n = list_next_entry(n, member))
Пример:
static void serio_free_event(struct serio_event *event)
{
module_put(event->owner);
kfree(event);
}
static void serio_remove_pending_events(void *object)
{
struct serio_event *event, *next;
unsigned long flags;
spin_lock_irqsave(&serio_event_lock, flags);
list_for_each_entry_safe(event, next, &serio_event_list, node) { // <-- DEREF_AFTER_FREE
if (event->object == object) {
list_del_init(&event->node); // Элемент удаляется из списка
serio_free_event(event); // Освобождается память, но next элемент остается! В конце цикла происходит инициализация event = next;
}
}
spin_unlock_irqrestore(&serio_event_lock, flags);
}
Ввиду сложных операций с указателями инструмент считает, что возможно дальнейшее использование уже освобождённого указателя.
Рекомендации по разметке: False Positive с комментарием:
Происходит обращение к следующему элементу списка, а не к освобождённому.
SIZEOF_POINTER_TYPE для функций, не связанных с выделением памяти
Данный тип детектора предназначен для обнаружения несоответствий в конструкциях вида x = (T1*)alloc(sizeof(T2)), когда тип передаваемый в оператор sizeof() не соответствует по размеру типу, к которому приводится результирующий указатель. Если инструмент обнаруживает похожую конструкцию, которая используется не для выделения памяти, то предупреждение будет ошибочным.
Например при использовании макроса:
#define cmpxchg(ptr, ...) \
({ \
typeof(ptr) __ai_ptr = (ptr); \
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
arch_cmpxchg(__ai_ptr, __VA_ARGS__); \
})
#endif
где arch_cmpxchg в свою очередь расширяется в:
#define __cmpxchg_wrapper(sfx, ptr, o, n) \
({ \
__typeof__(*(ptr)) __ret; \
__ret = (__typeof__(*(ptr))) \
__cmpxchg##sfx((ptr), (unsigned long)(o), \
(unsigned long)(n), sizeof(*(ptr))); \
__ret; \
})
Рекомендации по разметке: False Positive с комментарием:
Вызываемая функция не является функцией выделения памяти, на которые нацелен данный детектор.
PROC_USE.VULNERABLE при использовании функции sprintf()
Предупреждения относительно небезопасности использования sprintf() при подготовки вывода содержимого псевдофайлов, например, в sysfs.
Пример:
return sprintf(buf, "%d\n", udev->rx_lanes);
Рекомендации по разметке: Confirmed/Minor/Fix required.
При подготовке патча согласно последним тенденциям в таких случаях предлагается использовать вспомогательные функции sysfs_emit()/sysfs_emit_at() или scnprintf().
В случае если подготовленный патч с данным исправлением не был принят мейнтейнерами, изменить разметку на Won't fix/Minor/Ignore и в комментарии к предупреждению добавить ссылку на ответ мейнтейнера.
NULL_AFTER_DEREF
Детектор NULL_AFTER_DEREF обнаруживает ситуации, когда сначала переменная безусловно разыменовывается, а
затем сравнивается с NULL.
Чаще всего это происходит в следующих случаях:
Первый, это бессмысленная проверка на NULL указателя на поле структуры, которую надо удалить, указав в
комментарии причины, почему она действительно лишняя.
Пример:
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
break;
Это избыточная проверка, так как после присваивания адреса поля структуры, указатель гарантированно не будет равным
NULL, даже если значение указателя на структуру было NULL. Эта неадекватная проверка на
NULL не является проблемой с точки зрения безопасности, но является проблемой с точки зрения качества
кода. Если по случаю смещение поля структуры относительно начала структуры является нулевым, то всё равно код
рекомендуется исправить.
Рекомендации по разметке: Confirmed/Minor/Fix required с комментарием вида:
Да, pipe_ctx не может быть нулевым. Неадекватная проверка на NULL не является проблемой с точки зрения безопасности, но является проблемой с точки зрения качества кода.
Второй, когда безусловное разыменование было добавлено в код позже, без учета возможного разыменования 0.
Пример:
struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
if (!dev)
return -ENODEV;
В этом коде dev сначала разыменовывается, а потом сравнивается с 0.
В этом случае надо добавить аналогичную проверку перед безусловным разыменованием либо перенести инициализацию
переменной ssb_dev после проверки.
Рекомендации по разметке: Confirmed, уровень критичности Major с комментарием, объясняющим причину,
по которой безусловное разыменование тут не верно.
NO_CAST.INTEGER_OVERFLOW
Svace выдает это предупреждение в случае, когда слева от знака присваивания = (или от любого из знаков сравнения >, >=, <, <=) стоит переменная, размер типа которой больше? чем у переменных, стоящих в арифметическом выражении справа, без явного приведения к большему типу. При этом не учитывается "Integer Promotion" (см. ниже) и сами действия внутри выражения. Примеры:
size_t clen;
clen = 1 + (c32 >= 0x800) + (c32 >= 0x10000);
u64 tmp_gw_factor = 0;
u8 tq_avg;
tmp_gw_factor = tq_avg * tq_avg;
unsigned long temp_rem;
int shift, n_rem;
temp_rem = n_rem << shift;
if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb))
В процессе анализа комментариев на это предупреждение выяснилось, что существует мнение, что если int складывается или перемножается с int и присваивается в long, то переполнения не будет. На самом деле переполнение возможно, так как значение выражения int+int (или int*int, или даже char<<char) сначала приведется к int и только потом присвоится в long.
Эта ситуация называется "Integer Promotion" и описывается в п. 6.3.1.1 стандарта C99. Загрузить его можно отсюда: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf.
Вот как это выглядит в ассемблере:
addl %edx, %eax
cltq
movq %rax, -8(%rbp)
То есть это будет выглядеть, как обрезание результата вычисления выражения, если операнды были близки к INT_MAX.
Еще одним неочевидным следствием является то, что если старший бит результата будет 1, например, 0x80000000, то в long присвоится 0xffffffff80000000.
Рекомендации по разметке для таких случаев следующие.
Если результат вычисления выражения гарантированно будет меньше INT_MAX (или UINT_MAX) то Won't fix с объяснением в комментарии, почему оно меньше.
Если убедиться в этом не удалось, то Confirmed.
При подготовке патча можно привести один из операндов выражения к типу переменной слева от присваивания (long, size_t, 1ULL), или использовать специальные функции вида mul_u32_u32.
Примеры комментариев на такое предупреждение:
/drivers/firmware/efi/libstub/vsprintf.c:519
size_t clen;
clen = 1 + (c32 >= 0x800) + (c32 >= 0x10000);
Комментарий:
Значения в скобках возвращают 0 или 1, и переполнение не возникнет.
/net/batman-adv/bat_iv_ogm.c:2444
u64 tmp_gw_factor = 0;
u8 tq_avg;
tmp_gw_factor = tq_avg * tq_avg;
Комментарий:
Так как tq_avg имеет тип u8, то при умножении максимального значения 255 на 255, получится 65025, которое меньше чем INX_MAX. Переполнения не будет.
/fs/reiserfs/do_balan.c:805
unsigned long temp_rem;
int shift, n_rem;
temp_rem = n_rem << shift;
Комментарий:
В reiserfs размер блока 4K, чему соответствует значение s_blocksize_bits = 12, при делении на 4 (- UNFM_P_SHIFT) максимальный сдвиг составит 10 разрядов. В данном фрагменте выполняется работа с ключами в пределах блока 4К, таким образом максимальное значение n_rem, сдвинутое на 10 разрядов не выйдет за пределы 31 разряда (int).
/fs/btrfs/disk-io.c:2509
if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb))
Комментарий:
Функции btrfs_super_nodesize() и btrfs_super_bytes_used() определяются, используя макро в модуле ctree.h:
static inline u##bits btrfs_##name(const type *s) \
{ \
return get_unaligned_le##bits(&s->member); \
} \
BTRFS_SETGET_STACK_FUNCS(super_nodesize, struct btrfs_super_block,
nodesize, 32);
BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block,
bytes_used, 64);
Они дают доступ к полям не выровненного суперблока btrfs_super_block *sb
__le64 bytes_used;
__le32 nodesize;
Статический анализатор здесь предупреждает, что слева от знака '<' стоит 64-битное число, а справа 32-битное умножается на 6, и возможно переполнение, так как автоматического преобразования правой части в 64-битное число не будет. Однако переполнения не случится, так как максимальный размер nodesize по документации равен 65536, и выше стоит сравнение nodesize > BTRFS_MAX_METADATA_BLOCKSIZE (равно 65536) с присвоением ret = -EINVAL.
DEREF_OF_NULL.RET.STAT для mempool_alloc() с маской GFP_NOFS
При использовании функции mempool_alloc() с параметром GFP_NOFS SVACE детектор DEREF_OF_NULL.RET.STAT выдаёт предупреждение о возможном разыменовании нулевого указателя.
Например, smb2transport.c:720:
temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
memset(temp, 0, sizeof(struct mid_q_entry));
kref_init(&temp->refcount);
temp->mid = le64_to_cpu(shdr->MessageId);
В комментарии к этой функции написано:
Note that due to preallocation, this function never fails when called from process contexts (it might fail if called from an IRQ context).
Если в месте предупреждения можно показать, что вызов функции mempool_alloc() с маской GFP_NOFS никогда не может случиться из атомарного контекста, то проверять возвращаемое значение не требуется. См. также коммит, где подобная проверка mempool_alloc() удаляется, как лишняя.
В этом случае рекомендуется выставить вердикт Won't fix и написать комментарий:
В данном месте вызов mempool_alloc() никогда не может случиться в атомарном контексте, так как {ОБОСНОВАНИЕ ЭТОГО}. Поэтому выделение памяти при помощи mempool_alloc() с маской GFP_NOFS всегда завершится успешно, и проверка возвращаемого значения не требуется.
DIVISION_BY_ZERO.UNDER_CHECK для делителя, полученного из выражения с возможностью переполнения
В коде ниже переменная p_limit2, присутствующая в делителе, проверяется на 0, чтобы избежать деления на ноль. Но оно все равно может произойти при некоторых значениях p_limit2.
1823 u32 p_limit2 = rdev->pm.dpm.near_tdp_limit;
...
1830 if (p_limit2 != 0 && p_limit2 <=p_limit1) {
1831 dte_data->tdep_count = 3;
1832
1833 for (i = 0; i < k; i++) {
1834 dte_data->r[i] =
1835 (t_split[i] * (t_max -t_0/(u32)1000) * (1 << 14)) /
1836 (p_limit2 * (u32)100);
1837 }
Например, если p_limit2 = 1073741824 умножить на 100, то произойдет переполнение, так как результат в соответствии с integer promotion, приведется к u32 и старшие значимые биты отбросятся, а младшие 32 бита будут равны нулю, что приведет к делению на ноль.
В случае, если результат вычисления выражения для делителя гарантированно будет меньше INT_MAX (или UINT_MAX), то рекомендуется выставить вердикт Won't fix с объяснением в комментарии, почему при вычислении выражения для делителя не может произойти переполнение. В случае, если убедиться в этом не удалось, то вердикт должен быть Confirmed. При подготовке патча можно привести числитель и знаменатель к long.
UNCHECKED_FUNC_RES.STAT:игнорирование возвращаемого значения of_property_*()
В коде ядра встречаются ситуации, когда игнорирование возвращаемого значения функций чтения параметров Device Tree является корректным. Такое возникает, когда отсутствие читаемого параметра в Device Tree является ожидаемым, и в этом случае используется значение параметра по умолчанию, которое помещается в заполняемую переменную перед вызовом указанных функций.
Данные функции обычно получают на вход имя требуемого параметра в Device Tree и адрес переменной, куда надо записать его значение. Для того, чтобы определить необходимость проверки кода возврата в конкретном случае, требуется следующее.
-
Проверить, инициализирована ли уже данная переменная:
- присвоено ли ей какое-либо значение явным образом;
- произошла ли неявная инициализация при выделение памяти, например, за счёт использования функции семейства
kzalloc()или за счёт определения переменной в глобальном сегменте данных.
-
Далее, попытаться оценить возможность появления проблем с безопасностью в случае дальнейшего использования этой переменной с дефолтным значением.
Если проблем с безопасностью не выявлено, следует поставить статус
Won't fixи в комментарии отразить проведенное исследование.Если проблемы возможны или переменная не инициализирована, то следует поставить статус
Confirmedи уровень критичностиMajorилиCritical.
Например: /drivers/leds/leds-pca9532.c:483:
479 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
480 if (!pdata)
481 return ERR_PTR(-ENOMEM);
482
483 of_property_read_u8_array(np, "nxp,pwm", &pdata->pwm[0],
484 ARRAY_SIZE(pdata->pwm));
pdata инициализируется нулями, следовательно, в случае, если of_property_read_u8_array() не сможет прочесть значение property nxp,pwm, то pwm останется равным 0. Далее pwm используется для управления миганием светодиода. Значит, в худшем случае, диод будет мигать не так, как задумано. Угрозы безопасности это не несет.
В противном случае, простое добавление проверки кода возврата функции с выходом из нее в случае ошибки может привести к проблемам с работой существующих устройств, которым не требуется явное выставление значения этого параметра в Device Tree.
Например, /drivers/soundwire/qcom.c:773:
773 ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
774 bp_mode, nports);
Здесь был принят коммит a5943e4fb14e36df980f1814e2bd5ed3e4de4e87, добавляющий проверку кода возврата, с описанием: "The return value is checked for all other cases, not sure why it was missed here".
Через полтора месяца он был исправлен коммитом da096fbccd52803db3edd9dd0c5ae4079d31c456, в котором для новых версий контроллера оставили ошибочный код возврата функции, а для старых версий добавили специальную инициализацию переменной. В описании отмечено: "returning on error for those cases will break boards like DragonBoard DB845c and Lenovo Yoga C630".
NO_EFFECT: игнорирование предупреждения на проверку вида len < 0, когда
len объявлена как unsigned
При оценке предупреждения NO_CAST.INTEGER_OVERFLOW была найдена ситуация, когда размер выделяемой памяти приходит от пользователя и никак не проверяется в драйвере перед вызовом функции аллокации памяти.
Например: /fs/notify/fanotify/fanotify_user.c:466
WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN);
Исправление этой проблемы не требуется по следующим причинам:
- Эта проверка не ухудшает производительность, так как компилятор уберет ее при оптимизации кода.
- Ухудшается читаемость кода, потому что объявление переменной может быть достаточно далеко от кода с проверкой, поэтому для человека проверка диапазона, которая в том числе проверяет и на неотрицательность, является гораздо более явной и очевидной.
Об этом указано в патче от Линуса Торвальдса, который отменяет патч e6595224464b692ddae193d783402130d1625147 с исправлением указанной проблемы.
Тут следует поставить статус Won't fix и написать комментарий
Проверка действительно избыточная, но она будет убрана компилятором. А для читаемости кода лучше все оставить как есть.
NO_CAST.INTEGER_OVERFLOW: проверка размера памяти должна проводится перед
передачей ее в функцию аллокации
При оценке предупреждения NO_CAST.INTEGER_OVERFLOW была найдена ситуация, когда размер выделяемой памяти приходит от пользователя и никак не проверяется в драйвере перед вызовом функции аллокации памяти.
Например: /drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c:239
info = kvmalloc_array(in->bo_number, info_size, GFP_KERNEL);
if (!info)
return -ENOMEM;
/* copy the handle array from userspace to a kernel buffer */
r = -EFAULT;
if (likely(info_size == in->bo_info_size)) {
unsigned long bytes = in->bo_number * in->bo_info_size;
Значение in->bo_number получается из параметра ioctl вызова DRM_IOCTL_AMDGPU_BO_LIST и
используется для вычисления
размера выделяемой памяти в kvmalloc_array(). При этом этот размер никак не проверяется, что может
приводить
попыткам со стороны пользователя вызвать ситуацию out of memory при помощи, например, такого кода:
union drm_amdgpu_bo_list bo_list;
int fd, ret;
memset(&bo_list, 0, sizeof(bo_list));
fd = open(DEVICE_PATH, O_RDWR);
bo_list.in.bo_number = 1 << 31;
ret = ioctl(fd, DRM_IOCTL_AMDGPU_BO_LIST, &bo_list);
В комментарии Линуса Торвальдса к этой проблеме сказано, что размер памяти, который передаётся в функции аллокации, должен проверяться кодом драйверов или других компонентов ядра, исходя из некоторых разумных предположений об адекватном размере, который может быть.
Таким образом, в случаях, когда переменные, оцениваемые при исследовании предупреждения
NO_CAST.INTEGER_OVERFLOW и
его аналогов, используются в функциях аллокации, следует также оценивать наличие проверок, ограничивающих размер
выделяемой памяти. Если их нет, то рекомендуется выставить статус Confirmed и описать проблему в
комментарии к
предупреждению.
Взаимодействие с международным сообществом
Для отправки патчей в основную ветку ядра следуйте следующим инструкциям:
Отправка патчей в ядро.