Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 801dff41 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2018-05-29' of...

Merge tag 'drm-intel-fixes-2018-05-29' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

- Fix for potential Spectre vector in the new query uAPI
- Fix NULL pointer deref (FDO #106559)
- DMI fix to hide LVDS for Radiant P845 (FDO #105468)

* tag 'drm-intel-fixes-2018-05-29' of git://anongit.freedesktop.org/drm/drm-intel:
  drm/i915/query: nospec expects no more than an unsigned long
  drm/i915/query: Protect tainted function pointer lookup
  drm/i915/lvds: Move acpi lid notification registration to registration phase
  drm/i915: Disable LVDS on Radiant P845
parents b04e2177 65b3bdc8
Loading
Loading
Loading
Loading
+11 −4
Original line number Original line Diff line number Diff line
@@ -4,6 +4,8 @@
 * Copyright © 2018 Intel Corporation
 * Copyright © 2018 Intel Corporation
 */
 */


#include <linux/nospec.h>

#include "i915_drv.h"
#include "i915_drv.h"
#include "i915_query.h"
#include "i915_query.h"
#include <uapi/drm/i915_drm.h>
#include <uapi/drm/i915_drm.h>
@@ -100,7 +102,7 @@ int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)


	for (i = 0; i < args->num_items; i++, user_item_ptr++) {
	for (i = 0; i < args->num_items; i++, user_item_ptr++) {
		struct drm_i915_query_item item;
		struct drm_i915_query_item item;
		u64 func_idx;
		unsigned long func_idx;
		int ret;
		int ret;


		if (copy_from_user(&item, user_item_ptr, sizeof(item)))
		if (copy_from_user(&item, user_item_ptr, sizeof(item)))
@@ -109,12 +111,17 @@ int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
		if (item.query_id == 0)
		if (item.query_id == 0)
			return -EINVAL;
			return -EINVAL;


		if (overflows_type(item.query_id - 1, unsigned long))
			return -EINVAL;

		func_idx = item.query_id - 1;
		func_idx = item.query_id - 1;


		if (func_idx < ARRAY_SIZE(i915_query_funcs))
			ret = i915_query_funcs[func_idx](dev_priv, &item);
		else
		ret = -EINVAL;
		ret = -EINVAL;
		if (func_idx < ARRAY_SIZE(i915_query_funcs)) {
			func_idx = array_index_nospec(func_idx,
						      ARRAY_SIZE(i915_query_funcs));
			ret = i915_query_funcs[func_idx](dev_priv, &item);
		}


		/* Only write the length back to userspace if they differ. */
		/* Only write the length back to userspace if they differ. */
		if (ret != item.length && put_user(ret, &user_item_ptr->length))
		if (ret != item.length && put_user(ret, &user_item_ptr->length))
+40 −11
Original line number Original line Diff line number Diff line
@@ -574,6 +574,36 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
	return NOTIFY_OK;
	return NOTIFY_OK;
}
}


static int
intel_lvds_connector_register(struct drm_connector *connector)
{
	struct intel_lvds_connector *lvds = to_lvds_connector(connector);
	int ret;

	ret = intel_connector_register(connector);
	if (ret)
		return ret;

	lvds->lid_notifier.notifier_call = intel_lid_notify;
	if (acpi_lid_notifier_register(&lvds->lid_notifier)) {
		DRM_DEBUG_KMS("lid notifier registration failed\n");
		lvds->lid_notifier.notifier_call = NULL;
	}

	return 0;
}

static void
intel_lvds_connector_unregister(struct drm_connector *connector)
{
	struct intel_lvds_connector *lvds = to_lvds_connector(connector);

	if (lvds->lid_notifier.notifier_call)
		acpi_lid_notifier_unregister(&lvds->lid_notifier);

	intel_connector_unregister(connector);
}

/**
/**
 * intel_lvds_destroy - unregister and free LVDS structures
 * intel_lvds_destroy - unregister and free LVDS structures
 * @connector: connector to free
 * @connector: connector to free
@@ -586,9 +616,6 @@ static void intel_lvds_destroy(struct drm_connector *connector)
	struct intel_lvds_connector *lvds_connector =
	struct intel_lvds_connector *lvds_connector =
		to_lvds_connector(connector);
		to_lvds_connector(connector);


	if (lvds_connector->lid_notifier.notifier_call)
		acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);

	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
		kfree(lvds_connector->base.edid);
		kfree(lvds_connector->base.edid);


@@ -609,8 +636,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
	.fill_modes = drm_helper_probe_single_connector_modes,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.atomic_get_property = intel_digital_connector_atomic_get_property,
	.atomic_get_property = intel_digital_connector_atomic_get_property,
	.atomic_set_property = intel_digital_connector_atomic_set_property,
	.atomic_set_property = intel_digital_connector_atomic_set_property,
	.late_register = intel_connector_register,
	.late_register = intel_lvds_connector_register,
	.early_unregister = intel_connector_unregister,
	.early_unregister = intel_lvds_connector_unregister,
	.destroy = intel_lvds_destroy,
	.destroy = intel_lvds_destroy,
	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
@@ -827,6 +854,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
		},
		},
	},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Radiant P845",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"),
			DMI_MATCH(DMI_PRODUCT_NAME, "P845"),
		},
	},


	{ }	/* terminating entry */
	{ }	/* terminating entry */
};
};
@@ -1150,12 +1185,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)


	lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
	lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;


	lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
	if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
		DRM_DEBUG_KMS("lid notifier registration failed\n");
		lvds_connector->lid_notifier.notifier_call = NULL;
	}

	return;
	return;


failed:
failed: