lkml.org 
[lkml]   [2018]   [Mar]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 20/63] x86/MCE: Serialize sysfs changes
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Seunghun Han <kkamagui@gmail.com>

    commit b3b7c4795ccab5be71f080774c45bbbcc75c2aaf upstream.

    The check_interval file in

    /sys/devices/system/machinecheck/machinecheck<cpu number>

    directory is a global timer value for MCE polling. If it is changed by one
    CPU, mce_restart() broadcasts the event to other CPUs to delete and restart
    the MCE polling timer and __mcheck_cpu_init_timer() reinitializes the
    mce_timer variable.

    If more than one CPU writes a specific value to the check_interval file
    concurrently, mce_timer is not protected from such concurrent accesses and
    all kinds of explosions happen. Since only root can write to those sysfs
    variables, the issue is not a big deal security-wise.

    However, concurrent writes to these configuration variables is void of
    reason so the proper thing to do is to serialize the access with a mutex.

    Boris:

    - Make store_int_with_restart() use device_store_ulong() to filter out
    negative intervals
    - Limit min interval to 1 second
    - Correct locking
    - Massage commit message

    Signed-off-by: Seunghun Han <kkamagui@gmail.com>
    Signed-off-by: Borislav Petkov <bp@suse.de>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Cc: Tony Luck <tony.luck@intel.com>
    Cc: linux-edac <linux-edac@vger.kernel.org>
    Cc: stable@vger.kernel.org
    Link: http://lkml.kernel.org/r/20180302202706.9434-1-kkamagui@gmail.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/x86/kernel/cpu/mcheck/mce.c | 22 +++++++++++++++++++++-
    1 file changed, 21 insertions(+), 1 deletion(-)

    --- a/arch/x86/kernel/cpu/mcheck/mce.c
    +++ b/arch/x86/kernel/cpu/mcheck/mce.c
    @@ -60,6 +60,9 @@ static DEFINE_MUTEX(mce_chrdev_read_mute
    smp_load_acquire(&(p)); \
    })

    +/* sysfs synchronization */
    +static DEFINE_MUTEX(mce_sysfs_mutex);
    +
    #define CREATE_TRACE_POINTS
    #include <trace/events/mce.h>

    @@ -2220,6 +2223,7 @@ static ssize_t set_ignore_ce(struct devi
    if (kstrtou64(buf, 0, &new) < 0)
    return -EINVAL;

    + mutex_lock(&mce_sysfs_mutex);
    if (mca_cfg.ignore_ce ^ !!new) {
    if (new) {
    /* disable ce features */
    @@ -2232,6 +2236,8 @@ static ssize_t set_ignore_ce(struct devi
    on_each_cpu(mce_enable_ce, (void *)1, 1);
    }
    }
    + mutex_unlock(&mce_sysfs_mutex);
    +
    return size;
    }

    @@ -2244,6 +2250,7 @@ static ssize_t set_cmci_disabled(struct
    if (kstrtou64(buf, 0, &new) < 0)
    return -EINVAL;

    + mutex_lock(&mce_sysfs_mutex);
    if (mca_cfg.cmci_disabled ^ !!new) {
    if (new) {
    /* disable cmci */
    @@ -2255,6 +2262,8 @@ static ssize_t set_cmci_disabled(struct
    on_each_cpu(mce_enable_ce, NULL, 1);
    }
    }
    + mutex_unlock(&mce_sysfs_mutex);
    +
    return size;
    }

    @@ -2262,8 +2271,19 @@ static ssize_t store_int_with_restart(st
    struct device_attribute *attr,
    const char *buf, size_t size)
    {
    - ssize_t ret = device_store_int(s, attr, buf, size);
    + unsigned long old_check_interval = check_interval;
    + ssize_t ret = device_store_ulong(s, attr, buf, size);
    +
    + if (check_interval == old_check_interval)
    + return ret;
    +
    + if (check_interval < 1)
    + check_interval = 1;
    +
    + mutex_lock(&mce_sysfs_mutex);
    mce_restart();
    + mutex_unlock(&mce_sysfs_mutex);
    +
    return ret;
    }


    \
     
     \ /
      Last update: 2018-03-16 18:34    [W:4.394 / U:0.320 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site