Exemple #1
0
/**
 * @brief PPP callback to retrieve OsiModules from the running OS.
 *
 * Current implementation returns all the memory areas mapped by the
 * process and the files they were mapped from. Libraries that have
 * many mappings will appear multiple times.
 *
 * @todo Remove duplicates from results.
 */
void on_get_libraries(CPUState *env, OsiProc *p, OsiModules **out_ms) {
	PTR ts_first, ts_current;
	target_ulong current_pid;
	OsiModules *ms;
	OsiModule *m;
	uint32_t ms_capacity = 16;

	PTR vma_first, vma_current;

	// Find the process with the indicated pid.
	ts_first = ts_current = get_task_struct(env, (_ESP & THREADINFO_MASK));
	if (ts_current == (PTR)NULL) goto error0;

	do {
		if ((current_pid = get_pid(env, ts_current)) == p->pid) break;
		ts_current = get_task_struct_next(env, ts_current);
	} while(ts_current != (PTR)NULL && ts_current != ts_first);

	// memory read error or process not found
	if (ts_current == (PTR)NULL || current_pid != p->pid) goto error0;

	// Read the module info for the process.
	vma_first = vma_current = get_vma_first(env, ts_current);
	if (vma_current == (PTR)NULL) goto error0;

	ms = (OsiModules *)g_malloc0(sizeof(OsiModules));
	ms->module = g_new(OsiModule, ms_capacity);
	do {
		if (ms->num == ms_capacity) {
			ms_capacity *= 2;
			ms->module = g_renew(OsiModule, ms->module, ms_capacity);
		}

		m = &ms->module[ms->num++];
		memset(m, 0, sizeof(OsiModule));
		fill_osimodule(env, m, vma_current);

		vma_current = get_vma_next(env, vma_current);
	} while(vma_current != (PTR)NULL && vma_current != vma_first);

	*out_ms = ms;
	return;

error0:
	*out_ms = NULL;
	return;
}
Exemple #2
0
/**
 * @brief PPP callback to retrieve OsiModules from the running OS.
 *
 * Current implementation returns all the memory areas mapped by the
 * process and the files they were mapped from. Libraries that have
 * many mappings will appear multiple times.
 *
 * @todo Remove duplicates from results.
 */
void on_get_libraries(CPUState *env, OsiProc *p, OsiModules **out_ms) {
	PTR ts_first, ts_current;
	target_ulong current_pid;
	OsiModules *ms;
	OsiModule *m;
	uint32_t ms_capacity = 16;
	PTR vma_first, vma_current;
#ifdef OSI_LINUX_LIST_THREADS
	PTR tg_first, tg_next;
#endif

	// Get a starting process.
	ts_first = ts_current = get_task_struct(env, (_ESP & THREADINFO_MASK));
	if (ts_current == (PTR)NULL) goto error0;
	if (ts_current+ki.task.thread_group_offset != get_thread_group(env, ts_current)) {
		ts_first = ts_current = get_task_struct_next(env, ts_current);
	}

	// Find the process that matches p->pid.
	// XXX: We could probably just use p->offset instead of traversing
	//	  the process list.
	// XXX: An infinite loop will be triggered if p is a thread and
	//		OSI_LINUX_LIST_THREADS is not enabled.
	do {
		if ((current_pid = get_pid(env, ts_current)) == p->pid) goto pid_found;
#ifdef OSI_LINUX_LIST_THREADS
		tg_first = ts_current+ki.task.thread_group_offset;
		while ((tg_next = get_thread_group(env, ts_current)) != tg_first) {
			ts_current = tg_next-ki.task.thread_group_offset;
			if ((current_pid = get_pid(env, ts_current)) == p->pid) goto pid_found;
		}
		ts_current = tg_first-ki.task.thread_group_offset;
#endif
		ts_current = get_task_struct_next(env, ts_current);
	} while(ts_current != (PTR)NULL && ts_current != ts_first);
pid_found:

	// memory read error or process not found
	if (ts_current == (PTR)NULL || current_pid != p->pid) goto error0;

	// Read the module info for the process.
	vma_first = vma_current = get_vma_first(env, ts_current);
	if (vma_current == (PTR)NULL) goto error0;

	ms = (OsiModules *)g_malloc0(sizeof(OsiModules));
	ms->module = g_new(OsiModule, ms_capacity);
	do {
		if (ms->num == ms_capacity) {
			ms_capacity *= 2;
			ms->module = g_renew(OsiModule, ms->module, ms_capacity);
		}

		m = &ms->module[ms->num++];
		memset(m, 0, sizeof(OsiModule));
		fill_osimodule(env, m, vma_current);

		vma_current = get_vma_next(env, vma_current);
	} while(vma_current != (PTR)NULL && vma_current != vma_first);

	*out_ms = ms;
	return;

error0:
	*out_ms = NULL;
	return;
}
Exemple #3
0
/**
 * @brief PPP callback to retrieve process list from the running OS.
 */
