1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// +build !appengine
package osutil
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"sync"
"syscall"
"time"
"unsafe"
)
// UmountAll recurusively unmounts all mounts in dir.
func UmountAll(dir string) {
files, _ := ioutil.ReadDir(dir)
for _, f := range files {
name := filepath.Join(dir, f.Name())
if f.IsDir() {
UmountAll(name)
}
fn := []byte(name + "\x00")
syscall.Syscall(syscall.SYS_UMOUNT2, uintptr(unsafe.Pointer(&fn[0])), syscall.MNT_FORCE, 0)
}
}
func Sandbox(cmd *exec.Cmd, user, net bool) error {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = new(syscall.SysProcAttr)
}
if user {
uid, gid, err := initSandbox()
if err != nil {
return err
}
cmd.SysProcAttr.Credential = &syscall.Credential{
Uid: uid,
Gid: gid,
}
}
if net {
cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWNET | syscall.CLONE_NEWIPC |
syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID
}
return nil
}
func SandboxChown(file string) error {
uid, _, err := initSandbox()
if err != nil {
return err
}
return os.Chown(file, int(uid), int(uid))
}
var (
sandboxOnce sync.Once
sandboxUsername = "syzkaller"
sandboxUID = ^uint32(0)
sandboxGID = ^uint32(0)
)
func initSandbox() (uint32, uint32, error) {
sandboxOnce.Do(func() {
uid, err := usernameToID("-u")
if err != nil {
return
}
gid, err := usernameToID("-g")
if err != nil {
return
}
sandboxUID = uid
sandboxGID = gid
})
if sandboxUID == ^uint32(0) {
return 0, 0, fmt.Errorf("user %q is not found, can't sandbox command", sandboxUsername)
}
return sandboxUID, sandboxGID, nil
}
func usernameToID(what string) (uint32, error) {
out, err := RunCmd(time.Minute, "", "id", what, sandboxUsername)
if err != nil {
return 0, err
}
str := strings.Trim(string(out), " \t\n")
id, err := strconv.ParseUint(str, 10, 32)
if err != nil {
return 0, err
}
return uint32(id), nil
}
func setPdeathsig(cmd *exec.Cmd) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = new(syscall.SysProcAttr)
}
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
}
func prolongPipe(r, w *os.File) {
for sz := 128 << 10; sz <= 2<<20; sz *= 2 {
syscall.Syscall(syscall.SYS_FCNTL, w.Fd(), syscall.F_SETPIPE_SZ, uintptr(sz))
}
}
|