вторник, 14 января 2020 г.

using devm_kcalloc unchecked result in linux kernel

Part I
This time I add references to linux kernel github - although I ran my naive code analyzer on version 4.18 - all found bugs have long and happy life in current source tree

gb_generate_enum_strings in drivers/staging/greybus/audio_topology.c:
strings = devm_kcalloc(gb->dev, items, sizeof(char *), GFP_KERNEL);
data = gbenum->names;

for (i = 0; i < items; i++) {
  strings[i] = (const char *)data;

rt2880_pinmux_pins in drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c:  
p->func[i]->pins = devm_kcalloc(p->dev,
for (j = 0; j < p->func[i]->pin_count; j++)
  p->func[i]->pins[j] = p->func[i]->pin_first + j;

Using unchecked result from devm_kmalloc_array:
ti_sci_scan_clocks_from_fw in drivers/clk/keystone/sci-clk.c:
tmp_clks = devm_kmalloc_array(dev, max_clks + 64,
memcpy(tmp_clks, clks, max_clks * sizeof(sci_clk));

Doubtful case (I think is has delayed effects bcs no checks for ports field) - function mscc_ocelot_probe in drivers/net/ethernet/mscc/ocelot_board.c
ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
                     sizeof(struct ocelot_port *), GFP_KERNEL);

понедельник, 13 января 2020 г.

using devm_kzalloc unchecked result in linux kernel 4.18

Managed Device Resource (described in Documentation/driver-model/devres.txt) is witty technique for lazy developers. Unfortunately it does not exempt from the need to check results. I decided to see if there are such places in linux kernel (which can lead to null address dereference). Right way to do it is use Static Analyzer like clang, coverity or PVS Studio. But I am too lazy so I wrote simple and naive perl script and run it on linux kernel 4.18 source tree. It found 56 cases (from total 4173 where devm_kzalloc was used) - not too much for manual checking. So lets see what we have

impd1_probe in arch/arm/mach-integrator/impd1.c:
            lookup = devm_kzalloc(&dev->dev,
                          sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
            chipname = devm_kstrdup(&dev->dev, devname, GFP_KERNEL);
            mmciname = kasprintf(GFP_KERNEL, "lm%x:00700", dev->id);
            lookup->dev_id = mmciname;

st_sensors_of_probe in drivers/iio/common/st_sensors/st_sensors_core.c (still not fixed):
    pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
    if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2))
        pdata->drdy_int_pin = (u8) val;
        pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0;

    pdata->open_drain = of_property_read_bool(np, "drive-open-drain");

sm501_register_gpio_i2c_instance in drivers/mfd/sm501.c:
    lookup = devm_kzalloc(&pdev->dev,
                  sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
    lookup->dev_id = "i2c-gpio";
    if (iic->pin_sda < 32)
        lookup->table[0].chip_label = "SM501-LOW";
        lookup->table[0].chip_label = "SM501-HIGH";
    lookup->table[0].chip_hwnum = iic->pin_sda % 32;
    lookup->table[0].con_id = NULL;
    lookup->table[0].idx = 0;
    lookup->table[0].flags = GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN;

rt2880_pinmux_index in drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c (still not fixed):
            f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL);
            f[c]->groups[0] = i;

rt2880_pinmux_probe in drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c

        range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL);
        range->name = name = (char *) &range[1];
        sprintf(name, "pio");
        range->npins = __be32_to_cpu(*ngpio);
        range->base = __be32_to_cpu(*gpiobase);
        range->pin_base = range->base;

rt5514_spi_pcm_probe in sound/soc/codecs/rt5514-spi.c:
    rt5514_dsp = devm_kzalloc(component->dev, sizeof(*rt5514_dsp),

    rt5514_dsp->dev = &rt5514_spi->dev;

rt5663_parse_dp in sound/soc/codecs/rt5663.c (still not fixed):
        rt5663->imp_table = devm_kzalloc(dev, table_size, GFP_KERNEL);
            (u32 *)rt5663->imp_table, table_size);

