Skip to content
  • NeilBrown's avatar
    sysfs: be careful of error returns from ops->show() · c8a139d0
    NeilBrown authored
    ops->show() can return a negative error code.
    Commit 65da3484 ("sysfs: correctly handle short reads on PREALLOC attrs.")
    (in v4.4) caused this to be stored in an unsigned 'size_t' variable, so errors
    would look like large numbers.
    As a result, if an error is returned, sysfs_kf_read() will return the
    value of 'count', typically 4096.
    
    Commit 17d0774f ("sysfs: correctly handle read offset on PREALLOC attrs")
    (in v4.8) extended this error to use the unsigned large 'len' as a size for
    memmove().
    Consequently, if ->show returns an error, then the first read() on the
    sysfs file will return 4096 and could return uninitialized memory to
    user-space.
    If the application performs a subsequent read, this will trigger a memmove()
    with extremely large count, and is likely to crash the machine is bizarre ways.
    
    This bug can currently only be triggered by reading from an md
    sysfs attribute declared with __ATTR_PREALLOC() during the
    brief period between when mddev_put() deletes an mddev from
    the ->all_mddevs list, and when mddev_delayed_delete() - which is
    scheduled on a workqueue - completes.
    Before this, an error won't be returned by the ->show()
    After this, the ->show() won't be called.
    
    I can reproduce it reliably only by putting delay like
    	usleep_range(500000,700000);
    early in mddev_delayed_delete(). Then after creating an
    md device md0 run
      echo clear > /sys/block/md0/md/array_state; cat /sys/block/md0/md/array_state
    
    The bug can be triggered without the usleep.
    
    Fixes: 65da3484 ("sysfs: correctly handle short reads on PREALLOC attrs.")
    Fixes: 17d0774f
    
     ("sysfs: correctly handle read offset on PREALLOC attrs")
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarNeilBrown <neilb@suse.com>
    Acked-by: default avatarTejun Heo <tj@kernel.org>
    Reported-and-tested-by: default avatarMiroslav Benes <mbenes@suse.cz>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    c8a139d0