func (ctx *context) solverWorker() { conn := ctx.pool.Get() defer conn.Close() for r := range ctx.solverch { var arg string if r.IsIR { arg = "-action=ir" } else { arg = "-action=inst" } cmd := exec.Command(os.Args[0]+"-backend", arg, os.Args[1]) cmd.Stdin = strings.NewReader(r.Req) var outb, errb bytes.Buffer cmd.Stdout = &outb cmd.Stderr = &errb var sys syscall.SysProcAttr sys.Setpgid = true cmd.SysProcAttr = &sys err := cmd.Start() if err != nil { os.Stdout.Write([]byte("Error invoking solver: " + err.Error() + "\n")) r.result <- solverResp{"", friendlyError{"Error invoking solver", err}} continue } timeout := false timer := time.AfterFunc(10*time.Second, func() { syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) timeout = true }) err = cmd.Wait() timer.Stop() if timeout { os.Stdout.Write([]byte("Solver timeout\n")) r.result <- solverResp{"", friendlyError{"Solver timeout", nil}} } else if err != nil { r.result <- solverResp{"", friendlyError{"Error invoking solver", err}} } else if errb.Len() != 0 { r.result <- solverResp{"", friendlyError{errb.String(), nil}} } else { r.result <- solverResp{outb.String(), nil} } } }
func (su *Supervise) Spawn() { var args = make([]string, 3) args[0] = "/bin/bash" args[1] = "-c" args[2] = su.cmd var sysProcAttr = syscall.SysProcAttr{} sysProcAttr.Setsid = true var procAttr = syscall.ProcAttr{ su.cwd, os.Environ(), nil, &sysProcAttr, } var pid, _ = syscall.ForkExec("/bin/bash", args, &procAttr) su.pid = pid su.FlushStatus() su.WriteLog("child %d started", su.pid) }
// Converts IDMap to SysProcIDMap array and adds it to SysProcAttr. func (c *linuxContainer) addUidGidMappings(sys *syscall.SysProcAttr) error { if c.config.UidMappings != nil { sys.UidMappings = make([]syscall.SysProcIDMap, len(c.config.UidMappings)) for i, um := range c.config.UidMappings { sys.UidMappings[i].ContainerID = um.ContainerID sys.UidMappings[i].HostID = um.HostID sys.UidMappings[i].Size = um.Size } } if c.config.GidMappings != nil { sys.GidMappings = make([]syscall.SysProcIDMap, len(c.config.GidMappings)) for i, gm := range c.config.GidMappings { sys.GidMappings[i].ContainerID = gm.ContainerID sys.GidMappings[i].HostID = gm.HostID sys.GidMappings[i].Size = gm.Size } } return nil }
// Converts IDMap to SysProcIDMap array and adds it to SysProcAttr. func AddUidGidMappings(sys *syscall.SysProcAttr, container *libcontainer.Config) { if container.UidMappings != nil { sys.UidMappings = make([]syscall.SysProcIDMap, len(container.UidMappings)) for i, um := range container.UidMappings { sys.UidMappings[i].ContainerID = um.ContainerID sys.UidMappings[i].HostID = um.HostID sys.UidMappings[i].Size = um.Size } } if container.GidMappings != nil { sys.GidMappings = make([]syscall.SysProcIDMap, len(container.GidMappings)) for i, gm := range container.GidMappings { sys.GidMappings[i].ContainerID = gm.ContainerID sys.GidMappings[i].HostID = gm.HostID sys.GidMappings[i].Size = gm.Size } } }
func Tracer() { p := new(oz.Profile) if err := json.NewDecoder(os.Stdin).Decode(&p); err != nil { log.Error("unable to decode profile data: %v", err) os.Exit(1) } var proc_attr syscall.ProcAttr var sys_attr syscall.SysProcAttr sys_attr.Ptrace = true done := false proc_attr.Sys = &sys_attr cmd := os.Args[1] cmdArgs := os.Args[2:] log.Info("Tracer running command (%v) arguments (%v)\n", cmd, cmdArgs) c := exec.Command(cmd) c.SysProcAttr = &syscall.SysProcAttr{Ptrace: true} c.Env = os.Environ() c.Args = append(c.Args, cmdArgs...) pi, err := c.StdinPipe() if err != nil { fmt.Errorf("error creating stdin pipe for tracer process: %v", err) os.Exit(1) } jdata, err := json.Marshal(p) if err != nil { fmt.Errorf("Unable to marshal seccomp state: %+v", err) os.Exit(1) } io.Copy(pi, bytes.NewBuffer(jdata)) log.Info(string(jdata)) pi.Close() children := make(map[int]bool) if err := c.Start(); err == nil { children[c.Process.Pid] = true var s syscall.WaitStatus pid, err := syscall.Wait4(-1, &s, syscall.WALL, nil) children[pid] = true if err != nil { log.Error("Error (wait4): %v", err) } log.Info("Tracing child pid: %v\n", pid) for done == false { syscall.PtraceSetOptions(pid, unix.PTRACE_O_TRACESECCOMP|unix.PTRACE_O_TRACEFORK|unix.PTRACE_O_TRACEVFORK|unix.PTRACE_O_TRACECLONE|unix.PTRACE_O_TRACEEXIT) syscall.PtraceCont(pid, 0) pid, err = syscall.Wait4(-1, &s, syscall.WALL, nil) if err != nil { log.Error("Error (wait4): %v\n", err) if len(children) == 0 { done = true } continue } children[pid] = true if s.Exited() == true { delete(children, pid) log.Info("Child pid %v finished.\n", pid) if len(children) == 0 { done = true } continue } if uint32(s)>>8 == (uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_SECCOMP << 8)) { if err != nil { log.Error("Error (ptrace): %v", err) continue } var regs syscall.PtraceRegs err = syscall.PtraceGetRegs(pid, ®s) if err != nil { log.Error("Error (ptrace): %v", err) } systemcall, err := syscallByNum(int(regs.Orig_rax)) if err != nil { log.Error("Error: %v", err) continue } var callrep string = fmt.Sprintf("%s(", systemcall.name) var reg uint64 = 0 for arg := range systemcall.args { if systemcall.args[arg] == 0 { break } if arg > 0 { callrep += fmt.Sprintf(",") } switch arg { case 0: reg = regs.Rdi case 1: reg = regs.Rsi case 2: reg = regs.Rdx case 3: reg = regs.Rcx case 4: reg = regs.R8 case 5: reg = regs.R9 } if systemcall.args[arg] == STRINGARG { str, err := readStringArg(pid, uintptr(reg)) if err != nil { log.Error("Error: %v", err) } else { callrep += fmt.Sprintf("\"%s\"", str) } } else if systemcall.args[arg] == INTARG { callrep += fmt.Sprintf("%d", uint64(reg)) } else { /* Stringify pointers in writes to stdout/stderr */ write, err := syscallByName("write") if err != nil { log.Error("Error: %v", err) } if systemcall.num == write.num && (regs.Rdi == uint64(syscall.Stdout) || regs.Rdi == uint64(syscall.Stderr)) { str, err := readStringArg(pid, uintptr(reg)) if err != nil { log.Error("Error %v", err) } else { if isPrintableASCII(str) == true { callrep += fmt.Sprintf("\"%s\"", str) } else { callrep += fmt.Sprintf("0x%X", uintptr(reg)) } } } else { callrep += fmt.Sprintf("0x%X", uintptr(reg)) } } } callrep += ")" log.Info("==============================================\nseccomp hit on sandbox pid %v (%v) syscall %v (%v): \n\n%s\nI ==============================================\n\n", pid, getProcessCmdLine(pid), systemcall.name, regs.Orig_rax, callrep) } } } else { log.Error("Error: %v", err) } }
// Set the GidMappingsEnableSetgroups member to true, so the process's // setgroups proc entry wont be set to 'deny' if GidMappings are set func enableSetgroups(sys *syscall.SysProcAttr) { sys.GidMappingsEnableSetgroups = true }
func Tracer() { p := new(oz.Profile) if err := json.NewDecoder(os.Stdin).Decode(&p); err != nil { log.Error("unable to decode profile data: %v", err) os.Exit(1) } var proc_attr syscall.ProcAttr var sys_attr syscall.SysProcAttr sys_attr.Ptrace = true done := false proc_attr.Sys = &sys_attr cmd := os.Args[1] cmdArgs := os.Args[2:] log.Info("Tracer running command (%v) arguments (%v)\n", cmd, cmdArgs) c := exec.Command(cmd) c.SysProcAttr = &syscall.SysProcAttr{Ptrace: true} c.Env = os.Environ() c.Args = append(c.Args, cmdArgs...) pi, err := c.StdinPipe() if err != nil { fmt.Errorf("error creating stdin pipe for tracer process: %v", err) os.Exit(1) } jdata, err := json.Marshal(p) if err != nil { fmt.Errorf("Unable to marshal seccomp state: %+v", err) os.Exit(1) } io.Copy(pi, bytes.NewBuffer(jdata)) log.Info(string(jdata)) pi.Close() children := make(map[int]bool) renderFunctions := getRenderingFunctions() if err := c.Start(); err == nil { children[c.Process.Pid] = true var s syscall.WaitStatus pid, err := syscall.Wait4(-1, &s, syscall.WALL, nil) children[pid] = true if err != nil { log.Error("Error (wait4) here first: %v %i", err, pid) } log.Info("Tracing child pid: %v\n", pid) for done == false { syscall.PtraceSetOptions(pid, unix.PTRACE_O_TRACESECCOMP|unix.PTRACE_O_TRACEFORK|unix.PTRACE_O_TRACEVFORK|unix.PTRACE_O_TRACECLONE) syscall.PtraceCont(pid, 0) pid, err = syscall.Wait4(-1, &s, syscall.WALL, nil) if err != nil { log.Error("Error (wait4) here: %v %i %v\n", err, pid, children) if len(children) == 0 { done = true } continue } children[pid] = true if s.Exited() == true { delete(children, pid) log.Info("Child pid %v finished.\n", pid) if len(children) == 0 { done = true } continue } if s.Signaled() == true { log.Error("Other pid signalled %v %v", pid, s) delete(children, pid) continue } switch uint32(s) >> 8 { case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_SECCOMP << 8): if err != nil { log.Error("Error (ptrace): %v", err) continue } var regs syscall.PtraceRegs err = syscall.PtraceGetRegs(pid, ®s) if err != nil { log.Error("Error (ptrace): %v", err) } systemcall, err := syscallByNum(getSyscallNumber(regs)) if err != nil { log.Error("Error: %v", err) continue } /* Render the system call invocation */ r := getSyscallRegisterArgs(regs) call := "" if f, ok := renderFunctions[getSyscallNumber(regs)]; ok { call, err = f(pid, r) if err != nil { log.Info("%v", err) continue } } else { call = renderSyscallBasic(pid, systemcall, regs) } log.Info("==============================================\nseccomp hit on sandbox pid %v (%v) syscall %v (%v):\n\n%s\nI ==============================================\n\n", pid, getProcessCmdLine(pid), systemcall.name, systemcall.num, call) continue case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_EXIT << 8): log.Error("Ptrace exit event detected pid %v (%s)", pid, getProcessCmdLine(pid)) case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_CLONE << 8): log.Error("Ptrace clone event detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_FORK << 8): log.Error("PTrace fork event detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_VFORK << 8): log.Error("Ptrace vfork event detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_VFORK_DONE << 8): log.Error("Ptrace vfork done event detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_EXEC << 8): log.Error("Ptrace exec event detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGTRAP) | (unix.PTRACE_EVENT_STOP << 8): log.Error("Ptrace stop event detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGTRAP): log.Error("SIGTRAP detected in pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGCHLD): log.Error("SIGCHLD detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue case uint32(unix.SIGSTOP): log.Error("SIGSTOP detected pid %v (%s)", pid, getProcessCmdLine(pid)) continue default: y := s.StopSignal() log.Error("Child stopped for unknown reasons pid %v status %v signal %i (%s)", pid, s, y, getProcessCmdLine(pid)) continue } } } }
func prepareSysProcAttr(attr *syscall.SysProcAttr) { attr.Pdeathsig = syscall.SIGQUIT // Send SIGQUIT to children if parent exits }