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