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-2022-05-14' of git://anongit.freedesktop.org/drm/drm

Pull more drm fixes from Dave Airlie:
"Turns out I was right, some fixes hadn't made it to me yet. The vmwgfx
ones also popped up later, but all seem like bad enough things to fix.
The dma-buf, vc4 and nouveau ones are all pretty small.

The fbdev fixes are a bit more complicated: a fix to cleanup fbdev
devices properly, uncovered some use-after-free bugs in existing
drivers. Then the fix for those bugs wasn't correct. This reverts that
fix, and puts the proper fixes in place in the drivers to avoid the
use-after-frees.

This has had a fair number of eyes on it at this stage, and I'm
confident enough that it puts things in the right place, and is less
dangerous than reverting our way out of the initial change at this
stage.

fbdev:
- revert NULL deref fix that turned into a use-after-free
- prevent use-after-free in fbdev
- efifb/simplefb/vesafb: fix cleanup paths to avoid use-after-frees

dma-buf:
- fix panic in stats setup

vc4:
- fix hdmi build

nouveau:
- tegra iommu present fix
- fix leak in backlight name

vmwgfx:
- Black screen due to fences using FIFO checks on SVGA3
- Random black screens on boot due to uninitialized drm_mode_fb_cmd2
- Hangs on SVGA3 due to command buffers being used with gbobjects"

* tag 'drm-fixes-2022-05-14' of git://anongit.freedesktop.org/drm/drm:
drm/vmwgfx: Disable command buffers on svga3 without gbobjects
drm/vmwgfx: Initialize drm_mode_fb_cmd2
drm/vmwgfx: Fix fencing on SVGAv3
drm/vc4: hdmi: Fix build error for implicit function declaration
dma-buf: call dma_buf_stats_setup after dmabuf is in valid list
fbdev: efifb: Fix a use-after-free due early fb_info cleanup
drm/nouveau: Fix a potential theorical leak in nouveau_get_backlight_name()
drm/nouveau/tegra: Stop using iommu_present()
fbdev: vesafb: Cleanup fb_info in .fb_destroy rather than .remove
fbdev: efifb: Cleanup fb_info in .fb_destroy rather than .remove
fbdev: simplefb: Cleanup fb_info in .fb_destroy rather than .remove
fbdev: Prevent possible use-after-free in fb_release()
Revert "fbdev: Make fb_release() return -ENODEV if fbdev was unregistered"

