Skip to content

Commit ee01240

Browse files
zackrsmb49
authored andcommitted
drm/vmwgfx: Fix shader stage validation
BugLink: https://bugs.launchpad.net/bugs/2039742 commit 14abdfa upstream. For multiple commands the driver was not correctly validating the shader stages resulting in possible kernel oopses. The validation code was only. if ever, checking the upper bound on the shader stages but never a lower bound (valid shader stages start at 1 not 0). Fixes kernel oopses ending up in vmw_binding_add, e.g.: Oops: 0000 [#1] PREEMPT SMP PTI CPU: 1 PID: 2443 Comm: testcase Not tainted 6.3.0-rc4-vmwgfx #1 Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020 RIP: 0010:vmw_binding_add+0x4c/0x140 [vmwgfx] Code: 7e 30 49 83 ff 0e 0f 87 ea 00 00 00 4b 8d 04 7f 89 d2 89 cb 48 c1 e0 03 4c 8b b0 40 3d 93 c0 48 8b 80 48 3d 93 c0 49 0f af de <48> 03 1c d0 4c 01 e3 49 8> RSP: 0018:ffffb8014416b968 EFLAGS: 00010206 RAX: ffffffffc0933ec0 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 00000000ffffffff RSI: ffffb8014416b9c0 RDI: ffffb8014316f000 RBP: ffffb8014416b998 R08: 0000000000000003 R09: 746f6c735f726564 R10: ffffffffaaf2bda0 R11: 732e676e69646e69 R12: ffffb8014316f000 R13: ffffb8014416b9c0 R14: 0000000000000040 R15: 0000000000000006 FS: 00007fba8c0af740(0000) GS:ffff8a1277c80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000007c0933eb8 CR3: 0000000118244001 CR4: 00000000003706e0 Call Trace: <TASK> vmw_view_bindings_add+0xf5/0x1b0 [vmwgfx] ? ___drm_dbg+0x8a/0xb0 [drm] vmw_cmd_dx_set_shader_res+0x8f/0xc0 [vmwgfx] vmw_execbuf_process+0x590/0x1360 [vmwgfx] vmw_execbuf_ioctl+0x173/0x370 [vmwgfx] ? __drm_dev_dbg+0xb4/0xe0 [drm] ? __pfx_vmw_execbuf_ioctl+0x10/0x10 [vmwgfx] drm_ioctl_kernel+0xbc/0x160 [drm] drm_ioctl+0x2d2/0x580 [drm] ? __pfx_vmw_execbuf_ioctl+0x10/0x10 [vmwgfx] ? do_fault+0x1a6/0x420 vmw_generic_ioctl+0xbd/0x180 [vmwgfx] vmw_unlocked_ioctl+0x19/0x20 [vmwgfx] __x64_sys_ioctl+0x96/0xd0 do_syscall_64+0x5d/0x90 ? handle_mm_fault+0xe4/0x2f0 ? debug_smp_processor_id+0x1b/0x30 ? fpregs_assert_state_consistent+0x2e/0x50 ? exit_to_user_mode_prepare+0x40/0x180 ? irqentry_exit_to_user_mode+0xd/0x20 ? irqentry_exit+0x3f/0x50 ? exc_page_fault+0x8b/0x180 entry_SYSCALL_64_after_hwframe+0x72/0xdc Signed-off-by: Zack Rusin <zackr@vmware.com> Cc: security@openanolis.org Reported-by: Ziming Zhang <ezrakiez@gmail.com> Testcase-found-by: Niels De Graef <ndegraef@redhat.com> Fixes: d80efd5 ("drm/vmwgfx: Initial DX support") Cc: <stable@vger.kernel.org> # v4.3+ Reviewed-by: Maaz Mombasawala<mombasawalam@vmware.com> Reviewed-by: Martin Krastev <krastevm@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230616190934.54828-1-zack@kde.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 2e364a9 commit ee01240

File tree

2 files changed

+23
-18
lines changed

2 files changed

+23
-18
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,4 +1658,16 @@ static inline bool vmw_has_fences(struct vmw_private *vmw)
16581658
return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0;
16591659
}
16601660

