static errno_t sf_attach(void** cookie, socket_t so) { errno_t ret = 0; lck_mtx_lock(global_mutex); char name[PATH_MAX]; proc_selfname(name, PATH_MAX); pp("proc_selfname: %s", name); if (strncmp(name, "nc", 3)) { pp("装载到进程: %s", name); } else { ret = ENOPOLICY; } lck_mtx_unlock(global_mutex); return ret; }
static errno_t sf_connect_out(void* cookie, socket_t so, const struct sockaddr* to) { errno_t ret = 0; lck_mtx_lock(global_mutex); // struct sockaddr_in* addr = (struct sockaddr_in*)to; // if (inet_pton(AF_INET, proxy_ip, &addr->sin_addr.s_addr) == 0) { // sf_printf("inet_pton(%s) 失败", proxy_ip); // return -1; // } char name[PATH_MAX]; proc_selfname(name, PATH_MAX); pp("proc_selfname: %s", name); lck_mtx_unlock(global_mutex); return ret; }
//process // block/allow, or ask user and put thread to sleep kern_return_t process(void *cookie, socket_t so, const struct sockaddr *to) { //result kern_return_t result = kIOReturnError; //event firewallEvent event = {0}; //rule int action = RULE_STATE_NOT_FOUND; //awake reason int reason = 0; //socket type int socketType = 0; //length of socket type int socketTypeLength = 0; //process name char processName[PATH_MAX] = {0}; //what does rule say? // loop until we have an answer while(true) { //reset bzero(&event, sizeof(event)); //extract action action = ((struct cookieStruct*)cookie)->ruleAction; //get process name proc_selfname(processName, PATH_MAX); //block? if(RULE_STATE_BLOCK == action) { //dbg msg IOLog("LULU: rule says block for %s (pid: %d)\n", processName, proc_selfpid()); //gtfo! result = EPERM; //all done goto bail; } //allow? else if(RULE_STATE_ALLOW == action) { //dbg msg IOLog("LULU: rule says allow for %s (pid: %d)\n", processName, proc_selfpid()); //ok result = kIOReturnSuccess; //all done goto bail; } //not found // ->ask daemon and sleep for response else if(RULE_STATE_NOT_FOUND == action) { //dbg msg IOLog("LULU: no rule found for %s (pid: %d)\n", processName, proc_selfpid()); //zero out bzero(&event, sizeof(firewallEvent)); //set type event.networkOutEvent.type = EVENT_NETWORK_OUT; //add pid event.networkOutEvent.pid = proc_selfpid(); //init length socketTypeLength = sizeof(socketType); //get socket type sock_getsockopt(so, SOL_SOCKET, SO_TYPE, &socketType, &socketTypeLength); //save type event.networkOutEvent.socketType = socketType; //UDP sockets destination socket might be null // so grab via 'getpeername' and save as 'remote addr' if(NULL == to) { //copy into 'remote addr' for user mode if(0 != sock_getpeername(so, (struct sockaddr*)&(event.networkOutEvent.remoteAddress), sizeof(event.networkOutEvent.remoteAddress))) { //err msg IOLog("LULU ERROR: sock_getpeername() failed"); //bail goto bail; } } //copy remote socket for user mode else { //add remote (destination) socket addr memcpy(&(event.networkOutEvent.remoteAddress), to, sizeof(event.networkOutEvent.remoteAddress)); } //queue it up sharedDataQueue->enqueue_tail(&event, sizeof(firewallEvent)); //dbg msg IOLog("LULU: queued response to user mode, now going to sleep!\n"); //lock IOLockLock(ruleEventLock); //sleep reason = IOLockSleep(ruleEventLock, &ruleEventLock, THREAD_ABORTSAFE); //TODO: fix panic, think if kext is unloaded (sets ruleEventLock to NULL) this can still wake up? // "Preemption level underflow, possible cause unlocking an unlocked mutex or spinlock" // seems to happen when process is killed or kext unloaded while in the IOLockSleep!? //unlock IOLockUnlock(ruleEventLock); //thread wakeup cuz of signal, etc // ->just bail (process likely exited, etc) if(THREAD_AWAKENED != reason) { //dbg msg IOLog("LULU: thread awoke, but because of %d!\n", reason); //gtfo! result = EPERM; //all done goto bail; } //dbg msg IOLog("LULU: thread awoke, will check/process response\n"); //try get rule action again // ->not found, block, allow, etc ((struct cookieStruct*)(cookie))->ruleAction = queryRule(proc_selfpid()); //loop to (re)process } }//while bail: return result; }