Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+60 -15
+2 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
··· 692 692 return n ? -EFAULT : 0; 693 693 } 694 694 case AMDGPU_INFO_DEV_INFO: { 695 - struct drm_amdgpu_info_device dev_info = {}; 695 + struct drm_amdgpu_info_device dev_info; 696 696 uint64_t vm_size; 697 697 698 + memset(&dev_info, 0, sizeof(dev_info)); 698 699 dev_info.device_id = dev->pdev->device; 699 700 dev_info.chip_rev = adev->rev_id; 700 701 dev_info.external_rev = adev->external_rev_id;
+6 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
··· 778 778 tmp_str++; 779 779 while (isspace(*++tmp_str)); 780 780 781 - while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { 781 + while (tmp_str[0]) { 782 + sub_str = strsep(&tmp_str, delimiter); 782 783 ret = kstrtol(sub_str, 0, &parameter[parameter_size]); 783 784 if (ret) 784 785 return -EINVAL; ··· 1039 1038 memcpy(buf_cpy, buf, bytes); 1040 1039 buf_cpy[bytes] = '\0'; 1041 1040 tmp = buf_cpy; 1042 - while ((sub_str = strsep(&tmp, delimiter)) != NULL) { 1041 + while (tmp[0]) { 1042 + sub_str = strsep(&tmp, delimiter); 1043 1043 if (strlen(sub_str)) { 1044 1044 ret = kstrtol(sub_str, 0, &level); 1045 1045 if (ret) ··· 1637 1635 i++; 1638 1636 memcpy(buf_cpy, buf, count-i); 1639 1637 tmp_str = buf_cpy; 1640 - while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { 1638 + while (tmp_str[0]) { 1639 + sub_str = strsep(&tmp_str, delimiter); 1641 1640 ret = kstrtol(sub_str, 0, &parameter[parameter_size]); 1642 1641 if (ret) 1643 1642 return -EINVAL;
+27 -9
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 8717 8717 * the same resource. If we have a new DC context as part of 8718 8718 * the DM atomic state from validation we need to free it and 8719 8719 * retain the existing one instead. 8720 + * 8721 + * Furthermore, since the DM atomic state only contains the DC 8722 + * context and can safely be annulled, we can free the state 8723 + * and clear the associated private object now to free 8724 + * some memory and avoid a possible use-after-free later. 8720 8725 */ 8721 - struct dm_atomic_state *new_dm_state, *old_dm_state; 8722 8726 8723 - new_dm_state = dm_atomic_get_new_state(state); 8724 - old_dm_state = dm_atomic_get_old_state(state); 8727 + for (i = 0; i < state->num_private_objs; i++) { 8728 + struct drm_private_obj *obj = state->private_objs[i].ptr; 8725 8729 8726 - if (new_dm_state && old_dm_state) { 8727 - if (new_dm_state->context) 8728 - dc_release_state(new_dm_state->context); 8730 + if (obj->funcs == adev->dm.atomic_obj.funcs) { 8731 + int j = state->num_private_objs-1; 8729 8732 8730 - new_dm_state->context = old_dm_state->context; 8733 + dm_atomic_destroy_state(obj, 8734 + state->private_objs[i].state); 8731 8735 8732 - if (old_dm_state->context) 8733 - dc_retain_state(old_dm_state->context); 8736 + /* If i is not at the end of the array then the 8737 + * last element needs to be moved to where i was 8738 + * before the array can safely be truncated. 8739 + */ 8740 + if (i != j) 8741 + state->private_objs[i] = 8742 + state->private_objs[j]; 8743 + 8744 + state->private_objs[j].ptr = NULL; 8745 + state->private_objs[j].state = NULL; 8746 + state->private_objs[j].old_state = NULL; 8747 + state->private_objs[j].new_state = NULL; 8748 + 8749 + state->num_private_objs = j; 8750 + break; 8751 + } 8734 8752 } 8735 8753 } 8736 8754
+25 -2
drivers/gpu/drm/nouveau/nouveau_display.c
··· 191 191 uint32_t *tile_mode, 192 192 uint8_t *kind) 193 193 { 194 + struct nouveau_display *disp = nouveau_display(drm->dev); 194 195 BUG_ON(!tile_mode || !kind); 195 196 196 197 if (modifier == DRM_FORMAT_MOD_LINEAR) { ··· 203 202 * Extract the block height and kind from the corresponding 204 203 * modifier fields. See drm_fourcc.h for details. 205 204 */ 205 + 206 + if ((modifier & (0xffull << 12)) == 0ull) { 207 + /* Legacy modifier. Translate to this dev's 'kind.' */ 208 + modifier |= disp->format_modifiers[0] & (0xffull << 12); 209 + } 210 + 206 211 *tile_mode = (uint32_t)(modifier & 0xF); 207 212 *kind = (uint8_t)((modifier >> 12) & 0xFF); 208 213 ··· 234 227 } 235 228 } 236 229 230 + static const u64 legacy_modifiers[] = { 231 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0), 232 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1), 233 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2), 234 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3), 235 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4), 236 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5), 237 + DRM_FORMAT_MOD_INVALID 238 + }; 239 + 237 240 static int 238 241 nouveau_validate_decode_mod(struct nouveau_drm *drm, 239 242 uint64_t modifier, ··· 264 247 (disp->format_modifiers[mod] != modifier); 265 248 mod++); 266 249 267 - if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID) 268 - return -EINVAL; 250 + if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID) { 251 + for (mod = 0; 252 + (legacy_modifiers[mod] != DRM_FORMAT_MOD_INVALID) && 253 + (legacy_modifiers[mod] != modifier); 254 + mod++); 255 + if (legacy_modifiers[mod] == DRM_FORMAT_MOD_INVALID) 256 + return -EINVAL; 257 + } 269 258 270 259 nouveau_decode_mod(drm, modifier, tile_mode, kind); 271 260