Details

[Home]

Issue of the Implementation # K0005

Brief

(ath5k) Not all elements of chinfo[pier].pd_curves[] are freed

Detailed Description

Some of the memory blocks kcalloc'ed in ath5k_eeprom_convert_pcal_info_*() are not freed even when module ath5k is unloaded.

Here is the trace for one iteration of the outer 'for' loop in ath5k_eeprom_convert_pcal_info_2413(),
drivers/net/wireless/ath/ath5k/eeprom.c:1148:

// Allocation of chinfo[pier].pd_curves, line 1153.
// Room for 4 elements of type struct ath5k_pdgain_info
// is created.
called___kmalloc: (.text+0x212f) arguments: (48, 80d0), result: ab3ad780

// The inner loop, iter #0, 
// allocation of pd->pd_step and pd->pd_pwr  
// for chinfo[pier].pd_curves[pdgain_idx[0]] (lines 1176 and 1182)
called___kmalloc: (.text+0x212f) arguments: (4, 80d0), result: ab1c3f68
called___kmalloc: (.text+0x212f) arguments: (8, 80d0), result: ab1c3f70

// The inner loop, iter #1, 
// allocation of pd->pd_step and pd->pd_pwr  
// for chinfo[pier].pd_curves[pdgain_idx[1]] (lines 1176 and 1182)
called___kmalloc: (.text+0x212f) arguments: (5, 80d0), result: ab1c3f78
called___kmalloc: (.text+0x212f) arguments: (10, 80d0), result: ab17ce80
<...> 

Here is the trace for one iteration of the outer 'for' loop, ath5k_eeprom_free_pcal_info(),
drivers/net/wireless/ath/ath5k/eeprom.c:1564:

// The inner loop, iter #0, line 1573
called_kfree: (.text+0x20be) arguments: ((null))
called_kfree: (.text+0x20c6) arguments: ((null))

// The inner loop, iter #1, line 1573
called_kfree: (.text+0x20be) arguments: (ab1c3f78)
called_kfree: (.text+0x20c6) arguments: (ab17ce80)

// Deallocation of chinfo[pier].pd_curves array
called_kfree: (.text+0x20de) arguments: (ab3ad780)
<...> 

Same for other iterations of the outer 'for' loops in ath5k_eeprom_convert_pcal_info_*() and ath5k_eeprom_free_pcal_info().

ath5k_eeprom_free_pcal_info() tries to free 'pd_step' and 'pd_pwr' fields of wrong elements.

On the system where the problem showed up, chinfo[pier].pd_curves[] was an array of 4 (AR5K_EEPROM_N_PD_CURVES) elements, only 2 of which were actually used, #1 and #2, which was OK. The elements #0 and #3 remained filled with zeros.

Consider line 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] was 2 and pdgain_idx[] array was {1; 2}. From the code in eeprom.c, it looks like only these elements of chinfo[pier].pd_curves are actually used for calibration, etc.

Only ath5k_eeprom_free_pcal_info() works in a different way. It tries to free 'pd_step' and 'pd_pwr' for the first two elements of chinfo[pier].pd_curves instead of the elements that were actually allocated before:

    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);
        }
    }

That is, it processes pd_curves[0] and pd_curves[1] rather than pd_curves[pdgain_idx[0]] and pd_curves[pdgain_idx[1]].

Reproducing

To reproduce the problem, it is enough to load ath5k.ko module and then unload it again.

Possible solutions

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];

Component

linux-kernel 2.6.39-rc2

References

Problems found by KEDR
Beginning of the discussion: Kernel Bug Tracker, bug #32722

Accepted

Kernel Bug Tracker, bug #32942

Status

Fixed in the kernel 3.0

[Home]