mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
update documentations
This commit is contained in:
parent
7be82acdf7
commit
a4c78dcf5d
@ -1,5 +1,6 @@
|
|||||||
// Package cgroup provices builder to create multiple different cgroup-v1 sub groups
|
// 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
|
// current avaliable cgroups are cpuacct, memory, pids
|
||||||
// not avaliable: cpu, cpuset, devices, freezer, net_cls, blkio, perf_event, net_prio, huge_tlb, rdma
|
// not avaliable: cpu, cpuset, devices, freezer, net_cls, blkio, perf_event, net_prio, huge_tlb, rdma
|
||||||
package cgroup
|
package cgroup
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package forkexec
|
package forkexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package forkexec
|
package forkexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
7
pkg/forkexec/doc.go
Normal file
7
pkg/forkexec/doc.go
Normal 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
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package forkexec
|
package forkexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package forkexec
|
package forkexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package forkexec
|
package forkexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// Package forkexec provides interface to run a subprocess with seccomp filter, rlimit and
|
// +build linux
|
||||||
// containerized or ptraced
|
|
||||||
package forkexec
|
package forkexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package forkexec
|
package forkexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
// Package pipe provides a wrapper to create a pipe and
|
// 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
|
package pipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
@ -50,3 +51,7 @@ func NewBuffer(max int64) (*Buffer, error) {
|
|||||||
Done: done,
|
Done: done,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b Buffer) String() string {
|
||||||
|
return fmt.Sprintf("Buffer[%d/%d]", b.Buffer.Len(), b.Max)
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
|
// Package rlimit provides data structure for resource limits by setrlimit syscall on linux.
|
||||||
package rlimit
|
package rlimit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/criyle/go-sandbox/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RLimits defines the rlimit applied by setrlimit syscall to traced process
|
// RLimits defines the rlimit applied by setrlimit syscall to traced process
|
||||||
@ -67,3 +72,34 @@ func (r *RLimits) PrepareRLimit() []RLimit {
|
|||||||
}
|
}
|
||||||
return ret
|
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()
|
||||||
|
}
|
||||||
|
|||||||
@ -1,22 +1,5 @@
|
|||||||
// Package seccomp provides a generated filter format for seccomp filter
|
// Package seccomp provides a generated filter format for seccomp filter
|
||||||
|
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package seccomp
|
package seccomp
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Filter is the BPF seccomp filter value
|
// Filter is the BPF seccomp filter value
|
||||||
type Filter []byte
|
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])),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
15
pkg/seccomp/filter_linux.go
Normal file
15
pkg/seccomp/filter_linux.go
Normal 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])),
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package libseccomp
|
package libseccomp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
// Package libseccomp provides wrapper to "github.com/seccomp/libseccomp-golang"
|
// +build linux
|
||||||
|
|
||||||
package libseccomp
|
package libseccomp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
2
pkg/seccomp/libseccomp/doc.go
Normal file
2
pkg/seccomp/libseccomp/doc.go
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package libseccomp provides a wrapper for "github.com/seccomp/libseccomp-golang"
|
||||||
|
package libseccomp
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package libseccomp
|
package libseccomp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -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
|
package unixsocket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@ -11,17 +14,15 @@ import (
|
|||||||
// oob size default to page size
|
// oob size default to page size
|
||||||
const oobSize = 4096
|
const oobSize = 4096
|
||||||
|
|
||||||
// use pool to avoid allocate
|
// use pool to minimize allocate gabage collector overhead
|
||||||
var oobPool = sync.Pool{
|
var oobPool = sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return make([]byte, oobSize)
|
return make([]byte, oobSize)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Socket represents a unix socket
|
// Socket wrappers a unix socket connection
|
||||||
type Socket struct {
|
type Socket net.UnixConn
|
||||||
*net.UnixConn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Msg is the oob msg with the message
|
// Msg is the oob msg with the message
|
||||||
type Msg struct {
|
type Msg struct {
|
||||||
@ -37,46 +38,51 @@ type Msg struct {
|
|||||||
func NewSocket(fd int) (*Socket, error) {
|
func NewSocket(fd int) (*Socket, error) {
|
||||||
file := os.NewFile(uintptr(fd), "unix-socket")
|
file := os.NewFile(uintptr(fd), "unix-socket")
|
||||||
if file == nil {
|
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()
|
defer file.Close()
|
||||||
syscall.CloseOnExec(int(file.Fd()))
|
syscall.CloseOnExec(int(file.Fd()))
|
||||||
|
|
||||||
conn, err := net.FileConn(file)
|
conn, err := net.FileConn(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
unixConn, ok := conn.(*net.UnixConn)
|
unixConn, ok := conn.(*net.UnixConn)
|
||||||
if !ok {
|
if !ok {
|
||||||
conn.Close()
|
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
|
// NewSocketPair creates connected unix socketpair using SOCK_SEQPACKET
|
||||||
func NewSocketPair() (*Socket, *Socket, error) {
|
func NewSocketPair() (*Socket, *Socket, error) {
|
||||||
fd, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0)
|
fd, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0)
|
||||||
if err != nil {
|
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])
|
ins, err := NewSocket(fd[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syscall.Close(fd[0])
|
syscall.Close(fd[0])
|
||||||
syscall.Close(fd[1])
|
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])
|
outs, err := NewSocket(fd[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ins.Close()
|
ins.Close()
|
||||||
syscall.Close(fd[1])
|
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
|
return ins, outs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPassCred set sockopt for pass cred for unix socket
|
// SetPassCred set sockopt for pass cred for unix socket
|
||||||
func (s *Socket) SetPassCred(option int) error {
|
func (s *Socket) SetPassCred(option int) error {
|
||||||
sysconn, err := s.SyscallConn()
|
sysconn, err := (*net.UnixConn)(s).SyscallConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -87,16 +93,20 @@ func (s *Socket) SetPassCred(option int) error {
|
|||||||
|
|
||||||
// SendMsg sendmsg to unix socket and encode possible unix right / credential
|
// SendMsg sendmsg to unix socket and encode possible unix right / credential
|
||||||
func (s *Socket) SendMsg(b []byte, m *Msg) error {
|
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 m != nil {
|
||||||
if len(m.Fds) > 0 {
|
if len(m.Fds) > 0 {
|
||||||
oob = append(oob, syscall.UnixRights(m.Fds...)...)
|
oob.Write(syscall.UnixRights(m.Fds...))
|
||||||
}
|
}
|
||||||
if m.Cred != nil {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -107,7 +117,8 @@ func (s *Socket) SendMsg(b []byte, m *Msg) error {
|
|||||||
func (s *Socket) RecvMsg(b []byte) (int, *Msg, error) {
|
func (s *Socket) RecvMsg(b []byte) (int, *Msg, error) {
|
||||||
oob := oobPool.Get().([]byte)
|
oob := oobPool.Get().([]byte)
|
||||||
defer oobPool.Put(oob)
|
defer oobPool.Put(oob)
|
||||||
n, oobn, _, _, err := s.ReadMsgUnix(b, oob)
|
|
||||||
|
n, oobn, _, _, err := (*net.UnixConn)(s).ReadMsgUnix(b, oob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
@ -126,23 +137,24 @@ func (s *Socket) RecvMsg(b []byte) (int, *Msg, error) {
|
|||||||
func parseMsg(msgs []syscall.SocketControlMessage) (*Msg, error) {
|
func parseMsg(msgs []syscall.SocketControlMessage) (*Msg, error) {
|
||||||
var msg Msg
|
var msg Msg
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
if m.Header.Level == syscall.SOL_SOCKET {
|
if m.Header.Level != syscall.SOL_SOCKET {
|
||||||
switch m.Header.Type {
|
continue
|
||||||
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
|
|
||||||
|
|
||||||
|
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
|
return &msg, nil
|
||||||
|
|||||||
44
ptracer/context_other.go
Normal file
44
ptracer/context_other.go
Normal 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
3
ptracer/doc.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Package ptracer provides platfirm independent ptrace pooling loop
|
||||||
|
// interface to trace program syscalls on Linux.
|
||||||
|
package ptracer
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package unshare
|
package unshare
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package unshare
|
package unshare
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user