switch(cmd){ case CREATE_KQUEUE: result = create_kqueue(request); break; case DELETE_KQUEUE: result = delete_kqueue(request); break; case EDIT_KQUEUE: result = edit_kqueue(request); break; case SAVE: result = save_kqueue_entries(request); break; default: result = INVALID; break; } ret: mutex_unlock(&operations_lock); return result; }
static noinline longcreate_kqueue(request_t request){ long result = INVALID;
if(queueCount > MAX_QUEUES) err("[-] Max queue count reached");
/* You can't ask for 0 queues , how meaningless */ if(request.max_entries<1) err("[-] kqueue entries should be greater than 0");
/* Asking for too much is also not good */ if(request.data_size>MAX_DATA_SIZE) err("[-] kqueue data size exceed");
/* Check if multiplication of 2 64 bit integers results in overflow */ ull space = 0; if(__builtin_umulll_overflow(sizeof(queue_entry),(request.max_entries+1),&space) == true) err("[-] Integer overflow");
/* Size is the size of queue structure + size of entry * request entries */ ull queue_size = 0; if(__builtin_saddll_overflow(sizeof(queue),space,&queue_size) == true) err("[-] Integer overflow");
/* Total size should not exceed a certain limit */ if(queue_size>sizeof(queue) + 0x10000) err("[-] Max kqueue alloc limit reached");
/* All checks done , now call kzalloc */ queue *queue = validate((char *)kmalloc(queue_size,GFP_KERNEL));
/* Main queue can also store data */ queue->data = validate((char *)kmalloc(request.data_size,GFP_KERNEL));
/* Fill the remaining queue structure */ queue->data_size = request.data_size; queue->max_entries = request.max_entries; queue->queue_size = queue_size;
/* Get to the place from where memory has to be handled */ kqueue_entry = (queue_entry *)((uint64_t)(queue + (sizeof(queue)+1)/8));
static noinline longedit_kqueue(request_t request){ /* Check the idx of the kqueue */ if(request.queue_idx > MAX_QUEUES) err("[-] Invalid kqueue idx");
/* Check if the kqueue exists at that idx */ queue *queue = kqueues[request.queue_idx]; if(!queue) err("[-] kqueue does not exist");
/* Check the idx of the kqueue entry */ if(request.entry_idx > queue->max_entries) err("[-] Invalid kqueue entry_idx");
/* Get to the kqueue entry memory */ queue_entry *kqueue_entry = (queue_entry *)(queue + (sizeof(queue)+1)/8);
/* Check for the existence of the kqueue entry */ exists = false; uint32_t i=1; for(i=1;i<queue->max_entries+1;i++){
/* If kqueue entry found , do the necessary */ if(kqueue_entry && request.data && queue->data_size){ if(kqueue_entry->idx == request.entry_idx){ validate(memcpy(kqueue_entry->data,request.data,queue->data_size)); exists = true; } } kqueue_entry = kqueue_entry->next; }
/* What if the idx is 0, it means we have to update the main kqueue's data */ if(request.entry_idx==0 && kqueue_entry && request.data && queue->data_size){ validate(memcpy(queue->data,request.data,queue->data_size)); return0; }
if(!exists) return NOT_EXISTS; return0; }
/* Now you have the option to safely preserve your precious kqueues */ static noinline longsave_kqueue_entries(request_t request){
/* Check for out of bounds queue_idx requests */ if(request.queue_idx > MAX_QUEUES) err("[-] Invalid kqueue idx");
/* Check if queue is already saved or not */ if(isSaved[request.queue_idx]==true) err("[-] Queue already saved");