lkml.org 
[lkml]   [2020]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 093/113] x86/mce/amd: Fix kobject lifetime
    Date
    From: Thomas Gleixner <tglx@linutronix.de>

    commit 51dede9c05df2b78acd6dcf6a17d21f0877d2d7b upstream.

    Accessing the MCA thresholding controls in sysfs concurrently with CPU
    hotplug can lead to a couple of KASAN-reported issues:

    BUG: KASAN: use-after-free in sysfs_file_ops+0x155/0x180
    Read of size 8 at addr ffff888367578940 by task grep/4019

    and

    BUG: KASAN: use-after-free in show_error_count+0x15c/0x180
    Read of size 2 at addr ffff888368a05514 by task grep/4454

    for example. Both result from the fact that the threshold block
    creation/teardown code frees the descriptor memory itself instead of
    defining proper ->release function and leaving it to the driver core to
    take care of that, after all sysfs accesses have completed.

    Do that and get rid of the custom freeing code, fixing the above UAFs in
    the process.

    [ bp: write commit message. ]

    Fixes: 95268664390b ("[PATCH] x86_64: mce_amd support for family 0x10 processors")
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: Borislav Petkov <bp@suse.de>
    Cc: <stable@vger.kernel.org>
    Link: https://lkml.kernel.org/r/20200214082801.13836-1-bp@alien8.de
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/x86/kernel/cpu/mcheck/mce_amd.c | 17 +++++++++++------
    1 file changed, 11 insertions(+), 6 deletions(-)

    --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
    +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
    @@ -560,9 +560,12 @@ static const struct sysfs_ops threshold_
    .store = store,
    };

    +static void threshold_block_release(struct kobject *kobj);
    +
    static struct kobj_type threshold_ktype = {
    .sysfs_ops = &threshold_ops,
    .default_attrs = default_attrs,
    + .release = threshold_block_release,
    };

    static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
    @@ -765,8 +768,12 @@ static int threshold_create_device(unsig
    return err;
    }

    -static void deallocate_threshold_block(unsigned int cpu,
    - unsigned int bank)
    +static void threshold_block_release(struct kobject *kobj)
    +{
    + kfree(to_block(kobj));
    +}
    +
    +static void deallocate_threshold_block(unsigned int cpu, unsigned int bank)
    {
    struct threshold_block *pos = NULL;
    struct threshold_block *tmp = NULL;
    @@ -776,13 +783,11 @@ static void deallocate_threshold_block(u
    return;

    list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
    - kobject_put(&pos->kobj);
    list_del(&pos->miscj);
    - kfree(pos);
    + kobject_put(&pos->kobj);
    }

    - kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
    - per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
    + kobject_put(&head->blocks->kobj);
    }

    static void __threshold_remove_blocks(struct threshold_bank *b)

    \
     
     \ /
      Last update: 2020-02-27 15:47    [W:3.665 / U:0.156 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site