bool CopyToUser(void* userdst_ptr, const void* ksrc_ptr, size_t count) { uintptr_t userdst = (uintptr_t) userdst_ptr; uintptr_t ksrc = (uintptr_t) ksrc_ptr; bool result = true; Process* process = CurrentProcess(); assert(IsInProcessAddressSpace(process)); kthread_mutex_lock(&process->segment_lock); while ( count ) { struct segment* segment = FindSegment(process, userdst); if ( !segment || !(segment->prot & PROT_WRITE) ) { errno = EFAULT; result = false; break; } size_t amount = count; size_t segment_available = segment->addr + segment->size - userdst; if ( segment_available < amount ) amount = segment_available; memcpy((void*) userdst, (const void*) ksrc, amount); userdst += amount; ksrc += amount; count -= amount; } kthread_mutex_unlock(&process->segment_lock); return result; }
// Get process ID via name (must pass name as lowercase) DWORD Injector::GetProcessIdByName(const std::tstring& Name) { // Grab a new snapshot of the process EnsureCloseHandle Snap(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0)); if (Snap == INVALID_HANDLE_VALUE) throw std::runtime_error("Could not get process snapshot."); // Search for process PROCESSENTRY32 ProcEntry = { sizeof(ProcEntry) }; bool Found = false; BOOL MoreMods = Process32First(Snap, &ProcEntry); for (; MoreMods; MoreMods = Process32Next(Snap, &ProcEntry)) { std::tstring CurrentProcess(ProcEntry.szExeFile); CurrentProcess = toLower(CurrentProcess); Found = (CurrentProcess == Name); if (Found) break; } // Check process was found if (!Found) throw std::runtime_error("Could not find process."); // Return PID return ProcEntry.th32ProcessID; }
/******************************************************************************* * Function Name : main. * Description : Main routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ int main(void) { #ifdef DEBUG debug(); #endif Set_System(); Set_USBClock(); USB_Config(); USB_Init(); InitialIO(); InitialADC(); #ifdef JOYSTICK SSD1303_Init(); InitialSSD1306_controller(); #endif InitialProcTask(); //WaitConfig(); InitialDevice(&dev,&SSD1303_Prop,SongSmall5_DrawChar); SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); SysTick_SetReload(72000000/20); SysTick_CounterCmd(SysTick_Counter_Enable); SysTick_ITConfig(ENABLE); CurrentProcess = JoystickProcess; CurrentSystick = JoystickSystick; JoystickUIInit(); void HidProcess(void); while (1) { HidProcess(); continue; static u8 lastCamOn = 0; if(lastCamOn != bCameraOn) { if(bCameraOn) { CurrentProcess = TetrisProcess; CurrentSystick = TetrisSystick; TetrisUIInit(); } else { CurrentProcess = JoystickProcess; CurrentSystick = JoystickSystick; JoystickUIInit(); } } lastCamOn = bCameraOn; CurrentProcess(); } }
// NOTE: No overflow can happen here because the user can't make an infinitely // long string spanning the entire address space because the user can't // control the entire address space. char* GetStringFromUser(const char* usersrc_str) { uintptr_t usersrc = (uintptr_t) usersrc_str; size_t result_length = 0; Process* process = CurrentProcess(); assert(IsInProcessAddressSpace(process)); kthread_mutex_lock(&process->segment_lock); bool done = false; while ( !done ) { uintptr_t current_at = usersrc + result_length; struct segment* segment = FindSegment(process, current_at); if ( !segment || !(segment->prot & PROT_READ) ) { kthread_mutex_unlock(&process->segment_lock); return errno = EFAULT, (char*) NULL; } size_t segment_available = segment->addr + segment->size - current_at; volatile const char* str = (volatile const char*) current_at; size_t length = 0; for ( ; length < segment_available; length++ ) { char c = str[length]; if ( c == '\0' ) { done = true; break; } } result_length += length; } char* result = new char[result_length + 1]; if ( !result ) { kthread_mutex_unlock(&process->segment_lock); return (char*) NULL; } memcpy(result, (const char*) usersrc, result_length); result[result_length] = '\0'; // We have transferred a bunch of bytes from user-space and appended a zero // byte. This is a string. If no concurrent threads were modifying the // memory, this is the intended string. If the memory was modified, we got // potential garbage followed by a NUL byte. This is a string, but probably // not what was intended. If the garbage itself had a premature unexpected // NUL byte, that's okay, the garbage string just got truncated. kthread_mutex_unlock(&process->segment_lock); return result; }
void UserCrashHandler(struct interrupt_context* intctx) { Scheduler::SaveInterruptedContext(intctx, &CurrentThread()->registers); // Execute this crash handler with preemption on. Interrupt::Enable(); // TODO: Also send signals for other types of user-space crashes. if ( intctx->int_no == 14 /* Page fault */ ) { struct sigaction* act = &CurrentProcess()->signal_actions[SIGSEGV]; kthread_mutex_lock(&CurrentProcess()->signal_lock); bool handled = act->sa_handler != SIG_DFL && act->sa_handler != SIG_IGN; if ( handled ) CurrentThread()->DeliverSignalUnlocked(SIGSEGV); kthread_mutex_unlock(&CurrentProcess()->signal_lock); if ( handled ) { assert(Interrupt::IsEnabled()); return Signal::DispatchHandler(intctx, NULL); } } // Issue a diagnostic message to the kernel log concerning the crash. Log::PrintF("The current process (pid %ji `%s') crashed and was terminated:\n", (intmax_t) CurrentProcess()->pid, CurrentProcess()->program_image_path); Log::PrintF("%s exception at ip=0x%zx (cr2=0x%zx, err_code=0x%zx)\n", ExceptionName(intctx), ExceptionLocation(intctx), intctx->cr2, intctx->err_code); // Exit the process with the right error code. // TODO: Send a SIGINT, SIGBUS, or whatever instead. CurrentProcess()->ExitThroughSignal(SIGSEGV); // Deliver signals to this thread so it can exit correctly. assert(Interrupt::IsEnabled()); Signal::DispatchHandler(intctx, NULL); }
extern unsigned long __GetSystemWideUniqueTID(void) { return(CurrentProcess()); }
int sys_ppoll(struct pollfd* user_fds, size_t nfds, const struct timespec* user_timeout_ts, const sigset_t* user_sigmask) { ioctx_t ctx; SetupKernelIOCtx(&ctx); struct timespec timeout_ts; if ( !FetchTimespec(&timeout_ts, user_timeout_ts) ) return -1; if ( user_sigmask ) return errno = ENOSYS, -1; struct pollfd* fds = CopyFdsFromUser(user_fds, nfds); if ( !fds ) { return -1; } PollNode* nodes = new PollNode[nfds]; if ( !nodes ) { delete[] fds; return -1; } Process* process = CurrentProcess(); kthread_mutex_t wakeup_mutex = KTHREAD_MUTEX_INITIALIZER; kthread_cond_t wakeup_cond = KTHREAD_COND_INITIALIZER; kthread_mutex_lock(&wakeup_mutex); int ret = -1; bool self_woken = false; bool remote_woken = false; bool unexpected_error = false; Timer timer; struct poll_timeout pts; if ( timespec_le(timespec_make(0, 1), timeout_ts) ) { timer.Attach(Time::GetClock(CLOCK_MONOTONIC)); struct itimerspec its; its.it_interval = timespec_nul(); its.it_value = timeout_ts; pts.wake_mutex = &wakeup_mutex; pts.wake_cond = &wakeup_cond; pts.woken = &remote_woken; timer.Set(&its, NULL, 0, poll_timeout_callback, &pts); } size_t reqs; for ( reqs = 0; !unexpected_error && reqs < nfds; ) { PollNode* node = nodes + reqs; if ( fds[reqs].fd < 0 ) { fds[reqs].revents = POLLNVAL; // TODO: Should we set POLLNVAL in node->revents too? Should this // system call ignore this error and keep polling, or return to // user-space immediately? What if conditions are already true on // some of the file descriptors (those we have processed so far?)? node->revents = 0; reqs++; continue; } Ref<Descriptor> desc = process->GetDescriptor(fds[reqs].fd); if ( !desc ) { self_woken = unexpected_error = true; break; } node->events = fds[reqs].events | POLL__ONLY_REVENTS; node->revents = 0; node->wake_mutex = &wakeup_mutex; node->wake_cond = &wakeup_cond; node->woken = &remote_woken; reqs++; // TODO: How should errors be handled? if ( desc->poll(&ctx, node) == 0 ) self_woken = true; else if ( errno == EAGAIN ) errno = 0; else unexpected_error = self_woken = true; } if ( timeout_ts.tv_sec == 0 && timeout_ts.tv_nsec == 0 ) self_woken = true; while ( !(self_woken || remote_woken) ) { if ( !kthread_cond_wait_signal(&wakeup_cond, &wakeup_mutex) ) errno = -EINTR, self_woken = true; } kthread_mutex_unlock(&wakeup_mutex); for ( size_t i = 0; i < reqs; i++ ) if ( 0 <= fds[i].fd ) nodes[i].Cancel(); if ( timespec_le(timespec_make(0, 1), timeout_ts) ) { timer.Cancel(); timer.Detach(); } if ( !unexpected_error ) { int num_events = 0; for ( size_t i = 0; i < reqs; i++ ) { if ( fds[i].fd < -1 ) continue; if ( (fds[i].revents = nodes[i].revents) ) num_events++; } if ( CopyFdsToUser(user_fds, fds, nfds) ) ret = num_events; } delete[] nodes; delete[] fds; return ret; }