Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/hooks/syscalls_hc.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ static inline void fill_handler(struct syscall_event *args, int argc, const unsi
}

args->task = current;
// Denormalize identity so host-side hooks (e.g. process-tree exit tracking)
// can attribute the event without a separate OSI_PROC portal round-trip.
args->pid = task_pid_nr(current);
args->create_time = current->start_time;
args->retval = 0; // Initialize to 0, will be set by hypercall

regs = task_pt_regs(current);
Expand Down
5 changes: 5 additions & 0 deletions src/hooks/syscalls_hc.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ struct syscall_event {
struct task_struct *task; /* Task pointer */
struct pt_regs *regs; /* Pointer to current registers */
long retval; /* Return value */
uint64_t pid; /* current->pid, denormalized so the host
* can identify the task without a
* separate OSI_PROC round-trip */
uint64_t create_time; /* current->start_time (process identity,
* stable across execve) */
u32 argc; /* Number of arguments */
bool skip_syscall; /* Flag to skip syscall execution */
char syscall_name[SYSCALL_NAME_MAX_LEN]; /* Name of syscall (embedded in structure) */
Expand Down
1 change: 1 addition & 0 deletions src/portal/portal_op_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
X(exec, EXEC) \
X(osi_proc, OSI_PROC) \
X(osi_proc_handles, OSI_PROC_HANDLES) \
X(osi_proc_all, OSI_PROC_ALL) \
X(osi_mappings, OSI_MAPPINGS) \
X(osi_proc_mem, OSI_PROC_MEM) \
X(osi_proc_exe, OSI_PROC_EXE) \
Expand Down
93 changes: 93 additions & 0 deletions src/portal/portal_osi.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,99 @@ void handle_op_osi_proc_handles(portal_region *mem_region)
mem_region->header.op = (HYPER_RESP_READ_OK);
}

/*
* handle_op_osi_proc_all: kernel-side whole-process-tree walk.
*
* Returns a slim osi_proc_node (pid, ppid, create_time, ids, inline comm) for
* every user process in a single RCU-consistent pass, instead of the host
* issuing one HYPER_OP_OSI_PROC per pid. This turns a tree snapshot from 1+N
* portal round-trips into ceil(N / nodes-per-page) and, because the walk holds
* rcu_read_lock() throughout, yields a single coherent snapshot with no
* host-side tear between per-pid reads.
*
* Response layout: [osi_result_header][osi_proc_node * result_count].
* Records are fixed-size with comm inlined (no string pool), so ~72 fit a page.
*
* Pagination: mem_region->header.addr carries the number of user processes the
* host has already consumed (skip); total_count is the true count so the host
* knows when to stop. comm comes from task->comm (kernel memory) only -- like
* HYPER_OP_OSI_PROC this never touches userspace, so it is safe against
* exiting/mm-less contexts. Kernel threads (!mm) are skipped (that is slice 2).
*/
void handle_op_osi_proc_all(portal_region *mem_region)
{
struct task_struct *task;
int count = 0; /* nodes filled into this page */
int total_count = 0; /* all user procs (for host pagination) */
int skip = 0; /* procs already consumed by the host */
size_t max_nodes;
char *data_buf = PORTAL_DATA(mem_region);
struct osi_result_header *header = (struct osi_result_header *)data_buf;
struct osi_proc_node *node_arr;

skip = (int)(mem_region->header.addr);
if (skip < 0) {
skip = 0;
}

igloo_debug_osi("igloo: Handling HYPER_OP_OSI_PROC_ALL skip=%d\n", skip);

max_nodes = (CHUNK_SIZE - sizeof(struct osi_result_header)) /
sizeof(struct osi_proc_node);
if (max_nodes == 0) {
max_nodes = 1;
}

header->result_count = 0;
header->total_count = 0;
node_arr = (struct osi_proc_node *)(data_buf + sizeof(struct osi_result_header));

rcu_read_lock();
for_each_process(task) {
struct mm_struct *mm = task->mm;
struct osi_proc_node *node;
size_t name_len;
int ord;

if (!mm) {
continue; /* user processes only; kthreads are slice 2 */
}

ord = total_count; /* 0-based ordinal among user procs */
total_count++;

if (ord < skip || (size_t)count >= max_nodes) {
continue; /* already delivered, or this page is full */
}

node = &node_arr[count];
node->pid = (task->pid);
node->ppid = (task->real_parent ? task->real_parent->pid : 0);
node->create_time = (task->start_time);
node->uid = (task->cred->uid.val);
node->gid = (task->cred->gid.val);
node->euid = (task->cred->euid.val);
node->egid = (task->cred->egid.val);

name_len = strnlen(task->comm, sizeof(node->comm) - 1);
memcpy(node->comm, task->comm, name_len);
node->comm[name_len] = '\0';

count++;
}
rcu_read_unlock();

header->result_count = (count);
header->total_count = (total_count);

igloo_debug_osi("igloo: OSI_PROC_ALL returning %d procs (skip=%d total=%d)\n",
count, skip, total_count);

mem_region->header.size = (sizeof(struct osi_result_header) +
(count * sizeof(struct osi_proc_node)));
mem_region->header.op = (HYPER_RESP_READ_OK);
}

void handle_op_osi_proc_exe(portal_region *mem_region)
{
struct task_struct *task;
Expand Down
19 changes: 19 additions & 0 deletions src/portal/portal_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,25 @@ struct osi_proc {
uint64_t start_time;
};

/*
* Slim per-process record for the bulk process-tree walk
* (handle_op_osi_proc_all). Purpose-built for slice-1 tree()/get(): identity
* + genealogy + ids only, with comm inlined (no string pool) so records are
* fixed-size and densely packed (~72 per page vs ~18 for full osi_proc).
* TASK_COMM_LEN is 16; keep the field literal so the host ABI is stable
* regardless of the guest kernel's TASK_COMM_LEN.
*/
struct osi_proc_node {
uint64_t pid;
uint64_t ppid;
uint64_t create_time; // task->start_time; stable across execve (identity)
uint32_t uid;
uint32_t gid;
uint32_t euid;
uint32_t egid;
char comm[16]; // NUL-padded task->comm (truncated to 15 + NUL)
};

// File descriptor entry structure for handle_op_read_fds
struct osi_fd_entry {
uint64_t fd; // File descriptor number
Expand Down
Loading