Подробности

[В начало]

Проблема в реализации № K0005

Краткое описание

(ath5k) Не все элементы массива chinfo[pier].pd_curves[] освобождаются

Подробное описание

Некоторые из блоков памяти, выделенных с помощью kcalloc() в ath5k_eeprom_convert_pcal_info_*(), не удаляются даже при выгрузке модуля ath5k.

Трасса вызовов функций для одной итерации внешнего цикла 'for' в ath5k_eeprom_convert_pcal_info_2413(),
drivers/net/wireless/ath/ath5k/eeprom.c:1148:

// Создание chinfo[pier].pd_curves, строка 1153.
// Выделена память под 4 элемента типа struct ath5k_pdgain_info.
called___kmalloc: (.text+0x212f) arguments: (48, 80d0), result: ab3ad780

// Внутренний цикл, итерация 0, 
// создание pd->pd_step и pd->pd_pwr  
// для chinfo[pier].pd_curves[pdgain_idx[0]] (строки 1176 and 1182)
called___kmalloc: (.text+0x212f) arguments: (4, 80d0), result: ab1c3f68
called___kmalloc: (.text+0x212f) arguments: (8, 80d0), result: ab1c3f70

// Внутренний цикл, итерация 1, 
// создание pd->pd_step и pd->pd_pwr  
// для chinfo[pier].pd_curves[pdgain_idx[1]] (строки 1176 and 1182)
called___kmalloc: (.text+0x212f) arguments: (5, 80d0), result: ab1c3f78
called___kmalloc: (.text+0x212f) arguments: (10, 80d0), result: ab17ce80
<...> 

Трасса вызовов функций для одной итерации внешнего цикла 'for' в ath5k_eeprom_free_pcal_info(),
drivers/net/wireless/ath/ath5k/eeprom.c:1564:

// Внутренний цикл, итерация 0, строка 1573
called_kfree: (.text+0x20be) arguments: ((null))
called_kfree: (.text+0x20c6) arguments: ((null))

// Внутренний цикл, итерация 1, line 1573
called_kfree: (.text+0x20be) arguments: (ab1c3f78)
  called_kfree: (.text+0x20c6) arguments: (ab17ce80)

// Удаление массива chinfo[pier].pd_curves
called_kfree: (.text+0x20de) arguments: (ab3ad780)
<...> 

Аналогично - для остальных итераций внешних циклов 'for' в ath5k_eeprom_convert_pcal_info_*() и ath5k_eeprom_free_pcal_info().

ath5k_eeprom_free_pcal_info() пытается освободить поля 'pd_step' и 'pd_pwr' не для тех элементов, для которых это нужно.

На системе, где проявилась данная проблема, массив chinfo[pier].pd_curves[] состоял из 4 (AR5K_EEPROM_N_PD_CURVES) элементов, из которых использовались на практике только 2, №1 и №2, как и должно было быть. Элементы №0 и №3 оставались заполненными нулями.

Строка 1162:
    for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
        u8 idx = pdgain_idx[pdg];
        struct ath5k_pdgain_info *pd =
                &chinfo[pier].pd_curves[idx];

ee->ee_pd_gains[mode] было равно 2, массив pdgain_idx[] был {1; 2}. Судя по коду из eeprom.c, именно эти элементы и использовались в во всех операциях калибровки и пр.

Функция ath5k_eeprom_free_pcal_info(), тем не менее, работает по-другому. Она пытается освободить 'pd_step' и 'pd_pwr' для первых двух элементов массива chinfo[pier].pd_curves вместо тех двух элементов, для которых была выделена память:

    for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
        struct ath5k_pdgain_info *pd =
                &chinfo[pier].pd_curves[pdg];

        if (pd != NULL) {
            kfree(pd->pd_step);
            kfree(pd->pd_pwr);
        }
    }

Т.е., здесь обрабатываются элементы pd_curves[0] и pd_curves[1] вместо pd_curves[pdgain_idx[0]] и pd_curves[pdgain_idx[1]].

Способ воспроизведения

Чтобы воспроизвести проблему, достаточно загрузить модуль ath5k.ko, а затем выгрузить его.

Способы устранения

eeprom.c:1568:
-    for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+    for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
        struct ath5k_pdgain_info *pd =
                &chinfo[pier].pd_curves[pdg];

Компонент

linux-kernel 2.6.39-rc2

Ссылки

Problems found by KEDR
Начало обсуждения: Kernel Bug Tracker, bug #32722

Принято

Kernel Bug Tracker, bug #32942

Статус

Исправлено в ядре 3.0

[В начало]