+99 -40
+4 -4
drivers/dma-buf/dma-buf.c
··· 543 543 file->f_mode |= FMODE_LSEEK; 544 544 dmabuf->file = file; 545 545 546 - ret = dma_buf_stats_setup(dmabuf); 547 - if (ret) 548 - goto err_sysfs; 549 - 550 546 mutex_init(&dmabuf->lock); 551 547 INIT_LIST_HEAD(&dmabuf->attachments); 552 548 553 549 mutex_lock(&db_list.lock); 554 550 list_add(&dmabuf->list_node, &db_list.head); 555 551 mutex_unlock(&db_list.lock); 552 + 553 + ret = dma_buf_stats_setup(dmabuf); 554 + if (ret) 555 + goto err_sysfs; 556 556 557 557 return dmabuf; 558 558
+5 -4
drivers/gpu/drm/nouveau/nouveau_backlight.c
··· 46 46 nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], 47 47 struct nouveau_backlight *bl) 48 48 { 49 - const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL); 50 - if (nb < 0 || nb >= 100) 49 + const int nb = ida_alloc_max(&bl_ida, 99, GFP_KERNEL); 50 + 51 + if (nb < 0) 51 52 return false; 52 53 if (nb > 0) 53 54 snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb); ··· 415 414 nv_encoder, ops, &props); 416 415 if (IS_ERR(bl->dev)) { 417 416 if (bl->id >= 0) 418 - ida_simple_remove(&bl_ida, bl->id); 417 + ida_free(&bl_ida, bl->id); 419 418 ret = PTR_ERR(bl->dev); 420 419 goto fail_alloc; 421 420 } ··· 443 442 return; 444 443 445 444 if (bl->id >= 0) 446 - ida_simple_remove(&bl_ida, bl->id); 445 + ida_free(&bl_ida, bl->id); 447 446 448 447 backlight_device_unregister(bl->dev); 449 448 nv_conn->backlight = NULL;
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
··· 123 123 124 124 mutex_init(&tdev->iommu.mutex); 125 125 126 - if (iommu_present(&platform_bus_type)) { 126 + if (device_iommu_mapped(dev)) { 127 127 tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type); 128 128 if (!tdev->iommu.domain) 129 129 goto error;
+1
drivers/gpu/drm/vc4/vc4_hdmi.c
··· 38 38 #include <drm/drm_scdc_helper.h> 39 39 #include <linux/clk.h> 40 40 #include <linux/component.h> 41 + #include <linux/gpio/consumer.h> 41 42 #include <linux/i2c.h> 42 43 #include <linux/of_address.h> 43 44 #include <linux/of_gpio.h>
+8 -5
drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
··· 528 528 *seqno = atomic_add_return(1, &dev_priv->marker_seq); 529 529 } while (*seqno == 0); 530 530 531 - if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE)) { 531 + if (!vmw_has_fences(dev_priv)) { 532 532 533 533 /* 534 534 * Don't request hardware to send a fence. The ··· 675 675 */ 676 676 bool vmw_cmd_supported(struct vmw_private *vmw) 677 677 { 678 - if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | 679 - SVGA_CAP_CMD_BUFFERS_2)) != 0) 680 - return true; 678 + bool has_cmdbufs = 679 + (vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | 680 + SVGA_CAP_CMD_BUFFERS_2)) != 0; 681 + if (vmw_is_svga_v3(vmw)) 682 + return (has_cmdbufs && 683 + (vmw->capabilities & SVGA_CAP_GBOBJECTS) != 0); 681 684 /* 682 685 * We have FIFO cmd's 683 686 */ 684 - return vmw->fifo_mem != NULL; 687 + return has_cmdbufs || vmw->fifo_mem != NULL; 685 688 }
+8
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
··· 1679 1679 outl(status, vmw->io_start + SVGA_IRQSTATUS_PORT); 1680 1680 } 1681 1681 1682 + static inline bool vmw_has_fences(struct vmw_private *vmw) 1683 + { 1684 + if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | 1685 + SVGA_CAP_CMD_BUFFERS_2)) != 0) 1686 + return true; 1687 + return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0; 1688 + } 1689 + 1682 1690 #endif
+1 -1
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
··· 483 483 484 484 static int vmw_fb_kms_framebuffer(struct fb_info *info) 485 485 { 486 - struct drm_mode_fb_cmd2 mode_cmd; 486 + struct drm_mode_fb_cmd2 mode_cmd = {0}; 487 487 struct vmw_fb_par *par = info->par; 488 488 struct fb_var_screeninfo *var = &info->var; 489 489 struct drm_framebuffer *cur_fb;
+21 -7
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
··· 82 82 return container_of(fence->base.lock, struct vmw_fence_manager, lock); 83 83 } 84 84 85 + static u32 vmw_fence_goal_read(struct vmw_private *vmw) 86 + { 87 + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) 88 + return vmw_read(vmw, SVGA_REG_FENCE_GOAL); 89 + else 90 + return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL); 91 + } 92 + 93 + static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value) 94 + { 95 + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) 96 + vmw_write(vmw, SVGA_REG_FENCE_GOAL, value); 97 + else 98 + vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value); 99 + } 100 + 85 101 /* 86 102 * Note on fencing subsystem usage of irqs: 87 103 * Typically the vmw_fences_update function is called ··· 408 392 if (likely(!fman->seqno_valid)) 409 393 return false; 410 394 411 - goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL); 395 + goal_seqno = vmw_fence_goal_read(fman->dev_priv); 412 396 if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP)) 413 397 return false; 414 398 ··· 416 400 list_for_each_entry(fence, &fman->fence_list, head) { 417 401 if (!list_empty(&fence->seq_passed_actions)) { 418 402 fman->seqno_valid = true; 419 - vmw_fifo_mem_write(fman->dev_priv, 420 - SVGA_FIFO_FENCE_GOAL, 421 - fence->base.seqno); 403 + vmw_fence_goal_write(fman->dev_priv, 404 + fence->base.seqno); 422 405 break; 423 406 } 424 407 } ··· 449 434 if (dma_fence_is_signaled_locked(&fence->base)) 450 435 return false; 451 436 452 - goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL); 437 + goal_seqno = vmw_fence_goal_read(fman->dev_priv); 453 438 if (likely(fman->seqno_valid && 454 439 goal_seqno - fence->base.seqno < VMW_FENCE_WRAP)) 455 440 return false; 456 441 457 - vmw_fifo_mem_write(fman->dev_priv, SVGA_FIFO_FENCE_GOAL, 458 - fence->base.seqno); 442 + vmw_fence_goal_write(fman->dev_priv, fence->base.seqno); 459 443 fman->seqno_valid = true; 460 444 461 445 return true;
+18 -8
drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
··· 32 32 33 33 #define VMW_FENCE_WRAP (1 << 24) 34 34 35 + static u32 vmw_irqflag_fence_goal(struct vmw_private *vmw) 36 + { 37 + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) 38 + return SVGA_IRQFLAG_REG_FENCE_GOAL; 39 + else 40 + return SVGA_IRQFLAG_FENCE_GOAL; 41 + } 42 + 35 43 /** 36 44 * vmw_thread_fn - Deferred (process context) irq handler 37 45 * ··· 104 96 wake_up_all(&dev_priv->fifo_queue); 105 97 106 98 if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE | 107 - SVGA_IRQFLAG_FENCE_GOAL)) && 99 + vmw_irqflag_fence_goal(dev_priv))) && 108 100 !test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending)) 109 101 ret = IRQ_WAKE_THREAD; 110 102 ··· 145 137 if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) 146 138 return true; 147 139 148 - if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE) && 149 - vmw_fifo_idle(dev_priv, seqno)) 140 + if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno)) 150 141 return true; 151 142 152 143 /** ··· 167 160 unsigned long timeout) 168 161 { 169 162 struct vmw_fifo_state *fifo_state = dev_priv->fifo; 163 + bool fifo_down = false; 170 164 171 165 uint32_t count = 0; 172 166 uint32_t signal_seq; ··· 184 176 */ 185 177 186 178 if (fifo_idle) { 187 - down_read(&fifo_state->rwsem); 188 179 if (dev_priv->cman) { 189 180 ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible, 190 181 10*HZ); 191 182 if (ret) 192 183 goto out_err; 184 + } else if (fifo_state) { 185 + down_read(&fifo_state->rwsem); 186 + fifo_down = true; 193 187 } 194 188 } 195 189 ··· 228 218 } 229 219 } 230 220 finish_wait(&dev_priv->fence_queue, &__wait); 231 - if (ret == 0 && fifo_idle) 221 + if (ret == 0 && fifo_idle && fifo_state) 232 222 vmw_fence_write(dev_priv, signal_seq); 233 223 234 224 wake_up_all(&dev_priv->fence_queue); 235 225 out_err: 236 - if (fifo_idle) 226 + if (fifo_down) 237 227 up_read(&fifo_state->rwsem); 238 228 239 229 return ret; ··· 276 266 277 267 void vmw_goal_waiter_add(struct vmw_private *dev_priv) 278 268 { 279 - vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, 269 + vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv), 280 270 &dev_priv->goal_queue_waiters); 281 271 } 282 272 283 273 void vmw_goal_waiter_remove(struct vmw_private *dev_priv) 284 274 { 285 - vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, 275 + vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv), 286 276 &dev_priv->goal_queue_waiters); 287 277 } 288 278
+5 -3
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 1344 1344 ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb, 1345 1345 mode_cmd, 1346 1346 is_bo_proxy); 1347 - 1348 1347 /* 1349 1348 * vmw_create_bo_proxy() adds a reference that is no longer 1350 1349 * needed ··· 1384 1385 ret = vmw_user_lookup_handle(dev_priv, file_priv, 1385 1386 mode_cmd->handles[0], 1386 1387 &surface, &bo); 1387 - if (ret) 1388 + if (ret) { 1389 + DRM_ERROR("Invalid buffer object handle %u (0x%x).\n", 1390 + mode_cmd->handles[0], mode_cmd->handles[0]); 1388 1391 goto err_out; 1392 + } 1389 1393 1390 1394 1391 1395 if (!bo && 1392 1396 !vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) { 1393 - DRM_ERROR("Surface size cannot exceed %dx%d", 1397 + DRM_ERROR("Surface size cannot exceed %dx%d\n", 1394 1398 dev_priv->texture_max_width, 1395 1399 dev_priv->texture_max_height); 1396 1400 goto err_out;
+1 -4
drivers/video/fbdev/core/fbmem.c
··· 1434 1434 __acquires(&info->lock) 1435 1435 __releases(&info->lock) 1436 1436 { 1437 - struct fb_info * const info = file_fb_info(file); 1438 - 1439 - if (!info) 1440 - return -ENODEV; 1437 + struct fb_info * const info = file->private_data; 1441 1438 1442 1439 lock_fb_info(info); 1443 1440 if (info->fbops->fb_release)
+4
drivers/video/fbdev/core/fbsysfs.c
··· 80 80 { 81 81 if (!info) 82 82 return; 83 + 84 + if (WARN_ON(refcount_read(&info->count))) 85 + return; 86 + 83 87 kfree(info->apertures); 84 88 kfree(info); 85 89 }
+8 -1
drivers/video/fbdev/efifb.c
··· 243 243 static inline void efifb_show_boot_graphics(struct fb_info *info) {} 244 244 #endif 245 245 246 + /* 247 + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end 248 + * of unregister_framebuffer() or fb_release(). Do any cleanup here. 249 + */ 246 250 static void efifb_destroy(struct fb_info *info) 247 251 { 248 252 if (efifb_pci_dev) ··· 258 254 else 259 255 memunmap(info->screen_base); 260 256 } 257 + 261 258 if (request_mem_succeeded) 262 259 release_mem_region(info->apertures->ranges[0].base, 263 260 info->apertures->ranges[0].size); 264 261 fb_dealloc_cmap(&info->cmap); 262 + 263 + framebuffer_release(info); 265 264 } 266 265 267 266 static const struct fb_ops efifb_ops = { ··· 627 620 { 628 621 struct fb_info *info = platform_get_drvdata(pdev); 629 622 623 + /* efifb_destroy takes care of info cleanup */ 630 624 unregister_framebuffer(info); 631 625 sysfs_remove_groups(&pdev->dev.kobj, efifb_groups); 632 - framebuffer_release(info); 633 626 634 627 return 0; 635 628 }
+7 -1
drivers/video/fbdev/simplefb.c
··· 84 84 static void simplefb_clocks_destroy(struct simplefb_par *par); 85 85 static void simplefb_regulators_destroy(struct simplefb_par *par); 86 86 87 + /* 88 + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end 89 + * of unregister_framebuffer() or fb_release(). Do any cleanup here. 90 + */ 87 91 static void simplefb_destroy(struct fb_info *info) 88 92 { 89 93 struct simplefb_par *par = info->par; ··· 97 93 simplefb_clocks_destroy(info->par); 98 94 if (info->screen_base) 99 95 iounmap(info->screen_base); 96 + 97 + framebuffer_release(info); 100 98 101 99 if (mem) 102 100 release_mem_region(mem->start, resource_size(mem)); ··· 551 545 { 552 546 struct fb_info *info = platform_get_drvdata(pdev); 553 547 548 + /* simplefb_destroy takes care of info cleanup */ 554 549 unregister_framebuffer(info); 555 - framebuffer_release(info); 556 550 557 551 return 0; 558 552 }
+7 -1
drivers/video/fbdev/vesafb.c
··· 179 179 return err; 180 180 } 181 181 182 + /* 183 + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end 184 + * of unregister_framebuffer() or fb_release(). Do any cleanup here. 185 + */ 182 186 static void vesafb_destroy(struct fb_info *info) 183 187 { 184 188 struct vesafb_par *par = info->par; ··· 192 188 if (info->screen_base) 193 189 iounmap(info->screen_base); 194 190 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); 191 + 192 + framebuffer_release(info); 195 193 } 196 194 197 195 static struct fb_ops vesafb_ops = { ··· 490 484 { 491 485 struct fb_info *info = platform_get_drvdata(pdev); 492 486 487 + /* vesafb_destroy takes care of info cleanup */ 493 488 unregister_framebuffer(info); 494 489 if (((struct vesafb_par *)(info->par))->region) 495 490 release_region(0x3c0, 32); 496 - framebuffer_release(info); 497 491 498 492 return 0; 499 493 }