|
| 1 | +//go:build linux |
| 2 | +// +build linux |
| 3 | + |
| 4 | +package os |
| 5 | + |
| 6 | +import ( |
| 7 | + "errors" |
| 8 | + "syscall" |
| 9 | + "unsafe" |
| 10 | +) |
| 11 | + |
| 12 | +func Fork() (pid int, err error) { |
| 13 | + // ret := libc_fork() |
| 14 | + // ret, _, _ := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0) |
| 15 | + ret, _, _ := syscall.Syscall(57, 0, 0, 0) |
| 16 | + if ret < 0 { |
| 17 | + // TODO: parse the syscall return codes |
| 18 | + return 0, errors.New("fork failed") |
| 19 | + } |
| 20 | + return int(ret), nil |
| 21 | +} |
| 22 | + |
| 23 | +// the golang standard library does not expose interfaces for execve and fork, so we define them here the same way via the libc wrapper |
| 24 | +func Execve(pathname string, argv []string, envv []string) (err error) { |
| 25 | + argv0 := cstring(pathname) |
| 26 | + |
| 27 | + // transform argv and envv into the format expected by execve |
| 28 | + argv1 := make([]*byte, len(argv)+1) |
| 29 | + for i, arg := range argv { |
| 30 | + argv1[i] = &cstring(arg)[0] |
| 31 | + } |
| 32 | + argv1[len(argv)] = nil |
| 33 | + |
| 34 | + env1 := make([]*byte, len(envv)+1) |
| 35 | + for i, env := range envv { |
| 36 | + env1[i] = &cstring(env)[0] |
| 37 | + } |
| 38 | + env1[len(envv)] = nil |
| 39 | + |
| 40 | + // fail := libc_execve(&argv0[0], &argv1[0], &env1[0]) |
| 41 | + // fail, _, _ := syscall.Syscall(syscall.SYS_EXECVE, uintptr(unsafe.Pointer(&argv0[0])), uintptr(unsafe.Pointer(&argv1[0])), uintptr(unsafe.Pointer(&env1[0]))) |
| 42 | + fail, _, _ := syscall.Syscall(59, uintptr(unsafe.Pointer(&argv0[0])), uintptr(unsafe.Pointer(&argv1[0])), uintptr(unsafe.Pointer(&env1[0]))) |
| 43 | + if fail < 0 { |
| 44 | + // TODO: parse the syscall return codes |
| 45 | + return errors.New("execve failed") |
| 46 | + } |
| 47 | + |
| 48 | + return nil |
| 49 | +} |
| 50 | + |
| 51 | +func cstring(s string) []byte { |
| 52 | + data := make([]byte, len(s)+1) |
| 53 | + copy(data, s) |
| 54 | + // final byte should be zero from the initial allocation |
| 55 | + return data |
| 56 | +} |
0 commit comments