mirror of https://gitee.com/openkylin/linux.git
drm fixes for 5.8-rc8 (part 2)
nouveau: - final modifiers regression fix amdgpu: - Revert a fix which caused other regressions - Fix potential kernel info leak - Fix a use-after-free bug that was uncovered by another change in 5.7 -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJfI4xdAAoJEAx081l5xIa+MSkP/j6D/axuI0q5J31uERFAQluI KDmNrP8NTBYXPIGYNDI1pYtFXZusMq2+KBYF9Qa3AzKY5gQ/KejwdHJnS/nhGjwU S4HczrSZt9/RvPtOrHPFCETIxpUpiBjdH/Y/dj5XNIMgwYRejP6nDChkTHhIiA6W tev7WW2aCR8Xkf5O5YGfXGgDdh6a9EY/ZtSGdMgfqzP6BUWdT7JBCULxjMbOT7he +TLoVoA0LQ7Mh8chErMG8oO31CC3Gum/3lj9SUBPFwp0jbFvOEnX2rOxGu3yx/H4 XtQe3mns4R6aq6rPQXMKeLF76JsSHMwwUCJWdj0MasbnLkcc2X0ua6TPce/9FxRI SWjxba7NADkn1bUi4oKCwtHBFbJuf8193KV9Ksi2vzesRDwRzByjmshgkVQPeARw GSar2kFjN8xc5HwEBJ8zLTNNQzDuCGWgC9ivaxenLvHL/+wYaLwyDD9j1i6YIQ0L 8qYcUvABH/uM5eVWzZBwYb38+0l5kvRdX7G2cUeR6kXAdGg1v78Mf0OGhVrT6lx2 BDlOEMXFOF3d1iY51w6Qwx8hg2z0O7bHWQXdlwAT0CUlBTrBGPS7+b8yFyzQyttp tQGTpkl1evxziIBiKnlF9zU9koc9MjT9otjz9Q6mDZv4PyKemUdCxjdRfOAw0Xmx RHdnfNtig7Yz1C4g4tCD =5XAj -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2020-07-31' of git://anongit.freedesktop.org/drm/drm Pull more drm fixes from Dave Airlie: "As mentioned previously this contains the nouveau regression fix. amdgpu had three fixes outstanding as well, one revert, an info leak and use after free. The use after free is a bit trickier than I'd like, and I've personally gone over it to confirm I'm happy that it is doing what it says. nouveau: - final modifiers regression fix amdgpu: - Revert a fix which caused other regressions - Fix potential kernel info leak - Fix a use-after-free bug that was uncovered by another change in 5.7" * tag 'drm-fixes-2020-07-31' of git://anongit.freedesktop.org/drm/drm: drm/nouveau: Accept 'legacy' format modifiers Revert "drm/amdgpu: Fix NULL dereference in dpm sysfs handlers" drm/amd/display: Clear dm_state for fast updates drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl()
This commit is contained in:
commit
d8b9faec54
|
@ -692,9 +692,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
|||
return n ? -EFAULT : 0;
|
||||
}
|
||||
case AMDGPU_INFO_DEV_INFO: {
|
||||
struct drm_amdgpu_info_device dev_info = {};
|
||||
struct drm_amdgpu_info_device dev_info;
|
||||
uint64_t vm_size;
|
||||
|
||||
memset(&dev_info, 0, sizeof(dev_info));
|
||||
dev_info.device_id = dev->pdev->device;
|
||||
dev_info.chip_rev = adev->rev_id;
|
||||
dev_info.external_rev = adev->external_rev_id;
|
||||
|
|
|
@ -778,7 +778,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
|
|||
tmp_str++;
|
||||
while (isspace(*++tmp_str));
|
||||
|
||||
while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
|
||||
while (tmp_str[0]) {
|
||||
sub_str = strsep(&tmp_str, delimiter);
|
||||
ret = kstrtol(sub_str, 0, ¶meter[parameter_size]);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
@ -1038,7 +1039,8 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask)
|
|||
memcpy(buf_cpy, buf, bytes);
|
||||
buf_cpy[bytes] = '\0';
|
||||
tmp = buf_cpy;
|
||||
while ((sub_str = strsep(&tmp, delimiter)) != NULL) {
|
||||
while (tmp[0]) {
|
||||
sub_str = strsep(&tmp, delimiter);
|
||||
if (strlen(sub_str)) {
|
||||
ret = kstrtol(sub_str, 0, &level);
|
||||
if (ret)
|
||||
|
@ -1635,7 +1637,8 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
|
|||
i++;
|
||||
memcpy(buf_cpy, buf, count-i);
|
||||
tmp_str = buf_cpy;
|
||||
while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
|
||||
while (tmp_str[0]) {
|
||||
sub_str = strsep(&tmp_str, delimiter);
|
||||
ret = kstrtol(sub_str, 0, ¶meter[parameter_size]);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -8717,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||
* the same resource. If we have a new DC context as part of
|
||||
* the DM atomic state from validation we need to free it and
|
||||
* retain the existing one instead.
|
||||
*
|
||||
* Furthermore, since the DM atomic state only contains the DC
|
||||
* context and can safely be annulled, we can free the state
|
||||
* and clear the associated private object now to free
|
||||
* some memory and avoid a possible use-after-free later.
|
||||
*/
|
||||
struct dm_atomic_state *new_dm_state, *old_dm_state;
|
||||
|
||||
new_dm_state = dm_atomic_get_new_state(state);
|
||||
old_dm_state = dm_atomic_get_old_state(state);
|
||||
for (i = 0; i < state->num_private_objs; i++) {
|
||||
struct drm_private_obj *obj = state->private_objs[i].ptr;
|
||||
|
||||
if (new_dm_state && old_dm_state) {
|
||||
if (new_dm_state->context)
|
||||
dc_release_state(new_dm_state->context);
|
||||
if (obj->funcs == adev->dm.atomic_obj.funcs) {
|
||||
int j = state->num_private_objs-1;
|
||||
|
||||
new_dm_state->context = old_dm_state->context;
|
||||
dm_atomic_destroy_state(obj,
|
||||
state->private_objs[i].state);
|
||||
|
||||
if (old_dm_state->context)
|
||||
dc_retain_state(old_dm_state->context);
|
||||
/* If i is not at the end of the array then the
|
||||
* last element needs to be moved to where i was
|
||||
* before the array can safely be truncated.
|
||||
*/
|
||||
if (i != j)
|
||||
state->private_objs[i] =
|
||||
state->private_objs[j];
|
||||
|
||||
state->private_objs[j].ptr = NULL;
|
||||
state->private_objs[j].state = NULL;
|
||||
state->private_objs[j].old_state = NULL;
|
||||
state->private_objs[j].new_state = NULL;
|
||||
|
||||
state->num_private_objs = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@ nouveau_decode_mod(struct nouveau_drm *drm,
|
|||
uint32_t *tile_mode,
|
||||
uint8_t *kind)
|
||||
{
|
||||
struct nouveau_display *disp = nouveau_display(drm->dev);
|
||||
BUG_ON(!tile_mode || !kind);
|
||||
|
||||
if (modifier == DRM_FORMAT_MOD_LINEAR) {
|
||||
|
@ -202,6 +203,12 @@ nouveau_decode_mod(struct nouveau_drm *drm,
|
|||
* Extract the block height and kind from the corresponding
|
||||
* modifier fields. See drm_fourcc.h for details.
|
||||
*/
|
||||
|
||||
if ((modifier & (0xffull << 12)) == 0ull) {
|
||||
/* Legacy modifier. Translate to this dev's 'kind.' */
|
||||
modifier |= disp->format_modifiers[0] & (0xffull << 12);
|
||||
}
|
||||
|
||||
*tile_mode = (uint32_t)(modifier & 0xF);
|
||||
*kind = (uint8_t)((modifier >> 12) & 0xFF);
|
||||
|
||||
|
@ -227,6 +234,16 @@ nouveau_framebuffer_get_layout(struct drm_framebuffer *fb,
|
|||
}
|
||||
}
|
||||
|
||||
static const u64 legacy_modifiers[] = {
|
||||
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
|
||||
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
|
||||
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
|
||||
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
|
||||
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
|
||||
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
|
||||
DRM_FORMAT_MOD_INVALID
|
||||
};
|
||||
|
||||
static int
|
||||
nouveau_validate_decode_mod(struct nouveau_drm *drm,
|
||||
uint64_t modifier,
|
||||
|
@ -247,8 +264,14 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm,
|
|||
(disp->format_modifiers[mod] != modifier);
|
||||
mod++);
|
||||
|
||||
if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
|
||||
return -EINVAL;
|
||||
if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID) {
|
||||
for (mod = 0;
|
||||
(legacy_modifiers[mod] != DRM_FORMAT_MOD_INVALID) &&
|
||||
(legacy_modifiers[mod] != modifier);
|
||||
mod++);
|
||||
if (legacy_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nouveau_decode_mod(drm, modifier, tile_mode, kind);
|
||||
|
||||
|
|
Loading…
Reference in New Issue