update documentations

This commit is contained in:
criyle 2020-02-18 21:55:32 -05:00
parent 7be82acdf7
commit a4c78dcf5d
29 changed files with 183 additions and 54 deletions

View File

@ -1,5 +1,6 @@
// Package cgroup provices builder to create multiple different cgroup-v1 sub groups
// under systemd defined path (i.e. /sys/fs/cgroup)
// under systemd defined path (i.e. /sys/fs/cgroup).
//
// current avaliable cgroups are cpuacct, memory, pids
// not avaliable: cpu, cpuset, devices, freezer, net_cls, blkio, perf_event, net_prio, huge_tlb, rdma
package cgroup

View File

@ -1,3 +1,5 @@
// +build linux
package forkexec
import (

View File

@ -1,3 +1,5 @@
// +build linux
package forkexec
import (

7
pkg/forkexec/doc.go Normal file
View File

@ -0,0 +1,7 @@
// Package forkexec provides interface to run a subprocess with seccomp filter, rlimit and
// containerized or ptraced.
//
// unshare cgroup namespace requires kernel >= 4.6
// seccomp, unshare pid / user namespaces requires kernel >= 3.8
// pipe2, dup3 requires kernel >= 2.6.27
package forkexec

View File

@ -1,3 +1,5 @@
// +build linux
package forkexec
import (

View File

@ -1,3 +1,5 @@
// +build linux
package forkexec
import (

View File

@ -1,3 +1,5 @@
// +build linux
package forkexec
import (

View File

@ -1,5 +1,5 @@
// Package forkexec provides interface to run a subprocess with seccomp filter, rlimit and
// containerized or ptraced
// +build linux
package forkexec
import (

View File

@ -1,3 +1,5 @@
// +build linux
package forkexec
import (

View File

@ -1,9 +1,10 @@
// Package pipe provides a wrapper to create a pipe and
// read at most max content from the reader side
// collect at most max bytes from the reader side
package pipe
import (
"bytes"
"fmt"
"io"
"os"
)
@ -50,3 +51,7 @@ func NewBuffer(max int64) (*Buffer, error) {
Done: done,
}, nil
}
func (b Buffer) String() string {
return fmt.Sprintf("Buffer[%d/%d]", b.Buffer.Len(), b.Max)
}

View File

@ -1,7 +1,12 @@
// Package rlimit provides data structure for resource limits by setrlimit syscall on linux.
package rlimit
import (
"fmt"
"strings"
"syscall"
"github.com/criyle/go-sandbox/types"
)
// RLimits defines the rlimit applied by setrlimit syscall to traced process
@ -67,3 +72,34 @@ func (r *RLimits) PrepareRLimit() []RLimit {
}
return ret
}
func (r RLimit) String() string {
if r.Res == syscall.RLIMIT_CPU {
return fmt.Sprintf("CPU[%d s:%d s]", r.Rlim.Cur, r.Rlim.Max)
}
t := ""
switch r.Res {
case syscall.RLIMIT_DATA:
t = "Data"
case syscall.RLIMIT_FSIZE:
t = "File"
case syscall.RLIMIT_STACK:
t = "Stack"
case syscall.RLIMIT_AS:
t = "AddressSpace"
}
return fmt.Sprintf("%s[%v:%v]", t, types.Size(r.Rlim.Cur), types.Size(r.Rlim.Max))
}
func (r RLimits) String() string {
var sb strings.Builder
sb.WriteString("RLimits[")
for i, rl := range r.PrepareRLimit() {
if i > 0 {
sb.WriteByte(',')
}
sb.WriteString(rl.String())
}
sb.WriteString("]")
return sb.String()
}

View File

@ -1,22 +1,5 @@
// Package seccomp provides a generated filter format for seccomp filter
// +build linux
package seccomp
import (
"syscall"
"unsafe"
)
// Filter is the BPF seccomp filter value
type Filter []byte
// SockFprog converts Filter to SockFprog for seccomp syscall
func (f Filter) SockFprog() *syscall.SockFprog {
b := []byte(f)
return &syscall.SockFprog{
Len: uint16(len(b) / 8),
Filter: (*syscall.SockFilter)(unsafe.Pointer(&b[0])),
}
}

View File

@ -0,0 +1,15 @@
package seccomp
import (
"syscall"
"unsafe"
)
// SockFprog converts Filter to SockFprog for seccomp syscall
func (f Filter) SockFprog() *syscall.SockFprog {
b := []byte(f)
return &syscall.SockFprog{
Len: uint16(len(b) / 8),
Filter: (*syscall.SockFilter)(unsafe.Pointer(&b[0])),
}
}

View File

@ -1,3 +1,5 @@
// +build linux
package libseccomp
import (

View File

@ -1,4 +1,5 @@
// Package libseccomp provides wrapper to "github.com/seccomp/libseccomp-golang"
// +build linux
package libseccomp
import (

View File

@ -0,0 +1,2 @@
// Package libseccomp provides a wrapper for "github.com/seccomp/libseccomp-golang"
package libseccomp

View File

@ -1,3 +1,5 @@
// +build linux
package libseccomp
import (

View File

@ -1,6 +1,9 @@
// Package unixsocket provides wrapper for Linux unix socket to send and recv oob messages
// including fd and user credential.
package unixsocket
import (
"bytes"
"fmt"
"net"
"os"
@ -11,17 +14,15 @@ import (
// oob size default to page size
const oobSize = 4096
// use pool to avoid allocate
// use pool to minimize allocate gabage collector overhead
var oobPool = sync.Pool{
New: func() interface{} {
return make([]byte, oobSize)
},
}
// Socket represents a unix socket
type Socket struct {
*net.UnixConn
}
// Socket wrappers a unix socket connection
type Socket net.UnixConn
// Msg is the oob msg with the message
type Msg struct {
@ -37,46 +38,51 @@ type Msg struct {
func NewSocket(fd int) (*Socket, error) {
file := os.NewFile(uintptr(fd), "unix-socket")
if file == nil {
return nil, fmt.Errorf("NewSocket: fd(%d) is not a valid fd", fd)
return nil, fmt.Errorf("NewSocket: %d is not a valid fd", fd)
}
defer file.Close()
syscall.CloseOnExec(int(file.Fd()))
conn, err := net.FileConn(file)
if err != nil {
return nil, err
}
unixConn, ok := conn.(*net.UnixConn)
if !ok {
conn.Close()
return nil, fmt.Errorf("NewSocket: fd(%d) is not a unix socket", fd)
return nil, fmt.Errorf("NewSocket: %d is not a valid unix socket connection", fd)
}
return &Socket{unixConn}, nil
return (*Socket)(unixConn), nil
}
// NewSocketPair creates connected unix socketpair using SOCK_SEQPACKET
func NewSocketPair() (*Socket, *Socket, error) {
fd, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return nil, nil, fmt.Errorf("NewSocketPair: failed to call socketpair(%v)", err)
return nil, nil, fmt.Errorf("NewSocketPair: failed to call socketpair %w", err)
}
ins, err := NewSocket(fd[0])
if err != nil {
syscall.Close(fd[0])
syscall.Close(fd[1])
return nil, nil, fmt.Errorf("NewSocketPair: failed to call NewSocket ins(%v)", err)
return nil, nil, fmt.Errorf("NewSocketPair: failed to call NewSocket on sender %w", err)
}
outs, err := NewSocket(fd[1])
if err != nil {
ins.Close()
syscall.Close(fd[1])
return nil, nil, fmt.Errorf("NewSocketPair: failed to call NewSocket outs(%v)", err)
return nil, nil, fmt.Errorf("NewSocketPair: failed to call NewSocket receiver %w", err)
}
return ins, outs, nil
}
// SetPassCred set sockopt for pass cred for unix socket
func (s *Socket) SetPassCred(option int) error {
sysconn, err := s.SyscallConn()
sysconn, err := (*net.UnixConn)(s).SyscallConn()
if err != nil {
return err
}
@ -87,16 +93,20 @@ func (s *Socket) SetPassCred(option int) error {
// SendMsg sendmsg to unix socket and encode possible unix right / credential
func (s *Socket) SendMsg(b []byte, m *Msg) error {
var oob []byte
buf := oobPool.Get().([]byte)
defer oobPool.Put(buf)
oob := bytes.NewBuffer(buf[:0])
if m != nil {
if len(m.Fds) > 0 {
oob = append(oob, syscall.UnixRights(m.Fds...)...)
oob.Write(syscall.UnixRights(m.Fds...))
}
if m.Cred != nil {
oob = append(oob, syscall.UnixCredentials(m.Cred)...)
oob.Write(syscall.UnixCredentials(m.Cred))
}
}
_, _, err := s.WriteMsgUnix(b, oob, nil)
_, _, err := (*net.UnixConn)(s).WriteMsgUnix(b, oob.Bytes(), nil)
if err != nil {
return err
}
@ -107,7 +117,8 @@ func (s *Socket) SendMsg(b []byte, m *Msg) error {
func (s *Socket) RecvMsg(b []byte) (int, *Msg, error) {
oob := oobPool.Get().([]byte)
defer oobPool.Put(oob)
n, oobn, _, _, err := s.ReadMsgUnix(b, oob)
n, oobn, _, _, err := (*net.UnixConn)(s).ReadMsgUnix(b, oob)
if err != nil {
return 0, nil, err
}
@ -126,23 +137,24 @@ func (s *Socket) RecvMsg(b []byte) (int, *Msg, error) {
func parseMsg(msgs []syscall.SocketControlMessage) (*Msg, error) {
var msg Msg
for _, m := range msgs {
if m.Header.Level == syscall.SOL_SOCKET {
switch m.Header.Type {
case syscall.SCM_CREDENTIALS:
cred, err := syscall.ParseUnixCredentials(&m)
if err != nil {
return nil, err
}
msg.Cred = cred
case syscall.SCM_RIGHTS:
fds, err := syscall.ParseUnixRights(&m)
if err != nil {
return nil, err
}
msg.Fds = fds
if m.Header.Level != syscall.SOL_SOCKET {
continue
}
switch m.Header.Type {
case syscall.SCM_CREDENTIALS:
cred, err := syscall.ParseUnixCredentials(&m)
if err != nil {
return nil, err
}
msg.Cred = cred
case syscall.SCM_RIGHTS:
fds, err := syscall.ParseUnixRights(&m)
if err != nil {
return nil, err
}
msg.Fds = fds
}
}
return &msg, nil

44
ptracer/context_other.go Normal file
View File

@ -0,0 +1,44 @@
// +build !linux
package ptracer
// Context empty structure filler for other OS
type Context struct {
Pid int
}
func (c *Context) SyscallNo() uint {
return 0
}
func (c *Context) Arg0() uint {
return 0
}
func (c *Context) Arg1() uint {
return 0
}
func (c *Context) Arg2() uint {
return 0
}
func (c *Context) Arg3() uint {
return 0
}
func (c *Context) Arg4() uint {
return 0
}
func (c *Context) Arg5() uint {
return 0
}
func (c *Context) SetReturnValue(retval int) {
}
func (c *Context) GetString(addr uintptr) string {
return ""
}

3
ptracer/doc.go Normal file
View File

@ -0,0 +1,3 @@
// Package ptracer provides platfirm independent ptrace pooling loop
// interface to trace program syscalls on Linux.
package ptracer

View File

@ -1,3 +1,5 @@
// +build linux
package unshare
import (

View File

@ -1,3 +1,5 @@
// +build linux
package unshare
import (