Project

General

Profile

Wiki » History » Version 13

Елена Кузьмина, 06/30/2022 04:49 PM

1 7 Alexey Khoroshilov
{{toc}}
2
3 4 Alexey Khoroshilov
h2. Статический анализ ядра
4
5 5 Alexey Khoroshilov
Инструкции по работе с интерфейсом разметки (SVACER) доступны в разделе "файлы":https://forge.ispras.ru/projects/lvc/files.
6
7
8 4 Alexey Khoroshilov
Для получения доступа к временному серверу для совместной работы над разметкой предупреждений SVACE пишите:
9
khoroshilov@ispras.ru
10
11 5 Alexey Khoroshilov
На этом сервере необходимо выбрать проект linux, ветка linux-5.10.y, в которой есть единственный снэпшот с результатами.
12
13
Для того, чтобы отфильтровать те предупреждения, которые относятся к выбранным подсистемам в режиме Review необходимо нажать на кнопку Filters->Basic...
14
и внизу в поле Files ввести список интересующих путей, например:
15
<pre>
16
security/selinux;net/ipv4
17
</pre>
18
При этом надо убедиться, что кнопка .* рядом с Files нажата.
19
20
По результатам анализа 
21
# Необходимо выставить вердикт:
22
** Confirmed -- ошибка, которую рекомендуется исправить
23
** Won't fix -- истинное срабатывание, которое по тем или иным причинам исправлять нецелесообразно
24
** False Positive - ложное срабатывание инструмента статического анализа
25
** Unclear - требуется дополнительный анализ
26
# На вкладке Comment необходимо оставить комментарий, поясняющий вердикт.
27
  Сейчас это обязательно хотя бы в самом коротком виде, т.к. это единственный способ увидеть автора проведённого исследования предупреждения.
28 7 Alexey Khoroshilov
29
h3. Типовые ситуации при разметке предупреждений в ядре
30
31
h4. Защитное программирование
32
33
Например, чекеры вида UNREACHABLE_CODE.ENUM сообщают о недостижимости кода в switch для ветки по умолчанию, в которой содержится та или иная отладочная печать, например:
34
35
<pre><code class="c">
36
  switch () {
37
  case ENUM1:
38
  ...
39
  default:
40
    dev_dbg(ice_pf_to_dev(pf), "Invalid container type %d\n", c_type);
41
    return -EINVAL;
42
  }
43
</code></pre>
44
45
Этот код, действительно, недостижим при нормальной работе ядра. Тем не менее, его как правило имеет смысл оставить, чтобы при возникновении нештатных ситуаций, управление пошло по более контролируемой логике и в журнале появилась информация об обнаружении нештатной ситуации.
46
47
В этом случае рекомендуется выставить вердикт @Won't fix@ и написать комментарий @Защитное программирование@.
48
49 8 Alexey Khoroshilov
h4. Недостижимый код, зависящий от конфигурации
50
51
Чекеры вида UNREACHABLE_CODE.* сообщают о недостижимости кода, в который, действительно, недостижим в конфигурации, которая подвержалась статическому анализу, но может быть достижим в другой конфигурации. В SVACE в будущем планируется поддержать выявление таких ситуаций и подавлять предупреждения.
52
53
До тех пор при разметке предупреждений рекомендуется выставить вердикт @Won't fix@ и написать комментарий @Код достижим в другой конфигурации@.
54 5 Alexey Khoroshilov
55 9 Елена Кузьмина
h4. FREE_OF_ARITHM: Deallocating memory through a pointer 'fl' obtained as a result of arithmetic operation 
56
57
Срабатывают следущие чекеры: FREE_OF_ARITHM
58
59
Стандартный прием приведения члена структуры к содержащей его структуре. Используется для работы со списками, RCU, в различных видах циклов и пр. Т.к. для приведения используется макрос contaner_of, который производит арифметику, то использование такого приема вполне безопасно.
60 10 Alexey Khoroshilov
61 9 Елена Кузьмина
Пример:
62
<pre><code class="c">
63
struct ip6_flowlabel {
64
	...
65
	struct rcu_head		rcu;
66
	...
67
};
68
69
static void fl_free_rcu(struct rcu_head *head)
70
{
71
	struct ip6_flowlabel *fl = container_of(head, struct ip6_flowlabel, rcu);
72
        ...
73
	kfree(fl);  // // <-- FREE_OF_ARITHM
74
}
75
76
static void fl_free(struct ip6_flowlabel *fl)
77
{
78
        ...
79
	call_rcu(&fl->rcu, fl_free_rcu);
80
}
81
</code></pre>
82 10 Alexey Khoroshilov
83
При разметке предупреждений рекомендуется выставить вердикт @Won't fix@ и написать комментарий @Использование container_of@.
84 9 Елена Кузьмина
85 11 Елена Кузьмина
h4. PROC_USE.VULNERABLE
86
87
Чаще всего возникает при использовании функции sprintf() - как правило, для нужд sysfs. Мейнтейнеры находят поведение
88
безопасным (sysfs использует буфер размером PAGE_SIZE) и чаще всего не принимают патчи, меняющие sprintf() на безопасные функции.
89
90
Пример:
91
<pre><code class="c">
92
return sprintf(buf, "%d\n", udev->rx_lanes);
93
</code></pre>
94
95
Рекомендации по разметке: @Won't fix/Minor/Ignore@ .
96
97
h4. VARIABLE_IS_NOT_ARRAY.PROC
98
99
Возникает при передаче переменной как массива (указатель и длина) при вызове функций типа @of_property_read_*()@ или @copy_from_user()@.
100
101
Пример:
102
<pre><code class="c">
103
static int mmc_of_get_func_num(struct device_node *node)
104
{
105
	u32 reg;
106
	int ret;
107
108
	ret = of_property_read_u32(node, "reg", &reg);
109
	if (ret < 0)
110
		return ret;
111
	return reg;
112
}
113
</code></pre>
114
115 13 Елена Кузьмина
Рекомендации по разметке: @False Positive@ .
116 11 Елена Кузьмина
117
118
h4. UNREACHABLE_CODE.DEFAULT
119
120
Возникает, например, при наличии метки @default@, на которую управление попасть не должно (все метки @case@ со значениями типа @enum@ перечислены явно).
121
122
Пример:
123
<pre><code class="c">
124
/* entry requires deletion */
125
case FSCACHE_CHECKAUX_OBSOLETE:
126
	goto stale;
