Files
go-proot/tracee.go
Matheus Sampaio Queiroga f941c61928 Update structs
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>

Update structs

Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
2025-03-27 18:31:12 -03:00

206 lines
5.9 KiB
Go

package proot
import "golang.org/x/sys/unix"
const HostRootfs string = "/host-rootfs"
// extern Tracee *get_tracee(const Tracee *tracee, pid_t pid, bool create);
// extern Tracee *get_ptracee(const Tracee *ptracer, pid_t pid, bool only_stopped, bool only_with_pevent, word_t wait_options);
// extern Tracee *get_stopped_ptracee(const Tracee *ptracer, pid_t pid, bool only_with_pevent, word_t wait_options);
// extern bool has_ptracees(const Tracee *ptracer, pid_t pid, word_t wait_options);
// extern int new_child(Tracee *parent, word_t clone_flags);
// extern Tracee *new_dummy_tracee(TALLOC_CTX *context);
// extern void terminate_tracee(Tracee *tracee);
// extern void free_terminated_tracees();
// extern int swap_config(Tracee *tracee1, Tracee *tracee2);
// extern void kill_all_tracees();
type Tracee struct {
Link []*Tracee // Link for the list of all tracees.
PID int // Process identifier.
Vpid int // Unique tracee identifier.
Running bool // Is it currently running or not?
Terminated bool // Is this tracee ready to be freed? TODO: move to a list dedicated to terminated tracees instead.
KillallOnExit bool // Whether termination of this tracee implies an immediate kill of all tracees.
Parent *Tracee // Parent of this tracee, NULL if none.
Clone bool // Is it a "clone", i.e has the same parent as its creator.
// Support for ptrace emulation (tracer side).
AsPtracer struct {
nb_ptracees int
Zombies []*Tracee
WaitPid, WaitOptions int
// DOESNT_WAIT = 0,
// WAITS_IN_KERNEL = 1,
// WAITS_IN_PROOT = 2,
WaitsIN int
}
// Support for ptrace emulation (tracee side).
AsPtracee struct {
Ptrace *Tracee
Event4 struct {
Proot, Ptracer struct {
Value int
Pending bool
}
}
TracingStarted bool
IgnoreLoaderSyscalls bool
IgnoreSyscalls bool
OPtions int
IsZombie bool
}
/* Current status:
0: enter syscall
1: exit syscall no error
-errno: exit syscall with error. */
Status int
// How this tracee is restarted.
RestartHow int
// enum {
// SIGSTOP_IGNORED = 0, /* Ignore SIGSTOP (once the parent is known). */
// SIGSTOP_ALLOWED, /* Allow SIGSTOP (once the parent is known). */
// SIGSTOP_PENDING, /* Block SIGSTOP until the parent is unknown. */
// } sigstop;
Sigstop int
// Specify the type of the final component during the initialization of a binding. This variable is first defined in bind_path() then used in build_glue().
GlueType int
// Disable mixed-execution (native host) check.
MixedMode bool
// State of the seccomp acceleration for this tracee.
// enum { DISABLED = 0, DISABLING = 1, ENABLED = 2 } seccomp;
Seccomp int
Regs unix.PtraceRegs
// Ensure the sysexit stage is always hit under seccomp.
SysexitPending bool
// Path to the executable, à la /proc/self/exe.
Exe, NewExe string
// Runner command-line.
Qemu []string
// Path to glue between the guest rootfs and the host rootfs.
Glue string
/* For the mixed-mode, the guest LD_LIBRARY_PATH is saved
* during the "guest -> host" transition, in order to be
* restored during the "host -> guest" transition (only if the
* host LD_LIBRARY_PATH hasn't changed). */
HostLdsoPaths string
GuestLdsoPaths string
}
func (tracee *Tracee) GetTracee(pid int, create bool, nextVpid func() int) *Tracee {
if tracee != nil && tracee.PID == pid {
return tracee
}
for _, treacee := range tracee.Link {
if treacee.PID == pid {
return treacee
}
}
if create && nextVpid != nil {
newTracee := &Tracee{
PID: pid,
Vpid: nextVpid(),
Link: []*Tracee{},
Parent: tracee,
}
tracee.Link = append(tracee.Link, newTracee)
return newTracee
}
return nil
}
func (ptracee *Tracee) GetPtracee(pid int, onlyStopped, onlyWithPevent bool, waitOption int) *Tracee {
for _, zombie := range ptracee.AsPtracer.Zombies {
for _, ptracee := range zombie.Link {
if pid != ptracee.PID && pid != -1 {
continue
}
// #define EXPECTED_WAIT_CLONE(wait_options,tracee) ((((wait_options) & __WALL) != 0) || ((((wait_options) & __WCLONE) != 0) && (tracee)->clone) || ((((wait_options) & __WCLONE) == 0) && !(tracee)->clone))
if !ptracee.Clone {
continue
}
return ptracee
}
}
for _, ptracee := range ptracee.Link {
if ptracee.AsPtracee.Ptrace == nil || ptracee.PID != pid && pid != -1 {
continue
}
// #define EXPECTED_WAIT_CLONE(wait_options,tracee) ((((wait_options) & __WALL) != 0) || ((((wait_options) & __WCLONE) != 0) && (tracee)->clone) || ((((wait_options) & __WCLONE) == 0) && !(tracee)->clone))
if !ptracee.Clone {
continue
}
if !onlyStopped {
return ptracee
}
if ptracee.Running {
continue
}
if ptracee.AsPtracee.Event4.Ptracer.Pending || !onlyWithPevent {
return ptracee
}
if ptracee.PID == pid {
return nil
}
}
return nil
}
func (ptracee *Tracee) GetStoppedPtracee(pid int, onlyWithPevent bool, waitOptions int) *Tracee {
return ptracee.GetPtracee(pid, true, onlyWithPevent, waitOptions)
}
func (ptracee *Tracee) HasPtracee(pid, waitOptions int) bool {
return ptracee.GetPtracee(pid, false, false, waitOptions) != nil
}
func (tracee *Tracee) FreeTerminatedTracees() {
for index, tracee := range tracee.Link {
if tracee.Terminated {
tracee.Link = append(tracee.Link[:index], tracee.Link[min(len(tracee.Link)-1, index+1):]...)
}
}
}
func (tracee *Tracee) TerminateTracee() {
tracee.Terminated = true
if tracee.KillallOnExit {
unix.Kill(tracee.PID, unix.SIGKILL)
for _, pid := range tracee.Link {
unix.Kill(pid.PID, unix.SIGKILL)
}
}
}
func (parent *Tracee) NewChild(cloneFlags int) error {
if err := parent.fetchRegs(); err == nil {
// if (status >= 0 && get_sysnum(parent, CURRENT) == PR_clone)
// clone_flags = peek_reg(parent, CURRENT, SYSARG_1);
// else if (status >= 0 && get_sysnum(parent, CURRENT) == PR_clone3)
// clone_flags = peek_word(parent, peek_reg(parent, CURRENT, SYSARG_1));
}
return nil
}