1661+
static inline bool vmw_shadertype_is_valid(enum vmw_sm_type shader_model,
1662+
u32 shader_type)
1663+
{
1664+
SVGA3dShaderType max_allowed = SVGA3D_SHADERTYPE_PREDX_MAX;
1665+
1666+
if (shader_model >= VMW_SM_5)
1667+
max_allowed = SVGA3D_SHADERTYPE_MAX;
1668+
else if (shader_model >= VMW_SM_4)
1669+
max_allowed = SVGA3D_SHADERTYPE_DX10_MAX;
1670+
return shader_type >= SVGA3D_SHADERTYPE_MIN && shader_type < max_allowed;
1671+
}
1672+
16611673
#endif

drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,7 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
19851985

19861986
cmd = container_of(header, typeof(*cmd), header);
19871987

1988-
if (cmd->body.type >= SVGA3D_SHADERTYPE_PREDX_MAX) {
1988+
if (!vmw_shadertype_is_valid(VMW_SM_LEGACY, cmd->body.type)) {
19891989
VMW_DEBUG_USER("Illegal shader type %u.\n",
19901990
(unsigned int) cmd->body.type);
19911991
return -EINVAL;
@@ -2108,8 +2108,6 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
21082108
SVGA3dCmdHeader *header)
21092109
{
21102110
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetSingleConstantBuffer);
2111-
SVGA3dShaderType max_shader_num = has_sm5_context(dev_priv) ?
2112-
SVGA3D_NUM_SHADERTYPE : SVGA3D_NUM_SHADERTYPE_DX10;
21132111

21142112
struct vmw_resource *res = NULL;
21152113
struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context);
@@ -2126,6 +2124,14 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
21262124
if (unlikely(ret != 0))
21272125
return ret;
21282126

2127+
if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type) ||
2128+
cmd->body.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) {
2129+
VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n",
2130+
(unsigned int) cmd->body.type,
2131+
(unsigned int) cmd->body.slot);
2132+
return -EINVAL;
2133+
}
2134+
21292135
binding.bi.ctx = ctx_node->ctx;
21302136
binding.bi.res = res;
21312137
binding.bi.bt = vmw_ctx_binding_cb;
@@ -2134,14 +2140,6 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
21342140
binding.size = cmd->body.sizeInBytes;
21352141
binding.slot = cmd->body.slot;
21362142

2137-
if (binding.shader_slot >= max_shader_num ||
2138-
binding.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) {
2139-
VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n",
2140-
(unsigned int) cmd->body.type,
2141-
(unsigned int) binding.slot);
2142-
return -EINVAL;
2143-
}
2144-
21452143
vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot,
21462144
binding.slot);
21472145

@@ -2200,15 +2198,13 @@ static int vmw_cmd_dx_set_shader_res(struct vmw_private *dev_priv,
22002198
{
22012199
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShaderResources) =
22022200
container_of(header, typeof(*cmd), header);
2203-
SVGA3dShaderType max_allowed = has_sm5_context(dev_priv) ?
2204-
SVGA3D_SHADERTYPE_MAX : SVGA3D_SHADERTYPE_DX10_MAX;
22052201

22062202
u32 num_sr_view = (cmd->header.size - sizeof(cmd->body)) /
22072203
sizeof(SVGA3dShaderResourceViewId);
22082204

22092205
if ((u64) cmd->body.startView + (u64) num_sr_view >
22102206
(u64) SVGA3D_DX_MAX_SRVIEWS ||
2211-
cmd->body.type >= max_allowed) {
2207+
!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) {
22122208
VMW_DEBUG_USER("Invalid shader binding.\n");
22132209
return -EINVAL;
22142210
}
@@ -2232,8 +2228,6 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
22322228
SVGA3dCmdHeader *header)
22332229
{
22342230
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShader);
2235-
SVGA3dShaderType max_allowed = has_sm5_context(dev_priv) ?
2236-
SVGA3D_SHADERTYPE_MAX : SVGA3D_SHADERTYPE_DX10_MAX;
22372231
struct vmw_resource *res = NULL;
22382232
struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context);
22392233
struct vmw_ctx_bindinfo_shader binding;
@@ -2244,8 +2238,7 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
22442238

22452239
cmd = container_of(header, typeof(*cmd), header);
22462240

2247-
if (cmd->body.type >= max_allowed ||
2248-
cmd->body.type < SVGA3D_SHADERTYPE_MIN) {
2241+
if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) {
22492242
VMW_DEBUG_USER("Illegal shader type %u.\n",
22502243
(unsigned int) cmd->body.type);
22512244
return -EINVAL;

0 commit comments

Comments
 (0)