perl script used to find this bugs:

пятница, 3 января 2020 г.

typos in "Linux Device Drivers Development"

I decided in retirement to fill the gaps in my education, so now I reading book "Linux Device Drivers Development" and noticed lots of annoying typos in code samples

page 65:
/* some where */
spinlock_t my_spinlock;
static irqreturn_t my_irq_handler(int irq, void *data)
 unsigned long status, flags;
 spin_lock_irqsave(&my_spinlock, flags);
 status = access_shared_resources();
 spin_unlock_irqrestore(&gpio->slock, flags); // wut? &
 return IRQ_HANDLED;

page 103-104:
struct my_data {
 int my_int_var;
 struct tasklet_struct the_tasklet;
 int dma_request;

static irqreturn_t my_irq_handler(int irq, void *dev_id)
  struct my_data *md = dev_id;
  /* Let's schedule our tasklet */
  tasklet_schedule(&md.dma_tasklet); // wut? &md->
  return IRQ_HANDLED;

page 127:
/* Move the cursor ten time, relative from the beginning of the file */
if (lseek(fd, 7, SEEK_SET) < 0)
return 1;

An so on. Seems that code samples looks like Frankenstein ripped from some random kernel places

вторник, 19 ноября 2019 г.

last version of wincheck

it`s last because of
My former employer was so so nice that he allowed me to publish this build. Btw I seek new job


  • add support of Windows 1909
  • add support of new RFG relocs. As usually kernel itself has bad IMAGE_DYNAMIC_RELOCATION_TABLE - it contains zero type somewhere inside IMAGE_DYNAMIC_RELOCATION
  • add dumping of WMI_LOGGER_CONTEXTs for InfinityHook detection (with -wmi option)
  • add dumping of PsAltSystemCallHandlers
  • add dumping of PoPdcCallbacks (with -pofx option)
  • add dumping of PpmPlatformStates (with -ppm option)
  • add dumping callbacks registered with RtlRegisterFeatureConfigurationChangeNotification function 

пятница, 15 ноября 2019 г.


I commited today plugin for processing 64bit kernel resource with name "FUNCTIONEXTENTLIST" (located in RCDATA)

It seems that processing of this resource happens in huge unnamed sub called from famous KiFilterFiberContext, so this is apparently part of PatchGuard. Format of this resource relative simple.
At start we have signature CTXE for compressed data (LTXE for noncompressed but I have never seen this). Data unpacking with RtlDecompressBufferEx function. In packed data we have table with pair offsets, first to RUNTIME_FUNCTION recognised from IDA and second to some additional RUNTIME_FUNCTION (which usually skipped in IDA Pro for unknown reason)

And even after calling this plugin there are lots of some valid RUNTIME_FUNCTION in .pdata section - I don`t know why

четверг, 14 ноября 2019 г.

понедельник, 2 сентября 2019 г.

new RFG reloc types

It seems that est since build 18922 Microsoft turned on retpoline
This is implemented as RFG relocations with 3 new type:

Type 3
    DWORD       PageRelativeOffset : 12;
    DWORD       IndirectCall       : 1;
    DWORD       IATIndex           : 19;

Looks like IAT function calling patch:
     call    cs:__imp_PshedFreeMemory
     nop     dword ptr [rax+rax+00h]

Type 4
    WORD        PageRelativeOffset : 12;
    WORD        IndirectCall       : 1;
    WORD        RexWPrefix         : 1;
    WORD        CfgCheck           : 1;
    WORD        Reserved           : 1;

Looks like call reg patch:
    call    rax
    nop     dword ptr [rax]

Type 5
    WORD        PageRelativeOffset : 12;
    WORD        RegisterNumber     : 4;

Looks like call reg in switch patch:
   mov     ecx, ds:rva off_14000DEBC[rdx+rdi*4]
   add     rcx, rdx
   jmp     rcx             ; switch jump
   db 4 dup(0CCh)

I patched today my RFG plugin to IDA Pro to support this new types