127
default:
128
	BUG();
129
130
</code></pre>
131
132
Рекомендации по разметке: @Won't fix/Minor/Ignore@ .
133
134
135
h4. SIGNED_TO_BIGGER_UNSIGNED
136
137
Возникает при присваивании выражения знакового типа переменной беззнакового типа большей разрядности (при этом происходит @sign extension@). Как правило, надо исправлять типы переменных.
138
139
Пример:
140
<pre><code class="c">
141
int typec_set_mode(struct typec_port *port, int mode)
142
{
143
	struct typec_mux_state state = { };
144
	state.mode = mode;
145
	return typec_mux_set(port->mux, &state);
146
}
147
</code></pre>
148
149
Рекомендации по разметке: @Confirmed/Minor/Fix required@ .
150
151
h4. NO_CAST.INTEGER_OVERFLOW
152
153 12 Alexey Khoroshilov
Возникает при неявном преобразовании выражения к типу большей разрядности, при этом переполнения на практике обычно не происходит.
154 11 Елена Кузьмина
Пример:
155
<pre><code class="c">
156
timeout_ns = udev->u1_params.sel * 3;
157
</code></pre>
158 1 Alexey Khoroshilov
159 13 Елена Кузьмина
Рекомендации по разметке: @False Positive@ .
160
161
h4. DEREF_AFTER_FREE: A pointer to memory pointer that has been deallocated, is dereferenced.
162
163
Срабатывают следущие чекеры: DEREF_AFTER_FREE
164
165
Стандартный прием безопасного удаления элемента списка при обходе. Для этого используется макрос 
166
<pre><code class="c">
167
list_for_each_entry_safe():
168
169
#define list_for_each_entry_safe(pos, n, head, member)			\
170
	for (pos = list_first_entry(head, typeof(*pos), member),	\
171
		n = list_next_entry(pos, member);			\
172
	     !list_entry_is_head(pos, head, member); 			\
173
	     pos = n, n = list_next_entry(n, member))
174
</code></pre>
175
176
Пример:
177
<pre><code class="c">
178
static void serio_free_event(struct serio_event *event)
179
{
180
	module_put(event->owner);
181
	kfree(event);
182
}
183
184
static void serio_remove_pending_events(void *object)
185
{
186
	struct serio_event *event, *next;
187
	unsigned long flags;
188
189
	spin_lock_irqsave(&serio_event_lock, flags);
190
191
	list_for_each_entry_safe(event, next, &serio_event_list, node) {  // <-- DEREF_AFTER_FREE
192
193
		if (event->object == object) {
194
			list_del_init(&event->node); // Элемент удаляется из списка
195
			serio_free_event(event);     // Освобождается память, но next элемент отстается! В конце цикла происходит инициализация event = next;
196
		}
197
	}
198
199
	spin_unlock_irqrestore(&serio_event_lock, flags);
200
}
201
</code></pre>
202
203
Совет по разметке: @False Positive@
204 11 Елена Кузьмина
205 4 Alexey Khoroshilov
h2. Взаимодействие с международным сообществом
206 1 Alexey Khoroshilov
207 6 Alexey Khoroshilov
Для отправки патчей в основную ветку ядра следуйте следующим инструкциям:
208
[[How_to_send_patches_to_kernel|Отправка патчей в ядро]].