void on_get_processes(CPUState *env, OsiProcs **out_ps) {
	PTR ts_first, ts_current;
	OsiProcs *ps;
	OsiProc *p;
	uint32_t ps_capacity = 16;

	ts_first = ts_current = get_task_struct(env, (_ESP & THREADINFO_MASK));
	if (ts_current == (PTR)NULL) goto error0;

	// When thread_group points to itself, the task_struct belongs to a thread
	// (see kernel_structs.md for details). This will trigger an infinite loop
	// in the traversal loop.
	// Following next will lead us to a task_struct belonging to a process and
	// help avoid the condition.
	if (ts_current+ki.task.thread_group_offset != get_thread_group(env, ts_current)) {
		ts_first = ts_current = get_task_struct_next(env, ts_current);
	}

	ps = (OsiProcs *)g_malloc0(sizeof(OsiProcs));
	ps->proc = g_new(OsiProc, ps_capacity);
	do {
		if (ps->num == ps_capacity) {
			ps_capacity *= 2;
			ps->proc = g_renew(OsiProc, ps->proc, ps_capacity);
		}

		p = &ps->proc[ps->num++];

		// Garbage in p->name will cause fill_osiproc() to segfault.
		memset(p, 0, sizeof(OsiProc));
		fill_osiproc(env, p, ts_current);

#if 0
		/*********************************************************/
		// Test of fd -> name resolution.
		/*********************************************************/
		for (int fdn=0; fdn<10; fdn++) {
			char *s = get_fd_name(env, ts_current, fdn);
			LOG_INFO("%s fd%d -> %s", p->name, fdn, s);
			g_free(s);
		}
		/*********************************************************/
#endif

		ts_current = get_task_struct_next(env, ts_current);
	} while(ts_current != (PTR)NULL && ts_current != ts_first);

	// memory read error
	if (ts_current == (PTR)NULL) goto error1;

	*out_ps = ps;
	return;

error1:
	do {
		ps->num--;
		g_free(ps->proc[ps->num].name);
	} while (ps->num != 0);
	g_free(ps->proc);
	g_free(ps);
error0:
	*out_ps = NULL;
	return;
}
Exemple #4
0
/**
 * @brief PPP callback to retrieve process list from the running OS.
 */
void on_get_processes(CPUState *env, OsiProcs **out_ps) {
	PTR ts_first, ts_current;
	OsiProcs *ps;
	OsiProc *p;
	uint32_t ps_capacity = 16;
#ifdef OSI_LINUX_LIST_THREADS
	PTR tg_first, tg_next;
#endif

	// Get a task_struct of a process to start iterating the process list. If
	// current task is a thread (ts->t_group != &ts->t_group), follow ts->next
	// to get to a process.
	// Always starting the traversal with a process has the benefits of:
	// 	a. Simplifying the traversal when OSI_LINUX_LIST_THREADS is disabled.
	//  b. Avoiding an infinite loop when OSI_LINUX_LIST_THREADS is enabled and
	//	 the current task is a thread.
	// See kernel_structs.md for details.
	ts_first = ts_current = get_task_struct(env, (_ESP & THREADINFO_MASK));
	if (ts_current == (PTR)NULL) goto error0;
	if (ts_current+ki.task.thread_group_offset != get_thread_group(env, ts_current)) {
		ts_first = ts_current = get_task_struct_next(env, ts_current);
	}

	ps = (OsiProcs *)g_malloc0(sizeof(OsiProcs));
	ps->proc = g_new(OsiProc, ps_capacity);
	do {
		if (ps->num == ps_capacity) {
			ps_capacity *= 2;
			ps->proc = g_renew(OsiProc, ps->proc, ps_capacity);
		}
		p = &ps->proc[ps->num++];
		memset(p, 0, sizeof(OsiProc));	// fill_osiproc() expects p to be zeroed-out.
		fill_osiproc(env, p, ts_current);

#ifdef OSI_LINUX_LIST_THREADS
		// Traverse thread group list.
		// It is assumed that ts_current is a thread group leader.
		tg_first = ts_current+ki.task.thread_group_offset;
		while ((tg_next = get_thread_group(env, ts_current)) != tg_first) {
			ts_current = tg_next-ki.task.thread_group_offset;
			if (ps->num == ps_capacity) {
				ps_capacity *= 2;
				ps->proc = g_renew(OsiProc, ps->proc, ps_capacity);
			}
			p = &ps->proc[ps->num++];
			memset(p, 0, sizeof(OsiProc)); // fill_osiproc() expects p to be zeroed-out.
			fill_osiproc(env, p, ts_current);
		}
		ts_current = tg_first-ki.task.thread_group_offset;
#endif

#if 0
		/*********************************************************/
		// Test of fd -> name resolution.
		/*********************************************************/
		for (int fdn=0; fdn<256; fdn++) {
			char *s = get_fd_name(env, ts_current, fdn);
			LOG_INFO("%s fd%d -> %s", p->name, fdn, s);
			g_free(s);
		}
		/*********************************************************/
#endif

		ts_current = get_task_struct_next(env, ts_current);
	} while(ts_current != (PTR)NULL && ts_current != ts_first);

	// memory read error
	if (ts_current == (PTR)NULL) goto error1;

	*out_ps = ps;
	return;

error1:
	do {
		ps->num--;
		g_free(ps->proc[ps->num].name);
	} while (ps->num != 0);
	g_free(ps->proc);
	g_free(ps);
error0:
	*out_ps = NULL;
	return;
}